1 /*
2  * e-source-proxy.c
3  *
4  * This library is free software: you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation.
7  *
8  * This library is distributed in the hope that it will be useful, but
9  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11  * for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this library. If not, see <http://www.gnu.org/licenses/>.
15  *
16  */
17 
18 /**
19  * SECTION: e-source-proxy
20  * @include: libedataserver/libedataserver.h
21  * @short_description: #ESource extension for network proxy settings
22  *
23  * The #ESourceProxy extension defines a network proxy profile.
24  *
25  * An #ESource instance with this extension can serve as a #GProxyResolver.
26  *
27  * Access the extension as follows:
28  *
29  * |[
30  *   #include <libedataserver/libedataserver.h>
31  *
32  *   ESourceProxy *extension;
33  *
34  *   extension = e_source_get_extension (source, E_SOURCE_EXTENSION_PROXY);
35  * ]|
36  **/
37 
38 #include "evolution-data-server-config.h"
39 
40 #include <glib/gi18n-lib.h>
41 
42 #include <libedataserver/e-source-enumtypes.h>
43 #include <libedataserver/e-data-server-util.h>
44 
45 #include "e-source-proxy.h"
46 
47 typedef struct _AsyncContext AsyncContext;
48 
49 struct _ESourceProxyPrivate {
50 	EProxyMethod method;
51 	gchar *autoconfig_url;
52 	gchar **ignore_hosts;
53 
54 	gchar *ftp_host;
55 	guint16 ftp_port;
56 
57 	gchar *http_host;
58 	guint16 http_port;
59 	gboolean http_use_auth;
60 	gchar *http_auth_user;
61 	gchar *http_auth_password;
62 
63 	gchar *https_host;
64 	guint16 https_port;
65 
66 	gchar *socks_host;
67 	guint16 socks_port;
68 };
69 
70 struct _AsyncContext {
71 	gchar *uri;
72 	gchar **proxies;
73 };
74 
75 enum {
76 	PROP_0,
77 	PROP_AUTOCONFIG_URL,
78 	PROP_FTP_HOST,
79 	PROP_FTP_PORT,
80 	PROP_HTTP_AUTH_PASSWORD,
81 	PROP_HTTP_AUTH_USER,
82 	PROP_HTTP_HOST,
83 	PROP_HTTP_PORT,
84 	PROP_HTTP_USE_AUTH,
85 	PROP_HTTPS_HOST,
86 	PROP_HTTPS_PORT,
87 	PROP_IGNORE_HOSTS,
88 	PROP_METHOD,
89 	PROP_SOCKS_HOST,
90 	PROP_SOCKS_PORT
91 };
92 
G_DEFINE_TYPE_WITH_PRIVATE(ESourceProxy,e_source_proxy,E_TYPE_SOURCE_EXTENSION)93 G_DEFINE_TYPE_WITH_PRIVATE (
94 	ESourceProxy,
95 	e_source_proxy,
96 	E_TYPE_SOURCE_EXTENSION)
97 
98 static void
99 async_context_free (AsyncContext *async_context)
100 {
101 	g_free (async_context->uri);
102 	g_strfreev (async_context->proxies);
103 
104 	g_slice_free (AsyncContext, async_context);
105 }
106 
107 static gchar **
source_proxy_direct(void)108 source_proxy_direct (void)
109 {
110 	gchar **proxies;
111 
112 	proxies = g_new (gchar *, 2);
113 	proxies[0] = g_strdup ("direct://");
114 	proxies[1] = NULL;
115 
116 	return proxies;
117 }
118 
119 static gchar *
source_proxy_dup_http_proxy(ESourceProxy * extension,const gchar * http_host,guint16 http_port)120 source_proxy_dup_http_proxy (ESourceProxy *extension,
121                              const gchar *http_host,
122                              guint16 http_port)
123 {
124 	GString *http_proxy = g_string_new ("http://");
125 
126 	if (e_source_proxy_get_http_use_auth (extension)) {
127 		gchar *http_user;
128 		gchar *http_pass;
129 		gchar *enc_http_user;
130 		gchar *enc_http_pass;
131 
132 		http_user = e_source_proxy_dup_http_auth_user (extension);
133 		http_pass = e_source_proxy_dup_http_auth_password (extension);
134 
135 		enc_http_user = g_uri_escape_string (http_user, NULL, TRUE);
136 		enc_http_pass = g_uri_escape_string (http_pass, NULL, TRUE);
137 
138 		g_string_append (http_proxy, enc_http_user);
139 		g_string_append_c (http_proxy, ':');
140 		g_string_append (http_proxy, enc_http_pass);
141 		g_string_append_c (http_proxy, '@');
142 
143 		g_free (enc_http_user);
144 		g_free (enc_http_pass);
145 
146 		g_free (http_user);
147 		g_free (http_pass);
148 	}
149 
150 	g_string_append_printf (http_proxy, "%s:%u", http_host, http_port);
151 
152 	return g_string_free (http_proxy, FALSE);
153 }
154 
155 static gchar **
source_proxy_lookup_pacrunner(ESource * source,const gchar * uri,GCancellable * cancellable,GError ** error)156 source_proxy_lookup_pacrunner (ESource *source,
157                                const gchar *uri,
158                                GCancellable *cancellable,
159                                GError **error)
160 {
161 	GDBusProxy *pacrunner;
162 	ESourceProxy *extension;
163 	const gchar *extension_name;
164 	gchar *autoconfig_url;
165 	gchar **proxies = NULL;
166 
167 	extension_name = E_SOURCE_EXTENSION_PROXY;
168 	extension = e_source_get_extension (source, extension_name);
169 	autoconfig_url = e_source_proxy_dup_autoconfig_url (extension);
170 
171 	if (autoconfig_url == NULL) {
172 		proxies = source_proxy_direct ();
173 		goto exit;
174 	}
175 
176 	pacrunner = g_dbus_proxy_new_for_bus_sync (
177 		G_BUS_TYPE_SESSION,
178 		G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
179 		G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
180 		NULL,
181 		"org.gtk.GLib.PACRunner",
182 		"/org/gtk/GLib/PACRunner",
183 		"org.gtk.GLib.PACRunner",
184 		cancellable, error);
185 
186 	if (pacrunner != NULL) {
187 		GVariant *variant_proxies;
188 
189 		variant_proxies = g_dbus_proxy_call_sync (
190 			pacrunner, "Lookup",
191 			g_variant_new ("(ss)", autoconfig_url, uri),
192 			G_DBUS_CALL_FLAGS_NONE, -1,
193 			cancellable, error);
194 
195 		if (variant_proxies != NULL) {
196 			g_variant_get (variant_proxies, "(^as)", &proxies);
197 			g_variant_unref (variant_proxies);
198 		}
199 
200 		g_object_unref (pacrunner);
201 	}
202 
203 exit:
204 	g_free (autoconfig_url);
205 
206 	return proxies;
207 }
208 
209 static void
source_proxy_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)210 source_proxy_set_property (GObject *object,
211                            guint property_id,
212                            const GValue *value,
213                            GParamSpec *pspec)
214 {
215 	switch (property_id) {
216 		case PROP_AUTOCONFIG_URL:
217 			e_source_proxy_set_autoconfig_url (
218 				E_SOURCE_PROXY (object),
219 				g_value_get_string (value));
220 			return;
221 
222 		case PROP_FTP_HOST:
223 			e_source_proxy_set_ftp_host (
224 				E_SOURCE_PROXY (object),
225 				g_value_get_string (value));
226 			return;
227 
228 		case PROP_FTP_PORT:
229 			e_source_proxy_set_ftp_port (
230 				E_SOURCE_PROXY (object),
231 				g_value_get_uint (value));
232 			return;
233 
234 		case PROP_HTTP_AUTH_PASSWORD:
235 			e_source_proxy_set_http_auth_password (
236 				E_SOURCE_PROXY (object),
237 				g_value_get_string (value));
238 			return;
239 
240 		case PROP_HTTP_AUTH_USER:
241 			e_source_proxy_set_http_auth_user (
242 				E_SOURCE_PROXY (object),
243 				g_value_get_string (value));
244 			return;
245 
246 		case PROP_HTTP_HOST:
247 			e_source_proxy_set_http_host (
248 				E_SOURCE_PROXY (object),
249 				g_value_get_string (value));
250 			return;
251 
252 		case PROP_HTTP_PORT:
253 			e_source_proxy_set_http_port (
254 				E_SOURCE_PROXY (object),
255 				g_value_get_uint (value));
256 			return;
257 
258 		case PROP_HTTP_USE_AUTH:
259 			e_source_proxy_set_http_use_auth (
260 				E_SOURCE_PROXY (object),
261 				g_value_get_boolean (value));
262 			return;
263 
264 		case PROP_HTTPS_HOST:
265 			e_source_proxy_set_https_host (
266 				E_SOURCE_PROXY (object),
267 				g_value_get_string (value));
268 			return;
269 
270 		case PROP_HTTPS_PORT:
271 			e_source_proxy_set_https_port (
272 				E_SOURCE_PROXY (object),
273 				g_value_get_uint (value));
274 			return;
275 
276 		case PROP_IGNORE_HOSTS:
277 			e_source_proxy_set_ignore_hosts (
278 				E_SOURCE_PROXY (object),
279 				g_value_get_boxed (value));
280 			return;
281 
282 		case PROP_METHOD:
283 			e_source_proxy_set_method (
284 				E_SOURCE_PROXY (object),
285 				g_value_get_enum (value));
286 			return;
287 
288 		case PROP_SOCKS_HOST:
289 			e_source_proxy_set_socks_host (
290 				E_SOURCE_PROXY (object),
291 				g_value_get_string (value));
292 			return;
293 
294 		case PROP_SOCKS_PORT:
295 			e_source_proxy_set_socks_port (
296 				E_SOURCE_PROXY (object),
297 				g_value_get_uint (value));
298 			return;
299 	}
300 
301 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
302 }
303 
304 static void
source_proxy_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)305 source_proxy_get_property (GObject *object,
306                            guint property_id,
307                            GValue *value,
308                            GParamSpec *pspec)
309 {
310 	switch (property_id) {
311 		case PROP_AUTOCONFIG_URL:
312 			g_value_take_string (
313 				value,
314 				e_source_proxy_dup_autoconfig_url (
315 				E_SOURCE_PROXY (object)));
316 			return;
317 
318 		case PROP_FTP_HOST:
319 			g_value_take_string (
320 				value,
321 				e_source_proxy_dup_ftp_host (
322 				E_SOURCE_PROXY (object)));
323 			return;
324 
325 		case PROP_FTP_PORT:
326 			g_value_set_uint (
327 				value,
328 				e_source_proxy_get_ftp_port (
329 				E_SOURCE_PROXY (object)));
330 			return;
331 
332 		case PROP_HTTP_AUTH_PASSWORD:
333 			g_value_take_string (
334 				value,
335 				e_source_proxy_dup_http_auth_password (
336 				E_SOURCE_PROXY (object)));
337 			return;
338 
339 		case PROP_HTTP_AUTH_USER:
340 			g_value_take_string (
341 				value,
342 				e_source_proxy_dup_http_auth_user (
343 				E_SOURCE_PROXY (object)));
344 			return;
345 
346 		case PROP_HTTP_HOST:
347 			g_value_take_string (
348 				value,
349 				e_source_proxy_dup_http_host (
350 				E_SOURCE_PROXY (object)));
351 			return;
352 
353 		case PROP_HTTP_PORT:
354 			g_value_set_uint (
355 				value,
356 				e_source_proxy_get_http_port (
357 				E_SOURCE_PROXY (object)));
358 			return;
359 
360 		case PROP_HTTP_USE_AUTH:
361 			g_value_set_boolean (
362 				value,
363 				e_source_proxy_get_http_use_auth (
364 				E_SOURCE_PROXY (object)));
365 			return;
366 
367 		case PROP_HTTPS_HOST:
368 			g_value_take_string (
369 				value,
370 				e_source_proxy_dup_https_host (
371 				E_SOURCE_PROXY (object)));
372 			return;
373 
374 		case PROP_HTTPS_PORT:
375 			g_value_set_uint (
376 				value,
377 				e_source_proxy_get_https_port (
378 				E_SOURCE_PROXY (object)));
379 			return;
380 
381 		case PROP_IGNORE_HOSTS:
382 			g_value_take_boxed (
383 				value,
384 				e_source_proxy_dup_ignore_hosts (
385 				E_SOURCE_PROXY (object)));
386 			return;
387 
388 		case PROP_METHOD:
389 			g_value_set_enum (
390 				value,
391 				e_source_proxy_get_method (
392 				E_SOURCE_PROXY (object)));
393 			return;
394 
395 		case PROP_SOCKS_HOST:
396 			g_value_take_string (
397 				value,
398 				e_source_proxy_dup_socks_host (
399 				E_SOURCE_PROXY (object)));
400 			return;
401 
402 		case PROP_SOCKS_PORT:
403 			g_value_set_uint (
404 				value,
405 				e_source_proxy_get_socks_port (
406 				E_SOURCE_PROXY (object)));
407 			return;
408 	}
409 
410 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
411 }
412 
413 static void
source_proxy_finalize(GObject * object)414 source_proxy_finalize (GObject *object)
415 {
416 	ESourceProxyPrivate *priv;
417 
418 	priv = E_SOURCE_PROXY (object)->priv;
419 
420 	g_free (priv->autoconfig_url);
421 	g_strfreev (priv->ignore_hosts);
422 	g_free (priv->ftp_host);
423 	g_free (priv->http_host);
424 	g_free (priv->http_auth_user);
425 	g_free (priv->http_auth_password);
426 	g_free (priv->https_host);
427 	g_free (priv->socks_host);
428 
429 	/* Chain up to parent's finalize() method. */
430 	G_OBJECT_CLASS (e_source_proxy_parent_class)->finalize (object);
431 }
432 
433 static void
e_source_proxy_class_init(ESourceProxyClass * class)434 e_source_proxy_class_init (ESourceProxyClass *class)
435 {
436 	GObjectClass *object_class;
437 	ESourceExtensionClass *extension_class;
438 
439 	object_class = G_OBJECT_CLASS (class);
440 	object_class->set_property = source_proxy_set_property;
441 	object_class->get_property = source_proxy_get_property;
442 	object_class->finalize = source_proxy_finalize;
443 
444 	extension_class = E_SOURCE_EXTENSION_CLASS (class);
445 	extension_class->name = E_SOURCE_EXTENSION_PROXY;
446 
447 	g_object_class_install_property (
448 		object_class,
449 		PROP_AUTOCONFIG_URL,
450 		g_param_spec_string (
451 			"autoconfig-url",
452 			"Autoconfig URL",
453 			"Proxy autoconfiguration URL",
454 			NULL,
455 			G_PARAM_READWRITE |
456 			G_PARAM_CONSTRUCT |
457 			G_PARAM_EXPLICIT_NOTIFY |
458 			G_PARAM_STATIC_STRINGS |
459 			E_SOURCE_PARAM_SETTING));
460 
461 	g_object_class_install_property (
462 		object_class,
463 		PROP_FTP_HOST,
464 		g_param_spec_string (
465 			"ftp-host",
466 			"FTP Host",
467 			"FTP proxy host name",
468 			NULL,
469 			G_PARAM_READWRITE |
470 			G_PARAM_CONSTRUCT |
471 			G_PARAM_EXPLICIT_NOTIFY |
472 			G_PARAM_STATIC_STRINGS |
473 			E_SOURCE_PARAM_SETTING));
474 
475 	g_object_class_install_property (
476 		object_class,
477 		PROP_FTP_PORT,
478 		g_param_spec_uint (
479 			"ftp-port",
480 			"FTP Port",
481 			"FTP proxy port",
482 			0, G_MAXUINT16, 0,
483 			G_PARAM_READWRITE |
484 			G_PARAM_CONSTRUCT |
485 			G_PARAM_EXPLICIT_NOTIFY |
486 			G_PARAM_STATIC_STRINGS |
487 			E_SOURCE_PARAM_SETTING));
488 
489 	g_object_class_install_property (
490 		object_class,
491 		PROP_HTTP_AUTH_PASSWORD,
492 		g_param_spec_string (
493 			"http-auth-password",
494 			"HTTP Auth Password",
495 			"HTTP proxy password",
496 			NULL,
497 			G_PARAM_READWRITE |
498 			G_PARAM_CONSTRUCT |
499 			G_PARAM_EXPLICIT_NOTIFY |
500 			G_PARAM_STATIC_STRINGS |
501 			E_SOURCE_PARAM_SETTING));
502 
503 	g_object_class_install_property (
504 		object_class,
505 		PROP_HTTP_AUTH_USER,
506 		g_param_spec_string (
507 			"http-auth-user",
508 			"HTTP Auth User",
509 			"HTTP proxy username",
510 			NULL,
511 			G_PARAM_READWRITE |
512 			G_PARAM_CONSTRUCT |
513 			G_PARAM_EXPLICIT_NOTIFY |
514 			G_PARAM_STATIC_STRINGS |
515 			E_SOURCE_PARAM_SETTING));
516 
517 	g_object_class_install_property (
518 		object_class,
519 		PROP_HTTP_HOST,
520 		g_param_spec_string (
521 			"http-host",
522 			"HTTP Host",
523 			"HTTP proxy host name",
524 			NULL,
525 			G_PARAM_READWRITE |
526 			G_PARAM_CONSTRUCT |
527 			G_PARAM_EXPLICIT_NOTIFY |
528 			G_PARAM_STATIC_STRINGS |
529 			E_SOURCE_PARAM_SETTING));
530 
531 	g_object_class_install_property (
532 		object_class,
533 		PROP_HTTP_PORT,
534 		g_param_spec_uint (
535 			"http-port",
536 			"HTTP Port",
537 			"HTTP proxy port",
538 			0, G_MAXUINT16, 8080,
539 			G_PARAM_READWRITE |
540 			G_PARAM_CONSTRUCT |
541 			G_PARAM_EXPLICIT_NOTIFY |
542 			G_PARAM_STATIC_STRINGS |
543 			E_SOURCE_PARAM_SETTING));
544 
545 	g_object_class_install_property (
546 		object_class,
547 		PROP_HTTP_USE_AUTH,
548 		g_param_spec_boolean (
549 			"http-use-auth",
550 			"HTTP Use Auth",
551 			"Whether HTTP proxy server "
552 			"connections require authentication",
553 			FALSE,
554 			G_PARAM_READWRITE |
555 			G_PARAM_CONSTRUCT |
556 			G_PARAM_EXPLICIT_NOTIFY |
557 			G_PARAM_STATIC_STRINGS |
558 			E_SOURCE_PARAM_SETTING));
559 
560 	g_object_class_install_property (
561 		object_class,
562 		PROP_HTTPS_HOST,
563 		g_param_spec_string (
564 			"https-host",
565 			"HTTPS Host",
566 			"Secure HTTP proxy host name",
567 			NULL,
568 			G_PARAM_READWRITE |
569 			G_PARAM_CONSTRUCT |
570 			G_PARAM_EXPLICIT_NOTIFY |
571 			G_PARAM_STATIC_STRINGS |
572 			E_SOURCE_PARAM_SETTING));
573 
574 	g_object_class_install_property (
575 		object_class,
576 		PROP_HTTPS_PORT,
577 		g_param_spec_uint (
578 			"https-port",
579 			"HTTPS Port",
580 			"Secure HTTP proxy port",
581 			0, G_MAXUINT16, 0,
582 			G_PARAM_READWRITE |
583 			G_PARAM_CONSTRUCT |
584 			G_PARAM_EXPLICIT_NOTIFY |
585 			G_PARAM_STATIC_STRINGS |
586 			E_SOURCE_PARAM_SETTING));
587 
588 	g_object_class_install_property (
589 		object_class,
590 		PROP_IGNORE_HOSTS,
591 		g_param_spec_boxed (
592 			"ignore-hosts",
593 			"Ignore Hosts",
594 			"Hosts to connect directly",
595 			G_TYPE_STRV,
596 			G_PARAM_READWRITE |
597 			G_PARAM_CONSTRUCT |
598 			G_PARAM_EXPLICIT_NOTIFY |
599 			G_PARAM_STATIC_STRINGS |
600 			E_SOURCE_PARAM_SETTING));
601 
602 	g_object_class_install_property (
603 		object_class,
604 		PROP_METHOD,
605 		g_param_spec_enum (
606 			"method",
607 			"Method",
608 			"Proxy configuration method",
609 			E_TYPE_PROXY_METHOD,
610 			E_PROXY_METHOD_DEFAULT,
611 			G_PARAM_READWRITE |
612 			G_PARAM_CONSTRUCT |
613 			G_PARAM_EXPLICIT_NOTIFY |
614 			G_PARAM_STATIC_STRINGS |
615 			E_SOURCE_PARAM_SETTING));
616 
617 	g_object_class_install_property (
618 		object_class,
619 		PROP_SOCKS_HOST,
620 		g_param_spec_string (
621 			"socks-host",
622 			"SOCKS Host",
623 			"SOCKS proxy host name",
624 			NULL,
625 			G_PARAM_READWRITE |
626 			G_PARAM_CONSTRUCT |
627 			G_PARAM_EXPLICIT_NOTIFY |
628 			G_PARAM_STATIC_STRINGS |
629 			E_SOURCE_PARAM_SETTING));
630 
631 	g_object_class_install_property (
632 		object_class,
633 		PROP_SOCKS_PORT,
634 		g_param_spec_uint (
635 			"socks-port",
636 			"SOCKS Port",
637 			"SOCKS proxy port",
638 			0, G_MAXUINT16, 0,
639 			G_PARAM_READWRITE |
640 			G_PARAM_CONSTRUCT |
641 			G_PARAM_EXPLICIT_NOTIFY |
642 			G_PARAM_STATIC_STRINGS |
643 			E_SOURCE_PARAM_SETTING));
644 }
645 
646 static void
e_source_proxy_init(ESourceProxy * extension)647 e_source_proxy_init (ESourceProxy *extension)
648 {
649 	extension->priv = e_source_proxy_get_instance_private (extension);
650 }
651 
652 /**
653  * e_source_proxy_get_method:
654  * @extension: an #ESourceProxy
655  *
656  * Returns the proxy configuration method for @extension.
657  *
658  * The proxy configuration method determines the behavior of
659  * e_source_proxy_lookup().
660  *
661  * Returns: the proxy configuration method
662  *
663  * Since: 3.12
664  **/
665 EProxyMethod
e_source_proxy_get_method(ESourceProxy * extension)666 e_source_proxy_get_method (ESourceProxy *extension)
667 {
668 	g_return_val_if_fail (
669 		E_IS_SOURCE_PROXY (extension),
670 		E_PROXY_METHOD_DEFAULT);
671 
672 	return extension->priv->method;
673 }
674 
675 /**
676  * e_source_proxy_set_method:
677  * @extension: an #ESourceProxy
678  * @method: the proxy configuration method
679  *
680  * Sets the proxy configuration method for @extension.
681  *
682  * The proxy configuration method determines the behavior of
683  * e_source_proxy_lookup().
684  *
685  * Since: 3.12
686  **/
687 void
e_source_proxy_set_method(ESourceProxy * extension,EProxyMethod method)688 e_source_proxy_set_method (ESourceProxy *extension,
689                            EProxyMethod method)
690 {
691 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
692 
693 	if (method == extension->priv->method)
694 		return;
695 
696 	extension->priv->method = method;
697 
698 	g_object_notify (G_OBJECT (extension), "method");
699 }
700 
701 /**
702  * e_source_proxy_get_autoconfig_url:
703  * @extension: an #ESourceProxy
704  *
705  * Returns the URL that provides proxy configuration values.  When the
706  * @extension's #ESourceProxy:method is @E_PROXY_METHOD_AUTO, this URL
707  * is used to look up proxy information for all protocols.
708  *
709  * Returns: the autoconfiguration URL
710  *
711  * Since: 3.12
712  **/
713 const gchar *
e_source_proxy_get_autoconfig_url(ESourceProxy * extension)714 e_source_proxy_get_autoconfig_url (ESourceProxy *extension)
715 {
716 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
717 
718 	return extension->priv->autoconfig_url;
719 }
720 
721 /**
722  * e_source_proxy_dup_autoconfig_url:
723  * @extension: an #ESourceProxy
724  *
725  * Thread-safe variation of e_source_proxy_get_autoconfig_url().
726  * Use this function when accessing @extension from multiple threads.
727  *
728  * The returned string should be freed with g_free() when no longer needed.
729  *
730  * Returns: a newly-allocated copy of #ESourceProxy:autoconfig-url
731  *
732  * Since: 3.12
733  **/
734 gchar *
e_source_proxy_dup_autoconfig_url(ESourceProxy * extension)735 e_source_proxy_dup_autoconfig_url (ESourceProxy *extension)
736 {
737 	const gchar *protected;
738 	gchar *duplicate;
739 
740 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
741 
742 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
743 
744 	protected = e_source_proxy_get_autoconfig_url (extension);
745 	duplicate = g_strdup (protected);
746 
747 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
748 
749 	return duplicate;
750 }
751 
752 /**
753  * e_source_proxy_set_autoconfig_url:
754  * @extension: an #ESourceProxy
755  * @autoconfig_url: an autoconfiguration URL
756  *
757  * Sets the URL that provides proxy configuration values.  When the
758  * @extension's #ESourceProxy:method is @E_PROXY_METHOD_AUTO, this URL
759  * is used to look up proxy information for all protocols.
760  *
761  * Since: 3.12
762  **/
763 void
e_source_proxy_set_autoconfig_url(ESourceProxy * extension,const gchar * autoconfig_url)764 e_source_proxy_set_autoconfig_url (ESourceProxy *extension,
765                                    const gchar *autoconfig_url)
766 {
767 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
768 
769 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
770 
771 	if (e_util_strcmp0 (autoconfig_url, extension->priv->autoconfig_url) == 0) {
772 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
773 		return;
774 	}
775 
776 	g_free (extension->priv->autoconfig_url);
777 	extension->priv->autoconfig_url = e_util_strdup_strip (autoconfig_url);
778 
779 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
780 
781 	g_object_notify (G_OBJECT (extension), "autoconfig-url");
782 }
783 
784 /**
785  * e_source_proxy_get_ignore_hosts:
786  * @extension: an #ESourceProxy
787  *
788  * Returns a %NULL-terminated string array of hosts which are connected to
789  * directly, rather than via the proxy (if it is active).  The array elements
790  * can be hostnames, domains (using an initial wildcard like *.foo.com), IP
791  * host addresses (both IPv4 and IPv6) and network addresses with a netmask
792  * (something like 192.168.0.0/24).
793  *
794  * The returned array is owned by @extension and should not be modified or
795  * freed.
796  *
797  * Returns: (transfer none): a %NULL-terminated string array of hosts
798  *
799  * Since: 3.12
800  **/
801 const gchar * const *
e_source_proxy_get_ignore_hosts(ESourceProxy * extension)802 e_source_proxy_get_ignore_hosts (ESourceProxy *extension)
803 {
804 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
805 
806 	return (const gchar * const *) extension->priv->ignore_hosts;
807 }
808 
809 /**
810  * e_source_proxy_dup_ignore_hosts:
811  * @extension: an #ESourceProxy
812  *
813  * Thread-safe variation of e_source_proxy_get_ignore_hosts().
814  * Use this function when accessing @extension from multiple threads.
815  *
816  * The returned string array should be freed with g_strfreev() when no
817  * longer needed.
818  *
819  * Returns: (transfer full): a newly-allocated copy of
820  *          #ESourceProxy:ignore-hosts
821  *
822  * Since: 3.12
823  **/
824 gchar **
e_source_proxy_dup_ignore_hosts(ESourceProxy * extension)825 e_source_proxy_dup_ignore_hosts (ESourceProxy *extension)
826 {
827 	const gchar * const *protected;
828 	gchar **duplicate;
829 
830 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
831 
832 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
833 
834 	protected = e_source_proxy_get_ignore_hosts (extension);
835 	duplicate = g_strdupv ((gchar **) protected);
836 
837 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
838 
839 	return duplicate;
840 }
841 
842 /**
843  * e_source_proxy_set_ignore_hosts:
844  * @extension: an #ESourceProxy
845  * @ignore_hosts: a %NULL-terminated string array of hosts
846  *
847  * Sets the hosts which are connected to directly, rather than via the proxy
848  * (if it is active).  The array elements can be hostnames, domains (using an
849  * initial wildcard like *.foo.com), IP host addresses (both IPv4 and IPv6)
850  * and network addresses with a netmask (something like 192.168.0.0/24).
851  *
852  * Since: 3.12
853  **/
854 void
e_source_proxy_set_ignore_hosts(ESourceProxy * extension,const gchar * const * ignore_hosts)855 e_source_proxy_set_ignore_hosts (ESourceProxy *extension,
856                                  const gchar * const *ignore_hosts)
857 {
858 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
859 
860 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
861 
862 	if (e_util_strv_equal (ignore_hosts, extension->priv->ignore_hosts)) {
863 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
864 		return;
865 	}
866 
867 	g_strfreev (extension->priv->ignore_hosts);
868 	extension->priv->ignore_hosts = g_strdupv ((gchar **) ignore_hosts);
869 
870 	/* Strip leading and trailing whitespace from each element. */
871 	if (extension->priv->ignore_hosts != NULL) {
872 		guint length, ii;
873 
874 		length = g_strv_length (extension->priv->ignore_hosts);
875 		for (ii = 0; ii < length; ii++)
876 			g_strstrip (extension->priv->ignore_hosts[ii]);
877 	}
878 
879 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
880 
881 	g_object_notify (G_OBJECT (extension), "ignore-hosts");
882 }
883 
884 /**
885  * e_source_proxy_get_ftp_host:
886  * @extension: an #ESourceProxy
887  *
888  * Returns the machine name to proxy FTP through when @extension's
889  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
890  *
891  * Returns: FTP proxy host name
892  *
893  * Since: 3.12
894  **/
895 const gchar *
e_source_proxy_get_ftp_host(ESourceProxy * extension)896 e_source_proxy_get_ftp_host (ESourceProxy *extension)
897 {
898 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
899 
900 	return extension->priv->ftp_host;
901 }
902 
903 /**
904  * e_source_proxy_dup_ftp_host:
905  * @extension: an #ESourceProxy
906  *
907  * Thread-safe variation of e_source_proxy_get_ftp_host().
908  * Use this function when accessing @extension from multiple threads.
909  *
910  * The returned string should be freed with g_free() when no longer needed.
911  *
912  * Returns: a newly-allocated copy of #ESourceProxy:ftp-host
913  *
914  * Since: 3.12
915  **/
916 gchar *
e_source_proxy_dup_ftp_host(ESourceProxy * extension)917 e_source_proxy_dup_ftp_host (ESourceProxy *extension)
918 {
919 	const gchar *protected;
920 	gchar *duplicate;
921 
922 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
923 
924 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
925 
926 	protected = e_source_proxy_get_ftp_host (extension);
927 	duplicate = g_strdup (protected);
928 
929 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
930 
931 	return duplicate;
932 }
933 
934 /**
935  * e_source_proxy_set_ftp_host:
936  * @extension: an #ESourceProxy
937  * @ftp_host: FTP proxy host name
938  *
939  * Sets the machine name to proxy FTP through when @extension's
940  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
941  *
942  * Since: 3.12
943  **/
944 void
e_source_proxy_set_ftp_host(ESourceProxy * extension,const gchar * ftp_host)945 e_source_proxy_set_ftp_host (ESourceProxy *extension,
946                              const gchar *ftp_host)
947 {
948 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
949 
950 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
951 
952 	if (e_util_strcmp0 (ftp_host, extension->priv->ftp_host) == 0) {
953 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
954 		return;
955 	}
956 
957 	g_free (extension->priv->ftp_host);
958 	extension->priv->ftp_host = e_util_strdup_strip (ftp_host);
959 
960 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
961 
962 	g_object_notify (G_OBJECT (extension), "ftp-host");
963 }
964 
965 /**
966  * e_source_proxy_get_ftp_port:
967  * @extension: an #ESourceProxy
968  *
969  * Returns the port on the machine defined by #ESourceProxy:ftp-host to proxy
970  * through when @extension's #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
971  *
972  * Returns: FTP proxy port
973  *
974  * Since: 3.12
975  **/
976 guint16
e_source_proxy_get_ftp_port(ESourceProxy * extension)977 e_source_proxy_get_ftp_port (ESourceProxy *extension)
978 {
979 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), 0);
980 
981 	return extension->priv->ftp_port;
982 }
983 
984 /**
985  * e_source_proxy_set_ftp_port:
986  * @extension: an #ESourceProxy
987  * @ftp_port: FTP proxy port
988  *
989  * Sets the port on the machine defined by #ESourceProxy:ftp-host to proxy
990  * through when @extension's #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
991  *
992  * Since: 3.12
993  **/
994 void
e_source_proxy_set_ftp_port(ESourceProxy * extension,guint16 ftp_port)995 e_source_proxy_set_ftp_port (ESourceProxy *extension,
996                              guint16 ftp_port)
997 {
998 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
999 
1000 	if (ftp_port == extension->priv->ftp_port)
1001 		return;
1002 
1003 	extension->priv->ftp_port = ftp_port;
1004 
1005 	g_object_notify (G_OBJECT (extension), "ftp-port");
1006 }
1007 
1008 /**
1009  * e_source_proxy_get_http_host:
1010  * @extension: an #ESourceProxy
1011  *
1012  * Returns the machine name to proxy HTTP through when @extension's
1013  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1014  *
1015  * Returns: HTTP proxy host name
1016  *
1017  * Since: 3.12
1018  **/
1019 const gchar *
e_source_proxy_get_http_host(ESourceProxy * extension)1020 e_source_proxy_get_http_host (ESourceProxy *extension)
1021 {
1022 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1023 
1024 	return extension->priv->http_host;
1025 }
1026 
1027 /**
1028  * e_source_proxy_dup_http_host:
1029  * @extension: an #ESourceProxy
1030  *
1031  * Thread-safe variation of e_source_proxy_get_http_host().
1032  * Use this function when accessing @extension from multiple threads.
1033  *
1034  * The returned string should be freed with g_free() when no longer needed.
1035  *
1036  * Returns: a newly-allocated copy of #ESourceProxy:http-host
1037  *
1038  * Since: 3.12
1039  **/
1040 gchar *
e_source_proxy_dup_http_host(ESourceProxy * extension)1041 e_source_proxy_dup_http_host (ESourceProxy *extension)
1042 {
1043 	const gchar *protected;
1044 	gchar *duplicate;
1045 
1046 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1047 
1048 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1049 
1050 	protected = e_source_proxy_get_http_host (extension);
1051 	duplicate = g_strdup (protected);
1052 
1053 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1054 
1055 	return duplicate;
1056 }
1057 
1058 /**
1059  * e_source_proxy_set_http_host:
1060  * @extension: an #ESourceProxy
1061  * @http_host: HTTP proxy host name
1062  *
1063  * Sets the machine name to proxy HTTP through when @extension's
1064  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1065  *
1066  * Since: 3.12
1067  **/
1068 void
e_source_proxy_set_http_host(ESourceProxy * extension,const gchar * http_host)1069 e_source_proxy_set_http_host (ESourceProxy *extension,
1070                               const gchar *http_host)
1071 {
1072 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1073 
1074 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1075 
1076 	if (e_util_strcmp0 (http_host, extension->priv->http_host) == 0) {
1077 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1078 		return;
1079 	}
1080 
1081 	g_free (extension->priv->http_host);
1082 	extension->priv->http_host = e_util_strdup_strip (http_host);
1083 
1084 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1085 
1086 	g_object_notify (G_OBJECT (extension), "http-host");
1087 }
1088 
1089 /**
1090  * e_source_proxy_get_http_port:
1091  * @extension: an #ESourceProxy
1092  *
1093  * Returns the port on the machine defined by #ESourceProxy:http-host to proxy
1094  * through when @extension's #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1095  *
1096  * Returns: HTTP proxy port
1097  *
1098  * Since: 3.12
1099  **/
1100 guint16
e_source_proxy_get_http_port(ESourceProxy * extension)1101 e_source_proxy_get_http_port (ESourceProxy *extension)
1102 {
1103 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), 0);
1104 
1105 	return extension->priv->http_port;
1106 }
1107 
1108 /**
1109  * e_source_proxy_set_http_port:
1110  * @extension: an #ESourceProxy
1111  * @http_port: HTTP proxy port
1112  *
1113  * Sets the port on the machine defined by #ESourceProxy:http-host to proxy
1114  * through when @extension's #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1115  *
1116  * Since: 3.12
1117  **/
1118 void
e_source_proxy_set_http_port(ESourceProxy * extension,guint16 http_port)1119 e_source_proxy_set_http_port (ESourceProxy *extension,
1120                               guint16 http_port)
1121 {
1122 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1123 
1124 	if (http_port == extension->priv->http_port)
1125 		return;
1126 
1127 	extension->priv->http_port = http_port;
1128 
1129 	g_object_notify (G_OBJECT (extension), "http-port");
1130 }
1131 
1132 /**
1133  * e_source_proxy_get_http_use_auth:
1134  * @extension: an #ESourceProxy
1135  *
1136  * Returns whether the HTTP proxy server at #ESourceProxy:http-host and
1137  * #ESourceProxy:http-port requires authentication.
1138  *
1139  * The username/password combo is defined by #ESourceProxy:http-auth-user
1140  * and #ESourceProxy:http-auth-password, but only applies when @extension's
1141  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1142  *
1143  * Returns: whether to authenticate HTTP proxy connections
1144  *
1145  * Since: 3.12
1146  **/
1147 gboolean
e_source_proxy_get_http_use_auth(ESourceProxy * extension)1148 e_source_proxy_get_http_use_auth (ESourceProxy *extension)
1149 {
1150 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), FALSE);
1151 
1152 	return extension->priv->http_use_auth;
1153 }
1154 
1155 /**
1156  * e_source_proxy_set_http_use_auth:
1157  * @extension: an #ESourceProxy
1158  * @http_use_auth: whether to authenticate HTTP proxy connections
1159  *
1160  * Sets whether the HTTP proxy server at #ESourceProxy:http-host and
1161  * #ESourceProxy:http-port requires authentication.
1162  *
1163  * The username/password combo is defined by #ESourceProxy:http-auth-user
1164  * and #ESourceProxy:http-auth-password, but only applies when @extension's
1165  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1166  *
1167  * Since: 3.12
1168  **/
1169 void
e_source_proxy_set_http_use_auth(ESourceProxy * extension,gboolean http_use_auth)1170 e_source_proxy_set_http_use_auth (ESourceProxy *extension,
1171                                   gboolean http_use_auth)
1172 {
1173 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1174 
1175 	if (http_use_auth == extension->priv->http_use_auth)
1176 		return;
1177 
1178 	extension->priv->http_use_auth = http_use_auth;
1179 
1180 	g_object_notify (G_OBJECT (extension), "http-use-auth");
1181 }
1182 
1183 /**
1184  * e_source_proxy_get_http_auth_user:
1185  * @extension: an #ESourceProxy
1186  *
1187  * Returns the user name to pass as authentication when doing HTTP proxying
1188  * and #ESourceProxy:http-use-auth is %TRUE.
1189  *
1190  * Returns: HTTP proxy username
1191  *
1192  * Since: 3.12
1193  **/
1194 const gchar *
e_source_proxy_get_http_auth_user(ESourceProxy * extension)1195 e_source_proxy_get_http_auth_user (ESourceProxy *extension)
1196 {
1197 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1198 
1199 	return extension->priv->http_auth_user;
1200 }
1201 
1202 /**
1203  * e_source_proxy_dup_http_auth_user:
1204  * @extension: an #ESourceProxy
1205  *
1206  * Thread-safe variation of e_source_proxy_get_http_auth_user().
1207  * Use this function when accessing @extension from multiple threads.
1208  *
1209  * The returned string should be freed with g_free() when no longer needed.
1210  *
1211  * Returns: a newly-allocated copy of #ESourceProxy:http-auth-user
1212  *
1213  * Since: 3.12
1214  **/
1215 gchar *
e_source_proxy_dup_http_auth_user(ESourceProxy * extension)1216 e_source_proxy_dup_http_auth_user (ESourceProxy *extension)
1217 {
1218 	const gchar *protected;
1219 	gchar *duplicate;
1220 
1221 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1222 
1223 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1224 
1225 	protected = e_source_proxy_get_http_auth_user (extension);
1226 	duplicate = g_strdup (protected);
1227 
1228 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1229 
1230 	return duplicate;
1231 }
1232 
1233 /**
1234  * e_source_proxy_set_http_auth_user:
1235  * @extension: an #ESourceProxy
1236  * @http_auth_user: HTTP proxy username
1237  *
1238  * Sets the user name to pass as authentication when doing HTTP proxying
1239  * and #ESourceProxy:http-use-auth is %TRUE.
1240  *
1241  * Since: 3.12
1242  **/
1243 void
e_source_proxy_set_http_auth_user(ESourceProxy * extension,const gchar * http_auth_user)1244 e_source_proxy_set_http_auth_user (ESourceProxy *extension,
1245                                    const gchar *http_auth_user)
1246 {
1247 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1248 
1249 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1250 
1251 	if (e_util_strcmp0 (http_auth_user, extension->priv->http_auth_user) == 0) {
1252 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1253 		return;
1254 	}
1255 
1256 	g_free (extension->priv->http_auth_user);
1257 	extension->priv->http_auth_user = e_util_strdup_strip (http_auth_user);
1258 
1259 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1260 
1261 	g_object_notify (G_OBJECT (extension), "http-auth-user");
1262 }
1263 
1264 /**
1265  * e_source_proxy_get_http_auth_password:
1266  * @extension: an #ESourceProxy
1267  *
1268  * Returns the password to pass as authentication when doing HTTP proxying
1269  * and #ESourceProxy:http-use-auth is %TRUE.
1270  *
1271  * Returns: HTTP proxy password
1272  *
1273  * Since: 3.12
1274  **/
1275 const gchar *
e_source_proxy_get_http_auth_password(ESourceProxy * extension)1276 e_source_proxy_get_http_auth_password (ESourceProxy *extension)
1277 {
1278 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1279 
1280 	return extension->priv->http_auth_password;
1281 }
1282 
1283 /**
1284  * e_source_proxy_dup_http_auth_password:
1285  * @extension: an #ESourceProxy
1286  *
1287  * Thread-safe variation of e_source_proxy_get_http_auth_password().
1288  * Use this function when accessing @extension from multiple threads.
1289  *
1290  * The returned string should be freed with g_free() when no longer needed.
1291  *
1292  * Returns: a newly-allocated copy of #ESourceProxy:http-auth-password
1293  *
1294  * Since: 3.12
1295  **/
1296 gchar *
e_source_proxy_dup_http_auth_password(ESourceProxy * extension)1297 e_source_proxy_dup_http_auth_password (ESourceProxy *extension)
1298 {
1299 	const gchar *protected;
1300 	gchar *duplicate;
1301 
1302 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1303 
1304 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1305 
1306 	protected = e_source_proxy_get_http_auth_password (extension);
1307 	duplicate = g_strdup (protected);
1308 
1309 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1310 
1311 	return duplicate;
1312 }
1313 
1314 /**
1315  * e_source_proxy_set_http_auth_password:
1316  * @extension: an #ESourceProxy
1317  * @http_auth_password: HTTP proxy password
1318  *
1319  * Sets the password to pass as authentication when doing HTTP proxying
1320  * and #ESourceProxy:http-use-auth is %TRUE.
1321  *
1322  * Since: 3.12
1323  **/
1324 void
e_source_proxy_set_http_auth_password(ESourceProxy * extension,const gchar * http_auth_password)1325 e_source_proxy_set_http_auth_password (ESourceProxy *extension,
1326                                        const gchar *http_auth_password)
1327 {
1328 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1329 
1330 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1331 
1332 	if (e_util_strcmp0 (http_auth_password, extension->priv->http_auth_password) == 0) {
1333 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1334 		return;
1335 	}
1336 
1337 	g_free (extension->priv->http_auth_password);
1338 	extension->priv->http_auth_password = e_util_strdup_strip (http_auth_password);
1339 
1340 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1341 
1342 	g_object_notify (G_OBJECT (extension), "http-auth-password");
1343 }
1344 
1345 /**
1346  * e_source_proxy_get_https_host:
1347  * @extension: an #ESourceProxy
1348  *
1349  * Returns the machine name to proxy secure HTTP through when @extension's
1350  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1351  *
1352  * Returns: secure HTTP proxy host name
1353  *
1354  * Since: 3.12
1355  **/
1356 const gchar *
e_source_proxy_get_https_host(ESourceProxy * extension)1357 e_source_proxy_get_https_host (ESourceProxy *extension)
1358 {
1359 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1360 
1361 	return extension->priv->https_host;
1362 }
1363 
1364 /**
1365  * e_source_proxy_dup_https_host:
1366  * @extension: an #ESourceProxy
1367  *
1368  * Threads-safe variation of e_source_proxy_get_https_host().
1369  * Use this function when accessing @extension from multiple threads.
1370  *
1371  * The returned string should be freed with g_free() when no longer needed.
1372  *
1373  * Returns: a newly-allocated copy of #ESourceProxy:https-host
1374  *
1375  * Since: 3.12
1376  **/
1377 gchar *
e_source_proxy_dup_https_host(ESourceProxy * extension)1378 e_source_proxy_dup_https_host (ESourceProxy *extension)
1379 {
1380 	const gchar *protected;
1381 	gchar *duplicate;
1382 
1383 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1384 
1385 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1386 
1387 	protected = e_source_proxy_get_https_host (extension);
1388 	duplicate = g_strdup (protected);
1389 
1390 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1391 
1392 	return duplicate;
1393 }
1394 
1395 /**
1396  * e_source_proxy_set_https_host:
1397  * @extension: an #ESourceProxy
1398  * @https_host: secure HTTP proxy host name
1399  *
1400  * Sets the machine name to proxy secure HTTP through when @extension's
1401  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1402  *
1403  * Since: 3.12
1404  **/
1405 void
e_source_proxy_set_https_host(ESourceProxy * extension,const gchar * https_host)1406 e_source_proxy_set_https_host (ESourceProxy *extension,
1407                                const gchar *https_host)
1408 {
1409 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1410 
1411 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1412 
1413 	if (e_util_strcmp0 (https_host, extension->priv->https_host) == 0) {
1414 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1415 		return;
1416 	}
1417 
1418 	g_free (extension->priv->https_host);
1419 	extension->priv->https_host = e_util_strdup_strip (https_host);
1420 
1421 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1422 
1423 	g_object_notify (G_OBJECT (extension), "https-host");
1424 }
1425 
1426 /**
1427  * e_source_proxy_get_https_port:
1428  * @extension: an #ESourceProxy
1429  *
1430  * Returns the port on the machine defined by #ESourceProxy:https-host to proxy
1431  * through when @extension's #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1432  *
1433  * Returns: secure HTTP proxy port
1434  *
1435  * Since: 3.12
1436  **/
1437 guint16
e_source_proxy_get_https_port(ESourceProxy * extension)1438 e_source_proxy_get_https_port (ESourceProxy *extension)
1439 {
1440 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), 0);
1441 
1442 	return extension->priv->https_port;
1443 }
1444 
1445 /**
1446  * e_source_proxy_set_https_port:
1447  * @extension: an #ESourceProxy
1448  * @https_port: secure HTTP proxy port
1449  *
1450  * Sets the port on the machine defined by #ESourceProxy:https-host to proxy
1451  * through when @extension's #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1452  *
1453  * Since: 3.12
1454  **/
1455 void
e_source_proxy_set_https_port(ESourceProxy * extension,guint16 https_port)1456 e_source_proxy_set_https_port (ESourceProxy *extension,
1457                                guint16 https_port)
1458 {
1459 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1460 
1461 	if (https_port == extension->priv->https_port)
1462 		return;
1463 
1464 	extension->priv->https_port = https_port;
1465 
1466 	g_object_notify (G_OBJECT (extension), "https-port");
1467 }
1468 
1469 /**
1470  * e_source_proxy_get_socks_host:
1471  * @extension: an #ESourceProxy
1472  *
1473  * Returns the machine name to use as a SOCKS proxy when @extension's
1474  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1475  *
1476  * Returns: SOCKS proxy host name
1477  *
1478  * Since: 3.12
1479  **/
1480 const gchar *
e_source_proxy_get_socks_host(ESourceProxy * extension)1481 e_source_proxy_get_socks_host (ESourceProxy *extension)
1482 {
1483 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1484 
1485 	return extension->priv->socks_host;
1486 }
1487 
1488 /**
1489  * e_source_proxy_dup_socks_host:
1490  * @extension: an #ESourceProxy
1491  *
1492  * Thread-safe variation of e_source_proxy_get_socks_host().
1493  * Use this function when accessing @extension from multiple threads.
1494  *
1495  * The returned string should be freed with g_free() when no longer needed.
1496  *
1497  * Returns: a newly-allocated copy of #ESourceProxy:socks-host
1498  *
1499  * Since: 3.12
1500  **/
1501 gchar *
e_source_proxy_dup_socks_host(ESourceProxy * extension)1502 e_source_proxy_dup_socks_host (ESourceProxy *extension)
1503 {
1504 	const gchar *protected;
1505 	gchar *duplicate;
1506 
1507 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), NULL);
1508 
1509 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1510 
1511 	protected = e_source_proxy_get_socks_host (extension);
1512 	duplicate = g_strdup (protected);
1513 
1514 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1515 
1516 	return duplicate;
1517 }
1518 
1519 /**
1520  * e_source_proxy_set_socks_host:
1521  * @extension: an #ESourceProxy
1522  * @socks_host: SOCKS proxy host name
1523  *
1524  * Sets the machine name to use as a SOCKS proxy when @extension's
1525  * #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1526  *
1527  * Since: 3.12
1528  **/
1529 void
e_source_proxy_set_socks_host(ESourceProxy * extension,const gchar * socks_host)1530 e_source_proxy_set_socks_host (ESourceProxy *extension,
1531                                const gchar *socks_host)
1532 {
1533 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1534 
1535 	e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
1536 
1537 	if (e_util_strcmp0 (socks_host, extension->priv->socks_host) == 0) {
1538 		e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1539 		return;
1540 	}
1541 
1542 	g_free (extension->priv->socks_host);
1543 	extension->priv->socks_host = e_util_strdup_strip (socks_host);
1544 
1545 	e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
1546 
1547 	g_object_notify (G_OBJECT (extension), "socks-host");
1548 }
1549 
1550 /**
1551  * e_source_proxy_get_socks_port:
1552  * @extension: an #ESourceProxy
1553  *
1554  * Returns the port on the machine defined by #ESourceProxy:socks-host to proxy
1555  * through when @extension's #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1556  *
1557  * Returns: SOCKS proxy port
1558  *
1559  * Since: 3.12
1560  **/
1561 guint16
e_source_proxy_get_socks_port(ESourceProxy * extension)1562 e_source_proxy_get_socks_port (ESourceProxy *extension)
1563 {
1564 	g_return_val_if_fail (E_IS_SOURCE_PROXY (extension), 0);
1565 
1566 	return extension->priv->socks_port;
1567 }
1568 
1569 /**
1570  * e_source_proxy_set_socks_port:
1571  * @extension: an #ESourceProxy
1572  * @socks_port: SOCKS proxy port
1573  *
1574  * Sets the port on the machine defined by #ESourceProxy:socks-host to proxy
1575  * through when @extension's #ESourceProxy:method is @E_PROXY_METHOD_MANUAL.
1576  *
1577  * Since: 3.12
1578  **/
1579 void
e_source_proxy_set_socks_port(ESourceProxy * extension,guint16 socks_port)1580 e_source_proxy_set_socks_port (ESourceProxy *extension,
1581                                guint16 socks_port)
1582 {
1583 	g_return_if_fail (E_IS_SOURCE_PROXY (extension));
1584 
1585 	if (socks_port == extension->priv->socks_port)
1586 		return;
1587 
1588 	extension->priv->socks_port = socks_port;
1589 
1590 	g_object_notify (G_OBJECT (extension), "socks-port");
1591 }
1592 
1593 /**
1594  * e_source_proxy_lookup_sync:
1595  * @source: an #ESource
1596  * @uri: a URI representing the destination to connect to
1597  * @cancellable: optional #GCancellable object, or %NULL
1598  * @error: return location for a #GError, or %NULL
1599  *
1600  * Looks into @source's #ESourceProxy extension to determine what proxy,
1601  * if any, to use to connect to @uri.  The returned proxy URIs are of the
1602  * same form described by g_proxy_resolver_lookup().
1603  *
1604  * The proxy extension's #ESourceProxy:method controls how proxy URIs are
1605  * determined:
1606  *
1607  * When using @E_PROXY_METHOD_DEFAULT, the function will defer to the
1608  * #GProxyResolver returned by g_proxy_resolver_get_default().
1609  *
1610  * When using @E_PROXY_METHOD_MANUAL, the function will configure a
1611  * #GSimpleProxyResolver from the HTTP, HTTPS, FTP and SOCKS properties,
1612  * as well as #ESourceProxy:ignore-hosts.
1613  *
1614  * When using @E_PROXY_METHOD_AUTO, the function will execute a proxy
1615  * auto-config (PAC) file at #ESourceProxy:autoconfig-url.
1616  *
1617  * When using @E_PROXY_METHOD_NONE, the function will only return
1618  * <literal>direct://</literal>.
1619  *
1620  * If @source does not have an #ESourceProxy extension, the function sets
1621  * @error to @G_IO_ERROR_NOT_SUPPORTED and returns %NULL.
1622  *
1623  * Free the returned proxy URIs with g_strfreev() when finished with them.
1624  *
1625  * Returns: (transfer full): a %NULL-terminated array of proxy URIs, or %NULL
1626  *
1627  * Since: 3.12
1628  **/
1629 gchar **
e_source_proxy_lookup_sync(ESource * source,const gchar * uri,GCancellable * cancellable,GError ** error)1630 e_source_proxy_lookup_sync (ESource *source,
1631                             const gchar *uri,
1632                             GCancellable *cancellable,
1633                             GError **error)
1634 {
1635 	GProxyResolver *resolver = NULL;
1636 	ESourceProxy *extension;
1637 	EProxyMethod method;
1638 	const gchar *extension_name;
1639 	gchar **proxies;
1640 
1641 	g_return_val_if_fail (E_IS_SOURCE (source), NULL);
1642 	g_return_val_if_fail (uri != NULL, NULL);
1643 
1644 	extension_name = E_SOURCE_EXTENSION_PROXY;
1645 
1646 	if (!e_source_has_extension (source, extension_name)) {
1647 		g_set_error (
1648 			error, G_IO_ERROR,
1649 			G_IO_ERROR_NOT_SUPPORTED,
1650 			_("Source “%s” does not support proxy lookups"),
1651 			e_source_get_display_name (source));
1652 		return NULL;
1653 	}
1654 
1655 	extension = e_source_get_extension (source, extension_name);
1656 	method = e_source_proxy_get_method (extension);
1657 
1658 	if (method == E_PROXY_METHOD_DEFAULT) {
1659 		resolver = g_proxy_resolver_get_default ();
1660 		if (resolver != NULL)
1661 			g_object_ref (resolver);
1662 	}
1663 
1664 	if (method == E_PROXY_METHOD_MANUAL) {
1665 		gchar *ftp_proxy = NULL;
1666 		gchar *http_proxy = NULL;
1667 		gchar *https_proxy = NULL;
1668 		gchar *socks_proxy = NULL;
1669 		gchar **ignore_hosts;
1670 		gchar *host;
1671 		guint16 port;
1672 
1673 		host = e_source_proxy_dup_ftp_host (extension);
1674 		port = e_source_proxy_get_ftp_port (extension);
1675 		if (host != NULL && port > 0) {
1676 			ftp_proxy = g_strdup_printf (
1677 				"ftp://%s:%u", host, port);
1678 		}
1679 		g_free (host);
1680 
1681 		host = e_source_proxy_dup_http_host (extension);
1682 		port = e_source_proxy_get_http_port (extension);
1683 		if (host != NULL && port > 0) {
1684 			/* This one is a little more complicated. */
1685 			http_proxy = source_proxy_dup_http_proxy (
1686 				extension, host, port);
1687 		}
1688 		g_free (host);
1689 
1690 		host = e_source_proxy_dup_https_host (extension);
1691 		port = e_source_proxy_get_https_port (extension);
1692 		if (host != NULL && port > 0) {
1693 			https_proxy = g_strdup_printf (
1694 				"http://%s:%u", host, port);
1695 		}
1696 		g_free (host);
1697 
1698 		host = e_source_proxy_dup_socks_host (extension);
1699 		port = e_source_proxy_get_socks_port (extension);
1700 		if (host != NULL && port > 0) {
1701 			socks_proxy = g_strdup_printf (
1702 				"socks://%s:%u", host, port);
1703 		}
1704 		g_free (host);
1705 
1706 		ignore_hosts = e_source_proxy_dup_ignore_hosts (extension);
1707 		resolver = g_simple_proxy_resolver_new (NULL, ignore_hosts);
1708 		g_strfreev (ignore_hosts);
1709 
1710 		if (ftp_proxy != NULL) {
1711 			g_simple_proxy_resolver_set_uri_proxy (
1712 				G_SIMPLE_PROXY_RESOLVER (resolver),
1713 				"ftp", ftp_proxy);
1714 			g_free (ftp_proxy);
1715 		}
1716 
1717 		if (https_proxy != NULL) {
1718 			g_simple_proxy_resolver_set_uri_proxy (
1719 				G_SIMPLE_PROXY_RESOLVER (resolver),
1720 				"https", https_proxy);
1721 			g_free (https_proxy);
1722 		} else if (http_proxy != NULL) {
1723 			g_simple_proxy_resolver_set_uri_proxy (
1724 				G_SIMPLE_PROXY_RESOLVER (resolver),
1725 				"https", http_proxy);
1726 		}
1727 
1728 		if (http_proxy != NULL) {
1729 			g_simple_proxy_resolver_set_uri_proxy (
1730 				G_SIMPLE_PROXY_RESOLVER (resolver),
1731 				"http", http_proxy);
1732 			g_free (http_proxy);
1733 		}
1734 
1735 		if (socks_proxy != NULL) {
1736 			g_simple_proxy_resolver_set_uri_proxy (
1737 				G_SIMPLE_PROXY_RESOLVER (resolver),
1738 				"socks", socks_proxy);
1739 			g_simple_proxy_resolver_set_default_proxy (
1740 				G_SIMPLE_PROXY_RESOLVER (resolver),
1741 				socks_proxy);
1742 			g_free (socks_proxy);
1743 		}
1744 	}
1745 
1746 	if (method == E_PROXY_METHOD_AUTO) {
1747 		proxies = source_proxy_lookup_pacrunner (
1748 			source, uri, cancellable, error);
1749 
1750 	} else if (resolver != NULL) {
1751 		proxies = g_proxy_resolver_lookup (
1752 			resolver, uri, cancellable, error);
1753 
1754 	} else {
1755 		proxies = source_proxy_direct ();
1756 	}
1757 
1758 	g_clear_object (&resolver);
1759 
1760 	return proxies;
1761 }
1762 
1763 /* Helper for e_source_proxy_lookup() */
1764 static void
source_proxy_lookup_thread(GSimpleAsyncResult * simple,GObject * object,GCancellable * cancellable)1765 source_proxy_lookup_thread (GSimpleAsyncResult *simple,
1766                             GObject *object,
1767                             GCancellable *cancellable)
1768 {
1769 	AsyncContext *async_context;
1770 	GError *local_error = NULL;
1771 
1772 	async_context = g_simple_async_result_get_op_res_gpointer (simple);
1773 
1774 	async_context->proxies = e_source_proxy_lookup_sync (
1775 		E_SOURCE (object),
1776 		async_context->uri,
1777 		cancellable, &local_error);
1778 
1779 	if (local_error != NULL)
1780 		g_simple_async_result_take_error (simple, local_error);
1781 }
1782 
1783 /**
1784  * e_source_proxy_lookup:
1785  * @source: an #ESource
1786  * @uri: a URI representing the destination to connect to
1787  * @cancellable: optional #GCancellable object, or %NULL
1788  * @callback: a #GAsyncReadyCallback to call when the request is satisfied
1789  * @user_data: data to pass to the callback function
1790  *
1791  * Asynchronously determines what proxy, if any, to use to connect to @uri.
1792  * See e_source_proxy_lookup_sync() for more details.
1793  *
1794  * When the operation is finished, @callback will be called.  You can then
1795  * call e_source_proxy_lookup_finish() to get the result of the operation.
1796  *
1797  * Since: 3.12
1798  **/
1799 void
e_source_proxy_lookup(ESource * source,const gchar * uri,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1800 e_source_proxy_lookup (ESource *source,
1801                        const gchar *uri,
1802                        GCancellable *cancellable,
1803                        GAsyncReadyCallback callback,
1804                        gpointer user_data)
1805 {
1806 	GSimpleAsyncResult *simple;
1807 	AsyncContext *async_context;
1808 
1809 	g_return_if_fail (E_IS_SOURCE (source));
1810 	g_return_if_fail (uri != NULL);
1811 
1812 	async_context = g_slice_new0 (AsyncContext);
1813 	async_context->uri = g_strdup (uri);
1814 
1815 	simple = g_simple_async_result_new (
1816 		G_OBJECT (source), callback,
1817 		user_data, e_source_proxy_lookup);
1818 
1819 	g_simple_async_result_set_check_cancellable (simple, cancellable);
1820 
1821 	g_simple_async_result_set_op_res_gpointer (
1822 		simple, async_context, (GDestroyNotify) async_context_free);
1823 
1824 	g_simple_async_result_run_in_thread (
1825 		simple, source_proxy_lookup_thread,
1826 		G_PRIORITY_DEFAULT, cancellable);
1827 
1828 	g_object_unref (simple);
1829 }
1830 
1831 /**
1832  * e_source_proxy_lookup_finish:
1833  * @source: an #ESource
1834  * @result: a #GAsyncResult
1835  * @error: return location for a #GError, or %NULL
1836  *
1837  * Finishes the operation started with e_source_proxy_lookup().
1838  *
1839  * Free the returned proxy URIs with g_strfreev() when finished with them.
1840  *
1841  * Returns: (transfer full): a %NULL-terminated array of proxy URIs, or %NULL
1842  *
1843  * Since: 3.12
1844  **/
1845 gchar **
e_source_proxy_lookup_finish(ESource * source,GAsyncResult * result,GError ** error)1846 e_source_proxy_lookup_finish (ESource *source,
1847                               GAsyncResult *result,
1848                               GError **error)
1849 {
1850 	GSimpleAsyncResult *simple;
1851 	AsyncContext *async_context;
1852 	gchar **proxies;
1853 
1854 	g_return_val_if_fail (
1855 		g_simple_async_result_is_valid (
1856 		result, G_OBJECT (source), e_source_proxy_lookup), NULL);
1857 
1858 	simple = G_SIMPLE_ASYNC_RESULT (result);
1859 	async_context = g_simple_async_result_get_op_res_gpointer (simple);
1860 
1861 	if (g_simple_async_result_propagate_error (simple, error))
1862 		return NULL;
1863 
1864 	g_return_val_if_fail (async_context->proxies != NULL, NULL);
1865 
1866 	proxies = async_context->proxies;
1867 	async_context->proxies = NULL;
1868 
1869 	return proxies;
1870 }
1871 
1872