Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/proxy/proxy_config_service_linux.h" | |
| 6 | |
| 7 #include <ctype.h> | |
| 8 #include <string.h> | |
| 9 #include <gdk/gdk.h> | |
| 10 #include <gconf/gconf-client.h> | |
| 11 | |
| 12 #include <string> | |
| 13 #include <sstream> | |
| 14 #include <vector> | |
| 15 | |
| 16 #include "base/string_tokenizer.h" | |
| 17 #include "base/sys_string_conversions.h" | |
| 18 #include "net/base/net_errors.h" | |
| 19 #include "net/proxy/proxy_config.h" | |
| 20 #include "net/proxy/proxy_info.h" | |
| 21 #include "net/proxy/proxy_server.h" | |
| 22 | |
| 23 #define GCONF_MODE_KEY "/system/proxy/mode" | |
| 24 #define GCONF_USE_HTTP_PROXY_KEY "/system/http_proxy/use_http_proxy" | |
| 25 #define GCONF_AUTOCONFIG_KEY "/system/proxy/autoconfig_url" | |
| 26 #define GCONF_SAME_PROXY_KEY "/system/http_proxy/use_same_proxy" | |
| 27 #define GCONF_HTTP_PROXY_KEY "/system/http_proxy/host" | |
| 28 #define GCONF_HTTP_PROXY_PORT_KEY "/system/http_proxy/port" | |
| 29 #define GCONF_SHTTP_PROXY_KEY "/system/proxy/secure_host" | |
| 30 #define GCONF_SHTTP_PROXY_PORT_KEY "/system/proxy/secure_port" | |
| 31 #define GCONF_FTP_PROXY_KEY "/system/proxy/ftp_host" | |
| 32 #define GCONF_FTP_PROXY_PORT_KEY "/system/proxy/ftp_port" | |
| 33 #define GCONF_PROXY_BYPASS_LIST_KEY "/system/http_proxy/ignore_hosts" | |
| 34 #define GCONF_SOCKS_PROXY_KEY "/system/proxy/socks_host" | |
| 35 #define GCONF_SOCKS_PROXY_PORT_KEY "/system/proxy/socks_port" | |
| 36 | |
| 37 const struct SchemeInGCONF { | |
| 38 const gchar* scheme; | |
| 39 const gchar* host_key; | |
| 40 const gchar* port_key; | |
| 41 } kSchemeInGCONF[] = { | |
| 42 {"http", GCONF_HTTP_PROXY_KEY, GCONF_HTTP_PROXY_PORT_KEY}, | |
| 43 {"https", GCONF_SHTTP_PROXY_KEY, GCONF_SHTTP_PROXY_PORT_KEY}, | |
| 44 {"ftp", GCONF_FTP_PROXY_KEY, GCONF_FTP_PROXY_PORT_KEY}, | |
| 45 }; | |
| 46 | |
| 47 namespace net { | |
| 48 | |
| 49 // Simple test input data | |
| 50 bool IsValidDomain(const std::string& str) { | |
|
eroman
2009/03/30 21:25:08
nit: make this "static".
| |
| 51 if (str.size () < 3) | |
| 52 return false; | |
| 53 for (size_t i = 0; i < str.size(); i++) { | |
| 54 if ( !(isalnum(str[i]) || str[i] == '.' || str[i] == '-' || | |
|
eroman
2009/03/30 21:25:08
nit: remove the space here "( !"
| |
| 55 str[i] == ':' || str[i] == '[' || str [i] == ']')) | |
| 56 return false; | |
| 57 } | |
| 58 return true; | |
| 59 } | |
| 60 | |
| 61 ProxyServer GetProxyServerFromGconf( | |
|
eroman
2009/03/30 21:25:08
nit: make this "static".
| |
| 62 GConfClient* client, | |
| 63 ProxyServer::Scheme scheme, | |
| 64 const char* host_key, | |
| 65 const char* port_key) { | |
| 66 gchar* proxy_host = gconf_client_get_string(client, host_key, NULL); | |
| 67 gint proxy_port = gconf_client_get_int(client, port_key, NULL); | |
| 68 | |
| 69 ProxyServer result; // Initialized to invalid. | |
|
eroman
2009/03/30 21:25:08
nit: two spaces between ";" and "/"
| |
| 70 | |
| 71 if (proxy_host != NULL && IsValidDomain(proxy_host)) { | |
| 72 if (proxy_port == 0) | |
| 73 proxy_port = ProxyServer::GetDefaultPortForScheme (scheme); | |
|
eroman
2009/03/30 21:25:08
nit: no space between "GetDefaultPortForScheme" an
| |
| 74 result = ProxyServer(scheme, proxy_host, proxy_port); | |
| 75 } | |
| 76 | |
| 77 g_free(proxy_host); | |
| 78 return result; | |
| 79 } | |
| 80 | |
| 81 bool GetProxyConfigGCONF(ProxyConfig* config) { | |
|
eroman
2009/03/30 21:25:08
nit: make this "static".
| |
| 82 bool res = true; | |
|
eroman
2009/03/30 21:25:08
nit: I would suggest a more descriptive name like
| |
| 83 GConfClient* client = GCONF_CLIENT(gconf_client_get_default()); | |
| 84 gchar* mode; | |
| 85 | |
| 86 mode = gconf_client_get_string(client, GCONF_MODE_KEY, NULL); | |
| 87 if (mode) { | |
| 88 if (strcmp(mode, "auto") == 0) { | |
| 89 gchar* url = gconf_client_get_string(client, GCONF_AUTOCONFIG_KEY, NULL); | |
| 90 if (url) { | |
| 91 if (strlen (url)) | |
| 92 config->pac_url = GURL(url); | |
| 93 else | |
| 94 config->auto_detect = true; | |
| 95 } else { | |
| 96 res = false; | |
| 97 } | |
| 98 g_free(url); | |
| 99 } | |
| 100 | |
| 101 if (strcmp(mode, "manual") == 0) { | |
| 102 gboolean same_proxy, use_http_proxy; | |
| 103 | |
| 104 use_http_proxy = gconf_client_get_bool(client, GCONF_USE_HTTP_PROXY_KEY, | |
| 105 NULL); | |
| 106 config->proxy_rules = ""; | |
| 107 | |
| 108 if (!use_http_proxy) { | |
| 109 ProxyServer proxy_server = GetProxyServerFromGconf( | |
| 110 client, | |
|
eroman
2009/03/30 21:25:08
nit: indent these parameters by 4 spaces instead o
| |
| 111 ProxyServer::SCHEME_SOCKS4, | |
| 112 GCONF_SOCKS_PROXY_KEY, | |
| 113 GCONF_SOCKS_PROXY_PORT_KEY); | |
| 114 | |
| 115 if (proxy_server.is_valid()) { | |
| 116 config->proxy_rules += proxy_server.ToURI(); | |
| 117 } else { | |
| 118 res = false; | |
| 119 } | |
| 120 } else { | |
| 121 same_proxy = gconf_client_get_bool(client, GCONF_SAME_PROXY_KEY, NULL); | |
| 122 | |
| 123 if (same_proxy) { | |
| 124 ProxyServer proxy_server = GetProxyServerFromGconf( | |
| 125 client, | |
|
eroman
2009/03/30 21:25:08
nit: indent these parameters by 4 spaces instead o
| |
| 126 ProxyServer::SCHEME_HTTP, | |
| 127 GCONF_HTTP_PROXY_KEY, | |
| 128 GCONF_HTTP_PROXY_PORT_KEY); | |
| 129 | |
| 130 if (proxy_server.is_valid()) { | |
| 131 config->proxy_rules = proxy_server.ToURI(); | |
| 132 } else { | |
| 133 res = false; | |
| 134 } | |
| 135 } else { | |
| 136 for (size_t i = 0; i < arraysize(kSchemeInGCONF); ++i) { | |
| 137 ProxyServer proxy_server = GetProxyServerFromGconf( | |
| 138 client, | |
|
eroman
2009/03/30 21:25:08
nit: indent these parameters by 4 spaces instead o
| |
| 139 ProxyServer::SCHEME_HTTP, | |
| 140 kSchemeInGCONF[i].host_key, | |
| 141 kSchemeInGCONF[i].port_key); | |
| 142 | |
| 143 if (proxy_server.is_valid()) { | |
| 144 if (config->proxy_rules.size()) { | |
| 145 config->proxy_rules += ";"; | |
| 146 } | |
| 147 config->proxy_rules += kSchemeInGCONF[i].scheme; | |
| 148 config->proxy_rules += "="; | |
| 149 config->proxy_rules += proxy_server.ToURI(); | |
| 150 } | |
| 151 } | |
| 152 if (!config->proxy_rules.size()) { | |
| 153 ProxyServer proxy_server = GetProxyServerFromGconf( | |
| 154 client, | |
| 155 ProxyServer::SCHEME_SOCKS4, | |
| 156 GCONF_SOCKS_PROXY_KEY, | |
| 157 GCONF_SOCKS_PROXY_PORT_KEY); | |
| 158 | |
| 159 if (proxy_server.is_valid()) { | |
| 160 config->proxy_rules += proxy_server.ToURI(); | |
| 161 } | |
| 162 } | |
| 163 } | |
| 164 } | |
| 165 if (res && config->proxy_rules.size()) { | |
| 166 GSList* list; | |
| 167 | |
| 168 list = gconf_client_get_list(client, GCONF_PROXY_BYPASS_LIST_KEY, | |
| 169 GCONF_VALUE_STRING, NULL); | |
|
eroman
2009/03/30 21:25:08
nit: two more spaces to line this up.
| |
| 170 config->proxy_bypass.clear(); | |
| 171 | |
| 172 for (GSList* i = list; i; i = g_slist_next(i)) { | |
| 173 if (i->data) | |
| 174 config->proxy_bypass.push_back(static_cast<gchar*>(i->data)); | |
| 175 } | |
| 176 | |
| 177 g_slist_foreach(list, GFunc(g_free), NULL); | |
| 178 g_slist_free(list); | |
| 179 } | |
| 180 } | |
| 181 g_free(mode); | |
| 182 } else { | |
| 183 res = false; | |
| 184 } | |
| 185 | |
| 186 g_object_unref(client); | |
| 187 return res; | |
| 188 } | |
| 189 | |
| 190 const struct SchemeInEnv { | |
| 191 const gchar* scheme; | |
| 192 const gchar* env_name; | |
| 193 } kSchemeInEnv[] = { | |
|
eroman
2009/03/30 21:25:08
nit: can you make this "static" ?
| |
| 194 {"http", "http_proxy"}, | |
| 195 {"https", "https_proxy"}, | |
| 196 {"ftp", "ftp_proxy"}, | |
| 197 }; | |
| 198 | |
| 199 bool GetProxyConfigEnv(ProxyConfig* config) { | |
| 200 gchar* no_proxy = g_strdup(g_getenv("no_proxy")); | |
| 201 gchar* socks_ver = g_strdup(g_getenv("SOCKS_VERSION")); | |
| 202 gchar* socks_server = g_strdup(g_getenv("SOCKS_SERVER")); | |
| 203 gchar* auto_proxy = g_strdup(g_getenv("auto_proxy")); | |
| 204 bool res = true; | |
| 205 | |
| 206 config->proxy_rules = ""; | |
| 207 | |
| 208 if (auto_proxy != NULL) { | |
|
eroman
2009/03/30 21:25:08
nit: for consistency, consider "if (auto_proxy)"
| |
| 209 if (strlen(auto_proxy) == 0) | |
| 210 config->auto_detect = true; | |
| 211 else | |
| 212 config->pac_url = GURL(auto_proxy); | |
| 213 } | |
| 214 | |
| 215 if (socks_ver != NULL && socks_server != NULL) { | |
|
eroman
2009/03/30 21:25:08
nit: for consistency consider omitting "!= NULL"
| |
| 216 int ver = 0; | |
| 217 ProxyServer server; | |
| 218 | |
| 219 ver = atoi(socks_ver); | |
| 220 if (ver != 4 && ver != 5) | |
| 221 ver = 4; | |
| 222 | |
| 223 if (strncmp(socks_server, "socks", 5) == 0) { | |
| 224 server = ProxyServer::FromURI(socks_server); | |
| 225 } else { | |
| 226 if (ver == 4) | |
| 227 server = ProxyServer::FromURI("socks4://" + std::string(socks_server)); | |
| 228 else | |
| 229 server = ProxyServer::FromURI("socks5://" + std::string(socks_server)); | |
| 230 } | |
| 231 if (!server.is_valid()) | |
| 232 res = false; | |
| 233 else | |
| 234 config->proxy_rules += server.ToURI(); | |
| 235 } else { | |
| 236 gchar* all_proxy = g_strdup(g_getenv("all_proxy")); | |
| 237 if (all_proxy != NULL) { | |
|
eroman
2009/03/30 21:25:08
nit: for consistency consider omitting "!= NULL".
| |
| 238 ProxyServer server = ProxyServer::FromURI(all_proxy); | |
| 239 if (!server.is_valid()) | |
| 240 res = false; | |
| 241 else | |
| 242 config->proxy_rules = server.ToURI(); | |
| 243 } else { | |
| 244 for (size_t i = 0; i < arraysize(kSchemeInEnv); ++i) { | |
| 245 gchar* proxy = g_strdup(g_getenv(kSchemeInEnv[i].env_name)); | |
| 246 if (proxy != NULL) { | |
|
eroman
2009/03/30 21:25:08
nit: for consistency consider omitting "!= NULL".
| |
| 247 ProxyServer server = ProxyServer::FromURI(proxy); | |
| 248 if (server.is_valid()) { | |
| 249 if (config->proxy_rules.size() > 1) | |
|
eroman
2009/03/30 21:25:08
I believe you can just test > 0 here (i.e. not emp
| |
| 250 config->proxy_rules += ";"; | |
| 251 config->proxy_rules += kSchemeInEnv[i].scheme; | |
| 252 config->proxy_rules += "="; | |
| 253 config->proxy_rules += server.ToURI(); | |
| 254 } | |
| 255 } | |
| 256 g_free(proxy); | |
| 257 } | |
| 258 } | |
| 259 g_free(all_proxy); | |
| 260 } | |
| 261 | |
| 262 if (no_proxy) { | |
| 263 std::string str; | |
| 264 for (size_t i = 0, k = strlen(no_proxy); i < k; i++) { | |
| 265 if (no_proxy[i] != ' ') | |
| 266 str += no_proxy[i]; | |
|
eroman
2009/03/30 21:25:08
instead of stripping whitespace here, I would sugg
| |
| 267 } | |
| 268 StringTokenizer proxy_server_bypass_list(str, ","); | |
| 269 while (proxy_server_bypass_list.GetNext()) { | |
| 270 int i[4]; | |
| 271 std::string bypass_url_domain = proxy_server_bypass_list.token(); | |
| 272 if (sscanf(bypass_url_domain.c_str(), "%d.%d.%d.%d", | |
|
eroman
2009/03/30 21:25:08
I recommend using GURL to test if it is an IP addr
| |
| 273 i, i + 1, i + 2, i + 3) == 4) { | |
| 274 config->proxy_bypass.push_back(bypass_url_domain); | |
| 275 } else { | |
| 276 config->proxy_bypass.push_back("*" + bypass_url_domain); | |
| 277 } | |
| 278 } | |
| 279 } | |
| 280 | |
| 281 g_free(no_proxy); | |
| 282 g_free(socks_ver); | |
| 283 g_free(socks_server); | |
| 284 g_free(auto_proxy); | |
| 285 return res; | |
| 286 } | |
| 287 | |
| 288 int ProxyConfigServiceLinux::GetProxyConfig(ProxyConfig* config) { | |
| 289 if (g_getenv("DESKTOP_SESSION") && | |
| 290 strcmp(g_getenv("DESKTOP_SESSION"), "gnome") == 0 || | |
| 291 g_getenv("GNOME_DESKTOP_SESSION_ID")) { | |
| 292 gdk_threads_enter(); | |
| 293 if (GetProxyConfigGCONF(config)) { | |
| 294 gdk_threads_leave(); | |
| 295 return OK; | |
| 296 } | |
| 297 gdk_threads_leave(); | |
| 298 } | |
| 299 | |
| 300 if (GetProxyConfigEnv(config)) { | |
| 301 return OK; | |
| 302 } | |
| 303 return ERR_FAILED; | |
| 304 } | |
| 305 | |
| 306 } // namespace net | |
| OLD | NEW |