Mercurial > pidgin
changeset 14970:721465a37d4e
[gaim-migrate @ 17749]
Re-read Windows proxy information when it has changed.
committer: Tailor Script <tailor@pidgin.im>
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Wed, 15 Nov 2006 06:00:51 +0000 |
parents | 43f692951d49 |
children | 99112cd4a2f4 |
files | gtk/win32/win_gaim.c libgaim/proxy.c libgaim/win32/win32dep.c libgaim/win32/win32dep.h |
diffstat | 4 files changed, 212 insertions(+), 109 deletions(-) [+] |
line wrap: on
line diff
--- a/gtk/win32/win_gaim.c Tue Nov 14 16:32:40 2006 +0000 +++ b/gtk/win32/win_gaim.c Wed Nov 15 06:00:51 2006 +0000 @@ -35,8 +35,6 @@ #include <string.h> #include <stdio.h> -#define WIN32_PROXY_REGKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" - /* These will hopefully be in the win32api next time it is updated - at which point, we'll remove them */ #ifndef LANG_PERSIAN #define LANG_PERSIAN 0x29 @@ -460,48 +458,6 @@ return TRUE; } -static void wgaim_set_proxy() { - DWORD regval = 1; - DWORD reglen = sizeof(DWORD); - - /* If the proxy server environment variables are already set, - * we shouldn't override them */ - if (getenv("HTTP_PROXY") || getenv("http_proxy") || getenv("HTTPPROXY")) - return; - - if (read_reg_string(HKEY_CURRENT_USER, WIN32_PROXY_REGKEY, - "ProxyEnable", - (LPBYTE) ®val, ®len) && (regval & 1)) { - char proxy_server[2048]; - char *c = NULL; - reglen = sizeof(proxy_server); - - if (!read_reg_string(HKEY_CURRENT_USER, WIN32_PROXY_REGKEY, - "ProxyServer", (LPBYTE) &proxy_server, ®len)) - return; - - if ((reglen > strlen("http=")) - && (c = strstr(proxy_server, "http="))) { - char *d; - c += strlen("http="); - d = strchr(c, ';'); - if (d) { - *d = '\0'; - } - /* c now points the proxy server (and port) */ - } - - if (c) { - const char envstr_prefix[] = "HTTP_PROXY=http://"; - char envstr[sizeof(envstr_prefix) + strlen(c) + 1]; - snprintf(envstr, sizeof(envstr), "%s%s", - envstr_prefix, c); - printf("Setting HTTP Proxy: %s\n", envstr); - putenv(envstr); - } - } - -} #ifdef __GNUC__ # ifndef _stdcall @@ -572,8 +528,6 @@ if (!getenv("GAIM_MULTI_INST") && !wgaim_set_running()) return 0; - wgaim_set_proxy(); - /* Now we are ready for Gaim .. */ if ((hmod = LoadLibrary("gtkgaim.dll"))) { gaim_main = (LPFNGAIMMAIN) GetProcAddress(hmod, "gaim_main");
--- a/libgaim/proxy.c Tue Nov 14 16:32:40 2006 +0000 +++ b/libgaim/proxy.c Wed Nov 15 06:00:51 2006 +0000 @@ -1688,6 +1688,13 @@ GaimProxyInfo *gpi; const gchar *tmp; + /* This is used as a fallback so we don't overwrite the selected proxy type */ + static GaimProxyInfo *tmp_none_proxy_info = NULL; + if (!tmp_none_proxy_info) { + tmp_none_proxy_info = gaim_proxy_info_new(); + gaim_proxy_info_set_type(tmp_none_proxy_info, GAIM_PROXY_NONE); + } + if (account && gaim_account_get_proxy_info(account) != NULL) gpi = gaim_account_get_proxy_info(account); else if (gaim_running_gnome()) @@ -1696,41 +1703,41 @@ gpi = gaim_global_proxy_get_info(); if (gaim_proxy_info_get_type(gpi) == GAIM_PROXY_USE_ENVVAR) { +#ifdef _WIN32 + wgaim_check_for_proxy_changes(); +#endif if ((tmp = g_getenv("HTTP_PROXY")) != NULL || (tmp = g_getenv("http_proxy")) != NULL || (tmp = g_getenv("HTTPPROXY")) != NULL) { - char *proxyhost,*proxypath,*proxyuser,*proxypasswd; + char *proxyhost, *proxyuser, *proxypasswd; int proxyport; /* http_proxy-format: * export http_proxy="http://user:passwd@your.proxy.server:port/" */ - if(gaim_url_parse(tmp, &proxyhost, &proxyport, &proxypath, &proxyuser, &proxypasswd)) { + if(gaim_url_parse(tmp, &proxyhost, &proxyport, NULL, &proxyuser, &proxypasswd)) { gaim_proxy_info_set_host(gpi, proxyhost); g_free(proxyhost); - g_free(proxypath); - if (proxyuser != NULL) { - gaim_proxy_info_set_username(gpi, proxyuser); - g_free(proxyuser); - } - if (proxypasswd != NULL) { - gaim_proxy_info_set_password(gpi, proxypasswd); - g_free(proxypasswd); - } + + gaim_proxy_info_set_username(gpi, proxyuser); + g_free(proxyuser); + + gaim_proxy_info_set_password(gpi, proxypasswd); + g_free(proxypasswd); /* only for backward compatibility */ if (proxyport == 80 && ((tmp = g_getenv("HTTP_PROXY_PORT")) != NULL || (tmp = g_getenv("http_proxy_port")) != NULL || (tmp = g_getenv("HTTPPROXYPORT")) != NULL)) - proxyport = atoi(tmp); + proxyport = atoi(tmp); gaim_proxy_info_set_port(gpi, proxyport); } } else { /* no proxy environment variable found, don't use a proxy */ gaim_debug_info("proxy", "No environment settings found, not using a proxy\n"); - gaim_proxy_info_set_type(gpi, GAIM_PROXY_NONE); + gpi = tmp_none_proxy_info; } /* XXX: Do we want to skip this step if user/password were part of url? */
--- a/libgaim/win32/win32dep.c Tue Nov 14 16:32:40 2006 +0000 +++ b/libgaim/win32/win32dep.c Wed Nov 15 06:00:51 2006 +0000 @@ -44,6 +44,8 @@ */ #define _(x) gettext(x) +#define WIN32_PROXY_REGKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings" + /* For shfolder.dll */ typedef HRESULT (CALLBACK* LPFNSHGETFOLDERPATHA)(HWND, int, HANDLE, DWORD, LPSTR); typedef HRESULT (CALLBACK* LPFNSHGETFOLDERPATHW)(HWND, int, HANDLE, DWORD, LPWSTR); @@ -56,6 +58,9 @@ static HINSTANCE libgaimdll_hInstance = 0; +static HANDLE proxy_change_event = NULL; +static HKEY proxy_regkey = NULL; + /* * PUBLIC CODE */ @@ -319,75 +324,196 @@ return success; } -char *wgaim_read_reg_string(HKEY rootkey, const char *subkey, const char *valname) { - - DWORD type; - DWORD nbytes; - HKEY reg_key; - char *result = NULL; +static HKEY _reg_open_key(HKEY rootkey, const char *subkey, REGSAM access) { + HKEY reg_key = NULL; + LONG rv; if(G_WIN32_HAVE_WIDECHAR_API()) { wchar_t *wc_subkey = g_utf8_to_utf16(subkey, -1, NULL, NULL, NULL); - - if(RegOpenKeyExW(rootkey, wc_subkey, 0, - KEY_QUERY_VALUE, ®_key) == ERROR_SUCCESS) { - wchar_t *wc_valname = NULL; - if (valname) - wc_valname = g_utf8_to_utf16(valname, -1, - NULL, NULL, NULL); - - if(RegQueryValueExW(reg_key, wc_valname, 0, &type, - NULL, &nbytes) == ERROR_SUCCESS - && type == REG_SZ) { - wchar_t *wc_temp = - g_new(wchar_t, ((nbytes + 1) / sizeof(wchar_t)) + 1); - - if(RegQueryValueExW(reg_key, wc_valname, 0, - &type, (LPBYTE) wc_temp, - &nbytes) == ERROR_SUCCESS) { - wc_temp[nbytes / sizeof(wchar_t)] = '\0'; - result = g_utf16_to_utf8(wc_temp, -1, - NULL, NULL, NULL); - } - g_free(wc_temp); - } - g_free(wc_valname); - } + rv = RegOpenKeyExW(rootkey, wc_subkey, 0, access, ®_key); g_free(wc_subkey); } else { char *cp_subkey = g_locale_from_utf8(subkey, -1, NULL, NULL, NULL); - if(RegOpenKeyExA(rootkey, cp_subkey, 0, - KEY_QUERY_VALUE, ®_key) == ERROR_SUCCESS) { - char *cp_valname = NULL; - if(valname) - cp_valname = g_locale_from_utf8(valname, -1, - NULL, NULL, NULL); + rv = RegOpenKeyExA(rootkey, cp_subkey, 0, access, ®_key); + g_free(cp_subkey); + } + + if (rv != ERROR_SUCCESS) { + char *errmsg = g_win32_error_message(rv); + gaim_debug_info("wgaim", "Could not open reg key '%s' subkey '%s'.\nMessage: (%ld) %s\n", + ((rootkey == HKEY_LOCAL_MACHINE) ? "HKLM" : + (rootkey == HKEY_CURRENT_USER) ? "HKCU" : + (rootkey == HKEY_CLASSES_ROOT) ? "HKCR" : "???"), + subkey, rv, errmsg); + g_free(errmsg); + } + + return reg_key; +} + +static gboolean _reg_read(HKEY reg_key, const char *valname, LPDWORD type, LPBYTE data, LPDWORD data_len) { + LONG rv; + + if(G_WIN32_HAVE_WIDECHAR_API()) { + wchar_t *wc_valname = NULL; + if (valname) + wc_valname = g_utf8_to_utf16(valname, -1, NULL, NULL, NULL); + rv = RegQueryValueExW(reg_key, wc_valname, 0, type, data, data_len); + g_free(wc_valname); + } else { + char *cp_valname = NULL; + if(valname) + cp_valname = g_locale_from_utf8(valname, -1, NULL, NULL, NULL); + rv = RegQueryValueExA(reg_key, cp_valname, 0, type, data, data_len); + g_free(cp_valname); + } + + if (rv != ERROR_SUCCESS) { + char *errmsg = g_win32_error_message(rv); + gaim_debug_info("wgaim", "Could not read from reg key value '%s'.\nMessage: (%ld) %s\n", + valname, rv, errmsg); + g_free(errmsg); + } - if(RegQueryValueExA(reg_key, cp_valname, 0, &type, - NULL, &nbytes) == ERROR_SUCCESS - && type == REG_SZ) { - char *cp_temp = g_malloc(nbytes + 1); + return (rv == ERROR_SUCCESS); +} + +gboolean wgaim_read_reg_dword(HKEY rootkey, const char *subkey, const char *valname, LPDWORD result) { + + DWORD type; + DWORD nbytes; + HKEY reg_key = _reg_open_key(rootkey, subkey, KEY_QUERY_VALUE); + gboolean success = FALSE; + + if(reg_key) { + if(_reg_read(reg_key, valname, &type, (LPBYTE)result, &nbytes)) + success = TRUE; + RegCloseKey(reg_key); + } + + return success; +} + +char *wgaim_read_reg_string(HKEY rootkey, const char *subkey, const char *valname) { - if(RegQueryValueExA(reg_key, cp_valname, 0, - &type, cp_temp, - &nbytes) == ERROR_SUCCESS) { + DWORD type; + DWORD nbytes; + HKEY reg_key = _reg_open_key(rootkey, subkey, KEY_QUERY_VALUE); + char *result = NULL; + + if(reg_key) { + if(_reg_read(reg_key, valname, &type, NULL, &nbytes) && type == REG_SZ) { + LPBYTE data; + if(G_WIN32_HAVE_WIDECHAR_API()) + data = (LPBYTE) g_new(wchar_t, ((nbytes + 1) / sizeof(wchar_t)) + 1); + else + data = (LPBYTE) g_malloc(nbytes + 1); + + if(_reg_read(reg_key, valname, &type, data, &nbytes)) { + if(G_WIN32_HAVE_WIDECHAR_API()) { + wchar_t *wc_temp = (wchar_t*) data; + wc_temp[nbytes / sizeof(wchar_t)] = '\0'; + result = g_utf16_to_utf8(wc_temp, -1, + NULL, NULL, NULL); + } else { + char *cp_temp = (char*) data; cp_temp[nbytes] = '\0'; result = g_locale_to_utf8(cp_temp, -1, NULL, NULL, NULL); } - g_free (cp_temp); } - g_free(cp_valname); + g_free(data); } - g_free(cp_subkey); + RegCloseKey(reg_key); + } + + return result; +} + +static void wgaim_refresh_proxy(void) { + gboolean set_proxy = FALSE; + DWORD enabled = 0; + + wgaim_read_reg_dword(HKEY_CURRENT_USER, WIN32_PROXY_REGKEY, + "ProxyEnable", &enabled); + + if (enabled & 1) { + char *c = NULL; + char *tmp = wgaim_read_reg_string(HKEY_CURRENT_USER, WIN32_PROXY_REGKEY, + "ProxyServer"); + + /* 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) { + gaim_debug_info("wgaim", "Setting HTTP Proxy: 'http://%s'\n", c); + g_setenv("HTTP_PROXY", c, TRUE); + set_proxy = TRUE; + } + g_free(tmp); } - if(reg_key != NULL) - RegCloseKey(reg_key); + /* If there previously was a proxy set and there isn't one now, clear it */ + if (getenv("HTTP_PROXY") && !set_proxy) { + gaim_debug_info("wgaim", "Clearing HTTP Proxy\n"); + g_unsetenv("HTTP_PROXY"); + } +} + +static void watch_for_proxy_changes(void) { + LONG rv; + DWORD filter = REG_NOTIFY_CHANGE_NAME | + REG_NOTIFY_CHANGE_LAST_SET; + + if (!proxy_regkey && + !(proxy_regkey = _reg_open_key(HKEY_CURRENT_USER, + WIN32_PROXY_REGKEY, KEY_NOTIFY))) { + return; + } - return result; + if (!(proxy_change_event = CreateEvent(NULL, TRUE, FALSE, NULL))) { + char *errmsg = g_win32_error_message(GetLastError()); + gaim_debug_error("wgaim", "Unable to watch for proxy changes: %s\n", errmsg); + g_free(errmsg); + return; + } + + rv = RegNotifyChangeKeyValue(proxy_regkey, TRUE, filter, proxy_change_event, TRUE); + if (rv != ERROR_SUCCESS) { + char *errmsg = g_win32_error_message(rv); + gaim_debug_error("wgaim", "Unable to watch for proxy changes: %s\n", errmsg); + g_free(errmsg); + CloseHandle(proxy_change_event); + proxy_change_event = NULL; + } + +} + +gboolean wgaim_check_for_proxy_changes(void) { + gboolean changed = FALSE; + + if (proxy_change_event && WaitForSingleObject(proxy_change_event, 0) == WAIT_OBJECT_0) { + CloseHandle(proxy_change_event); + proxy_change_event = NULL; + changed = TRUE; + wgaim_refresh_proxy(); + watch_for_proxy_changes(); + } + + return changed; } void wgaim_init(void) { @@ -430,6 +556,15 @@ if (!g_thread_supported()) g_thread_init(NULL); + /* If the proxy server environment variables are already set, + * we shouldn't override them */ + if (!getenv("HTTP_PROXY") && !getenv("http_proxy") && !getenv("HTTPPROXY")) { + wgaim_refresh_proxy(); + watch_for_proxy_changes(); + } else { + gaim_debug_info("wgaim", "HTTP_PROXY env. var already set. Ignoring win32 Internet Settings.\n"); + } + gaim_debug_info("wgaim", "wgaim_init end\n"); } @@ -444,6 +579,11 @@ g_free(app_data_dir); app_data_dir = NULL; + if (proxy_regkey) { + RegCloseKey(proxy_regkey); + proxy_regkey = NULL; + } + libgaimdll_hInstance = NULL; }
--- a/libgaim/win32/win32dep.h Tue Nov 14 16:32:40 2006 +0000 +++ b/libgaim/win32/win32dep.h Wed Nov 15 06:00:51 2006 +0000 @@ -41,6 +41,8 @@ gboolean wgaim_write_reg_string(HKEY rootkey, const char *subkey, const char *valname, const char *value); char *wgaim_escape_dirsep(const char *filename); /* needs to be g_free'd */ GIOChannel *wgaim_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 wgaim_check_for_proxy_changes(void); /* Determine Gaim paths */ char *wgaim_get_special_folder(int folder_type); /* needs to be g_free'd */