summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornicolas.dufresne@gmail.com <nicolas.dufresne@gmail.com@c587cffe-e639-0410-9787-d7902ae8ed56>2012-07-05 16:01:12 +0000
committernicolas.dufresne@gmail.com <nicolas.dufresne@gmail.com@c587cffe-e639-0410-9787-d7902ae8ed56>2012-07-05 16:01:12 +0000
commit61048ad16366884c6a9b908a90fb56c875fe46c7 (patch)
treeb1c3384447f88766ab15579f536bfabc9201007f
parent75d11a34620966a07638337959aa8cd8c9d89893 (diff)
downloadlibproxy-61048ad16366884c6a9b908a90fb56c875fe46c7.tar.gz
Allow multiple result to be returned from static config
git-svn-id: http://libproxy.googlecode.com/svn/trunk@842 c587cffe-e639-0410-9787-d7902ae8ed56
-rw-r--r--libproxy/extension_config.cpp4
-rw-r--r--libproxy/extension_config.hpp6
-rw-r--r--libproxy/extension_ignore.hpp2
-rw-r--r--libproxy/modules/config_envvar.cpp15
-rw-r--r--libproxy/modules/config_gnome.cpp107
-rw-r--r--libproxy/modules/config_gnome3.cpp105
-rw-r--r--libproxy/modules/config_kde4.cpp23
-rw-r--r--libproxy/modules/config_macosx.cpp25
-rw-r--r--libproxy/modules/config_sysconfig.cpp21
-rw-r--r--libproxy/modules/config_w32reg.cpp23
-rw-r--r--libproxy/modules/ignore_domain.cpp2
-rw-r--r--libproxy/modules/ignore_hostname.cpp2
-rw-r--r--libproxy/modules/ignore_ip.cpp2
-rw-r--r--libproxy/modules/wpad_dns_alias.cpp16
-rw-r--r--libproxy/proxy.cpp169
15 files changed, 292 insertions, 230 deletions
diff --git a/libproxy/extension_config.cpp b/libproxy/extension_config.cpp
index 6cefd30..075b91a 100644
--- a/libproxy/extension_config.cpp
+++ b/libproxy/extension_config.cpp
@@ -20,11 +20,11 @@
#include "extension_config.hpp"
using namespace libproxy;
-string config_extension::get_ignore(url) {
+string config_extension::get_ignore(const url&) {
return "";
}
-bool config_extension::set_creds(url, string, string) {
+bool config_extension::set_creds(const url&, const string&, const string&) {
return false;
}
diff --git a/libproxy/extension_config.hpp b/libproxy/extension_config.hpp
index a24add8..79f1624 100644
--- a/libproxy/extension_config.hpp
+++ b/libproxy/extension_config.hpp
@@ -31,11 +31,11 @@ using namespace libmodman;
class DLL_PUBLIC config_extension : public extension<config_extension> {
public:
// Abstract methods
- virtual url get_config(url dst) throw (runtime_error)=0;
+ virtual vector<url> get_config(const url &dst) throw (runtime_error)=0;
// Virtual methods
- virtual string get_ignore(url dst);
- virtual bool set_creds(url proxy, string username, string password);
+ virtual string get_ignore(const url &dst);
+ virtual bool set_creds(const url &proxy, const string &username, const string &password);
// Final methods
bool get_valid();
diff --git a/libproxy/extension_ignore.hpp b/libproxy/extension_ignore.hpp
index 7659bf3..63845fe 100644
--- a/libproxy/extension_ignore.hpp
+++ b/libproxy/extension_ignore.hpp
@@ -30,7 +30,7 @@ using namespace libmodman;
class DLL_PUBLIC ignore_extension : public extension<ignore_extension> {
public:
- virtual bool ignore(url& dst, string ignorestr)=0;
+ virtual bool ignore(url& dst, const string &ignorestr)=0;
};
}
diff --git a/libproxy/modules/config_envvar.cpp b/libproxy/modules/config_envvar.cpp
index f1c4e46..37713c7 100644
--- a/libproxy/modules/config_envvar.cpp
+++ b/libproxy/modules/config_envvar.cpp
@@ -24,17 +24,18 @@ using namespace libproxy;
class envvar_config_extension : public config_extension {
public:
- url get_config(url url) throw (runtime_error) {
- char *proxy = NULL;
+ vector<url> get_config(const url &dst) throw (runtime_error) {
+ const char *proxy = NULL;
+ vector<url> response;
// If the URL is an ftp url, try to read the ftp proxy
- if (url.get_scheme() == "ftp") {
+ if (dst.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 (dst.get_scheme() == "https") {
if (!(proxy = getenv("https_proxy")))
proxy = getenv("HTTPS_PROXY");
}
@@ -47,10 +48,12 @@ public:
if (!proxy)
throw runtime_error("Unable to read configuration");
- return libproxy::url(proxy);
+
+ response.push_back(url(proxy));
+ return response;
}
- string get_ignore(url) {
+ string get_ignore(const url&) {
char *ignore = getenv("no_proxy");
ignore = ignore ? ignore : getenv("NO_PROXY");
return string(ignore ? ignore : "");
diff --git a/libproxy/modules/config_gnome.cpp b/libproxy/modules/config_gnome.cpp
index 1599e62..027e5e7 100644
--- a/libproxy/modules/config_gnome.cpp
+++ b/libproxy/modules/config_gnome.cpp
@@ -123,7 +123,7 @@ static int popen2(const char *program, FILE** read, FILE** write, pid_t* pid) {
}
}
-static inline uint16_t get_port(string &port)
+static inline uint16_t get_port(const string &port)
{
uint16_t retval;
@@ -133,6 +133,22 @@ static inline uint16_t get_port(string &port)
return retval;
}
+void store_response(const string &type,
+ const string &host,
+ const string &port,
+ bool auth,
+ const string &username,
+ const string &password,
+ vector<url> &response) {
+ if (host != "" && get_port(port) != 0) {
+ string tmp = type + "://";
+ if (auth)
+ tmp += username + ":" + password + "@";
+ tmp += host + ":" + port;
+ response.push_back(url(tmp));
+ }
+}
+
class gnome_config_extension : public config_extension {
public:
gnome_config_extension() {
@@ -173,10 +189,12 @@ public:
kill(this->pid, SIGTERM);
}
- url get_config(url dest) throw (runtime_error) {
+ vector<url> get_config(const url &dest) throw (runtime_error) {
// Check for changes in the config
fd_set rfds;
struct timeval timeout = { 0, 0 };
+ vector<url> response;
+
FD_ZERO(&rfds);
FD_SET(fileno(this->read), &rfds);
if (select(fileno(this->read)+1, &rfds, NULL, NULL, &timeout) > 0)
@@ -185,76 +203,53 @@ public:
// Mode is wpad:// or pac+http://...
if (this->data[PROXY_MODE] == "auto") {
string pac = this->data[PROXY_AUTOCONFIG_URL];
- return url::is_valid(pac) ? url(string("pac+") + pac) : url("wpad://");
+ response.push_back(url::is_valid(pac) ? url(string("pac+") + pac) : url("wpad://"));
+ return response;
}
// Mode is http://... or socks://...
else if (this->data[PROXY_MODE] == "manual") {
- string type, host, port;
bool auth = this->data[PROXY_USE_AUTHENTICATION] == "true";
string username = url::encode(this->data[PROXY_AUTH_USER], URL_ALLOWED_IN_USERINFO_ELEMENT);
string password = url::encode(this->data[PROXY_AUTH_PASSWORD], URL_ALLOWED_IN_USERINFO_ELEMENT);
- bool same_proxy = this->data[PROXY_SAME_FOR_ALL] == "true";
-
- // If socks is set use it (except when same_proxy is set)
- if (!same_proxy) {
- type = "socks";
- host = this->data[PROXY_SOCKS_HOST];
- port = this->data[PROXY_SOCKS_PORT];
- }
- if (host == "" || get_port(port) == 0) {
- // Get the per-scheme proxy settings
- if (dest.get_scheme() == "http") {
- type = "http";
- host = this->data[PROXY_HTTP_HOST];
- port = this->data[PROXY_HTTP_PORT];
- }
- else if (dest.get_scheme() == "https") {
- // It is expected that the configured server is an
- // HTTP server that support CONNECT method.
- type = "http";
- host = this->data[PROXY_SECURE_HOST];
- port = this->data[PROXY_SECURE_PORT];
- }
- else if (dest.get_scheme() == "ftp") {
- // It is expected that the configured server is an
- // HTTP server that handles proxying FTP URLs
- // (e.g. request with header "Host: ftp://ftp.host.org")
- type = "http";
- host = this->data[PROXY_FTP_HOST];
- port = this->data[PROXY_FTP_PORT];
- }
-
- // If no proxy is set and we have the same_proxy option
- // enabled try socks at the end only.
- if (same_proxy && (host == "" || get_port(port) == 0)) {
- type = "socks";
- host = this->data[PROXY_SOCKS_HOST];
- port = this->data[PROXY_SOCKS_PORT];
- }
- }
-
-
- // If host and port were found, build config url
- if (host != "" && get_port(port) != 0) {
- string tmp = type + "://";
- if (auth)
- tmp += username + ":" + password + "@";
- tmp += host + ":" + port;
- return url(tmp);
+ // Get the per-scheme proxy settings
+ if (dest.get_scheme() == "http")
+ store_response("http", this->data[PROXY_HTTP_HOST],
+ this->data[PROXY_HTTP_PORT], auth, username, password, response);
+ else if (dest.get_scheme() == "https")
+ // It is expected that the configured server is an
+ // HTTP server that support CONNECT method.
+ store_response("http", this->data[PROXY_SECURE_HOST],
+ this->data[PROXY_SECURE_PORT], auth, username, password, response);
+ else if (dest.get_scheme() == "ftp")
+ // It is expected that the configured server is an
+ // HTTP server that handles proxying FTP URLs
+ // (e.g. request with header "Host: ftp://ftp.host.org")
+ store_response("http", this->data[PROXY_FTP_HOST],
+ this->data[PROXY_FTP_PORT], auth, username, password, response);
+
+ store_response("socks", this->data[PROXY_SOCKS_HOST],
+ this->data[PROXY_SOCKS_PORT], auth, username, password, response);
+
+ // In case nothing matched, try HTTP Connect and fallback to direct.
+ // If there is not secure HTTP proxy, this will only add direct:// to
+ // the response
+ if (response.size() == 0) {
+ store_response("http", this->data[PROXY_SECURE_HOST],
+ this->data[PROXY_SECURE_PORT], auth, username, password, response);
+ response.push_back(url("direct://"));
}
}
- // Mode is direct://
- return url("direct://");
+ return response;
}
- string get_ignore(url) {
+ string get_ignore(const url&) {
return this->data[PROXY_IGNORE_HOSTS];
}
- bool set_creds(url /*proxy*/, string username, string password) {
+ virtual bool set_creds(url /*proxy*/, string username, string password) {
string auth = PROXY_USE_AUTHENTICATION "\ttrue\n";
string user = string(PROXY_AUTH_USER "\t") + username + "\n";
string pass = string(PROXY_AUTH_PASSWORD "\t") + password + "\n";
diff --git a/libproxy/modules/config_gnome3.cpp b/libproxy/modules/config_gnome3.cpp
index 07f9f14..00c0146 100644
--- a/libproxy/modules/config_gnome3.cpp
+++ b/libproxy/modules/config_gnome3.cpp
@@ -113,7 +113,7 @@ static int popen2(const char *program, FILE** read, FILE** write, pid_t* pid) {
}
}
-static inline uint16_t get_port(string &port)
+static inline uint16_t get_port(const string &port)
{
uint16_t retval;
@@ -163,10 +163,28 @@ public:
kill(this->pid, SIGTERM);
}
- url get_config(url dest) throw (runtime_error) {
+ void store_response(const string &type,
+ const string &host,
+ const string &port,
+ bool auth,
+ const string &username,
+ const string &password,
+ vector<url> &response) {
+ if (host != "" && get_port(port) != 0) {
+ string tmp = type + "://";
+ if (auth)
+ tmp += username + ":" + password + "@";
+ tmp += host + ":" + port;
+ response.push_back(url(tmp));
+ }
+ }
+
+ vector<url> get_config(const url &dest) throw (runtime_error) {
// Check for changes in the config
fd_set rfds;
struct timeval timeout = { 0, 0 };
+ vector<url> response;
+
FD_ZERO(&rfds);
FD_SET(fileno(this->read), &rfds);
if (select(fileno(this->read)+1, &rfds, NULL, NULL, &timeout) > 0)
@@ -175,72 +193,49 @@ public:
// Mode is wpad:// or pac+http://...
if (this->data[PROXY_MODE] == "auto") {
string pac = this->data[PROXY_AUTOCONFIG_URL];
- return url::is_valid(pac) ? url(string("pac+") + pac) : url("wpad://");
+ response.push_back(url::is_valid(pac) ? url(string("pac+") + pac) : url("wpad://"));
+ return response;
}
// Mode is http://... or socks://...
else if (this->data[PROXY_MODE] == "manual") {
- string type, host, port;
bool auth = this->data[PROXY_USE_AUTHENTICATION] == "true";
string username = url::encode(this->data[PROXY_AUTH_USER], URL_ALLOWED_IN_USERINFO_ELEMENT);
string password = url::encode(this->data[PROXY_AUTH_PASSWORD], URL_ALLOWED_IN_USERINFO_ELEMENT);
- bool same_proxy = this->data[PROXY_SAME_FOR_ALL] == "true";
-
- // If socks is set use it (except when same_proxy is set)
- if (!same_proxy) {
- type = "socks";
- host = this->data[PROXY_SOCKS_HOST];
- port = this->data[PROXY_SOCKS_PORT];
- }
- if (host == "" || get_port(port) == 0) {
- // Get the per-scheme proxy settings
- if (dest.get_scheme() == "http") {
- type = "http";
- host = this->data[PROXY_HTTP_HOST];
- port = this->data[PROXY_HTTP_PORT];
- }
- else if (dest.get_scheme() == "https") {
- // It is expected that the configured server is an
- // HTTP server that support CONNECT method.
- type = "http";
- host = this->data[PROXY_SECURE_HOST];
- port = this->data[PROXY_SECURE_PORT];
- }
- else if (dest.get_scheme() == "ftp") {
- // It is expected that the configured server is an
- // HTTP server that handles proxying FTP URLs
- // (e.g. request with header "Host: ftp://ftp.host.org")
- type = "http";
- host = this->data[PROXY_FTP_HOST];
- port = this->data[PROXY_FTP_PORT];
- }
-
- // If no proxy is set and we have the same_proxy option
- // enabled try socks at the end only.
- if (same_proxy && (host == "" || get_port(port) == 0)) {
- type = "socks";
- host = this->data[PROXY_SOCKS_HOST];
- port = this->data[PROXY_SOCKS_PORT];
- }
- }
-
-
- // If host and port were found, build config url
- if (host != "" && get_port(port) != 0) {
- string tmp = type + "://";
- if (auth)
- tmp += username + ":" + password + "@";
- tmp += host + ":" + port;
- return url(tmp);
+ // Get the per-scheme proxy settings
+ if (dest.get_scheme() == "http")
+ store_response("http", this->data[PROXY_HTTP_HOST],
+ this->data[PROXY_HTTP_PORT], auth, username, password, response);
+ else if (dest.get_scheme() == "https")
+ // It is expected that the configured server is an
+ // HTTP server that support CONNECT method.
+ store_response("http", this->data[PROXY_SECURE_HOST],
+ this->data[PROXY_SECURE_PORT], auth, username, password, response);
+ else if (dest.get_scheme() == "ftp")
+ // It is expected that the configured server is an
+ // HTTP server that handles proxying FTP URLs
+ // (e.g. request with header "Host: ftp://ftp.host.org")
+ store_response("http", this->data[PROXY_FTP_HOST],
+ this->data[PROXY_FTP_PORT], auth, username, password, response);
+
+ store_response("socks", this->data[PROXY_SOCKS_HOST],
+ this->data[PROXY_SOCKS_PORT], auth, username, password, response);
+
+ // In case nothing matched, try HTTP Connect and fallback to direct.
+ // If there is not secure HTTP proxy, this will only add direct:// to
+ // the response
+ if (response.size() == 0) {
+ store_response("http", this->data[PROXY_SECURE_HOST],
+ this->data[PROXY_SECURE_PORT], auth, username, password, response);
+ response.push_back(url("direct://"));
}
}
- // Mode is direct://
- return url("direct://");
+ return response;
}
- string get_ignore(url) {
+ string get_ignore(const url&) {
return this->data[PROXY_IGNORE_HOSTS];
}
diff --git a/libproxy/modules/config_kde4.cpp b/libproxy/modules/config_kde4.cpp
index bbf1910..f23320d 100644
--- a/libproxy/modules/config_kde4.cpp
+++ b/libproxy/modules/config_kde4.cpp
@@ -46,9 +46,11 @@ public:
delete this->cfg;
}
- url get_config(url dst) throw (runtime_error) {
+ vector<url> get_config(const url &dst) throw (runtime_error) {
string tmp;
QString prxy;
+ vector<url> response;
+
switch (this->grp->readEntry("ProxyType", 0)) {
case 1: // Use a manual proxy
prxy = this->grp->readEntry(QString(dst.get_scheme().c_str()) + "Proxy", "");
@@ -62,26 +64,31 @@ public:
};
// The result of toLatin1() is undefined for non-Latin1 strings.
// However, KDE saves this entry using IDN and percent-encoding, so no problem...
- return string(prxy.toLatin1().data());
+ response.push_back(string(prxy.toLatin1().data()));
+ break;
case 2: // Use a manual PAC
// The result of toLatin1() is undefined for non-Latin1 strings.
// However, KDE saves this entry using IDN and percent-encoding, so no problem...
tmp = string(this->grp->readEntry("Proxy Config Script", "").toLatin1().data());
if (url::is_valid("pac+" + tmp))
- return url("pac+" + tmp);
- return url("wpad://");
+ response.push_back(url("pac+" + tmp));
+ else
+ response.push_back(string("wpad://"));
+ break;
case 3: // Use WPAD
- return url("wpad://");
+ response.push_back(string("wpad://"));
+ break;
case 4: // Use envvar
throw runtime_error("User config_envvar"); // We'll bypass this config plugin and let the envvar plugin work
default:
- return url("direct://");
+ response.push_back(url("direct://"));
+ break;
};
- // Never get here!
+ return response;
}
- string get_ignore(url /*dst*/) {
+ string get_ignore(const url& /*dst*/) {
// Apply ignore list only for manual proxy configuration
if (this->grp->readEntry("ProxyType", 0) == 1) {
string prefix = this->grp->readEntry("ReversedException", false) ? "-" : "";
diff --git a/libproxy/modules/config_macosx.cpp b/libproxy/modules/config_macosx.cpp
index c675662..1c43000 100644
--- a/libproxy/modules/config_macosx.cpp
+++ b/libproxy/modules/config_macosx.cpp
@@ -114,40 +114,45 @@ static string capitalize(string str) {
class macosx_config_extension : public config_extension {
public:
- url get_config(url url) throw (runtime_error) {
+ vector<url> get_config(const url &url) throw (runtime_error) {
string tmp;
CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL);
+ vector<url> response;
+
if (!proxies) throw runtime_error("Unable to fetch proxy configuration");
// wpad://
if (getbool(proxies, "ProxyAutoDiscoveryEnable")) {
CFRelease(proxies);
- return libproxy::url(string("wpad://"));
+ response.push_back(url("wpad://"));
}
// pac+http://...
- if (getbool(proxies, "ProxyAutoConfigEnable") &&
+ else if (getbool(proxies, "ProxyAutoConfigEnable") &&
(tmp = str(getobj<CFStringRef>(proxies, "ProxyAutoConfigURLString"))) != "" &&
url::is_valid(tmp)) {
CFRelease(proxies);
- return libproxy::url(string("pac+") + tmp);
+ response.push_back(url(string("pac+") + tmp));
}
// http:// or socks:// (TODO: gopher:// and rtsp:// ???)
- if ((protocol_url(proxies, toupper(url.get_scheme()), tmp) && url::is_valid(tmp)) ||
+ else if ((protocol_url(proxies, toupper(url.get_scheme()), tmp) && url::is_valid(tmp)) ||
(protocol_url(proxies, capitalize(url.get_scheme()), tmp) && url::is_valid(tmp)) ||
(protocol_url(proxies, toupper("http"), tmp) && url::is_valid(tmp)) ||
(protocol_url(proxies, toupper("socks"), tmp) && url::is_valid(tmp))) {
CFRelease(proxies);
- return libproxy::url(tmp);
+ response.push_back(url(tmp));
+ }
+ else {
+ // direct://
+ CFRelease(proxies);
+ response.push_back(url("direct://"));
}
- // direct://
- CFRelease(proxies);
- return libproxy::url(string("direct://"));
+ return response;
}
- string get_ignore(url) {
+ string get_ignore(const url&) {
// Get config dict
CFDictionaryRef proxies = SCDynamicStoreCopyProxies(NULL);
if (!proxies) return "";
diff --git a/libproxy/modules/config_sysconfig.cpp b/libproxy/modules/config_sysconfig.cpp
index 6e97ae8..b7985ae 100644
--- a/libproxy/modules/config_sysconfig.cpp
+++ b/libproxy/modules/config_sysconfig.cpp
@@ -124,20 +124,24 @@ public:
~sysconfig_config_extension() {
}
- url get_config(url url) throw (runtime_error) {
+ vector<url> get_config(const url &dst) throw (runtime_error) {
map<string,string>::const_iterator it = _data.find("PROXY_ENABLED");
- if (it != _data.end() && it->second == "no")
- return libproxy::url("direct://");
+ vector<url> response;
+
+ if (it != _data.end() && it->second == "no") {
+ response.push_back(url("direct://"));
+ return response;
+ }
string key;
string proxy;
// If the URL is an ftp url, try to read the ftp proxy
- if (url.get_scheme() == "ftp")
+ if (dst.get_scheme() == "ftp")
key = "FTP_PROXY";
- else if (url.get_scheme() == "http")
+ else if (dst.get_scheme() == "http")
key = "HTTP_PROXY";
- else if (url.get_scheme() == "https")
+ else if (dst.get_scheme() == "https")
key = "HTTPS_PROXY";
it = _data.find(key);
@@ -147,10 +151,11 @@ public:
if (proxy.empty())
throw runtime_error("Unable to read configuration");
- return libproxy::url(proxy);
+ response.push_back(url(proxy));
+ return response;
}
- string get_ignore(url) {
+ string get_ignore(const url&) {
map<string,string>::const_iterator it = _data.find("NO_PROXY");
if (it != _data.end())
return it->second;
diff --git a/libproxy/modules/config_w32reg.cpp b/libproxy/modules/config_w32reg.cpp
index 0111c33..fc49e41 100644
--- a/libproxy/modules/config_w32reg.cpp
+++ b/libproxy/modules/config_w32reg.cpp
@@ -108,22 +108,24 @@ static map<string, string> parse_manual(string data) {
class w32reg_config_extension : public config_extension {
public:
- url get_config(url dst) throw (runtime_error) {
+ vector<url> get_config(const url &dst) throw (runtime_error) {
char *tmp = NULL;
uint32_t enabled = 0;
+ vector<url> response;
// WPAD
if (is_enabled(W32REG_OFFSET_WPAD)) {
- return url("wpad://");
+ response.push_back(url("wpad://"));
+ return response;
}
// 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);
+ response.push_back(url(string("pac+") + tmp));
delete tmp;
- return cfg;
+ return response;
}
// Manual proxy
@@ -135,22 +137,25 @@ public:
// First we look for an exact match
if (manual.find(dst.get_scheme()) != manual.end())
- return manual[dst.get_scheme()];
+ response.push_back(manual[dst.get_scheme()]);
// Next we look for http
else if (manual.find("http") != manual.end())
- return manual["http"];
+ response.push_back(manual["http"]);
// Last we look for socks
else if (manual.find("socks") != manual.end())
- return manual["socks"];
+ response.push_back(manual["socks"]);
+
+ return response;
}
// Direct
- return url("direct://");
+ response.push_back(url("direct://"));
+ return response;
}
- string get_ignore(url dst) {
+ string get_ignore(const url &dst) {
char *tmp;
if (get_registry(W32REG_BASEKEY, "ProxyOverride", &tmp, NULL, NULL)) {
string po = tmp;
diff --git a/libproxy/modules/ignore_domain.cpp b/libproxy/modules/ignore_domain.cpp
index 9ec28ce..f39e545 100644
--- a/libproxy/modules/ignore_domain.cpp
+++ b/libproxy/modules/ignore_domain.cpp
@@ -24,7 +24,7 @@ using namespace libproxy;
class domain_ignore_extension : public ignore_extension {
public:
- virtual bool ignore(url& url, string ignorestr) {
+ virtual bool ignore(url& url, const string &ignorestr) {
/* Get our URL's hostname and port */
string host = url.get_host();
int port = url.get_port();
diff --git a/libproxy/modules/ignore_hostname.cpp b/libproxy/modules/ignore_hostname.cpp
index c9a7621..6caa291 100644
--- a/libproxy/modules/ignore_hostname.cpp
+++ b/libproxy/modules/ignore_hostname.cpp
@@ -24,7 +24,7 @@ using namespace libproxy;
class hostname_ignore_extension : public ignore_extension {
public:
- virtual bool ignore(url& url, string ignorestr) {
+ virtual bool ignore(url& url, const string &ignorestr) {
if (ignorestr == "<local>" &&
url.get_host().find(':') == string::npos && // Make sure it's not IPv6
url.get_host().find('.') == string::npos)
diff --git a/libproxy/modules/ignore_ip.cpp b/libproxy/modules/ignore_ip.cpp
index c019fec..e1b99bd 100644
--- a/libproxy/modules/ignore_ip.cpp
+++ b/libproxy/modules/ignore_ip.cpp
@@ -113,7 +113,7 @@ sockaddr_from_cidr(sa_family_t af, uint8_t cidr)
class ip_ignore_extension : public ignore_extension {
public:
- virtual bool ignore(url& url, string ignore) {
+ virtual bool ignore(url& url, const string &ignore) {
bool result = false;
uint16_t port = 0;
const struct sockaddr *dst_ip = url.get_ips(false) ? url.get_ips(false)[0] : NULL;
diff --git a/libproxy/modules/wpad_dns_alias.cpp b/libproxy/modules/wpad_dns_alias.cpp
index ca89c36..449d8ee 100644
--- a/libproxy/modules/wpad_dns_alias.cpp
+++ b/libproxy/modules/wpad_dns_alias.cpp
@@ -22,9 +22,15 @@ using namespace libproxy;
class dns_alias_wpad_extension : public wpad_extension {
public:
- dns_alias_wpad_extension() { rewind(); }
- bool found() { return lastpac != NULL; }
- void rewind() { lasturl = NULL; lastpac = NULL; }
+ dns_alias_wpad_extension() : lasturl(NULL), lastpac(NULL) { }
+ bool found() { return lastpac != NULL; }
+
+ void rewind() {
+ if (lasturl) delete lasturl;
+ if (lastpac) delete lastpac;
+ lasturl = NULL;
+ lastpac = NULL;
+ }
url* next(char** pac) {
if (lasturl) return false;
@@ -32,8 +38,8 @@ public:
lasturl = new url("http://wpad/wpad.dat");
lastpac = *pac = lasturl->get_pac();
if (!lastpac) {
- delete lasturl;
- return NULL;
+ delete lasturl;
+ return NULL;
}
return lasturl;
diff --git a/libproxy/proxy.cpp b/libproxy/proxy.cpp
index e9e5026..6d048db 100644
--- a/libproxy/proxy.cpp
+++ b/libproxy/proxy.cpp
@@ -59,7 +59,13 @@ private:
void lock();
void unlock();
- void _get_proxies(url *realurl, vector<string> &response);
+ void check_network_topology();
+ void get_config(url &realurl, vector<url> &configs, string &ignore);
+ bool is_ignored(url &realurl, const string &ignore);
+ bool expand_wpad(const url &confurl);
+ bool expand_pac(url &configurl);
+ void run_pac(url &realurl, const url &confurl, vector<string> &response);
+ void clear_cache();
#ifdef WIN32
HANDLE mutex;
@@ -70,6 +76,7 @@ private:
char* pac;
url* pacurl;
bool wpad;
+ bool debug;
};
static bool istringcmp(string a, string b) {
@@ -79,18 +86,17 @@ static bool istringcmp(string a, string b) {
}
// Convert the PAC formatted response into our proxy URL array response
-static vector<string>
-format_pac_response(string response)
+static void format_pac_response(string response, vector<string> &retval)
{
- vector<string> retval;
-
// Skip ahead one character if we start with ';'
- if (response[0] == ';')
- return format_pac_response(response.substr(1));
+ if (response[0] == ';') {
+ format_pac_response(response.substr(1), retval);
+ return;
+ }
// If the string contains a delimiter (';')
if (response.find(';') != string::npos) {
- retval = format_pac_response(response.substr(response.find(';')+1));
+ format_pac_response(response.substr(response.find(';') + 1), retval);
response = response.substr(0, response.find(';'));
}
@@ -115,12 +121,12 @@ format_pac_response(string response)
retval.insert(retval.begin(), string("socks://") + server);
else if (istringcmp(method, "socks4") && url::is_valid("http://" + server))
retval.insert(retval.begin(), string("socks4://") + server);
+ else if (istringcmp(method, "socks4a") && url::is_valid("http://" + server))
+ retval.insert(retval.begin(), string("socks4a://") + server);
else if (istringcmp(method, "socks5") && url::is_valid("http://" + server))
retval.insert(retval.begin(), string("socks5://") + server);
else if (istringcmp(method, "direct"))
retval.insert(retval.begin(), string("direct://"));
-
- return retval;
}
proxy_factory::proxy_factory() {
@@ -159,6 +165,8 @@ proxy_factory::proxy_factory() {
this->mm.load_dir(module_dir);
this->mm.load_dir(module_dir, false);
+ this->debug = (getenv("_PX_DEBUG") != NULL);
+
unlock();
}
@@ -179,25 +187,42 @@ proxy_factory::~proxy_factory() {
}
-vector<string> proxy_factory::get_proxies(string url_) {
- url* realurl = NULL;
+vector<string> proxy_factory::get_proxies(string realurl) {
vector<string> response;
// Check to make sure our url is valid
- if (!url::is_valid(url_))
+ if (!url::is_valid(realurl))
goto do_return;
- realurl = new url(url_);
lock();
// Let trap and forward exceptions so we don't deadlock
try {
- _get_proxies(realurl, response);
+ vector<url> configs;
+ string ignore;
+ url dst(realurl);
+
+ check_network_topology();
+ get_config(dst, configs, ignore);
+
+ if (debug) cerr << "Config is: " << endl;
+
+ for (vector<url>::iterator i=configs.begin() ; i != configs.end() ; i++) {
+ url confurl(*i);
+
+ if (debug) cerr << "\t" << confurl.to_string() << endl;
+
+ if (expand_wpad(confurl) || expand_pac(confurl)) {
+ run_pac(dst, confurl, response);
+ } else {
+ clear_cache();
+ response.push_back(confurl.to_string());
+ }
+ }
+
unlock();
- if (realurl) delete realurl;
} catch (exception &e) {
unlock();
- if (realurl) delete realurl;
throw e;
}
@@ -207,16 +232,8 @@ do_return:
return response;
}
-void proxy_factory::_get_proxies(url *realurl, vector<string> &response) {
- url confurl("direct://");
- bool ignored = false, invign = false;
- string confign;
- config_extension* config = NULL;
+void proxy_factory::check_network_topology() {
vector<network_extension*> networks;
- vector<config_extension*> configs;
- vector<ignore_extension*> ignores;
- const char* debug = getenv("_PX_DEBUG");
-
// Check to see if our network topology has changed...
networks = this->mm.get_extensions<network_extension>();
@@ -232,32 +249,40 @@ void proxy_factory::_get_proxies(url *realurl, vector<string> &response) {
break;
}
}
+}
+
+void proxy_factory::get_config(url &realurl, vector<url> &config, string &ignore) {
+ vector<config_extension*> configs;
configs = this->mm.get_extensions<config_extension>();
for (vector<config_extension*>::iterator i=configs.begin() ; i != configs.end() ; i++) {
- config = *i;
+ config_extension *configurator = *i;
- // Try to get the confurl
+ // Try to get the configuration
try {
- confurl = config->get_config(*realurl);
- confign = config->get_ignore(*realurl);
- config->set_valid(true);
+ ignore = configurator->get_ignore(realurl);
+ if (!is_ignored(realurl, ignore))
+ config = configurator->get_config(realurl);
+ if (debug) {
+ if (configurator) {
+ cerr << "Configuration extension is: " << typeid(*configurator).name() << endl;
+ cerr << "Ingored list is: " << ignore << endl;
+ } else {
+ cerr << "No configuration extension found." << endl;
+ }
+ }
break;
}
catch (runtime_error e) {
- confurl = "direct://";
- confign = "";
- config->set_valid(false);
- config = NULL;
+ ignore = "";
}
}
- if (debug) {
- if (config)
- cerr << "Using config: " << typeid(*config).name() << endl;
- else
- cerr << "Using config: NULL" << endl;
- cerr << "Using ignore: " << confign << endl;
- }
+}
+
+bool proxy_factory::is_ignored(url &realurl, const string &ignore) {
+ vector<ignore_extension*> ignores;
+ bool ignored = false, invign = false;
+ string confign = ignore;
/* Check our ignore patterns */
ignores = this->mm.get_extensions<ignore_extension>();
@@ -270,16 +295,22 @@ void proxy_factory::_get_proxies(url *realurl, vector<string> &response) {
string ignorestr = confign.substr (i, next - i);
ignorestr = ignorestr.substr(ignorestr.find_first_not_of(" \t\n"), ignorestr.find_last_not_of(" \t\n")+1);
for (vector<ignore_extension*>::iterator it=ignores.begin() ; it != ignores.end() && !ignored ; it++)
- ignored = ((*it)->ignore(*realurl, ignorestr));
+ ignored = ((*it)->ignore(realurl, ignorestr));
}
i = next+1;
}
- if (!ignored && invign) return;
- if (ignored && !invign) return;
- /* If we have a wpad config */
- if (debug) cerr << "Config is: " << confurl.to_string() << endl;
+ if (invign)
+ return !ignored;
+ else
+ return ignored;
+}
+
+bool proxy_factory::expand_wpad(const url &confurl)
+{
+ bool rtv = false;
if (confurl.get_scheme() == "wpad") {
+ rtv = true;
/* If the config has just changed from PAC to WPAD, clear the PAC */
if (!this->wpad) {
if (this->pac) delete this->pac;
@@ -331,8 +362,17 @@ void proxy_factory::_get_proxies(url *realurl, vector<string> &response) {
}
}
+ return rtv;
+}
+
+bool proxy_factory::expand_pac(url &confurl)
+{
+ bool rtv = false;
+
// If we have a PAC config
- else if (confurl.get_scheme().substr(0, 4) == "pac+") {
+ if (confurl.get_scheme().substr(0, 4) == "pac+") {
+ rtv = true;
+
/* Save the PAC config */
if (this->wpad)
this->wpad = false;
@@ -350,15 +390,20 @@ void proxy_factory::_get_proxies(url *realurl, vector<string> &response) {
/* Try to load the PAC if it is not already loaded */
if (!this->pac) {
this->pacurl = new url(confurl);
- this->pac = confurl.get_pac();
- if (!this->pac) {
- if (debug) cerr << "Unable to download PAC!" << endl;
- return;
+ this->pac = confurl.get_pac();
+ if (debug) {
+ if (!this->pac)
+ cerr << "Unable to download PAC!" << endl;
+ else
+ cerr << "PAC received!" << endl;
}
- if (debug) cerr << "PAC received!" << endl;
}
}
+ return rtv;
+}
+
+void proxy_factory::run_pac(url &realurl, const url &confurl, vector<string> &response) {
/* In case of either PAC or WPAD, we'll run the PAC */
if (this->pac && (confurl.get_scheme() == "wpad" || confurl.get_scheme().substr(0, 4) == "pac+") ) {
vector<pacrunner_extension*> pacrunners = this->mm.get_extensions<pacrunner_extension>();
@@ -371,20 +416,16 @@ void proxy_factory::_get_proxies(url *realurl, vector<string> &response) {
/* Run the PAC, but only try one PACRunner */
if (debug) cerr << "Using pacrunner: " << typeid(*pacrunners[0]).name() << endl;
- string pacresp = pacrunners[0]->get(this->pac, this->pacurl->to_string())->run(*realurl);
+ string pacresp = pacrunners[0]->get(this->pac, this->pacurl->to_string())->run(realurl);
if (debug) cerr << "Pacrunner returned: " << pacresp << endl;
- response = format_pac_response(pacresp);
+ format_pac_response(pacresp, response);
}
+}
- /* If we have a manual config (http://..., socks://..., etc.) */
- else
- {
- this->wpad = false;
- if (this->pac) { delete this->pac; this->pac = NULL; }
- if (this->pacurl) { delete this->pacurl; this->pacurl = NULL; }
- response.clear();
- response.push_back(confurl.to_string());
- }
+void proxy_factory::clear_cache() {
+ this->wpad = false;
+ if (this->pac) { delete this->pac; this->pac = NULL; }
+ if (this->pacurl) { delete this->pacurl; this->pacurl = NULL; }
}
void proxy_factory::lock() {