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