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 |