# HG changeset patch # User Daniel Atallah # Date 1219725389 0 # Node ID 54eb782d472130a563c7fdb1cb6c9f01963d983f # Parent 4ecea8ae3d21c78026bf6a6f25f7a2d6ce8416fc Add support for reading SOCKS proxy information from the Windows proxy settings. Fixes #1614 diff -r 4ecea8ae3d21 -r 54eb782d4721 libpurple/proxy.c --- 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; diff -r 4ecea8ae3d21 -r 54eb782d4721 libpurple/win32/win32dep.c --- 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"); } diff -r 4ecea8ae3d21 -r 54eb782d4721 libpurple/win32/win32dep.h --- 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 */