2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU Lesser General Public
4 * License as published by the Free Software Foundation; either
5 * version 2 of the License, or (at your option) version 3.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * You should have received a copy of the GNU Lesser General Public
13 * License along with the program; if not, see <http://www.gnu.org/licenses/>
17 * Jeffrey Stedfast <fejj@ximian.com>
18 * Veerapuram Varadhan <vvaradhan@novell.com>
20 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
33 #ifndef IN6_ARE_ADDR_EQUAL
34 #define IN6_ARE_ADDR_EQUAL(a, b) \
35 (memcmp ((gpointer)(a), (gpointer)(b), sizeof (struct in6_addr)) == 0)
38 #include <netinet/in.h>
39 #include <sys/socket.h>
42 #include <libsoup/soup-address.h>
43 #include <libsoup/soup-uri.h>
46 #define E_PROXY_GET_PRIVATE(obj) \
47 (G_TYPE_INSTANCE_GET_PRIVATE \
48 ((obj), E_TYPE_PROXY, EProxyPrivate))
50 G_DEFINE_TYPE (EProxy, e_proxy, G_TYPE_OBJECT)
56 PROXY_TYPE_SYSTEM = 0,
59 PROXY_TYPE_AUTO_URL /* no auto-proxy at the moment */
64 E_PROXY_KEY_USE_HTTP_PROXY,
65 E_PROXY_KEY_HTTP_HOST,
66 E_PROXY_KEY_HTTP_PORT,
67 E_PROXY_KEY_HTTP_USE_AUTH,
68 E_PROXY_KEY_HTTP_AUTH_USER,
69 E_PROXY_KEY_HTTP_AUTH_PWD,
70 E_PROXY_KEY_HTTP_IGNORE_HOSTS,
71 E_PROXY_KEY_HTTPS_HOST,
72 E_PROXY_KEY_HTTPS_PORT,
73 E_PROXY_KEY_SOCKS_HOST,
74 E_PROXY_KEY_SOCKS_PORT,
75 E_PROXY_KEY_AUTOCONFIG_URL
78 struct _EProxyPrivate {
79 SoupURI *uri_http, *uri_https, *uri_socks;
80 GSList * ign_hosts; /* List of hostnames. (Strings) */
81 GSList * ign_addrs; /* List of hostaddrs. (ProxyHostAddrs) */
82 gboolean use_proxy; /* Is our-proxy enabled? */
84 GSettings *evolution_proxy_settings;
85 GSettings *proxy_settings;
86 GSettings *proxy_http_settings;
87 GSettings *proxy_https_settings;
88 GSettings *proxy_socks_settings;
91 /* Enum definition is copied from gnome-vfs/modules/http-proxy.c */
98 ProxyAddrType type; /* Specifies whether IPV4 or IPV6 */
99 gpointer addr; /* Either in_addr * or in6_addr * */
100 gpointer mask; /* Either in_addr * or in6_addr * */
109 static guint signals[LAST_SIGNAL] = { 0 };
111 /* Forward declarations. */
113 static void ipv6_network_addr (const struct in6_addr *addr,
114 const struct in6_addr *mask,
115 struct in6_addr *res);
118 ep_free_proxy_host_addr (ProxyHostAddr *host)
134 ep_read_key_boolean (EProxy *proxy,
137 gboolean res = FALSE;
139 g_return_val_if_fail (E_IS_PROXY (proxy), FALSE);
142 case E_PROXY_KEY_USE_HTTP_PROXY:
143 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
144 /* it's not used in the UI, thus behave like always set to TRUE */
145 res = TRUE; /* g_settings_get_boolean (proxy->priv->proxy_http_settings, "enabled"); */
147 res = g_settings_get_boolean (proxy->priv->evolution_proxy_settings, "use-http-proxy");
149 case E_PROXY_KEY_HTTP_USE_AUTH:
150 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
151 res = g_settings_get_boolean (proxy->priv->proxy_http_settings, "use-authentication");
153 res = g_settings_get_boolean (proxy->priv->evolution_proxy_settings, "use-authentication");
156 g_warn_if_reached ();
164 ep_read_key_int (EProxy *proxy,
169 g_return_val_if_fail (E_IS_PROXY (proxy), 0);
172 case E_PROXY_KEY_HTTP_PORT:
173 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
174 res = g_settings_get_int (proxy->priv->proxy_http_settings, "port");
176 res = g_settings_get_int (proxy->priv->evolution_proxy_settings, "http-port");
178 case E_PROXY_KEY_HTTPS_PORT:
179 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
180 res = g_settings_get_int (proxy->priv->proxy_https_settings, "port");
182 res = g_settings_get_int (proxy->priv->evolution_proxy_settings, "secure-port");
184 case E_PROXY_KEY_SOCKS_PORT:
185 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
186 res = g_settings_get_int (proxy->priv->proxy_socks_settings, "port");
188 res = g_settings_get_int (proxy->priv->evolution_proxy_settings, "socks-port");
191 g_warn_if_reached ();
198 /* free returned pointer with g_free() */
200 ep_read_key_string (EProxy *proxy,
205 g_return_val_if_fail (E_IS_PROXY (proxy), NULL);
208 case E_PROXY_KEY_MODE:
209 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
210 res = g_settings_get_string (proxy->priv->proxy_settings, "mode");
212 g_warn_if_reached ();
214 case E_PROXY_KEY_HTTP_HOST:
215 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
216 res = g_settings_get_string (proxy->priv->proxy_http_settings, "host");
218 res = g_settings_get_string (proxy->priv->evolution_proxy_settings, "http-host");
220 case E_PROXY_KEY_HTTPS_HOST:
221 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
222 res = g_settings_get_string (proxy->priv->proxy_https_settings, "host");
224 res = g_settings_get_string (proxy->priv->evolution_proxy_settings, "secure-host");
226 case E_PROXY_KEY_SOCKS_HOST:
227 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
228 res = g_settings_get_string (proxy->priv->proxy_socks_settings, "host");
230 res = g_settings_get_string (proxy->priv->evolution_proxy_settings, "socks-host");
232 case E_PROXY_KEY_HTTP_AUTH_USER:
233 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
234 res = g_settings_get_string (proxy->priv->proxy_http_settings, "authentication-user");
236 res = g_settings_get_string (proxy->priv->evolution_proxy_settings, "authentication-user");
238 case E_PROXY_KEY_HTTP_AUTH_PWD:
239 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
240 res = g_settings_get_string (proxy->priv->proxy_http_settings, "authentication-password");
242 res = g_settings_get_string (proxy->priv->evolution_proxy_settings, "authentication-password");
244 case E_PROXY_KEY_AUTOCONFIG_URL:
245 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
246 res = g_settings_get_string (proxy->priv->proxy_settings, "autoconfig-url");
248 res = g_settings_get_string (proxy->priv->evolution_proxy_settings, "autoconfig-url");
251 g_warn_if_reached ();
258 /* list of newly allocated strings, use g_free() for each member and free list itself too */
260 ep_read_key_list (EProxy *proxy,
266 g_return_val_if_fail (E_IS_PROXY (proxy), NULL);
269 case E_PROXY_KEY_HTTP_IGNORE_HOSTS:
270 if (proxy->priv->type == PROXY_TYPE_SYSTEM)
271 strv = g_settings_get_strv (proxy->priv->proxy_settings, "ignore-hosts");
273 strv = g_settings_get_strv (proxy->priv->evolution_proxy_settings, "ignore-hosts");
276 g_warn_if_reached ();
283 for (ii = 0; strv && strv[ii]; ii++) {
284 res = g_slist_prepend (res, g_strdup (strv[ii]));
289 res = g_slist_reverse (res);
296 ep_is_in_ignored (EProxy *proxy,
303 g_return_val_if_fail (proxy != NULL, FALSE);
304 g_return_val_if_fail (host != NULL, FALSE);
307 if (!priv->ign_hosts)
310 hn = g_ascii_strdown (host, -1);
312 for (l = priv->ign_hosts; l; l = l->next) {
313 if (*((gchar *) l->data) == '*') {
314 if (g_str_has_suffix (hn, ((gchar *) l->data) + 1)) {
318 } else if (strcmp (hn, l->data) == 0) {
329 ep_need_proxy_http (EProxy *proxy,
332 SoupAddress *addr = NULL;
333 EProxyPrivate *priv = proxy->priv;
334 ProxyHostAddr *p_addr = NULL;
338 /* check for ignored first */
339 if (ep_is_in_ignored (proxy, host))
342 addr = soup_address_new (host, 0);
343 status = soup_address_resolve_sync (addr, NULL);
344 if (status == SOUP_STATUS_OK) {
346 struct sockaddr * so_addr = NULL;
348 so_addr = soup_address_get_sockaddr (addr, &addr_len);
350 /* This will never happen, since we have already called
351 * soup_address_resolve_sync ().
354 g_object_unref (addr);
358 if (so_addr->sa_family == AF_INET) {
359 struct in_addr in, *mask, *addr_in;
361 in = ((struct sockaddr_in *) so_addr)->sin_addr;
362 for (l = priv->ign_addrs; l; l = l->next) {
363 p_addr = (ProxyHostAddr *) l->data;
364 if (p_addr->type == PROXY_IPV4) {
365 addr_in = ((struct in_addr *) p_addr->addr);
366 mask = ((struct in_addr *) p_addr->mask);
367 if ((in.s_addr & mask->s_addr) == addr_in->s_addr) {
368 d (g_print ("Host [%s] doesn't require proxy\n", host));
369 g_object_unref (addr);
375 struct in6_addr in6, net6;
376 struct in_addr *addr_in, *mask;
378 in6 = ((struct sockaddr_in6 *) so_addr)->sin6_addr;
379 for (l = priv->ign_addrs; l; l = l->next) {
380 p_addr = (ProxyHostAddr *) l->data;
381 ipv6_network_addr (&in6, (struct in6_addr *) p_addr->mask, &net6);
382 if (p_addr->type == PROXY_IPV6) {
383 if (IN6_ARE_ADDR_EQUAL (&net6, (struct in6_addr *) p_addr->addr)) {
384 d (g_print ("Host [%s] doesn't require proxy\n", host));
385 g_object_unref (addr);
388 } else if (p_addr->type == PROXY_IPV6 &&
389 IN6_IS_ADDR_V4MAPPED (&net6)) {
392 addr_in = ((struct in_addr *) p_addr->addr);
393 mask = ((struct in_addr *) p_addr->mask);
395 v4addr = net6.s6_addr[12] << 24
396 | net6.s6_addr[13] << 16
397 | net6.s6_addr[14] << 8
399 if ((v4addr & mask->s_addr) != addr_in->s_addr) {
400 d (g_print ("Host [%s] doesn't require proxy\n", host));
401 g_object_unref (addr);
409 d (g_print ("%s needs a proxy to connect to internet\n", host));
410 g_object_unref (addr);
416 ep_need_proxy_https (EProxy *proxy,
419 /* Can we share ignore list from HTTP at all? */
420 return !ep_is_in_ignored (proxy, host);
424 ep_need_proxy_socks (EProxy *proxy,
427 /* Can we share ignore list from HTTP at all? */
428 return !ep_is_in_ignored (proxy, host);
432 ep_manipulate_ipv4 (ProxyHostAddr *host_addr,
433 struct in_addr *addr_in,
436 gboolean has_error = FALSE;
437 struct in_addr *addr, *mask;
442 host_addr->type = PROXY_IPV4;
443 addr = g_new0 (struct in_addr, 1);
444 memcpy (addr, addr_in, sizeof (struct in_addr));
445 mask = g_new0 (struct in_addr, 1);
449 gint width = strtol (netmask, &endptr, 10);
451 if (*endptr != '\0' || width < 0 || width > 32) {
454 mask->s_addr = htonl (~0 << width);
455 addr->s_addr &= mask->s_addr;
457 mask->s_addr = 0xFFFFFFFF;
460 host_addr->addr = addr;
461 host_addr->mask = mask;
467 ipv6_network_addr (const struct in6_addr *addr,
468 const struct in6_addr *mask,
469 struct in6_addr *res)
473 for (i = 0; i < 16; ++i) {
474 res->s6_addr[i] = addr->s6_addr[i] & mask->s6_addr[i];
479 ep_manipulate_ipv6 (ProxyHostAddr *host_addr,
480 struct in6_addr *addr_in6,
483 gboolean has_error = FALSE;
484 struct in6_addr *addr, *mask;
490 host_addr->type = PROXY_IPV6;
492 addr = g_new0 (struct in6_addr, 1);
493 mask = g_new0 (struct in6_addr, 1);
495 for (i = 0; i < 16; ++i) {
496 addr->s6_addr[i] = addr_in6->s6_addr[i];
500 gint width = strtol (netmask, &endptr, 10);
502 if (*endptr != '\0' || width < 0 || width > 128) {
505 for (i = 0; i < 16; ++i) {
506 mask->s6_addr[i] = 0;
508 for (i = 0; i < width / 8; i++) {
509 mask->s6_addr[i] = 0xff;
511 mask->s6_addr[i] = (0xff << (8 - width % 8)) & 0xff;
512 ipv6_network_addr (addr, mask, addr);
514 for (i = 0; i < 16; ++i) {
515 mask->s6_addr[i] = 0xff;
519 host_addr->addr = addr;
520 host_addr->mask = mask;
526 ep_parse_ignore_host (gpointer data,
529 EProxy * proxy = (EProxy *) user_data;
530 EProxyPrivate * priv = NULL;
533 gchar *input, *netmask, *hostname;
534 ProxyHostAddr *host_addr;
535 gboolean has_error = FALSE;
537 if (!proxy || !proxy->priv)
541 input = (gchar *) data;
543 if ((netmask = strrchr (input, '/')) != NULL) {
544 hostname = g_strndup (input, netmask - input);
547 hostname = g_ascii_strdown (input, -1);
550 addr = soup_address_new (hostname, 0);
551 status = soup_address_resolve_sync (addr, NULL);
552 if (status == SOUP_STATUS_OK) {
554 struct sockaddr * so_addr = NULL;
556 host_addr = g_new0 (ProxyHostAddr, 1);
558 so_addr = soup_address_get_sockaddr (addr, &addr_len);
560 /* This will never happen, since we have already called
561 * soup_address_resolve_sync ().
566 if (so_addr->sa_family == AF_INET)
567 has_error = ep_manipulate_ipv4 (
569 &((struct sockaddr_in *) so_addr)->sin_addr,
572 has_error = ep_manipulate_ipv6 (
574 &((struct sockaddr_in6 *) so_addr)->sin6_addr,
578 priv->ign_addrs = g_slist_append (
579 priv->ign_addrs, host_addr);
580 priv->ign_hosts = g_slist_append (
581 priv->ign_hosts, hostname);
586 d (g_print ("Unable to resolve %s\n", hostname));
587 priv->ign_hosts = g_slist_append (priv->ign_hosts, hostname);
590 g_object_unref (addr);
594 ep_change_uri (SoupURI **soup_uri,
597 gboolean changed = FALSE;
599 g_return_val_if_fail (soup_uri != NULL, FALSE);
603 soup_uri_free (*soup_uri);
607 } else if (*soup_uri) {
608 gchar *old = soup_uri_to_string (*soup_uri, FALSE);
611 gint len = strlen (old);
613 /* remove ending slash, if there */
614 if (old[len - 1] == '/')
618 changed = old && uri && g_ascii_strcasecmp (old, uri) != 0;
620 soup_uri_free (*soup_uri);
621 *soup_uri = soup_uri_new (uri);
626 *soup_uri = soup_uri_new (uri);
634 update_proxy_uri (const gchar *uri,
635 const gchar *proxy_user,
636 const gchar *proxy_pw)
638 gchar *res, *user = NULL, *pw = NULL;
641 g_return_val_if_fail (uri != NULL, NULL);
643 if (proxy_user && *proxy_user) {
644 user = soup_uri_encode (proxy_user, ":/;#@?\\");
646 pw = soup_uri_encode (proxy_pw, ":/;#@?\\");
650 return g_strdup (uri);
652 /* here can be only http or https and nothing else */
653 is_https = g_str_has_prefix (uri, "https://");
655 res = g_strdup_printf (
657 is_https ? "https" : "http",
661 uri + strlen ("http://") + (is_https ? 1 : 0));
670 ep_set_proxy (EProxy *proxy,
671 gboolean regen_ign_host_list)
673 gchar *proxy_server, *uri_http = NULL, *uri_https = NULL, *uri_socks = NULL;
674 gint proxy_port, old_type;
675 EProxyPrivate * priv = proxy->priv;
677 gboolean changed = FALSE, sys_manual = TRUE;
679 old_type = priv->type;
680 priv->type = g_settings_get_int (priv->evolution_proxy_settings, "proxy-type");
681 if (priv->type > PROXY_TYPE_AUTO_URL)
682 priv->type = PROXY_TYPE_SYSTEM;
683 changed = priv->type != old_type;
685 if (priv->type == PROXY_TYPE_SYSTEM) {
686 gchar *mode = ep_read_key_string (proxy, E_PROXY_KEY_MODE);
688 /* supporting only manual system proxy setting */
689 sys_manual = mode && g_str_equal (mode, "manual");
694 priv->use_proxy = ep_read_key_boolean (proxy, E_PROXY_KEY_USE_HTTP_PROXY);
695 if (!priv->use_proxy || priv->type == PROXY_TYPE_NO_PROXY || !sys_manual) {
696 changed = ep_change_uri (&priv->uri_http, NULL) || changed;
697 changed = ep_change_uri (&priv->uri_https, NULL) || changed;
698 changed = ep_change_uri (&priv->uri_socks, NULL) || changed;
702 proxy_server = ep_read_key_string (proxy, E_PROXY_KEY_HTTP_HOST);
703 proxy_port = ep_read_key_int (proxy, E_PROXY_KEY_HTTP_PORT);
704 if (proxy_server != NULL && *proxy_server && !g_ascii_isspace (*proxy_server)) {
706 uri_http = g_strdup_printf ("http://%s:%d", proxy_server, proxy_port);
708 uri_http = g_strdup_printf ("http://%s", proxy_server);
711 g_free (proxy_server);
712 d (g_print ("ep_set_proxy: uri_http: %s\n", uri_http));
714 proxy_server = ep_read_key_string (proxy, E_PROXY_KEY_HTTPS_HOST);
715 proxy_port = ep_read_key_int (proxy, E_PROXY_KEY_HTTPS_PORT);
716 if (proxy_server != NULL && *proxy_server && !g_ascii_isspace (*proxy_server)) {
718 uri_https = g_strdup_printf ("https://%s:%d", proxy_server, proxy_port);
720 uri_https = g_strdup_printf ("https://%s", proxy_server);
723 g_free (proxy_server);
724 d (g_print ("ep_set_proxy: uri_https: %s\n", uri_https));
726 proxy_server = ep_read_key_string (proxy, E_PROXY_KEY_SOCKS_HOST);
727 proxy_port = ep_read_key_int (proxy, E_PROXY_KEY_SOCKS_PORT);
728 if (proxy_server != NULL && *proxy_server && !g_ascii_isspace (*proxy_server)) {
730 uri_socks = g_strdup_printf ("socks://%s:%d", proxy_server, proxy_port);
732 uri_socks = g_strdup_printf ("socks://%s", proxy_server);
735 g_free (proxy_server);
736 d (g_print ("ep_set_proxy: uri_socks: %s\n", uri_socks));
738 if (regen_ign_host_list) {
739 if (priv->ign_hosts) {
740 g_slist_foreach (priv->ign_hosts, (GFunc) g_free, NULL);
741 g_slist_free (priv->ign_hosts);
742 priv->ign_hosts = NULL;
745 if (priv->ign_addrs) {
746 g_slist_foreach (priv->ign_addrs, (GFunc) ep_free_proxy_host_addr, NULL);
747 g_slist_free (priv->ign_addrs);
748 priv->ign_addrs = NULL;
751 ignore = ep_read_key_list (proxy, E_PROXY_KEY_HTTP_IGNORE_HOSTS);
753 g_slist_foreach (ignore, (GFunc) ep_parse_ignore_host, proxy);
754 g_slist_foreach (ignore, (GFunc) g_free, NULL);
755 g_slist_free (ignore);
759 if (ep_read_key_boolean (proxy, E_PROXY_KEY_HTTP_USE_AUTH)) {
760 gchar *proxy_user, *proxy_pw, *tmp = NULL, *tmps = NULL;
762 proxy_user = ep_read_key_string (proxy, E_PROXY_KEY_HTTP_AUTH_USER);
763 proxy_pw = ep_read_key_string (proxy, E_PROXY_KEY_HTTP_AUTH_PWD);
765 if (uri_http && proxy_user && *proxy_user) {
767 uri_http = update_proxy_uri (uri_http, proxy_user, proxy_pw);
770 if (uri_https && proxy_user && *proxy_user) {
772 uri_https = update_proxy_uri (uri_https, proxy_user, proxy_pw);
781 changed = ep_change_uri (&priv->uri_http, uri_http) || changed;
782 changed = ep_change_uri (&priv->uri_https, uri_https) || changed;
783 changed = ep_change_uri (&priv->uri_socks, uri_socks) || changed;
791 G_STRFUNC, changed ? 1 : 0,
792 uri_http ? uri_http : "[null]",
793 uri_https ? uri_https : "[null]",
794 uri_socks ? uri_socks : "[null]"));
796 g_signal_emit (proxy, signals[CHANGED], 0);
804 ep_evo_proxy_changed_cb (GSettings *settings,
810 g_return_if_fail (E_IS_PROXY (proxy));
814 d (g_print ("%s: proxy settings changed, key '%s'\n", G_STRFUNC, key ? key : "NULL"));
815 if (g_strcmp0 (key, "proxy-type") == 0) {
816 ep_set_proxy (proxy, TRUE);
817 } else if (priv->type == PROXY_TYPE_SYSTEM) {
821 ep_set_proxy (proxy, g_strcmp0 (key, "ignore-hosts") == 0);
825 ep_sys_proxy_changed_cb (GSettings *settings,
829 g_return_if_fail (proxy != NULL);
831 if (proxy->priv->type != PROXY_TYPE_SYSTEM)
834 ep_set_proxy (proxy, g_strcmp0 (key, "ignore-hosts") == 0);
838 ep_sys_proxy_http_changed_cb (GSettings *settings,
842 g_return_if_fail (proxy != NULL);
844 if (proxy->priv->type != PROXY_TYPE_SYSTEM)
847 ep_set_proxy (proxy, FALSE);
851 ep_sys_proxy_https_changed_cb (GSettings *settings,
855 g_return_if_fail (proxy != NULL);
857 if (proxy->priv->type != PROXY_TYPE_SYSTEM)
860 ep_set_proxy (proxy, FALSE);
864 ep_sys_proxy_socks_changed_cb (GSettings *settings,
868 g_return_if_fail (proxy != NULL);
870 if (proxy->priv->type != PROXY_TYPE_SYSTEM)
873 ep_set_proxy (proxy, FALSE);
877 e_proxy_dispose (GObject *object)
882 proxy = E_PROXY (object);
885 if (priv->evolution_proxy_settings) {
886 g_signal_handlers_disconnect_by_func (priv->evolution_proxy_settings, ep_evo_proxy_changed_cb, proxy);
887 g_object_unref (priv->evolution_proxy_settings);
888 priv->evolution_proxy_settings = NULL;
891 if (priv->proxy_settings) {
892 g_signal_handlers_disconnect_by_func (priv->proxy_settings, ep_sys_proxy_changed_cb, proxy);
893 g_object_unref (priv->proxy_settings);
894 priv->proxy_settings = NULL;
897 if (priv->proxy_http_settings) {
898 g_signal_handlers_disconnect_by_func (priv->proxy_http_settings, ep_sys_proxy_http_changed_cb, proxy);
899 g_object_unref (priv->proxy_http_settings);
900 priv->proxy_http_settings = NULL;
903 if (priv->proxy_https_settings) {
904 g_signal_handlers_disconnect_by_func (priv->proxy_https_settings, ep_sys_proxy_https_changed_cb, proxy);
905 g_object_unref (priv->proxy_https_settings);
906 priv->proxy_https_settings = NULL;
909 if (priv->proxy_socks_settings) {
910 g_signal_handlers_disconnect_by_func (priv->proxy_socks_settings, ep_sys_proxy_socks_changed_cb, proxy);
911 g_object_unref (priv->proxy_socks_settings);
912 priv->proxy_socks_settings = NULL;
916 soup_uri_free (priv->uri_http);
919 soup_uri_free (priv->uri_https);
922 soup_uri_free (priv->uri_socks);
924 g_slist_foreach (priv->ign_hosts, (GFunc) g_free, NULL);
925 g_slist_free (priv->ign_hosts);
927 g_slist_foreach (priv->ign_addrs, (GFunc) ep_free_proxy_host_addr, NULL);
928 g_slist_free (priv->ign_addrs);
930 /* Chain up to parent's dispose() method. */
931 G_OBJECT_CLASS (e_proxy_parent_class)->dispose (object);
935 e_proxy_class_init (EProxyClass *class)
937 GObjectClass *object_class;
939 g_type_class_add_private (class, sizeof (EProxyPrivate));
941 object_class = G_OBJECT_CLASS (class);
942 object_class->dispose = e_proxy_dispose;
946 * @proxy: the #EProxy which emitted the signal
948 * Emitted when proxy settings changes.
950 signals[CHANGED] = g_signal_new (
952 G_OBJECT_CLASS_TYPE (object_class),
954 G_STRUCT_OFFSET (EProxyClass, changed),
956 g_cclosure_marshal_VOID__VOID,
962 e_proxy_init (EProxy *proxy)
964 proxy->priv = E_PROXY_GET_PRIVATE (proxy);
966 proxy->priv->type = PROXY_TYPE_SYSTEM;
968 proxy->priv->evolution_proxy_settings = g_settings_new ("org.gnome.evolution.shell.network-config");
969 proxy->priv->proxy_settings = g_settings_new ("org.gnome.system.proxy");
970 proxy->priv->proxy_http_settings = g_settings_get_child (proxy->priv->proxy_settings, "http");
971 proxy->priv->proxy_https_settings = g_settings_get_child (proxy->priv->proxy_settings, "https");
972 proxy->priv->proxy_socks_settings = g_settings_get_child (proxy->priv->proxy_settings, "socks");
974 g_signal_connect (proxy->priv->evolution_proxy_settings, "changed", G_CALLBACK (ep_evo_proxy_changed_cb), proxy);
975 g_signal_connect (proxy->priv->proxy_settings, "changed", G_CALLBACK (ep_sys_proxy_changed_cb), proxy);
976 g_signal_connect (proxy->priv->proxy_http_settings, "changed", G_CALLBACK (ep_sys_proxy_http_changed_cb), proxy);
977 g_signal_connect (proxy->priv->proxy_https_settings, "changed", G_CALLBACK (ep_sys_proxy_https_changed_cb), proxy);
978 g_signal_connect (proxy->priv->proxy_socks_settings, "changed", G_CALLBACK (ep_sys_proxy_socks_changed_cb), proxy);
989 return g_object_new (E_TYPE_PROXY, NULL);
993 * e_proxy_setup_proxy:
998 e_proxy_setup_proxy (EProxy *proxy)
1000 g_return_if_fail (E_IS_PROXY (proxy));
1002 /* We get the evolution-shell proxy keys here
1003 * set soup up to use the proxy,
1004 * and listen to any changes */
1006 /* XXX Why can't we do this automatically in constructed() ? */
1008 ep_set_proxy (proxy, TRUE);
1012 * e_proxy_peek_uri_for:
1017 e_proxy_peek_uri_for (EProxy *proxy,
1020 SoupURI *res = NULL;
1023 g_return_val_if_fail (E_IS_PROXY (proxy), NULL);
1024 g_return_val_if_fail (uri != NULL, NULL);
1026 soup_uri = soup_uri_new (uri);
1027 if (soup_uri == NULL)
1030 if (soup_uri->scheme == SOUP_URI_SCHEME_HTTP)
1031 res = proxy->priv->uri_http;
1032 else if (soup_uri->scheme == SOUP_URI_SCHEME_HTTPS)
1033 res = proxy->priv->uri_https;
1034 else if (soup_uri->scheme && g_ascii_strcasecmp (soup_uri->scheme, "socks") == 0)
1035 res = proxy->priv->uri_socks;
1037 soup_uri_free (soup_uri);
1043 * e_proxy_require_proxy_for_uri:
1048 e_proxy_require_proxy_for_uri (EProxy *proxy,
1051 SoupURI *soup_uri = NULL;
1052 gboolean need_proxy = FALSE;
1054 g_return_val_if_fail (E_IS_PROXY (proxy), FALSE);
1055 g_return_val_if_fail (uri != NULL, FALSE);
1057 if (!proxy->priv->use_proxy || proxy->priv->type == PROXY_TYPE_NO_PROXY) {
1058 d (g_print ("[%s] don't need a proxy to connect to internet\n", uri));
1062 soup_uri = soup_uri_new (uri);
1063 if (soup_uri == NULL)
1066 if (soup_uri->scheme == SOUP_URI_SCHEME_HTTP)
1067 need_proxy = ep_need_proxy_http (proxy, soup_uri->host);
1068 else if (soup_uri->scheme == SOUP_URI_SCHEME_HTTPS)
1069 need_proxy = ep_need_proxy_https (proxy, soup_uri->host);
1070 else if (soup_uri->scheme && g_ascii_strcasecmp (soup_uri->scheme, "socks") == 0)
1071 need_proxy = ep_need_proxy_socks (proxy, soup_uri->host);
1073 soup_uri_free (soup_uri);