[evolution-patches] IMAP over ssh.



Without a GUI configuration for it (it's #if 0 here for testing and for
reference; I'll put it back in my own build but not commit it).

I can't get at either of my IMAP accounts without this.

Index: camel/providers/imap/camel-imap-provider.c
===================================================================
RCS file: /cvs/gnome/evolution/camel/providers/imap/camel-imap-provider.c,v
retrieving revision 1.24
diff -u -p -r1.24 camel-imap-provider.c
--- camel/providers/imap/camel-imap-provider.c	22 May 2002 20:17:48 -0000	1.24
+++ camel/providers/imap/camel-imap-provider.c	4 Sep 2003 17:38:24 -0000
@@ -39,6 +39,15 @@ static gint check_equal (char *s1, char 
 static gint imap_url_equal (gconstpointer a, gconstpointer b);
 
 CamelProviderConfEntry imap_conf_entries[] = {
+#if 0
+	{ CAMEL_PROVIDER_CONF_SECTION_START, "cmdsection", NULL,
+	  N_("Connection to Server") },
+	{ CAMEL_PROVIDER_CONF_CHECKBOX, "use_command", NULL,
+	  N_("Use custom command to connect to server"), "0" },
+	{ CAMEL_PROVIDER_CONF_ENTRY, "command", "use_command",
+	  N_("Command:"), "ssh -C -l %u %h exec /usr/sbin/imapd" },
+	{ CAMEL_PROVIDER_CONF_SECTION_END },
+#endif
 	{ CAMEL_PROVIDER_CONF_SECTION_START, "mailcheck", NULL,
 	  N_("Checking for new mail") },
 	{ CAMEL_PROVIDER_CONF_CHECKBOX, "check_all", NULL,
Index: camel/providers/imap/camel-imap-store.c
===================================================================
RCS file: /cvs/gnome/evolution/camel/providers/imap/camel-imap-store.c,v
retrieving revision 1.256
diff -u -p -r1.256 camel-imap-store.c
--- camel/providers/imap/camel-imap-store.c	19 Aug 2003 02:36:26 -0000	1.256
+++ camel/providers/imap/camel-imap-store.c	4 Sep 2003 17:38:25 -0000
@@ -52,6 +52,7 @@
 #include "camel-stream.h"
 #include "camel-stream-buffer.h"
 #include "camel-stream-fs.h"
+#include "camel-stream-process.h"
 #include "camel-tcp-stream-raw.h"
 #include "camel-tcp-stream-ssl.h"
 #include "camel-url.h"
@@ -251,6 +252,7 @@ camel_imap_store_init (gpointer object, 
 	imap_store->dir_sep = '\0';
 	imap_store->current_folder = NULL;
 	imap_store->connected = FALSE;
+	imap_store->preauthed = FALSE;
 	
 	imap_store->tag_prefix = imap_tag_prefix++;
 	if (imap_tag_prefix > 'Z')
@@ -599,9 +601,10 @@ connect_to_server (CamelService *service
 	store->istream = camel_stream_buffer_new (tcp_stream, CAMEL_STREAM_BUFFER_READ);
 	
 	store->connected = TRUE;
+	store->preauthed = FALSE;
 	store->command = 0;
 	
-	/* Read the greeting, if any. FIXME: deal with PREAUTH */
+	/* Read the greeting, if any, and deal with PREAUTH */
 	if (camel_imap_store_readline (store, &buf, ex) < 0) {
 		if (store->istream) {
 			camel_object_unref (CAMEL_OBJECT (store->istream));
@@ -617,6 +620,8 @@ connect_to_server (CamelService *service
 		
 		return FALSE;
 	}
+	if (!strncmp(buf, "* PREAUTH", 9))
+		store->preauthed = TRUE;
 	g_free (buf);
 	
 	/* get the imap server capabilities */
@@ -728,6 +733,149 @@ connect_to_server (CamelService *service
 #endif /* HAVE_SSL */
 }
 
+static gboolean
+connect_to_server_process (CamelService *service, const char *cmd, CamelException *ex)
+{
+	CamelImapStore *store = (CamelImapStore *) service;
+	CamelStream *cmd_stream;
+	int ret, i = 0;
+	char *buf;
+	char *cmd_copy;
+	char *full_cmd;
+	char *child_env[7];
+
+	/* Put full details in the environment, in case the connection 
+	   program needs them */
+	buf = camel_url_to_string(service->url, 0);
+	child_env[i++] = g_strdup_printf("URL=%s", buf);
+	g_free(buf);
+
+	child_env[i++] = g_strdup_printf("URLHOST=%s", service->url->host);
+	if (service->url->port)
+		child_env[i++] = g_strdup_printf("URLPORT=%d", service->url->port);
+	if (service->url->user)
+		child_env[i++] = g_strdup_printf("URLUSER=%s", service->url->user);
+	if (service->url->passwd)
+		child_env[i++] = g_strdup_printf("URLPASSWD=%s", service->url->passwd);
+	if (service->url->path)
+		child_env[i++] = g_strdup_printf("URLPATH=%s", service->url->path);
+	child_env[i] = NULL;
+
+	/* Now do %h, %u, etc. substitution in cmd */
+	buf = cmd_copy = g_strdup(cmd);
+
+	full_cmd = "";
+
+	for(;;) {
+		char *pc;
+		char *tmp;
+		char *var;
+		int len;
+
+		pc = strchr(buf, '%');
+	ignore:
+		if (!pc) {
+			tmp = g_strdup_printf("%s%s", full_cmd, buf);
+			g_free(full_cmd);
+			full_cmd = tmp;
+			break;
+		}
+		
+		len = pc - buf;
+
+		var = NULL;
+
+		switch(pc[1]) {
+		case 'h':
+			var = service->url->host;
+			break;
+		case 'u':
+			var = service->url->user;
+			break;
+		}
+		if (!var) {
+			/* If there wasn't a valid %-code, with an actual
+			   variable to insert, pretend we didn't see the % */
+			pc = strchr(pc + 1, '%');
+			goto ignore;
+		}
+		tmp = g_strdup_printf("%s%.*s%s", full_cmd, len, buf, var);
+		g_free(full_cmd);
+		full_cmd = tmp;
+		buf = pc + 2;
+	}
+			
+	g_free(cmd_copy);
+
+	cmd_stream = camel_stream_process_new ();
+	
+	ret = camel_stream_process_connect (CAMEL_STREAM_PROCESS(cmd_stream),
+					    full_cmd, (const char **)child_env);
+
+	while (i)
+		g_free(child_env[--i]);
+		
+	if (ret == -1) {
+		if (errno == EINTR)
+			camel_exception_set (ex, CAMEL_EXCEPTION_USER_CANCEL,
+					     _("Connection cancelled"));
+		else
+			camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_UNAVAILABLE,
+					      _("Could not connect with command \"%s\": %s"),
+					      full_cmd, g_strerror (errno));
+		
+		camel_object_unref (CAMEL_OBJECT (cmd_stream));
+		g_free(full_cmd);
+		return FALSE;
+	}
+	g_free(full_cmd);
+	
+	store->ostream = cmd_stream;
+	store->istream = camel_stream_buffer_new (cmd_stream, CAMEL_STREAM_BUFFER_READ);
+	
+	store->connected = TRUE;
+	store->preauthed = FALSE;
+	store->command = 0;
+	
+	/* Read the greeting, if any, and deal with PREAUTH */
+	if (camel_imap_store_readline (store, &buf, ex) < 0) {
+		if (store->istream) {
+			camel_object_unref (CAMEL_OBJECT (store->istream));
+			store->istream = NULL;
+		}
+		
+		if (store->ostream) {
+			camel_object_unref (CAMEL_OBJECT (store->ostream));
+			store->ostream = NULL;
+		}
+		
+		store->connected = FALSE;
+		return FALSE;
+	}
+	if (!strncmp(buf, "* PREAUTH", 9))
+		store->preauthed = TRUE;
+	g_free (buf);
+	
+	/* get the imap server capabilities */
+	if (!imap_get_capability (service, ex)) {
+		if (store->istream) {
+			camel_object_unref (CAMEL_OBJECT (store->istream));
+			store->istream = NULL;
+		}
+		
+		if (store->ostream) {
+			camel_object_unref (CAMEL_OBJECT (store->ostream));
+			store->ostream = NULL;
+		}
+		
+		store->connected = FALSE;
+		return FALSE;
+	}
+	
+	return TRUE;
+	
+}
+
 static struct {
 	char *value;
 	int mode;
@@ -742,10 +890,16 @@ static struct {
 static gboolean
 connect_to_server_wrapper (CamelService *service, CamelException *ex)
 {
+	const char *command;
 #ifdef HAVE_SSL
 	const char *use_ssl;
 	int i, ssl_mode;
-	
+#endif
+	command = camel_url_get_param (service->url, "command");
+	if (command)
+		return connect_to_server_process (service, command, ex);
+
+#ifdef HAVE_SSL
 	use_ssl = camel_url_get_param (service->url, "use_ssl");
 	if (use_ssl) {
 		for (i = 0; ssl_options[i].value; i++)
@@ -1070,6 +1224,13 @@ imap_auth_loop (CamelService *service, C
 	
 	CAMEL_SERVICE_ASSERT_LOCKED (store, connect_lock);
 	
+	if (store->preauthed) {
+		if (camel_verbose_debug)
+			fprintf(stderr, "Server %s has preauthenticated us.\n",
+				service->url->host);
+		return TRUE;
+	}
+
 	if (service->url->authmech) {
 		if (!g_hash_table_lookup (store->authtypes, service->url->authmech)) {
 			camel_exception_setv (ex, CAMEL_EXCEPTION_SERVICE_CANT_AUTHENTICATE,
Index: camel/providers/imap/camel-imap-store.h
===================================================================
RCS file: /cvs/gnome/evolution/camel/providers/imap/camel-imap-store.h,v
retrieving revision 1.55
diff -u -p -r1.55 camel-imap-store.h
--- camel/providers/imap/camel-imap-store.h	24 Oct 2002 14:01:53 -0000	1.55
+++ camel/providers/imap/camel-imap-store.h	4 Sep 2003 17:38:25 -0000
@@ -107,6 +107,7 @@ struct _CamelImapStore {
 	
 	/* Information about the command channel / connection status */
 	gboolean connected;
+	gboolean preauthed;
 	char tag_prefix;
 	guint32 command;
 	CamelFolder *current_folder;



-- 
dwmw2




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