Index: camel/ChangeLog
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/ChangeLog,v
retrieving revision 1.2474
diff -u -p -r1.2474 ChangeLog
--- camel/ChangeLog	24 Aug 2005 02:35:14 -0000	1.2474
+++ camel/ChangeLog	26 Aug 2005 05:11:35 -0000
@@ -1,3 +1,12 @@
+2005-08-26  Not Zed  <NotZed@Ximian.com>
+
+	** See bug #304415.
+
+	* camel-gpg-context.c (gpg_conf): utility for getting values from
+	the gpg config file.
+	(gpg_hash_to_id): get the default algo from the gpg options.
+	(gpg_hash_str): get the default from gpg options.
+
 2005-08-22  Not Zed  <NotZed@Ximian.com>
 
 	* camel-store.c (camel_store_rename_folder): init folders and only
Index: camel/camel-gpg-context.c
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-gpg-context.c,v
retrieving revision 1.74
diff -u -p -r1.74 camel-gpg-context.c
--- camel/camel-gpg-context.c	24 Aug 2005 02:35:14 -0000	1.74
+++ camel/camel-gpg-context.c	26 Aug 2005 05:11:35 -0000
@@ -62,12 +62,20 @@
 #include "camel-debug.h"
 #include "camel-i18n.h"
 
+#include <pthread.h>
+
 #define d(x) 
 
 #ifdef GPG_LOG
 static int logid;
 #endif
 
+/* If we need it, we keep track of the gpg config file globally */
+static char *gpg_conf_name;
+static time_t gpg_conf_mtime;
+static pthread_mutex_t gpg_conf_lock = PTHREAD_MUTEX_INITIALIZER;
+static GHashTable *gpg_conf_table;
+
 static CamelCipherContextClass *parent_class = NULL;
 
 /**
@@ -112,17 +120,120 @@ camel_gpg_context_set_always_trust (Came
 	ctx->always_trust = always_trust;
 }
 
+/* This gets values from the gpg conf file.  Because some values need
+   'pgp-' infront of them, this will automatically convert 'pgp-foo'
+   into a lookup in the conf for 'foo', with 'pgp-' prefixed to it,
+   and still return static strings */
+
+static const char *
+gpg_conf(CamelGpgContext *ctx, const char *name)
+{
+	const char *val;
+	struct stat st;
+
+	/* gpg man page doesn't say much about gpg.conf, this assumes 1 option per line,
+	   with maybe a '=' or single whitespace between option and arguments, if any */
+
+	pthread_mutex_lock(&gpg_conf_lock);
+
+	/* TODO: because we need to return static strings, this leaks any options
+	   that changed while we were running ... probably don't care */
+
+	if (gpg_conf_name == NULL
+	    || (stat(gpg_conf_name, &st) == 0 && st.st_mtime != gpg_conf_mtime)) {
+		FILE *fp;
+		int debug;
+
+		if (gpg_conf_name == NULL) {	
+			const char *home;
+
+			home = getenv("GNUPGHOME");
+			if (home == NULL || home[0] == 0)
+				gpg_conf_name = g_build_filename(g_get_home_dir(), ".gnupg", "gpg.conf", NULL);
+			else
+				gpg_conf_name = g_build_filename(home, "gpg.conf", NULL);
+
+			if (stat(gpg_conf_name, &st) == 0)
+				gpg_conf_mtime = st.st_mtime;
+		} else {
+			gpg_conf_mtime = st.st_mtime;
+		}
+
+		if (gpg_conf_table == NULL)
+			gpg_conf_table = g_hash_table_new(g_str_hash, g_str_equal);
+
+		debug = camel_debug_start("gpg:conf");
+		if (debug)
+			printf("(re)Reading gpg options from '%s'\n", gpg_conf_name);
+
+		fp = fopen(gpg_conf_name, "r");
+		if (fp) {
+			GString *line = g_string_new("");
+			int c;
+
+			do {
+				c = fgetc(fp);
+				if (c == '\n' || c == EOF) {
+					char *p = line->str, *n;
+
+					while (*p && (*p == ' ' || *p == '\t'))
+						p+=1;
+					if (*p && *p != '#') {
+						n = p;
+						while (*p && *p != '=' && *p != ' ' && *p != '\t')
+							p+=1;
+						if (*p)
+							*p++ = 0;
+						else
+							p = n;
+
+						if ((val = g_hash_table_lookup(gpg_conf_table, n)) == NULL
+						    || strcmp(val, p) != 0) {
+							g_hash_table_insert(gpg_conf_table, g_strdup(n), g_strdup(p));
+							if (debug)
+								printf("%s='%s'\n", n, p);
+						}
+					}
+					g_string_truncate(line, 0);
+				} else
+					g_string_append_c(line, c);
+			} while (c != EOF);
+			g_string_free(line, TRUE);
+			fclose(fp);
+		}
+
+		if (debug)
+			camel_debug_end();
+	}
+
+	val = g_hash_table_lookup(gpg_conf_table, name);
+	if (val == NULL && !strncmp(name, "pgp-", 4)) {
+		val = g_hash_table_lookup(gpg_conf_table, name+4);
+		if (val) {
+			char *v;
+
+			v = g_strdup_printf("pgp-%s", val);
+			g_hash_table_insert(gpg_conf_table, g_strdup(name), v);
+			val = v;
+		}
+	}
+
+	pthread_mutex_unlock(&gpg_conf_lock);
+
+	return val;
+}
 
 static const char *
 gpg_hash_to_id (CamelCipherContext *context, CamelCipherHash hash)
 {
+	const char *v;
+
 	switch (hash) {
 	case CAMEL_CIPHER_HASH_MD2:
 		return "pgp-md2";
 	case CAMEL_CIPHER_HASH_MD5:
 		return "pgp-md5";
 	case CAMEL_CIPHER_HASH_SHA1:
-	case CAMEL_CIPHER_HASH_DEFAULT:
 		return "pgp-sha1";
 	case CAMEL_CIPHER_HASH_RIPEMD160:
 		return "pgp-ripemd160";
@@ -130,9 +241,10 @@ gpg_hash_to_id (CamelCipherContext *cont
 		return "pgp-tiger192";
 	case CAMEL_CIPHER_HASH_HAVAL5160:
 		return "pgp-haval-5-160";
+	default:
+		v = gpg_conf((CamelGpgContext *)context, "pgp-digest-algo");
+		return v?v:"pgp-sha1";
 	}
-	
-	return NULL;
 }
 
 static CamelCipherHash
@@ -464,27 +576,37 @@ gpg_ctx_free (struct _GpgCtx *gpg)
 	g_free (gpg);
 }
 
-static const char *
+static char *
 gpg_hash_str (CamelCipherHash hash)
 {
+	const char *v;
+
 	switch (hash) {
 	case CAMEL_CIPHER_HASH_MD2:
-		return "--digest-algo=MD2";
+		v ="MD2";
+		break;
 	case CAMEL_CIPHER_HASH_MD5:
-		return "--digest-algo=MD5";
+		v = "MD5";
+		break;
 	case CAMEL_CIPHER_HASH_SHA1:
-		return "--digest-algo=SHA1";
+		v = "SHA1";
+		break;
 	case CAMEL_CIPHER_HASH_RIPEMD160:
-		return "--digest-algo=RIPEMD160";
+		v = "RIPEMD160";
+		break;
 	default:
-		return NULL;
+		v = gpg_conf(NULL, "digest-algo");
+		if (v == NULL)
+			v = "SHA1";
+		break;
 	}
+
+	return g_strdup_printf("--digest-algo=%s", v);
 }
 
 static GPtrArray *
-gpg_ctx_get_argv (struct _GpgCtx *gpg, int status_fd, char **sfd, int passwd_fd, char **pfd)
+gpg_ctx_get_argv (struct _GpgCtx *gpg, int status_fd, char **sfd, int passwd_fd, char **pfd, char **hash)
 {
-	const char *hash_str;
 	GPtrArray *argv;
 	char *buf;
 	int i;
@@ -517,9 +639,9 @@ gpg_ctx_get_argv (struct _GpgCtx *gpg, i
 		g_ptr_array_add (argv, "--detach");
 		if (gpg->armor)
 			g_ptr_array_add (argv, "--armor");
-		hash_str = gpg_hash_str (gpg->hash);
-		if (hash_str)
-			g_ptr_array_add (argv, (char *) hash_str);
+		*hash = gpg_hash_str (gpg->hash);
+		if (*hash)
+			g_ptr_array_add (argv, *hash);
 		if (gpg->userid) {
 			g_ptr_array_add (argv, "-u");
 			g_ptr_array_add (argv, (char *) gpg->userid);
@@ -584,7 +706,7 @@ gpg_ctx_get_argv (struct _GpgCtx *gpg, i
 static int
 gpg_ctx_op_start (struct _GpgCtx *gpg)
 {
-	char *status_fd = NULL, *passwd_fd = NULL;
+	char *status_fd = NULL, *passwd_fd = NULL, *hash = NULL;
 	int i, maxfd, errnosave, fds[10];
 	GPtrArray *argv;
 	int flags;
@@ -598,7 +720,7 @@ gpg_ctx_op_start (struct _GpgCtx *gpg)
 			goto exception;
 	}
 	
-	argv = gpg_ctx_get_argv (gpg, fds[7], &status_fd, fds[8], &passwd_fd);
+	argv = gpg_ctx_get_argv (gpg, fds[7], &status_fd, fds[8], &passwd_fd, &hash);
 	
 	if (!(gpg->pid = fork ())) {
 		/* child process */
@@ -629,13 +751,15 @@ gpg_ctx_op_start (struct _GpgCtx *gpg)
 		g_ptr_array_free (argv, TRUE);
 		g_free (status_fd);
 		g_free (passwd_fd);
+		g_free(hash);
 		goto exception;
 	}
 	
 	g_ptr_array_free (argv, TRUE);
 	g_free (status_fd);
 	g_free (passwd_fd);
-	
+	g_free(hash);
+
 	/* Parent */
 	close (fds[0]);
 	gpg->stdin_fd = fds[1];
Index: camel/camel-gpg-context.h
===================================================================
RCS file: /cvs/gnome/evolution-data-server/camel/camel-gpg-context.h,v
retrieving revision 1.4
diff -u -p -r1.4 camel-gpg-context.h
--- camel/camel-gpg-context.h	1 Nov 2002 00:45:05 -0000	1.4
+++ camel/camel-gpg-context.h	26 Aug 2005 05:11:35 -0000
@@ -47,9 +47,7 @@ struct _CamelGpgContext {
 
 struct _CamelGpgContextClass {
 	CamelCipherContextClass parent_class;
-	
 };
-
 
 CamelType camel_gpg_context_get_type (void);
 
