Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:pchenthill
evolution-data-server
bnc-174255-honour-system-proxy-settings.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File bnc-174255-honour-system-proxy-settings.patch of Package evolution-data-server
--- servers/groupwise/Makefile.am 2006-05-19 19:19:26.000000000 +0530 +++ servers/groupwise/Makefile.am 2006-05-19 02:15:44.000000000 +0530 @@ -15,9 +15,10 @@ create_account_LDADD = \ $(E_DATA_SERVER_LIBS) soap_test_SOURCES = soap-test.c -soap_test_LDADD = \ - $(SOUP_LIBS) \ - libegroupwise-1.2.la \ +soap_test_LDADD = \ + $(top_builddir)/libedataserver/libedataserver-1.2.la \ + $(SOUP_LIBS) \ + libegroupwise-1.2.la \ $(E_DATA_SERVER_LIBS) lib_LTLIBRARIES = libegroupwise-1.2.la Index: servers/groupwise/e-gw-connection.c =================================================================== RCS file: /cvs/gnome/evolution-data-server/servers/groupwise/e-gw-connection.c,v retrieving revision 1.142 diff -u -p -r1.142 e-gw-connection.c --- servers/groupwise/e-gw-connection.c 11 Apr 2006 05:18:49 -0000 1.142 +++ servers/groupwise/e-gw-connection.c 2006-05-19 01:55:05.000000000 +0530 @@ -27,6 +27,7 @@ #include <string.h> #include <ctype.h> #include <glib/gi18n-lib.h> +#include <libedataserver/e-proxy.h> #include <libsoup/soup-session-sync.h> #include <libsoup/soup-soap-message.h> #include <libsoup/soup-misc.h> @@ -37,6 +38,9 @@ /* For soup sync session timeout */ #define GW_SOUP_SESSION_TIMEOUT 30 +/* Soup session proxy-uri property */ +#define SOUP_SESSION_PROXY_URI "proxy-uri" + static GObjectClass *parent_class = NULL; static GHashTable *loaded_connections_permissions = NULL; @@ -57,8 +61,37 @@ struct _EGwConnectionPrivate { GList *book_list; EGwSendOptions *opts; GMutex *reauth_mutex; + EProxy *proxy; }; +static void +update_soup_session_proxy_settings (EProxy *proxy, SoupSession* session, + const char* uri) +{ + SoupUri *proxy_uri = NULL; + + if (!session || !uri || !proxy) + return; + + if (e_proxy_require_proxy_for_uri (proxy, uri)) + proxy_uri = e_proxy_peek_uri (proxy); + + g_object_set (session, SOUP_SESSION_PROXY_URI, + proxy_uri, NULL); +} + +static void +proxy_settings_changed (EProxy *proxy, gpointer user_data) +{ + EGwConnection* conn = (EGwConnection *)user_data; + if (!conn || !conn->priv || !conn->priv->soup_session) + return; + + update_soup_session_proxy_settings (proxy, + conn->priv->soup_session, + conn->priv->uri); +} + static EGwConnectionStatus reauthenticate (EGwConnection *cnc) { @@ -319,6 +352,11 @@ e_gw_connection_dispose (GObject *object g_free (priv->server_time) ; priv->server_time = NULL ; } + + if (priv->proxy) { + g_object_unref (priv->proxy); + priv->proxy = NULL; + } } if (parent_class->dispose) @@ -369,6 +407,11 @@ e_gw_connection_init (EGwConnection *cnc */ if (g_getenv ("SOUP_SESSION_TIMEOUT")) timeout = atoi (g_getenv ("SOUP_SESSION_TIMEOUT")); + + /* Initialize proxy settings */ + priv->proxy = e_proxy_new (); + e_proxy_setup_proxy (priv->proxy); + g_signal_connect (priv->proxy, "changed", G_CALLBACK (proxy_settings_changed), cnc); /* create the SoupSession for this connection */ priv->soup_session = soup_session_sync_new_with_options (SOUP_SESSION_TIMEOUT, timeout, NULL); @@ -448,11 +491,17 @@ e_gw_connection_new (const char *uri, co return cnc; } } - /* not found, so create a new connection */ cnc = g_object_new (E_TYPE_GW_CONNECTION, NULL); + /* Set proxy details for the Soup session before any + communication. + */ + update_soup_session_proxy_settings (cnc->priv->proxy, + cnc->priv->soup_session, + uri); + msg = form_login_request (uri, username, password); /* send message to server */ --- servers/exchange/lib/e2k-context.c 11 Apr 2006 05:18:49 -0000 1.142 +++ servers/exchange/lib/e2k-context.c 2006-05-19 01:59:30.000000000 +0530 @@ -49,6 +49,7 @@ #include "e2k-utils.h" #include "e2k-xml-utils.h" +#include <libedataserver/e-proxy.h> #include <libsoup/soup-address.h> #include <libsoup/soup-message-filter.h> #include <libsoup/soup-session-async.h> @@ -104,6 +105,7 @@ struct _E2kContextPrivate { /* Forms-based authentication */ char *cookie; gboolean cookie_verified; + EProxy* proxy; }; /* For operations with progress */ @@ -113,6 +115,9 @@ struct _E2kContextPrivate { /* For soup sync session timeout */ #define E2K_SOUP_SESSION_TIMEOUT 30 +/* Soup session proxy-uri property */ +#define SOUP_SESSION_PROXY_URI "proxy-uri" + #ifdef E2K_DEBUG char *e2k_debug; int e2k_debug_level; @@ -123,6 +128,31 @@ static void unsubscribe_internal (E2kCon static gboolean do_notification (GIOChannel *source, GIOCondition condition, gpointer data); static void setup_message (SoupMessageFilter *filter, SoupMessage *msg); +static void proxy_settings_changed (EProxy *proxy, gpointer user_data); + + +static void +proxy_settings_changed (EProxy *proxy, gpointer user_data) +{ + SoupUri *proxy_uri = NULL; + E2kContext* ctx = (E2kContext *)user_data; + if (!ctx || !ctx->priv || + (!ctx->priv->session && !ctx->priv->async_session) || + (!ctx->priv->owa_uri)) + return; + + if (!e_proxy_require_proxy_for_uri (proxy, ctx->priv->owa_uri)) + proxy_uri = NULL; + else + proxy_uri = e_proxy_peek_uri (proxy); + + if (ctx->priv->session) + g_object_set (ctx->priv->session, SOUP_SESSION_PROXY_URI, + proxy_uri, NULL); + if (ctx->priv->async_session) + g_object_set (ctx->priv->async_session, SOUP_SESSION_PROXY_URI, + proxy_uri, NULL); +} static void init (GObject *object) @@ -134,6 +164,9 @@ init (GObject *object) g_hash_table_new (g_str_hash, g_str_equal); ctx->priv->subscriptions_by_uri = g_hash_table_new (g_str_hash, g_str_equal); + ctx->priv->proxy = e_proxy_new (); + e_proxy_setup_proxy (ctx->priv->proxy); + g_signal_connect (ctx->priv->proxy, "changed", G_CALLBACK (proxy_settings_changed), ctx); } static void @@ -180,8 +213,13 @@ dispose (GObject *object) g_free (ctx->priv->cookie); + if (ctx->priv->proxy) { + g_object_unref (ctx->priv->proxy); + ctx->priv->proxy = NULL; + } g_free (ctx->priv); ctx->priv = NULL; + } G_OBJECT_CLASS (parent_class)->dispose (object); @@ -361,6 +399,7 @@ e2k_context_set_auth (E2kContext *ctx, c const char *password) { guint timeout = E2K_SOUP_SESSION_TIMEOUT; + SoupUri* uri = NULL; g_return_if_fail (E2K_IS_CONTEXT (ctx)); @@ -390,10 +429,15 @@ e2k_context_set_auth (E2kContext *ctx, c */ if (g_getenv ("SOUP_SESSION_TIMEOUT")) timeout = atoi (g_getenv ("SOUP_SESSION_TIMEOUT")); - + + /* Check do we need a proxy to contact the server? */ + if (e_proxy_require_proxy_for_uri (ctx->priv->proxy, ctx->priv->owa_uri)) + uri = e_proxy_peek_uri (ctx->priv->proxy); + ctx->priv->session = soup_session_sync_new_with_options ( SOUP_SESSION_USE_NTLM, !authmech || !strcmp (authmech, "NTLM"), SOUP_SESSION_TIMEOUT, timeout, + SOUP_SESSION_PROXY_URI, uri, NULL); g_signal_connect (ctx->priv->session, "authenticate", G_CALLBACK (session_authenticate), ctx); @@ -402,7 +446,7 @@ e2k_context_set_auth (E2kContext *ctx, c ctx->priv->async_session = soup_session_async_new_with_options ( SOUP_SESSION_USE_NTLM, !authmech || !strcmp (authmech, "NTLM"), - NULL); + SOUP_SESSION_PROXY_URI, uri, NULL); g_signal_connect (ctx->priv->async_session, "authenticate", G_CALLBACK (session_authenticate), ctx); soup_session_add_filter (ctx->priv->async_session, Index: libedataserver/Makefile.am =================================================================== RCS file: /cvs/gnome/evolution-data-server/libedataserver/Makefile.am,v retrieving revision 1.29 diff -u -p -r1.29 Makefile.am --- libedataserver/Makefile.am 24 Apr 2006 09:11:35 -0000 1.29 +++ libedataserver/Makefile.am 19 May 2006 11:54:20 -0000 @@ -7,7 +7,8 @@ INCLUDES = \ -DE_DATA_SERVER_EXTENSIONDIR=\"$(extensiondir)\" \ -DE_DATA_SERVER_IMAGESDIR=\"$(imagesdir)\" \ -DE_DATA_SERVER_UI_GLADEDIR=\""$(gladedir)"\" \ - $(E_DATA_SERVER_CFLAGS) + $(E_DATA_SERVER_CFLAGS) \ + $(SOUP_CFLAGS) # The marshallers MARSHAL_GENERATED = e-data-server-marshal.c e-data-server-marshal.h @@ -32,6 +33,7 @@ libedataserver_1_2_la_SOURCES = \ e-list-iterator.c \ e-memory.c \ e-msgport.c \ + e-proxy.c \ e-sexp.c \ e-source-group.c \ e-source-list.c \ @@ -50,7 +52,8 @@ libedataserver_1_2_la_LIBADD = \ $(E_DATA_SERVER_LIBS) \ $(ICONV_LIBS) \ $(top_builddir)/libdb/dist/libdb-4.1.la \ - $(SOCKET_LIBS) + $(SOCKET_LIBS) \ + $(SOUP_LIBS) libedataserver_1_2_la_LDFLAGS = \ -version-info $(LIBEDATASERVER_CURRENT):$(LIBEDATASERVER_REVISION):$(LIBEDATASERVER_AGE) $(NO_UNDEFINED) @@ -72,6 +75,7 @@ libedataserverinclude_HEADERS = \ e-list-iterator.h \ e-memory.h \ e-msgport.h \ + e-proxy.h \ e-sexp.h \ e-source-group.h \ e-source-list.h \ --- /dev/null 2006-04-01 01:07:59.000000000 +0530 +++ libedataserver/e-proxy.h 2006-05-19 01:49:14.000000000 +0530 @@ -0,0 +1,63 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * Veerapuram Varadhan <vvaradhan@novell.com> + * + * Copyright 2002 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifndef __E_PROXY_H__ +#define __E_PROXY_H__ + +#include <libsoup/soup-uri.h> + +G_BEGIN_DECLS + +#define E_TYPE_PROXY (e_proxy_get_type ()) +#define E_PROXY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_PROXY, EProxy)) +#define E_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_PROXY, EProxyClass)) +#define E_IS_PROXY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_PROXY)) +#define E_IS_PROXY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), E_TYPE_PROXY)) + +typedef struct _EProxy EProxy; +typedef struct _EProxyClass EProxyClass; +typedef struct _EProxyPrivate EProxyPrivate; + +struct _EProxy { + GObject parent; + EProxyPrivate *priv; +}; + +struct _EProxyClass { + GObjectClass parent_class; + /* Signals. */ + + void (*changed) (EProxy *proxy); +}; + +EProxy* e_proxy_new (void); +SoupUri* e_proxy_peek_uri (EProxy* proxy); +void e_proxy_setup_proxy (EProxy* proxy); +GType e_proxy_get_type (void); +gboolean e_proxy_require_proxy_for_uri (EProxy *proxy, + const char* uri); + +G_END_DECLS + +#endif --- /dev/null 2006-04-01 01:07:59.000000000 +0530 +++ libedataserver/e-proxy.c 2006-05-21 16:34:33.000000000 +0530 @@ -0,0 +1,647 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Authors: Jeffrey Stedfast <fejj@ximian.com> + * Veerapuram Varadhan <vvaradhan@novell.com> + * + * Copyright 2002 Ximian, Inc. (www.ximian.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA. + * + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <netinet/in.h> +#include <sys/socket.h> +#include <string.h> +#include <stdlib.h> +#include <glib.h> +#include <glib-object.h> + +#include <gconf/gconf.h> +#include <gconf/gconf-client.h> + +#include <libsoup/soup-address.h> +#include <libsoup/soup-uri.h> +#include "e-proxy.h" + +/* Debug */ +#define d(x) + +/* GConf paths and keys */ +#define PATH_GCONF_GNOME_VFS "/system/http_proxy" +#define KEY_GCONF_HTTP_PROXY_PORT (PATH_GCONF_GNOME_VFS "/" "port") +#define KEY_GCONF_HTTP_PROXY_HOST (PATH_GCONF_GNOME_VFS "/" "host") + +#define KEY_GCONF_USE_HTTP_PROXY (PATH_GCONF_GNOME_VFS "/" "use_http_proxy") + +#define KEY_GCONF_HTTP_AUTH_USER (PATH_GCONF_GNOME_VFS "/" "authentication_user") +#define KEY_GCONF_HTTP_AUTH_PW (PATH_GCONF_GNOME_VFS "/" "authentication_password") +#define KEY_GCONF_HTTP_USE_AUTH (PATH_GCONF_GNOME_VFS "/" "use_authentication") + +#define KEY_GCONF_HTTP_PROXY_IGNORE_HOSTS (PATH_GCONF_GNOME_VFS "/" "ignore_hosts") + +struct _EProxyPrivate { + SoupUri* uri; + guint notify_id; /* conxn id of gconf_client_notify_add */ + GSList* ign_hosts; /* List of hostnames. (Strings) */ + GSList* ign_addrs; /* List of hostaddrs. (ProxyHostAddrs) */ + gboolean use_proxy; /* Is system-proxy enabled? */ +}; + +/* Enum definition is copied from gnome-vfs/modules/http-proxy.c */ +typedef enum { + PROXY_IPV4 = 4, + PROXY_IPV6 = 6 +} ProxyAddrType; + +typedef struct { + ProxyAddrType type; /* Specifies whether IPV4 or IPV6 */ + void* addr; /* Either in_addr* or in6_addr* */ + void* mask; /* Either in_addr* or in6_addr* */ +} ProxyHostAddr; + +/* Signals. */ +enum { + CHANGED, + LAST_SIGNAL +}; + +static GObjectClass *parent_class; +static unsigned int signals[LAST_SIGNAL] = { 0 }; + +/* Forward declarations. */ + +static void ep_setting_changed (GConfClient *client, guint32 cnxn_id, + GConfEntry *entry, gpointer user_data); +static void e_proxy_dispose (GObject* object); + +static void ipv6_network_addr (const struct in6_addr *addr, + const struct in6_addr *mask, + struct in6_addr *res); + +static void +ep_free_proxy_host_addr (ProxyHostAddr* host) +{ + if (host) { + if (host->addr) { + g_free (host->addr); + host->addr = NULL; + } + if (host->mask) { + g_free (host->mask); + host->mask = NULL; + } + g_free (host); + } +} + + +static void +e_proxy_class_init (EProxyClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->dispose = e_proxy_dispose; + + /* signals */ + + /** + * EProxy::changed: + * @proxy: the proxy + * + * Emitted when proxy settings in gconf changes. + **/ + signals[CHANGED] = + g_signal_new ("changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EProxyClass, changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + +} + +static void +e_proxy_init (EProxy *pxy, EProxyClass *klass) +{ + EProxyPrivate *priv; + + /* allocate internal structure */ + priv = g_new0 (EProxyPrivate, 1); + pxy->priv = priv; + priv->ign_hosts = NULL; + priv->ign_addrs = NULL; + priv->uri = NULL; + priv->notify_id = 0; + priv->use_proxy = FALSE; +} + +static void +e_proxy_dispose (GObject *object) +{ + EProxy *proxy = (EProxy *)object; + + if (!E_IS_PROXY (proxy)) + return; + + EProxyPrivate *priv = proxy->priv; + + if (priv) { + GConfClient* client = NULL; + + if ((client = gconf_client_get_default ())) { + if (priv->notify_id > 0) + gconf_client_notify_remove (client, priv->notify_id); + g_object_unref (client); + } + + if (priv->uri) + soup_uri_free (priv->uri); + + if (priv->ign_hosts) { + g_slist_foreach (priv->ign_hosts, (GFunc) ep_free_proxy_host_addr, NULL); + g_slist_free (priv->ign_hosts); + } + + if (priv->ign_addrs) { + g_slist_foreach (priv->ign_addrs, (GFunc) g_free, NULL); + g_slist_free (priv->ign_addrs); + } + + priv->notify_id = 0; + + g_free (priv); + priv = NULL; + } +} + +GType +e_proxy_get_type (void) +{ + static GType type = 0; + + if (!type) { + static GTypeInfo info = { + sizeof (EProxyClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) e_proxy_class_init, + NULL, NULL, + sizeof (EProxy), + 0, + (GInstanceInitFunc) e_proxy_init + }; + type = g_type_register_static (G_TYPE_OBJECT, "EProxy", &info, 0); + } + + return type; +} + +static gboolean +ep_need_proxy (EProxy* proxy, const char* host) +{ + SoupAddress *addr = NULL; + EProxyPrivate *priv = proxy->priv; + ProxyHostAddr *p_addr = NULL; + GSList *l; + guint status; + + addr = soup_address_new (host, 0); + status = soup_address_resolve_sync (addr); + if (status == SOUP_STATUS_OK) { + gint addr_len; + struct sockaddr* s_addr = NULL; + + s_addr = soup_address_get_sockaddr (addr, &addr_len); + + /* This will never happen, since we have already called + soup_address_resolve_sync(). + */ + if (!s_addr) + return TRUE; + + if (s_addr->sa_family == AF_INET) { + struct in_addr in, *mask, *addr_in; + + in = ((struct sockaddr_in *)s_addr)->sin_addr; + for (l = priv->ign_addrs; l; l = l->next) { + p_addr = (ProxyHostAddr *)l->data; + if (p_addr->type == PROXY_IPV4) { + addr_in = ((struct in_addr *)p_addr->addr); + mask = ((struct in_addr *)p_addr->mask); + d(g_print ("ep_need_proxy:ipv4: in: %ul\t mask: %ul\t addr: %ul\n", + in.s_addr, mask->s_addr, addr_in->s_addr)); + if ((in.s_addr & mask->s_addr) == addr_in->s_addr) { + d(g_print ("Host [%s] doesn't require proxy\n", host)); + return FALSE; + } + } + } + } else { + struct in6_addr in6, net6; + struct in_addr *addr_in, *mask; + + in6 = ((struct sockaddr_in6 *)s_addr)->sin6_addr; + for (l = priv->ign_addrs; l; l = l->next) { + p_addr = (ProxyHostAddr *)l->data; + ipv6_network_addr (&in6, (struct in6_addr *)p_addr->mask, &net6); + if (p_addr->type == PROXY_IPV6) { + if (IN6_ARE_ADDR_EQUAL (&net6, (struct in6_addr *)p_addr->addr)) { + d(g_print ("Host [%s] doesn't require proxy\n", host)); + return FALSE; + } + } else if (p_addr->type == PROXY_IPV6 && + IN6_IS_ADDR_V4MAPPED (&net6)) { + guint32 v4addr; + + addr_in = ((struct in_addr *)p_addr->addr); + mask = ((struct in_addr *)p_addr->mask); + + v4addr = net6.s6_addr[12] << 24 + | net6.s6_addr[13] << 16 + | net6.s6_addr[14] << 8 + | net6.s6_addr[15]; + if ((v4addr & mask->s_addr) != addr_in->s_addr) { + d(g_print ("Host [%s] doesn't require proxy\n", host)); + return FALSE; + } + } + } + } + } else { + GSList* l; + gchar* hn = g_ascii_strdown (host, -1); + + for (l = priv->ign_hosts; l; l = l->next) { + if (*((gchar *)l->data) == '*') { + if (g_str_has_suffix (hn, ((gchar *)l->data)+1)) { + g_free (hn); + return FALSE; + } + } else if (strcmp (hn, l->data) == 0) { + g_free (hn); + return FALSE; + } + } + g_free (hn); + } + + d(g_print ("%s needs a proxy to connect to internet\n", host)); + return TRUE; +} + +static gboolean +ep_manipulate_ipv4 (ProxyHostAddr *host_addr, + struct in_addr *addr_in, + gchar* netmask) +{ + gboolean has_error = FALSE; + struct in_addr *addr, *mask; + + if (!addr_in) + return has_error; + + host_addr->type = PROXY_IPV4; + addr = g_new0 (struct in_addr, 1); + memcpy (addr, addr_in, sizeof (struct in_addr)); + mask = g_new0 (struct in_addr, 1); + + if (netmask) { + gchar *endptr; + gint width = strtol (netmask, &endptr, 10); + + if (*endptr != '\0' || width < 0 || width > 32) { + has_error = TRUE; + } + mask->s_addr = htonl (~0 << width); + addr->s_addr &= mask->s_addr; + } else { + mask->s_addr = 0xFFFFFFFF; + } + + d(g_print ("ep_manipulate_ipv4: addr_in: %ul, addr: %ul, mask: %ul\n", + addr_in->s_addr, addr->s_addr, mask->s_addr)); + + host_addr->addr = addr; + host_addr->mask = mask; + + return has_error; +} + +static void +ipv6_network_addr(const struct in6_addr *addr, const struct in6_addr *mask, + struct in6_addr *res) +{ + gint i; + + for (i = 0; i < 16; ++i) { + res->s6_addr[i] = addr->s6_addr[i] & mask->s6_addr[i]; + } +} + +static gboolean +ep_manipulate_ipv6 (ProxyHostAddr *host_addr, + struct in6_addr *addr_in6, + gchar* netmask) +{ + gboolean has_error = FALSE; + struct in6_addr *addr, *mask; + int i; + + if (!addr_in6) + return has_error; + + host_addr->type = PROXY_IPV6; + + addr = g_new0 (struct in6_addr, 1); + mask = g_new0 (struct in6_addr, 1); + + for (i = 0; i < 16; ++i) { + addr->s6_addr[i] = addr_in6->s6_addr[i]; + } + if (netmask) { + gchar *endptr; + gint width = strtol(netmask, &endptr, 10); + + if (*endptr != '\0' || width < 0 || width > 128) { + has_error = TRUE; + } + for (i = 0; i < 16; ++i) { + mask->s6_addr[i] = 0; + } + for (i = 0; i < width / 8; i++) { + mask->s6_addr[i] = 0xff; + } + mask->s6_addr[i] = (0xff << (8 - width % 8)) & 0xff; + ipv6_network_addr(addr, mask, addr); + } else { + for (i = 0; i < 16; ++i) { + mask->s6_addr[i] = 0xff; + } + } + + host_addr->addr = addr; + host_addr->mask = mask; + + return has_error; +} + +static void +ep_parse_ignore_host (gpointer data, gpointer user_data) +{ + EProxy* proxy = (EProxy *)user_data; + EProxyPrivate* priv = NULL; + SoupAddress *addr; + guint status; + gchar *input, *netmask, *hostname; + ProxyHostAddr *host_addr; + gboolean has_error = FALSE; + + if (!proxy || !proxy->priv) + return; + + priv = proxy->priv; + input = (gchar *)data; + + if ((netmask = strrchr (input, '/')) != NULL) { + hostname = g_strndup (input, netmask - input); + ++netmask; + } else { + hostname = g_ascii_strdown (input, -1); + } + + addr = soup_address_new (hostname, 0); + status = soup_address_resolve_sync (addr); + if (status == SOUP_STATUS_OK) { + gint addr_len; + struct sockaddr* s_addr = NULL; + + host_addr = g_new0 (ProxyHostAddr, 1); + + s_addr = soup_address_get_sockaddr (addr, &addr_len); + + /* This will never happen, since we have already called + soup_address_resolve_sync(). + */ + if (!s_addr) + goto error; + + if (s_addr->sa_family == AF_INET) + has_error = ep_manipulate_ipv4 (host_addr, + &((struct sockaddr_in *)s_addr)->sin_addr, + netmask); + else + has_error = ep_manipulate_ipv6 (host_addr, + &((struct sockaddr_in6 *)s_addr)->sin6_addr, + netmask); + + if (!has_error) + priv->ign_addrs = g_slist_append (priv->ign_addrs, host_addr); + + g_free (hostname); + } else { + d(g_print ("Unable to resolve %s\n", hostname)); + priv->ign_hosts = g_slist_append (priv->ign_hosts, hostname); + } + error: + g_object_unref (addr); +} + +static void +ep_set_proxy (GConfClient *client, + gpointer user_data, + gboolean regen_ign_host_list, + gboolean set_auth) +{ + char *proxy_server = NULL, *proxy_user = NULL, *proxy_pw = NULL, *uri = NULL; + gboolean use_auth; + int proxy_port; + EProxy* proxy = (EProxy *)user_data; + EProxyPrivate* priv = proxy->priv; + GSList *ignore; + + priv->use_proxy = gconf_client_get_bool (client, KEY_GCONF_USE_HTTP_PROXY, NULL); + if (priv->use_proxy == FALSE) { + if (priv->uri) { + soup_uri_free (priv->uri); + priv->uri = NULL; + } + goto emit_signal; + } + + proxy_server = gconf_client_get_string (client, KEY_GCONF_HTTP_PROXY_HOST, NULL); + proxy_port = gconf_client_get_int (client, KEY_GCONF_HTTP_PROXY_PORT, NULL); + uri = g_strdup_printf ("http://%s:%d", proxy_server, proxy_port); + d(g_print ("ep_set_proxy: uri: %s\n", uri)); + + if (regen_ign_host_list) { + if (priv->ign_hosts) { + g_slist_foreach (priv->ign_hosts, (GFunc) g_free, NULL); + g_slist_free (priv->ign_hosts); + priv->ign_hosts = NULL; + } + + if (priv->ign_addrs) { + g_slist_foreach (priv->ign_addrs, (GFunc) g_free, NULL); + g_slist_free (priv->ign_addrs); + priv->ign_addrs = NULL; + } + + ignore = gconf_client_get_list (client, KEY_GCONF_HTTP_PROXY_IGNORE_HOSTS, + GCONF_VALUE_STRING, NULL); + if (ignore) { + g_slist_foreach (ignore, (GFunc) ep_parse_ignore_host, proxy); + g_slist_foreach (ignore, (GFunc) g_free, NULL); + g_slist_free (ignore); + } + } else if (set_auth) { + + use_auth = gconf_client_get_bool (client, KEY_GCONF_HTTP_USE_AUTH, NULL); + if (use_auth == TRUE) { + proxy_user = gconf_client_get_string (client, KEY_GCONF_HTTP_AUTH_USER, NULL); + proxy_pw = gconf_client_get_string (client, KEY_GCONF_HTTP_AUTH_PW, NULL); + + if (uri) + g_free (uri); + + uri = g_strdup_printf ("http://%s:%s@%s:%d", proxy_user, proxy_pw, proxy_server, proxy_port); + } + } + + if (priv->uri) { + soup_uri_free (priv->uri); + priv->uri = NULL; + } + + if (uri) + priv->uri = soup_uri_new (uri); + d(g_print ("system-proxy: uri: %s\n", uri)); + + emit_signal: + g_signal_emit (proxy, signals[CHANGED], 0); + + g_free (uri); + + return; +} + +static void +ep_setting_changed (GConfClient *client, guint32 cnxn_id, + GConfEntry *entry, gpointer user_data) +{ + const char *key; + EProxy* proxy = (EProxy *)user_data; + + if (!proxy || !proxy->priv) + return; + + key = gconf_entry_get_key(entry); + + if (strcmp(key, KEY_GCONF_USE_HTTP_PROXY) == 0 + || strcmp(key, KEY_GCONF_HTTP_PROXY_IGNORE_HOSTS) == 0 + || strcmp(key, KEY_GCONF_HTTP_PROXY_HOST) == 0 + || strcmp(key, KEY_GCONF_HTTP_PROXY_PORT) == 0) { + gboolean regen_ign_host_list = FALSE; + + if (strcmp(key, KEY_GCONF_HTTP_PROXY_IGNORE_HOSTS) == 0) + regen_ign_host_list = TRUE; + ep_set_proxy (client, user_data, regen_ign_host_list, FALSE); + d(g_print ("e-proxy.c:ep_settings_changed: proxy settings changed\n")); + } else if (strcmp(key, KEY_GCONF_HTTP_AUTH_USER) == 0 + || strcmp(key, KEY_GCONF_HTTP_AUTH_PW) == 0 + || strcmp(key, KEY_GCONF_HTTP_USE_AUTH) == 0) { + ep_set_proxy (client, user_data, FALSE, TRUE); + d(g_print ("e-proxy.c:ep_settings_changed: auth settings changed\n")); + } +} + +EProxy* +e_proxy_new (void) +{ + EProxy *proxy = NULL; + + proxy = g_object_new (E_TYPE_PROXY, NULL); + + return proxy; +} + +void +e_proxy_setup_proxy (EProxy* proxy) +{ + GConfClient *client; + + /* We get the gnome-vfs proxy keys here + set soup up to use the proxy, + and listen to any changes */ + + if (!(client = gconf_client_get_default ())) + return; + + if (!proxy || !proxy->priv) + return; + + /* Listen to the changes in the gnome-vfs path */ + gconf_client_add_dir (client, PATH_GCONF_GNOME_VFS, + GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); + + if (proxy->priv->notify_id == 0) + proxy->priv->notify_id = gconf_client_notify_add (client, PATH_GCONF_GNOME_VFS, + ep_setting_changed, (gpointer)proxy, + NULL, NULL); + + ep_set_proxy (client, proxy, TRUE, TRUE); + + g_object_unref (client); +} + +SoupUri* +e_proxy_peek_uri (EProxy* proxy) +{ + if (!proxy || !proxy->priv) + return NULL; + + return proxy->priv->uri; +} + +gboolean +e_proxy_require_proxy_for_uri (EProxy* proxy, const char* uri) +{ + SoupUri *srv_uri = NULL; + gboolean ret = FALSE; + + if (!uri || !proxy || !proxy->priv) + return ret; + + if (!proxy->priv->use_proxy) { + d(g_print ("[%s] don't need a proxy to connect to internet\n", uri)); + return ret; + } + + srv_uri = soup_uri_new (uri); + + ret = ep_need_proxy (proxy, srv_uri->host); + + soup_uri_free (srv_uri); + + return ret; +}
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor