evolution-data-server r8581 - in trunk: . libedataserver servers/exchange servers/exchange/lib servers/groupwise



Author: msuman
Date: Tue Mar 25 11:28:00 2008
New Revision: 8581
URL: http://svn.gnome.org/viewvc/evolution-data-server?rev=8581&view=rev

Log:
Varadhan's patch for configurable proxy settings in Evolution. 

M    ChangeLog
M    servers/exchange/lib/e2k-context.c
M    servers/exchange/ChangeLog
M    servers/groupwise/ChangeLog
M    servers/groupwise/Makefile.am
M    servers/groupwise/e-gw-connection.c
A    libedataserver/e-proxy.c
A    libedataserver/e-proxy.h
M    libedataserver/Makefile.am


Added:
   trunk/libedataserver/e-proxy.c
   trunk/libedataserver/e-proxy.h
Modified:
   trunk/ChangeLog
   trunk/libedataserver/Makefile.am
   trunk/servers/exchange/ChangeLog
   trunk/servers/exchange/lib/e2k-context.c
   trunk/servers/groupwise/ChangeLog
   trunk/servers/groupwise/Makefile.am
   trunk/servers/groupwise/e-gw-connection.c

Modified: trunk/libedataserver/Makefile.am
==============================================================================
--- trunk/libedataserver/Makefile.am	(original)
+++ trunk/libedataserver/Makefile.am	Tue Mar 25 11:28:00 2008
@@ -7,7 +7,8 @@
 	-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)
 
 lib_LTLIBRARIES = libedataserver-1.2.la
 noinst_PROGRAMS = test-source-list
@@ -28,6 +29,7 @@
 	e-list-iterator.c		\
 	e-memory.c			\
 	e-msgport.c			\
+	e-proxy.c			\
 	e-sexp.c			\
 	e-source-group.c		\
 	e-source-list.c			\
@@ -46,7 +48,8 @@
 	$(E_DATA_SERVER_LIBS)				\
 	$(ICONV_LIBS)					\
 	$(DB_LIBS)					\
-	$(SOCKET_LIBS)
+	$(SOCKET_LIBS)					\
+	$(SOUP_LIBS)
 
 libedataserver_1_2_la_LDFLAGS = \
 	-version-info $(LIBEDATASERVER_CURRENT):$(LIBEDATASERVER_REVISION):$(LIBEDATASERVER_AGE) $(NO_UNDEFINED)
@@ -69,6 +72,7 @@
 	e-list-iterator.h		\
 	e-memory.h			\
 	e-msgport.h			\
+	e-proxy.h			\
 	e-sexp.h			\
 	e-source-group.h		\
 	e-source-list.h			\

Added: trunk/libedataserver/e-proxy.c
==============================================================================
--- (empty file)
+++ trunk/libedataserver/e-proxy.c	Tue Mar 25 11:28:00 2008
@@ -0,0 +1,649 @@
+/* -*- 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_NETWORK_CONFIG "/apps/evolution/shell/network_config"
+#define KEY_GCONF_HTTP_PROXY_PORT (PATH_GCONF_NETWORK_CONFIG "/" "http_port")
+#define KEY_GCONF_HTTP_PROXY_HOST (PATH_GCONF_NETWORK_CONFIG "/" "http_host")
+#define KEY_GCONF_HTTPS_PROXY_PORT (PATH_GCONF_NETWORK_CONFIG "/" "secure_port")
+#define KEY_GCONF_HTTPS_PROXY_HOST (PATH_GCONF_NETWORK_CONFIG "/" "secure_host")
+#define KEY_GCONF_SOCKS_PROXY_PORT (PATH_GCONF_NETWORK_CONFIG "/" "socks_port")
+#define KEY_GCONF_SOCKS_PROXY_HOST (PATH_GCONF_NETWORK_CONFIG "/" "socks_host")
+#define KEY_GCONF_USE_HTTP_PROXY (PATH_GCONF_NETWORK_CONFIG "/" "use_http_proxy")
+#define KEY_GCONF_HTTP_AUTH_USER (PATH_GCONF_NETWORK_CONFIG "/" "authentication_user")
+#define KEY_GCONF_HTTP_AUTH_PW   (PATH_GCONF_NETWORK_CONFIG "/" "authentication_password")
+#define KEY_GCONF_HTTP_USE_AUTH (PATH_GCONF_NETWORK_CONFIG "/" "use_authentication")
+
+#define KEY_GCONF_HTTP_PROXY_IGNORE_HOSTS (PATH_GCONF_NETWORK_CONFIG "/" "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, NULL);
+	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, NULL);
+	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 evolution-shell 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 evolution-shell path */
+	gconf_client_add_dir (client, PATH_GCONF_NETWORK_CONFIG,
+			      GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+
+	if (proxy->priv->notify_id == 0)
+		proxy->priv->notify_id = gconf_client_notify_add (client, PATH_GCONF_NETWORK_CONFIG,
+								  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;
+}

Added: trunk/libedataserver/e-proxy.h
==============================================================================
--- (empty file)
+++ trunk/libedataserver/e-proxy.h	Tue Mar 25 11:28:00 2008
@@ -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

Modified: trunk/servers/exchange/lib/e2k-context.c
==============================================================================
--- trunk/servers/exchange/lib/e2k-context.c	(original)
+++ trunk/servers/exchange/lib/e2k-context.c	Tue Mar 25 11:28:00 2008
@@ -48,6 +48,7 @@
 #include "e2k-utils.h"
 #include "e2k-xml-utils.h"
 
+#include <libedataserver/e-proxy.h>
 #include <libsoup/soup.h>
 #include <libxml/parser.h>
 #include <libxml/tree.h>
@@ -98,6 +99,7 @@
 	/* Forms-based authentication */
 	char *cookie;
 	gboolean cookie_verified;
+	EProxy* proxy;
 };
 
 /* For operations with progress */
@@ -107,6 +109,9 @@
 /* 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;
@@ -124,7 +129,32 @@
 static gboolean do_notification (GIOChannel *source, GIOCondition condition, gpointer data);
 
 static void setup_message (SoupSession *session, SoupMessage *msg, SoupSocket *socket, gpointer user_data);
+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)
 {
@@ -135,6 +165,9 @@
 		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
@@ -182,8 +215,13 @@
 		g_free (ctx->priv->cookie);
 		g_free (ctx->priv->notification_uri);
 
+		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 @@
 		      const char *password)
 {
 	guint timeout = E2K_SOUP_SESSION_TIMEOUT;
+	SoupURI* uri = NULL;
 #ifdef E2K_DEBUG
 	SoupLogger *logger;
 	SoupLoggerLogLevel level;
@@ -395,9 +434,14 @@
 	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);
@@ -406,7 +450,7 @@
 
 	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);
 	g_signal_connect (ctx->priv->async_session, "request_started",

Modified: trunk/servers/groupwise/Makefile.am
==============================================================================
--- trunk/servers/groupwise/Makefile.am	(original)
+++ trunk/servers/groupwise/Makefile.am	Tue Mar 25 11:28:00 2008
@@ -15,9 +15,10 @@
 	$(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) 
 
 build-timestamp.h : $(top_builddir)/config.h

Modified: trunk/servers/groupwise/e-gw-connection.c
==============================================================================
--- trunk/servers/groupwise/e-gw-connection.c	(original)
+++ trunk/servers/groupwise/e-gw-connection.c	Tue Mar 25 11:28:00 2008
@@ -27,6 +27,7 @@
 #include <string.h>
 #include <ctype.h>
 #include <glib/gi18n-lib.h>
+#include <libedataserver/e-proxy.h>
 #include <libsoup/soup.h>
 #include "soup-soap-message.h"
 #include "e-gw-connection.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 @@
 	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)
 {
@@ -342,6 +375,11 @@
 			g_free (priv->server_time) ;
 			priv->server_time = NULL ;
 		}
+
+		if (priv->proxy) {
+			g_object_unref (priv->proxy);
+			priv->proxy = NULL;
+		}
 	}
 
 	if (parent_class->dispose)
@@ -393,6 +431,11 @@
 	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);
 	priv->reauth_mutex = g_mutex_new ();
@@ -491,6 +534,12 @@
 	/* 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 */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]