changeset 23970:54eb782d4721

Add support for reading SOCKS proxy information from the Windows proxy settings. Fixes #1614
author Daniel Atallah <daniel.atallah@gmail.com>
date Tue, 26 Aug 2008 04:36:29 +0000
parents 4ecea8ae3d21
children 920933ba2caa
files libpurple/proxy.c libpurple/win32/win32dep.c libpurple/win32/win32dep.h
diffstat 3 files changed, 154 insertions(+), 100 deletions(-) [+]
line wrap: on
line diff
--- a/libpurple/proxy.c	Tue Aug 26 04:08:22 2008 +0000
+++ b/libpurple/proxy.c	Tue Aug 26 04:36:29 2008 +0000
@@ -347,6 +347,143 @@
 
 	return &info;
 }
+
+#ifdef _WIN32
+
+typedef BOOL (CALLBACK* LPFNWINHTTPGETIEPROXYCONFIG)(/*IN OUT*/ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* pProxyConfig);
+
+/* This modifies "host" in-place evilly */
+static void
+_proxy_fill_hostinfo(PurpleProxyInfo *info, char *host, int default_port)
+{
+	int port = default_port;
+	char *d;
+
+	d = g_strrstr(host, ":");
+	if (d)
+		*d = '\0';
+	d++;
+	if (*d)
+		sscanf(d, "%d", &port);
+
+	purple_proxy_info_set_host(info, host);
+	purple_proxy_info_set_port(info, port);
+}
+
+static PurpleProxyInfo *
+purple_win32_proxy_get_info(void)
+{
+	static LPFNWINHTTPGETIEPROXYCONFIG MyWinHttpGetIEProxyConfig = NULL;
+	static gboolean loaded = FALSE;
+	static PurpleProxyInfo info = {0, NULL, 0, NULL, NULL};
+
+	WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_config;
+
+	if (!loaded) {
+		loaded = TRUE;
+		MyWinHttpGetIEProxyConfig = (LPFNWINHTTPGETIEPROXYCONFIG)
+			wpurple_find_and_loadproc("winhttp.dll", "WinHttpGetIEProxyConfigForCurrentUser");
+		if (!MyWinHttpGetIEProxyConfig)
+			purple_debug_info("proxy", "Unable to read Windows Proxy Settings.\n");
+	}
+
+	if (!MyWinHttpGetIEProxyConfig)
+		return NULL;
+
+	ZeroMemory(&ie_proxy_config, sizeof(ie_proxy_config));
+	if (!MyWinHttpGetIEProxyConfig(&ie_proxy_config)) {
+		purple_debug_error("proxy", "Error reading Windows Proxy Settings(%lu).\n", GetLastError());
+		return NULL;
+	}
+
+	/* We can't do much if it is autodetect*/
+	if (ie_proxy_config.fAutoDetect) {
+		purple_debug_error("proxy", "Windows Proxy Settings set to autodetect (not supported).\n");
+
+		/* TODO: For 3.0.0 we'll revisit this (maybe)*/
+
+		return NULL;
+
+	} else if (ie_proxy_config.lpszProxy) {
+		gchar *proxy_list = g_utf16_to_utf8(ie_proxy_config.lpszProxy, -1,
+									 NULL, NULL, NULL);
+
+		/* We can't do anything about the bypass list, as we don't have the url */
+		/* TODO: For 3.0.0 we'll revisit this*/
+
+		/* There are proxy settings for several protocols */
+		if (proxy_list && *proxy_list) {
+			char *specific = NULL, *tmp;
+
+			/* If there is only a global proxy, which  means "HTTP" */
+			if (!strchr(proxy_list, ';') || (specific = g_strstr_len(proxy_list, -1, "http=")) != NULL) {
+
+				if (specific) {
+					specific += strlen("http=");
+					tmp = strchr(specific, ';');
+					if (tmp)
+						*tmp = '\0';
+					/* specific now points the proxy server (and port) */
+				} else
+					specific = proxy_list;
+
+				purple_proxy_info_set_type(&info, PURPLE_PROXY_HTTP);
+				_proxy_fill_hostinfo(&info, specific, 80);
+				/* TODO: is there a way to set the username/password? */
+				purple_proxy_info_set_username(&info, NULL);
+				purple_proxy_info_set_password(&info, NULL);
+
+				purple_debug_info("proxy", "Windows Proxy Settings: HTTP proxy: '%s:%d'.\n",
+								  purple_proxy_info_get_host(&info),
+								  purple_proxy_info_get_port(&info));
+
+			} else if ((specific = g_strstr_len(proxy_list, -1, "socks=")) != NULL) {
+
+				specific += strlen("socks=");
+				tmp = strchr(specific, ';');
+				if (tmp)
+					*tmp = '\0';
+				/* specific now points the proxy server (and port) */
+
+				purple_proxy_info_set_type(&info, PURPLE_PROXY_SOCKS5);
+				_proxy_fill_hostinfo(&info, specific, 1080);
+				/* TODO: is there a way to set the username/password? */
+				purple_proxy_info_set_username(&info, NULL);
+				purple_proxy_info_set_password(&info, NULL);
+
+				purple_debug_info("proxy", "Windows Proxy Settings: SOCKS5 proxy: '%s:%d'.\n",
+								  purple_proxy_info_get_host(&info),
+								  purple_proxy_info_get_port(&info));
+
+			} else {
+
+				purple_debug_info("proxy", "Windows Proxy Settings: No supported proxy specified.\n");
+
+				purple_proxy_info_set_type(&info, PURPLE_PROXY_NONE);
+
+			}
+		}
+
+		/* TODO: Fix API to be able look at proxy bypass settings */
+
+		g_free(proxy_list);
+	} else {
+		purple_debug_info("proxy", "No Windows proxy set.\n");
+		purple_proxy_info_set_type(&info, PURPLE_PROXY_NONE);
+	}
+
+	if (ie_proxy_config.lpszAutoConfigUrl)
+		GlobalFree(ie_proxy_config.lpszAutoConfigUrl);
+	if (ie_proxy_config.lpszProxy)
+		GlobalFree(ie_proxy_config.lpszProxy);
+	if (ie_proxy_config.lpszProxyBypass)
+		GlobalFree(ie_proxy_config.lpszProxyBypass);
+
+	return &info;
+}
+#endif
+
+
 /**************************************************************************
  * Proxy API
  **************************************************************************/
@@ -1878,9 +2015,6 @@
 	}
 
 	if (purple_proxy_info_get_type(gpi) == PURPLE_PROXY_USE_ENVVAR) {
-#ifdef _WIN32
-		wpurple_check_for_proxy_changes();
-#endif
 		if ((tmp = g_getenv("HTTP_PROXY")) != NULL ||
 			(tmp = g_getenv("http_proxy")) != NULL ||
 			(tmp = g_getenv("HTTPPROXY")) != NULL) {
@@ -1922,6 +2056,11 @@
 
 			}
 		} else {
+#ifdef _WIN32
+			PurpleProxyInfo *wgpi;
+			if ((wgpi = purple_win32_proxy_get_info()) != NULL)
+				return wgpi;
+#endif
 			/* no proxy environment variable found, don't use a proxy */
 			purple_debug_info("proxy", "No environment settings found, not using a proxy\n");
 			gpi = tmp_none_proxy_info;
--- a/libpurple/win32/win32dep.c	Tue Aug 26 04:08:22 2008 +0000
+++ b/libpurple/win32/win32dep.c	Tue Aug 26 04:36:29 2008 +0000
@@ -416,107 +416,18 @@
 	return result;
 }
 
-/* the winapi headers don't yet have winhttp.h, so we use the struct from msdn directly */
-typedef struct {
-  BOOL fAutoDetect;
-  LPWSTR lpszAutoConfigUrl;
-  LPWSTR lpszProxy;
-  LPWSTR lpszProxyBypass;
-} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
-
-typedef BOOL (CALLBACK* LPFNWINHTTPGETIEPROXYCONFIG)(/*IN OUT*/ WINHTTP_CURRENT_USER_IE_PROXY_CONFIG* pProxyConfig);
-
-gboolean wpurple_check_for_proxy_changes(void) {
-	static gboolean loaded = FALSE;
-	static LPFNWINHTTPGETIEPROXYCONFIG MyWinHttpGetIEProxyConfig = NULL;
-
-	WINHTTP_CURRENT_USER_IE_PROXY_CONFIG ie_proxy_config;
-	char *tmp = NULL, *c = NULL;
-	gboolean changed = FALSE;
-
-	if (!loaded) {
-		loaded = TRUE;
-
-		if (getenv("HTTP_PROXY") || getenv("http_proxy") || getenv("HTTPPROXY")) {
-			purple_debug_info("wpurple", "HTTP_PROXY env. var already set.  Ignoring win32 Internet Settings.\n");
-			return FALSE;
-		}
-
-		MyWinHttpGetIEProxyConfig = (LPFNWINHTTPGETIEPROXYCONFIG)
-			wpurple_find_and_loadproc("winhttp.dll", "WinHttpGetIEProxyConfigForCurrentUser");
-		if (!MyWinHttpGetIEProxyConfig)
-			purple_debug_info("wpurple", "Unable to read Windows Proxy Settings.\n");
-	}
-
-	if (!MyWinHttpGetIEProxyConfig)
-		return FALSE;
-
-	ZeroMemory(&ie_proxy_config, sizeof(ie_proxy_config));
-	if (!MyWinHttpGetIEProxyConfig(&ie_proxy_config)) {
-		purple_debug_error("wpurple", "Error reading Windows Proxy Settings(%lu).\n", GetLastError());
-		return FALSE;
-	}
-
-	/* We can't do much if it is autodetect*/
-	if (ie_proxy_config.fAutoDetect)
-		purple_debug_error("wpurple", "Windows Proxy Settings set to autodetect (not supported).\n");
-	else if (ie_proxy_config.lpszProxy) {
-		tmp = g_utf16_to_utf8(ie_proxy_config.lpszProxy, -1,
-						NULL, NULL, NULL);
-		/* We can't do anything about the bypass list, as we don't have the url */
-	} else
-		purple_debug_info("wpurple", "No Windows Proxy Set.\n");
-
-	if (ie_proxy_config.lpszAutoConfigUrl)
-		GlobalFree(ie_proxy_config.lpszAutoConfigUrl);
-	if (ie_proxy_config.lpszProxy)
-		GlobalFree(ie_proxy_config.lpszProxy);
-	if (ie_proxy_config.lpszProxyBypass)
-		GlobalFree(ie_proxy_config.lpszProxyBypass);
-
-	/* There are proxy settings for several protocols */
-	if (tmp && (c = g_strstr_len(tmp, strlen(tmp), "http="))) {
-		char *d;
-		c += strlen("http=");
-		d = strchr(c, ';');
-		if (d)
-			*d = '\0';
-		/* c now points the proxy server (and port) */
-	/* There is only a global proxy */
-	} else if (tmp && strlen(tmp) > 0 && !strchr(tmp, ';')) {
-		c = tmp;
-	}
-
-	if (c && *c) {
-		const char *current = g_getenv("HTTP_PROXY");
-		if (!current || strcmp(current, c)) {
-			purple_debug_info("wpurple", "Setting HTTP Proxy: 'http://%s'\n", c);
-			g_setenv("HTTP_PROXY", c, TRUE);
-			changed = TRUE;
-		}
-	}
-	/* If there previously was a proxy set and there isn't one now, clear it */
-	else if (getenv("HTTP_PROXY")) {
-		purple_debug_info("wpurple", "Clearing HTTP Proxy\n");
-		g_unsetenv("HTTP_PROXY");
-		changed = TRUE;
-	}
-
-	g_free(tmp);
-
-	return changed;
-}
-
 void wpurple_init(void) {
 	WORD wVersionRequested;
 	WSADATA wsaData;
 	const char *perlenv;
 	char *newenv;
 
+	if (!g_thread_supported())
+		g_thread_init(NULL);
+
 	purple_debug_info("wpurple", "wpurple_init start\n");
 	purple_debug_info("wpurple", "libpurple version: " DISPLAY_VERSION "\n");
 
-
 	purple_debug_info("wpurple", "Glib:%u.%u.%u\n",
 		glib_major_version, glib_minor_version, glib_micro_version);
 
@@ -544,9 +455,6 @@
 		purple_debug_warning("wpurple", "putenv failed for PERL5LIB\n");
 	g_free(newenv);
 
-	if (!g_thread_supported())
-		g_thread_init(NULL);
-
 	purple_debug_info("wpurple", "wpurple_init end\n");
 }
 
--- a/libpurple/win32/win32dep.h	Tue Aug 26 04:08:22 2008 +0000
+++ b/libpurple/win32/win32dep.h	Tue Aug 26 04:36:29 2008 +0000
@@ -29,10 +29,19 @@
 #include "wpurpleerror.h"
 #include "libc_interface.h"
 
+
 #ifdef __cplusplus
 extern "C" {
 #endif /* __cplusplus */
 
+/* the winapi headers don't yet have winhttp.h, so we use the struct from msdn directly */
+typedef struct {
+  BOOL fAutoDetect;
+  LPWSTR lpszAutoConfigUrl;
+  LPWSTR lpszProxy;
+  LPWSTR lpszProxyBypass;
+} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
+
 /* rpcndr.h defines small as char, causing problems, so we need to undefine it */
 #undef small
 
@@ -49,8 +58,6 @@
 gboolean wpurple_write_reg_string(HKEY rootkey, const char *subkey, const char *valname, const char *value);
 char *wpurple_escape_dirsep(const char *filename); /* needs to be g_free'd */
 GIOChannel *wpurple_g_io_channel_win32_new_socket(int socket); /* Until we get the post-2.8 glib win32 giochannel implementation working, use the thread-based one */
-/** Check for changes to the system proxy settings and update the HTTP_PROXY env. var. if there have been changes */
-gboolean wpurple_check_for_proxy_changes(void);
 
 /* Determine Purple paths */
 gchar *wpurple_get_special_folder(int folder_type); /* needs to be g_free'd */