diff options
author | npmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56> | 2008-06-05 20:56:04 +0000 |
---|---|---|
committer | npmccallum <npmccallum@c587cffe-e639-0410-9787-d7902ae8ed56> | 2008-06-05 20:56:04 +0000 |
commit | 9a401f3d7392134859a809905b11b7bcfaeea50b (patch) | |
tree | f34c169d4e4f43546bd4404af8c69be09e30ea55 | |
parent | 197ba7edc0ce6f6758b198821a9c6bf7c1fd1932 (diff) | |
download | libproxy-git-libproxy-0.2.3.tar.gz |
The real 0.2.3 releaselibproxy-0.2.3
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | Makefile.am | 5 | ||||
-rw-r--r-- | configure.ac | 41 | ||||
-rw-r--r-- | libproxy-1.0.pc.in | 10 | ||||
-rw-r--r-- | src/bin/proxy.c | 26 | ||||
-rw-r--r-- | src/lib/Makefile.am | 18 | ||||
-rw-r--r-- | src/lib/array.c | 138 | ||||
-rw-r--r-- | src/lib/array.h | 39 | ||||
-rw-r--r-- | src/lib/config_file.c | 158 | ||||
-rw-r--r-- | src/lib/config_file.h | 2 | ||||
-rw-r--r-- | src/lib/dhcp.c (renamed from src/lib/wpad_dhcp.c) | 2 | ||||
-rw-r--r-- | src/lib/dhcp.h (renamed from src/lib/wpad_dhcp.h) | 0 | ||||
-rw-r--r-- | src/lib/dns.c (renamed from src/lib/wpad_dns.c) | 42 | ||||
-rw-r--r-- | src/lib/dns.h (renamed from src/lib/wpad_dns.h) | 0 | ||||
-rw-r--r-- | src/lib/misc.c | 24 | ||||
-rw-r--r-- | src/lib/misc.h | 2 | ||||
-rw-r--r-- | src/lib/pac.c | 34 | ||||
-rw-r--r-- | src/lib/proxy.h | 2 | ||||
-rw-r--r-- | src/lib/proxy_factory.c | 402 | ||||
-rw-r--r-- | src/lib/proxy_factory.h | 20 | ||||
-rw-r--r-- | src/lib/slp.c (renamed from src/lib/wpad_slp.c) | 2 | ||||
-rw-r--r-- | src/lib/slp.h (renamed from src/lib/wpad_slp.h) | 0 | ||||
-rw-r--r-- | src/lib/strdict.c | 122 | ||||
-rw-r--r-- | src/lib/strdict.h | 35 | ||||
-rw-r--r-- | src/lib/url.c | 46 | ||||
-rw-r--r-- | src/lib/url.h | 2 | ||||
-rw-r--r-- | src/lib/wpad.c | 5 | ||||
-rw-r--r-- | src/lib/wpad.h | 6 | ||||
-rw-r--r-- | src/plugins/Makefile.am | 10 | ||||
-rw-r--r-- | src/plugins/mozjs.c | 189 | ||||
-rw-r--r-- | src/plugins/networkmanager.c | 4 | ||||
-rw-r--r-- | src/plugins/webkit.c | 209 |
32 files changed, 893 insertions, 709 deletions
@@ -1,3 +1,10 @@ +Thu Jun 05 17:05:12 2008 Nathaniel McCallum <nathaniel@natemccallum.com> + * === Released 0.2.3 === + * New plugin: webkit (JavaScript) + * Massive speed improvements in all javascript plugins + * Bug fixes + * Memory leak fixes + * pkgconfig support Wed Jan 09 04:18:45 2008 Jeff Schroeder <jeffschroeder@computer.org> * === Released 0.2.2 === * Python bindings fix diff --git a/Makefile.am b/Makefile.am index af437a6..42ca864 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1 +1,6 @@ SUBDIRS = src + +EXTRA_DIST = libproxy-1.0.pc.in + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = libproxy-1.0.pc diff --git a/configure.ac b/configure.ac index 36ad1e7..9b425b1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.61) -AC_INIT([libproxy],[0.2.2],[nathaniel@natemccallum.com]) +AC_INIT([libproxy],[0.2.3],[nathaniel@natemccallum.com]) AC_CONFIG_SRCDIR([src/lib/proxy_factory.c]) AM_INIT_AUTOMAKE @@ -11,16 +11,14 @@ AC_PROG_LIBTOOL AC_PROG_LN_S AC_PROG_MAKE_SET -### Check for pthread -AC_CHECK_HEADERS(pthread.h) -AC_CHECK_FUNCS(pthread_mutex_init) - ### Checks for libraries for plugins. PKG_CHECK_MODULES(x11, x11, have_x11=yes, have_x11=no) PKG_CHECK_MODULES(xmu, xmu, have_xmu=yes, have_xmu=no) PKG_CHECK_MODULES(gconf, gconf-2.0, have_gconf=yes, have_gconf=no) +PKG_CHECK_MODULES(webkit, webkit-1.0, have_webkit=yes, have_webkit=no) PKG_CHECK_MODULES(mozjs, xulrunner-js, have_mozjs=yes, - [PKG_CHECK_MODULES(mozjs, firefox-js, have_mozjs=yes, have_mozjs=no)]) + [PKG_CHECK_MODULES(mozjs, firefox-js, have_mozjs=yes, + [PKG_CHECK_MODULES(mozjs, mozilla-js, have_mozjs=yes, have_mozjs=no)])]) PKG_CHECK_MODULES(NetworkManager, NetworkManager, have_networkmanager=yes, have_networkmanager=no) @@ -88,6 +86,27 @@ else fi AM_CONDITIONAL([WITH_KDE], [test x$with_kde = xyes]) +# WebKit Javascript +AC_ARG_WITH([webkit], + [AS_HELP_STRING([--with-webkit], + [build WebKit JavaScriptCore PAC runner plugin @<:@automatic@:>@])], + [], + [test x$have_webkit == xyes && with_webkit=yes]) +if test x$with_webkit = xyes; then + if test x$have_webkit == xyes; then + WEBKIT_CFLAGS="$webkit_CFLAGS" + WEBKIT_LIBS="$webkit_LIBS" + AC_SUBST(WEBKIT_CFLAGS) + AC_SUBST(WEBKIT_LIBS) + else + echo "WebKit JavaScriptCore plugin requires: WebKit!" + exit 1 + fi +else + with_webkit=no +fi +AM_CONDITIONAL([WITH_WEBKIT], [test x$with_webkit = xyes]) + # Mozilla Javascript AC_ARG_WITH([mozjs], [AS_HELP_STRING([--with-mozjs], @@ -157,15 +176,16 @@ AC_C_CONST AC_TYPE_SIZE_T PLUGINDIR=$libdir/$PACKAGE_NAME/$PACKAGE_VERSION/plugins AC_SUBST(PLUGINDIR) -CFLAGS="-std=c99 $CFLAGS -DPLUGINDIR=\\\"$PLUGINDIR\\\" -DSYSCONFDIR=\\\"$sysconfdir\\\" -D_POSIX_C_SOURCE=1" +CFLAGS="-g -std=c99 $CFLAGS -DPLUGINDIR=\\\"$PLUGINDIR\\\" -DSYSCONFDIR=\\\"$sysconfdir\\\" -D_POSIX_C_SOURCE=1" ### Checks for library functions. AC_FUNC_MALLOC #AC_CHECK_FUNCS([gethostbyname gethostname memset socket strdup strstr]) -AC_CONFIG_FILES([Makefile src/Makefile src/lib/Makefile src/plugins/Makefile - src/bin/Makefile src/bindings/Makefile src/bindings/python/Makefile - src/bindings/java/Makefile src/bindings/dotnet/Makefile]) +AC_CONFIG_FILES([libproxy-1.0.pc Makefile src/Makefile src/lib/Makefile + src/plugins/Makefile src/bin/Makefile src/bindings/Makefile + src/bindings/python/Makefile src/bindings/java/Makefile + src/bindings/dotnet/Makefile]) AC_OUTPUT ### Print build summary @@ -176,6 +196,7 @@ echo -e "\t\tenvvar : $with_envvar" echo -e "\t\tfile : $with_file" echo -e "\t\tgnome : $with_gnome" echo -e "\t\tkde : $with_kde" +echo -e "\t\twebkit : $with_webkit" echo -e "\t\tmozjs : $with_mozjs" echo -e "\t\tnetworkmanager : $with_networkmanager" echo diff --git a/libproxy-1.0.pc.in b/libproxy-1.0.pc.in new file mode 100644 index 0000000..3ba0a67 --- /dev/null +++ b/libproxy-1.0.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libproxy +Description: Proxy Configuration Library +Version: @VERSION@ +Libs: -L${libdir} -lproxy +Cflags: -I${includedir} diff --git a/src/bin/proxy.c b/src/bin/proxy.c index 225948f..4fd6681 100644 --- a/src/bin/proxy.c +++ b/src/bin/proxy.c @@ -23,7 +23,7 @@ #include <unistd.h> #include <string.h> -/* Import libproxy API */ +// Import libproxy API #include <proxy.h> #define STDIN fileno(stdin) @@ -36,20 +36,20 @@ static char * readline(int fd) { - /* Verify we have an open socket */ + // Verify we have an open socket if (fd < 0) return NULL; - /* For each character received add it to the buffer unless it is a newline */ + // For each character received add it to the buffer unless it is a newline char *buffer = NULL; for (int i=1; i > 0 ; i++) { char c; - /* Receive a single character, check for newline or EOF */ + // Receive a single character, check for newline or EOF if (read(fd, &c, 1) != 1) return buffer; if (c == '\n') return buffer ? buffer : strdup(""); - /* Allocate new buffer if we need */ + // Allocate new buffer if we need if (i % 1024 == 1) { char *tmp = buffer; @@ -58,7 +58,7 @@ readline(int fd) if (tmp) { strcpy(buffer, tmp); free(tmp); } } - /* Add new character */ + // Add new character buffer[i-1] = c; } return buffer; @@ -67,7 +67,7 @@ readline(int fd) int main(int argc, char **argv) { - /* Create the proxy factory object */ + // Create the proxy factory object pxProxyFactory *pf = px_proxy_factory_new(); if (!pf) { @@ -75,14 +75,12 @@ main(int argc, char **argv) return 1; } - /* For each URL we read on STDIN, get the proxies to use */ + // For each URL we read on STDIN, get the proxies to use for (char *url = NULL ; url = readline(STDIN) ; free(url)) { - /* - * Get an array of proxies to use. These should be used - * in the order returned. Only move on to the next proxy - * if the first one fails (etc). - */ + // Get an array of proxies to use. These should be used + // in the order returned. Only move on to the next proxy + // if the first one fails (etc). char **proxies = px_proxy_factory_get_proxies(pf, url); for (int i = 0 ; proxies[i] ; i++) { @@ -96,7 +94,7 @@ main(int argc, char **argv) free(proxies); } - /* Destantiate the proxy factory object */ + // Destantiate the proxy factory object px_proxy_factory_free(pf); return 0; } diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am index 31a4297..f320af6 100644 --- a/src/lib/Makefile.am +++ b/src/lib/Makefile.am @@ -1,20 +1,8 @@ lib_LTLIBRARIES = libproxy.la -libproxy_la_SOURCES = \ - array.c array.h \ - config_file.c config_file.h \ - misc.c misc.h \ - pac.c pac.h \ - proxy_factory.c proxy_factory.h \ - strdict.c strdict.h \ - url.c url.h \ - wpad.c wpad.h \ - wpad_dhcp.c wpad_dhcp.h \ - wpad_dns.c wpad_dns.h \ - wpad_slp.c wpad_slp.h \ - proxy.h - +libproxy_la_SOURCES = misc.c url.c pac.c dhcp.c dns.c slp.c wpad.c proxy_factory.c config_file.c \ + misc.h url.h pac.h dhcp.h dns.h slp.h wpad.h proxy_factory.h proxy.h config_file.h libproxy_la_CFLAGS = -Wall -libproxy_la_LDFLAGS = -lpthread +libproxy_la_LDFLAGS = -lm include_HEADERS = proxy.h diff --git a/src/lib/array.c b/src/lib/array.c deleted file mode 100644 index 5441d9e..0000000 --- a/src/lib/array.c +++ /dev/null @@ -1,138 +0,0 @@ -/******************************************************************************* - * libproxy - A library for proxy configuration - * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - ******************************************************************************/ - -#include <stdint.h> -#include <string.h> - -#include "misc.h" -#include "array.h" - -struct _pxArray { - pxArrayItemsEqual equals; - pxArrayItemCallback free; - bool unique; - bool replace; - unsigned int length; - void **data; -}; - -static bool -identity(void *a, void *b) -{ - return (a == b); -} - -static void -nothing(void *a) -{ - return; -} - -pxArray * -px_array_new(pxArrayItemsEqual equals, pxArrayItemCallback free, bool unique, bool replace) -{ - pxArray *self = px_malloc0(sizeof(pxArray)); - self->equals = equals ? equals : &identity; - self->free = free ? free : ¬hing; - self->unique = unique; - self->replace = replace; - self->length = 0; - self->data = px_malloc0(sizeof(void *)); - return self; -} - -bool -px_array_add(pxArray *self, void *item) -{ - /* Verify some basic stuff */ - if (!self || !item) return false; - - /* If we are a unique array and a dup is found, either bail or replace the item */ - if (self->unique && px_array_find(self, item) >= 0) - { - if (!self->replace) - return false; - - self->free(self->data[px_array_find(self, item)]); - self->data[px_array_find(self, item)] = item; - return true; - } - - self->length++; - void **data = px_malloc0(sizeof(void *) * (self->length + 1)); - memcpy(data, self->data, sizeof(void *) * self->length); - data[self->length] = item; - px_free(self->data); - self->data = data; - return true; -} - -bool -px_array_del(pxArray *self, const void *item) -{ - unsigned int index = px_array_find(self, item); - if (index < 0) return false; - - /* Free the old one and shift elements down */ - self->free(self->data[index]); - memmove(self->data+index, - self->data+index+1, - sizeof(void *) * (self->length - index)); - - return true; -} - -void -px_array_foreach(pxArray *self, pxArrayItemCallbackWithArg cb, void *arg) -{ - for (int i=0 ; self->data[i] ; i++) - cb(self->data[i], arg); -} - -int -px_array_find(pxArray *self, const void *item) -{ - if (!self || !item) return -1; - - for (int i=0 ; self->data[i] ; i++) - if (self->equals(self->data[i], (void *) item)) - return i; - - return -1; -} - -const void * -px_array_get(pxArray *self, int index) -{ - if (!self) return NULL; - if (index < 0) index = self->length + index; - if (index < 0) return NULL; - - return self->data[index]; -} - -void -px_array_free(pxArray *self) -{ - if (!self) return; - - for (int i=0 ; self->data[i] ; i++) - self->free(self->data[i]); - px_free(self); -} diff --git a/src/lib/array.h b/src/lib/array.h deleted file mode 100644 index acd5b9e..0000000 --- a/src/lib/array.h +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * libproxy - A library for proxy configuration - * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - ******************************************************************************/ - -#include <stdbool.h> - -typedef bool (*pxArrayItemsEqual)(void *, void *); -typedef void (*pxArrayItemCallback)(void *); -typedef void (*pxArrayItemCallbackWithArg)(void *, void *); -typedef struct _pxArray pxArray; - -pxArray *px_array_new(pxArrayItemsEqual equals, pxArrayItemCallback free, bool unique, bool replace); - -bool px_array_add(pxArray *self, void *item); - -bool px_array_del(pxArray *self, const void *item); - -void px_array_foreach(pxArray *self, pxArrayItemCallbackWithArg cb, void *arg); - -int px_array_find(pxArray *self, const void *item); - -const void *px_array_get(pxArray *self, int index); - -void px_array_free(pxArray *self); diff --git a/src/lib/config_file.c b/src/lib/config_file.c index 8e32cab..69f5fec 100644 --- a/src/lib/config_file.c +++ b/src/lib/config_file.c @@ -24,64 +24,130 @@ #include <string.h> #include "misc.h" -#include "strdict.h" #include "config_file.h" +struct _pxConfigFileSection { + char *name; + char **keys; + char **vals; +}; +typedef struct _pxConfigFileSection pxConfigFileSection; + struct _pxConfigFile { - char *filename; - time_t mtime; - pxStrDict *sections; + char *filename; + time_t mtime; + pxConfigFileSection **sections; }; pxConfigFile * px_config_file_new(char *filename) { - /* Open the file and stat it */ + // Open the file and stat it struct stat st; int fd = open(filename, O_RDONLY); if (fd < 0) return NULL; fstat(fd, &st); - /* Allocate our structure; get mtime and filename */ + // Allocate our structure; get mtime and filename pxConfigFile *self = px_malloc0(sizeof(pxConfigFile)); - self->filename = px_strdup(filename); self->mtime = st.st_mtime; - self->sections = px_strdict_new((void *) px_strdict_free); + self->filename = px_strdup(filename); - /* Add one section (PX_CONFIG_FILE_DEFAULT_SECTION) */ - px_strdict_set(self->sections, PX_CONFIG_FILE_DEFAULT_SECTION, px_strdict_new(free)); - pxStrDict *current = (pxStrDict *) px_strdict_get(self->sections, PX_CONFIG_FILE_DEFAULT_SECTION); + // Add one section (PX_CONFIG_FILE_DEFAULT_SECTION) + self->sections = px_malloc0(sizeof(pxConfigFileSection *) * 2); + self->sections[0] = px_malloc0(sizeof(pxConfigFileSection)); + self->sections[0]->name = px_strdup(PX_CONFIG_FILE_DEFAULT_SECTION); + pxConfigFileSection *current = self->sections[0]; - /* Parse our file */ + // Parse our file for (char *line=NULL ; (line = px_readline(fd)) ; px_free(line)) { - /* Strip */ + // Strip char *tmp = px_strstrip(line); px_free(line); line = tmp; - /* Check for comment and/or empty line */ + // Check for comment and/or empty line if (*line == '#' || !strcmp(line, "")) continue; - /* If we have a new section */ + // If we have a new section if (*line == '[' || line[strlen(line)-1] == ']') { - /* Get just the section name */ + // Get just the section name memmove(line, line+1, strlen(line)-1); line[strlen(line)-2] = '\0'; - if (px_strdict_get(self->sections, line)) - current = (pxStrDict *) px_strdict_get(self->sections, line); - else - px_strdict_set(self->sections, line, px_strdict_new(free)); + // Check for each section... + for (int i=0 ; self->sections[i] ; i++) + { + // If we found the section already, set it as current and move on + if (!strcmp(self->sections[i]->name, line)) + { + current = self->sections[i]; + break; + } + + // If the section wasn't found, add a new section + if (!self->sections[i+1]) + { + // Create new section + current = px_malloc0(sizeof(pxConfigFileSection)); + current->name = px_strdup(line); + + // Add section to the end + pxConfigFileSection **sections = self->sections; + self->sections = px_malloc0(sizeof(pxConfigFileSection *) * (i+3)); + memcpy(self->sections, sections, sizeof(pxConfigFileSection) * (i+1)); + self->sections[i+1] = current; + px_free(sections); + + break; + } + } + continue; } - /* If this is a key/val line, get the key/val. */ - else if ((tmp = strchr(line, '=')) && tmp[1]) + // If this is a key/val line, get the key/val. + if ((tmp = strchr(line, '=')) && tmp[1]) { - *tmp = '\0'; - char *key = px_strstrip(line); - px_strdict_set(current, key, px_strstrip(tmp+1)); - px_free(key); + // If this is our first key/val, create a new array + if (!current->keys || !current->vals) + { + // Add key + current->keys = px_malloc0(sizeof(char *) * 2); + current->keys[0] = px_strndup(line, tmp - line); + current->keys[1] = NULL; + + // Add val + current->vals = px_malloc0(sizeof(char *) * 2); + current->vals[0] = px_strdup(tmp+1); + current->vals[1] = NULL; + } + + // If this is not our first key/val, tack it on the end + else + { + for (int i=0 ; current->keys[i] ; i++) + { + if (!current->keys[i+1]) + { + // Add val + char **vals = px_malloc0(sizeof(char *) * (i+3)); + memcpy(vals, current->vals, sizeof(char *) * (i+1)); + vals[i+1] = px_strstrip(tmp+1); + px_free(current->vals); current->vals = vals; + + // Add key + *tmp = '\0'; + char **keys = px_malloc0(sizeof(char *) * (i+3)); + memcpy(keys, current->keys, sizeof(char *) * (i+1)); + keys[i+1] = px_strstrip(line); + px_free(current->keys); current->keys = keys; + + break; + } + } + } + continue; } } @@ -96,10 +162,39 @@ px_config_file_is_stale(pxConfigFile *self) return (!stat(self->filename, &st) && st.st_mtime > self->mtime); } +char ** +px_config_file_get_sections(pxConfigFile *self) +{ + int count; + for (count=0 ; self->sections[count] ; count++); + char **output = px_malloc0(sizeof(char *) * ++count); + for (count=0 ; self->sections[count] ; count++) + output[count] = px_strdup(self->sections[count]->name); + return output; +} + +char ** +px_config_file_get_keys(pxConfigFile *self, char *section) +{ + for (int i=0 ; self->sections[i] ; i++) + { + if (!strcmp(self->sections[i]->name, section)) + return px_strdupv((const char **) self->sections[i]->keys); + } + + return NULL; +} + char * px_config_file_get_value(pxConfigFile *self, char *section, char *key) { - return px_strdup(px_strdict_get((pxStrDict *) px_strdict_get(self->sections, section), key)); + for (int i=0 ; self->sections[i] ; i++) + if (!strcmp(self->sections[i]->name, section)) + for (int j=0 ; self->sections[i]->keys && self->sections[i]->keys[j] ; j++) + if (!strcmp(self->sections[i]->keys[j], key)) + return px_strdup(self->sections[i]->vals[j]); + + return NULL; } void @@ -107,7 +202,14 @@ px_config_file_free(pxConfigFile *self) { if (!self) return; - px_strdict_free(self->sections); + for (int i=0 ; self->sections && self->sections[i] ; i++) + { + px_free(self->sections[i]->name); + px_strfreev(self->sections[i]->keys); + px_strfreev(self->sections[i]->vals); + px_free(self->sections[i]); + } + px_free(self->sections); px_free(self->filename); px_free(self); } diff --git a/src/lib/config_file.h b/src/lib/config_file.h index 5aa9826..938d203 100644 --- a/src/lib/config_file.h +++ b/src/lib/config_file.h @@ -28,6 +28,8 @@ typedef struct _pxConfigFile pxConfigFile; pxConfigFile *px_config_file_new (char *filename); bool px_config_file_is_stale (pxConfigFile *self); +char **px_config_file_get_sections(pxConfigFile *self); +char **px_config_file_get_keys (pxConfigFile *self, char *section); char *px_config_file_get_value (pxConfigFile *self, char *section, char *key); void px_config_file_free (pxConfigFile *self); diff --git a/src/lib/wpad_dhcp.c b/src/lib/dhcp.c index 9d613f8..1afe13d 100644 --- a/src/lib/wpad_dhcp.c +++ b/src/lib/dhcp.c @@ -20,7 +20,7 @@ #include <stdlib.h> #include "pac.h" -#include "wpad_dhcp.h" +#include "dhcp.h" struct _pxDHCP { }; diff --git a/src/lib/wpad_dhcp.h b/src/lib/dhcp.h index 2e83e67..2e83e67 100644 --- a/src/lib/wpad_dhcp.h +++ b/src/lib/dhcp.h diff --git a/src/lib/wpad_dns.c b/src/lib/dns.c index 8bf4576..6861fdc 100644 --- a/src/lib/wpad_dns.c +++ b/src/lib/dns.c @@ -26,7 +26,7 @@ #include "misc.h" #include "pac.h" -#include "wpad_dns.h" +#include "dns.h" struct _pxDNS { pxURL **urls; @@ -34,13 +34,13 @@ struct _pxDNS { char *domain; }; -/* The top-level domain blacklist */ +// The top-level domain blacklist static char *tld[] = { - /* General top-level domains */ + // General top-level domains "arpa", "root", "aero", "biz", "cat", "com", "coop", "edu", "gov", "info", "int", "jobs", "mil", "mobi", "museum", "name", "net", "org", "pro", "travel", - /* Country codes */ + // Country codes "ac", "ad", "ae", "af", "ag", "ai", "al", "am", "an", "ao", "aq", "ar", "as", "at", "au", "aw", "ax", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", "bj", "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw", "by", @@ -63,23 +63,23 @@ static char *tld[] = { "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws", "ye", "yt", "yu", "za", "zm", "zw", - /* Other domains to blacklist */ + // Other domains to blacklist "co.uk", "com.au", - /* Terminator */ + // Terminator NULL }; static char * get_domain_name() { - /* Get the hostname */ + // Get the hostname char *hostname = px_malloc0(128); for (int i = 0 ; gethostname(hostname, (i + 1) * 128) && errno == ENAMETOOLONG ; ) hostname = px_malloc0((++i + 1) * 128); - /* Lookup the hostname */ - /* TODO: Make this whole process not suck */ + // Lookup the hostname + // TODO: Make this whole process not suck struct hostent *host_info = gethostbyname(hostname); if (host_info) { @@ -87,7 +87,7 @@ get_domain_name() hostname = px_strdup(host_info->h_name); } - /* Get domain portion */ + // Get domain portion if (!strchr(hostname, '.')) return NULL; if (!strcmp(".", strchr(hostname, '.'))) return NULL; char *tmp = px_strdup(strchr(hostname, '.') + 1); @@ -107,29 +107,29 @@ get_urls(const char *domain) return urls; } - /* Split up the domain */ + // Split up the domain char **domainv = px_strsplit(domain, "."); if (!domainv) return NULL; - /* Count the number of domain blocks */ + // Count the number of domain blocks int count = 0; for (int i=0 ; *(domainv + i) ; i++) count++; - /* Allocate our URL array */ + // Allocate our URL array urls = px_malloc0(sizeof(pxURL *) * (count + 2)); - /* Create the URLs */ + // Create the URLs urls[0] = px_url_new("http://wpad/wpad.dat"); char *url = px_malloc0(strlen("http://wpad./wpad.dat") + strlen(domain) + 1); for (int i=0, j=1 ; domainv[i] ; i++) { - /* Check the domain against the blacklist */ + // Check the domain against the blacklist char *tmp = px_strjoin((const char **) (domainv + i), "."); for (int k=0; tld[k] ; k++) if (!strcmp(tmp, tld[k])) { px_free(tmp); tmp = NULL; break; } if (!tmp) continue; - /* Create the URL */ + // Create the URL sprintf(url, "http://wpad.%s/wpad.dat", tmp); px_free(tmp); tmp = NULL; urls[j] = px_url_new(url); @@ -176,25 +176,25 @@ px_dns_next(pxDNS *self) if (!self->urls) { char *domain; - /* Reset the counter */ + // Reset the counter self->next = 0; - /* Get the domain name */ + // Get the domain name if (self->domain) domain = px_strdup(self->domain); else domain = get_domain_name(); - /* Get the URLs */ + // Get the URLs self->urls = get_urls(domain); px_free(domain); - /* Make sure we have more than one URL */ + // Make sure we have more than one URL if (!self->urls || !self->urls[0]) return NULL; } - /* Try to find a PAC at each URL */ + // Try to find a PAC at each URL for (pxPAC *pac = NULL ; self->urls[self->next] ; ) if ((pac = px_pac_new(self->urls[self->next++]))) return pac; diff --git a/src/lib/wpad_dns.h b/src/lib/dns.h index f3deac7..f3deac7 100644 --- a/src/lib/wpad_dns.h +++ b/src/lib/dns.h diff --git a/src/lib/misc.c b/src/lib/misc.c index 358d1c0..40f7886 100644 --- a/src/lib/misc.c +++ b/src/lib/misc.c @@ -110,13 +110,13 @@ px_strcat(const char *s, ...) { va_list args; - /* Count the number of characters to concatentate */ + // Count the number of characters to concatentate va_start(args, s); int count = strlen(s); for (char *tmp = NULL ; (tmp = va_arg(args, char *)) ; count += strlen(tmp)); va_end(args); - /* Build our output string */ + // Build our output string char *output = px_malloc0(count + 1); strcat(output, s); va_start(args, s); @@ -139,13 +139,13 @@ px_strjoin(const char **strv, const char *delimiter) if (!strv) return NULL; if (!delimiter) return NULL; - /* Count up the length we need */ + // Count up the length we need size_t length = 0; for (int i=0 ; strv[i]; i++) length += strlen(strv[i]) + strlen(delimiter); if (!length) return NULL; - /* Do the join */ + // Do the join char *str = px_malloc0(length); for (int i=0 ; strv[i]; i++) { @@ -164,15 +164,15 @@ px_strjoin(const char **strv, const char *delimiter) char ** px_strsplit(const char *string, const char *delimiter) { - /* Count how many times the delimiter appears */ + // Count how many times the delimiter appears int count = 1; for (const char *tmp = string ; (tmp = strstr(tmp, delimiter)) ; tmp += strlen(delimiter)) count++; - /* Allocate the vector */ + // Allocate the vector char **strv = px_malloc0(sizeof(char *) * (count + 1)); - /* Fill the vector */ + // Fill the vector const char *last = string; for (int i=0 ; i < count ; i++) { @@ -210,20 +210,20 @@ px_strfreev(char **strv) char * px_readline(int fd) { - /* Verify we have an open socket */ + // Verify we have an open socket if (fd < 0) return NULL; - /* For each character received add it to the buffer unless it is a newline */ + // For each character received add it to the buffer unless it is a newline char *buffer = NULL; for (int i=1; i > 0 ; i++) { char c; - /* Receive a single character, check for newline or EOF */ + // Receive a single character, check for newline or EOF if (read(fd, &c, 1) != 1) return buffer; if (c == '\n') return buffer ? buffer : px_strdup(""); - /* Allocate new buffer if we need */ + // Allocate new buffer if we need if (i % 1024 == 1) { char *tmp = buffer; @@ -231,7 +231,7 @@ px_readline(int fd) if (tmp) { strcpy(buffer, tmp); px_free(tmp); } } - /* Add new character */ + // Add new character buffer[i-1] = c; } return buffer; diff --git a/src/lib/misc.h b/src/lib/misc.h index b1e45e6..bee77ac 100644 --- a/src/lib/misc.h +++ b/src/lib/misc.h @@ -20,7 +20,7 @@ #ifndef MISC_H_ #define MISC_H_ -#include <stdlib.h> /* For type size_t */ +#include <stdlib.h> // For type size_t /** * Allocates memory and always returns valid memory. diff --git a/src/lib/pac.c b/src/lib/pac.c index ca32ede..9403d39 100644 --- a/src/lib/pac.c +++ b/src/lib/pac.c @@ -70,13 +70,13 @@ px_pac_new(pxURL *url) { if (!url) return NULL; - /* Allocate the object */ + // Allocate the object pxPAC *self = px_malloc0(sizeof(pxPAC)); - /* Copy the given URL */ - self->url = px_url_new(px_url_to_string(url)); /* Always returns valid value */ + // Copy the given URL + self->url = px_url_new(px_url_to_string(url)); // Always returns valid value - /* Make sure we have a real pxPAC */ + // Make sure we have a real pxPAC if (!px_pac_reload(self)) { px_pac_free(self); return NULL; } return self; @@ -90,13 +90,13 @@ px_pac_new(pxURL *url) pxPAC * px_pac_new_from_string(char *url) { - /* Create temporary URL */ + // Create temporary URL pxURL *tmpurl = px_url_new(url); if (!tmpurl) return NULL; - /* Create pac */ + // Create pac pxPAC *self = px_pac_new(tmpurl); - px_url_free(tmpurl); /* Free no longer used URL */ + px_url_free(tmpurl); // Free no longer used URL if (!self) return NULL; return self; } @@ -124,33 +124,33 @@ px_pac_reload(pxPAC *self) bool correct_mime_type; unsigned long int content_length = 0; - /* Get the pxPAC */ + // Get the pxPAC sock = px_url_get(self->url, headers); if (sock < 0) return false; - /* Verify status line */ + // Verify status line line = px_readline(sock); if (!line) goto error; - if (strncmp(line, "HTTP", strlen("HTTP"))) goto error; /* Check valid HTTP response */ - if (!strchr(line, ' ') || atoi(strchr(line, ' ') + 1) != 200) goto error; /* Check status code */ + if (strncmp(line, "HTTP", strlen("HTTP"))) goto error; // Check valid HTTP response + if (!strchr(line, ' ') || atoi(strchr(line, ' ') + 1) != 200) goto error; // Check status code - /* Check for correct mime type and content length */ + // Check for correct mime type and content length while (strcmp(line, "\r")) { - /* Check for content type */ + // Check for content type if (strstr(line, "Content-Type: ") == line && strstr(line, PAC_MIME_TYPE)) correct_mime_type = true; - /* Check for content length */ + // Check for content length else if (strstr(line, "Content-Length: ") == line) content_length = atoi(line + strlen("Content-Length: ")); - /* Get new line */ + // Get new line px_free(line); line = px_readline(sock); if (!line) goto error; } - /* Get content */ + // Get content if (!content_length || !correct_mime_type) goto error; px_free(line); line = NULL; px_free(self->cache); @@ -158,7 +158,7 @@ px_pac_reload(pxPAC *self) for (int recvd=0 ; recvd != content_length ; ) recvd += recv(sock, self->cache + recvd, content_length - recvd, 0); - /* Clean up */ + // Clean up close(sock); return true; diff --git a/src/lib/proxy.h b/src/lib/proxy.h index 3257e8a..9dc9f66 100644 --- a/src/lib/proxy.h +++ b/src/lib/proxy.h @@ -35,8 +35,6 @@ pxProxyFactory *px_proxy_factory_new(); * A NULL-terminated array of proxy strings is returned. * If the first proxy fails, the second should be tried, etc... * Don't forget to free the strings/array when you are done. - * In all cases, at least one entry in the array will be returned. - * There are no error conditions. * * The format of the returned proxy strings are as follows: * - http://proxy:port diff --git a/src/lib/proxy_factory.c b/src/lib/proxy_factory.c index 1376563..5591c9c 100644 --- a/src/lib/proxy_factory.c +++ b/src/lib/proxy_factory.c @@ -34,8 +34,6 @@ #include "proxy_factory.h" #include "wpad.h" #include "config_file.h" -#include "array.h" -#include "strdict.h" #define DEFAULT_CONFIG_ORDER "USER,SESSION,SYSTEM" @@ -46,19 +44,25 @@ struct _pxProxyFactoryConfig { }; typedef struct _pxProxyFactoryConfig pxProxyFactoryConfig; +struct _pxKeyVal { + char *key; + void *value; +}; +typedef struct _pxKeyVal pxKeyVal; + struct _pxProxyFactory { - pthread_mutex_t mutex; - pxArray *plugins; - pxProxyFactoryConfig **configs; - pxStrDict *misc; - pxArray *on_get_proxies; - pxPACRunnerCallback pac_runner; - pxPAC *pac; - pxWPAD *wpad; - pxConfigFile *cf; + pthread_mutex_t mutex; + void **plugins; + pxProxyFactoryConfig **configs; + pxKeyVal **misc; + pxProxyFactoryVoidCallback *on_get_proxy; + pxPACRunnerCallback pac_runner; + pxPAC *pac; + pxWPAD *wpad; + pxConfigFile *cf; }; -/* Convert the PAC formatted response into our proxy URL array response */ +// Convert the PAC formatted response into our proxy URL array response static char ** _format_pac_response(char *response) { @@ -107,7 +111,7 @@ _sockaddr_equals(const struct sockaddr *ip_a, const struct sockaddr *ip_b, const if (ip_a->sa_family != ip_b->sa_family) return false; if (nm && ip_a->sa_family != nm->sa_family) return false; - /* Setup the arrays */ + // Setup the arrays uint8_t bytes = 0, *a_data = NULL, *b_data = NULL, *nm_data = NULL; if (ip_a->sa_family == AF_INET) { @@ -142,26 +146,26 @@ _sockaddr_from_string(const char *ip, int len) if (!ip) return NULL; struct sockaddr *result = NULL; - /* Copy the string */ + // Copy the string if (len >= 0) ip = px_strndup(ip, len); else ip = px_strdup(ip); - /* Try to parse IPv4 */ + // Try to parse IPv4 result = px_malloc0(sizeof(struct sockaddr_in)); result->sa_family = AF_INET; if (inet_pton(AF_INET, ip, &((struct sockaddr_in *) result)->sin_addr) > 0) goto out; - /* Try to parse IPv6 */ + // Try to parse IPv6 px_free(result); result = px_malloc0(sizeof(struct sockaddr_in6)); result->sa_family = AF_INET6; if (inet_pton(AF_INET6, ip, &((struct sockaddr_in6 *) result)->sin6_addr) > 0) goto out; - /* No address found */ + // No address found px_free(result); result = NULL; out: @@ -172,7 +176,7 @@ _sockaddr_from_string(const char *ip, int len) static struct sockaddr * _sockaddr_from_cidr(int af, int cidr) { - /* TODO: Support CIDR notation */ + // TODO: Support CIDR notation return NULL; } @@ -186,25 +190,21 @@ _ip_ignore(pxURL *url, char *ignore) const struct sockaddr *dst_ip = px_url_get_ip_no_dns(url); struct sockaddr *ign_ip = NULL, *net_ip = NULL; - /* - * IPv4 - * IPv6 - */ + // IPv4 + // IPv6 if ((ign_ip = _sockaddr_from_string(ignore, -1))) goto out; - /* - * IPv4/CIDR - * IPv4/IPv4 - * IPv6/CIDR - * IPv6/IPv6 - */ + // IPv4/CIDR + // IPv4/IPv4 + // IPv6/CIDR + // IPv6/IPv6 if (strchr(ignore, '/')) { ign_ip = _sockaddr_from_string(ignore, strchr(ignore, '/') - ignore); net_ip = _sockaddr_from_string(strchr(ignore, '/') + 1, -1); - /* If CIDR notation was used, get the netmask */ + // If CIDR notation was used, get the netmask if (ign_ip && !net_ip) { uint32_t cidr = 0; @@ -221,15 +221,13 @@ _ip_ignore(pxURL *url, char *ignore) net_ip = NULL; } - /* - * IPv4:port - * [IPv6]:port - */ + // IPv4:port + // [IPv6]:port if (strrchr(ignore, ':') && sscanf(strrchr(ignore, ':'), ":%u", &port) == 1 && port > 0) { ign_ip = _sockaddr_from_string(ignore, strrchr(ignore, ':') - ignore); - /* Make sure this really is just a port and not just an IPv6 address */ + // Make sure this really is just a port and not just an IPv6 address if (ign_ip && (ign_ip->sa_family != AF_INET6 || ignore[0] == '[')) goto out; @@ -251,11 +249,11 @@ _domain_ignore(pxURL *url, char *ignore) if (!url || !ignore) return false; - /* Get our URL's hostname and port */ + // Get our URL's hostname and port char *host = px_strdup(px_url_get_host(url)); int port = px_url_get_port(url); - /* Get our ignore pattern's hostname and port */ + // Get our ignore pattern's hostname and port char *ihost = px_strdup(ignore); int iport = 0; if (strchr(ihost, ':')) @@ -267,49 +265,33 @@ _domain_ignore(pxURL *url, char *ignore) iport = 0; } - /* Hostname match (domain.com or domain.com:80) */ + // Hostname match (domain.com or domain.com:80) if (!strcmp(host, ihost)) if (!iport || port == iport) goto match; - /* Endswith (.domain.com or .domain.com:80) */ + // Endswith (.domain.com or .domain.com:80) if (ihost[0] == '.' && _endswith(host, ihost)) if (!iport || port == iport) goto match; - /* Glob (*.domain.com or *.domain.com:80) */ + // Glob (*.domain.com or *.domain.com:80) if (ihost[0] == '*' && _endswith(host, ihost+1)) if (!iport || port == iport) goto match; - /* No match was found */ + // No match was found px_free(host); px_free(ihost); return false; - /* A match was found */ + // A match was found match: px_free(host); px_free(ihost); return true; } -static void -destantiate_plugins(void *item, void *self) -{ - /* Call the destantiation hook */ - pxProxyFactoryVoidCallback destantiate; - destantiate = dlsym(item, "on_proxy_factory_destantiate"); - if (destantiate) - destantiate(self); -} - -static void -call_on_proxy_factory_get_proxies(void *item, void *self) -{ - ((pxProxyFactoryVoidCallback) item)(self); -} - /** * Creates a new pxProxyFactory instance. * @@ -319,33 +301,44 @@ pxProxyFactory * px_proxy_factory_new () { pxProxyFactory *self = px_malloc0(sizeof(pxProxyFactory)); + unsigned int i; + + // Create the mutex pthread_mutex_init(&self->mutex, NULL); - self->plugins = px_array_new(NULL, (void *) dlclose, true, false); - self->misc = px_strdict_new(NULL); - self->on_get_proxies = px_array_new(NULL, NULL, true, false); - /* Open the plugin dir */ + // Open the plugin dir DIR *plugindir = opendir(PLUGINDIR); if (!plugindir) return self; - /* For each plugin... */ + // Count the number of plugins + for (i=0 ; readdir(plugindir) ; i++); + self->plugins = (void **) px_malloc0(sizeof(void *) * (i + 1)); + rewinddir(plugindir); + + // For each plugin... struct dirent *ent; - for (int i=0 ; (ent = readdir(plugindir)) ; i++) + for (i=0 ; (ent = readdir(plugindir)) ; i++) { - /* Load the plugin */ + // Load the plugin char *tmp = px_strcat(PLUGINDIR, "/", ent->d_name, NULL); - void *plugin = dlopen(tmp, RTLD_NOW | RTLD_LOCAL); + self->plugins[i] = dlopen(tmp, RTLD_NOW | RTLD_LOCAL); px_free(tmp); - if (!plugin) + if (!(self->plugins[i])) + { + dlerror(); + i--; continue; + } - /* Call the instantiation hook */ + // Call the instantiation hook pxProxyFactoryBoolCallback instantiate; - instantiate = dlsym(plugin, "on_proxy_factory_instantiate"); + instantiate = dlsym(self->plugins[i], "on_proxy_factory_instantiate"); if (instantiate && !instantiate(self)) - dlclose(plugin); - else if (instantiate) - px_array_add(self->plugins, plugin); + { + dlclose(self->plugins[i]); + self->plugins[i--] = NULL; + continue; + } } closedir(plugindir); @@ -358,29 +351,27 @@ px_proxy_factory_config_add(pxProxyFactory *self, const char *name, pxConfigCate int count; pxProxyFactoryConfig **tmp; - /* Verify some basic stuff */ + // Verify some basic stuff if (!self) return false; if (!callback) return false; if (!name || !strcmp(name, "")) return false; - /* Allocate an empty config array if there is none */ + // Allocate an empty config array if there is none if (!self->configs) self->configs = px_malloc0(sizeof(pxProxyFactoryConfig *)); - /* - * Make sure that 'name' is unique - * Also, get a count of how many configs we have - */ + // Make sure that 'name' is unique + // Also, get a count of how many configs we have for (count=0 ; self->configs[count] ; count++) if (!strcmp(self->configs[count]->name, name)) return false; - /* Allocate new array, copy old values into it and free old array */ + // Allocate new array, copy old values into it and free old array tmp = px_malloc0(sizeof(pxProxyFactoryConfig *) * (count + 2)); memcpy(tmp, self->configs, sizeof(pxProxyFactoryConfig *) * count); px_free(self->configs); self->configs = tmp; - /* Add the new callback to the end */ + // Add the new callback to the end self->configs[count] = px_malloc0(sizeof(pxProxyFactoryConfig)); self->configs[count]->category = category; self->configs[count]->name = px_strdup(name); @@ -394,12 +385,12 @@ px_proxy_factory_config_del(pxProxyFactory *self, const char *name) { int i,j; - /* Verify some basic stuff */ + // Verify some basic stuff if (!self) return false; if (!name || !strcmp(name, "")) return false; if (!self->configs) return false; - /* Remove and shift all configs down (if found) */ + // Remove and shift all configs down (if found) for (i=0,j=0 ; self->configs[j]; i++,j++) { if (i != j) @@ -411,7 +402,7 @@ px_proxy_factory_config_del(pxProxyFactory *self, const char *name) } } - /* If we have an empty array, free it */ + // If we have an empty array, free it if (!self->configs[0]) { px_free(self->configs); @@ -424,21 +415,83 @@ px_proxy_factory_config_del(pxProxyFactory *self, const char *name) bool px_proxy_factory_misc_set(pxProxyFactory *self, const char *key, const void *value) { - /* Verify some basic stuff */ - if (!self) return false; - if (!key || !strcmp(key, "")) return false; - - return px_strdict_set(self->misc, key, (void *) value); + int count; + pxKeyVal **tmp; + + // Verify some basic stuff + if (!self) return false; + if (!key || !strcmp(key, "")) return false; + + // Allocate an empty config array if there is none + if (!self->misc) self->misc = px_malloc0(sizeof(pxKeyVal *)); + + // Count the number of values + for (count=0 ; self->misc[count] ; count++); + + // Unset value + if (!value) + { + // Remove the keyval, shifting downward + for (int i=0,j=0 ; self->misc[i] ; i++, j++) + { + // If the key is found, remove it + if (!strcmp(key, self->misc[i]->key)) + { + px_free(self->misc[i]->key); + px_free(self->misc[i]); + self->misc[i] = NULL; + count--; + j--; + } + + // Shift down + if (i > 0 && j > 0) + self->misc[j] = self->misc[i]; + } + + // Resize array + tmp = px_malloc0(sizeof(pxKeyVal *) * (count + 1)); + memcpy(tmp, self->misc, sizeof(pxKeyVal *) * count); + px_free(self->misc); + self->misc = tmp; + return true; + } + + // Attempt to update the value within the array + for (int i=0 ; self->misc[i] ; i++) + { + if (!strcmp(key, self->misc[i]->key)) + { + self->misc[i]->value = (void *) value; + return true; + } + } + + // The key was not found in the array, so add it + tmp = px_malloc0(sizeof(pxKeyVal *) * (count + 2)); + memcpy(tmp, self->misc, sizeof(pxKeyVal *) * count); + tmp[count] = px_malloc0(sizeof(pxKeyVal)); + tmp[count]->key = px_strdup(key); + tmp[count]->value = (void *) value; + px_free(self->misc); + self->misc = tmp; + return true; } void * px_proxy_factory_misc_get(pxProxyFactory *self, const char *key) { - /* Verify some basic stuff */ + // Verify some basic stuff if (!self) return NULL; if (!key || !strcmp(key, "")) return NULL; + if (!self->misc) return NULL; + + // Find the value listed + for (int i=0 ; self->misc[i] ; i++) + if (!strcmp(key, self->misc[i]->key)) + return self->misc[i]->value; - return (void *) px_strdict_get(self->misc, key); + return NULL; } /** @@ -446,9 +499,6 @@ px_proxy_factory_misc_get(pxProxyFactory *self, const char *key) * * A NULL-terminated array of proxy strings is returned. * If the first proxy fails, the second should be tried, etc... - * Don't forget to free the strings/array when you are done. - * In all cases, at least one entry in the array will be returned. - * There are no error conditions. * * The format of the returned proxy strings are as follows: * - http://proxy:port @@ -465,47 +515,48 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) char **response = px_strsplit("direct://", ";"); char *tmp = NULL, *order = NULL, **orderv = NULL; - /* Verify some basic stuff */ + // Verify some basic stuff if (!self) goto do_return; if (!url || !strcmp(url, "")) goto do_return; if (!realurl) goto do_return; - /* Lock mutex */ + // Lock mutex pthread_mutex_lock(&self->mutex); - /* Call the events */ - px_array_foreach(self->on_get_proxies, call_on_proxy_factory_get_proxies, self); + // Call the events + for (int i=0 ; self->on_get_proxy && self->on_get_proxy[i] ; i++) + self->on_get_proxy[i](self); - /* If our config file is stale, close it */ + // If our config file is stale, close it if (self->cf && px_config_file_is_stale(self->cf)) { px_config_file_free(self->cf); self->cf = NULL; } - /* Try to open our config file if we don't have one */ + // Try to open our config file if we don't have one if (!self->cf) self->cf = px_config_file_new(SYSCONFDIR "/proxy.conf"); - /* If we have a config file, load the order from it */ + // If we have a config file, load the order from it if (self->cf) tmp = px_config_file_get_value(self->cf, PX_CONFIG_FILE_DEFAULT_SECTION, "config_order"); - /* Attempt to get info from the environment */ + // Attempt to get info from the environment order = getenv("PX_CONFIG_ORDER"); - /* Create the config order */ + // Create the config order order = px_strcat(tmp ? tmp : "", ",", order ? order : "", ",", DEFAULT_CONFIG_ORDER, NULL); px_free(tmp); tmp = NULL; - /* Create the config plugin order vector */ + // Create the config plugin order vector orderv = px_strsplit(order, ","); px_free(order); - /* Get the config by searching the config order */ + // Get the config by searching the config order for (int i=0 ; orderv[i] && !config ; i++) { - /* Get the category (if applicable) */ + // Get the category (if applicable) pxConfigCategory category; if (!strcmp(orderv[i], "USER")) category = PX_CONFIG_CATEGORY_USER; @@ -526,11 +577,11 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) } px_strfreev(orderv); - /* No config was found via search order, call all plugins */ + // No config was found via search order, call all plugins for (int i=0 ; self->configs && self->configs[i] && !config ; i++) config = self->configs[i]->callback(self); - /* No plugin returned a valid config, fall back to 'wpad://' */ + // No plugin returned a valid config, fall back to 'wpad://' if (!config) { fprintf(stderr, "*** Unable to locate valid config! Falling back to auto-detection...\n"); @@ -539,7 +590,7 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) config->ignore = px_strdup(""); } - /* If the config plugin returned an invalid config type or malformed URL, fall back to 'wpad://' */ + // If the config plugin returned an invalid config type or malformed URL, fall back to 'wpad://' if (!(!strncmp(config->url, "http://", 7) || !strncmp(config->url, "socks://", 8) || !strncmp(config->url, "pac+", 4) || @@ -564,7 +615,7 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) config->url = px_strdup("wpad://"); } - /* Check our ignore patterns */ + // Check our ignore patterns char **ignores = px_strsplit(config->ignore, ","); for (int i=0 ; ignores[i] ; i++) { @@ -576,10 +627,10 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) } px_strfreev(ignores); - /* If we have a wpad config */ + // If we have a wpad config if (!strcmp(config->url, "wpad://")) { - /* Get the WPAD object if needed */ + // Get the WPAD object if needed if (!self->wpad) { if (self->pac) px_pac_free(self->pac); @@ -592,46 +643,45 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) } } - /* - * If we have no PAC, get one - * If getting the PAC fails, but the WPAD cycle worked, restart the cycle - */ + // If we have no PAC, get one + // If getting the PAC fails, but the WPAD cycle worked, restart the cycle if (!self->pac && !(self->pac = px_wpad_next(self->wpad)) && px_wpad_pac_found(self->wpad)) { px_wpad_rewind(self->wpad); self->pac = px_wpad_next(self->wpad); } - /* If the WPAD cycle failed, fall back to direct */ + // If the WPAD cycle failed, fall back to direct if (!self->pac) { fprintf(stderr, "*** Unable to locate PAC! Falling back to direct...\n"); goto do_return; } - /* Run the PAC */ + // Run the PAC if (self->pac_runner) { px_strfreev(response); response = _format_pac_response(self->pac_runner(self, self->pac, realurl)); } - /* No PAC runner found, fall back to direct */ + // No PAC runner found, fall back to direct else fprintf(stderr, "*** PAC found, but no active PAC runner! Falling back to direct...\n"); } - /* If we have a PAC config */ + // If we have a PAC config else if (!strncmp(config->url, "pac+", 4)) { - /* Clear WPAD to indicate that this is a non-WPAD PAC */ + // Clear WPAD to indicate that this is a non-WPAD PAC if (self->wpad) { px_wpad_free(self->wpad); self->wpad = NULL; } - /* If a PAC already exists, but came from a different URL than the one specified, remove it */ + // If a PAC alread exists, but comes from a different URL than the one + // specified, remove it if (self->pac) { pxURL *urltmp = px_url_new(config->url + 4); @@ -648,14 +698,14 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) px_url_free(urltmp); } - /* Try to load the PAC if it is not already loaded */ + // Try to load the PAC if it is not already loaded if (!self->pac && !(self->pac = px_pac_new_from_string(config->url + 4))) { fprintf(stderr, "*** Invalid PAC URL! Falling back to direct...\n"); goto do_return; } - /* Run the PAC */ + // Run the PAC if (self->pac_runner) { px_strfreev(response); @@ -665,7 +715,7 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) fprintf(stderr, "*** PAC found, but no active PAC runner! Falling back to direct...\n"); } - /* If we have a manual config (http://..., socks://...) */ + // If we have a manual config (http://..., socks://...) else if (!strncmp(config->url, "http://", 7) || !strncmp(config->url, "socks://", 8)) { if (self->wpad) { px_wpad_free(self->wpad); self->wpad = NULL; } @@ -674,7 +724,7 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) response = px_strsplit(config->url, ";"); } - /* Actually return, freeing misc stuff */ + // Actually return, freeing misc stuff do_return: if (config) { px_free(config->url); px_free(config->ignore); px_free(config); } if (realurl) px_url_free(realurl); @@ -683,15 +733,60 @@ px_proxy_factory_get_proxies (pxProxyFactory *self, char *url) } bool -px_proxy_factory_on_get_proxies_add (pxProxyFactory *self, pxProxyFactoryVoidCallback callback) +px_proxy_factory_on_get_proxy_add (pxProxyFactory *self, pxProxyFactoryVoidCallback callback) { - return self ? px_array_add(self->on_get_proxies, callback) : false; + int count; + pxProxyFactoryVoidCallback *tmp; + + // Verify some basic stuff + if (!self) return false; + if (!callback) return false; + + // Allocate an empty config array if there is none + if (!self->on_get_proxy) self->on_get_proxy = px_malloc0(sizeof(pxProxyFactoryVoidCallback)); + + // Get a count of how many callbacks we have + for (count=0 ; self->on_get_proxy[count] ; count++); + + // Allocate new array, copy old values into it and free old array + tmp = px_malloc0(sizeof(pxProxyFactoryVoidCallback) * (count + 2)); + memcpy(tmp, self->on_get_proxy, sizeof(pxProxyFactoryVoidCallback) * count); + px_free(self->on_get_proxy); + self->on_get_proxy = tmp; + + // Add the new callback to the end + self->on_get_proxy[count] = callback; + + return true; } bool -px_proxy_factory_on_get_proxies_del (pxProxyFactory *self, pxProxyFactoryVoidCallback callback) +px_proxy_factory_on_get_proxy_del (pxProxyFactory *self, pxProxyFactoryVoidCallback callback) { - return self ? px_array_del(self->on_get_proxies, callback) : false; + int i,j; + + // Verify some basic stuff + if (!self) return false; + if (!callback) return false; + if (!self->on_get_proxy) return false; + + // Remove and shift all callbacks down (if found) + for (i=0,j=0 ; self->on_get_proxy[j]; i++,j++) + { + if (i != j) + self->on_get_proxy[j] = self->on_get_proxy[i]; + else if (self->on_get_proxy[i] == callback) + self->on_get_proxy[j--] = NULL; + } + + // If we have an empty array, free it + if (!self->on_get_proxy[0]) + { + px_free(self->on_get_proxy); + self->on_get_proxy = NULL; + } + + return i != j ? true : false; } bool @@ -706,10 +801,17 @@ px_proxy_factory_pac_runner_set (pxProxyFactory *self, pxPACRunnerCallback callb void px_proxy_factory_network_changed(pxProxyFactory *self) { - px_wpad_free(self->wpad); - px_pac_free(self->pac); - self->wpad = NULL; - self->pac = NULL; + if (self->wpad) + { + px_wpad_free(self->wpad); + self->wpad = NULL; + } + + if (self->pac) + { + px_pac_free(self->pac); + self->pac = NULL; + } } /** @@ -718,18 +820,42 @@ px_proxy_factory_network_changed(pxProxyFactory *self) void px_proxy_factory_free (pxProxyFactory *self) { + unsigned int i; + if (!self) return; pthread_mutex_lock(&self->mutex); - /* Free the plugins */ - px_array_foreach(self->plugins, destantiate_plugins, self); - px_array_free(self->plugins); + // Free the plugins + if (self->plugins) + { + for (i=0 ; self->plugins[i] ; i++) + { + // Call the destantiation hook + pxProxyFactoryVoidCallback destantiate; + destantiate = dlsym(self->plugins[i], "on_proxy_factory_destantiate"); + if (destantiate) + destantiate(self); + + // Unload the plugin + dlclose(self->plugins[i]); + self->plugins[i] = NULL; + } + px_free(self->plugins); + } - /* Free misc */ - px_strdict_free(self->misc); + // Free misc + if (self->misc) + { + for (i=0 ; self->misc[i] ; i++) + { + px_free(self->misc[i]->key); + px_free(self->misc[i]); + } + px_free(self->misc); + } - /* Free everything else */ + // Free everything else px_pac_free(self->pac); px_wpad_free(self->wpad); px_config_file_free(self->cf); diff --git a/src/lib/proxy_factory.h b/src/lib/proxy_factory.h index c73dad7..57ee186 100644 --- a/src/lib/proxy_factory.h +++ b/src/lib/proxy_factory.h @@ -35,15 +35,13 @@ enum _pxConfigCategory { }; typedef enum _pxConfigCategory pxConfigCategory; -/* - * URLs look like this: - * http://host:port - * socks://host:port - * pac+http://pac_host:port/path/to/pac - * wpad:// - * direct:// - */ - /* TODO: ignore syntax TBD */ +// URLs look like this: +// http://host:port +// socks://host:port +// pac+http://pac_host:port/path/to/pac +// wpad:// +// direct:// +// TODO: ignore syntax TBD struct _pxConfig { char *url; char *ignore; @@ -68,8 +66,8 @@ bool px_proxy_factory_config_del (pxProxyFactory *self, const c bool px_proxy_factory_misc_set (pxProxyFactory *self, const char *key, const void *value); void *px_proxy_factory_misc_get (pxProxyFactory *self, const char *key); void px_proxy_factory_network_changed (pxProxyFactory *self); -bool px_proxy_factory_on_get_proxies_add(pxProxyFactory *self, pxProxyFactoryVoidCallback callback); -bool px_proxy_factory_on_get_proxies_del(pxProxyFactory *self, pxProxyFactoryVoidCallback callback); +bool px_proxy_factory_on_get_proxy_add(pxProxyFactory *self, pxProxyFactoryVoidCallback callback); +bool px_proxy_factory_on_get_proxy_del(pxProxyFactory *self, pxProxyFactoryVoidCallback callback); bool px_proxy_factory_pac_runner_set (pxProxyFactory *self, pxPACRunnerCallback callback); #endif /*PROXY_FACTORY_H_*/ diff --git a/src/lib/wpad_slp.c b/src/lib/slp.c index 7251ce4..1e65013 100644 --- a/src/lib/wpad_slp.c +++ b/src/lib/slp.c @@ -20,7 +20,7 @@ #include <stdlib.h> #include "pac.h" -#include "wpad_slp.h" +#include "slp.h" struct _pxSLP { }; diff --git a/src/lib/wpad_slp.h b/src/lib/slp.h index 9f3b5bf..9f3b5bf 100644 --- a/src/lib/wpad_slp.h +++ b/src/lib/slp.h diff --git a/src/lib/strdict.c b/src/lib/strdict.c deleted file mode 100644 index 3157e65..0000000 --- a/src/lib/strdict.c +++ /dev/null @@ -1,122 +0,0 @@ -/******************************************************************************* - * libproxy - A library for proxy configuration - * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - ******************************************************************************/ - -#include <stdint.h> -#include <string.h> - -#include "misc.h" -#include "array.h" -#include "strdict.h" - -struct _pxStrDict { - pxStrDictItemCallback free; - pxArray *data; -}; - -static bool -dict_equals(void *a, void *b) -{ - if (!a || !b) return false; - void **aa = (void **) a; - void **bb = (void **) b; - return (!strcmp((char *) *aa, (char *) *bb)); -} - -static void -dict_free(void *item) -{ - char *key = (char *) ((void **) item)[0]; - void **realitem = ((void **) item)[1]; - pxStrDictItemCallback do_free = ((void **) item)[2]; - - do_free(realitem); - px_free(key); - px_free(item); -} - -static void -dict_foreach(void *item, void *misc) -{ - pxStrDictForeachCallback foreach = ((void **) misc)[0]; - char *key = ((void **) item)[0]; - void *val = ((void **) item)[1]; - void *arg = ((void **) misc)[1]; - foreach(key, val, arg); -} - -static void -do_nothing(void *item) -{ -} - -pxStrDict *px_strdict_new(pxStrDictItemCallback free) -{ - pxStrDict *self = px_malloc0(sizeof(pxStrDict)); - self->free = free ? free : do_nothing; - self->data = px_array_new(dict_equals, dict_free, true, false); - return self; -} - -bool -px_strdict_set(pxStrDict *self, const char *key, void *value) -{ - if (!self || !key) return false; - - /* We are unseting the value */ - if (!value) - { - void *item[3] = { (void *) key, value, self->free }; - return px_array_del(self->data, item); - } - - void **item = px_malloc0(sizeof(void *) * 3); - item[0] = px_strdup(key); - item[1] = value; - item[2] = self->free; - - if (px_array_add(self->data, item)) - return true; - - px_free(*item); - px_free(item); - return false; -} - -const void * -px_strdict_get(pxStrDict *self, const char *key) -{ - void *v[3] = { (void *) key, NULL, NULL }; - int i = px_array_find(self->data, v); - if (i < 0) return NULL; - return px_array_get(self->data, i); -} - -void -px_strdict_foreach(pxStrDict *self, pxStrDictForeachCallback *cb, void *arg) -{ - void *v[2] = { cb, arg }; - px_array_foreach(self->data, dict_foreach, v); -} - -void -px_strdict_free(pxStrDict *self) -{ - px_array_free(self->data); - px_free(self); -} diff --git a/src/lib/strdict.h b/src/lib/strdict.h deleted file mode 100644 index 9a7dc1a..0000000 --- a/src/lib/strdict.h +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * libproxy - A library for proxy configuration - * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - ******************************************************************************/ - -#include <stdbool.h> - -typedef void (*pxStrDictItemCallback)(void *); -typedef void (*pxStrDictForeachCallback)(const char *, void *, void *); - -typedef struct _pxStrDict pxStrDict; - -pxStrDict *px_strdict_new(pxStrDictItemCallback free); - -bool px_strdict_set(pxStrDict *self, const char *key, void *value); - -const void *px_strdict_get(pxStrDict *self, const char *key); - -void px_strdict_foreach(pxStrDict *self, pxStrDictForeachCallback *cb, void *arg); - -void px_strdict_free(pxStrDict *self); diff --git a/src/lib/url.c b/src/lib/url.c index ba156e4..3eb0e35 100644 --- a/src/lib/url.c +++ b/src/lib/url.c @@ -87,10 +87,10 @@ px_url_get(pxURL *self, const char **headers) char *joined_headers = NULL; int sock = -1; - /* DNS lookup of host */ + // DNS lookup of host if (!px_url_get_ips(self)) goto error; - /* Iterate through each pxIP trying to make a connection */ + // Iterate through each pxIP trying to make a connection for (int i = 0 ; self->ips && self->ips[i] && sock < 0 ; i++) { sock = socket(self->ips[i]->sa_family, SOCK_STREAM, 0); @@ -108,7 +108,7 @@ px_url_get(pxURL *self, const char **headers) } if (sock < 0) goto error; - /* Merge optional headers */ + // Merge optional headers if (headers) { joined_headers = px_strjoin(headers, "\r\n"); @@ -117,17 +117,17 @@ px_url_get(pxURL *self, const char **headers) else joined_headers = px_strdup(""); - /* Create request header */ + // Create request header request = px_strcat("GET ", px_url_get_path(self), " HTTP/1.1\r\nHost: ", px_url_get_host(self), "\r\n", joined_headers, "\r\n\r\n", NULL); px_free(joined_headers); - /* Send HTTP request */ + // Send HTTP request if (send(sock, request, strlen(request), 0) != strlen(request)) goto error; px_free(request); request = NULL; - /* Return the socket, which is ready for reading the response */ + // Return the socket, which is ready for reading the response return sock; error: @@ -166,12 +166,12 @@ px_url_get_ip_no_dns(pxURL *self) { if (!self) return NULL; - /* Check the cache */ + // Check the cache if (self->ips && self->ips[0]) return (const struct sockaddr *) self->ips[0]; px_free(self->ips); - /* Try for IPv4 first */ + // Try for IPv4 first struct sockaddr *ip = px_malloc0(sizeof(struct sockaddr_in)); if (inet_pton(AF_INET, px_url_get_host(self), &((struct sockaddr_in *) ip)->sin_addr) > 0) { @@ -182,7 +182,7 @@ px_url_get_ip_no_dns(pxURL *self) } px_free(ip); - /* Try for IPv6 next */ + // Try for IPv6 next ip = px_malloc0(sizeof(struct sockaddr_in6)); if (inet_pton(AF_INET6, px_url_get_host(self), &((struct sockaddr_in6 *) ip)->sin6_addr) > 0) { @@ -193,7 +193,7 @@ px_url_get_ip_no_dns(pxURL *self) } px_free(ip); - /* The hostname was not an IP address */ + // The hostname was not an IP address return NULL; } @@ -206,24 +206,24 @@ px_url_get_ips(pxURL *self) { if (!self) return NULL; - /* Check the cache */ + // Check the cache if (self->ips) return (const struct sockaddr **) self->ips; - /* Check without DNS first */ + // Check without DNS first if (px_url_get_ip_no_dns(self)) return (const struct sockaddr **) self->ips; - /* Check DNS for IPs */ + // Check DNS for IPs struct addrinfo *info; if (!getaddrinfo(px_url_get_host(self), NULL, NULL, &info)) { struct addrinfo *first = info; int count; - /* Count how many IPs we got back */ + // Count how many IPs we got back for (count=0 ; info ; info = info->ai_next) count++; - /* Copy the sockaddr's into self->ips */ + // Copy the sockaddr's into self->ips info = first; self->ips = px_malloc0(sizeof(struct sockaddr *) * ++count); for (int i=0 ; info ; info = info->ai_next) @@ -246,7 +246,7 @@ px_url_get_ips(pxURL *self) return (const struct sockaddr **) self->ips; } - /* No addresses found */ + // No addresses found return NULL; } @@ -287,24 +287,24 @@ px_url_get_scheme(pxURL *self) pxURL * px_url_new(const char *url) { - /* Allocate pxURL */ + // Allocate pxURL pxURL *self = px_malloc0(sizeof(pxURL)); - /* Get scheme */ + // Get scheme if (!strstr(url, "://")) goto error; self->scheme = px_strndup(url, strstr(url, "://") - url); - /* Get host */ + // Get host self->host = px_strdup(strstr(url, "://") + strlen("://")); - /* Get path */ + // Get path self->path = px_strdup(strchr(self->host, '/')); if (self->path) self->host[strlen(self->host) - strlen(self->path)] = 0; else self->path = px_strdup(""); - /* Get the port */ + // Get the port bool port_specified = false; if (strchr(self->host, ':')) { if (!atoi(strchr(self->host, ':')+1)) goto error; @@ -315,10 +315,10 @@ px_url_new(const char *url) else self->port = px_url_get_default_port(self); - /* Make sure we have a real host */ + // Make sure we have a real host if (!strcmp(self->host, "")) goto error; - /* Verify by re-assembly */ + // Verify by re-assembly self->url = px_malloc0(strlen(url) + 1); if (!port_specified) snprintf(self->url, strlen(url) + 1, "%s://%s%s", self->scheme, self->host, self->path); diff --git a/src/lib/url.h b/src/lib/url.h index bf2fd68..3e1b667 100644 --- a/src/lib/url.h +++ b/src/lib/url.h @@ -20,7 +20,7 @@ #ifndef URL_H_ #define URL_H_ -#include "stdbool.h" /* For type bool */ +#include "stdbool.h" // For type bool /** * WPAD object. All fields are private. diff --git a/src/lib/wpad.c b/src/lib/wpad.c index 7c18ef4..65fffad 100644 --- a/src/lib/wpad.c +++ b/src/lib/wpad.c @@ -18,6 +18,9 @@ ******************************************************************************/ #include "misc.h" +#include "dhcp.h" +#include "dns.h" +#include "slp.h" #include "wpad.h" struct _pxWPAD { @@ -71,7 +74,7 @@ px_wpad_next(pxWPAD *self) { if (!self) return NULL; - /* Check all the detectors for a PAC */ + // Check all the detectors for a PAC pxPAC *pac = NULL; if (!(pac = px_dhcp_next(self->dhcp))) if (!(pac = px_slp_next(self->slp))) diff --git a/src/lib/wpad.h b/src/lib/wpad.h index 3e6d8bb..411b0de 100644 --- a/src/lib/wpad.h +++ b/src/lib/wpad.h @@ -21,9 +21,9 @@ #define WPAD_H_ #include "pac.h" -#include "wpad_dhcp.h" -#include "wpad_dns.h" -#include "wpad_slp.h" +#include "dhcp.h" +#include "dns.h" +#include "slp.h" /** * WPAD object. All fields are private. diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am index 5e5d18c..9a561ea 100644 --- a/src/plugins/Makefile.am +++ b/src/plugins/Makefile.am @@ -14,6 +14,9 @@ endif if WITH_KDE plugin_LTLIBRARIES += kde.la endif +if WITH_WEBKIT +plugin_LTLIBRARIES += webkit.la +endif if WITH_MOZJS plugin_LTLIBRARIES += mozjs.la endif @@ -45,6 +48,13 @@ kde_la_CFLAGS = -I$(top_srcdir)/src/lib @KDE_CFLAGS@ kde_la_LIBADD = ../lib/libproxy.la kde_la_LDFLAGS = -module -avoid-version @KDE_LIBS@ +# WebKit (JavaScriptCore) based PAC runner +webkit_la_SOURCES = webkit.c +webkit_la_CFLAGS = -I$(top_srcdir)/src/lib @WEBKIT_CFLAGS@ +webkit_la_LIBADD = ../lib/libproxy.la +webkit_la_LDFLAGS = -module -avoid-version @WEBKIT_LIBS@ +nodist_webkit_la_SOURCES = pacutils.h + # Mozilla (Spidermonkey) based PAC runner mozjs_la_SOURCES = mozjs.c mozjs_la_CFLAGS = -I$(top_srcdir)/src/lib @MOZJS_CFLAGS@ diff --git a/src/plugins/mozjs.c b/src/plugins/mozjs.c index 5f89672..88c8180 100644 --- a/src/plugins/mozjs.c +++ b/src/plugins/mozjs.c @@ -36,38 +36,34 @@ static JSBool dnsResolve(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, // Get hostname argument char *tmp = px_strdup(JS_GetStringBytes(JS_ValueToString(cx, argv[0]))); + // Set the default return value + *rval = JSVAL_NULL; + // Look it up - struct addrinfo *info; + struct addrinfo *info = NULL; if (getaddrinfo(tmp, NULL, NULL, &info)) - goto error; + goto out; + + // Allocate the IP address px_free(tmp); + tmp = px_malloc0(INET6_ADDRSTRLEN+1); - // Try for IPv4 - tmp = px_malloc0(INET_ADDRSTRLEN+1); - if (inet_ntop(info->ai_family, + // Try for IPv4 and IPv6 + if (!inet_ntop(info->ai_family, &((struct sockaddr_in *) info->ai_addr)->sin_addr, tmp, INET_ADDRSTRLEN+1) > 0) - { - JSString *ip = JS_NewString(cx, tmp, strlen(tmp)); - *rval = STRING_TO_JSVAL(ip); - return true; - } - - // Try for IPv6 - px_free(tmp); - tmp = px_malloc0(INET6_ADDRSTRLEN+1); - if (inet_ntop(info->ai_family, - &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr, - tmp, INET6_ADDRSTRLEN+1) > 0) - { - JSString *ip = JS_NewString(cx, tmp, strlen(tmp)); - *rval = STRING_TO_JSVAL(ip); - return true; - } + if (!inet_ntop(info->ai_family, + &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr, + tmp, INET6_ADDRSTRLEN+1) > 0) + goto out; + + // We succeeded + *rval = STRING_TO_JSVAL(JS_NewString(cx, tmp, strlen(tmp))); + tmp = NULL; - error: + out: + if (info) freeaddrinfo(info); px_free(tmp); - *rval = JSVAL_NULL; return true; } @@ -83,72 +79,115 @@ static JSBool myIpAddress(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, return true; } +typedef struct { + JSRuntime *run; + JSContext *ctx; + JSClass *cls; + char *pac; +} ctxStore; + +static void ctxs_free(ctxStore *self) +{ + if (!self) return; + if (self->ctx) JS_DestroyContext(self->ctx); + if (self->run) JS_DestroyRuntime(self->run); + if (self->cls) px_free(self->cls); + px_free(self->pac); + px_free(self); +} + +static ctxStore *ctxs_new(pxPAC *pac) +{ + JSObject *global = NULL; + jsval rval; + + // Create the basic context + ctxStore *self = px_malloc0(sizeof(ctxStore)); + + // Setup Javascript global class + self->cls = px_malloc0(sizeof(JSClass)); + self->cls->name = "global"; + self->cls->flags = 0; + self->cls->addProperty = JS_PropertyStub; + self->cls->delProperty = JS_PropertyStub; + self->cls->getProperty = JS_PropertyStub; + self->cls->setProperty = JS_PropertyStub; + self->cls->enumerate = JS_EnumerateStub; + self->cls->resolve = JS_ResolveStub; + self->cls->convert = JS_ConvertStub; + self->cls->finalize = JS_FinalizeStub; + + // Initialize Javascript runtime environment + if (!(self->run = JS_NewRuntime(1024 * 1024))) goto error; + if (!(self->ctx = JS_NewContext(self->run, 1024 * 1024))) goto error; + if (!(global = JS_NewObject(self->ctx, self->cls, NULL, NULL))) goto error; + JS_InitStandardClasses(self->ctx, global); + + // Define Javascript functions + JS_DefineFunction(self->ctx, global, "dnsResolve", dnsResolve, 1, 0); + JS_DefineFunction(self->ctx, global, "myIpAddress", myIpAddress, 0, 0); + JS_EvaluateScript(self->ctx, global, JAVASCRIPT_ROUTINES, + strlen(JAVASCRIPT_ROUTINES), "pacutils.js", 0, &rval); + + // Add PAC to the environment + JS_EvaluateScript(self->ctx, global, px_pac_to_string(pac), + strlen(px_pac_to_string(pac)), + px_url_to_string((pxURL *) px_pac_get_url(pac)), + 0, &rval); + + // Save the pac + self->pac = px_strdup(px_pac_to_string(pac)); + return self; + +error: + ctxs_free(self); + return NULL; +} + char *mozjs_pacrunner(pxProxyFactory *self, pxPAC *pac, pxURL *url) { - JSRuntime *runtime = NULL; - JSContext *context = NULL; - JSObject *global = NULL; - jsval rval; - char *answer = NULL; - // Make sure we have the pac file and url if (!pac) return NULL; if (!url) return NULL; if (!px_pac_to_string(pac) && !px_pac_reload(pac)) return NULL; - - // Setup Javascript global class - JSClass *global_class = px_malloc0(sizeof(JSClass)); - global_class->name = "global"; - global_class->flags = 0; - global_class->addProperty = JS_PropertyStub; - global_class->delProperty = JS_PropertyStub; - global_class->getProperty = JS_PropertyStub; - global_class->setProperty = JS_PropertyStub; - global_class->enumerate = JS_EnumerateStub; - global_class->resolve = JS_ResolveStub; - global_class->convert = JS_ConvertStub; - global_class->finalize = JS_FinalizeStub; - - // Initialize Javascript runtime environment - if (!(runtime = JS_NewRuntime(1024 * 1024))) goto out; - if (!(context = JS_NewContext(runtime, 1024 * 1024))) goto out; - if (!(global = JS_NewObject(context, global_class, NULL, NULL))) goto out; - JS_InitStandardClasses(context, global); - - // Define Javascript functions - JS_DefineFunction(context, global, "dnsResolve", dnsResolve, 1, 0); - JS_DefineFunction(context, global, "myIpAddress", myIpAddress, 0, 0); - JS_EvaluateScript(context, global, JAVASCRIPT_ROUTINES, - strlen(JAVASCRIPT_ROUTINES), "pacutils.js", 0, &rval); - - // Add PAC to the environment - JS_EvaluateScript(context, JS_GetGlobalObject(context), - px_pac_to_string(pac), strlen(px_pac_to_string(pac)), - px_url_to_string((pxURL *) px_pac_get_url(pac)), 0, &rval); + + // Get the cached context + ctxStore *ctxs = px_proxy_factory_misc_get(self, "mozjs"); + + // If there is a cached context, make sure it is the same pac + if (ctxs && strcmp(ctxs->pac, px_pac_to_string(pac))) + { + ctxs_free(ctxs); + ctxs = NULL; + } + + // If no context exists (or if the pac was changed), create one + if (!ctxs) + { + if ((ctxs = ctxs_new(pac))) + px_proxy_factory_misc_set(self, "mozjs", ctxs); + else + return NULL; + } // Build arguments to the FindProxyForURL() function char *tmpurl = px_strdup(px_url_to_string(url)); char *tmphost = px_strdup(px_url_get_host(url)); - jsval val[2] = { - STRING_TO_JSVAL(JS_NewString(context, tmpurl, strlen(tmpurl))), - STRING_TO_JSVAL(JS_NewString(context, tmphost, strlen(tmphost))) + jsval args[2] = { + STRING_TO_JSVAL(JS_NewString(ctxs->ctx, tmpurl, strlen(tmpurl))), + STRING_TO_JSVAL(JS_NewString(ctxs->ctx, tmphost, strlen(tmphost))) }; // Find the proxy (call FindProxyForURL()) - JSBool result = JS_CallFunctionName(context, JS_GetGlobalObject(context), - "FindProxyForURL", 2, val, &rval); - if (!result) goto out; - answer = px_strdup(JS_GetStringBytes(JS_ValueToString(context, rval))); + jsval rval; + JSBool result = JS_CallFunctionName(ctxs->ctx, JS_GetGlobalObject(ctxs->ctx), "FindProxyForURL", 2, args, &rval); + if (!result) return NULL; + char *answer = px_strdup(JS_GetStringBytes(JS_ValueToString(ctxs->ctx, rval))); if (!answer || !strcmp(answer, "undefined")) { px_free(answer); - answer = NULL; + return NULL; } - - out: - if (context) JS_DestroyContext(context); - if (runtime) JS_DestroyRuntime(runtime); - px_free(global_class); - return answer; + return answer; } bool on_proxy_factory_instantiate(pxProxyFactory *self) @@ -159,4 +198,6 @@ bool on_proxy_factory_instantiate(pxProxyFactory *self) void on_proxy_factory_destantiate(pxProxyFactory *self) { px_proxy_factory_pac_runner_set(self, NULL); + ctxs_free(px_proxy_factory_misc_get(self, "mozjs")); + px_proxy_factory_misc_set(self, "mozjs", NULL); } diff --git a/src/plugins/networkmanager.c b/src/plugins/networkmanager.c index fca92d6..e7c8360 100644 --- a/src/plugins/networkmanager.c +++ b/src/plugins/networkmanager.c @@ -84,13 +84,13 @@ nm_on_get_proxy(pxProxyFactory *self) bool on_proxy_factory_instantiate(pxProxyFactory *self) { - px_proxy_factory_on_get_proxies_add(self, nm_on_get_proxy); + px_proxy_factory_on_get_proxy_add(self, nm_on_get_proxy); } void on_proxy_factory_destantiate(pxProxyFactory *self) { - px_proxy_factory_on_get_proxies_del(self, nm_on_get_proxy); + px_proxy_factory_on_get_proxy_del(self, nm_on_get_proxy); DBusConnection *conn = px_proxy_factory_misc_get(self, "networkmanager"); if (conn) { diff --git a/src/plugins/webkit.c b/src/plugins/webkit.c new file mode 100644 index 0000000..859c618 --- /dev/null +++ b/src/plugins/webkit.c @@ -0,0 +1,209 @@ +/******************************************************************************* + * libproxy - A library for proxy configuration + * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + ******************************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netdb.h> +#include <arpa/inet.h> +#define __USE_BSD +#include <unistd.h> + +#include <misc.h> +#include <proxy_factory.h> + +#include <JavaScriptCore/JavaScript.h> +#include "pacutils.h" + +static char *jstr2str(JSStringRef str, bool release) +{ + char *tmp = px_malloc0(JSStringGetMaximumUTF8CStringSize(str)+1); + JSStringGetUTF8CString(str, tmp, JSStringGetMaximumUTF8CStringSize(str)+1); + if (release) JSStringRelease(str); + return tmp; +} + +static JSValueRef dnsResolve(JSContextRef ctx, JSObjectRef func, JSObjectRef self, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + if (argc != 1) return NULL; + if (!JSValueIsString(ctx, argv[0])) return NULL; + + // Get hostname argument + char *tmp = jstr2str(JSValueToStringCopy(ctx, argv[0], NULL), true); + + // Look it up + struct addrinfo *info; + if (getaddrinfo(tmp, NULL, NULL, &info)) + return NULL; + px_free(tmp); + + // Try for IPv4 + tmp = px_malloc0(INET6_ADDRSTRLEN+1); + if (!inet_ntop(info->ai_family, + &((struct sockaddr_in *) info->ai_addr)->sin_addr, + tmp, INET_ADDRSTRLEN+1) > 0) + // Try for IPv6 + if (!inet_ntop(info->ai_family, + &((struct sockaddr_in6 *) info->ai_addr)->sin6_addr, + tmp, INET6_ADDRSTRLEN+1) > 0) + { + freeaddrinfo(info); + px_free(tmp); + return NULL; + } + freeaddrinfo(info); + + // Create the return value + JSStringRef str = JSStringCreateWithUTF8CString(tmp); + JSValueRef ret = JSValueMakeString(ctx, str); + JSStringRelease(str); + px_free(tmp); + + return ret; +} + +static JSValueRef myIpAddress(JSContextRef ctx, JSObjectRef func, JSObjectRef self, size_t argc, const JSValueRef argv[], JSValueRef* exception) +{ + char hostname[1024]; + if (!gethostname(hostname, 1023)) { + JSStringRef str = JSStringCreateWithUTF8CString(hostname); + JSValueRef val = JSValueMakeString(ctx, str); + JSStringRelease(str); + JSValueRef ip = dnsResolve(ctx, func, self, 1, &val, NULL); + return ip; + } + return NULL; +} + +typedef struct { + JSGlobalContextRef ctx; + char *pac; +} ctxStore; + +static void ctxs_free(ctxStore *self) +{ + if (!self) return; + JSGlobalContextRelease(self->ctx); + JSGarbageCollect(self->ctx); + px_free(self->pac); + px_free(self); +} + +static ctxStore *ctxs_new(pxPAC *pac) +{ + JSStringRef str = NULL; + JSObjectRef func = NULL; + + // Create the basic context + ctxStore *self = px_malloc0(sizeof(ctxStore)); + self->pac = px_strdup(px_pac_to_string(pac)); + if (!(self->ctx = JSGlobalContextCreate(NULL))) goto error; + + // Add dnsResolve into the context + str = JSStringCreateWithUTF8CString("dnsResolve"); + func = JSObjectMakeFunctionWithCallback(self->ctx, str, dnsResolve); + JSObjectSetProperty(self->ctx, JSContextGetGlobalObject(self->ctx), str, func, kJSPropertyAttributeNone, NULL); + JSStringRelease(str); + + // Add myIpAddress into the context + str = JSStringCreateWithUTF8CString("myIpAddress"); + func = JSObjectMakeFunctionWithCallback(self->ctx, str, myIpAddress); + JSObjectSetProperty(self->ctx, JSContextGetGlobalObject(self->ctx), str, func, kJSPropertyAttributeNone, NULL); + JSStringRelease(str); + + // Add all other routines into the context + str = JSStringCreateWithUTF8CString(JAVASCRIPT_ROUTINES); + if (!JSCheckScriptSyntax(self->ctx, str, NULL, 0, NULL)) goto error; + JSEvaluateScript(self->ctx, str, NULL, NULL, 1, NULL); + JSStringRelease(str); + + // Add the PAC into the context + str = JSStringCreateWithUTF8CString(self->pac); + if (!JSCheckScriptSyntax(self->ctx, str, NULL, 0, NULL)) goto error; + JSEvaluateScript(self->ctx, str, NULL, NULL, 1, NULL); + JSStringRelease(str); + + return self; + +error: + if (str) JSStringRelease(str); + ctxs_free(self); + return NULL; +} + +char *webkit_pacrunner(pxProxyFactory *self, pxPAC *pac, pxURL *url) +{ + JSStringRef str = NULL; + JSValueRef val = NULL; + char *tmp = NULL; + + // Make sure we have the pac file and url + if (!pac) return NULL; + if (!url) return NULL; + if (!px_pac_to_string(pac) && !px_pac_reload(pac)) return NULL; + + // Get the cached context + ctxStore *ctxs = px_proxy_factory_misc_get(self, "webkit"); + + // If there is a cached context, make sure it is the same pac + if (ctxs && strcmp(ctxs->pac, px_pac_to_string(pac))) + { + ctxs_free(ctxs); + ctxs = NULL; + } + + // If no context exists (or if the pac was changed), create one + if (!ctxs) + { + if ((ctxs = ctxs_new(pac))) + px_proxy_factory_misc_set(self, "webkit", ctxs); + else + return NULL; + } + + // Run the PAC + tmp = px_strcat("FindProxyForURL(\"", px_url_to_string(url), "\", \"", px_url_get_host(url), "\");", NULL); + str = JSStringCreateWithUTF8CString(tmp); + px_free(tmp); tmp = NULL; + if (!JSCheckScriptSyntax(ctxs->ctx, str, NULL, 0, NULL)) goto error; + if (!(val = JSEvaluateScript(ctxs->ctx, str, NULL, NULL, 1, NULL))) goto error; + if (!JSValueIsString(ctxs->ctx, val)) goto error; + JSStringRelease(str); + + // Convert the return value to a string + return jstr2str(JSValueToStringCopy(ctxs->ctx, val, NULL), true); + +error: + if (str) JSStringRelease(str); + ctxs_free(ctxs); + return tmp; +} + +bool on_proxy_factory_instantiate(pxProxyFactory *self) +{ + return px_proxy_factory_pac_runner_set(self, webkit_pacrunner); +} + +void on_proxy_factory_destantiate(pxProxyFactory *self) +{ + px_proxy_factory_pac_runner_set(self, NULL); + ctxs_free(px_proxy_factory_misc_get(self, "webkit")); + px_proxy_factory_misc_set(self, "webkit", NULL); +} |