Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright 2010, 2013 Red Hat, Inc.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see
19 : : * <http://www.gnu.org/licenses/>.
20 : : */
21 : :
22 : : #include "config.h"
23 : :
24 : : #include <stdlib.h>
25 : : #include <string.h>
26 : :
27 : : #include "gsimpleproxyresolver.h"
28 : : #include "ginetaddress.h"
29 : : #include "ginetaddressmask.h"
30 : : #include "gnetworkingprivate.h"
31 : : #include "gtask.h"
32 : :
33 : : #include "glibintl.h"
34 : :
35 : : /**
36 : : * GSimpleProxyResolver:
37 : : *
38 : : * `GSimpleProxyResolver` is a simple [iface@Gio.ProxyResolver] implementation
39 : : * that handles a single default proxy, multiple URI-scheme-specific
40 : : * proxies, and a list of hosts that proxies should not be used for.
41 : : *
42 : : * `GSimpleProxyResolver` is never the default proxy resolver, but it
43 : : * can be used as the base class for another proxy resolver
44 : : * implementation, or it can be created and used manually, such as
45 : : * with [method@Gio.SocketClient.set_proxy_resolver].
46 : : *
47 : : * Since: 2.36
48 : : */
49 : :
50 : : typedef struct {
51 : : gchar *name;
52 : : gsize length;
53 : : gushort port;
54 : : } GSimpleProxyResolverDomain;
55 : :
56 : : struct _GSimpleProxyResolverPrivate {
57 : : gchar *default_proxy, **ignore_hosts;
58 : : GHashTable *uri_proxies;
59 : :
60 : : GPtrArray *ignore_ips;
61 : : GSimpleProxyResolverDomain *ignore_domains;
62 : : };
63 : :
64 : : static void g_simple_proxy_resolver_iface_init (GProxyResolverInterface *iface);
65 : :
66 [ + + + - : 119 : G_DEFINE_TYPE_WITH_CODE (GSimpleProxyResolver, g_simple_proxy_resolver, G_TYPE_OBJECT,
+ + ]
67 : : G_ADD_PRIVATE (GSimpleProxyResolver)
68 : : G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER,
69 : : g_simple_proxy_resolver_iface_init))
70 : :
71 : : enum
72 : : {
73 : : PROP_0,
74 : : PROP_DEFAULT_PROXY,
75 : : PROP_IGNORE_HOSTS
76 : : };
77 : :
78 : : static void reparse_ignore_hosts (GSimpleProxyResolver *resolver);
79 : :
80 : : static void
81 : 7 : g_simple_proxy_resolver_finalize (GObject *object)
82 : : {
83 : 7 : GSimpleProxyResolver *resolver = G_SIMPLE_PROXY_RESOLVER (object);
84 : 7 : GSimpleProxyResolverPrivate *priv = resolver->priv;
85 : :
86 : 7 : g_free (priv->default_proxy);
87 : 7 : g_hash_table_destroy (priv->uri_proxies);
88 : :
89 : 7 : g_clear_pointer (&priv->ignore_hosts, g_strfreev);
90 : : /* This will free ignore_ips and ignore_domains */
91 : 7 : reparse_ignore_hosts (resolver);
92 : :
93 : 7 : G_OBJECT_CLASS (g_simple_proxy_resolver_parent_class)->finalize (object);
94 : 7 : }
95 : :
96 : : static void
97 : 7 : g_simple_proxy_resolver_init (GSimpleProxyResolver *resolver)
98 : : {
99 : 7 : resolver->priv = g_simple_proxy_resolver_get_instance_private (resolver);
100 : 7 : resolver->priv->uri_proxies = g_hash_table_new_full (g_str_hash, g_str_equal,
101 : : g_free, g_free);
102 : 7 : }
103 : :
104 : : static void
105 : 12 : g_simple_proxy_resolver_set_property (GObject *object,
106 : : guint prop_id,
107 : : const GValue *value,
108 : : GParamSpec *pspec)
109 : : {
110 : 12 : GSimpleProxyResolver *resolver = G_SIMPLE_PROXY_RESOLVER (object);
111 : :
112 [ + + - ]: 12 : switch (prop_id)
113 : : {
114 : 6 : case PROP_DEFAULT_PROXY:
115 : 6 : g_simple_proxy_resolver_set_default_proxy (resolver, g_value_get_string (value));
116 : 6 : break;
117 : :
118 : 6 : case PROP_IGNORE_HOSTS:
119 : 6 : g_simple_proxy_resolver_set_ignore_hosts (resolver, g_value_get_boxed (value));
120 : 6 : break;
121 : :
122 : 0 : default:
123 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
124 : : }
125 : 12 : }
126 : :
127 : : static void
128 : 2 : g_simple_proxy_resolver_get_property (GObject *object,
129 : : guint prop_id,
130 : : GValue *value,
131 : : GParamSpec *pspec)
132 : : {
133 : 2 : GSimpleProxyResolver *resolver = G_SIMPLE_PROXY_RESOLVER (object);
134 : :
135 [ + + - ]: 2 : switch (prop_id)
136 : : {
137 : 1 : case PROP_DEFAULT_PROXY:
138 : 1 : g_value_set_string (value, resolver->priv->default_proxy);
139 : 1 : break;
140 : :
141 : 1 : case PROP_IGNORE_HOSTS:
142 : 1 : g_value_set_boxed (value, resolver->priv->ignore_hosts);
143 : 1 : break;
144 : :
145 : 0 : default:
146 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
147 : : }
148 : 2 : }
149 : :
150 : : static void
151 : 13 : reparse_ignore_hosts (GSimpleProxyResolver *resolver)
152 : 5 : {
153 : 13 : GSimpleProxyResolverPrivate *priv = resolver->priv;
154 : : GPtrArray *ignore_ips;
155 : : GArray *ignore_domains;
156 : : gchar *host, *tmp, *colon, *bracket;
157 : : GInetAddress *iaddr;
158 : : GInetAddressMask *mask;
159 : : GSimpleProxyResolverDomain domain;
160 : : gushort port;
161 : : int i;
162 : :
163 [ + + ]: 13 : if (priv->ignore_ips)
164 : 6 : g_ptr_array_free (priv->ignore_ips, TRUE);
165 [ + + ]: 13 : if (priv->ignore_domains)
166 : : {
167 [ + + ]: 6 : for (i = 0; priv->ignore_domains[i].name; i++)
168 : 5 : g_free (priv->ignore_domains[i].name);
169 : 1 : g_free (priv->ignore_domains);
170 : : }
171 : 13 : priv->ignore_ips = NULL;
172 : 13 : priv->ignore_domains = NULL;
173 : :
174 [ + + - + ]: 13 : if (!priv->ignore_hosts || !priv->ignore_hosts[0])
175 : 7 : return;
176 : :
177 : 6 : ignore_ips = g_ptr_array_new_with_free_func (g_object_unref);
178 : 6 : ignore_domains = g_array_new (TRUE, FALSE, sizeof (GSimpleProxyResolverDomain));
179 : :
180 [ + + ]: 19 : for (i = 0; priv->ignore_hosts[i]; i++)
181 : : {
182 : 13 : host = g_strchomp (priv->ignore_hosts[i]);
183 : :
184 : : /* See if it's an IP address or IP/length mask */
185 : 13 : mask = g_inet_address_mask_new_from_string (host, NULL);
186 [ + + ]: 13 : if (mask)
187 : : {
188 : 8 : g_ptr_array_add (ignore_ips, mask);
189 : 8 : continue;
190 : : }
191 : :
192 : 5 : port = 0;
193 : :
194 [ - + ]: 5 : if (*host == '[')
195 : : {
196 : : /* [IPv6]:port */
197 : 0 : host++;
198 : 0 : bracket = strchr (host, ']');
199 [ # # # # : 0 : if (!bracket || !bracket[1] || bracket[1] != ':')
# # ]
200 : 0 : goto bad;
201 : :
202 : 0 : port = strtoul (bracket + 2, &tmp, 10);
203 [ # # ]: 0 : if (*tmp)
204 : 0 : goto bad;
205 : :
206 : 0 : *bracket = '\0';
207 : : }
208 : : else
209 : : {
210 : 5 : colon = strchr (host, ':');
211 [ + + + - ]: 5 : if (colon && !strchr (colon + 1, ':'))
212 : : {
213 : : /* hostname:port or IPv4:port */
214 : 2 : port = strtoul (colon + 1, &tmp, 10);
215 [ - + ]: 2 : if (*tmp)
216 : 0 : goto bad;
217 : 2 : *colon = '\0';
218 : : }
219 : : }
220 : :
221 : 5 : iaddr = g_inet_address_new_from_string (host);
222 [ + + ]: 5 : if (iaddr)
223 : 1 : g_object_unref (iaddr);
224 : : else
225 : : {
226 [ + - - + : 4 : if (g_str_has_prefix (host, "*."))
+ - + + ]
227 : 2 : host += 2;
228 [ + + ]: 2 : else if (*host == '.')
229 : 1 : host++;
230 : : }
231 : :
232 : 5 : memset (&domain, 0, sizeof (domain));
233 : 5 : domain.name = g_strdup (host);
234 : 5 : domain.length = strlen (domain.name);
235 : 5 : domain.port = port;
236 : 5 : g_array_append_val (ignore_domains, domain);
237 : 5 : continue;
238 : :
239 : 0 : bad:
240 : 0 : g_warning ("Ignoring invalid ignore_hosts value '%s'", host);
241 : : }
242 : :
243 [ + - ]: 6 : if (ignore_ips->len)
244 : 6 : priv->ignore_ips = ignore_ips;
245 : : else
246 : 0 : g_ptr_array_free (ignore_ips, TRUE);
247 : :
248 [ + + ]: 6 : if (ignore_domains->len)
249 : 1 : priv->ignore_domains = (GSimpleProxyResolverDomain *)ignore_domains->data;
250 : 6 : g_array_free (ignore_domains, ignore_domains->len == 0);
251 : : }
252 : :
253 : : static gboolean
254 : 58 : ignore_host (GSimpleProxyResolver *resolver,
255 : : const gchar *host,
256 : : gushort port)
257 : : {
258 : 58 : GSimpleProxyResolverPrivate *priv = resolver->priv;
259 : 58 : gchar *ascii_host = NULL;
260 : 58 : gboolean ignore = FALSE;
261 : : gsize offset, length;
262 : : guint i;
263 : :
264 [ + - ]: 58 : if (priv->ignore_ips)
265 : : {
266 : : GInetAddress *iaddr;
267 : :
268 : 58 : iaddr = g_inet_address_new_from_string (host);
269 [ + + ]: 58 : if (iaddr)
270 : : {
271 [ + + ]: 48 : for (i = 0; i < priv->ignore_ips->len; i++)
272 : : {
273 : 40 : GInetAddressMask *mask = priv->ignore_ips->pdata[i];
274 : :
275 [ + + ]: 40 : if (g_inet_address_mask_matches (mask, iaddr))
276 : : {
277 : 10 : ignore = TRUE;
278 : 10 : break;
279 : : }
280 : : }
281 : :
282 : 18 : g_object_unref (iaddr);
283 [ + + ]: 18 : if (ignore)
284 : 10 : return TRUE;
285 : : }
286 : : }
287 : :
288 [ + + ]: 48 : if (priv->ignore_domains)
289 : : {
290 : 38 : length = 0;
291 [ - + ]: 38 : if (g_hostname_is_non_ascii (host))
292 : 0 : host = ascii_host = g_hostname_to_ascii (host);
293 [ + - ]: 38 : if (host)
294 : 38 : length = strlen (host);
295 : :
296 [ + - + + ]: 163 : for (i = 0; length > 0 && priv->ignore_domains[i].length; i++)
297 : : {
298 : 143 : GSimpleProxyResolverDomain *domain = &priv->ignore_domains[i];
299 : :
300 [ + + ]: 143 : if (domain->length > length)
301 : 18 : continue;
302 : :
303 : 125 : offset = length - domain->length;
304 [ + + + + : 125 : if ((domain->port == 0 || domain->port == port) &&
+ + ]
305 [ + - + + : 131 : (offset == 0 || (offset > 0 && host[offset - 1] == '.')) &&
+ + ]
306 : 67 : (g_ascii_strcasecmp (domain->name, host + offset) == 0))
307 : : {
308 : 18 : ignore = TRUE;
309 : 18 : break;
310 : : }
311 : : }
312 : :
313 : 38 : g_free (ascii_host);
314 : : }
315 : :
316 : 48 : return ignore;
317 : : }
318 : :
319 : : static gchar **
320 : 58 : g_simple_proxy_resolver_lookup (GProxyResolver *proxy_resolver,
321 : : const gchar *uri,
322 : : GCancellable *cancellable,
323 : : GError **error)
324 : : {
325 : 58 : GSimpleProxyResolver *resolver = G_SIMPLE_PROXY_RESOLVER (proxy_resolver);
326 : 58 : GSimpleProxyResolverPrivate *priv = resolver->priv;
327 : 58 : const gchar *proxy = NULL;
328 : : gchar **proxies;
329 : :
330 [ - + - - ]: 58 : if (priv->ignore_ips || priv->ignore_domains)
331 : : {
332 : 58 : gchar *host = NULL;
333 : : gint port;
334 : :
335 [ + - ]: 58 : if (g_uri_split_network (uri, G_URI_FLAGS_NONE, NULL,
336 [ + + ]: 58 : &host, &port, NULL) &&
337 : 58 : ignore_host (resolver, host, port > 0 ? port : 0))
338 : 28 : proxy = "direct://";
339 : :
340 : 58 : g_free (host);
341 : : }
342 : :
343 [ + + + + ]: 58 : if (!proxy && g_hash_table_size (priv->uri_proxies))
344 : : {
345 : 7 : gchar *scheme = g_ascii_strdown (uri, strcspn (uri, ":"));
346 : :
347 : 7 : proxy = g_hash_table_lookup (priv->uri_proxies, scheme);
348 : 7 : g_free (scheme);
349 : : }
350 : :
351 [ + + ]: 58 : if (!proxy)
352 : 26 : proxy = priv->default_proxy;
353 [ + + ]: 58 : if (!proxy)
354 : 2 : proxy = "direct://";
355 : :
356 [ + + ]: 58 : if (!strncmp (proxy, "socks://", 8))
357 : : {
358 : 2 : proxies = g_new0 (gchar *, 4);
359 : 2 : proxies[0] = g_strdup_printf ("socks5://%s", proxy + 8);
360 : 2 : proxies[1] = g_strdup_printf ("socks4a://%s", proxy + 8);
361 : 2 : proxies[2] = g_strdup_printf ("socks4://%s", proxy + 8);
362 : 2 : proxies[3] = NULL;
363 : : }
364 : : else
365 : : {
366 : 56 : proxies = g_new0 (gchar *, 2);
367 : 56 : proxies[0] = g_strdup (proxy);
368 : : }
369 : :
370 : 58 : return proxies;
371 : : }
372 : :
373 : : static void
374 : 1 : g_simple_proxy_resolver_lookup_async (GProxyResolver *proxy_resolver,
375 : : const gchar *uri,
376 : : GCancellable *cancellable,
377 : : GAsyncReadyCallback callback,
378 : : gpointer user_data)
379 : : {
380 : 1 : GSimpleProxyResolver *resolver = G_SIMPLE_PROXY_RESOLVER (proxy_resolver);
381 : : GTask *task;
382 : 1 : GError *error = NULL;
383 : : char **proxies;
384 : :
385 : 1 : task = g_task_new (resolver, cancellable, callback, user_data);
386 [ + - ]: 1 : g_task_set_source_tag (task, g_simple_proxy_resolver_lookup_async);
387 : :
388 : 1 : proxies = g_simple_proxy_resolver_lookup (proxy_resolver, uri,
389 : : cancellable, &error);
390 [ + - ]: 1 : if (proxies)
391 : 1 : g_task_return_pointer (task, proxies, (GDestroyNotify)g_strfreev);
392 : : else
393 : 0 : g_task_return_error (task, error);
394 : 1 : g_object_unref (task);
395 : 1 : }
396 : :
397 : : static gchar **
398 : 1 : g_simple_proxy_resolver_lookup_finish (GProxyResolver *resolver,
399 : : GAsyncResult *result,
400 : : GError **error)
401 : : {
402 : 1 : g_return_val_if_fail (g_task_is_valid (result, resolver), NULL);
403 : :
404 : 1 : return g_task_propagate_pointer (G_TASK (result), error);
405 : : }
406 : :
407 : : static void
408 : 3 : g_simple_proxy_resolver_class_init (GSimpleProxyResolverClass *resolver_class)
409 : : {
410 : 3 : GObjectClass *object_class = G_OBJECT_CLASS (resolver_class);
411 : :
412 : 3 : object_class->get_property = g_simple_proxy_resolver_get_property;
413 : 3 : object_class->set_property = g_simple_proxy_resolver_set_property;
414 : 3 : object_class->finalize = g_simple_proxy_resolver_finalize;
415 : :
416 : : /**
417 : : * GSimpleProxyResolver:default-proxy:
418 : : *
419 : : * The default proxy URI that will be used for any URI that doesn't
420 : : * match #GSimpleProxyResolver:ignore-hosts, and doesn't match any
421 : : * of the schemes set with g_simple_proxy_resolver_set_uri_proxy().
422 : : *
423 : : * Note that as a special case, if this URI starts with
424 : : * "socks://", #GSimpleProxyResolver will treat it as referring
425 : : * to all three of the socks5, socks4a, and socks4 proxy types.
426 : : */
427 : 3 : g_object_class_install_property (object_class, PROP_DEFAULT_PROXY,
428 : : g_param_spec_string ("default-proxy", NULL, NULL,
429 : : NULL,
430 : : G_PARAM_READWRITE |
431 : : G_PARAM_STATIC_STRINGS));
432 : :
433 : : /**
434 : : * GSimpleProxyResolver:ignore-hosts:
435 : : *
436 : : * A list of hostnames and IP addresses that the resolver should
437 : : * allow direct connections to.
438 : : *
439 : : * Entries can be in one of 4 formats:
440 : : *
441 : : * - A hostname, such as "example.com", ".example.com", or
442 : : * "*.example.com", any of which match "example.com" or
443 : : * any subdomain of it.
444 : : *
445 : : * - An IPv4 or IPv6 address, such as "192.168.1.1",
446 : : * which matches only that address.
447 : : *
448 : : * - A hostname or IP address followed by a port, such as
449 : : * "example.com:80", which matches whatever the hostname or IP
450 : : * address would match, but only for URLs with the (explicitly)
451 : : * indicated port. In the case of an IPv6 address, the address
452 : : * part must appear in brackets: "[::1]:443"
453 : : *
454 : : * - An IP address range, given by a base address and prefix length,
455 : : * such as "fe80::/10", which matches any address in that range.
456 : : *
457 : : * Note that when dealing with Unicode hostnames, the matching is
458 : : * done against the ASCII form of the name.
459 : : *
460 : : * Also note that hostname exclusions apply only to connections made
461 : : * to hosts identified by name, and IP address exclusions apply only
462 : : * to connections made to hosts identified by address. That is, if
463 : : * example.com has an address of 192.168.1.1, and the :ignore-hosts list
464 : : * contains only "192.168.1.1", then a connection to "example.com"
465 : : * (eg, via a #GNetworkAddress) will use the proxy, and a connection to
466 : : * "192.168.1.1" (eg, via a #GInetSocketAddress) will not.
467 : : *
468 : : * These rules match the "ignore-hosts"/"noproxy" rules most
469 : : * commonly used by other applications.
470 : : */
471 : 3 : g_object_class_install_property (object_class, PROP_IGNORE_HOSTS,
472 : : g_param_spec_boxed ("ignore-hosts", NULL, NULL,
473 : : G_TYPE_STRV,
474 : : G_PARAM_READWRITE |
475 : : G_PARAM_STATIC_STRINGS));
476 : :
477 : 3 : }
478 : :
479 : : static void
480 : 3 : g_simple_proxy_resolver_iface_init (GProxyResolverInterface *iface)
481 : : {
482 : 3 : iface->lookup = g_simple_proxy_resolver_lookup;
483 : 3 : iface->lookup_async = g_simple_proxy_resolver_lookup_async;
484 : 3 : iface->lookup_finish = g_simple_proxy_resolver_lookup_finish;
485 : 3 : }
486 : :
487 : : /**
488 : : * g_simple_proxy_resolver_new:
489 : : * @default_proxy: (nullable): the default proxy to use, eg
490 : : * "socks://192.168.1.1"
491 : : * @ignore_hosts: (array zero-terminated=1) (nullable): an optional list of hosts/IP addresses
492 : : * to not use a proxy for.
493 : : *
494 : : * Creates a new #GSimpleProxyResolver. See
495 : : * #GSimpleProxyResolver:default-proxy and
496 : : * #GSimpleProxyResolver:ignore-hosts for more details on how the
497 : : * arguments are interpreted.
498 : : *
499 : : * Returns: (transfer full): a new #GSimpleProxyResolver
500 : : *
501 : : * Since: 2.36
502 : : */
503 : : GProxyResolver *
504 : 6 : g_simple_proxy_resolver_new (const gchar *default_proxy,
505 : : gchar **ignore_hosts)
506 : : {
507 : 6 : return g_object_new (G_TYPE_SIMPLE_PROXY_RESOLVER,
508 : : "default-proxy", default_proxy,
509 : : "ignore-hosts", ignore_hosts,
510 : : NULL);
511 : : }
512 : :
513 : : /**
514 : : * g_simple_proxy_resolver_set_default_proxy:
515 : : * @resolver: a #GSimpleProxyResolver
516 : : * @default_proxy: (nullable): the default proxy to use
517 : : *
518 : : * Sets the default proxy on @resolver, to be used for any URIs that
519 : : * don't match #GSimpleProxyResolver:ignore-hosts or a proxy set
520 : : * via g_simple_proxy_resolver_set_uri_proxy().
521 : : *
522 : : * If @default_proxy starts with "socks://",
523 : : * #GSimpleProxyResolver will treat it as referring to all three of
524 : : * the socks5, socks4a, and socks4 proxy types.
525 : : *
526 : : * Since: 2.36
527 : : */
528 : : void
529 : 6 : g_simple_proxy_resolver_set_default_proxy (GSimpleProxyResolver *resolver,
530 : : const gchar *default_proxy)
531 : : {
532 : 6 : g_return_if_fail (G_IS_SIMPLE_PROXY_RESOLVER (resolver));
533 : 6 : g_return_if_fail (default_proxy == NULL || g_uri_is_valid (default_proxy, G_URI_FLAGS_NONE, NULL));
534 : :
535 : 6 : g_free (resolver->priv->default_proxy);
536 : 6 : resolver->priv->default_proxy = g_strdup (default_proxy);
537 : 6 : g_object_notify (G_OBJECT (resolver), "default-proxy");
538 : : }
539 : :
540 : : /**
541 : : * g_simple_proxy_resolver_set_ignore_hosts:
542 : : * @resolver: a #GSimpleProxyResolver
543 : : * @ignore_hosts: (array zero-terminated=1): %NULL-terminated list of hosts/IP addresses
544 : : * to not use a proxy for
545 : : *
546 : : * Sets the list of ignored hosts.
547 : : *
548 : : * See #GSimpleProxyResolver:ignore-hosts for more details on how the
549 : : * @ignore_hosts argument is interpreted.
550 : : *
551 : : * Since: 2.36
552 : : */
553 : : void
554 : 6 : g_simple_proxy_resolver_set_ignore_hosts (GSimpleProxyResolver *resolver,
555 : : gchar **ignore_hosts)
556 : : {
557 : 6 : g_return_if_fail (G_IS_SIMPLE_PROXY_RESOLVER (resolver));
558 : :
559 : 6 : g_strfreev (resolver->priv->ignore_hosts);
560 : 6 : resolver->priv->ignore_hosts = g_strdupv (ignore_hosts);
561 : 6 : reparse_ignore_hosts (resolver);
562 : 6 : g_object_notify (G_OBJECT (resolver), "ignore-hosts");
563 : : }
564 : :
565 : : /**
566 : : * g_simple_proxy_resolver_set_uri_proxy:
567 : : * @resolver: a #GSimpleProxyResolver
568 : : * @uri_scheme: the URI scheme to add a proxy for
569 : : * @proxy: the proxy to use for @uri_scheme
570 : : *
571 : : * Adds a URI-scheme-specific proxy to @resolver; URIs whose scheme
572 : : * matches @uri_scheme (and which don't match
573 : : * #GSimpleProxyResolver:ignore-hosts) will be proxied via @proxy.
574 : : *
575 : : * As with #GSimpleProxyResolver:default-proxy, if @proxy starts with
576 : : * "socks://", #GSimpleProxyResolver will treat it
577 : : * as referring to all three of the socks5, socks4a, and socks4 proxy
578 : : * types.
579 : : *
580 : : * Since: 2.36
581 : : */
582 : : void
583 : 3 : g_simple_proxy_resolver_set_uri_proxy (GSimpleProxyResolver *resolver,
584 : : const gchar *uri_scheme,
585 : : const gchar *proxy)
586 : : {
587 : 3 : g_return_if_fail (G_IS_SIMPLE_PROXY_RESOLVER (resolver));
588 : :
589 : 3 : g_hash_table_replace (resolver->priv->uri_proxies,
590 : 3 : g_ascii_strdown (uri_scheme, -1),
591 : 3 : g_strdup (proxy));
592 : : }
|