summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libproxy/CMakeLists.txt32
-rw-r--r--libproxy/array.cpp157
-rw-r--r--libproxy/array.hpp51
-rw-r--r--libproxy/config_file.cpp149
-rw-r--r--libproxy/config_file.hpp49
-rw-r--r--libproxy/dl_module.cpp82
-rw-r--r--libproxy/dl_module.hpp (renamed from libproxy/strdict.hpp)63
-rw-r--r--libproxy/misc.cpp295
-rw-r--r--libproxy/module_manager.cpp296
-rw-r--r--libproxy/module_manager.hpp140
-rw-r--r--libproxy/module_types.cpp123
-rw-r--r--libproxy/module_types.hpp123
-rw-r--r--libproxy/modules.hpp89
-rw-r--r--libproxy/modules/config_direct.cpp62
-rw-r--r--libproxy/modules/config_envvar.cpp101
-rw-r--r--libproxy/modules/config_file.cpp118
-rw-r--r--libproxy/modules/config_gnome.cpp411
-rw-r--r--libproxy/modules/config_kde4.cpp169
-rw-r--r--libproxy/modules/config_w32reg.cpp194
-rw-r--r--libproxy/modules/config_wpad.cpp51
-rw-r--r--libproxy/modules/ignore_domain.cpp101
-rw-r--r--libproxy/modules/ignore_ip.cpp320
-rw-r--r--libproxy/modules/network_networkmanager.cpp143
-rw-r--r--libproxy/modules/pacrunner_mozjs.cpp232
-rw-r--r--libproxy/modules/pacrunner_webkit.cpp213
-rw-r--r--libproxy/modules/pxgconf.cpp180
-rw-r--r--libproxy/modules/wpad_dns.cpp67
-rw-r--r--libproxy/modules/wpad_dnsdevolution.cpp199
-rw-r--r--libproxy/modules/xhasclient.cpp36
-rw-r--r--libproxy/pac.cpp210
-rw-r--r--libproxy/pac.hpp87
-rw-r--r--libproxy/proxy.cpp554
-rw-r--r--libproxy/strdict.cpp126
-rw-r--r--libproxy/url.cpp516
-rw-r--r--libproxy/url.hpp157
-rw-r--r--utils/CMakeLists.txt5
-rw-r--r--utils/iniparse.c23
37 files changed, 2366 insertions, 3558 deletions
diff --git a/libproxy/CMakeLists.txt b/libproxy/CMakeLists.txt
index e06ba82..b484309 100644
--- a/libproxy/CMakeLists.txt
+++ b/libproxy/CMakeLists.txt
@@ -1,5 +1,5 @@
### Main library
-add_library(libproxy SHARED array.cpp config_file.cpp misc.cpp module_manager.cpp pac.cpp proxy.cpp strdict.cpp url.cpp)
+add_library(libproxy SHARED config_file.cpp dl_module.cpp module_manager.cpp module_types.cpp pac.cpp proxy.cpp url.cpp)
target_link_libraries(libproxy m pthread dl)
set_property(SOURCE proxy.cpp PROPERTY COMPILE_DEFINITIONS SYSCONFDIR="/etc/";MODULEDIR="${moduledir}")
set_target_properties(libproxy PROPERTIES PREFIX "" COMPILE_FLAGS -g VERSION 0 SOVERSION 0.0.0)
@@ -21,7 +21,7 @@ function(px_module name condition)
endif()
add_library(${name} MODULE modules/${name}.cpp)
target_link_libraries(${name} libproxy)
- set_target_properties(${name} PROPERTIES PREFIX "" COMPILE_FLAGS "-g -std=c99")
+ set_target_properties(${name} PROPERTIES PREFIX "" COMPILE_FLAGS -g)
set_property(SOURCE modules/${name}.cpp PROPERTY COMPILE_DEFINITIONS SYSCONFDIR="/etc/";LIBEXECDIR="${libexecdir}";GCONFTOOLBIN="${GCONFTOOLBIN}")
install(TARGETS ${name} LIBRARY DESTINATION ${rmoduledir})
if(${ARGC} GREATER 3)
@@ -60,15 +60,15 @@ if(UNIX AND NOT APPLE)
endif()
if(X11_FOUND)
px_check_modules(GNOME gconf-2.0)
- find_package(KDE4)
- if(${KDE4_FOUND} STREQUAL "TRUE")
- set(KDE4_FOUND 1)
- set(KDE4_LIBRARIES ${KDE4_KDECORE_LIBS})
- include_directories(${KDE4_INCLUDE_DIR})
- link_directories(${KDE4_LIB_DIR})
- else()
- set(KDE4_FOUND 0)
- endif()
+ #find_package(KDE4)
+ #if(${KDE4_FOUND} STREQUAL "TRUE")
+ # set(KDE4_FOUND 1)
+ # set(KDE4_LIBRARIES ${KDE4_KDECORE_LIBS})
+ # include_directories(${KDE4_INCLUDE_DIR})
+ # link_directories(${KDE4_LIB_DIR})
+ #else()
+ # set(KDE4_FOUND 0)
+ #endif()
endif()
find_program(GCONFTOOLBIN gconftool-2)
endif()
@@ -86,11 +86,11 @@ if(UNIX AND NOT APPLE)
px_module(network_networkmanager ${NM_FOUND} ${NM_LIBRARIES})
px_module(pacrunner_mozjs ${MOZJS_FOUND} ${MOZJS_LIBRARIES})
px_module(pacrunner_webkit ${WEBKIT_FOUND} ${WEBKIT_LIBRARIES})
-# if(GNOME_FOUND)
-# add_executable(pxgconf src/modules/pxgconf.c)
-# target_link_libraries(pxgconf ${GNOME_LIBRARIES})
-# install(TARGETS pxgconf RUNTIME DESTINATION ${rlibexecdir})
-# endif()
+ if(GNOME_FOUND)
+ add_executable(pxgconf modules/pxgconf.cpp)
+ target_link_libraries(pxgconf ${GNOME_LIBRARIES})
+ install(TARGETS pxgconf RUNTIME DESTINATION ${rlibexecdir})
+ endif()
elseif(APPLE)
px_module(pacrunner_webkit 2 ${WEBKIT_LIBRARIES})
px_module(pacrunner_macosx 2)
diff --git a/libproxy/array.cpp b/libproxy/array.cpp
deleted file mode 100644
index b4c7f23..0000000
--- a/libproxy/array.cpp
+++ /dev/null
@@ -1,157 +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.hpp"
-#include "array.hpp"
-
-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 = (pxArray *) px_malloc0(sizeof(pxArray));
- self->equals = equals ? equals : &identity;
- self->free = free ? free : &nothing;
- self->unique = unique;
- self->replace = replace;
- self->length = 0;
- self->data = NULL;
- 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;
- }
-
- void **data = (void **) 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)
-{
- 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 ; i < self->length ; i++)
- cb(self->data[i], arg);
-}
-
-int
-px_array_find(pxArray *self, const void *item)
-{
- if (!self || !item) return -1;
-
- for (int i=0 ; i < self->length ; 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;
- if (index >= self->length) return NULL;
-
- return self->data[index];
-}
-
-void
-px_array_free(pxArray *self)
-{
- if (!self) return;
-
- // NOTE: We free in the reverse order of allocation
- // This fixes an odd bug where dlopen()'d modules need
- // to be dlclose()'d in the reverse order of their opening
- for (int i=self->length-1 ; i >= 0 ; i--)
- self->free(self->data[i]);
- px_free(self->data);
- px_free(self);
-}
-
-int
-px_array_length(pxArray *self)
-{
- if (!self) return -1;
-
- return self->length;
-}
-
-void
-px_array_sort(pxArray *self, int (*compare)(const void *, const void *))
-{
- qsort(self->data, self->length, sizeof(void *), compare);
-}
-
diff --git a/libproxy/array.hpp b/libproxy/array.hpp
deleted file mode 100644
index d94b001..0000000
--- a/libproxy/array.hpp
+++ /dev/null
@@ -1,51 +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
- ******************************************************************************/
-
-#ifndef ARRAY_H_
-#define ARRAY_H_
-#include <stdbool.h>
-
-typedef bool (*pxArrayItemsEqual)(void *, void *);
-typedef void (*pxArrayItemCallback)(void *);
-typedef void (*pxArrayItemCallbackWithArg)(void *, void *);
-typedef struct _pxArray pxArray;
-
-__attribute__ ((visibility("default")))
-pxArray *px_array_new(pxArrayItemsEqual equals, pxArrayItemCallback free, bool unique, bool replace);
-
-__attribute__ ((visibility("default")))
-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);
-
-__attribute__ ((visibility("default")))
-const void *px_array_get(pxArray *self, int index);
-
-__attribute__ ((visibility("default")))
-void px_array_free(pxArray *self);
-
-int px_array_length(pxArray *self);
-
-void px_array_sort(pxArray *self, int (*compare)(const void *, const void *));
-
-#endif /* ARRAY_H_ */
diff --git a/libproxy/config_file.cpp b/libproxy/config_file.cpp
index f13e570..ae3ede4 100644
--- a/libproxy/config_file.cpp
+++ b/libproxy/config_file.cpp
@@ -17,102 +17,85 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
+#include <fstream>
+
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <string.h>
-#include "misc.hpp"
-#include "strdict.hpp"
#include "config_file.hpp"
-struct _pxConfigFile {
- char *filename;
- time_t mtime;
- pxStrDict *sections;
-};
+namespace com {
+namespace googlecode {
+namespace libproxy {
-pxConfigFile *
-px_config_file_new(char *filename)
-{
- /* 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 */
- pxConfigFile *self = (pxConfigFile *) px_malloc0(sizeof(pxConfigFile));
- self->filename = px_strdup(filename);
- self->mtime = st.st_mtime;
- self->sections = px_strdict_new((pxStrDictItemCallback) px_strdict_free);
-
- /* 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);
-
- /* Parse our file */
- for (char *line=NULL ; (line = px_readline(fd, NULL, 0)) ; px_free(line) )
- {
- if (*line)
- {
- /* Strip */
- char *tmp = px_strstrip(line);
- px_free(line); line = tmp;
- /* Check for comment and/or empty line */
- if (*line == '#' || !strcmp(line, "")) continue;
- /* If we have a new section */
- if (*line == '[' || line[strlen(line)-1] == ']')
- {
- /* 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));
- current = (pxStrDict *) px_strdict_get(self->sections, line);
- }
-
- }
-
- /* If this is a key/val line, get the key/val. */
- else 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);
- }
- }
- }
- close(fd);
- return self;
-}
+#define PX_CONFIG_FILE_DEFAULT_SECTION "__DEFAULT__"
-bool
-px_config_file_is_stale(pxConfigFile *self)
-{
- struct stat st;
- return (!stat(self->filename, &st) && st.st_mtime > self->mtime);
+static string trim(string str, const char *set) {
+ const string::size_type first = str.find_first_not_of(set);
+ if (first != string::npos)
+ str = str.substr(first, str.find_last_not_of(set)-first+1);
+ return str;
}
-char *
-px_config_file_get_value(pxConfigFile *self, char *section, char *key)
-{
- return px_strdup((const char *) px_strdict_get((pxStrDict *) px_strdict_get(self->sections, section), key));
+string config_file::get_value(const string key) throw (key_error) {
+ return this->get_value(PX_CONFIG_FILE_DEFAULT_SECTION, key);
}
-void
-px_config_file_free(pxConfigFile *self)
-{
- if (!self) return;
+string config_file::get_value(const string section, const string key) throw (key_error) {
+ if (this->sections.find(section) == this->sections.end())
+ throw key_error(string("Section not found: ") + section);
+ if (this->sections[section].find(key) == this->sections[section].end())
+ throw key_error(string("Key not found in section: ") + section);
+ return this->sections[section][key];
+}
- px_strdict_free(self->sections);
- px_free(self->filename);
- px_free(self);
+bool config_file::is_stale() {
+ struct stat st;
+ return (!stat(this->filename.c_str(), &st) && st.st_mtime > this->mtime);
}
+bool config_file::load(string filename) {
+ // Stat the file and get its mtime
+ struct stat st;
+ if (stat(filename.c_str(), &st))
+ return false;
+ this->filename = filename;
+ this->mtime = st.st_mtime;
+
+ // Open the file
+ ifstream file(filename.c_str());
+ if (!file.is_open())
+ return false;
+
+ string current = PX_CONFIG_FILE_DEFAULT_SECTION;
+ for (string line="" ; !file.eof() ; getline(file, line)) {
+ if (file.fail()) {
+ this->sections.clear();
+ file.close();
+ return false;
+ }
+
+ // Strip the line
+ line = trim(line, " \t");
+
+ // Check for comment and/or empty line
+ if (line[0] == '#' || line[0] == ';' || line == "") continue;
+
+ // If we have a new section, get the current section name
+ if (line[0] == '[' || line[line.size()-1] == ']')
+ current = trim(line, "[]");
+
+ // Otherwise set our value
+ else if (line.find('=') != string::npos)
+ this->sections[current][line.substr(0, line.find('='))] = line.substr(line.find('=')+1);
+ }
+
+ file.close();
+ return true;
+}
+
+}
+}
+}
diff --git a/libproxy/config_file.hpp b/libproxy/config_file.hpp
index 4d578bd..0be5045 100644
--- a/libproxy/config_file.hpp
+++ b/libproxy/config_file.hpp
@@ -1,38 +1,53 @@
/*******************************************************************************
* 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
******************************************************************************/
-#ifndef CONFIG_FILE_H_
-#define CONFIG_FILE_H_
+#ifndef CONFIG_FILE_HPP_
+#define CONFIG_FILE_HPP_
-#include <stdbool.h>
+#include <stdexcept>
+#include <map>
+using namespace std;
-#define PX_CONFIG_FILE_DEFAULT_SECTION "__DEFAULT__"
+namespace com {
+namespace googlecode {
+namespace libproxy {
-typedef struct _pxConfigFile pxConfigFile;
+class key_error : public runtime_error {
+public:
+ key_error(const string& __arg): runtime_error(__arg) {}
+};
-__attribute__ ((visibility("default")))
-pxConfigFile *px_config_file_new (char *filename);
-__attribute__ ((visibility("default")))
-bool px_config_file_is_stale (pxConfigFile *self);
-__attribute__ ((visibility("default")))
-char *px_config_file_get_value (pxConfigFile *self, char *section, char *key);
-__attribute__ ((visibility("default")))
-void px_config_file_free (pxConfigFile *self);
+class config_file {
+public:
+ string get_value(const string key) throw (key_error);
+ string get_value(const string section, const string key) throw (key_error);
+ bool is_stale();
+ bool load(string filename);
-#endif /*CONFIG_FILE_H_*/
+private:
+ string filename;
+ time_t mtime;
+ map<string, map<string, string> > sections;
+};
+
+}
+}
+}
+
+#endif /*CONFIG_FILE_HPP_*/
diff --git a/libproxy/dl_module.cpp b/libproxy/dl_module.cpp
new file mode 100644
index 0000000..ccceb44
--- /dev/null
+++ b/libproxy/dl_module.cpp
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * libproxy - A library for proxy configuration
+ * Copyright (C) 2009 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 "dl_module.hpp"
+
+#ifdef _WIN32
+#include <windows.h>
+#define pdlmtype HMODULE
+#define pdlopen(filename) LoadLibrary(filename)
+#define pdlsym GetProcAddress
+#define pdlclose FreeLibrary
+static std::string pdlerror() {
+ std::string e;
+ LPTSTR msg;
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL,
+ GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ &msg,
+ 0,
+ NULL);
+ e = std::string(msg);
+ LocalFree(msg);
+ return e;
+}
+
+#else
+#include <dlfcn.h>
+#define pdlmtype void*
+#define pdlopen(filename) dlopen(filename, RTLD_NOW | RTLD_LOCAL)
+#define pdlsym dlsym
+#define pdlclose dlclose
+static std::string pdlerror() { return std::string(dlerror()); }
+#endif
+
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
+
+dl_module::~dl_module() {
+ pdlclose((pdlmtype) this->dlobject);
+}
+
+dl_module::dl_module(const string filename) throw (dl_error) {
+ this->dlobject = pdlopen(filename.c_str());
+ if (!this->dlobject)
+ throw dl_error(pdlerror());
+}
+
+bool dl_module::operator==(const dl_module& module) const {
+ return (this->dlobject == module.dlobject);
+}
+
+void* dl_module::getsym(const string symbolname) const throw (dl_error) {
+ void*sym = pdlsym((pdlmtype) this->dlobject, symbolname.c_str());
+ if (!sym)
+ throw dl_error("Symbol not found: " + symbolname);
+ return sym;
+}
+
+}
+}
+}
diff --git a/libproxy/strdict.hpp b/libproxy/dl_module.hpp
index 01829e7..5ed1cb0 100644
--- a/libproxy/strdict.hpp
+++ b/libproxy/dl_module.hpp
@@ -1,39 +1,54 @@
/*******************************************************************************
* libproxy - A library for proxy configuration
- * Copyright (C) 2006 Nathaniel McCallum <nathaniel@natemccallum.com>
- *
+ * Copyright (C) 2009 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;
-
-__attribute__ ((visibility("default")))
-pxStrDict *px_strdict_new(pxStrDictItemCallback free);
-
-__attribute__ ((visibility("default")))
-bool px_strdict_set(pxStrDict *self, const char *key, void *value);
-
-__attribute__ ((visibility("default")))
-const void *px_strdict_get(pxStrDict *self, const char *key);
-
-void px_strdict_foreach(pxStrDict *self, pxStrDictForeachCallback *cb, void *arg);
-
-__attribute__ ((visibility("default")))
-void px_strdict_free(pxStrDict *self);
+#ifndef DLOBJECT_HPP_
+#define DLOBJECT_HPP_
+
+#include <string>
+#include <stdexcept>
+
+namespace com {
+namespace googlecode {
+namespace libproxy {
+
+using namespace std;
+
+class dl_error : public runtime_error {
+public:
+ dl_error(const string& __arg): runtime_error(__arg) {}
+};
+
+class dl_module {
+ public:
+ ~dl_module();
+ dl_module(const string filename) throw (dl_error);
+ bool operator==(const dl_module& module) const;
+ template <class T> T get_symbol(const string symbolname) const throw (dl_error) {
+ return (T) this->getsym(symbolname);
+ }
+
+ private:
+ void* getsym(const string symbolname) const throw (dl_error);
+ void* dlobject;
+ };
+}
+}
+}
+
+#endif /* DLOBJECT_HPP_ */
diff --git a/libproxy/misc.cpp b/libproxy/misc.cpp
deleted file mode 100644
index 2c79eba..0000000
--- a/libproxy/misc.cpp
+++ /dev/null
@@ -1,295 +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 <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <stdarg.h>
-
-#include "misc.hpp"
-
-/**
- * Allocates memory and always returns valid memory.
- * @size Amount of memory to allocate in bytes
- * @return Pointer to the allocated memory
- */
-__attribute__ ((visibility("default")))
-void *
-px_malloc0(size_t size)
-{
- void *mem = malloc(size);
- assert(mem != NULL);
- memset(mem, 0, size);
- return mem;
-}
-
-/**
- * Frees memory and doesn't crash if that memory is NULL
- * @mem Memory to free or NULL
- */
-__attribute__ ((visibility("default")))
-void
-px_free(void *mem)
-{
- if (!mem) return;
- free(mem);
-}
-
-/**
- * Duplicates the first n characters of the string s
- * @s String to duplicate
- * @n Number of characters of the string to duplicate
- * @return Newly allocated string
- */
-char *
-px_strndup(const char *s, size_t n)
-{
- if (!s) return NULL;
- char *tmp = (char *) px_malloc0(n+1);
- strncpy(tmp, s, n);
- return tmp;
-}
-
-/**
- * Duplicates a string
- * @s String to duplicate
- * @return Newly allocated string
- */
-char *
-px_strdup(const char *s)
-{
- if (!s) return NULL;
- return px_strndup(s, strlen(s));
-}
-
-/**
- * Duplicates a string vector
- * @sv String vector to duplicate
- * @return Newly allocated string vector (free w/ px_strfreev())
- */
-char **
-px_strdupv(const char **sv)
-{
- int count;
-
- if (!sv) return NULL;
- for (count=0 ; sv[count] ; count++);
-
- char **output = (char **) px_malloc0(sizeof(char *) * ++count);
- for (int i=0 ; sv[i] ; i++)
- output[i] = px_strdup(sv[i]);
-
- return output;
-}
-
-/**
- * Concatenates two or more strings into a newly allocated string
- * @s The first string to concatenate.
- * @... Subsequent strings. The last argument must be NULL.
- * @return Newly allocated string
- */
-char *
-px_strcat(const char *s, ...)
-{
- va_list args;
-
- /* 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 */
- char *output = (char *) px_malloc0(count + 1);
- strcat(output, s);
- va_start(args, s);
- for (char *tmp = NULL ; (tmp = va_arg(args, char *)) ; )
- strcat(output, tmp);
- va_end(args);
-
- return output;
-}
-
-/**
- * Joins NULL terminated array of strings into one string separated by delimiter
- * @strv NULL terminated array of string to join
- * @delimiter The string to use in between each string in the array
- * @return Newly allocated string
- */
-char *
-px_strjoin(const char **strv, const char *delimiter)
-{
- if (!strv) return NULL;
- if (!delimiter) return NULL;
-
- /* 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 */
- char *str = (char *) px_malloc0(length);
- for (int i=0 ; strv[i]; i++)
- {
- strcat(str, strv[i]);
- if (strv[i+1]) strcat(str, delimiter);
- }
- return str;
-}
-
-/**
- * Splits a string into a NULL terminated array based on delimiter
- * @string The string to split
- * @delimiter The delimiter to split on
- * @return The NULL terminated array (free with px_strfreev())
- */
-char **
-px_strsplit(const char *string, const char *delimiter)
-{
- /* if string is empty, return NULL */
- if (!string) return NULL;
-
- /* 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 */
- char **strv = (char **) px_malloc0(sizeof(char *) * (count + 1));
-
- /* Fill the vector */
- const char *last = string;
- for (int i=0 ; i < count ; i++)
- {
- const char *tmp = strstr(last, delimiter);
- if (!tmp)
- strv[i] = px_strdup(last);
- else
- {
- strv[i] = px_strndup(last, tmp - last);
- last = tmp + strlen(delimiter);
- }
- }
-
- return strv;
-}
-
-/**
- * Frees the memory used by a NULL terminated string array
- * @strv The NULL terminated string array
- */
-void
-px_strfreev(char **strv)
-{
- if (!strv) return;
- for (int i=0 ; *(strv + i) ; i++)
- px_free(*(strv + i));
- px_free(strv);
-}
-
-/**
- * Reads a single line of text from the specified file descriptor
- * @fd File descriptor to read from
- * @buffer The buffer to write to (usually NULL)
- * @bufsize The size of the buffer (usually 0)
- * @return Newly allocated string containing one line only
- */
-char *
-px_readline(int fd, char *buffer, size_t bufsize)
-{
- char c = '\0';
-
- /* Verify we have an open socket */
- if (fd < 0) return NULL;
-
- /* Read a character. If we don't get a character, return the buffer. */
- if (read(fd, &c, 1) != 1) return buffer;
-
- /* If we are at the end of the line, return. */
- if (c == '\n') return buffer ? buffer : px_strdup("");
-
- /* We have a character, make sure we have a buffer. */
- if (!buffer)
- {
- buffer = px_strdup("");
- bufsize = 0;
- }
-
- /* If our buffer is full, add more to the buffer. */
- if (bufsize <= strlen(buffer))
- {
- char *tmp = (char *) px_malloc0(1024 + strlen(buffer) + 1);
- strcpy(tmp, buffer);
- free(buffer);
- buffer = tmp;
- bufsize = strlen(buffer) + 1024;
- }
-
- strncat(buffer, &c, 1);
- return px_readline(fd, buffer, bufsize);
-}
-
-/**
- * Trims off all the leading whitespace characters
- * @string The string to strip
- * @return A newly allocated copy of string without all the leading whitespace
- */
-char *
-px_strlstrip(char *string)
-{
- for (int i=0 ; string[i] ; i++)
- if (!isspace(string[i]))
- return px_strdup(string + i);
- return px_strdup("");
-}
-
-/**
- * Trims off all the trailing whitespace characters
- * @string The string to strip
- * @return A newly allocated copy of string without all the trailing whitespace
- */
-char *
-px_strrstrip(char *string)
-{
- char *tmp = string = px_strdup(string);
-
- for (int i=0 ; string[i] ; i++)
- if (!isspace(string[i]))
- tmp = string + i;
- tmp[1] = '\0';
- return string;
-}
-
-/**
- * Trims off all the leading and trailing whitespace characters
- * @string The string to strip
- * @return A newly allocated copy of string without all the leading and trailing whitespace
- */
-char *
-px_strstrip(char *string)
-{
- char *tmp = px_strrstrip(string);
- string = px_strlstrip(tmp);
- px_free(tmp);
- return string;
-}
diff --git a/libproxy/module_manager.cpp b/libproxy/module_manager.cpp
index 4a18136..201fc76 100644
--- a/libproxy/module_manager.cpp
+++ b/libproxy/module_manager.cpp
@@ -17,181 +17,137 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdio.h>
-#include <stdlib.h>
-#include <libgen.h>
-#include <string.h>
-#include <dirent.h>
-#include <math.h>
-
-#ifdef _WIN32
-#include <windows.h>
-#define pdlmtype HMODULE
-#define pdlopen(filename) LoadLibrary(filename)
-#define pdlsym GetProcAddress
-#define pdlclose FreeLibrary
-#else
-#include <dlfcn.h>
-#define pdlmtype void *
-#define pdlopen(filename) dlopen(filename, RTLD_NOW | RTLD_LOCAL)
-#define pdlsym dlsym
-#define pdlclose dlclose
-#endif
+#include <sys/stat.h> // For stat()
+#include <dirent.h> // For opendir(), readdir(), closedir()
#include "module_manager.hpp"
-#include "misc.hpp"
-#include "array.hpp"
-#include "strdict.hpp"
-struct _pxModuleManager {
- pxArray *dlmodules;
- pxStrDict *registrations;
- pxStrDict *types;
-};
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
-typedef struct _pxModuleTypeRegistration {
- pxModuleRegistrationComparison cmp;
- bool sngl;
-} pxModuleTypeRegistration;
+static vector<string> strsplit(const char* cstr, string delimiter) {
+ vector<string> v;
+ string str = cstr ? cstr : "";
-static void
-regfree(pxModuleRegistration *self)
-{
- px_free(self->name);
- if (self->instance)
- self->free(self->instance);
- px_free(self);
-}
+ for (int i=str.find(delimiter) ; i != string::npos ; i=str.find(delimiter)) {
+ v.push_back(str.substr(0, i));
+ str = str.substr(i+delimiter.size());
+ }
+ if (str != "")
+ v.push_back(str);
-static bool
-regeq(pxModuleRegistration *self, pxModuleRegistration *other)
-{
- return !strcmp(self->name, other->name);
+ return v;
}
-static char *
-basename_noext(const char *filename)
-{
- char *tmp = px_strdup(filename);
- filename = px_strdup(basename(tmp));
- px_free(tmp);
- if (strrchr(filename, '.'))
- ((char *) strrchr(filename, '.'))[0] = '\0';
- return (char *) filename;
+static string basename_noext(string filename) {
+ // Basename
+ if (filename.find_last_of("/\\") != string::npos)
+ filename = filename.substr(filename.find_last_of("/\\")+1);
+
+ // Noext
+ if (filename.rfind(".") != string::npos)
+ return filename.substr(0, filename.rfind("."));
+ return filename;
}
-static bool
-globmatch(const char *glob, const char *string)
+static bool globmatch(string glob, string str)
{
- if (!glob) return false;
- if (!string) return false;
-
- char **segments = px_strsplit(glob, "*");
- for (int i=0 ; segments[i] ; i++)
+ vector<string> segments = strsplit(glob.c_str(), "*");
+ for (vector<string>::iterator i=segments.begin() ; i != segments.end() ; i++)
{
+ // Handle when the glob does not end with '*'
+ // (insist the segment match the end of the string)
+ if (i == segments.end() && *i != "" && str != "")
+ return false;
+
// Search for this segment in this string
- const char *offset = strstr(string, segments[i]);
+ int offset = str.find(*i);
// If the segment isn't found at all, its not a match
- if (!offset)
- goto nomatch;
+ if (offset == string::npos)
+ return false;
// Handle when the glob does not start with '*'
// (insist the segment match the start of the string)
- if (i == 0 && strcmp(segments[i], "") && offset != string)
- goto nomatch;
+ if (i == segments.begin() && *i != "" && offset != 0)
+ return false;
// Increment further into the string
- string = offset + strlen(segments[i]);
-
- // Handle when the glob does not end with '*'
- // (insist the segment match the end of the string)
- if (!segments[i+1] && strcmp(segments[i], "") && string[0])
- goto nomatch;
+ str = str.substr(offset + i->size());
}
- px_strfreev(segments);
return true;
-
- nomatch:
- px_strfreev(segments);
- return false;
}
-pxModuleManager *
-px_module_manager_new()
-{
- pxModuleManager *self = (pxModuleManager *) px_malloc0(sizeof(pxModuleManager));
- self->dlmodules = px_array_new(NULL, (pxArrayItemCallback) pdlclose, true, false);
- self->registrations = px_strdict_new((pxStrDictItemCallback) px_array_free);
- self->types = px_strdict_new((pxStrDictItemCallback) px_free);
- return self;
+string module::_bnne(const string fn) const {
+ return basename_noext(fn);
}
-void
-px_module_manager_free(pxModuleManager *self)
-{
- px_strdict_free(self->types);
- px_strdict_free(self->registrations);
- px_array_free(self->dlmodules);
- px_free(self);
+module_manager::~module_manager() {
+ // Free all modules
+ for (map<const type_info*, vector<module*> >::iterator i=this->modules.begin() ; i != this->modules.end() ; i++) {
+ for (vector<module*>::iterator j=i->second.begin() ; j != i->second.end() ; j++)
+ delete *j;
+ i->second.clear();
+ }
+ this->modules.clear();
+
+ // Free all dl_modules
+ for (set<dl_module*>::iterator i=this->dl_modules.begin() ; i != this->dl_modules.end() ; i++)
+ delete *i;
+ this->dl_modules.clear();
}
-bool
-px_module_manager_load(pxModuleManager *self, char *filename)
-{
- pxModuleLoadFunction load;
- if (!self) return false;
- if (!filename) return false;
+bool module_manager::load_file(const string filename) {
+ dl_module* dlobj = NULL;
+ module_manager::INIT_TYPE load;
+
+ // Stat the file to make sure it is a file
+ struct stat st;
+ if (stat(filename.c_str(), &st) != 0) return false;
+ if (!S_ISREG(st.st_mode)) return false;
// Prepare for blacklist check
- char **blacklist = px_strsplit(getenv("PX_MODULE_BLACKLIST"), ",");
- char **whitelist = px_strsplit(getenv("PX_MODULE_WHITELIST"), ",");
- char *modname = basename_noext(filename);
- bool doload = true;
+ vector<string> blacklist = strsplit(getenv("PX_MODULE_BLACKLIST"), ",");
+ vector<string> whitelist = strsplit(getenv("PX_MODULE_WHITELIST"), ",");
+ string modname = basename_noext(filename);
+ bool doload = true;
// Check our whitelist/blacklist to see if we should load this module
- for (int i=0 ; blacklist && blacklist[i]; i++)
- if (globmatch(blacklist[i], modname))
+ for (vector<string>::iterator i=blacklist.begin() ; i != blacklist.end() ; i++)
+ if (globmatch(*i, modname))
doload = false;
- for (int i=0 ; whitelist && whitelist[i]; i++)
- if (globmatch(whitelist[i], modname))
+ for (vector<string>::iterator i=whitelist.begin() ; i != whitelist.end() ; i++)
+ if (globmatch(*i, modname))
doload = true;
- // Cleanup
- px_strfreev(blacklist);
- px_strfreev(whitelist);
- px_free(modname);
-
if (!doload)
return false;
- /* Load the module */
- pdlmtype module = pdlopen(filename);
- if (!module) goto error;
+ // Load the module
+ dlobj = new dl_module (filename);
- /* Make sure this module is unique */
- if (px_array_find(self->dlmodules, module) >= 0) goto error;
+ // Insert the module
+ if (this->dl_modules.insert(dlobj).second == false) {
+ delete dlobj;
+ return false;
+ }
- /* Call the px_module_load() function */
- load = (pxModuleLoadFunction) pdlsym(module, "px_module_load");
- if (!load || !load(self)) goto error;
+ // Call the INIT function
+ load = dlobj->get_symbol<module_manager::INIT_TYPE>(module_manager::INIT_NAME());
+ if (!load || !load(*this)) {
+ this->dl_modules.erase(dlobj);
+ delete dlobj;
+ return false;
+ }
- if (!px_array_add(self->dlmodules, module)) goto error;
return true;
-
-error:
- if (module) pdlclose(module);
- return false;
}
-bool
-px_module_manager_load_dir(pxModuleManager *self, char *dirname)
-{
- if (!self) return false;
- if (!dirname) return false;
-
+bool module_manager::load_dir(const string dirname) {
/* Open the module dir */
- DIR *moduledir = opendir(dirname);
+ DIR *moduledir = opendir(dirname.c_str());
if (!moduledir) return false;
/* For each module... */
@@ -200,88 +156,14 @@ px_module_manager_load_dir(pxModuleManager *self, char *dirname)
for (int i=0 ; (ent = readdir(moduledir)) ; i++)
{
/* Load the module */
- char *tmp = px_strcat(dirname, "/", ent->d_name, NULL);
- loaded = px_module_manager_load(self, tmp) || loaded;
- px_free(tmp);
+ string tmp = dirname + "/" + ent->d_name;
+ loaded = this->load_file(tmp) || loaded;
+
}
closedir(moduledir);
return loaded;
}
-bool
-_px_module_manager_register_module_full(pxModuleManager *self,
- const char *id,
- const char *name,
- size_t namelen,
- pxModuleConstructor _new,
- pxModuleDestructor free)
-{
- if (!self) return false;
- if (!id) return false;
- if (!name) return false;
- if (!_new) return false;
-
- // Ensure only a single registration in the case of a singleton
- pxModuleTypeRegistration *tr = (pxModuleTypeRegistration *) px_strdict_get(self->types, id);
- if (tr && tr->sngl && px_array_length((pxArray *) px_strdict_get(self->registrations, id)) > 0)
- return false;
-
- pxModuleRegistration *reg = (pxModuleRegistration *) px_malloc0(sizeof(pxModuleRegistration));
- reg->name = px_strndup(name, namelen);
- reg->pxnew = _new;
- reg->free = free;
-
- // Create a new empty array if there is no registrations for this id
- if (!px_strdict_get(self->registrations, id))
- px_strdict_set(self->registrations, id, px_array_new((pxArrayItemsEqual) regeq, (pxArrayItemCallback) regfree, true, true));
-
- // Add the module to the registrations for this id
- pxArray *registrations = (pxArray *) px_strdict_get(self->registrations, id);
- return px_array_add(registrations, reg);
}
-
-void **
-_px_module_manager_instantiate_type_full(pxModuleManager *self,
- const char *id)
-{
- if (!self) return NULL;
- if (!id) return NULL;
-
- // Find the array of registrations for this id
- pxArray *regs = (pxArray *) px_strdict_get(self->registrations, id);
- if (!regs || px_array_length(regs) < 1) return NULL;
-
- // Make sure we have an instance for each of our registrations
- for (int i=0 ; i < px_array_length(regs) ; i++)
- {
- pxModuleRegistration *reg = (pxModuleRegistration *) px_array_get(regs, i);
- if (!reg->instance)
- reg->instance = reg->pxnew();
- }
-
- // Sort the instances
- if (px_strdict_get(self->types, id))
- px_array_sort(regs, (int (*)(const void*, const void*)) ((pxModuleTypeRegistration *) px_strdict_get(self->types, id))->cmp);
-
- // Allocate our instances array
- void **instances = (void **) px_malloc0(sizeof(void *) * (px_array_length(regs) + 1));
- for (int i=0 ; i < px_array_length(regs) ; i++)
- instances[i] = ((pxModuleRegistration *) px_array_get(regs, i))->instance;
- return instances;
}
-
-bool
-_px_module_manager_register_type_full(pxModuleManager *self,
- const char *id,
- pxModuleRegistrationComparison cmp,
- bool singleton)
-{
- if (!self) return false;
- if (!id) return false;
- if (!cmp && !singleton) return true;
-
- pxModuleTypeRegistration *tr = (pxModuleTypeRegistration *) px_malloc0(sizeof(pxModuleTypeRegistration));
- tr->cmp = cmp;
- tr->sngl = singleton;
- return px_strdict_set(self->types, id, tr);
}
diff --git a/libproxy/module_manager.hpp b/libproxy/module_manager.hpp
index edc82f0..9c7ce4d 100644
--- a/libproxy/module_manager.hpp
+++ b/libproxy/module_manager.hpp
@@ -17,61 +17,103 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#ifndef MODULE_MANAGER_H_
-#define MODULE_MANAGER_H_
-
-#include <stdbool.h>
-#include <assert.h>
-
-/*
- * Define the pxModuleManager object
- */
-typedef struct _pxModuleManager pxModuleManager;
-typedef void *(*pxModuleConstructor)();
-typedef void (*pxModuleDestructor) (void *module);
-
-typedef bool (*pxModuleLoadFunction)(pxModuleManager *);
-typedef void (*pxModuleFreeFunction)(pxModuleManager *);
-
-
-/*
- * Define the pxModuleRegistration object
- */
-struct _pxModuleRegistration {
- char *name;
- void *instance;
- pxModuleConstructor pxnew;
- pxModuleDestructor free;
+#ifndef MODULEMANAGER_HPP_
+#define MODULEMANAGER_HPP_
+
+#include <map>
+#include <set>
+#include <vector>
+#include <typeinfo>
+#include <algorithm>
+
+#include "dl_module.hpp"
+
+#define PX_MODULE_ID(name) virtual string get_id() const { return this->_bnne(name ? name : __FILE__); }
+#define PX_MODULE_LOAD(basetype, name, cond) \
+ extern "C" bool px_module_load(module_manager& mm) { \
+ if (cond) return mm.register_module<basetype>(new name ## _ ## basetype); \
+ return false; \
+ }
+
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
+
+class module {
+public:
+ virtual ~module() {}
+ virtual bool operator<(const module& other) const { return false; }
+ virtual string get_id() const=0;
+
+protected:
+ string _bnne(const string fn) const;
};
-typedef struct _pxModuleRegistration pxModuleRegistration;
-typedef int (*pxModuleRegistrationComparison)(pxModuleRegistration **self, pxModuleRegistration **other);
-pxModuleManager *px_module_manager_new ();
-void px_module_manager_free (pxModuleManager *self);
+class module_manager {
+public:
+ typedef bool (*INIT_TYPE)(module_manager&);
+ static const char* INIT_NAME() { return "px_module_load"; }
+
+ ~module_manager();
+
+ template <class T> vector<T*> get_modules() const {
+ vector<module*> modlist = this->modules.find(&typeid(T))->second;
+ vector<T*> retlist;
-bool px_module_manager_load (pxModuleManager *self, char *filename);
-bool px_module_manager_load_dir (pxModuleManager *self, char *dirname);
+ for (int i=0 ; i < modlist.size() ; i++)
+ retlist.push_back(dynamic_cast<T*>(modlist[i]));
-#define __str__(s) #s
-#define __px_module_manager_get_id(type, version) #type "__" __str__(version)
+ return retlist;
+ }
-__attribute__ ((visibility("default")))
-bool _px_module_manager_register_module_full(pxModuleManager *self, const char *id, const char *name, size_t namelen, pxModuleConstructor pxnew, pxModuleDestructor free);
-#define px_module_manager_register_module(self, type, pxnew, free) \
- _px_module_manager_register_module_full(self, __px_module_manager_get_id(type, type ## Version), \
- __FILE__, strrchr(__FILE__, '.') ? strrchr(__FILE__, '.') - __FILE__ : strlen(__FILE__), \
- pxnew, free)
-#define px_module_manager_register_module_with_name(self, type, name, pxnew, free) \
- _px_module_manager_register_module_full(self, __px_module_manager_get_id(type, type ## Version), name, strlen(name), pxnew, free)
+ template <class T> bool register_module(T* module) {
+ struct pcmp {
+ static bool cmp(T* x, T* y) { return *x < *y; }
+ };
-void **_px_module_manager_instantiate_type_full(pxModuleManager *self, const char *id);
-#define px_module_manager_instantiate_type(self, type) \
- (type **) _px_module_manager_instantiate_type_full(self, __px_module_manager_get_id(type, type ## Version))
+ // If the class for this module is a singleton...
+ if (this->singletons.find(&typeid(T)) != this->singletons.end()) {
+ // ... and we already have an instance of this class ...
+ if (this->modules[&typeid(T)].size() > 0) {
+ // ... free the module and return
+ delete module;
+ return false;
+ }
+ }
-bool _px_module_manager_register_type_full(pxModuleManager *self, const char *id, pxModuleRegistrationComparison cmp, bool singleton);
-#define px_module_manager_register_type(self, type, cmp, sngl) \
- _px_module_manager_register_type_full(self, __px_module_manager_get_id(type, type ## Version), cmp, sngl)
+ // Otherwise we just add the module and sort
+ vector<T*> modlist = this->get_modules<T>();
+ modlist.push_back(module);
+ sort(modlist.begin(), modlist.end(), &pcmp::cmp);
+
+ // Insert to our store
+ this->modules[&typeid(T)].clear();
+ for (int i=0 ; i < modlist.size() ; i++)
+ this->modules[&typeid(T)].push_back(modlist[i]);
+
+ return true;
+
+ }
+
+ template <class T> bool set_singleton(bool singleton) {
+ if (singleton)
+ return this->singletons.insert(&typeid(T)).second;
+ this->singletons.erase(&typeid(T));
+ return true;
+ }
+
+ bool load_file(const string filename);
+ bool load_dir(const string dirname);
+
+private:
+ set<dl_module*> dl_modules;
+ map<const type_info*, vector<module*> > modules;
+ set<const type_info*> singletons;
+};
-#define PX_MODULE_SUBCLASS(type) type __parent__
+}
+}
+}
-#endif /* MODULE_MANAGER_H_ */
+#endif /* MODULEMANAGER_HPP_ */
diff --git a/libproxy/module_types.cpp b/libproxy/module_types.cpp
new file mode 100644
index 0000000..c5c2b70
--- /dev/null
+++ b/libproxy/module_types.cpp
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * libproxy - A library for proxy configuration
+ * Copyright (C) 2009 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 "module_types.hpp"
+
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
+
+static const char *DEFAULT_CONFIG_ORDER[] = {
+ "USER",
+ "SESSION",
+ "SYSTEM",
+ "config_envvar",
+ "config_wpad",
+ NULL
+};
+
+static const char *DEFAULT_WPAD_ORDER[] = {
+ "wpad_dhcp",
+ "wpad_slp",
+ "wpad_dns",
+ "wpad_dnsdevolution",
+ NULL
+};
+
+static inline int _config_module_findpos(config_module::category category, string id, string order) {
+ if (order == "")
+ return 0;
+
+ size_t next = order.find(",");
+ string segment = order.substr(0, next);
+
+ if ((segment == "USER" && config_module::CATEGORY_USER == category) ||
+ (segment == "SESSION" && config_module::CATEGORY_SESSION == category) ||
+ (segment == "SYSTEM" && config_module::CATEGORY_SYSTEM == category) ||
+ (segment == id))
+ return 0;
+
+ return 1 + _config_module_findpos(category, id, order.substr(next == string::npos ? string::npos : next+1));
+}
+
+string config_module::get_ignore(url url) {
+ return "";
+}
+
+bool config_module::set_creds(url proxy, string username, string password) {
+ return false;
+}
+
+bool config_module::operator<(const config_module& module) const {
+ // Attempt to get config order
+ const char* fileorder = getenv("_PX_CONFIG_ORDER");
+ const char* envorder = getenv("PX_CONFIG_ORDER");
+
+ // Create the config order
+ string order = string(fileorder ? fileorder : "") +
+ string((fileorder && envorder) ? "," : "") +
+ string( envorder ? envorder : "");
+ for (int i=0 ; DEFAULT_CONFIG_ORDER[i] ; i++)
+ order += string(",") + DEFAULT_CONFIG_ORDER[i];
+
+ return (_config_module_findpos(this->get_category(), this->get_id(), order) -
+ _config_module_findpos(module.get_category(), module.get_id(), order) < 0);
+}
+
+bool config_module::get_valid() {
+ return this->valid;
+}
+
+void config_module::set_valid(bool valid) {
+ this->valid = valid;
+}
+
+pacrunner_module::pacrunner_module() {
+ this->pr = NULL;
+}
+
+pacrunner_module::~pacrunner_module() {
+ if (this->pr) delete this->pr;
+}
+
+string pacrunner_module::run(const pac pac, const url url) throw (bad_alloc) {
+ if (!this->pr || this->last != pac.to_string()) {
+ if (this->pr) delete this->pr;
+ this->pr = this->get_pacrunner(pac);
+ this->last = pac.to_string();
+ }
+
+ return this->pr->run(url);
+}
+
+bool wpad_module::operator<(const wpad_module& module) const {
+ for (int i=0 ; DEFAULT_WPAD_ORDER[i] ; i++) {
+ if (module.get_id() == DEFAULT_WPAD_ORDER[i])
+ break;
+ if (this->get_id() == DEFAULT_WPAD_ORDER[i])
+ return true;
+ }
+ return false;
+}
+
+
+}
+}
+}
diff --git a/libproxy/module_types.hpp b/libproxy/module_types.hpp
new file mode 100644
index 0000000..b9aa3ea
--- /dev/null
+++ b/libproxy/module_types.hpp
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * libproxy - A library for proxy configuration
+ * Copyright (C) 2009 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
+ ******************************************************************************/
+
+#ifndef MODULE_TYPES_HPP_
+#define MODULE_TYPES_HPP_
+
+#include <stdexcept>
+
+#include "module_manager.hpp"
+#include "pac.hpp"
+
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
+
+// Config module
+class config_module : public module {
+public:
+ typedef enum {
+ CATEGORY_AUTO = 0,
+ CATEGORY_NONE = 0,
+ CATEGORY_SYSTEM = 1,
+ CATEGORY_SESSION = 2,
+ CATEGORY_USER = 3,
+ CATEGORY__LAST = CATEGORY_USER
+ } category;
+
+ // Abstract methods
+ virtual category get_category() const=0;
+ virtual url get_config(url dst) throw (runtime_error)=0;
+
+ // Virtual methods
+ virtual string get_ignore(url dst);
+ virtual bool set_creds(url proxy, string username, string password);
+
+ // Final methods
+ bool get_valid();
+ void set_valid(bool valid);
+ bool operator<(const config_module& module) const;
+private:
+ bool valid;
+};
+
+#define PX_MODULE_CONFIG_CATEGORY(cat) virtual category get_category() const { return cat; }
+
+// Ignore module
+class ignore_module : public module {
+public:
+ // Abstract methods
+ virtual bool ignore(url& dst, string ignorestr)=0;
+};
+
+// Network module
+class network_module : public module {
+public:
+ // Abstract methods
+ virtual bool changed()=0;
+};
+
+// PACRunner module
+class pacrunner {
+public:
+ virtual string run(const url url) throw (bad_alloc)=0;
+};
+
+class pacrunner_module : public module {
+public:
+ // Abstract methods
+ virtual pacrunner* get_pacrunner(const pac pac) throw (bad_alloc)=0;
+
+ // Final methods
+ pacrunner_module();
+ ~pacrunner_module();
+ string run(const pac pac, const url dst) throw (bad_alloc);
+private:
+ pacrunner* pr;
+ string last;
+};
+
+#define PX_DEFINE_PACRUNNER_MODULE(name, cond) \
+ class name ## _pacrunner_module : public pacrunner_module { \
+ public: \
+ PX_MODULE_ID(NULL); \
+ pacrunner* get_pacrunner(const pac pac) throw (bad_alloc) { \
+ return new name ## _pacrunner(pac); \
+ } \
+ }; \
+ PX_MODULE_LOAD(pacrunner_module, name, cond)
+
+// WPAD module
+class wpad_module : public module {
+public:
+ // Abstract methods
+ virtual bool found()=0;
+ virtual pac* next()=0;
+ virtual void rewind()=0;
+
+ // Virtual methods
+ virtual bool operator<(const wpad_module& module) const;
+};
+
+}
+}
+}
+
+#endif /* MODULE_TYPES_HPP_ */
diff --git a/libproxy/modules.hpp b/libproxy/modules.hpp
deleted file mode 100644
index 2c84630..0000000
--- a/libproxy/modules.hpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*******************************************************************************
- * libproxy - A library for proxy configuration
- * Copyright (C) 2009 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
- ******************************************************************************/
-
-#ifndef MODULE_H_
-#define MODULE_H_
-#include "module_manager.hpp"
-#include "pac.hpp"
-
-/*
- * Config module
- */
-enum _pxConfigModuleCategory {
- PX_CONFIG_MODULE_CATEGORY_AUTO = 0,
- PX_CONFIG_MODULE_CATEGORY_NONE = 0,
- PX_CONFIG_MODULE_CATEGORY_SYSTEM = 1,
- PX_CONFIG_MODULE_CATEGORY_SESSION = 2,
- PX_CONFIG_MODULE_CATEGORY_USER = 3,
- PX_CONFIG_MODULE_CATEGORY__LAST = PX_CONFIG_MODULE_CATEGORY_USER
-};
-typedef enum _pxConfigModuleCategory pxConfigModuleCategory;
-
-typedef struct _pxConfigModule {
- pxConfigModuleCategory category;
- bool valid;
- char *(*get_config) (struct _pxConfigModule *self, pxURL *url);
- char *(*get_ignore) (struct _pxConfigModule *self, pxURL *url);
- bool (*get_credentials)(struct _pxConfigModule *self, pxURL *proxy, char **username, char **password);
- bool (*set_credentials)(struct _pxConfigModule *self, pxURL *proxy, const char *username, const char *password);
-} pxConfigModule;
-#define pxConfigModuleVersion 0
-
-#define PX_CONFIG_MODULE_BUILD(self, cat, getconf, getign, getcred, setcred) \
- ((pxConfigModule *) self)->category = cat; \
- ((pxConfigModule *) self)->get_config = getconf; \
- ((pxConfigModule *) self)->get_ignore = getign; \
- ((pxConfigModule *) self)->get_credentials = getcred; \
- ((pxConfigModule *) self)->set_credentials = setcred;
-
-/*
- * Ignore module
- */
-typedef struct _pxIgnoreModule {
- bool (*ignore)(struct _pxIgnoreModule *self, pxURL *url, const char *ignorestr);
-} pxIgnoreModule;
-#define pxIgnoreModuleVersion 0
-
-/*
- * Network module
- */
-typedef struct _pxNetworkModule {
- bool (*changed)(struct _pxNetworkModule *self);
-} pxNetworkModule;
-#define pxNetworkModuleVersion 0
-
-/*
- * PACRunner module
- */
-typedef struct _pxPACRunnerModule {
- char *(*run)(struct _pxPACRunnerModule *self, pxPAC *pac, pxURL *url);
-} pxPACRunnerModule;
-#define pxPACRunnerModuleVersion 0
-
-/*
- * WPAD module
- */
-typedef struct _pxWPADModule {
- bool found;
- pxPAC *(*next) (struct _pxWPADModule *self);
- void (*rewind)(struct _pxWPADModule *self);
-} pxWPADModule;
-#define pxWPADModuleVersion 0
-
-#endif /* MODULE_H_ */
diff --git a/libproxy/modules/config_direct.cpp b/libproxy/modules/config_direct.cpp
deleted file mode 100644
index 446e7fb..0000000
--- a/libproxy/modules/config_direct.cpp
+++ /dev/null
@@ -1,62 +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 <stdlib.h>
-#include <string.h>
-
-#include "../misc.hpp"
-#include "../modules.hpp"
-
-static char *
-_get_config(pxConfigModule *self, pxURL *url)
-{
- return px_strdup("direct://");
-}
-
-static char *
-_get_ignore(pxConfigModule *self, pxURL *url)
-{
- return px_strdup("");
-}
-
-static bool
-_get_credentials(pxConfigModule *self, pxURL *url, char **username, char **password)
-{
- return false;
-}
-
-static bool
-_set_credentials(pxConfigModule *self, pxURL *url, const char *username, const char *password)
-{
- return false;
-}
-
-static void *
-_constructor()
-{
- pxConfigModule *self = px_malloc0(sizeof(pxConfigModule));
- PX_CONFIG_MODULE_BUILD(self, PX_CONFIG_MODULE_CATEGORY_NONE, _get_config, _get_ignore, _get_credentials, _set_credentials);
- return self;
-}
-
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxConfigModule, _constructor, px_free);
-}
diff --git a/libproxy/modules/config_envvar.cpp b/libproxy/modules/config_envvar.cpp
index 315bd0c..b8620b5 100644
--- a/libproxy/modules/config_envvar.cpp
+++ b/libproxy/modules/config_envvar.cpp
@@ -17,60 +17,47 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <string.h>
-
-#include "../misc.hpp"
-#include "../modules.hpp"
-
-static char *
-_get_config(pxConfigModule *self, pxURL *url)
-{
- char *proxy = NULL;
-
- // If the URL is an ftp url, try to read the ftp proxy
- if (!strcmp(px_url_get_scheme(url), "ftp"))
- proxy = getenv("ftp_proxy");
-
- // If the URL is an https url, try to read the https proxy
- else if (!strcmp(px_url_get_scheme(url), "https"))
- proxy = getenv("https_proxy");
-
- // If the URL is not ftp or no ftp_proxy was found, get the http_proxy
- if (!proxy)
- proxy = getenv("http_proxy");
-
- return px_strdup(proxy);
-}
-
-static char *
-_get_ignore(pxConfigModule *self, pxURL *url)
-{
- return px_strdup(getenv("no_proxy"));
-}
-
-static bool
-_get_credentials(pxConfigModule *self, pxURL *url, char **username, char **password)
-{
- return false;
-}
-
-static bool
-_set_credentials(pxConfigModule *self, pxURL *url, const char *username, const char *password)
-{
- return false;
-}
-
-static void *
-_constructor()
-{
- pxConfigModule *self = (pxConfigModule *) px_malloc0(sizeof(pxConfigModule));
- PX_CONFIG_MODULE_BUILD(self, PX_CONFIG_MODULE_CATEGORY_NONE, _get_config, _get_ignore, _get_credentials, _set_credentials);
- return self;
-}
-
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxConfigModule, _constructor, px_free);
-}
+#include <cstdlib>
+
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
+
+class envvar_config_module : public config_module {
+public:
+ PX_MODULE_ID(NULL);
+ PX_MODULE_CONFIG_CATEGORY(config_module::CATEGORY_NONE);
+
+ url get_config(url url) throw (runtime_error) {
+ char *proxy = NULL;
+
+ // If the URL is an ftp url, try to read the ftp proxy
+ if (url.get_scheme() == "ftp") {
+ if (!(proxy = getenv("ftp_proxy")))
+ proxy = getenv("FTP_PROXY");
+ }
+
+ // If the URL is an https url, try to read the https proxy
+ if (url.get_scheme() == "https") {
+ if (!(proxy = getenv("https_proxy")))
+ proxy = getenv("HTTPS_PROXY");
+ }
+
+ // If the URL is not ftp or no ftp_proxy was found, get the http_proxy
+ if (!proxy) {
+ if (!(proxy = getenv("http_proxy")))
+ proxy = getenv("HTTP_PROXY");
+ }
+
+ if (!proxy)
+ throw runtime_error("Unable to read configuration");
+ return com::googlecode::libproxy::url(proxy);
+ }
+
+ string get_ignore(url dst) {
+ char *ignore = getenv("no_proxy");
+ ignore = ignore ? ignore : getenv("NO_PROXY");
+ return string(ignore ? ignore : "");
+ }
+};
+
+PX_MODULE_LOAD(config_module, envvar, true);
diff --git a/libproxy/modules/config_file.cpp b/libproxy/modules/config_file.cpp
index 39cd01f..bd5640a 100644
--- a/libproxy/modules/config_file.cpp
+++ b/libproxy/modules/config_file.cpp
@@ -17,98 +17,48 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <string.h>
-
-#include "../misc.hpp"
-#include "../modules.hpp"
#include "../config_file.hpp"
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
-typedef struct _pxFileConfigModule {
- PX_MODULE_SUBCLASS(pxConfigModule);
- char *filename;
- pxConfigFile *cf;
-} pxFileConfigModule;
-
-static void
-_destructor(void *s)
-{
- pxFileConfigModule *self = (pxFileConfigModule *) self;
-
- px_config_file_free(self->cf);
- px_free(self->filename);
- px_free(self);
-}
-
-static char *
-_get_config(pxConfigModule *ss, pxURL *url)
-{
- pxFileConfigModule *self = (pxFileConfigModule *) self;
-
- if (!self->cf)
- self->cf = px_config_file_new(self->filename);
- if (!self->cf)
- return NULL;
- return px_config_file_get_value(self->cf, PX_CONFIG_FILE_DEFAULT_SECTION, "proxy");
-}
-
-static char *
-_get_ignore(pxConfigModule *s, pxURL *url)
-{
- pxFileConfigModule *self = (pxFileConfigModule *) self;
-
- if (!self->cf)
- self->cf = px_config_file_new(self->filename);
- if (!self->cf)
- return NULL;
- return px_config_file_get_value(self->cf, PX_CONFIG_FILE_DEFAULT_SECTION, "ignore");
-}
+class system_file_config_module : public config_module {
+public:
+ PX_MODULE_ID("config_file_system");
+ PX_MODULE_CONFIG_CATEGORY(config_module::CATEGORY_SYSTEM);
-static bool
-_get_credentials(pxConfigModule *s, pxURL *proxy, char **username, char **password)
-{
- pxFileConfigModule *self = (pxFileConfigModule *) self;
-
- return false;
-}
+ system_file_config_module() {
+ this->cf.load(this->get_filename());
+ }
-static bool
-_set_credentials(pxConfigModule *s, pxURL *proxy, const char *username, const char *password)
-{
- pxFileConfigModule *self = (pxFileConfigModule *) self;
+ url get_config(url url) throw (runtime_error) {
+ if (this->cf.is_stale())
+ this->cf.load(this->get_filename());
+ return this->cf.get_value("proxy");
+ }
- return false;
-}
+ string get_ignore(url& url) {
+ if (this->cf.is_stale())
+ this->cf.load(this->get_filename());
+ return this->cf.get_value("ignore");
+ }
-static void *
-_system_constructor()
-{
- pxFileConfigModule *self = (pxFileConfigModule *) px_malloc0(sizeof(pxFileConfigModule));
- PX_CONFIG_MODULE_BUILD(self, PX_CONFIG_MODULE_CATEGORY_SYSTEM, _get_config, _get_ignore, _get_credentials, _set_credentials);
- self->filename = px_strdup(SYSCONFDIR "proxy.conf");
+protected:
+ virtual string get_filename() { return SYSCONFDIR "proxy.conf"; }
- return self;
-}
+private:
+ config_file cf;
+};
-static void *
-_user_constructor()
-{
- pxFileConfigModule *self = (pxFileConfigModule *) px_malloc0(sizeof(pxFileConfigModule));
- PX_CONFIG_MODULE_BUILD(self, PX_CONFIG_MODULE_CATEGORY_USER, _get_config, _get_ignore, _get_credentials, _set_credentials);
- self->filename = px_strcat(getenv("HOME"), "/", ".proxy.conf", NULL);
+class user_file_config_module : public system_file_config_module {
+public:
+ PX_MODULE_ID("config_file_user");
+ PX_MODULE_CONFIG_CATEGORY(config_module::CATEGORY_USER);
- if (!self->filename || !strcmp(self->filename, ""))
- {
- _destructor((void *) self);
- return NULL;
- }
- return self;
-}
+protected:
+ virtual string get_filename() { return string(getenv("HOME")) + string("/.proxy.conf"); }
+};
-bool
-px_module_load(pxModuleManager *self)
-{
- bool a = px_module_manager_register_module_with_name(self, pxConfigFile, "config_file_system", _system_constructor, _destructor);
- bool b = px_module_manager_register_module_with_name(self, pxConfigFile, "config_file_user", _user_constructor, _destructor);
- return (a || b);
+extern "C" bool px_module_load(module_manager& mm) {
+ bool success = mm.register_module<config_module>(new user_file_config_module);
+ return mm.register_module<config_module>(new system_file_config_module) || success;
}
diff --git a/libproxy/modules/config_gnome.cpp b/libproxy/modules/config_gnome.cpp
index 91907ae..3675924 100644
--- a/libproxy/modules/config_gnome.cpp
+++ b/libproxy/modules/config_gnome.cpp
@@ -17,261 +17,220 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
-#include <time.h>
-
-#include "../misc.hpp"
-#include "../modules.hpp"
-#include "../strdict.hpp"
-#include "xhasclient.cpp"
-
-#define BUFFERSIZE 10240
-#define CACHETIME 5
-
-typedef struct _pxGConfConfigModule {
- PX_MODULE_SUBCLASS(pxConfigModule);
- FILE *pipe;
- pxStrDict *data;
- time_t last;
-} pxGConfConfigModule;
+#include <cstdio> // For fileno(), fread(), pclose(), popen(), sscanf()
+#include <sys/select.h> // For select(...)
+#include <fcntl.h> // For fcntl(...)
+#include "xhasclient.cpp" // For xhasclient(...)
-static const char *_all_keys[] = {
- "/system/proxy/mode", "/system/proxy/autoconfig_url",
- "/system/http_proxy/host", "/system/http_proxy/port",
- "/system/proxy/secure_host", "/system/proxy/secure_port",
- "/system/proxy/ftp_host", "/system/proxy/ftp_port",
- "/system/proxy/socks_host", "/system/proxy/socks_port",
- "/system/http_proxy/ignore_hosts",
- "/system/http_proxy/use_authentication",
- "/system/http_proxy/authentication_user",
- "/system/http_proxy/authentication_password", NULL
-};
+/*
+int popen2(const char *program, FILE **read, FILE **write) {
+ int wpipe[2];
+
+ if (!read || !write || !program || !*program)
+ return EINVAL;
+
+ *read = NULL;
+ *write = NULL;
+
+ if (pipe(wpipe) < 0)
+ return errno;
+
+ switch (pid = vfork()) {
+ case -1: // Error
+ close(wpipe[0]);
+ close(wpipe[1]);
+ return ASOIMWE;
+ case 0: // Child
+ close(wpipe[1]);
+ dup2(wpipe[0], STDIN_FILENO);
+ close(wpipe[0]);
-static FILE *
-_start_get_config()
-{
- char buffer[BUFFERSIZE] = "";
-
- // Build our command
- if (strlen(GCONFTOOLBIN " -g") + 1 > BUFFERSIZE)
- return NULL;
- strcpy(buffer, GCONFTOOLBIN " -g");
- for (int i=0 ; _all_keys[i] ; i++)
- {
- if (strlen(buffer) + strlen(_all_keys[i]) + 2 > BUFFERSIZE)
- return NULL;
- strcat(buffer, " ");
- strcat(buffer, _all_keys[i]);
- }
- if (strlen(buffer) + strlen(" 2>&1") + 1 > BUFFERSIZE)
- return NULL;
- strcat(buffer, " 2>&1");
- // Open our pipe
- return popen(buffer, "r");
-}
-static pxStrDict *
-_finish_get_config(FILE *pipe)
-{
- char buffer[BUFFERSIZE] = "";
- char **values = NULL;
- pxStrDict *kv = NULL;
-
- if (!pipe) return NULL;
-
- // Read the output and split it into its separate values (one per line)
- if (fread(buffer, sizeof(char), BUFFERSIZE, pipe) == 0) goto error;
- if (!(values = px_strsplit(buffer, "\n"))) goto error;
-
- // Build up our dictionary with the values
- kv = px_strdict_new((pxStrDictItemCallback) px_free);
- for (int i=0 ; _all_keys[i] ; i++)
- {
- if (!values[i])
- goto error;
- if (strchr(values[i], ' '))
- strcpy(values[i], "");
- if (!px_strdict_set(kv, _all_keys[i], px_strdup(values[i])))
- goto error;
+ execl(_PATH_BSHELL, "sh", "-c", program, (char *)NULL);
+ _exit(127);
+ // NOTREACHED
+ }
}
- // Cleanup
- px_strfreev(values);
- if (pclose(pipe) < 0)
- {
- px_strdict_free(kv);
- return NULL;
+ // Parent; assume fdopen can't fail.
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ (void)close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ (void)close(pdes[0]);
}
- return kv;
- error:
- pclose(pipe);
- px_strfreev(values);
- px_strdict_free(kv);
- return NULL;
-}
+ // Link into list of file descriptors.
+ cur->fp = iop;
+ cur->pid = pid;
+ cur->next = pidlist;
+ pidlist = cur;
-static void
-_destructor(void *s)
-{
- pxGConfConfigModule *self = (pxGConfConfigModule *) s;
+ return (iop);
+}*/
- if (self->pipe) pclose(self->pipe);
- px_strdict_free(self->data);
- px_free(self);
-}
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
-static char *
-_get_config(pxConfigModule *s, pxURL *url)
-{
- pxGConfConfigModule *self = (pxGConfConfigModule *) s;
-
- // Update our config if possible
- if (self->pipe)
- {
- pxStrDict *tmp = _finish_get_config(self->pipe);
- self->pipe = NULL;
- if (tmp)
- {
- px_strdict_free(self->data);
- self->data = tmp;
- self->last = time(NULL);
+static const char *_all_keys[] = {
+ "/system/proxy/mode", "/system/proxy/autoconfig_url",
+ "/system/http_proxy/host", "/system/http_proxy/port",
+ "/system/proxy/secure_host", "/system/proxy/secure_port",
+ "/system/proxy/ftp_host", "/system/proxy/ftp_port",
+ "/system/proxy/socks_host", "/system/proxy/socks_port",
+ "/system/http_proxy/ignore_hosts",
+ "/system/http_proxy/use_authentication",
+ "/system/http_proxy/authentication_user",
+ "/system/http_proxy/authentication_password",
+ NULL
+};
+
+class gnome_config_module : public config_module {
+public:
+ PX_MODULE_ID(NULL);
+ PX_MODULE_CONFIG_CATEGORY(config_module::CATEGORY_SESSION);
+
+ gnome_config_module() {
+ int count;
+ string cmd = LIBEXECDIR "pxgconf";
+ for (count=0 ; _all_keys[count] ; count++)
+ cmd += string(" ", 1) + _all_keys[count];
+
+ this->pipe = popen(cmd.c_str(), "r");
+ if (!this->pipe)
+ throw io_error("Unable to open gconf helper!");
+ if (fcntl(fileno(this->pipe), F_SETFL, FNONBLOCK) == -1) {
+ pclose(this->pipe);
+ throw io_error("Unable to set pipe to non-blocking!");
}
+
+ this->update_data(count);
}
- if (!px_strdict_get(self->data, "/system/proxy/mode"))
- return NULL;
+ ~gnome_config_module() {
+ if (this->pipe)
+ pclose(this->pipe);
+ }
- char *curl = NULL;
+ url get_config(url dest) throw (runtime_error) {
+ // Check for changes in the config
+ if (this->pipe) this->update_data();
- // Mode is direct://
- if (!strcmp((const char *) px_strdict_get(self->data, "/system/proxy/mode"), "none"))
- curl = px_strdup("direct://");
+ // Mode is wpad:// or pac+http://...
+ if (this->data["/system/proxy/mode"] == "auto") {
+ string pac = this->data["/system/proxy/autoconfig_url"];
+ return url::is_valid(pac) ? url(string("pac+") + pac) : url("wpad://");
+ }
- // Mode is wpad:// or pac+http://...
- else if (!strcmp((const char *) px_strdict_get(self->data, "/system/proxy/mode"), "auto"))
- {
- if (px_url_is_valid((const char *) px_strdict_get(self->data, "/system/proxy/autoconfig_url")))
- curl = px_strcat("pac+", px_strdict_get(self->data, "/system/proxy/autoconfig_url"), NULL);
- else
- curl = px_strdup("wpad://");
- }
+ // Mode is http://... or socks://...
+ else if (this->data["/system/proxy/mode"] == "manual") {
+ string type = "http", host, port;
+ bool auth = this->data["/system/http_proxy/use_authentication"] == "true";
+ string username = this->data["/system/http_proxy/authentication_user"];
+ string password = this->data["/system/http_proxy/authentication_password"];
+ uint16_t p = 0;
+
+ // Get the per-scheme proxy settings
+ if (dest.get_scheme() == "https") {
+ host = this->data["/system/proxy/secure_host"];
+ port = this->data["/system/proxy/secure_port"];
+ if (sscanf(port.c_str(), "%hu", &p) != 1) p = 0;
+ }
+ else if (dest.get_scheme() == "ftp") {
+ host = this->data["/system/proxy/ftp_host"];
+ port = this->data["/system/proxy/ftp_port"];
+ if (sscanf(port.c_str(), "%hu", &p) != 1) p = 0;
+ }
+ if (host == "" || p == 0)
+ {
+ host = this->data["/system/http_proxy/host"];
+ port = this->data["/system/http_proxy/port"];
+ if (sscanf(port.c_str(), "%hu", &p) != 1) p = 0;
+ }
- // Mode is http://... or socks://...
- else if (!strcmp((const char *) px_strdict_get(self->data, "/system/proxy/mode"), "manual"))
- {
- char *type = px_strdup("http");
- char *host = NULL;
- char *port = NULL;
- char *username = NULL;
- char *password = NULL;
-
- uint16_t p = 0;
-
- // Get the per-scheme proxy settings
- if (!strcmp(px_url_get_scheme(url), "https"))
- {
- host = px_strdup((const char *) px_strdict_get(self->data, "/system/proxy/secure_host"));
- port = px_strdup((const char *) px_strdict_get(self->data, "/system/proxy/secure_port"));
- if (!port || sscanf(port, "%hu", &p) != 1) p = 0;
- }
- else if (!strcmp(px_url_get_scheme(url), "ftp"))
- {
- host = px_strdup((const char *) px_strdict_get(self->data, "/system/proxy/ftp_host"));
- port = px_strdup((const char *) px_strdict_get(self->data, "/system/proxy/ftp_port"));
- if (!port || sscanf(port, "%hu", &p) != 1) p = 0;
- }
- if (!host || !strcmp(host, "") || !p)
- {
- px_free(host);
- px_free(port);
-
- host = px_strdup((const char *) px_strdict_get(self->data, "/system/http_proxy/host"));
- port = px_strdup((const char *) px_strdict_get(self->data, "/system/http_proxy/port"));
- if (!strcmp((const char *) px_strdict_get(self->data, "/system/http_proxy/use_authentication"), "true")) {
- username = px_strdup((const char *) px_strdict_get(self->data, "/system/http_proxy/authentication_user"));
- password = px_strdup((const char *) px_strdict_get(self->data, "/system/http_proxy/authentication_password"));
+ // If http(s)/ftp proxy is not set, try socks
+ if (host == "" || p == 0)
+ {
+ host = this->data["/system/proxy/socks_host"];
+ port = this->data["/system/proxy/socks_port"];
+ if (sscanf(port.c_str(), "%hu", &p) != 1) p = 0;
}
- if (!port || sscanf(port, "%hu", &p) != 1) p = 0;
- }
- // If http(s)/ftp proxy is not set, try socks
- if (!host || !strcmp(host, "") || !p)
- {
- px_free(type);
- px_free(host);
- px_free(port);
-
- type = px_strdup("socks");
- host = px_strdup((const char *) px_strdict_get(self->data, "/system/proxy/socks_host"));
- port = px_strdup((const char *) px_strdict_get(self->data, "/system/proxy/socks_port"));
- if (!port || sscanf(port, "%hu", &p) != 1) p = 0;
+ // If host and port were found, build config url
+ if (host != "" && p != 0) {
+ string tmp = type + "://";
+ if (auth)
+ tmp += username + ":" + password + "@";
+ tmp += host + ":" + port;
+ return url(tmp);
+ }
}
- // If host and port were found, build config url
- if (host && strcmp(host, "") && p)
- curl = px_strcat(type, "://", username && password ? px_strcat(username, ":", password, "@", NULL) : "", host, ":", port, NULL);
+ // Mode is direct://
+ return url("direct://");
+ }
- px_free(type);
- px_free(host);
- px_free(port);
- px_free(username);
- px_free(password);
+ string get_ignore(url url) {
+ return this->data["/system/http_proxy/ignore_hosts"];
}
- // Start a refresh in the background
- if (time(NULL) - self->last > CACHETIME)
- self->pipe = _start_get_config();
+private:
+ FILE *pipe;
+ map<string, string> data;
- return curl;
-}
+ string readline(string buffer="") {
+ char c;
-static char *
-_get_ignore(pxConfigModule *s, pxURL *url)
-{
- pxGConfConfigModule *self = (pxGConfConfigModule *) s;
-
- char *ignores = px_strdup((const char *) px_strdict_get(self->data, "/system/http_proxy/ignore_hosts"));
- if (ignores && ignores[strlen(ignores)-1] == ']' && ignores[0] == '[')
- {
- char *tmp = px_strndup(ignores+1, strlen(ignores+1)-1);
- px_free(ignores);
- ignores = tmp;
- }
-
- return ignores ? ignores : px_strdup("");
-}
+ // If the fread() call would block, an error occurred or
+ // we are at the end of the line, we're done
+ if (fread(&c, sizeof(char), 1, this->pipe) != 1 || c == '\n')
+ return buffer;
-static bool
-_get_credentials(pxConfigModule *self, pxURL *proxy, char **username, char **password)
-{
- return false;
-}
+ // Process the next character
+ return this->readline(buffer + string(&c, 1));
+ }
-static bool
-_set_credentials(pxConfigModule *self, pxURL *proxy, const char *username, const char *password)
-{
- return false;
-}
+ // This method attempts to update data
+ // If called with no arguments, it will check for new data (sleeping for <=1000
+ // useconds) and returning true or false depending on if at least one line of
+ // data was found.
+ // However, if req > 0, we will keep checking for new lines (at 1000 usec ivals)
+ // until enough lines are found. This allows us to wait for *all* the initial
+ // values to be read in before we start processing gconf requests.
+ bool update_data(int req=0, int found=0) {
+ // If we have collected the correct number of lines, return true
+ if (req > 0 && found >= req)
+ return true;
+
+ // We need the pipe to be open
+ if (!this->pipe) return false;
+
+ fd_set rfds;
+ struct timeval timeout = { 0, 1000 };
+ FD_ZERO(&rfds);
+ FD_SET(fileno(this->pipe), &rfds);
+ if (select(fileno(this->pipe)+1, &rfds, NULL, NULL, &timeout) < 1)
+ return req > 0 ? this->update_data(req, found) : false; // If we still haven't met
+ // our req quota, try again
+
+ bool retval = false;
+ for (string line = this->readline() ; line != "" ; line = this->readline()) {
+ string key = line.substr(0, line.find("\t"));
+ string val = line.substr(line.find("\t")+1);
+ this->data[key] = val;
+ retval = ++found > req;
+ }
-static void *
-_constructor()
-{
- pxGConfConfigModule *self = (pxGConfConfigModule *) px_malloc0(sizeof(pxGConfConfigModule));
- PX_CONFIG_MODULE_BUILD(self, PX_CONFIG_MODULE_CATEGORY_SESSION, _get_config, _get_ignore, _get_credentials, _set_credentials);
- self->pipe = _start_get_config();
- return self;
-}
+ return (this->update_data(req, found) || retval);
+ }
+};
-bool
-px_module_load(pxModuleManager *self)
-{
- // If we are running in GNOME, then make sure this plugin is registered.
- if (!x_has_client("gnome-session", "gnome-settings-daemon", "gnome-panel", NULL))
- return false;
- return px_module_manager_register_module(self, pxConfigModule, _constructor, _destructor);
+// If we are running in GNOME, then make sure this plugin is registered.
+extern "C" bool px_module_load(module_manager& mm) {
+ if (xhasclient("gnome-session", "gnome-settings-daemon", "gnome-panel", NULL)) {
+ try { return mm.register_module<config_module>(new gnome_config_module); }
+ catch (io_error) { return false; }
+ }
}
diff --git a/libproxy/modules/config_kde4.cpp b/libproxy/modules/config_kde4.cpp
index afa3720..b5e8684 100644
--- a/libproxy/modules/config_kde4.cpp
+++ b/libproxy/modules/config_kde4.cpp
@@ -17,122 +17,63 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-#include <stdio.h>
+#include <kstandarddirs.h> // For KStandardDirs
+#include "xhasclient.cpp" // For xhasclient(...)
-#include "../misc.hpp"
-#include "../modules.hpp"
#include "../config_file.hpp"
-
-#include <kstandarddirs.h>
-
-typedef struct _pxKConfigConfigModule {
- PX_MODULE_SUBCLASS(pxConfigModule);
- pxConfigFile *cf;
-} pxKConfigConfigModule;
-
-static void
-_destructor(void *s)
-{
- pxKConfigConfigModule *self = (pxKConfigConfigModule *) s;
-
- px_config_file_free(self->cf);
- px_free(self);
-}
-
-static char *
-_get_config(pxConfigModule *s, pxURL *url)
-{
- pxKConfigConfigModule *self = (pxKConfigConfigModule *) s;
-
- // TODO: make ignores work w/ KDE
- char *curl = NULL, *tmp = NULL;
-
- // Open the config file
- pxConfigFile *cf = self->cf;
- if (!cf || px_config_file_is_stale(cf))
- {
- if (cf) px_config_file_free(cf);
- QString localdir = KStandardDirs().localkdedir();
- QByteArray ba = localdir.toLatin1();
- tmp = px_strcat(ba.data(), "/share/config/kioslaverc", NULL);
- cf = px_config_file_new(tmp);
- px_free(tmp);
- self->cf = cf;
- }
- if (!cf) goto out;
-
- // Read the config file to find out what type of proxy to use
- tmp = px_config_file_get_value(cf, "Proxy Settings", "ProxyType");
- if (!tmp) goto out;
-
- // Don't use any proxy
- if (!strcmp(tmp, "0"))
- curl = px_strdup("direct://");
-
- // Use a manual proxy
- else if (!strcmp(tmp, "1"))
- curl = px_config_file_get_value(cf, "Proxy Settings", "httpProxy");
-
- // Use a manual PAC
- else if (!strcmp(tmp, "2"))
- {
- px_free(tmp);
- tmp = px_config_file_get_value(cf, "Proxy Settings", "Proxy Config Script");
- if (tmp) curl = px_strcat("pac+", tmp);
- else curl = px_strdup("wpad://");
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
+
+class kde_config_module : public config_module {
+public:
+ PX_MODULE_ID(NULL);
+ PX_MODULE_CONFIG_CATEGORY(config_module::CATEGORY_SESSION);
+
+ url get_config(url url) throw (runtime_error) {
+ // Open the config file
+ if (this->cf.is_stale())
+ {
+ QString localdir = KStandardDirs().localkdedir();
+ QByteArray ba = localdir.toLatin1();
+ if (!cf.load(string(ba.data()) + "/share/config/kioslaverc"))
+ throw runtime_error("Unable to load kde config file!");
+ }
+
+ try {
+ // Read the config file to find out what type of proxy to use
+ string ptype = this->cf.get_value("Proxy Settings", "ProxyType");
+
+ // Use a manual proxy
+ if (ptype == "1")
+ return com::googlecode::libproxy::url(this->cf.get_value("Proxy Settings", "httpProxy"));
+
+ // Use a manual PAC
+ else if (ptype == "2")
+ {
+ string tmp = "";
+ try { tmp = this->cf.get_value("Proxy Settings", "Proxy Config Script"); }
+ catch (key_error&) {}
+
+ if (tmp != "") return com::googlecode::libproxy::url(string("pac+") + tmp);
+ else return com::googlecode::libproxy::url("wpad://");
+ }
+
+ // Use WPAD
+ else if (ptype == "3")
+ return com::googlecode::libproxy::url("wpad://");
+
+ // Use envvar
+ else if (ptype == "4")
+ throw runtime_error("User config_envvar"); // We'll bypass this config plugin and let the envvar plugin work
+ }
+ catch (key_error&) { }
+
+ // Don't use any proxy
+ return com::googlecode::libproxy::url("direct://");
}
- // Use WPAD
- else if (!strcmp(tmp, "3"))
- curl = px_strdup("wpad://");
-
- // Use envvar
- else if (!strcmp(tmp, "4"))
- curl = NULL; // We'll bypass this config plugin and let the envvar plugin work
-
- // Cleanup
- px_free(tmp);
-
- out:
- return curl;
-}
+private:
+ config_file cf;
+};
-static char *
-_get_ignore(pxConfigModule *self, pxURL *url)
-{
- return px_strdup("");
-}
-
-static bool
-_get_credentials(pxConfigModule *self, pxURL *proxy, char **username, char **password)
-{
- return false;
-}
-
-static bool
-_set_credentials(pxConfigModule *self, pxURL *proxy, const char *username, const char *password)
-{
- return false;
-}
-
-static void *
-_constructor()
-{
- pxKConfigConfigModule *self = (pxKConfigConfigModule *)px_malloc0(sizeof(pxKConfigConfigModule));
- PX_CONFIG_MODULE_BUILD(self, PX_CONFIG_MODULE_CATEGORY_SESSION, _get_config, _get_ignore, _get_credentials, _set_credentials);
- return self;
-}
-
-extern "C" bool
-px_module_load(pxModuleManager *self)
-{
- // If we are running in KDE, then make sure this plugin is registered.
- char *tmp = getenv("KDE_FULL_SESSION");
- if (tmp == NULL) {
- return false;
- }
- return px_module_manager_register_module(self, pxConfigModule, _constructor, _destructor);
-}
+PX_MODULE_LOAD(config_module, kde, xhasclient("kicker", NULL));
diff --git a/libproxy/modules/config_w32reg.cpp b/libproxy/modules/config_w32reg.cpp
index 95321fc..3f3ac95 100644
--- a/libproxy/modules/config_w32reg.cpp
+++ b/libproxy/modules/config_w32reg.cpp
@@ -18,19 +18,14 @@
#include <windows.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../misc.hpp"
-#include "../modules.hpp"
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
#define W32REG_OFFSET_PAC (1 << 2)
#define W32REG_OFFSET_WPAD (1 << 3)
#define W32REG_BASEKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings"
-static bool
-_get_registry(const char *key, const char *name, uchar **sval, uint32_t *slen, uint32_t *ival)
-{
+static bool _get_registry(const char *key, const char *name, uchar **sval, uint32_t *slen, uint32_t *ival) {
HKEY hkey;
LONG result;
DWORD type;
@@ -40,7 +35,7 @@ _get_registry(const char *key, const char *name, uchar **sval, uint32_t *slen, u
// Don't allow the caller to specify both sval and ival
if (sval && ival)
return false;
-
+
// Open the key
if (RegOpenKeyExA(HKEY_CURRENT_USER, key, 0, KEY_READ, &hkey) != ERROR_SUCCESS)
return false;
@@ -61,7 +56,7 @@ _get_registry(const char *key, const char *name, uchar **sval, uint32_t *slen, u
case REG_SZ:
if (!sval) return false;
if (slen) *slen = buflen;
- *sval = px_malloc(buflen);
+ *sval = new char[buflen];
return !memcpy_s(*sval, buflen, buffer, buflen);
case REG_DWORD:
if (ival) return !memcpy_s(ival, sizeof(uint32_t), buffer, buflen);
@@ -69,10 +64,7 @@ _get_registry(const char *key, const char *name, uchar **sval, uint32_t *slen, u
return false;
}
-
-static bool
-_is_enabled(uint8_t type)
-{
+static bool _is_enabled(uint8_t type) {
uchar *data = NULL;
uint32_t dlen = 0;
bool result = false;
@@ -85,127 +77,81 @@ _is_enabled(uint8_t type)
if (dlen >= 9)
result = data[8] & type == type; // Check to see if the bit is set
- px_free(data);
+ delete data;
return result;
}
-static char *
-_get_pac()
-{
- char *pac = NULL;
- char *url = NULL;
-
- if (!_is_enabled(W32REG_OFFSET_PAC)) return NULL;
- if (!_get_registry(W32REG_BASEKEY, "AutoConfigURL", &pac, NULL, NULL)) return NULL;
-
- url = px_strcat("pac+", pac, NULL);
- px_free(pac);
- return url;
-}
-
-static char *
-_get_manual(pxURL *url)
-{
- char *val = NULL;
- char *url = NULL;
- char **vals = NULL;
- uint32_t enabled = 0;
-
- // Check to see if we are enabled
- if (!_get_registry(W32REG_BASEKEY, "ProxyEnable", NULL, NULL, &enabled) || !enabled) return NULL;
-
- // Get the value of ProxyServer
- if (!_get_registry(W32REG_BASEKEY, "ProxyServer", &val, NULL, NULL)) return NULL;
-
+static map<string, string> _parse_manual(string data) {
// ProxyServer comes in two formats:
// 1.2.3.4:8080 or ftp=1.2.3.4:8080;https=1.2.3.4:8080...
- // If we have the first format, just prepend "http://" and we're done
- if (!strchr(val, ';'))
- {
- url = px_strcat("http://", val, NULL);
- px_free(val);
- return url;
- }
-
- // Ok, now we have the more difficult format...
- // ... so split up all the various proxies
- vals = px_strsplit(val, ";");
- px_free(val);
+ map<string, url> rval;
- // First we look for an exact match
- for (int i=0 ; !url && vals[i] ; i++)
- {
- char *tmp = px_strcat(px_url_get_scheme(url), "=", NULL);
-
- // If we've found an exact match, use it
- if (!strncmp(tmp, vals[i], strlen(tmp)))
- url = px_strcat(px_url_get_scheme(url), "://", vals[i]+strlen(tmp), NULL);
-
- px_free(tmp);
+ // If we have the second format, do recursive parsing,
+ // then handle just the first entry
+ if (data.find(";") != string::npos) {
+ rval = _parse_manual(data.substr(data.find(";")+1));
+ data = data.substr(0, data.find(";"));
}
- // Second we look for http=
- for (int i=0 ; !url && vals[i] ; i++)
- if (!strncmp("http=", vals[i], strlen("http=")))
- url = px_strcat("http://", vals[i]+strlen("http="), NULL);
-
- // Last we look for socks=
- for (int i=0 ; !url && vals[i] ; i++)
- if (!strncmp("socks=", vals[i], strlen("socks=")))
- url = px_strcat("socks://", vals[i]+strlen("socks="), NULL);
-
- return url;
-}
-
-static char *
-_get_config(pxConfigModule *self, pxURL *url)
-{
- char *config = NULL;
-
- // WPAD
- if (_is_enabled(W32REG_OFFSET_WPAD))
- return px_strdup("wpad://");
-
- // PAC
- if ((config = _get_pac()))
- return config;
-
- // Manual proxy
- if ((config = _get_manual(url)))
- return config;
-
- // Direct
- return px_strdup("direct://");
-}
-
-static char *
-_get_ignore(pxConfigModule *self, pxURL *url)
-{
- return px_strdup("");
-}
+ // If we have the first format, just assign HTTP and we're done
+ if (data.find("=") == string::npos) {
+ rval["http"] = data;
+ return rval;
+ }
-static bool
-_get_credentials(pxConfigModule *self, pxURL *url, char **username, char **password)
-{
- return false;
-}
+ // Otherwise set the value for this single entry and return
+ string protocol = data.substr(0, data.find("="));
+ try { rval[protocol] = url(protocol + "://" + data.substr(data.find("=")+1)); }
+ catch (parse_error&) {}
-static bool
-_set_credentials(pxConfigModule *self, pxURL *url, const char *username, const char *password)
-{
- return false;
+ return rval;
}
-static void *
-_constructor()
-{
- pxConfigModule *self = px_malloc0(sizeof(pxConfigModule));
- PX_CONFIG_MODULE_BUILD(self, PX_CONFIG_MODULE_CATEGORY_USER, _get_config, _get_ignore, _get_credentials, _set_credentials);
- return self;
+class w32reg_config_module : public config_module {
+public:
+ PX_MODULE_ID(NULL);
+ PX_MODULE_CONFIG_CATEGORY(config_module::CATEGORY_SYSTEM);
+
+ url get_config(url dst) throw (runtime_error) {
+ char *tmp = NULL;
+ uint32_t enabled = 0;
+
+ // WPAD
+ if (_is_enabled(W32REG_OFFSET_WPAD))
+ return url("wpad://");
+
+ // PAC
+ if (_is_enabled(W32REG_OFFSET_PAC) &&
+ _get_registry(W32REG_BASEKEY, "AutoConfigURL", &tmp, NULL, NULL) &&
+ url::is_valid(string("pac+") + tmp)) {
+ url cfg(string("pac+") + tmp);
+ delete tmp;
+ return cfg;
+ }
+
+ // Manual proxy
+ // Check to see if we are enabled and get the value of ProxyServer
+ if (_get_registry(W32REG_BASEKEY, "ProxyEnable", NULL, NULL, &enabled) && enabled &&
+ _get_registry(W32REG_BASEKEY, "ProxyServer", &tmp, NULL, NULL)) {
+ map<string, string> manual = _parse_manual(tmp);
+ delete tmp;
+
+ // First we look for an exact match
+ if (manual.find(dst.get_scheme()) != map<string, url>::end)
+ return manual[dst.get_scheme()];
+
+ // Next we look for http
+ else if (manual.find("http") != map<string, url>::end)
+ return manual["http"];
+
+ // Last we look for socks
+ else if (manual.find("socks") != map<string, url>::end)
+ return manual["socks"];
+ }
+
+ // Direct
+ return url("direct://");
+ }
}
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxConfigModule, _constructor, px_free);
-}
+PX_MODULE_LOAD(config_module, w32reg, true);
diff --git a/libproxy/modules/config_wpad.cpp b/libproxy/modules/config_wpad.cpp
index d194e4b..ef440a4 100644
--- a/libproxy/modules/config_wpad.cpp
+++ b/libproxy/modules/config_wpad.cpp
@@ -17,46 +17,17 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <string.h>
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
-#include "../misc.hpp"
-#include "../modules.hpp"
+class wpad_config_module : public config_module {
+public:
+ PX_MODULE_ID(NULL);
+ PX_MODULE_CONFIG_CATEGORY(config_module::CATEGORY_NONE);
-static char *
-_get_config(pxConfigModule *self, pxURL *url)
-{
- return px_strdup("wpad://");
-}
+ url get_config(url dst) throw (runtime_error) {
+ return url("wpad://");
+ }
+};
-static char *
-_get_ignore(pxConfigModule *self, pxURL *url)
-{
- return px_strdup("");
-}
-
-static bool
-_get_credentials(pxConfigModule *self, pxURL *url, char **username, char **password)
-{
- return false;
-}
-
-static bool
-_set_credentials(pxConfigModule *self, pxURL *url, const char *username, const char *password)
-{
- return false;
-}
-
-static void *
-_constructor()
-{
- pxConfigModule *self = (pxConfigModule *) px_malloc0(sizeof(pxConfigModule));
- PX_CONFIG_MODULE_BUILD(self, PX_CONFIG_MODULE_CATEGORY_NONE, _get_config, _get_ignore, _get_credentials, _set_credentials);
- return self;
-}
-
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxConfigModule, _constructor, px_free);
-}
+PX_MODULE_LOAD(config_module, wpad, true);
diff --git a/libproxy/modules/ignore_domain.cpp b/libproxy/modules/ignore_domain.cpp
index ceca7d5..b9bd990 100644
--- a/libproxy/modules/ignore_domain.cpp
+++ b/libproxy/modules/ignore_domain.cpp
@@ -17,81 +17,46 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
+#include <cstdio>
-#include "../misc.hpp"
-#include "../modules.hpp"
+#include "../module_types.hpp"
-static inline bool
-_endswith(char *string, char *suffix)
-{
- int st_len = strlen(string);
- int su_len = strlen(suffix);
+using namespace com::googlecode::libproxy;
- return (st_len >= su_len && !strcmp(string + (st_len-su_len), suffix));
-}
+class domain_ignore_module : public ignore_module {
+public:
+ PX_MODULE_ID(NULL);
-static bool
-_ignore(pxIgnoreModule *self, pxURL *url, const char *ignore)
-{
- if (!url || !ignore)
- return false;
+ virtual bool ignore(url& url, string ignorestr) {
+ /* Get our URL's hostname and port */
+ string host = url.get_host();
+ int port = url.get_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 */
+ string ihost = ignorestr;
+ int iport = 0;
+ if (ihost.find(':') != string::npos) {
+ if (sscanf(ignorestr.substr(ihost.find(':')+1).c_str(), "%d", &iport) == 1)
+ ihost = ihost.substr(0, ihost.find(':'));
+ else
+ iport = 0;
+ }
- /* Get our ignore pattern's hostname and port */
- char *ihost = px_strdup(ignore);
- int iport = 0;
- if (strchr(ihost, ':'))
- {
- char *tmp = strchr(ihost, ':');
- if (sscanf(tmp+1, "%d", &iport) == 1)
- *tmp = '\0';
- else
- iport = 0;
- }
-
- /* 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) */
- if (ihost[0] == '.' && _endswith(host, ihost))
- if (!iport || port == iport)
- goto match;
+ /* Hostname match (domain.com or domain.com:80) */
+ if (host == ihost)
+ return (iport == 0 || port == iport);
- /* Glob (*.domain.com or *.domain.com:80) */
- if (ihost[0] == '*' && _endswith(host, ihost+1))
- if (!iport || port == iport)
- goto match;
+ /* Endswith (.domain.com or .domain.com:80) */
+ if (ihost[0] == '.' && host.find(ihost) == host.size() - ihost.size())
+ return (iport == 0 || port == iport);
- /* No match was found */
- px_free(host);
- px_free(ihost);
- return false;
+ /* Glob (*.domain.com or *.domain.com:80) */
+ if (ihost[0] == '*' && host.find(ihost.substr(1)) == host.size() - ihost.substr(1).size())
+ return (iport == 0 || port == iport);
- /* A match was found */
- match:
- px_free(host);
- px_free(ihost);
- return true;
-}
-
-static void *
-_constructor()
-{
- pxIgnoreModule *self = (pxIgnoreModule *) px_malloc0(sizeof(pxIgnoreModule));
- self->ignore = _ignore;
- return self;
-}
+ /* No match was found */
+ return false;
+ }
+};
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxIgnoreModule, _constructor, px_free);
-}
+PX_MODULE_LOAD(ignore_module, domain, true);
diff --git a/libproxy/modules/ignore_ip.cpp b/libproxy/modules/ignore_ip.cpp
index 2ea20ae..81be231 100644
--- a/libproxy/modules/ignore_ip.cpp
+++ b/libproxy/modules/ignore_ip.cpp
@@ -17,10 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdint.h>
+#include <cstdio>
+#include <cstring>
#ifdef _WIN32
#define _WIN32_WINNT 0x0501
@@ -35,183 +33,161 @@ typedef unsigned short int sa_family_t;
#include <netinet/in.h>
#endif
-#include "../misc.hpp"
-#include "../modules.hpp"
+#include "../module_types.hpp"
-static bool
+using namespace com::googlecode::libproxy;
+
+static inline bool
_sockaddr_equals(const struct sockaddr *ip_a, const struct sockaddr *ip_b, const struct sockaddr *nm)
{
- if (!ip_a || !ip_b) return false;
- 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 */
- uint8_t bytes = 0, *a_data = NULL, *b_data = NULL, *nm_data = NULL;
- if (ip_a->sa_family == AF_INET)
- {
- bytes = 32 / 8;
- a_data = (uint8_t *) &((struct sockaddr_in *) ip_a)->sin_addr;
- b_data = (uint8_t *) &((struct sockaddr_in *) ip_b)->sin_addr;
- nm_data = nm ? (uint8_t *) &((struct sockaddr_in *) nm)->sin_addr : NULL;
- }
- else if (ip_a->sa_family == AF_INET6)
- {
- bytes = 128 / 8;
- a_data = (uint8_t *) &((struct sockaddr_in6 *) ip_a)->sin6_addr;
- b_data = (uint8_t *) &((struct sockaddr_in6 *) ip_b)->sin6_addr;
- nm_data = nm ? (uint8_t *) &((struct sockaddr_in6 *) nm)->sin6_addr : NULL;
- }
- else
- return false;
-
- for (int i=0 ; i < bytes ; i++)
- {
- if (nm && (a_data[i] & nm_data[i]) != (b_data[i] & nm_data[i]))
- return false;
- else if (!nm && (a_data[i] != b_data[i]))
- return false;
- }
- return true;
+ if (!ip_a || !ip_b) return false;
+ 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 */
+ uint8_t bytes = 0, *a_data = NULL, *b_data = NULL, *nm_data = NULL;
+ if (ip_a->sa_family == AF_INET)
+ {
+ bytes = 32 / 8;
+ a_data = (uint8_t *) &((struct sockaddr_in *) ip_a)->sin_addr;
+ b_data = (uint8_t *) &((struct sockaddr_in *) ip_b)->sin_addr;
+ nm_data = nm ? (uint8_t *) &((struct sockaddr_in *) nm)->sin_addr : NULL;
+ }
+ else if (ip_a->sa_family == AF_INET6)
+ {
+ bytes = 128 / 8;
+ a_data = (uint8_t *) &((struct sockaddr_in6 *) ip_a)->sin6_addr;
+ b_data = (uint8_t *) &((struct sockaddr_in6 *) ip_b)->sin6_addr;
+ nm_data = nm ? (uint8_t *) &((struct sockaddr_in6 *) nm)->sin6_addr : NULL;
+ }
+ else
+ return false;
+
+ for (int i=0 ; i < bytes ; i++)
+ {
+ if (nm && (a_data[i] & nm_data[i]) != (b_data[i] & nm_data[i]))
+ return false;
+ else if (!nm && (a_data[i] != b_data[i]))
+ return false;
+ }
+ return true;
}
-static struct sockaddr *
-_sockaddr_from_string(const char *ip, int len)
+static inline sockaddr *
+_sockaddr_from_string(string ip)
{
- if (!ip) return NULL;
- struct sockaddr *result = NULL;
-
- /* Copy the string */
- if (len >= 0)
- ip = px_strndup(ip, len);
- else
- ip = px_strdup(ip);
-
- /* Try to parse */
- struct addrinfo *info = NULL;
- struct addrinfo flags;
- flags.ai_family = AF_UNSPEC;
- flags.ai_socktype = 0;
- flags.ai_protocol = 0;
- flags.ai_flags = AI_NUMERICHOST;
- if (getaddrinfo(ip, NULL, &flags, &info) != 0 || !info) goto out;
-
- /* Copy the results into our buffer */
- result = (struct sockaddr *) px_malloc0(info->ai_addrlen);
- memcpy(result, info->ai_addr, info->ai_addrlen);
-
- out:
- px_free((char *) ip);
- return result;
+ struct sockaddr *result = NULL;
+
+ /* Try to parse */
+ struct addrinfo *info = NULL;
+ struct addrinfo flags;
+ flags.ai_family = AF_UNSPEC;
+ flags.ai_socktype = 0;
+ flags.ai_protocol = 0;
+ flags.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(ip.c_str(), NULL, &flags, &info) != 0 || !info) return result;
+
+ /* Copy the results into our buffer */
+ if (!(result = (sockaddr *) new char[info->ai_addrlen])) return result;
+ memcpy(result, info->ai_addr, info->ai_addrlen);
+ return result;
}
-static struct sockaddr *
+static inline sockaddr *
_sockaddr_from_cidr(sa_family_t af, uint8_t cidr)
{
- /* IPv4 */
- if (af == AF_INET)
- {
- struct sockaddr_in *mask = (sockaddr_in *) px_malloc0(sizeof(struct sockaddr_in));
- mask->sin_family = af;
- mask->sin_addr.s_addr = htonl(~0 << (32 - (cidr > 32 ? 32 : cidr)));
-
- return (struct sockaddr *) mask;
- }
-
- /* IPv6 */
- else if (af == AF_INET6)
- {
- struct sockaddr_in6 *mask = (sockaddr_in6 *) px_malloc0(sizeof(struct sockaddr_in6));
- mask->sin6_family = af;
- for (uint8_t i=0 ; i < sizeof(mask->sin6_addr) ; i++)
- mask->sin6_addr.s6_addr[i] = ~0 << (8 - (8*i > cidr ? 0 : cidr-8*i < 8 ? cidr-8*i : 8) );
-
- return (struct sockaddr *) mask;
- }
-
- return NULL;
+ /* IPv4 */
+ if (af == AF_INET)
+ {
+ sockaddr_in *mask = new sockaddr_in;
+ mask->sin_family = af;
+ mask->sin_addr.s_addr = htonl(~0 << (32 - (cidr > 32 ? 32 : cidr)));
+
+ return (struct sockaddr *) mask;
+ }
+
+ /* IPv6 */
+ else if (af == AF_INET6)
+ {
+ sockaddr_in6 *mask = new sockaddr_in6;
+ mask->sin6_family = af;
+ for (uint8_t i=0 ; i < sizeof(mask->sin6_addr) ; i++)
+ mask->sin6_addr.s6_addr[i] = ~0 << (8 - (8*i > cidr ? 0 : cidr-8*i < 8 ? cidr-8*i : 8) );
+
+ return (sockaddr *) mask;
+ }
+
+ return NULL;
}
-static bool
-_ignore(struct _pxIgnoreModule *self, pxURL *url, const char *ignore)
-{
- if (!url || !ignore) return false;
-
-
- bool result = false;
- uint32_t port = 0;
- const struct sockaddr **dst_ips = px_url_get_ips(url, false);
- const struct sockaddr *dst_ip = dst_ips && dst_ips[0] ? dst_ips[0] : NULL;
- struct sockaddr *ign_ip = NULL, *net_ip = NULL;
-
- /*
- * IPv4
- * IPv6
- */
- if ((ign_ip = _sockaddr_from_string(ignore, -1)))
- goto out;
-
- /*
- * 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 (ign_ip && !net_ip)
- {
- uint32_t cidr = 0;
- if (sscanf(strchr(ignore, '/') + 1, "%d", &cidr) == 1)
- net_ip = _sockaddr_from_cidr(ign_ip->sa_family, cidr);
- }
-
- if (ign_ip && net_ip && ign_ip->sa_family == net_ip->sa_family)
- goto out;
-
- px_free(ign_ip);
- px_free(net_ip);
- ign_ip = NULL;
- net_ip = NULL;
- }
-
- /*
- * 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 */
- if (ign_ip && (ign_ip->sa_family != AF_INET6 || ignore[0] == '['))
- goto out;
-
- px_free(ign_ip);
- ign_ip = NULL;
- port = 0;
- }
-
- out:
- result = _sockaddr_equals(dst_ip, ign_ip, net_ip);
- px_free(ign_ip);
- px_free(net_ip);
- return port != 0 ? (port == px_url_get_port(url) && result): result;
-}
-
-static void *
-_constructor()
-{
- pxIgnoreModule *self = (pxIgnoreModule*) px_malloc0(sizeof(pxIgnoreModule));
- self->ignore = _ignore;
- return self;
-}
-
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxIgnoreModule, _constructor, px_free);
-}
+class ip_ignore_module : public ignore_module {
+public:
+ PX_MODULE_ID(NULL);
+
+ virtual bool ignore(url& url, string ignore) {
+ bool result = false;
+ uint32_t port = 0;
+ const struct sockaddr *dst_ip = url.get_ips(false)->size() > 0 ? (*url.get_ips(false))[0] : NULL;
+ struct sockaddr *ign_ip = NULL, *net_ip = NULL;
+
+ /*
+ * IPv4
+ * IPv6
+ */
+ if ((ign_ip = _sockaddr_from_string(ignore)))
+ goto out;
+
+ /*
+ * IPv4/CIDR
+ * IPv4/IPv4
+ * IPv6/CIDR
+ * IPv6/IPv6
+ */
+ if (ignore.find('/') != string::npos)
+ {
+ ign_ip = _sockaddr_from_string(ignore.substr(0, ignore.find('/')));
+ net_ip = _sockaddr_from_string(ignore.substr(ignore.find('/') + 1));
+
+ /* If CIDR notation was used, get the netmask */
+ if (ign_ip && !net_ip)
+ {
+ uint32_t cidr = 0;
+ if (sscanf(ignore.substr(ignore.find('/') + 1).c_str(), "%d", &cidr) == 1)
+ net_ip = _sockaddr_from_cidr(ign_ip->sa_family, cidr);
+ }
+
+ if (ign_ip && net_ip && ign_ip->sa_family == net_ip->sa_family)
+ goto out;
+
+ delete ign_ip;
+ delete net_ip;
+ ign_ip = NULL;
+ net_ip = NULL;
+ }
+
+ /*
+ * IPv4:port
+ * [IPv6]:port
+ */
+ if (ignore.rfind(':') != string::npos && sscanf(ignore.substr(ignore.rfind(':')).c_str(), ":%u", &port) == 1 && port > 0)
+ {
+ ign_ip = _sockaddr_from_string(ignore.substr(ignore.rfind(':')).c_str());
+
+ /* 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;
+
+ delete ign_ip;
+ ign_ip = NULL;
+ port = 0;
+ }
+
+ out:
+ result = _sockaddr_equals(dst_ip, ign_ip, net_ip);
+ free(ign_ip);
+ free(net_ip);
+ return port != 0 ? (port == url.get_port() && result) : result;
+ }
+};
+
+PX_MODULE_LOAD(ignore_module, ip, true);
diff --git a/libproxy/modules/network_networkmanager.cpp b/libproxy/modules/network_networkmanager.cpp
index 40b98df..e37a4c7 100644
--- a/libproxy/modules/network_networkmanager.cpp
+++ b/libproxy/modules/network_networkmanager.cpp
@@ -17,94 +17,77 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-
-#include "../misc.hpp"
-#include "../modules.hpp"
+#include "../module_types.hpp"
#include <dbus/dbus.h>
#include <NetworkManager/NetworkManager.h>
-typedef struct _pxNetworkManagerNetworkModule {
- PX_MODULE_SUBCLASS(pxNetworkModule);
- DBusConnection *conn;
-} pxNetworkManagerNetworkModule;
-
-static void
-_destructor(void *s)
-{
- pxNetworkManagerNetworkModule *self = (pxNetworkManagerNetworkModule *) s;
-
- dbus_connection_close(self->conn);
- px_free(self);
-}
-
-static bool
-_changed(pxNetworkModule *s)
-{
- pxNetworkManagerNetworkModule *self = (pxNetworkManagerNetworkModule *) s;
-
- // Make sure we have a valid connection with a proper match
- DBusConnection *conn = self->conn;
- if (!conn || !dbus_connection_get_is_connected(conn))
- {
- // If the connection was disconnected,
- // close it an clear the queue
- if (conn)
+using namespace com::googlecode::libproxy;
+
+class networkmanager_network_module : public network_module {
+public:
+ PX_MODULE_ID(NULL);
+
+ networkmanager_network_module() {
+ this->conn = NULL;
+ }
+
+ ~networkmanager_network_module() {
+ if (this->conn) dbus_connection_close(this->conn);
+ }
+
+ bool changed() {
+ // Make sure we have a valid connection with a proper match
+ DBusConnection *conn = this->conn;
+ if (!conn || !dbus_connection_get_is_connected(conn))
{
- dbus_connection_close(conn);
- dbus_connection_read_write(conn, 0);
- for (DBusMessage *msg=NULL ; (msg = dbus_connection_pop_message(conn)) ; dbus_message_unref(msg));
+ // If the connection was disconnected,
+ // close it an clear the queue
+ if (conn)
+ {
+ dbus_connection_close(conn);
+ dbus_connection_read_write(conn, 0);
+ for (DBusMessage *msg=NULL ; (msg = dbus_connection_pop_message(conn)) ; dbus_message_unref(msg));
+ }
+
+ // Create a new connections
+ conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
+ this->conn = conn;
+ if (!conn) return false;
+
+ // If connection was successful, set it up
+ dbus_connection_set_exit_on_disconnect(conn, false);
+ dbus_bus_add_match(conn, "type='signal',interface='" NM_DBUS_INTERFACE "',member='StateChange'", NULL);
+ dbus_connection_flush(conn);
}
- // Create a new connections
- conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
- self->conn = conn;
- if (!conn) return false;
+ // We are guaranteed a connection,
+ // so check for incoming messages
+ bool changed = false;
+ while (true)
+ {
+ DBusMessage *msg = NULL;
+ uint32_t state;
- // If connection was successful, set it up
- dbus_connection_set_exit_on_disconnect(conn, false);
- dbus_bus_add_match(conn, "type='signal',interface='" NM_DBUS_INTERFACE "',member='StateChange'", NULL);
- dbus_connection_flush(conn);
- }
+ // Pull messages off the queue
+ dbus_connection_read_write(conn, 0);
+ if (!(msg = dbus_connection_pop_message(conn)))
+ break;
+
+ // If a message is the right type and value,
+ // we'll reset the network
+ if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID))
+ if (state == NM_STATE_CONNECTED)
+ changed = true;
- // We are guaranteed a connection,
- // so check for incoming messages
- bool changed = false;
- while (true)
- {
- DBusMessage *msg = NULL;
- uint32_t state;
-
- // Pull messages off the queue
- dbus_connection_read_write(conn, 0);
- if (!(msg = dbus_connection_pop_message(conn)))
- break;
-
- // If a message is the right type and value,
- // we'll reset the network
- if (dbus_message_get_args(msg, NULL, DBUS_TYPE_UINT32, &state, DBUS_TYPE_INVALID))
- if (state == NM_STATE_CONNECTED)
- changed = true;
-
- dbus_message_unref(msg);
+ dbus_message_unref(msg);
+ }
+
+ return changed;
}
- return changed;
-}
-
-static void *
-_constructor()
-{
- pxNetworkManagerNetworkModule *self = (pxNetworkManagerNetworkModule*) px_malloc0(sizeof(pxNetworkManagerNetworkModule));
- self->__parent__.changed = _changed;
- return self;
-}
-
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxNetworkModule, _constructor, _destructor);
-}
+private:
+ DBusConnection *conn;
+};
+
+PX_MODULE_LOAD(network_module, networkmanager, true);
diff --git a/libproxy/modules/pacrunner_mozjs.cpp b/libproxy/modules/pacrunner_mozjs.cpp
index d24dea1..74cbeaa 100644
--- a/libproxy/modules/pacrunner_mozjs.cpp
+++ b/libproxy/modules/pacrunner_mozjs.cpp
@@ -17,18 +17,10 @@
* 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>
-#include <netinet/in.h>
-#define __USE_BSD
-#include <unistd.h>
-
-#include "../misc.hpp"
-#include "../modules.hpp"
+#include <cstring> // ?
+
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
#include <jsapi.h>
#include "pacutils.h"
@@ -41,21 +33,9 @@
#define INET6_ADDRSTRLEN 46
#endif
-typedef struct {
- JSRuntime *run;
- JSContext *ctx;
- JSClass *cls;
- char *pac;
-} ctxStore;
-
-typedef struct _pxMozillaPACRunnerModule {
- PX_MODULE_SUBCLASS(pxPACRunnerModule);
- ctxStore *ctxs;
-} pxMozillaPACRunnerModule;
-
static JSBool dnsResolve(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) {
// Get hostname argument
- char *tmp = px_strdup(JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
+ char *tmp = JS_strdup(cx, JS_GetStringBytes(JS_ValueToString(cx, argv[0])));
// Set the default return value
*rval = JSVAL_NULL;
@@ -66,8 +46,9 @@ static JSBool dnsResolve(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
goto out;
// Allocate the IP address
- px_free(tmp);
- tmp = (char *) px_malloc0(INET6_ADDRSTRLEN+1);
+ JS_free(cx, tmp);
+ tmp = (char *) JS_malloc(cx, INET6_ADDRSTRLEN+1);
+ memset(tmp, 0, INET6_ADDRSTRLEN+1);
// Try for IPv4 and IPv6
if (!inet_ntop(info->ai_family,
@@ -84,7 +65,7 @@ static JSBool dnsResolve(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
out:
if (info) freeaddrinfo(info);
- px_free(tmp);
+ JS_free(cx, tmp);
return true;
}
@@ -95,136 +76,87 @@ static JSBool myIpAddress(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval arg = STRING_TO_JSVAL(myhost);
return dnsResolve(cx, obj, 1, &arg, rval);
}
- px_free(hostname);
+ JS_free(cx, hostname);
*rval = JSVAL_NULL;
return true;
}
-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 = (ctxStore*) px_malloc0(sizeof(ctxStore));
-
- // Setup Javascript global class
- self->cls = (JSClass*) 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;
-}
-
-static void
-_destructor(void *s)
-{
- pxMozillaPACRunnerModule * self = (pxMozillaPACRunnerModule *) s;
-
- ctxs_free(self->ctxs);
- px_free(self);
-}
-
-static char *
-_run(pxPACRunnerModule *self, pxPAC *pac, pxURL *url)
-{
- // 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 = ((pxMozillaPACRunnerModule *) self)->ctxs;
-
- // 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;
- ((pxMozillaPACRunnerModule *) self)->ctxs = NULL;
+class mozjs_pacrunner : public pacrunner {
+public:
+ mozjs_pacrunner(const pac pac) throw (bad_alloc) {
+ jsval rval;
+
+ // Set defaults
+ this->jsrun = NULL;
+ this->jsctx = NULL;
+
+ // Setup Javascript global class
+ JSClass cls = {
+ "global", JSCLASS_GLOBAL_FLAGS,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_PropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
+ };
+
+ // Initialize Javascript runtime environment
+ if (!(this->jsrun = JS_NewRuntime(1024 * 1024))) goto error;
+ if (!(this->jsctx = JS_NewContext(this->jsrun, 1024 * 1024))) goto error;
+ //JS_SetOptions(this->jsctx, JSOPTION_VAROBJFIX);
+ //JS_SetVersion(this->jsctx, JSVERSION_LATEST);
+ //JS_SetErrorReporter(cx, reportError);
+ if (!(this->jsglb = JS_NewObject(this->jsctx, &cls, NULL, NULL))) goto error;
+ if (!JS_InitStandardClasses(this->jsctx, this->jsglb)) goto error;
+
+ // Define Javascript functions
+ JS_DefineFunction(this->jsctx, this->jsglb, "dnsResolve", dnsResolve, 1, 0);
+ JS_DefineFunction(this->jsctx, this->jsglb, "myIpAddress", myIpAddress, 0, 0);
+ JS_EvaluateScript(this->jsctx, this->jsglb, JAVASCRIPT_ROUTINES,
+ strlen(JAVASCRIPT_ROUTINES), "pacutils.js", 0, &rval);
+
+ // Add PAC to the environment
+ JS_EvaluateScript(this->jsctx, this->jsglb, pac.to_string().c_str(),
+ strlen(pac.to_string().c_str()),
+ pac.get_url().to_string().c_str(), 0, &rval);
+ return;
+
+ error:
+ if (this->jsctx) JS_DestroyContext(this->jsctx);
+ if (this->jsrun) JS_DestroyRuntime(this->jsrun);
+ throw bad_alloc();
}
- // If no context exists (or if the pac was changed), create one
- if (!ctxs)
- {
- if ((ctxs = ctxs_new(pac)))
- ((pxMozillaPACRunnerModule *) self)->ctxs = ctxs;
- else
- return NULL;
+ ~mozjs_pacrunner() {
+ if (this->jsctx) JS_DestroyContext(this->jsctx);
+ if (this->jsrun) JS_DestroyRuntime(this->jsrun);
+ // JS_ShutDown()?
}
- // 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 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())
- 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);
- return NULL;
+ string run(const url url) throw (bad_alloc) {
+ // Build arguments to the FindProxyForURL() function
+ char *tmpurl = JS_strdup(this->jsctx, url.to_string().c_str());
+ char *tmphost = JS_strdup(this->jsctx, url.get_host().c_str());
+ if (!tmpurl || !tmphost) {
+ if (tmpurl) JS_free(this->jsctx, tmpurl);
+ if (tmphost) JS_free(this->jsctx, tmphost);
+ throw bad_alloc();
+ }
+ jsval args[2] = {
+ STRING_TO_JSVAL(JS_NewString(this->jsctx, tmpurl, strlen(tmpurl))),
+ STRING_TO_JSVAL(JS_NewString(this->jsctx, tmphost, strlen(tmphost)))
+ };
+
+ // Find the proxy (call FindProxyForURL())
+ jsval rval;
+ JSBool result = JS_CallFunctionName(this->jsctx, this->jsglb, "FindProxyForURL", 2, args, &rval);
+ if (!result) return "";
+ string answer = string(JS_GetStringBytes(JS_ValueToString(this->jsctx, rval)));
+ if (answer == "undefined") return "";
+ return answer;
}
- return answer;
-}
-static void *
-_constructor()
-{
- pxMozillaPACRunnerModule *self = (pxMozillaPACRunnerModule*) px_malloc0(sizeof(pxMozillaPACRunnerModule));
- self->__parent__.run = _run;
- return self;
-}
+private:
+ JSRuntime *jsrun;
+ JSContext *jsctx;
+ JSObject *jsglb;
+};
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxPACRunnerModule, _constructor, _destructor);
-}
+PX_DEFINE_PACRUNNER_MODULE(mozjs, true);
diff --git a/libproxy/modules/pacrunner_webkit.cpp b/libproxy/modules/pacrunner_webkit.cpp
index eb7d661..592bbae 100644
--- a/libproxy/modules/pacrunner_webkit.cpp
+++ b/libproxy/modules/pacrunner_webkit.cpp
@@ -17,25 +17,8 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-#ifdef _WIN32
-#define _WIN32_WINNT 0x0501
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <../platform/win32/inet.h>
-#else
-#include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#endif
-#define __USE_BSD
-#include <unistd.h>
-
-#include "../misc.hpp"
-#include "../modules.hpp"
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
#include <JavaScriptCore/JavaScript.h>
#include "pacutils.h"
@@ -48,19 +31,9 @@
#define INET6_ADDRSTRLEN 46
#endif
-typedef struct {
- JSGlobalContextRef ctx;
- char *pac;
-} ctxStore;
-
-typedef struct _pxWebKitPACRunnerModule {
- PX_MODULE_SUBCLASS(pxPACRunnerModule);
- ctxStore *ctxs;
-} pxWebKitPACRunnerModule;
-
-static char *jstr2str(JSStringRef str, bool release)
+static char *jstr2str(JSStringRef str, bool release) throw (bad_alloc)
{
- char *tmp = (char*) px_malloc0(JSStringGetMaximumUTF8CStringSize(str)+1);
+ char *tmp = new char[JSStringGetMaximumUTF8CStringSize(str)+1];
JSStringGetUTF8CString(str, tmp, JSStringGetMaximumUTF8CStringSize(str)+1);
if (release) JSStringRelease(str);
return tmp;
@@ -78,10 +51,10 @@ static JSValueRef dnsResolve(JSContextRef ctx, JSObjectRef func, JSObjectRef sel
struct addrinfo *info;
if (getaddrinfo(tmp, NULL, NULL, &info))
return NULL;
- px_free(tmp);
+ delete tmp;
// Try for IPv4
- tmp = (char*) px_malloc0(INET6_ADDRSTRLEN+1);
+ tmp = new char[INET6_ADDRSTRLEN+1];
if (!inet_ntop(info->ai_family,
&((struct sockaddr_in *) info->ai_addr)->sin_addr,
tmp, INET_ADDRSTRLEN+1) > 0)
@@ -91,7 +64,7 @@ static JSValueRef dnsResolve(JSContextRef ctx, JSObjectRef func, JSObjectRef sel
tmp, INET6_ADDRSTRLEN+1) > 0)
{
freeaddrinfo(info);
- px_free(tmp);
+ delete tmp;
return NULL;
}
freeaddrinfo(info);
@@ -100,7 +73,7 @@ static JSValueRef dnsResolve(JSContextRef ctx, JSObjectRef func, JSObjectRef sel
JSStringRef str = JSStringCreateWithUTF8CString(tmp);
JSValueRef ret = JSValueMakeString(ctx, str);
JSStringRelease(str);
- px_free(tmp);
+ delete tmp;
return ret;
}
@@ -118,125 +91,77 @@ static JSValueRef myIpAddress(JSContextRef ctx, JSObjectRef func, JSObjectRef se
return NULL;
}
-static void ctxs_free(ctxStore *self)
-{
- if (!self) return;
- JSGarbageCollect(self->ctx);
- JSGlobalContextRelease(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 = (ctxStore*) 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);
+class webkit_pacrunner : public pacrunner {
+public:
+ ~webkit_pacrunner() {
+ JSGarbageCollect(this->jsctx);
+ JSGlobalContextRelease(this->jsctx);
+ }
- // 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);
+ webkit_pacrunner(const pac pac) throw (bad_alloc) {
+ JSStringRef str = NULL;
+ JSObjectRef func = NULL;
- // 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);
+ // Create the basic context
+ if (!(this->jsctx = JSGlobalContextCreate(NULL))) goto error;
- return self;
-
-error:
- if (str) JSStringRelease(str);
- ctxs_free(self);
- return NULL;
-}
+ // Add dnsResolve into the context
+ str = JSStringCreateWithUTF8CString("dnsResolve");
+ func = JSObjectMakeFunctionWithCallback(this->jsctx, str, dnsResolve);
+ JSObjectSetProperty(this->jsctx, JSContextGetGlobalObject(this->jsctx), str, func, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(str);
-static void
-_destructor(void *s)
-{
- pxWebKitPACRunnerModule *self = (pxWebKitPACRunnerModule *) s;
+ // Add myIpAddress into the context
+ str = JSStringCreateWithUTF8CString("myIpAddress");
+ func = JSObjectMakeFunctionWithCallback(this->jsctx, str, myIpAddress);
+ JSObjectSetProperty(this->jsctx, JSContextGetGlobalObject(this->jsctx), str, func, kJSPropertyAttributeNone, NULL);
+ JSStringRelease(str);
- ctxs_free(self->ctxs);
- px_free(self);
-}
+ // Add all other routines into the context
+ str = JSStringCreateWithUTF8CString(JAVASCRIPT_ROUTINES);
+ if (!JSCheckScriptSyntax(this->jsctx, str, NULL, 0, NULL)) goto error;
+ JSEvaluateScript(this->jsctx, str, NULL, NULL, 1, NULL);
+ JSStringRelease(str);
-static char *
-_run(pxPACRunnerModule *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 = ((pxWebKitPACRunnerModule *) self)->ctxs;
-
- // 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;
- }
+ // Add the PAC into the context
+ str = JSStringCreateWithUTF8CString(pac.to_string().c_str());
+ if (!JSCheckScriptSyntax(this->jsctx, str, NULL, 0, NULL)) goto error;
+ JSEvaluateScript(this->jsctx, str, NULL, NULL, 1, NULL);
+ JSStringRelease(str);
+ return;
- // If no context exists (or if the pac was changed), create one
- if (!ctxs)
- {
- if ((ctxs = ctxs_new(pac)))
- ((pxWebKitPACRunnerModule *) self)->ctxs = ctxs;
- else
- return NULL;
+ error:
+ if (str) JSStringRelease(str);
+ if (this->jsctx) {
+ JSGarbageCollect(this->jsctx);
+ JSGlobalContextRelease(this->jsctx);
+ }
+ throw bad_alloc();
}
- // 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);
+ string run(const url url) throw (bad_alloc) {
+ JSStringRef str = NULL;
+ JSValueRef val = NULL;
+ string tmp;
+
+ // Run the PAC
+ tmp = string("FindProxyForURL(\"") + url.to_string() + string("\", \"") + url.get_host() + "\");";
+ str = JSStringCreateWithUTF8CString(tmp.c_str());
+ if (!JSCheckScriptSyntax(this->jsctx, str, NULL, 0, NULL)) goto error;
+ if (!(val = JSEvaluateScript(this->jsctx, str, NULL, NULL, 1, NULL))) goto error;
+ if (!JSValueIsString(this->jsctx, val)) goto error;
+ JSStringRelease(str);
- // Convert the return value to a string
- return jstr2str(JSValueToStringCopy(ctxs->ctx, val, NULL), true);
+ // Convert the return value to a string
+ return jstr2str(JSValueToStringCopy(this->jsctx, val, NULL), true);
-error:
- if (str) JSStringRelease(str);
- ctxs_free(ctxs);
- return tmp;
-}
+ error:
+ if (str) JSStringRelease(str);
+ throw bad_alloc();
+ }
-static void *
-_constructor()
-{
- pxWebKitPACRunnerModule *self = (pxWebKitPACRunnerModule*) px_malloc0(sizeof(pxWebKitPACRunnerModule));
- self->__parent__.run = _run;
- return self;
-}
+private:
+ JSGlobalContextRef jsctx;
+};
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxPACRunnerModule, _constructor, _destructor);
-}
+PX_DEFINE_PACRUNNER_MODULE(webkit, true);
diff --git a/libproxy/modules/pxgconf.cpp b/libproxy/modules/pxgconf.cpp
new file mode 100644
index 0000000..0164413
--- /dev/null
+++ b/libproxy/modules/pxgconf.cpp
@@ -0,0 +1,180 @@
+#include <cstdio>
+#include <unistd.h>
+#include <signal.h>
+
+#include <glib.h>
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+
+using namespace std;
+
+static GMainLoop* loop = NULL;
+
+static int _print_value(const GConfValue *value, const char *suffix) {
+ int count = 0;
+ GSList* cursor = NULL;
+
+ if (!value) return 0;
+
+ switch (value->type) {
+ case GCONF_VALUE_STRING:
+ return printf("%s%s", gconf_value_get_string(value), suffix);
+ case GCONF_VALUE_INT:
+ return printf("%d%s", gconf_value_get_int(value), suffix);
+ case GCONF_VALUE_FLOAT:
+ return printf("%f%s", gconf_value_get_float(value), suffix);
+ case GCONF_VALUE_BOOL:
+ if (gconf_value_get_bool(value))
+ return printf("true%s", suffix);
+ return printf("false%s", suffix);
+ case GCONF_VALUE_LIST:
+ cursor = gconf_value_get_list(value);
+ for ( ; cursor ; cursor = g_slist_next(cursor))
+ count += _print_value((const GConfValue *) cursor->data, cursor->next ? "," : suffix);
+ return count;
+ case GCONF_VALUE_PAIR:
+ return _print_value(gconf_value_get_car(value), ",") +
+ _print_value(gconf_value_get_cdr(value), suffix);
+ }
+ return 0;
+}
+
+static void _on_value_change(GConfClient *client, guint cnxn_id, GConfEntry *entry, void *user_data) {
+ printf("%s\t", gconf_entry_get_key(entry));
+ _print_value(gconf_entry_get_value(entry), "\n");
+}
+
+static void _on_sig(int signal) {
+ g_main_loop_quit(loop);
+}
+
+static gboolean _error(GIOChannel *source, GIOCondition condition, gpointer data) {
+ g_main_loop_quit(loop);
+ return false;
+}
+
+static gboolean _set_key(const char *key, const char *val) {
+ gboolean error = false;
+ GConfClient *client = gconf_client_get_default();
+ GConfValue *value = gconf_client_get(client, key, NULL);
+ GConfValueType type = value ? value->type : GCONF_VALUE_STRING;
+ gconf_value_free(value);
+
+ switch (type) {
+ case GCONF_VALUE_STRING:
+ error = !gconf_client_set_string(client, key, val, NULL);
+ break;
+ case GCONF_VALUE_INT:
+ int ival;
+ error = sscanf(val, "%d", &ival) != 1;
+ error = error || !gconf_client_set_int(client, key, ival, NULL);
+ break;
+ case GCONF_VALUE_FLOAT:
+ int fval;
+ error = sscanf(val, "%f", &fval) != 1;
+ error = error || !gconf_client_set_float(client, key, fval, NULL);
+ break;
+ case GCONF_VALUE_BOOL:
+ error = !gconf_client_set_float(client, key, !g_strcmp0(val, "true"), NULL);
+ break;
+ case GCONF_VALUE_LIST:
+ case GCONF_VALUE_PAIR:
+ default:
+ g_critical("Invalid value type!");
+ error = true;
+ }
+
+ g_object_unref(client);
+ return !error;
+}
+
+static gboolean _stdin(GIOChannel *source, GIOCondition condition, gpointer data) {
+ gchar *key, *val;
+ GIOStatus st = g_io_channel_read_line(source, &key, NULL, NULL, NULL);
+
+ // Remove the trailing '\n'
+ for (int i=0 ; key && key[i] ; i++)
+ if (key[i] == '\n')
+ key[i] = NULL;
+
+ // If we were successful
+ if (key && st == G_IO_STATUS_NORMAL) {
+ if (!g_strrstr(key, "\t"))
+ goto exit;
+
+ val = g_strrstr(key, "\t") + 1;
+ *(val-1) = NULL;
+
+ if (!_set_key(key, val))
+ goto exit;
+
+ g_free(key);
+ return true;
+ }
+ else if (key && st == G_IO_STATUS_AGAIN) {
+ g_free(key);
+ return _stdin(source, condition, data);
+ }
+
+exit:
+ g_free(key);
+ return _error(source, condition, data);
+}
+
+int main(int argc, char **argv) {
+ if (argc < 2) return 1;
+
+ // Register sighup handler
+ if (signal(SIGHUP, _on_sig) == SIG_ERR || signal(SIGPIPE, _on_sig) == SIG_ERR) {
+ fprintf(stderr, "Unable to trap signals!");
+ return 2;
+ }
+
+ // Switch stdout to line buffering
+ if (setvbuf(stdout, NULL, _IOLBF, 0)) {
+ fprintf(stderr, "Unable to switch stdout to line buffering!");
+ return 3;
+ }
+
+ // Switch stdin to line buffering
+ if (setvbuf(stdin, NULL, _IOLBF, 0)) {
+ fprintf(stderr, "Unable to switch stdin to line buffering!");
+ return 4;
+ }
+
+ // Init
+ g_type_init();
+
+ // Get the main loop
+ loop = g_main_loop_new(NULL, false);
+
+ // Setup our GIO Channels
+ GIOChannel* inchan = g_io_channel_unix_new(fileno(stdin));
+ GIOChannel* outchan = g_io_channel_unix_new(fileno(stdout));
+ g_io_add_watch(inchan, G_IO_IN, _stdin, NULL);
+ g_io_add_watch(inchan, G_IO_PRI, _stdin, NULL);
+ g_io_add_watch(inchan, G_IO_ERR, _error, NULL);
+ g_io_add_watch(inchan, G_IO_HUP, _error, NULL);
+ g_io_add_watch(outchan, G_IO_ERR, _error, NULL);
+ g_io_add_watch(outchan, G_IO_HUP, _error, NULL);
+
+ // Get GConf client
+ GConfClient* client = gconf_client_get_default();
+
+ // Add server notifications for all keys
+ for (int i=1 ; i < argc ; i++) {
+ gconf_client_add_dir(client, argv[i], GCONF_CLIENT_PRELOAD_NONE, NULL);
+ gconf_client_notify_add(client, argv[i], _on_value_change, NULL, NULL, NULL);
+ gconf_client_notify(client, argv[i]);
+ }
+
+ g_main_loop_run(loop);
+
+ // Cleanup
+ g_object_unref(client);
+ g_io_channel_shutdown(inchan, FALSE, NULL);
+ g_io_channel_shutdown(outchan, FALSE, NULL);
+ g_io_channel_unref(inchan);
+ g_io_channel_unref(outchan);
+ g_main_loop_unref(loop);
+}
diff --git a/libproxy/modules/wpad_dns.cpp b/libproxy/modules/wpad_dns.cpp
index a8858e5..8918560 100644
--- a/libproxy/modules/wpad_dns.cpp
+++ b/libproxy/modules/wpad_dns.cpp
@@ -17,50 +17,37 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdlib.h>
-#include <string.h>
+#include "../module_types.hpp"
-#include "../misc.hpp"
-#include "../modules.hpp"
-#include "../pac.hpp"
+using namespace com::googlecode::libproxy;
-typedef struct _pxDNSWPADModule {
- PX_MODULE_SUBCLASS(pxWPADModule);
- bool rewound;
-} pxDNSWPADModule;
+class dns_wpad_module : public wpad_module {
+public:
+ PX_MODULE_ID(NULL);
-static pxPAC *
-_next(pxWPADModule *self)
-{
- if (((pxDNSWPADModule *) self)->rewound)
- {
- pxPAC *pac = px_pac_new_from_string("http://wpad/wpad.dat");
- self->found = pac != NULL;
- return pac;
+ dns_wpad_module() {
+ this->last = NULL;
}
- else
- return NULL;
-}
-static void
-_rewind(pxWPADModule *self)
-{
- ((pxDNSWPADModule *) self)->rewound = true;
-}
+ bool found() {
+ return this->last != NULL;
+ }
+
+ pac* next() {
+ if (this->last) return NULL;
+
+ try { this->last = new pac(url("http://wpad/wpad.dat")); }
+ catch (io_error& e) { }
+
+ return this->last;
+ }
+
+ void rewind() {
+ this->last = NULL;
+ }
-static void *
-_constructor()
-{
- pxDNSWPADModule *self = (pxDNSWPADModule*) px_malloc0(sizeof(pxDNSWPADModule));
- self->rewound = true;
- self->__parent__.found = false;
- self->__parent__.next = _next;
- self->__parent__.rewind = _rewind;
- return self;
-}
+private:
+ pac* last;
+};
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxWPADModule, _constructor, px_free);
-}
+PX_MODULE_LOAD(wpad_module, dns, true);
diff --git a/libproxy/modules/wpad_dnsdevolution.cpp b/libproxy/modules/wpad_dnsdevolution.cpp
index 05019b7..37e7770 100644
--- a/libproxy/modules/wpad_dnsdevolution.cpp
+++ b/libproxy/modules/wpad_dnsdevolution.cpp
@@ -17,165 +17,88 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#define __USE_BSD
-#include <unistd.h>
-
-#ifdef _WIN32
-#include <winsock2.h>
-#else
-#include <netdb.h>
-#endif
-
-#include "../misc.hpp"
-#include "../array.hpp"
-#include "../modules.hpp"
-#include "../pac.hpp"
-
-/* The top-level domain blacklist */
+#include <cstring>
+
+#include "../module_types.hpp"
+using namespace com::googlecode::libproxy;
+
+/* The domain blacklist */
/* TODO: Make this not suck */
-static char *tld[] = {
- /* 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 */
- "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",
- "bz", "ca", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn",
- "co", "cr", "cu", "cv", "cx", "cy", "cz", "de", "dj", "dk", "dm", "do",
- "dz", "ec", "ee", "eg", "er", "es", "et", "eu", "fi", "fj", "fk", "fm",
- "fo", "fr", "ga", "gb", "gd", "ge", "gf", "gg", "gh", "gi", "gl", "gm",
- "gn", "gp", "gq", "gr", "gs", "gt", "gu", "gw", "gy", "hk", "hm", "hn",
- "hr", "ht", "hu", "id", "ie", "il", "im", "in", "io", "iq", "ir", "is",
- "it", "je", "jm", "jo", "jp", "ke", "kg", "kh", "ki", "km", "kn", "kr",
- "kw", "ky", "kz", "la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu",
- "lv", "ly", "ma", "mc", "md", "mg", "mh", "mk", "ml", "mm", "mn", "mo",
- "mp", "mq", "mr", "ms", "mt", "mu", "mv", "mw", "mx", "my", "mz", "na",
- "nc", "ne", "nf", "ng", "ni", "nl", "no", "np", "nr", "nu", "nz", "om",
- "pa", "pe", "pf", "pg", "ph", "pk", "pl", "pm", "pn", "pr", "ps", "pt",
- "pw", "py", "qa", "re", "ro", "ru", "rw", "sa", "sb", "sc", "sd", "se",
- "sg", "sh", "si", "sj", "sk", "sl", "sm", "sn", "sr", "st", "su", "sv",
- "sy", "sz", "tc", "td", "tf", "tg", "th", "tj", "tk", "tl", "tm", "tn",
- "to", "tp", "tr", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "um", "us",
- "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws", "ye",
- "yt", "yu", "za", "zm", "zw",
-
- /* Other domains to blacklist */
+/* Is there a list of 'public' domains somewhere? */
+static const char *blacklist[] = {
"co.uk", "com.au",
/* Terminator */
NULL
};
-typedef struct _pxDNSDevolutionWPADModule {
- PX_MODULE_SUBCLASS(pxWPADModule);
- pxArray *urls;
- int next;
-} pxDNSDevolutionWPADModule;
-
-static char *
-_get_domain_name()
+static string
+_get_fqdn()
{
- /* Get the hostname */
- char *hostname = (char *) px_malloc0(128);
- for (int i = 0 ; gethostname(hostname, (i + 1) * 128) && errno == ENAMETOOLONG ; )
- hostname = (char *) px_malloc0((++i + 1) * 128);
+#define BUFLEN 512
+ char hostname[BUFLEN];
+
+ // Zero out the buffer
+ memset(hostname, 0, BUFLEN);
+
+ // Get the hostname
+ if (gethostname(hostname, BUFLEN)) return "";
/* Lookup the hostname */
/* TODO: Make this whole process not suck */
struct hostent *host_info = gethostbyname(hostname);
if (host_info)
- {
- px_free(hostname);
- hostname = px_strdup(host_info->h_name);
- }
+ strncpy(hostname, host_info->h_name, BUFLEN-1);
- /* Get domain portion */
- if (!strchr(hostname, '.')) return NULL;
- if (!strcmp(".", strchr(hostname, '.'))) return NULL;
- char *tmp = px_strdup(strchr(hostname, '.') + 1);
- px_free(hostname);
- return tmp;
+ try { return string(hostname).substr(string(hostname).find(".")).substr(1); }
+ catch (out_of_range& e) { return ""; }
}
-static pxArray *
-_get_urls()
-{
- char *domain = _get_domain_name();
- if (!domain) return NULL;
-
- /* Split up the domain */
- char **domainv = px_strsplit(domain, ".");
- px_free(domain);
- if (!domainv) return NULL;
-
- pxArray *urls = px_array_new(NULL, px_free, false, false);
- for (int i=1 ; domainv[i] ; i++)
- {
- /* Check the domain against the blacklist */
- domain = px_strjoin((const char **) (domainv + i), ".");
- for (int k=0; tld[k] ; k++)
- if (!strcmp(domain, tld[k])) { px_free(domain); domain = NULL; break; }
- if (!domain) continue;
-
- /* Create a URL */
- char *url = px_strcat("http://wpad.", domain, "/wpad.dat", NULL);
- px_array_add(urls, url);
- px_free(domain);
+class dnsdevolution_wpad_module : public wpad_module {
+public:
+ PX_MODULE_ID(NULL);
+
+ dnsdevolution_wpad_module() {
+ this->rewind();
}
- return urls;
-}
+ bool found() {
+ return this->lpac != NULL;
+ }
-static pxPAC *
-_next(pxWPADModule *self)
-{
- pxDNSDevolutionWPADModule *dnsd = (pxDNSDevolutionWPADModule *) self;
- if (!dnsd->urls)
- dnsd->urls = _get_urls();
- if (!dnsd->urls)
- return NULL;
-
- pxPAC *pac = px_pac_new_from_string((char *) px_array_get(dnsd->urls, dnsd->next++));
- if (pac)
- self->found = true;
- return pac;
-}
+ pac* next() {
+ // If we have rewound start the new count
+ if (this->last == "")
+ this->last = _get_fqdn();
-static void
-_rewind(pxWPADModule *s)
-{
- pxDNSDevolutionWPADModule * self = (pxDNSDevolutionWPADModule *) s;
+ // Get the 'next' segment
+ if (this->last.find(".") == string::npos) return NULL;
+ this->last = this->last.substr(this->last.find(".")+1);
- px_array_free(self->urls);
- self->urls = NULL;
- self->next = 0;
- self->__parent__.found = false;
-}
+ // Don't do TLD's
+ if (this->last.find(".") == string::npos) return NULL;
-static void
-_destructor(void *s)
-{
- _rewind((pxWPADModule *) s);
- px_free(s);
-}
+ // Process blacklist
+ for (int i=0 ; blacklist[i] ; i++)
+ if (this->last == blacklist[i])
+ return NULL;
-static void *
-_constructor()
-{
- pxDNSDevolutionWPADModule *self = (pxDNSDevolutionWPADModule*) px_malloc0(sizeof(pxDNSDevolutionWPADModule));
- self->__parent__.next = _next;
- self->__parent__.rewind = _rewind;
- _rewind((pxWPADModule *) self);
- return self;
-}
+ // Try to load
+ try { this->lpac = new pac(url(string("http://wpad.") + this->last + "/wpad.dat")); }
+ catch (parse_error& e) { }
+ catch (io_error& e) { }
-bool
-px_module_load(pxModuleManager *self)
-{
- return px_module_manager_register_module(self, pxWPADModule, _constructor, _destructor);
-}
+ return this->lpac;
+ }
+
+ void rewind() {
+ this->last = "";
+ }
+
+
+private:
+ string last;
+ pac* lpac;
+};
+
+PX_MODULE_LOAD(wpad_module, dnsdevolution, true);
diff --git a/libproxy/modules/xhasclient.cpp b/libproxy/modules/xhasclient.cpp
index 85c563a..af829f4 100644
--- a/libproxy/modules/xhasclient.cpp
+++ b/libproxy/modules/xhasclient.cpp
@@ -1,6 +1,6 @@
/*
*
- *
+ *
Copyright 1989, 1998 The Open Group
Permission to use, copy, modify, distribute, and sell this software and its
@@ -31,54 +31,46 @@ in this Software without prior written authorization from The Open Group.
* Reworked by Nathaniel McCallum, 2007
*/
-#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
#include <X11/Xlib.h>
#include <X11/Xmu/WinUtil.h>
-bool
-x_has_client(char *prog, ...)
-{
+bool xhasclient(const char *prog, ...) {
va_list ap;
-
+
// Open display
Display *display = XOpenDisplay(NULL);
if (!display)
return false;
-
+
// For each screen...
- for (int i=0; i < ScreenCount(display); i++)
- {
+ for (int i=0; i < ScreenCount(display); i++) {
Window dummy, *children = NULL;
unsigned int nchildren = 0;
-
+
// Get the root window's children
if (!XQueryTree(display, RootWindow(display, i), &dummy, &dummy, &children, &nchildren))
continue;
-
+
// For each child on the screen...
- for (int j=0; j < nchildren; j++)
- {
+ for (int j=0; j < nchildren; j++) {
// If we can get their client info...
Window client;
- if ((client = XmuClientWindow(display, children[j])) != None)
- {
+ if ((client = XmuClientWindow(display, children[j])) != None) {
int argc;
char **argv;
-
+
// ... and if we can find out their command ...
if (!XGetCommand (display, client, &argv, &argc) || argc == 0)
continue;
-
+
// ... check the commands against our list
va_start(ap, prog);
- for (char *s = prog ; s ; s = va_arg(ap, char *))
- {
+ for (const char *s = prog ; s ; s = va_arg(ap, char *)) {
// We've found a match, return...
- if (!strcmp(argv[0], s))
- {
+ if (!strcmp(argv[0], s)) {
va_end(ap);
XCloseDisplay(display);
return true;
@@ -88,7 +80,7 @@ x_has_client(char *prog, ...)
}
}
}
-
+
// Close the display
XCloseDisplay(display);
return false;
diff --git a/libproxy/pac.cpp b/libproxy/pac.cpp
index bd533a7..c842537 100644
--- a/libproxy/pac.cpp
+++ b/libproxy/pac.cpp
@@ -17,177 +17,125 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <unistd.h>
-#include <string.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
+#include <cstdlib> // For atoi(...)
+#include <sys/stat.h> // For stat(...)
+#include <cstdio> // For sscanf(...)
#ifdef _WIN32
#include <winsock2.h>
+#define pfsize(st) (st.st_size)
#else
#include <sys/socket.h>
+#define pfsize(st) (st.st_blksize * st.st_blocks)
#endif
-#include "url.hpp"
-#include "misc.hpp"
#include "pac.hpp"
+// This mime type should be reported by the web server
#define PAC_MIME_TYPE "application/x-ns-proxy-autoconfig"
+// Fall back to checking for this mime type, which servers often report wrong
+#define PAC_MIME_TYPE_FB "text/plain"
-/**
- * ProxyAutoConfig object. All fields are private.
- */
-struct _pxPAC {
- pxURL *url;
- char *cache;
- time_t expires;
-};
-
-/**
- * Frees memory used by the ProxyAutoConfig.
- */
-void
-px_pac_free(pxPAC *self)
-{
- if (!self) return;
- px_url_free(self->url);
- px_free(self->cache);
- px_free(self);
-}
+// This is the maximum pac size (to avoid memory attacks)
+#define PAC_MAX_SIZE 102400
-/**
- * Get the URL which the pxPAC uses.
- * @return The URL that the pxPAC came from
- */
-const pxURL *
-px_pac_get_url(pxPAC *self)
-{
- return self->url;
-}
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
-/**
- * Create a new ProxyAutoConfig.
- * @url The URL where the PAC file is found
- * @return A new ProxyAutoConfig or NULL on error
- */
-pxPAC *
-px_pac_new(pxURL *url)
+static inline string _readline(int fd)
{
- if (!url) return NULL;
-
- /* Allocate the object */
- pxPAC *self = (pxPAC *) px_malloc0(sizeof(pxPAC));
-
- /* 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 */
- if (!px_pac_reload(self)) { px_pac_free(self); return NULL; }
-
- return self;
+ // Read a character.
+ // If we don't get a character, return empty string.
+ // If we are at the end of the line, return empty string.
+ char c = '\0';
+ if (read(fd, &c, 1) != 1 || c == '\n') return "";
+ return string(1, c) + _readline(fd);
}
-/**
- * Create a new ProxyAutoConfig (from a string for convenience).
- * @url The url (string) where the PAC file is found
- * @return A new ProxyAutoConfig or NULL on error
- */
-pxPAC *
-px_pac_new_from_string(char *url)
-{
- /* Create temporary URL */
- pxURL *tmpurl = px_url_new(url);
- if (!tmpurl) return NULL;
-
- /* Create pac */
- pxPAC *self = px_pac_new(tmpurl);
- px_url_free(tmpurl); /* Free no longer used URL */
- if (!self) return NULL;
- return self;
+pac::~pac() {
+ delete this->pacurl;
}
-/**
- * Returns the Javascript code which the pxPAC uses.
- * @return The Javascript code used by the pxPAC
- */
-const char *
-px_pac_to_string(pxPAC *self)
-{
- return self->cache;
+pac::pac(const pac& pac) {
+ this->pacurl = new libproxy::url(*pac.pacurl);
+ this->cache = pac.cache;
}
-/**
- * Download the latest version of the pxPAC file
- * @return Whether the download was successful or not
- */
-bool
-px_pac_reload(pxPAC *self)
-{
+pac::pac(const url& url) throw (io_error) {
int sock;
- char *line = NULL;
- const char *headers[3] = { "Accept: " PAC_MIME_TYPE, "Connection: close", NULL };
bool correct_mime_type;
- unsigned long int content_length = 0;
+ unsigned long int content_length = 0, status = 0;
+
+ this->pacurl = new libproxy::url(url.to_string().find("pac+") == 0 ? url.to_string().substr(4) : url);
/* Get the pxPAC */
- sock = px_url_get(self->url, headers);
- if (sock < 0) return false;
+ map<string, string> headers;
+ headers["Accept"] = PAC_MIME_TYPE;
+ headers["Connection"] = "close";
+ sock = this->pacurl->open(headers);
+ if (sock < 0) throw io_error("Unable to connect: " + url.to_string());
- if (strcmp(px_url_get_scheme(self->url),"file"))
+ if (url.get_scheme() != "file")
{
/* Verify status line */
- line = px_readline(sock, NULL, 0);
- 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 */
+ string line = _readline(sock);
+ if (sscanf(line.c_str(), "HTTP/1.%*d %d", &status) != 1 || status != 200) goto error;
/* Check for correct mime type and content length */
- while (strcmp(line, "\r")) {
- /* Check for content type */
- if (strstr(line, "Content-Type: ") == line && strstr(line, PAC_MIME_TYPE))
+ for (line = _readline(sock) ; line != "\r" && line != "" ; line = _readline(sock)) {
+ // Check for content type
+ if (line.find("Content-Type: ") == 0 &&
+ line.find(PAC_MIME_TYPE) != string::npos ||
+ line.find(PAC_MIME_TYPE_FB) != string::npos)
correct_mime_type = true;
- /* Check for content length */
- else if (strstr(line, "Content-Length: ") == line)
- content_length = atoi(line + strlen("Content-Length: "));
-
- /* Get new line */
- px_free(line);
- line = px_readline(sock, NULL, 0);
- if (!line) goto error;
+ // Check for content length
+ else if (content_length == 0)
+ sscanf(line.c_str(), "Content-Length: %lu", &content_length);
}
- /* Get content */
- if (!content_length || !correct_mime_type) goto error;
- px_free(line); line = NULL;
- px_free(self->cache);
- self->cache = (char *) px_malloc0(content_length+1);
- for (int recvd=0 ; recvd != content_length ; )
- recvd += recv(sock, self->cache + recvd, content_length - recvd, 0);
+ // Get content
+ if (!content_length || content_length > PAC_MAX_SIZE || !correct_mime_type) goto error;
+ char *buffer = new char[content_length];
+ for (int recvd=0 ; recvd < content_length ; )
+ recvd += recv(sock, buffer + recvd, content_length - recvd, 0);
+ this->cache = buffer;
+ delete buffer;
}
else
{ /* file:// url */
- struct stat buffer;
+ struct stat st;
int status;
- if (fstat(sock, &buffer)) goto error;
-#ifdef _WIN32
- self->cache = (char *) px_malloc0(buffer.st_size + 1);
- status = read(sock, self->cache, buffer.st_size);
-#else
- self->cache = (char *) px_malloc0(buffer.st_blksize * buffer.st_blocks + 1);
- status = read(sock, self->cache, buffer.st_blksize * buffer.st_blocks);
-#endif
+ if (fstat(sock, &st) || pfsize(st) > PAC_MAX_SIZE) goto error;
+ char *buffer = new char[pfsize(st)+1];
+ if (read(sock, buffer, pfsize(st)) == 0) {
+ delete buffer;
+ goto error;
+ }
+ this->cache = buffer;
+ delete buffer;
}
- /* Clean up */
+ // Clean up
close(sock);
- return true;
+ return;
+
+error:
+ if (sock >= 0) close(sock);
+ throw io_error("Unable to read PAC from " + url.to_string());
+}
- error:
- px_free(self->cache); self->cache = NULL;
- if (sock >= 0) close(sock);
- px_free(line);
- return false;
+url pac::get_url() const {
+ return *(this->pacurl);
+}
+
+string pac::to_string() const {
+ return this->cache;
+}
+
+}
+}
}
diff --git a/libproxy/pac.hpp b/libproxy/pac.hpp
index 4a29b83..8c3030d 100644
--- a/libproxy/pac.hpp
+++ b/libproxy/pac.hpp
@@ -1,72 +1,55 @@
/*******************************************************************************
* 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
******************************************************************************/
-#ifndef PAC_H_
-#define PAC_H_
+#ifndef PAC_HPP_
+#define PAC_HPP_
-#include "url.hpp"
-
-/**
- * pxPAC object. All fields are private.
- */
-typedef struct _pxPAC pxPAC;
-
-/**
- * Frees memory used by the ProxyAutoConfig.
- */
-void px_pac_free(pxPAC *self);
-
-/**
- * Get the URL which the pxPAC uses.
- * @return The URL that the pxPAC came from
- */
-__attribute__ ((visibility("default")))
-const pxURL *px_pac_get_url(pxPAC *self);
+#include <stdexcept>
-/**
- * Create a new ProxyAutoConfig.
- * @url The URL where the PAC file is found
- * @return A new ProxyAutoConfig or NULL on error
- */
-pxPAC *px_pac_new(pxURL *url);
-
-/**
- * Create a new ProxyAutoConfig (from a string for convenience).
- * @url The url (string) where the PAC file is found
- * @return A new ProxyAutoConfig or NULL on error
- */
-__attribute__ ((visibility("default")))
-pxPAC *px_pac_new_from_string(char *url);
-
-/**
- * Returns the Javascript code which the pxPAC uses.
- * @return The Javascript code used by the pxPAC
- */
-__attribute__ ((visibility("default")))
-const char *px_pac_to_string(pxPAC *self);
-
-/**
- * Download the latest version of the pxPAC file
- * @return Whether the download was successful or not
- */
-__attribute__ ((visibility("default")))
-bool px_pac_reload(pxPAC *self);
+#include "url.hpp"
-#endif /*PAC_H_*/
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
+
+class io_error : public runtime_error {
+public:
+ io_error(const string& __arg): runtime_error(__arg) {}
+};
+
+class pac {
+public:
+ ~pac();
+ pac(const url& url) throw (io_error);
+ pac(const pac& pac);
+ url get_url() const;
+ string to_string() const;
+
+private:
+ url* pacurl;
+ string cache;
+};
+
+}
+}
+}
+
+#endif /*PAC_HPP_*/
diff --git a/libproxy/proxy.cpp b/libproxy/proxy.cpp
index c410f7f..40466a8 100644
--- a/libproxy/proxy.cpp
+++ b/libproxy/proxy.cpp
@@ -18,10 +18,10 @@
******************************************************************************/
#define _BSD_SOURCE
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
+#include <algorithm>
+#include <iostream>
+#include <cstring>
+
#include <pthread.h>
#ifdef _WIN32
@@ -29,418 +29,302 @@
#define setenv(name, value, overwrite) SetEnvironmentVariable(name, value)
#endif
-#include "misc.hpp"
-#include "proxy.h"
#include "config_file.hpp"
-#include "array.hpp"
-#include "strdict.hpp"
-#include "module_manager.hpp"
-#include "modules.hpp"
-
-struct _pxProxyFactory {
- pthread_mutex_t mutex;
- pxModuleManager *mm;
- pxPAC *pac;
- bool wpad;
+#include "module_types.hpp"
+
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
+
+class proxy_factory {
+public:
+ proxy_factory();
+ ~proxy_factory();
+ vector<string> get_proxies(string url);
+
+private:
+ pthread_mutex_t mutex;
+ module_manager mm;
+ libproxy::pac* pac;
+ bool wpad;
};
-/* Convert the PAC formatted response into our proxy URL array response */
-static char **
-_format_pac_response(char *response)
-{
- char **chain, *tmp;
+bool istringcmp(string a, string b) {
+ transform( a.begin(), a.end(), a.begin(), ::tolower );
+ transform( b.begin(), b.end(), b.begin(), ::tolower );
+ return ( a == b );
+}
- if (!response) return px_strsplit("direct://", ";");
- chain = px_strsplit(response, ";");
- px_free(response);
+// Convert the PAC formatted response into our proxy URL array response
+static vector<string>
+_format_pac_response(string response)
+{
+ vector<string> retval;
- for (int i=0 ; chain[i] ; i++)
- {
- tmp = px_strstrip(chain[i]);
- px_free(chain[i]);
-
- if (!strncmp(tmp, "PROXY", 5) || !strncmp(tmp, "SOCKS", 5))
- {
- char *hostport = px_strstrip(tmp + 5);
- if (!strncmp(tmp, "PROXY", 5))
- chain[i] = px_strcat("http://", hostport, NULL);
- else
- chain[i] = px_strcat("socks://", hostport, NULL);
- px_free(hostport);
- }
- else
- chain[i] = px_strdup("direct://");
+ // Skip ahead one character if we start with ';'
+ if (response[0] == ';')
+ return _format_pac_response(response.substr(1));
- px_free(tmp);
+ // If the string contains a delimiter (';')
+ if (response.find(';') != string::npos) {
+ retval = _format_pac_response(response.substr(response.find(';')+1));
+ response = response.substr(0, response.find(';'));
}
- return chain;
-}
-
-static inline int
-_px_wpad_module_findpos(const char *name)
-{
- int pos = 0;
-
- char **orderv = px_strsplit("wpad_dhcp,wpad_slp,wpad_dns,wpad_dnsdevolution", ",");
- for (pos = 0 ; orderv[pos] ; pos++)
- if (!strcmp(name, orderv[pos]))
- goto do_return;
+ // Strip whitespace
+ response = response.substr(response.find_first_not_of(" \t"), response.find_last_not_of(" \t")+1);
+
+ // Get the method and the server
+ string method = "";
+ string server = "";
+ if (response.find_first_of(" \t") == string::npos)
+ method = response;
+ else {
+ method = response.substr(0, response.find_first_of(" \t"));
+ server = response.substr(response.find_first_of(" \t") + 1);
+ }
- do_return:
- px_strfreev(orderv);
- return pos;
-}
+ // Insert our url value
+ if (istringcmp(method, "proxy") && url::is_valid("http://" + server))
+ retval.insert(retval.begin(), string("http://") + server);
+ else if (istringcmp(method, "socks") && url::is_valid("http://" + server))
+ retval.insert(retval.begin(), string("socks://") + server);
+ else if (istringcmp(method, "direct"))
+ retval.insert(retval.begin(), string("direct://"));
-static int
-_px_wpad_module_cmp(pxModuleRegistration **a, pxModuleRegistration **b)
-{
- if (!a || !*a) return 0;
- if (!b || !*b) return 0;
- return _px_wpad_module_findpos((*a)->name) - _px_wpad_module_findpos((*b)->name);
+ return retval;
}
-static inline int
-_px_config_module_findpos(pxConfigModuleCategory category, const char *name)
-{
- int pos = 0;
-
- /* Attempt to get config order */
- char *fileorder = getenv("_PX_CONFIG_ORDER");
- char *envorder = getenv("PX_CONFIG_ORDER");
-
- /* Create the config order */
- char *order = px_strcat(fileorder ? fileorder : "", ",",
- envorder ? envorder : "", ",",
- "USER,SESSION,SYSTEM,config_envvar,config_wpad,config_direct",
- NULL);
-
- /* Create the config plugin order vector */
- char **orderv = px_strsplit(order, ",");
- px_free(order);
-
- /* Get the config by searching the config order */
- for (pos=0 ; orderv[pos] ; pos++)
- {
- if ((!strcmp(orderv[pos], "USER") && PX_CONFIG_MODULE_CATEGORY_USER == category) ||
- (!strcmp(orderv[pos], "SESSION") && PX_CONFIG_MODULE_CATEGORY_SESSION == category) ||
- (!strcmp(orderv[pos], "SYSTEM") && PX_CONFIG_MODULE_CATEGORY_SYSTEM == category) ||
- (!strcmp(orderv[pos], name)))
- break;
- }
- px_strfreev(orderv);
- return pos;
-}
+proxy_factory::proxy_factory() {
+ pthread_mutex_init(&this->mutex, NULL);
+ pthread_mutex_lock(&this->mutex);
+ this->pac = NULL;
+
+ // Register our singletons
+ this->mm.set_singleton<pacrunner_module>(true);
+
+ // If we have a config file, load the config order from it
+ setenv("_PX_CONFIG_ORDER", "", 1);
+ config_file cf;
+ if (cf.load(SYSCONFDIR "proxy.conf")) {
+ try {
+ string tmp = cf.get_value("config_order");
+ setenv("_PX_CONFIG_ORDER", tmp.c_str(), 1);
+ }
+ catch (key_error e) { }
+ }
-static int
-_px_config_module_cmp(pxModuleRegistration **a, pxModuleRegistration **b)
-{
- if (!a || !*a) return 0;
- if (!b || !*b) return 0;
+ // Load all modules
+ this->mm.load_dir(MODULEDIR);
- return _px_config_module_findpos(((pxConfigModule *) (*a)->instance)->category, (*a)->name) -
- _px_config_module_findpos(((pxConfigModule *) (*b)->instance)->category, (*b)->name);
+ pthread_mutex_unlock(&this->mutex);
}
-/**
- * Creates a new pxProxyFactory instance. This instance should be kept
- * around as long as possible as it contains cached data to increase
- * performance. Memory usage should be minimal (cache is small) and the
- * cache lifespan is handled automatically.
- *
- * @return A new pxProxyFactory instance or NULL on error
- */
-pxProxyFactory *
-px_proxy_factory_new ()
-{
- pxProxyFactory *self = (pxProxyFactory *) px_malloc0(sizeof(pxProxyFactory));
- self->mm = px_module_manager_new();
- pxConfigFile *cf = NULL;
- char *tmp;
-
- /* Register our module types */
- if (!px_module_manager_register_type(self->mm, pxConfigModule, _px_config_module_cmp, false)) goto error;
- if (!px_module_manager_register_type(self->mm, pxPACRunnerModule, NULL, true)) goto error;
- if (!px_module_manager_register_type(self->mm, pxWPADModule, _px_wpad_module_cmp, false)) goto error;
-
- /* If we have a config file, load the config order from it */
- setenv("_PX_CONFIG_ORDER", "", 1);
- cf = px_config_file_new(SYSCONFDIR "proxy.conf");
- if (cf)
- {
- tmp = px_config_file_get_value(cf, PX_CONFIG_FILE_DEFAULT_SECTION, "config_order");
- px_config_file_free(cf);
- if (tmp && setenv("_PX_CONFIG_ORDER", tmp, 1))
- {
- px_free(tmp);
- goto error;
- }
- px_free(tmp);
- }
-
- /* Load all modules */
- if (!px_module_manager_load_dir(self->mm, MODULEDIR)) goto error;
-
- pthread_mutex_init(&self->mutex, NULL);
- return self;
-
- error:
- px_proxy_factory_free(self);
- return NULL;
+proxy_factory::~proxy_factory() {
+ pthread_mutex_lock(&this->mutex);
+ if (this->pac) delete this->pac;
+ pthread_mutex_unlock(&this->mutex);
+ pthread_mutex_destroy(&this->mutex);
}
-/**
- * Get which proxies to use for the specified URL.
- *
- * 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.
- *
- * Regarding performance: this method always blocks and may be called
- * in a separate thread (is thread-safe). In most cases, the time
- * required to complete this function call is simply the time required
- * to read the configuration (i.e. from gconf, kconfig, etc).
- *
- * In the case of PAC, if no valid PAC is found in the cache (i.e.
- * configuration has changed, cache is invalid, etc), the PAC file is
- * downloaded and inserted into the cache. This is the most expensive
- * operation as the PAC is retrieved over the network. Once a PAC exists
- * in the cache, it is merely a javascript invocation to evaluate the PAC.
- * One should note that DNS can be called from within a PAC during
- * javascript invocation.
- *
- * In the case of WPAD, WPAD is used to automatically locate a PAC on the
- * network. Currently, we only use DNS for this, but other methods may
- * be implemented in the future. Once the PAC is located, normal PAC
- * performance (described above) applies.
- *
- * The format of the returned proxy strings are as follows:
- * - http://[username:password@]proxy:port
- * - socks://[username:password@]proxy:port
- * - direct://
- * Please note that the username and password in the above URLs are optional
- * and should be use to authenticate the connection if present.
- *
- * @url The URL we are trying to reach
- * @return A NULL-terminated array of proxy strings to use
- */
-char **
-px_proxy_factory_get_proxies (pxProxyFactory *self, char *url)
-{
- char **response = px_strsplit("direct://", ";");
- char *confurl = NULL;
- char *confign = NULL;
- pxConfigModule *config = NULL;
- pxIgnoreModule **ignores = NULL;
- pxConfigModule **configs = NULL;
- pxNetworkModule **networks = NULL;
- char **ignore_split = NULL;
-
- /* Verify some basic stuff */
- if (!self) return response;
- pthread_mutex_lock(&self->mutex);
-
- /* Convert the URL */
- pxURL *realurl = px_url_new(url);
- if (!realurl) goto do_return;
-
- /* Check to see if our network has changed */
- networks = px_module_manager_instantiate_type(self->mm, pxNetworkModule);
- for (int i=0 ; networks && networks[i] ; i++)
- {
- if (networks[i]->changed(networks[i]))
- {
- pxWPADModule **wpads = px_module_manager_instantiate_type(self->mm, pxWPADModule);
- for (int j=0 ; wpads[j] ; j++)
- {
- wpads[j]->rewind(wpads[j]);
- }
- px_free(wpads);
- px_pac_free(self->pac);
- self->pac = NULL;
+
+vector<string> proxy_factory::get_proxies(string __url) {
+ url* realurl = NULL;
+ url confurl("direct://");
+ string confign;
+ config_module* config;
+ vector<network_module*> networks;
+ vector<config_module*> configs;
+ vector<ignore_module*> ignores;
+ vector<string> response;
+
+ // Check to make sure our url is valid
+ if (!url::is_valid(__url))
+ goto do_return;
+ realurl = new url(__url);
+
+ // Lock the mutex
+ pthread_mutex_lock(&this->mutex);
+
+ // Check to see if our network topology has changed...
+ networks = this->mm.get_modules<network_module>();
+ for (vector<network_module*>::iterator i=networks.begin() ; i != networks.end() ; i++) {
+ // If it has, reset our wpad/pac setup and we'll retry our config
+ if ((*i)->changed()) {
+ vector<wpad_module*> wpads = this->mm.get_modules<wpad_module>();
+ for (vector<wpad_module*>::iterator j=wpads.begin() ; j != wpads.end() ; j++)
+ (*j)->rewind();
+ if (this->pac) delete this->pac;
+ this->pac = NULL;
break;
}
}
- px_free(networks);
- /* Attempt to load a valid config */
- configs = px_module_manager_instantiate_type(self->mm, pxConfigModule);
- for (int i=0 ; configs && configs[i] ; i++)
- {
- config = configs[i];
- confurl = config->get_config(config, realurl);
- if (!confurl)
- goto invalid;
- confign = config->get_ignore(config, realurl);
-
- /* If the config plugin returned an invalid config type or malformed URL, mark as invalid */
- if (!(!strncmp(confurl, "http://", 7) ||
- !strncmp(confurl, "socks://", 8) ||
- !strncmp(confurl, "pac+", 4) ||
- !strcmp (confurl, "wpad://") ||
- !strcmp (confurl, "direct://")))
- goto invalid;
- else if (!strncmp(confurl, "pac+", 4) && !px_url_is_valid(confurl + 4))
- goto invalid;
- else if ((!strncmp(confurl, "http://", 7) || !strncmp(confurl, "socks://", 8)) &&
- !px_url_is_valid(confurl))
- goto invalid;
-
- config->valid = true;
+ configs = this->mm.get_modules<config_module>();
+ for (vector<config_module*>::iterator i=configs.begin() ; i != configs.end() ; i++) {
+ config = *i;
+
+ // Try to get the confurl
+ try { confurl = (config)->get_config(*realurl); }
+ catch (runtime_error e) { goto invalid_config; }
+
+ // Validate the input
+ if (!(confurl.get_scheme() == "http" ||
+ confurl.get_scheme() == "socks" ||
+ confurl.get_scheme().substr(0, 4) == "pac+" ||
+ confurl.get_scheme() == "wpad" ||
+ confurl.get_scheme() == "direct"))
+ goto invalid_config;
+
+ config->set_valid(true);
break;
- invalid:
- px_free(confurl); confurl = NULL;
- px_free(confign); confign = NULL;
- config->valid = false;
- config = NULL;
+ invalid_config:
+ confurl = "direct://";
+ confign = "";
+ (config)->set_valid(false);
+ config = NULL;
}
- px_free(configs);
- if (!config) goto do_return;
/* Check our ignore patterns */
- ignores = px_module_manager_instantiate_type(self->mm, pxIgnoreModule);
- ignore_split = px_strsplit(confign, ",");
- px_free(confign); confign = NULL;
- for (int i=0 ; ignore_split && ignore_split[i] ; i++)
- {
- for (int j=0 ; ignores && ignores[j] ; j++)
- {
- if (ignores[j]->ignore(ignores[j], realurl, ignore_split[i]))
- {
- px_free(ignores);
- px_strfreev(ignore_split);
+ ignores = this->mm.get_modules<ignore_module>();
+ for (int i=-1 ; i < confign.size() ; i=confign.find(',')) {
+ for (vector<ignore_module*>::iterator it=ignores.begin() ; it != ignores.end() ; it++)
+ if ((*it)->ignore(*realurl, confign.substr(i+1, confign.find(','))))
goto do_return;
- }
- }
}
- px_free(ignores);
- px_strfreev(ignore_split);
/* If we have a wpad config */
- if (!strcmp(confurl, "wpad://"))
- {
+ if (confurl.get_scheme() == "wpad") {
/* If the config has just changed from PAC to WPAD, clear the PAC */
- if (!self->wpad)
- {
- px_pac_free(self->pac);
- self->pac = NULL;
- self->wpad = true;
+ if (!this->wpad) {
+ if (this->pac) delete this->pac;
+ this->pac = NULL;
+ this->wpad = true;
}
/* If we have no PAC, get one */
- if (!self->pac)
- {
- pxWPADModule **wpads = px_module_manager_instantiate_type(self->mm, pxWPADModule);
- for (int i=0 ; wpads[i] ; i++)
- if ((self->pac = wpads[i]->next(wpads[i])))
+ if (!this->pac) {
+ vector<wpad_module*> wpads = this->mm.get_modules<wpad_module>();
+ for (vector<wpad_module*>::iterator i=wpads.begin() ; i != wpads.end() ; i++)
+ if ((this->pac = (*i)->next()))
break;
/* If getting the PAC fails, but the WPAD cycle worked, restart the cycle */
- if (!self->pac)
- {
- for (int i=0 ; wpads[i] ; i++)
- {
- if (wpads[i]->found)
- {
+ if (!this->pac) {
+ for (vector<wpad_module*>::iterator i=wpads.begin() ; i != wpads.end() ; i++) {
+ if ((*i)->found()) {
/* Since a PAC was found at some point,
* rewind all the WPADS to start from the beginning */
/* Yes, the reuse of 'i' here is intentional...
* This is because if *any* of the wpads have found a pac,
* we need to reset them all to keep consistent state. */
- for (i=0 ; wpads[i] ; i++)
- wpads[i]->rewind(wpads[i]);
+ for (i=wpads.begin() ; i != wpads.end() ; i++)
+ (*i)->rewind();
- /* Attempt to find a PAC */
- for (i=0 ; wpads[i] ; i++)
- if ((self->pac = wpads[i]->next(wpads[i])))
+ // Attempt to find a PAC
+ for (i=wpads.begin() ; i != wpads.end() ; i++)
+ if ((this->pac = (*i)->next()))
break;
break;
}
}
}
- px_free(wpads);
}
}
- /* If we have a PAC config */
- else if (!strncmp(confurl, "pac+", 4))
+ // If we have a PAC config
+ else if (confurl.get_scheme().substr(0, 4) == "pac+")
{
/* Save the PAC config */
- if (self->wpad)
- self->wpad = false;
+ if (this->wpad)
+ this->wpad = false;
/* If a PAC already exists, but came from a different URL than the one specified, remove it */
- if (self->pac)
- {
- pxURL *urltmp = px_url_new(confurl + 4);
- if (!urltmp)
- goto do_return;
- if (!px_url_equals(urltmp, px_pac_get_url(self->pac)))
+ if (this->pac) {
+ if (this->pac->get_url() == confurl)
{
- px_pac_free(self->pac);
- self->pac = NULL;
+ delete this->pac;
+ this->pac = NULL;
}
- px_url_free(urltmp);
}
/* Try to load the PAC if it is not already loaded */
- if (!self->pac && !(self->pac = px_pac_new_from_string(confurl + 4)))
+ if (!this->pac && !(this->pac = new libproxy::pac(confurl)))
goto do_return;
}
/* In case of either PAC or WPAD, we'll run the PAC */
- if (!strcmp(confurl, "wpad://") || !strncmp(confurl, "pac+", 4))
- {
- pxPACRunnerModule **pacrunners = px_module_manager_instantiate_type(self->mm, pxPACRunnerModule);
+ if (this->pac && confurl.get_scheme() == "wpad" || confurl.get_scheme().substr(0, 4) == "pac+" ) {
+ vector<pacrunner_module*> pacrunners = this->mm.get_modules<pacrunner_module>();
/* No PAC runner found, fall back to direct */
- if (!pacrunners)
- {
- px_free(pacrunners);
+ if (pacrunners.size() == 0)
goto do_return;
- }
/* Run the PAC, but only try one PACRunner */
- px_strfreev(response);
- response = _format_pac_response(pacrunners[0]->run(pacrunners[0], self->pac, realurl));
- px_free(pacrunners);
+ response = _format_pac_response(pacrunners[0]->run(*this->pac, *realurl));
}
/* If we have a manual config (http://..., socks://...) */
- else if (!strncmp(confurl, "http://", 7) || !strncmp(confurl, "socks://", 8))
+ else if (confurl.get_scheme() == "http" || confurl.get_scheme() == "socks")
{
- self->wpad = false;
- if (self->pac) { px_pac_free(self->pac); self->pac = NULL; }
- px_strfreev(response);
- response = px_strsplit(confurl, ";");
+ this->wpad = false;
+ if (this->pac) { delete this->pac; this->pac = NULL; }
+ response.clear();
+ response.push_back(confurl.to_string());
}
/* Actually return, freeing misc stuff */
do_return:
- px_free(confurl);
- px_url_free(realurl);
- pthread_mutex_unlock(&self->mutex);
+ pthread_mutex_unlock(&this->mutex);
+ if (realurl)
+ delete realurl;
+ if (response.size() == 0)
+ response.push_back("direct://");
return response;
}
-/**
- * Frees the pxProxyFactory instance when no longer used.
- */
-void
-px_proxy_factory_free (pxProxyFactory *self)
-{
- if (!self) return;
+}
+}
+}
- pthread_mutex_lock(&self->mutex);
+struct _pxProxyFactory {
+ com::googlecode::libproxy::proxy_factory pf;
+};
+
+extern "C" struct _pxProxyFactory *px_proxy_factory_new(void) {
+ return new struct _pxProxyFactory;
+}
- /* Free the module manager */
- px_module_manager_free(self->mm);
+extern "C" char** px_proxy_factory_get_proxies(struct _pxProxyFactory *self, const char *url) {
+ vector<string> proxies;
+ char** retval;
+
+ // Call the main method
+ //try {
+ proxies = self->pf.get_proxies(url);
+ retval = new char*[proxies.size()+1];
+ //} catch (exception&) {
+ // Return NULL on any exception
+ // return NULL;
+ //}
+
+ // Copy the results into an array
+ // Return NULL on memory allocation failure
+ retval[proxies.size()] = NULL;
+ for (int i=0 ; i < proxies.size() ; i++) {
+ retval[i] = strdup(proxies[i].c_str());
+ if (retval[i] == NULL) {
+ for (int j=i-1 ; j >= 0 ; j--)
+ free(retval[j]);
+ delete retval;
+ return NULL;
+ }
+ }
+ return retval;
+}
- /* Free everything else */
- px_pac_free(self->pac);
- pthread_mutex_unlock(&self->mutex);
- pthread_mutex_destroy(&self->mutex);
- px_free(self);
+extern "C" void px_proxy_factory_free(struct _pxProxyFactory *self) {
+ delete self;
}
diff --git a/libproxy/strdict.cpp b/libproxy/strdict.cpp
deleted file mode 100644
index b773cf9..0000000
--- a/libproxy/strdict.cpp
+++ /dev/null
@@ -1,126 +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.hpp"
-#include "array.hpp"
-#include "strdict.hpp"
-
-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 **) ((void **) item)[1];
- pxStrDictItemCallback do_free = (pxStrDictItemCallback) ((void **) item)[2];
-
- do_free(realitem);
- px_free(key);
- px_free(item);
-}
-
-static void
-dict_foreach(void *item, void *misc)
-{
- pxStrDictForeachCallback foreach = (pxStrDictForeachCallback) ((void **) misc)[0];
- char *key = (char *) ((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 = (pxStrDict*) 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, (void *) value, (void *) self->free };
- return px_array_del(self->data, item);
- }
-
- void **item = (void **) px_malloc0(sizeof(void *) * 3);
- item[0] = px_strdup(key);
- item[1] = value;
- item[2] = (void *) 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)
-{
- if (!self || !key) return NULL;
-
- void *v[3] = { (void *) key, NULL, NULL }, **ret;
- int i = px_array_find(self->data, v);
- if (i < 0) return NULL;
- ret = (void **) px_array_get(self->data, i);
- return ret[1];
-}
-
-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)
-{
- if (!self) return;
- px_array_free(self->data);
- px_free(self);
-}
diff --git a/libproxy/url.cpp b/libproxy/url.cpp
index 8ee9992..b49aeb8 100644
--- a/libproxy/url.cpp
+++ b/libproxy/url.cpp
@@ -17,105 +17,203 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#include <stdbool.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <fcntl.h>
-
-#ifdef _WIN32
-#define _WIN32_WINNT 0x0501
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#else
-#include <sys/socket.h>
-#include <netdb.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#endif
-
-#include "misc.hpp"
+#include <fcntl.h> // For ::open()
+#include <cstring> // For memcpy()
+#include <sstream> // For int/string conversion (using stringstream)
+#include <cstdio> // For sscanf()
+
#include "url.hpp"
-/**
- * pxURL object. All fields are private.
- */
-struct _pxURL {
- char *url;
- char *scheme;
- char *username;
- char *password;
- char *host;
- int port;
- char *path;
- struct sockaddr **ips;
-};
-
-/**
- * @return Frees the pxURL
- */
-void
-px_url_free(pxURL *self)
-{
- if (!self) return;
- px_free(self->url);
- px_free(self->scheme);
- px_free(self->host);
- px_free(self->path);
- if (self->ips)
+namespace com {
+namespace googlecode {
+namespace libproxy {
+using namespace std;
+
+static inline int _get_default_port(string scheme) {
+ struct servent *serv;
+ if ((serv = getservbyname(scheme.c_str(), NULL))) return ntohs(serv->s_port);
+ return 0;
+}
+
+template <class T>
+static inline string _to_string (const T& t) {
+ stringstream ss;
+ ss << t;
+ return ss.str();
+}
+
+#define _copyaddr_t(type, addr) (sockaddr*) memcpy(new type, &(addr), sizeof(type))
+static inline sockaddr* _copyaddr(const struct sockaddr& addr) {
+ switch (addr.sa_family) {
+ case (AF_INET):
+ return _copyaddr_t(sockaddr_in, addr);
+ case (AF_INET6):
+ return _copyaddr_t(sockaddr_in6, addr);
+ default:
+ return NULL;
+ }
+}
+
+bool url::is_valid(const string __url) {
+ url* tmp;
+ try { tmp = new url(__url); }
+ catch (parse_error& pe) { return false; }
+ delete tmp;
+ return true;
+}
+
+url::url(const string url) throw(parse_error, logic_error) {
+ char *schm = new char[url.size()];
+ char *auth = new char[url.size()];
+ char *host = new char[url.size()];
+ char *path = new char[url.size()];
+ bool port_specified = false;
+ this->ips = NULL;
+
+ // Break apart our url into 4 sections: scheme, auth (user/pass), host and path
+ // We'll do further parsing of auth and host a bit later
+ // NOTE: reset the unused variable after each scan or we get bleed-through
+ if (sscanf(url.c_str(), "%[^:]://%[^@]@%[^/]/%s", schm, auth, host, path) != 4 && !((*path = NULL)) && // URL with auth, host and path
+ sscanf(url.c_str(), "%[^:]://%[^@]@%[^/]", schm, auth, host) != 3 && !((*auth = NULL)) && // URL with auth, host
+ sscanf(url.c_str(), "%[^:]://%[^/]/%s", schm, host, path) != 3 && !((*path = NULL)) && // URL with host, path
+ sscanf(url.c_str(), "%[^:]://%[^/]", schm, host) != 2 && !((*host = NULL)) && // URL with host
+ !(sscanf(url.c_str(), "%[^:]://%s", schm, path) == 2 && string("file") == schm) && !((*path = NULL)) && // URL with path (ex: file:///foo)
+ !(sscanf(url.c_str(), "%[^:]://", schm) == 1 && (string("direct") == schm || string("wpad") == schm))) // URL with scheme-only (ex: wpad://, direct://)
{
- for (int i=0 ; self->ips[i] ; i++)
- px_free(self->ips[i]);
- px_free(self->ips);
+ delete schm;
+ delete auth;
+ delete host;
+ delete path;
+ throw parse_error("Invalid URL: " + url);
+ }
+
+ // Set scheme and path
+ this->scheme = schm;
+ this->path = *path ? string("/") + path : "";
+ *schm = NULL;
+ *path = NULL;
+
+ // Parse auth further
+ if (*auth) {
+ this->user = auth;
+ if (string(auth).find(":") != string:: npos) {
+ this->pass = this->user.substr(this->user.find(":")+1);
+ this->user = this->user.substr(0, this->user.find(":"));
+ }
+ *auth = NULL;
+ }
+
+ // Parse host further. Basically, we're looking for a port.
+ if (*host) {
+ this->host = host;
+ port_specified = sscanf(host, "%*[^:]:%d", &this->port) == 1;
+ if (port_specified)
+ this->host = this->host.substr(0, this->host.rfind(':'));
+ else
+ this->port = _get_default_port(this->scheme);
+ *host = NULL;
}
- px_free(self);
+
+ // Cleanup
+ delete schm;
+ delete auth;
+ delete host;
+ delete path;
+
+ // Verify by re-assembly
+ if (this->user != "" && this->pass != "")
+ this->orig = this->scheme + "://" + this->user + ":" + this->pass + "@" + this->host;
+ else
+ this->orig = this->scheme + "://" + this->host;
+ if (port_specified)
+ this->orig = this->orig + ":" + _to_string<int>(this->port) + this->path;
+ else
+ this->orig = this->orig + this->path;
+ if (this->orig != url)
+ throw logic_error("Re-assembly failed!");
+}
+
+url::url(const url &url) {
+ this->ips = NULL;
+ *this = url;
+}
+
+url::~url() {
+ if (this->ips) {
+ for (vector<const sockaddr*>::iterator i = this->ips->begin() ; i != this->ips->end() ; i++)
+ delete *i;
+ delete this->ips;
+ }
+}
+
+bool url::operator==(const url& url) const {
+ return this->orig == url.to_string();
}
-/**
- * Tells whether or not a pxURL string has valid syntax
- * @return true if the pxURL is valid, otherwise false
- */
-bool
-px_url_is_valid(const char *url)
-{
- pxURL *tmp = px_url_new(url);
- if (!tmp) return false;
- px_url_free(tmp);
- return true;
+url& url::operator=(const url& url) {
+ // Ensure these aren't the same objects
+ if (&url == this)
+ return *this;
+
+ this->host = url.host;
+ this->orig = url.orig;
+ this->pass = url.pass;
+ this->path = url.path;
+ this->port = url.port;
+ this->scheme = url.scheme;
+ this->user = url.user;
+
+ if (this->ips) {
+ // Free any existing ip cache
+ for (vector<const sockaddr*>::iterator i = this->ips->begin() ; i != this->ips->end() ; i++)
+ delete *i;
+ delete this->ips;
+ this->ips = NULL;
+ }
+
+ if (url.ips) {
+ // Copy the new ip cache
+ this->ips = new vector<const sockaddr*>();
+ for (vector<const sockaddr*>::iterator i = url.ips->begin() ; i != url.ips->end() ; i++)
+ this->ips->push_back(_copyaddr(**i));
+ }
+ return *this;
}
-/**
- * Sends a get request for the pxURL.
- * @headers A list of headers to be included in the request.
- * @return Socket to read the response on.
- */
-int
-px_url_get(pxURL *self, const char **headers)
-{
- char *request = NULL;
+url& url::operator=(string strurl) throw (parse_error) {
+ url* tmp = new url(strurl);
+ *this = *tmp;
+ delete tmp;
+ return *this;
+}
+
+int url::open() {
+ map<string, string> headers;
+ return this->open(headers);
+}
+
+int url::open(map<string, string> headers) {
char *joined_headers = NULL;
+ string request;
int sock = -1;
- /* in case of a file:// url we open the file and return a hande to it */
- if (!strcmp(self->scheme,"file"))
- return open(self->path, O_RDONLY);
+ // In case of a file:// url we open the file and return a handle to it
+ if (this->scheme == "file")
+ return ::open(this->path.c_str(), O_RDONLY);
- /* DNS lookup of host */
- if (!px_url_get_ips(self, true)) goto error;
+ // DNS lookup of host
+ if (!this->get_ips(true)) goto error;
- /* 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);
+ // Iterate through each IP trying to make a connection
+ for (vector<const sockaddr*>::iterator i = this->ips->begin() ; i != this->ips->end() ; i++) {
+ sock = socket((*i)->sa_family, SOCK_STREAM, 0);
if (sock < 0) continue;
- if (self->ips[i]->sa_family == AF_INET &&
- !connect(sock, self->ips[i], sizeof(struct sockaddr_in)))
+ if ((*i)->sa_family == AF_INET &&
+ !connect(sock, *i, sizeof(struct sockaddr_in)))
break;
- else if (self->ips[i]->sa_family == AF_INET6 &&
- !connect(sock, self->ips[i], sizeof(struct sockaddr_in6)))
+ else if ((*i)->sa_family == AF_INET6 &&
+ !connect(sock, *i, sizeof(struct sockaddr_in6)))
break;
close(sock);
@@ -123,252 +221,90 @@ px_url_get(pxURL *self, const char **headers)
}
if (sock < 0) goto error;
- /* Merge optional headers */
- if (headers)
- {
- joined_headers = px_strjoin(headers, "\r\n");
- if (!joined_headers) goto error;
- }
- else
- joined_headers = px_strdup("");
+ // Set any required headers
+ headers["Host"] = this->host;
- /* 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);
+ // Build the request string
+ request = "GET " + this->path + " HTTP/1.1\r\n";
+ for (map<string, string>::iterator it = headers.begin() ; it != headers.end() ; it++)
+ request += it->first + ": " + it->second + "\r\n";
+ request += "\r\n";
- /* Send HTTP request */
- if (send(sock, request, strlen(request), 0) != strlen(request)) goto error;
- px_free(request); request = NULL;
+ // Send HTTP request
+ if (send(sock, request.c_str(), request.size(), 0) != request.size()) goto error;
- /* Return the socket, which is ready for reading the response */
+ // Return the socket, which is ready for reading the response
return sock;
error:
if (sock >= 0) close(sock);
- px_free(request);
return -1;
}
-/**
- * @return The default port for this type of pxURL
- */
-static int
-px_url_get_default_port(pxURL *self)
-{
- struct servent *serv;
- if ((serv = getservbyname(self->scheme, NULL))) return ntohs(serv->s_port);
- return 0;
-}
-
-/**
- * @return Host portion of the pxURL
- */
-const char *
-px_url_get_host(pxURL *self)
-{
- if (!self) return NULL;
- return self->host;
+string url::get_host() const {
+ return this->host;
}
-/**
- * Get the IP addresses of the hostname in this pxURL.
- * @usedns Should we look up hostnames in DNS?
- * @return IP addresses of the host in the pxURL.
- */
-const struct sockaddr **
-px_url_get_ips(pxURL *self, bool usedns)
-{
- if (!self) return NULL;
-
- /* Check the cache */
- if (self->ips) return (const struct sockaddr **) self->ips;
+const vector<const sockaddr*>* url::get_ips(bool usedns) {
+ // Check the cache
+ if (this->ips) return (const vector<const sockaddr*>*) this->ips;
- /* Check without DNS first */
- if (usedns && px_url_get_ips(self, false)) return (const struct sockaddr **) self->ips;
+ // Check without DNS first
+ if (usedns && this->get_ips(false)) return (const vector<const sockaddr*>*) this->ips;
- /* Check DNS for IPs */
- struct addrinfo *info;
+ // Check DNS for IPs
+ struct addrinfo* info;
struct addrinfo flags;
flags.ai_family = AF_UNSPEC;
flags.ai_socktype = 0;
flags.ai_protocol = 0;
flags.ai_flags = AI_NUMERICHOST;
- if (!getaddrinfo(px_url_get_host(self), NULL, usedns ? NULL : &flags, &info))
- {
- struct addrinfo *first = info;
- int count;
-
- /* Count how many IPs we got back */
- for (count=0 ; info ; info = info->ai_next)
- count++;
-
- /* Copy the sockaddr's into self->ips */
- info = first;
- self->ips = (struct sockaddr **) px_malloc0(sizeof(struct sockaddr *) * ++count);
- for (int i=0 ; info ; info = info->ai_next)
- {
- if (info->ai_addr->sa_family == AF_INET)
- {
- self->ips[i] = (struct sockaddr *) px_malloc0(sizeof(struct sockaddr_in));
- memcpy(self->ips[i], info->ai_addr, sizeof(struct sockaddr_in));
- ((struct sockaddr_in *) self->ips[i++])->sin_port = htons(self->port);
- }
- else if (info->ai_addr->sa_family == AF_INET6)
- {
- self->ips[i] = (struct sockaddr *) px_malloc0(sizeof(struct sockaddr_in6));
- memcpy(self->ips[i], info->ai_addr, sizeof(struct sockaddr_in6));
- ((struct sockaddr_in6 *) self->ips[i++])->sin6_port = htons(self->port);
+ if (!getaddrinfo(this->host.c_str(), NULL, usedns ? NULL : &flags, &info)) {
+ struct addrinfo* first = info;
+
+ // Create our vector since we actually have a result
+ this->ips = new vector<const sockaddr*>();
+
+ // Copy the sockaddr's into this->ips
+ for ( ; info ; info = info->ai_next) {
+ if (info->ai_addr->sa_family == AF_INET || info->ai_addr->sa_family == AF_INET6) {
+ this->ips->push_back(_copyaddr(*(info->ai_addr)));
+ ((sockaddr_in*)(*(this->ips))[this->ips->size()-1])->sin_port = htons(this->port);
}
}
freeaddrinfo(first);
- return (const struct sockaddr **) self->ips;
+ return (const vector<const sockaddr*>*) this->ips;
}
- /* No addresses found */
+ // No addresses found
return NULL;
}
-/**
- * @return Password portion of the pxURL
- */
-const char *
-px_url_get_password(pxURL *self)
-{
- if (!self) return NULL;
- return self->password;
+string url::get_password() const {
+ return this->pass;
}
-/**
- * @return Path portion of the pxURL
- */
-const char *
-px_url_get_path(pxURL *self)
-{
- if (!self) return NULL;
- return self->path;
+string url::get_path() const {
+ return this->path;
}
-/**
- * @return Port portion of the pxURL
- */
-int
-px_url_get_port(pxURL *self)
-{
- if (!self) return 0;
- return self->port;
+int url::get_port() const {
+ return this->port;
}
-/**
- * @return Scheme portion of the pxURL
- */
-__attribute__ ((visibility("default")))
-const char *
-px_url_get_scheme(pxURL *self)
-{
- if (!self) return NULL;
- return self->scheme;
+string url::get_scheme() const {
+ return this->scheme;
}
-/**
- * @return Username portion of the pxURL
- */
-const char *
-px_url_get_username(pxURL *self)
-{
- if (!self) return NULL;
- return self->username;
+string url::get_username() const {
+ return this->user;
}
-/**
- * @url String used to create the new pxURL object
- * @return New pxURL object
- */
-pxURL *
-px_url_new(const char *url)
-{
- bool port_specified;
- if (!url) return NULL;
- const char *start = url;
-
- /* Allocate pxURL */
- pxURL *self = (pxURL *) px_malloc0(sizeof(pxURL));
-
- /* Get scheme */
- if (!strstr(start, "://")) goto error;
- self->scheme = px_strndup(start, strstr(start, "://") - start);
- start += strlen(self->scheme) + 3;
-
- /* If we have a username and password */
- if (strchr(start, '@') && (strchr(start, '/') > strchr(start, '@') || strchr(start, '/') == NULL))
- {
- if (!strchr(start, ':')) goto error; // Can't find user/pass delimiter
- self->username = px_strndup(start, strchr(start, ':') - start);
- start += strlen(self->username) + 1;
- self->password = px_strndup(start, strchr(start, '@') - start);
- start += strlen(self->password) + 1;
- }
-
- /* Get host */
- self->host = px_strdup(start);
-
- /* 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 */
- port_specified = false;
- if (strchr(self->host, ':')) {
- if (!atoi(strchr(self->host, ':')+1)) goto error;
- self->port = atoi(strchr(self->host, ':')+1);
- *(strchr(self->host, ':')) = 0;
- port_specified = true;
- }
- else
- self->port = px_url_get_default_port(self);
-
- /* Make sure we have a real host */
- if (!strcmp(self->host, "") && strcmp(self->scheme, "file")) goto error;
-
- /* Verify by re-assembly */
- self->url = (char *) px_malloc0(strlen(url) + 1);
- if (self->username && self->password)
- snprintf(self->url, strlen(url) + 1, "%s://%s:%s@%s", self->scheme, self->username, self->password, self->host);
- else
- snprintf(self->url, strlen(url) + 1, "%s://%s", self->scheme, self->host);
- if (port_specified)
- snprintf(self->url + strlen(self->url), strlen(url) + 1 - strlen(self->url), ":%d%s", self->port, self->path);
- else
- snprintf(self->url + strlen(self->url), strlen(url) + 1 - strlen(self->url), "%s", self->path);
- if (strcmp(self->url, url)) goto error;
-
- return self;
-
- error:
- px_url_free(self);
- return NULL;
+string url::to_string() const {
+ return this->orig;
}
-/**
- * @return String representation of the pxURL
- */
-const char *
-px_url_to_string(pxURL *self)
-{
- if (!self) return NULL;
- return self->url;
}
-
-/**
- * @return true if the URLs are the same, else false
- */
-bool
-px_url_equals(pxURL *self, const pxURL *other)
-{
- return !strcmp(px_url_to_string(self), px_url_to_string((pxURL*) other));
+}
}
diff --git a/libproxy/url.hpp b/libproxy/url.hpp
index d12fc22..27b4711 100644
--- a/libproxy/url.hpp
+++ b/libproxy/url.hpp
@@ -17,91 +17,72 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
******************************************************************************/
-#ifndef URL_H_
-#define URL_H_
-
-#include "stdbool.h" /* For type bool */
-
-/**
- * WPAD object. All fields are private.
- */
-typedef struct _pxURL pxURL;
-
-/**
- * @return Frees the pxURL
- */
-void px_url_free(pxURL *self);
-
-/**
- * Tells whether or not a pxURL string has valid syntax
- * @return true if the pxURL is valid, otherwise false
- */
-__attribute__ ((visibility("default")))
-bool px_url_is_valid(const char *url);
-
-/**
- * Sends a get request for the pxURL.
- * @headers A list of headers to be included in the request.
- * @return Socket to read the response on.
- */
-int px_url_get(pxURL *self, const char **headers);
-
-/**
- * @return Host portion of the pxURL
- */
-__attribute__ ((visibility("default")))
-const char *px_url_get_host(pxURL *self);
-
-/**
- * Get the IP addresses of the hostname in this pxURL.
- * @usedns Should we look up hostnames in DNS?
- * @return IP addresses of the host in the pxURL.
- */
-__attribute__ ((visibility("default")))
-const struct sockaddr **px_url_get_ips(pxURL *self, bool usedns);
-
-/**
- * @return Password portion of the pxURL
- */
-const char *px_url_get_password(pxURL *self);
-
-/**
- * @return Path portion of the pxURL
- */
-const char *px_url_get_path(pxURL *self);
-
-/**
- * @return Port portion of the pxURL
- */
-__attribute__ ((visibility("default")))
-int px_url_get_port(pxURL *self);
-
-/**
- * @return Scheme portion of the pxURL
- */
-__attribute__ ((visibility("default")))
-const char *px_url_get_scheme(pxURL *self);
-
-/**
- * @return Username portion of the pxURL
- */
-const char *px_url_get_username(pxURL *self);
-
-/**
- * @url String used to create the new pxURL object
- * @return New pxURL object
- */
-pxURL *px_url_new(const char *url);
-
-/**
- * @return String representation of the pxURL
- */
-__attribute__ ((visibility("default")))
-const char *px_url_to_string(pxURL *self);
-
-/**
- * @return true if the URLs are the same, else false
- */
-bool px_url_equals(pxURL *self, const pxURL *other);
-
-#endif /*URL_H_*/
+#ifndef URL_HPP_
+#define URL_HPP_
+
+#ifdef _WIN32
+#define _WIN32_WINNT 0x0501
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#else
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#endif
+
+#include <map>
+#include <stdexcept>
+#include <string>
+#include <vector>
+
+namespace com {
+namespace googlecode {
+namespace libproxy {
+
+using namespace std;
+
+class parse_error : public runtime_error {
+public:
+ parse_error(const string& __arg): runtime_error(__arg) {}
+};
+
+class url {
+public:
+ static bool is_valid(const string url);
+
+ ~url();
+ url(const url& url);
+ url(string url) throw (parse_error, logic_error);
+ bool operator==(const url& url) const;
+ url& operator=(const url& url);
+ url& operator=(string url) throw (parse_error);
+
+ int open();
+ int open(map<string, string> headers);
+
+ string get_host() const;
+ const vector<const sockaddr*>* get_ips(bool usedns);
+ string get_password() const;
+ string get_path() const;
+ int get_port() const;
+ string get_scheme() const;
+ string get_username() const;
+ string to_string() const;
+
+private:
+ string host;
+ vector<const sockaddr*>* ips;
+ string pass;
+ string path;
+ int port;
+ string scheme;
+ string orig;
+ string user;
+};
+
+}
+}
+}
+
+#endif /*URL_HPP_*/
diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt
index 4f27eb7..eebe337 100644
--- a/utils/CMakeLists.txt
+++ b/utils/CMakeLists.txt
@@ -5,8 +5,5 @@ add_executable(proxy proxy.c)
target_link_libraries(proxy libproxy)
install(TARGETS proxy RUNTIME DESTINATION ${rbindir})
-add_executable(iniparse iniparse.c)
-target_link_libraries(iniparse libproxy)
-
-set_target_properties(proxy iniparse PROPERTIES COMPILE_FLAGS "-g -std=c99")
+set_target_properties(proxy PROPERTIES COMPILE_FLAGS "-g -std=c99")
diff --git a/utils/iniparse.c b/utils/iniparse.c
deleted file mode 100644
index 211f835..0000000
--- a/utils/iniparse.c
+++ /dev/null
@@ -1,23 +0,0 @@
-#include <stdio.h>
-
-#include "../libproxy/strdict.h"
-#include "../libproxy/config_file.h"
-
-int main(int argc, char **argv) {
- if (argc != 4) {
- printf("You started with %d parameters.\n", argc);
- printf("Wrong invocation. Start with 3 parameters:\n");
- printf("1. path to config file\n2. Section name in conf file.\n3. Keyname to read.\n");
- printf("iniparse will return \"key = value\" if found\n.");
- return 2;
- }
- pxConfigFile* cf = px_config_file_new(argv[1]);
- if (!cf) {
- printf("Could not find conf file.\n.");
- return 1;
- }
- char* val1 = px_config_file_get_value(cf, argv[2], argv[3]);
- printf("%s = %s", argv[3] == NULL ? "NULL" : argv[3], val1 == NULL ? "NULL" : val1);
- px_config_file_free(cf);
- return 0;
-}