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