unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* New crypto patch series
@ 2011-05-26  1:01 Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 01/11] Simplify reply_part function to eliminate redundant code paths Jameson Graef Rollins
                   ` (11 more replies)
  0 siblings, 12 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

Hi, folks.  This is a series of patches that constitute a complete
rework of notmuch crypto support (signature verification and
decryption of PGP/MIME messages, with emacs ui support), including
some relevant preparatory patches, on top of the notmuch/master branch
at b6862c7eb9bfb00183e568b40d77ea25ade21db2.  This work is also
available on the "new-crypto" branch of my notmuch repo:

git://finestructure.net/notmuch [new-crypto]
aa41285c5f75f8ea30d4582f6b8e1aa306f1632c

It's sounding unlikely that Carl will accept this work in to master
any time soon, due to concerns he has about how the crypto processing
affects part numbering (a concern that I think is pretty minor, and
really don't affect the usability of the new functionality, fwiw).  In
the mean time, I wanted to get these patches out there, for those of
us that depend on this functionality.

jamie.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 01/11] Simplify reply_part function to eliminate redundant code paths.
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 02/11] Integrate reply_part_content function into reply_part function Jameson Graef Rollins
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

This is the same logic but with less code.
---
 notmuch-reply.c |   41 ++++++++++++++---------------------------
 1 files changed, 14 insertions(+), 27 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index ab15650..5d72b1f 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -88,31 +88,8 @@ static void
 reply_part (GMimeObject *part,
 	    unused (int *part_count))
 {
-    GMimeContentDisposition *disposition;
-    GMimeContentType *content_type;
-
-    disposition = g_mime_object_get_content_disposition (part);
-    if (disposition &&
-	strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
-    {
-	const char *filename = g_mime_part_get_filename (GMIME_PART (part));
-	content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
-
-	if (g_mime_content_type_is_type (content_type, "text", "*") &&
-	    !g_mime_content_type_is_type (content_type, "text", "html"))
-	{
-	    reply_part_content (part);
-	}
-	else
-	{
-	    printf ("Attachment: %s (%s)\n", filename,
-		    g_mime_content_type_to_string (content_type));
-	}
-
-	return;
-    }
-
-    content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
+    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
+    GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part);
 
     if (g_mime_content_type_is_type (content_type, "text", "*") &&
 	!g_mime_content_type_is_type (content_type, "text", "html"))
@@ -121,8 +98,18 @@ reply_part (GMimeObject *part,
     }
     else
     {
-	printf ("Non-text part: %s\n",
-		g_mime_content_type_to_string (content_type));
+	if (disposition &&
+	    strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
+	{
+	    const char *filename = g_mime_part_get_filename (GMIME_PART (part));
+	    printf ("Attachment: %s (%s)\n", filename,
+		    g_mime_content_type_to_string (content_type));
+	}
+	else
+	{
+	    printf ("Non-text part: %s\n",
+		    g_mime_content_type_to_string (content_type));
+	}
     }
 }
 
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 02/11] Integrate reply_part_content function into reply_part function.
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 01/11] Simplify reply_part function to eliminate redundant code paths Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 03/11] Use empty strings instead of NULL in format_reply structure Jameson Graef Rollins
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

After the last patch to eliminate some redundant code paths in
reply_part, the reply_part_content function was only being called
once.  Disolving the function and integrating its contents into the
reply_part function makes things a little simpler, and frees up some
name space that will be needed in the next patch.
---
 notmuch-reply.c |   52 +++++++++++++++++++++++-----------------------------
 1 files changed, 23 insertions(+), 29 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 5d72b1f..8c5e76c 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -38,34 +38,6 @@ static const notmuch_show_format_t format_reply = {
 };
 
 static void
-reply_part_content (GMimeObject *part)
-{
-    GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
-    GMimeDataWrapper *wrapper;
-    const char *charset;
-
-    charset = g_mime_object_get_content_type_parameter (part, "charset");
-    stream_stdout = g_mime_stream_file_new (stdout);
-    if (stream_stdout) {
-	g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
-	stream_filter = g_mime_stream_filter_new(stream_stdout);
-        if (charset) {
-          g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
-                                   g_mime_filter_charset_new(charset, "UTF-8"));
-        }
-    }
-    g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
-			     g_mime_filter_reply_new(TRUE));
-    wrapper = g_mime_part_get_content_object (GMIME_PART (part));
-    if (wrapper && stream_filter)
-	g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
-    if (stream_filter)
-	g_object_unref(stream_filter);
-    if (stream_stdout)
-	g_object_unref(stream_stdout);
-}
-
-static void
 show_reply_headers (GMimeMessage *message)
 {
     GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
@@ -94,7 +66,29 @@ reply_part (GMimeObject *part,
     if (g_mime_content_type_is_type (content_type, "text", "*") &&
 	!g_mime_content_type_is_type (content_type, "text", "html"))
     {
-	reply_part_content (part);
+	GMimeStream *stream_stdout = NULL, *stream_filter = NULL;
+	GMimeDataWrapper *wrapper;
+	const char *charset;
+
+	charset = g_mime_object_get_content_type_parameter (part, "charset");
+	stream_stdout = g_mime_stream_file_new (stdout);
+	if (stream_stdout) {
+	    g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
+	    stream_filter = g_mime_stream_filter_new(stream_stdout);
+	    if (charset) {
+		g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
+					 g_mime_filter_charset_new(charset, "UTF-8"));
+	    }
+	}
+	g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
+				 g_mime_filter_reply_new(TRUE));
+	wrapper = g_mime_part_get_content_object (GMIME_PART (part));
+	if (wrapper && stream_filter)
+	    g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
+	if (stream_filter)
+	    g_object_unref(stream_filter);
+	if (stream_stdout)
+	    g_object_unref(stream_stdout);
     }
     else
     {
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 03/11] Use empty strings instead of NULL in format_reply structure.
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 01/11] Simplify reply_part function to eliminate redundant code paths Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 02/11] Integrate reply_part_content function into reply_part function Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 04/11] Break up format->part function into part_start and part_content functions Jameson Graef Rollins
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

This keeps things consistent with notmuch-show, and prevents having to
check for the existence of the field pointer for simple string output
formats.
---
 notmuch-reply.c |   12 ++++++------
 show-message.c  |    2 +-
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/notmuch-reply.c b/notmuch-reply.c
index 8c5e76c..7959935 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -29,12 +29,12 @@ reply_part (GMimeObject *part,
 	    unused (int *part_count));
 
 static const notmuch_show_format_t format_reply = {
-    NULL,
-	NULL, NULL,
-	    NULL, NULL, NULL,
-	    NULL, reply_part, NULL, NULL, NULL,
-	NULL, NULL,
-    NULL
+    "",
+	"", NULL,
+	    "", NULL, "",
+	    "", reply_part, NULL, "", "",
+	"", "",
+    ""
 };
 
 static void
diff --git a/show-message.c b/show-message.c
index 2ec9eca..32bb860 100644
--- a/show-message.c
+++ b/show-message.c
@@ -46,7 +46,7 @@ show_message_part (GMimeObject *part,
     selected = (params->part <= 0 || state->part_count == params->part);
 
     if (selected || state->in_zone) {
-	if (!first && (params->part <= 0 || state->in_zone) && format->part_sep)
+	if (!first && (params->part <= 0 || state->in_zone))
 	    fputs (format->part_sep, stdout);
 
 	format->part (part, &(state->part_count));
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 04/11] Break up format->part function into part_start and part_content functions.
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (2 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 03/11] Use empty strings instead of NULL in format_reply structure Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 05/11] test: new test-lib function to test for equality between files Jameson Graef Rollins
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

Future improvements (eg. crypto support) will require adding new part
header.  By breaking up the output of part headers from the output of
part content, we can easily out new part headers with new formatting
functions.
---
 notmuch-client.h |    5 +-
 notmuch-reply.c  |   13 ++++--
 notmuch-show.c   |  122 +++++++++++++++++++++++++++++++----------------------
 show-message.c   |    4 +-
 4 files changed, 85 insertions(+), 59 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index 7221c68..b278bc7 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -65,8 +65,9 @@ typedef struct notmuch_show_format {
 		    notmuch_message_t *message);
     const char *header_end;
     const char *body_start;
-    void (*part) (GMimeObject *part,
-		  int *part_count);
+    void (*part_start) (GMimeObject *part,
+			int *part_count);
+    void (*part_content) (GMimeObject *part);
     void (*part_end) (GMimeObject *part);
     const char *part_sep;
     const char *body_end;
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 7959935..9c35475 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -25,14 +25,18 @@
 #include "gmime-filter-headers.h"
 
 static void
-reply_part (GMimeObject *part,
-	    unused (int *part_count));
+reply_part_content (GMimeObject *part);
 
 static const notmuch_show_format_t format_reply = {
     "",
 	"", NULL,
 	    "", NULL, "",
-	    "", reply_part, NULL, "", "",
+	    "",
+	        NULL,
+	        reply_part_content,
+	        NULL,
+	        "",
+	    "",
 	"", "",
     ""
 };
@@ -57,8 +61,7 @@ show_reply_headers (GMimeMessage *message)
 }
 
 static void
-reply_part (GMimeObject *part,
-	    unused (int *part_count))
+reply_part_content (GMimeObject *part)
 {
     GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
     GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part);
diff --git a/notmuch-show.c b/notmuch-show.c
index 65c780e..363cdbf 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -29,8 +29,11 @@ format_headers_text (const void *ctx,
 		     notmuch_message_t *message);
 
 static void
-format_part_text (GMimeObject *part,
-		  int *part_count);
+format_part_start_text (GMimeObject *part,
+			int *part_count);
+
+static void
+format_part_content_text (GMimeObject *part);
 
 static void
 format_part_end_text (GMimeObject *part);
@@ -39,7 +42,12 @@ static const notmuch_show_format_t format_text = {
     "",
 	"\fmessage{ ", format_message_text,
 	    "\fheader{\n", format_headers_text, "\fheader}\n",
-	    "\fbody{\n", format_part_text, format_part_end_text, "", "\fbody}\n",
+	    "\fbody{\n",
+	        format_part_start_text,
+	        format_part_content_text,
+	        format_part_end_text,
+	        "",
+	    "\fbody}\n",
 	"\fmessage}\n", "",
     ""
 };
@@ -53,8 +61,11 @@ format_headers_json (const void *ctx,
 		     notmuch_message_t *message);
 
 static void
-format_part_json (GMimeObject *part,
-		  int *part_count);
+format_part_start_json (unused (GMimeObject *part),
+			int *part_count);
+
+static void
+format_part_content_json (GMimeObject *part);
 
 static void
 format_part_end_json (GMimeObject *part);
@@ -63,7 +74,12 @@ static const notmuch_show_format_t format_json = {
     "[",
 	"{", format_message_json,
 	    ", \"headers\": {", format_headers_json, "}",
-	    ", \"body\": [", format_part_json, format_part_end_json, ", ", "]",
+	    ", \"body\": [",
+	        format_part_start_json,
+	        format_part_content_json,
+	        format_part_end_json,
+	        ", ",
+	    "]",
 	"}", ", ",
     "]"
 };
@@ -77,20 +93,29 @@ static const notmuch_show_format_t format_mbox = {
     "",
         "", format_message_mbox,
             "", NULL, "",
-            "", NULL, NULL, "", "",
+            "",
+                NULL,
+                NULL,
+                NULL,
+                "",
+            "",
         "", "",
     ""
 };
 
 static void
-format_part_raw (GMimeObject *part,
-		 unused (int *part_count));
+format_part_content_raw (GMimeObject *part);
 
 static const notmuch_show_format_t format_raw = {
     "",
 	"", NULL,
 	    "", NULL, "",
-            "", format_part_raw, NULL, "", "",
+            "",
+                NULL,
+                format_part_content_raw,
+                NULL,
+                "",
+            "",
 	"", "",
     ""
 };
@@ -372,46 +397,41 @@ show_part_content (GMimeObject *part, GMimeStream *stream_out)
 }
 
 static void
-format_part_text (GMimeObject *part, int *part_count)
+format_part_start_text (GMimeObject *part, int *part_count)
 {
-    GMimeContentDisposition *disposition;
-    GMimeContentType *content_type;
+    GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part);
 
-    disposition = g_mime_object_get_content_disposition (part);
     if (disposition &&
 	strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
     {
-	const char *filename = g_mime_part_get_filename (GMIME_PART (part));
-	content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
-
-	printf ("\fattachment{ ID: %d, Content-type: %s\n",
-		*part_count,
-		g_mime_content_type_to_string (content_type));
-	printf ("Attachment: %s (%s)\n", filename,
-		g_mime_content_type_to_string (content_type));
+	printf ("\fattachment{ ID: %d", *part_count);
 
-	if (g_mime_content_type_is_type (content_type, "text", "*") &&
-	    !g_mime_content_type_is_type (content_type, "text", "html"))
-	{
-	    GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
-	    g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
-	    show_part_content (part, stream_stdout);
-	    g_object_unref(stream_stdout);
-	}
+    } else {
 
-	return;
+	printf ("\fpart{ ID: %d", *part_count);
     }
+}
 
-    content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
+static void
+format_part_content_text (GMimeObject *part)
+{
+    GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part);
+    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
+    GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
+
+    printf (", Content-type: %s\n", g_mime_content_type_to_string (content_type));
 
-    printf ("\fpart{ ID: %d, Content-type: %s\n",
-	    *part_count,
-	    g_mime_content_type_to_string (content_type));
+    if (disposition &&
+	strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
+    {
+	const char *filename = g_mime_part_get_filename (GMIME_PART (part));
+	printf ("Attachment: %s (%s)\n", filename,
+		g_mime_content_type_to_string (content_type));
+    }
 
     if (g_mime_content_type_is_type (content_type, "text", "*") &&
 	!g_mime_content_type_is_type (content_type, "text", "html"))
     {
-	GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
 	g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
 	show_part_content (part, stream_stdout);
 	g_object_unref(stream_stdout);
@@ -447,27 +467,27 @@ format_part_end_text (GMimeObject *part)
 }
 
 static void
-format_part_json (GMimeObject *part, int *part_count)
+format_part_start_json (unused (GMimeObject *part), int *part_count)
 {
-    GMimeContentType *content_type;
-    GMimeContentDisposition *disposition;
-    void *ctx = talloc_new (NULL);
+    printf ("{\"id\": %d", *part_count);
+}
+
+static void
+format_part_content_json (GMimeObject *part)
+{
+    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
     GMimeStream *stream_memory = g_mime_stream_mem_new ();
+    const char *cid = g_mime_object_get_content_id (part);
+    void *ctx = talloc_new (NULL);
+    GMimeContentDisposition *disposition = g_mime_object_get_content_disposition (part);
     GByteArray *part_content;
-    const char *cid;
 
-    content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
-
-    printf ("{\"id\": %d, \"content-type\": %s",
-	    *part_count,
+    printf (", \"content-type\": %s",
 	    json_quote_str (ctx, g_mime_content_type_to_string (content_type)));
 
-    cid = g_mime_object_get_content_id (part);
     if (cid != NULL)
-	    printf(", \"content-id\": %s",
-		   json_quote_str (ctx, cid));
+	    printf(", \"content-id\": %s", json_quote_str (ctx, cid));
 
-    disposition = g_mime_object_get_content_disposition (part);
     if (disposition &&
 	strcmp (disposition->disposition, GMIME_DISPOSITION_ATTACHMENT) == 0)
     {
@@ -510,7 +530,7 @@ format_part_end_json (GMimeObject *part)
 }
 
 static void
-format_part_raw (GMimeObject *part, unused (int *part_count))
+format_part_content_raw (GMimeObject *part)
 {
     GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
     g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
@@ -538,7 +558,7 @@ show_message (void *ctx,
 	fputs (format->body_start, stdout);
     }
 
-    if (format->part)
+    if (format->part_content)
 	show_message_body (notmuch_message_get_filename (message),
 			   format, params);
 
diff --git a/show-message.c b/show-message.c
index 32bb860..fbae530 100644
--- a/show-message.c
+++ b/show-message.c
@@ -49,7 +49,9 @@ show_message_part (GMimeObject *part,
 	if (!first && (params->part <= 0 || state->in_zone))
 	    fputs (format->part_sep, stdout);
 
-	format->part (part, &(state->part_count));
+	if (format->part_start)
+	    format->part_start (part, &(state->part_count));
+	format->part_content (part);
     }
 
     if (GMIME_IS_MULTIPART (part)) {
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 05/11] test: new test-lib function to test for equality between files
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (3 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 04/11] Break up format->part function into part_start and part_content functions Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 06/11] test: add notmuch_show_sanitize_all function that is a little more aggressive Jameson Graef Rollins
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

We need to be able to test for the presence of a newline at the end of
output.  There's no good way to capture trailing newlines in bash, so
redirecting output to a file is the next best thing.  This new
function should be used when testing for output that is expected to
have trailing newlines.

The next commit will demonstrate the use of this.
---
 test/test-lib.sh |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/test/test-lib.sh b/test/test-lib.sh
index f536172..9e2e0b5 100755
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -441,6 +441,29 @@ test_expect_equal ()
     fi
 }
 
+test_expect_equal_file ()
+{
+	exec 1>&6 2>&7		# Restore stdout and stderr
+	inside_subtest=
+	test "$#" = 3 && { prereq=$1; shift; } || prereq=
+	test "$#" = 2 ||
+	error "bug in the test script: not 2 or 3 parameters to test_expect_equal"
+
+	output="$1"
+	expected="$2"
+	if ! test_skip "$@"
+	then
+		if diff -q "$expected" "$output" >/dev/null ; then
+			test_ok_ "$test_subtest_name"
+		else
+			testname=$this_test.$test_count
+			mv "$output" $testname.output
+			mv "$expected" $testname.expected
+			test_failure_ "$test_subtest_name" "$(diff -u $testname.expected $testname.output)"
+		fi
+    fi
+}
+
 test_expect_equal_failure ()
 {
 	exec 1>&6 2>&7		# Restore stdout and stderr
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 06/11] test: add notmuch_show_sanitize_all function that is a little more aggressive.
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (4 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 05/11] test: new test-lib function to test for equality between files Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 07/11] test: add crypto tests for signature verification and decryption Jameson Graef Rollins
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

The old notmuch_show_sanitize function only scrubed part of the
filename.  This one scrubs the full filename, as well as the message
id.
---
 test/test-lib.sh |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/test/test-lib.sh b/test/test-lib.sh
index 9e2e0b5..ae25635 100755
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -502,6 +502,12 @@ notmuch_show_sanitize ()
 {
     sed -e "$NOTMUCH_SHOW_FILENAME_SQUELCH"
 }
+notmuch_show_sanitize_all ()
+{
+    sed \
+	-e 's| filename:.*| filename:XXXXX|' \
+	-e 's| id:[^ ]* | id:XXXXX |'
+}
 
 # End of notmuch helper functions
 
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 07/11] test: add crypto tests for signature verification and decryption
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (5 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 06/11] test: add notmuch_show_sanitize_all function that is a little more aggressive Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 08/11] Add signature verification of PGP/MIME-signed parts with --verify Jameson Graef Rollins
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

This adds a new "crypto" test script to the test suite to test
PGP/MIME signature verification and message decryption.  Included here
is a test GNUPGHOME with a test secret key (passwordless), and test
for:

  * signing/verification
  * signing/verification with full owner trust
  * verification with signer key unavailable
  * encryption/decryption
  * decryption failure with missing key
  * encryption/decryption + signing/verfifying
  * reply to encrypted message
  * verification of signature from revoked key

These tests are not expected to pass now, but will as crypto
functionality is included.
---
 test/basic                 |    5 +-
 test/crypto                |  330 ++++++++++++++++++++++++++++++++++++++++++++
 test/gnupg-secret-key.NOTE |    9 ++
 test/gnupg-secret-key.asc  |   34 +++++
 test/notmuch-test          |    1 +
 test/test-lib.sh           |   29 ++++
 6 files changed, 407 insertions(+), 1 deletions(-)
 create mode 100755 test/crypto
 create mode 100644 test/gnupg-secret-key.NOTE
 create mode 100644 test/gnupg-secret-key.asc

diff --git a/test/basic b/test/basic
index 3b43ad9..d6c0d00 100755
--- a/test/basic
+++ b/test/basic
@@ -57,7 +57,10 @@ available=$(ls -1 ../ | \
     sed -r -e "/^(aggregate-results.sh|Makefile|Makefile.local|notmuch-test)/d" \
 	   -e "/^(README|test-lib.sh|test-results|tmp.*|valgrind|corpus*)/d" \
 	   -e "/^(emacs.expected-output|smtp-dummy|smtp-dummy.c|test-verbose)/d" \
-	   -e "/^(test.expected-output|.*~)/d" | sort)
+	   -e "/^(test.expected-output|.*~)/d" \
+	   -e "/^(gnupg-secret-key.asc)/d" \
+	   -e "/^(gnupg-secret-key.NOTE)/d" \
+	   | sort)
 test_expect_equal "$tests_in_suite" "$available"
 
 EXPECTED=../test.expected-output
diff --git a/test/crypto b/test/crypto
new file mode 100755
index 0000000..3b0f381
--- /dev/null
+++ b/test/crypto
@@ -0,0 +1,330 @@
+#!/bin/bash
+
+# TODO:
+# - decryption/verification with signer key not available
+# - verification of signatures from expired/revoked keys
+
+test_description='PGP/MIME signature verification and decryption'
+. ./test-lib.sh
+
+add_gnupg_home ()
+{
+    local output
+    [ -d ${GNUPGHOME} ] && return
+    mkdir -m 0700 "$GNUPGHOME"
+    gpg --no-tty --import <../gnupg-secret-key.asc >"$GNUPGHOME"/import.log 2>&1
+    test_debug "cat $GNUPGHOME/import.log"
+    if (gpg --quick-random --version >/dev/null 2>&1) ; then
+	echo quick-random >> "$GNUPGHOME"/gpg.conf
+    elif (gpg --debug-quick-random --version >/dev/null 2>&1) ; then
+	echo debug-quick-random >> "$GNUPGHOME"/gpg.conf
+    fi
+}
+
+##################################################
+
+add_gnupg_home
+# get key fingerprint
+FINGERPRINT=$(gpg --no-tty --list-secret-keys --with-colons --fingerprint | grep '^fpr:' | cut -d: -f10)
+
+# for some reason this is needed for emacs_deliver_message to work,
+# although I can't figure out why
+add_email_corpus
+
+test_expect_success 'emacs delivery of signed message' \
+'emacs_deliver_message \
+    "test signed message 001" \
+    "This is a test signed message." \
+    "(mml-secure-message-sign)"'
+
+test_begin_subtest "signature verification"
+output=$(notmuch show --format=json --verify subject:"test signed message 001" \
+    | notmuch_json_show_sanitize \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -0000"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "good",
+ "fingerprint": "'$FINGERPRINT'",
+ "created": 946728000}],
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"}]},
+ []]]]'
+test_expect_equal \
+    "$output" \
+    "$expected"
+
+test_begin_subtest "signature verification with full owner trust"
+# give the key full owner trust
+echo "${FINGERPRINT}:6:" | gpg --no-tty --import-ownertrust >>"$GNUPGHOME"/trust.log 2>&1
+gpg --no-tty --check-trustdb >>"$GNUPGHOME"/trust.log 2>&1
+output=$(notmuch show --format=json --verify subject:"test signed message 001" \
+    | notmuch_json_show_sanitize \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -0000"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "good",
+ "fingerprint": "'$FINGERPRINT'",
+ "created": 946728000,
+ "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"}]},
+ []]]]'
+test_expect_equal \
+    "$output" \
+    "$expected"
+
+test_begin_subtest "signature verification with signer key unavailable"
+# move the gnupghome temporarily out of the way
+mv "${GNUPGHOME}"{,.bak}
+output=$(notmuch show --format=json --verify subject:"test signed message 001" \
+    | notmuch_json_show_sanitize \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -0000"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "error",
+ "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
+ "errors": 2}],
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"}]},
+ []]]]'
+test_expect_equal \
+    "$output" \
+    "$expected"
+mv "${GNUPGHOME}"{.bak,}
+
+# create a test encrypted message with attachment
+cat <<EOF >TESTATTACHMENT
+This is a test file.
+EOF
+test_expect_success 'emacs delivery of encrypted message with attachment' \
+'emacs_deliver_message \
+    "test encrypted message 001" \
+    "This is a test encrypted message.\n" \
+    "(mml-attach-file \"TESTATTACHMENT\") (mml-secure-message-encrypt)"'
+
+test_begin_subtest "decryption, --format=text"
+output=$(notmuch show --format=text --decrypt subject:"test encrypted message 001" \
+    | notmuch_show_sanitize_all \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='\fmessage{ id:XXXXX depth:0 match:1 filename:XXXXX
+\fheader{
+Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (inbox)
+Subject: test encrypted message 001
+From: Notmuch Test Suite <test_suite@notmuchmail.org>
+To: test_suite@notmuchmail.org
+Date: 01 Jan 2000 12:00:00 -0000
+\fheader}
+\fbody{
+\fpart{ ID: 1, Content-type: multipart/mixed
+\fpart{ ID: 2, Content-type: text/plain
+This is a test encrypted message.
+\fpart}
+\fattachment{ ID: 3, Content-type: application/octet-stream
+Attachment: TESTATTACHMENT (application/octet-stream)
+Non-text part: application/octet-stream
+\fattachment}
+\fpart}
+\fbody}
+\fmessage}'
+test_expect_equal \
+    "$output" \
+    "$expected"
+
+test_begin_subtest "decryption, --format=json"
+output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \
+    | notmuch_json_show_sanitize \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test encrypted message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -0000"},
+ "body": [{"id": 1,
+ "encstatus": [{"status": "good"}],
+ "sigstatus": [],
+ "content-type": "multipart/mixed",
+ "content": [{"id": 2,
+ "content-type": "text/plain",
+ "content": "This is a test encrypted message.\n"},
+ {"id": 3,
+ "content-type": "application/octet-stream",
+ "filename": "TESTATTACHMENT"}]}]},
+ []]]]'
+test_expect_equal \
+    "$output" \
+    "$expected"
+
+test_begin_subtest "decryption, --format=json, --part=2"
+output=$(notmuch show --format=json --part=2 --decrypt subject:"test encrypted message 001" \
+    | notmuch_json_show_sanitize \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='{"id": 2,
+ "content-type": "text/plain",
+ "content": "This is a test encrypted message.\n"}'
+test_expect_equal \
+    "$output" \
+    "$expected"
+
+test_begin_subtest "decrypt attachment (--part=3 --format=raw)"
+notmuch show \
+    --format=raw \
+    --part=3 \
+    --decrypt \
+    subject:"test encrypted message 001" >OUTPUT
+test_expect_equal_file OUTPUT TESTATTACHMENT
+
+test_begin_subtest "decryption failure with missing key"
+mv "${GNUPGHOME}"{,.bak}
+output=$(notmuch show --format=json --decrypt subject:"test encrypted message 001" \
+    | notmuch_json_show_sanitize \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test encrypted message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -0000"},
+ "body": [{"id": 1,
+ "encstatus": [{"status": "bad"}],
+ "content-type": "multipart/encrypted",
+ "content": [{"id": 2,
+ "content-type": "application/pgp-encrypted"},
+ {"id": 3,
+ "content-type": "application/octet-stream"}]}]},
+ []]]]'
+test_expect_equal \
+    "$output" \
+    "$expected"
+mv "${GNUPGHOME}"{.bak,}
+
+test_expect_success 'emacs delivery of encrypted + signed message' \
+'emacs_deliver_message \
+    "test encrypted message 002" \
+    "This is another test encrypted message.\n" \
+    "(mml-secure-message-sign-encrypt)"'
+
+test_begin_subtest "decryption + signature verification"
+output=$(notmuch show --format=json --decrypt subject:"test encrypted message 002" \
+    | notmuch_json_show_sanitize \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test encrypted message 002",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -0000"},
+ "body": [{"id": 1,
+ "encstatus": [{"status": "good"}],
+ "sigstatus": [{"status": "good",
+ "fingerprint": "'$FINGERPRINT'",
+ "created": 946728000,
+ "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
+ "content-type": "text/plain",
+ "content": "This is another test encrypted message.\n"}]},
+ []]]]'
+test_expect_equal \
+    "$output" \
+    "$expected"
+
+test_begin_subtest "reply to encrypted message"
+output=$(notmuch reply --decrypt subject:"test encrypted message 002" \
+    | grep -v -e '^In-Reply-To:' -e '^References:')
+expected='From: Notmuch Test Suite <test_suite@notmuchmail.org>
+Subject: Re: test encrypted message 002
+
+On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+> This is another test encrypted message.'
+test_expect_equal \
+    "$output" \
+    "$expected"
+
+test_begin_subtest "signature verification with revoked key"
+# generate revokation certificate and load it to revoke key
+echo "y
+1
+Notmuch Test Suite key revocation (automated) $(date '+%F_%T%z')
+
+y
+
+" \
+    | gpg --no-tty --quiet --command-fd 0 --armor --gen-revoke "0x${FINGERPRINT}!" 2>/dev/null \
+    | gpg --no-tty --quiet --import
+output=$(notmuch show --format=json --verify subject:"test signed message 001" \
+    | notmuch_json_show_sanitize \
+    | sed -e 's|"created": [1234567890]*|"created": 946728000|')
+expected='[[[{"id": "XXXXX",
+ "match": true,
+ "filename": "YYYYY",
+ "timestamp": 946728000,
+ "date_relative": "2000-01-01",
+ "tags": ["inbox"],
+ "headers": {"Subject": "test signed message 001",
+ "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
+ "To": "test_suite@notmuchmail.org",
+ "Cc": "",
+ "Bcc": "",
+ "Date": "01 Jan 2000 12:00:00 -0000"},
+ "body": [{"id": 1,
+ "sigstatus": [{"status": "error",
+ "keyid": "6D92612D94E46381",
+ "errors": 8}],
+ "content-type": "text/plain",
+ "content": "This is a test signed message.\n"}]},
+ []]]]'
+test_expect_equal \
+    "$output" \
+    "$expected"
+
+test_done
diff --git a/test/gnupg-secret-key.NOTE b/test/gnupg-secret-key.NOTE
new file mode 100644
index 0000000..604496c
--- /dev/null
+++ b/test/gnupg-secret-key.NOTE
@@ -0,0 +1,9 @@
+How the crypto test gnupg secret was generated:
+
+GNUPGHOME=gnupghome gpg --quick-random --gen-key
+kind: 1 (RSA/RSA)
+size: 1024
+expire: 0
+name: Notmuch Test Suite
+email: test_suite@notmuchmail.org
+(no passphrase)
diff --git a/test/gnupg-secret-key.asc b/test/gnupg-secret-key.asc
new file mode 100644
index 0000000..6431b56
--- /dev/null
+++ b/test/gnupg-secret-key.asc
@@ -0,0 +1,34 @@
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.10 (GNU/Linux)
+
+lQHYBE1Mm18BBADlMsMlUeO6usp/XuulgimqlCSphHcYZvH6+Sy7u7W4TpJzid7e
+jEOCrk3UZi2XMPW9+snDMhV9e28HeRz61zAO9G/gedn4N+mKOyTaELEmj9SP2IG2
+ZTvdUvn30vWIHyfRIww3qEiSzNULKn6zTDfcg6BIY6ZDQ6GFSfH5EioxuQARAQAB
+AAP8CM2/sS9JZWLHZHJrmsU6fygxlaarlxmyhxwLG9WZ+qUJ+xDQqWZkhssrMigP
+7ZQehwLwZ7mvbvfOy/qwTPJMZjQMMuTGEzclwBTOTttSxEDS+kgYmZ05CBjIgXbo
+8+k+L347l+kVRBFsi1cqOkCr+VZQwhOnbeNb8uJsUx27aAECAPD7jsBP73LRgoXQ
+x650D2fzjjuomGVsIxSAPjkDRYmtorsRftaEy7DkvX3Ihu5WN6YRRjJavoL+f8ar
+4escR40CAPN7NOFOGmiFZYzQcfJYQI2m7YDk4B51JxORFvLrvGT+LJnVwhtFsdGS
+QnMyO4eNpKH0qeEkT5Zqha2oyAc0Yd0B/3f962YCmYlbDAvWjcbMvhV7G4DbazVp
+2TNR0BhhEMiOlHuwmTO59s2iukuE5ifaVbwrj+NgpipTsaffKnhALlGjV7Q7Tm90
+bXVjaCBUZXN0IFN1aXRlIDx0ZXN0X3N1aXRlQG5vdG11Y2htYWlsLm9yZz4gKElO
+U0VDVVJFISmIuAQTAQIAIgUCTUybXwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgEC
+F4AACgkQbZJhLZTkY4GJFAP9E0mOw+RUGdmqbxSbd2rm0/inUSYOC0Pvt/D05pUY
+xzXDAMZwsy1DWhfS7bSgdD3YTM/22b/LJ2FmbLUF1cU6cNslmdPdfHDZ5+C4qpa1
+uW11y7djlBFAwxc3NBypT6Bmh/iIixrx413cw8CEU0lSZbSXUvbxZ7Rg4JYm2K6f
+Y7SdAdgETUybXwEEAM74QJJWzPavquSF0IkKDFjEvI44WC1HGNsJF3JVuKv9G00P
+RaHavNNcHEG8MorbfaWk7pipaEJ3+zbPKgp2vRCSJnLL6z813JIQqXJTZzu1ip63
+s4icfOfXkxFJ5AaFd/pVdi+wjmEwvv+YMtJT9DyXANo6b2eQu+0bMtP4Xuv/ABEB
+AAEAA/wJArUJw450070K6eoXeg22wT0iq/O0aCExSzoI5Kmywytj6KnnAmp9TftL
+WVgrkQntVjrhzPsYoB40JEMrGKd7QL/6LPTNWq3eFW38PSpCiG83T0rtmKCKqHB1
+Uo0B78AHfYYX7MUOEuCq2AhKTAdZukesoCpmVxcEFtjDEbOB8QIA3cvXrPJN/J2S
+W61mdMT7KlaXZZD8Phs/TY2ZLAiMKUAP1dVYNDvRSDjZLvQrqKQjEAN5jM81cWAV
+pvOIavLhOwIA7uMVIiaQ3vIy10C7ltiLT6YuJL/O6XDnXY/PDuXOatQahd/gmI0q
+dGQLSaHIxYILPZPaW6t0orx+dduQ0ES0DQIA21nEKX0MZpYOY1eIt6OlKemsjL2a
+UTdFhq/OgwVv+QRVHNdYQXmKpKDeW30lN/+BI3zyDTZjtehwKMMxNTu4AJu/iJ8E
+GAECAAkFAk1Mm18CGwwACgkQbZJhLZTkY4H8kgQA4vHsTt8dlJdWJAu2SKZGOPRs
+bIPu5XtRXe3RYbW5H7PqbAnrKIzlIKpkPNTwLL4wVXaF+R/aHa8ZKX3paohrPL74
+qpbffwtHXyVEwyWlw3m9mgti0de1dy1YvVasCe/UQ8Frc6uNmOwtlQE20k4R4cLI
+SWXT1JrwPoKh9xe++90=
+=rvTR
+-----END PGP PRIVATE KEY BLOCK-----
diff --git a/test/notmuch-test b/test/notmuch-test
index 0ea4f4f..37db920 100755
--- a/test/notmuch-test
+++ b/test/notmuch-test
@@ -39,6 +39,7 @@ TESTS="
   emacs
   emacs-large-search-buffer
   maildir-sync
+  crypto
 "
 TESTS=${NOTMUCH_TESTS:=$TESTS}
 
diff --git a/test/test-lib.sh b/test/test-lib.sh
index ae25635..428ac7b 100755
--- a/test/test-lib.sh
+++ b/test/test-lib.sh
@@ -379,6 +379,26 @@ add_message ()
     notmuch new > /dev/null
 }
 
+# Deliver a message with emacs and add it to the database
+#
+# Uses emacs to generate and deliver a message to the mail store.
+# Accepts arbitrary extra emacs/elisp functions to modify the message
+# before sending, which is useful to doing things like attaching files
+# to the message and encrypting/signing.
+emacs_deliver_message ()
+{
+    local subject="$1"
+    local body="$2"
+    shift 2
+    # before we can send a message, we have to prepare the FCC maildir
+    mkdir -p "$MAIL_DIR"/sent/{cur,new,tmp}
+    ../smtp-dummy sent_message &
+    smtp_dummy_pid=$!
+    test_emacs "(setq message-send-mail-function 'message-smtpmail-send-it) (setq smtpmail-smtp-server \"localhost\") (setq smtpmail-smtp-service \"25025\") (notmuch-hello) (notmuch-mua-mail) (message-goto-to) (insert \"test_suite@notmuchmail.org\nDate: 01 Jan 2000 12:00:00 -0000\") (message-goto-subject) (insert \"${subject}\") (message-goto-body) (insert \"${body}\") $@ (message-send-and-exit)" >/dev/null 2>&1
+    wait ${smtp_dummy_pid}
+    notmuch new >/dev/null
+}
+
 # Generate a corpus of email and add it to the database.
 #
 # This corpus is fixed, (it happens to be 50 messages from early in
@@ -509,6 +529,14 @@ notmuch_show_sanitize_all ()
 	-e 's| id:[^ ]* | id:XXXXX |'
 }
 
+notmuch_json_show_sanitize ()
+{
+    sed -e 's|, |,\n |g' | \
+	sed \
+	-e 's|"id": "[^"]*",|"id": "XXXXX",|' \
+	-e 's|"filename": "[^"]*",|"filename": "YYYYY",|'
+}
+
 # End of notmuch helper functions
 
 # Use test_set_prereq to tell that a particular prerequisite is available.
@@ -945,6 +973,7 @@ rm -fr "$test" || {
 }
 
 MAIL_DIR="${TMP_DIRECTORY}/mail"
+export GNUPGHOME="${TMP_DIRECTORY}/gnupg"
 export NOTMUCH_CONFIG="${TMP_DIRECTORY}/notmuch-config"
 
 mkdir -p "${test}"
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 08/11] Add signature verification of PGP/MIME-signed parts with --verify.
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (6 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 07/11] test: add crypto tests for signature verification and decryption Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 09/11] Add decryption of PGP/MIME-encrypted parts with --decrypt Jameson Graef Rollins
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

This is primarily for notmuch-show, although the functionality is
added to show-message.  Once signatures are processed a new
part_sigstatus formatter is emitted, and the entire multipart/signed
part is replaced with the contents of the signed part.

At the moment only a json part_sigstatus formatting function is
available.  Emacs support to follow.

The original work for this patch was done by

  Daniel Kahn Gillmor <dkg@fifthhorseman.net>

whose help with this functionality I greatly appreciate.
---
 Makefile.local          |    1 +
 notmuch-client.h        |    5 ++
 notmuch-gmime-session.c |   49 ++++++++++++++++++++++++
 notmuch-reply.c         |    2 +
 notmuch-show.c          |   96 +++++++++++++++++++++++++++++++++++++++++++++++
 notmuch.1               |   11 +++++
 notmuch.c               |    8 ++++
 show-message.c          |   41 +++++++++++++++++++-
 8 files changed, 212 insertions(+), 1 deletions(-)
 create mode 100644 notmuch-gmime-session.c

diff --git a/Makefile.local b/Makefile.local
index 8a8832d..f726f1f 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -246,6 +246,7 @@ notmuch_client_srcs =		\
 	notmuch-show.c		\
 	notmuch-tag.c		\
 	notmuch-time.c		\
+	notmuch-gmime-session.c \
 	query-string.c		\
 	show-message.c		\
 	json.c			\
diff --git a/notmuch-client.h b/notmuch-client.h
index b278bc7..dc4ed7a 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -67,6 +67,7 @@ typedef struct notmuch_show_format {
     const char *body_start;
     void (*part_start) (GMimeObject *part,
 			int *part_count);
+    void (*part_sigstatus) (const GMimeSignatureValidity* validity);
     void (*part_content) (GMimeObject *part);
     void (*part_end) (GMimeObject *part);
     const char *part_sep;
@@ -80,6 +81,7 @@ typedef struct notmuch_show_params {
     int entire_thread;
     int raw;
     int part;
+    GMimeCipherContext* cryptoctx;
 } notmuch_show_params_t;
 
 /* There's no point in continuing when we've detected that we've done
@@ -233,4 +235,7 @@ notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
 notmuch_bool_t
 debugger_is_active (void);
 
+GType
+notmuch_gmime_session_get_type (void);
+
 #endif
diff --git a/notmuch-gmime-session.c b/notmuch-gmime-session.c
new file mode 100644
index 0000000..d83d9b3
--- /dev/null
+++ b/notmuch-gmime-session.c
@@ -0,0 +1,49 @@
+#include "notmuch-client.h"
+
+/* CRUFTY BOILERPLATE for GMimeSession (dkg thinks this will go away once GMime 2.6 comes out) */
+typedef struct _NotmuchGmimeSession NotmuchGmimeSession;
+typedef struct _NotmuchGmimeSessionClass NotmuchGmimeSessionClass;
+
+struct _NotmuchGmimeSession {
+    GMimeSession parent_object;
+};
+
+struct _NotmuchGmimeSessionClass {
+    GMimeSessionClass parent_class;
+};
+
+static void notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass);
+
+static GMimeSessionClass *parent_class = NULL;
+
+GType
+notmuch_gmime_session_get_type (void)
+{
+    static GType type = 0;
+
+    if (!type) {
+	static const GTypeInfo info = {
+	    sizeof (NotmuchGmimeSessionClass),
+	    NULL, /* base_class_init */
+	    NULL, /* base_class_finalize */
+	    (GClassInitFunc) notmuch_gmime_session_class_init,
+	    NULL, /* class_finalize */
+	    NULL, /* class_data */
+	    sizeof (NotmuchGmimeSession),
+	    0,    /* n_preallocs */
+	    NULL, /* object_init */
+	    NULL, /* value_table */
+	};
+	type = g_type_register_static (GMIME_TYPE_SESSION, "NotmuchGmimeSession", &info, 0);
+    }
+    return type;
+}
+
+static void
+notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass)
+{
+    GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
+    parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
+    session_class->request_passwd = NULL;
+}
+/* END CRUFTY BOILERPLATE */
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 9c35475..99bb15f 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -33,6 +33,7 @@ static const notmuch_show_format_t format_reply = {
 	    "", NULL, "",
 	    "",
 	        NULL,
+	        NULL,
 	        reply_part_content,
 	        NULL,
 	        "",
@@ -447,6 +448,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_
     const notmuch_show_format_t *format = &format_reply;
     notmuch_show_params_t params;
     params.part = -1;
+    params.cryptoctx = NULL;
 
     for (messages = notmuch_query_search_messages (query);
 	 notmuch_messages_valid (messages);
diff --git a/notmuch-show.c b/notmuch-show.c
index 363cdbf..bb54e56 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -44,6 +44,7 @@ static const notmuch_show_format_t format_text = {
 	    "\fheader{\n", format_headers_text, "\fheader}\n",
 	    "\fbody{\n",
 	        format_part_start_text,
+	        NULL,
 	        format_part_content_text,
 	        format_part_end_text,
 	        "",
@@ -65,6 +66,9 @@ format_part_start_json (unused (GMimeObject *part),
 			int *part_count);
 
 static void
+format_part_sigstatus_json (const GMimeSignatureValidity* validity);
+
+static void
 format_part_content_json (GMimeObject *part);
 
 static void
@@ -76,6 +80,7 @@ static const notmuch_show_format_t format_json = {
 	    ", \"headers\": {", format_headers_json, "}",
 	    ", \"body\": [",
 	        format_part_start_json,
+	        format_part_sigstatus_json,
 	        format_part_content_json,
 	        format_part_end_json,
 	        ", ",
@@ -97,6 +102,7 @@ static const notmuch_show_format_t format_mbox = {
                 NULL,
                 NULL,
                 NULL,
+                NULL,
                 "",
             "",
         "", "",
@@ -112,6 +118,7 @@ static const notmuch_show_format_t format_raw = {
 	    "", NULL, "",
             "",
                 NULL,
+                NULL,
                 format_part_content_raw,
                 NULL,
                 "",
@@ -396,6 +403,22 @@ show_part_content (GMimeObject *part, GMimeStream *stream_out)
 	g_object_unref(stream_filter);
 }
 
+static const char*
+signerstatustostring (GMimeSignerStatus x)
+{
+    switch (x) {
+    case GMIME_SIGNER_STATUS_NONE:
+	return "none";
+    case GMIME_SIGNER_STATUS_GOOD:
+	return "good";
+    case GMIME_SIGNER_STATUS_BAD:
+	return "bad";
+    case GMIME_SIGNER_STATUS_ERROR:
+	return "error";
+    }
+    return "unknown";
+}
+
 static void
 format_part_start_text (GMimeObject *part, int *part_count)
 {
@@ -473,6 +496,65 @@ format_part_start_json (unused (GMimeObject *part), int *part_count)
 }
 
 static void
+format_part_sigstatus_json (const GMimeSignatureValidity* validity)
+{
+    printf (", \"sigstatus\": [");
+
+    if (!validity) {
+	printf ("]");
+	return;
+    }
+
+    const GMimeSigner *signer = g_mime_signature_validity_get_signers (validity);
+    int first = 1;
+    void *ctx_quote = talloc_new (NULL);
+
+    while (signer) {
+	if (first)
+	    first = 0;
+	else
+	    printf (", ");
+
+	printf ("{");
+
+	/* status */
+	printf ("\"status\": %s", json_quote_str (ctx_quote, signerstatustostring(signer->status)));
+
+	if (signer->status == GMIME_SIGNER_STATUS_GOOD)
+	{
+	    if (signer->fingerprint)
+		printf (", \"fingerprint\": %s", json_quote_str (ctx_quote, signer->fingerprint));
+	    /* these dates are seconds since the epoch; should we
+	     * provide a more human-readable format string? */
+	    if (signer->created)
+		printf (", \"created\": %d", (int) signer->created);
+	    if (signer->expires)
+		printf (", \"expires\": %d", (int) signer->expires);
+	    /* output user id only if validity is FULL or ULTIMATE. */
+	    /* note that gmime is using the term "trust" here, which
+	     * is WRONG.  It's actually user id "validity". */
+	    if ((signer->name) && (signer->trust)) {
+		if ((signer->trust == GMIME_SIGNER_TRUST_FULLY) || (signer->trust == GMIME_SIGNER_TRUST_ULTIMATE))
+		    printf (", \"userid\": %s", json_quote_str (ctx_quote, signer->name));
+           }
+       } else {
+           if (signer->keyid)
+               printf (", \"keyid\": %s", json_quote_str (ctx_quote, signer->keyid));
+       }
+       if (signer->errors != GMIME_SIGNER_ERROR_NONE) {
+           printf (", \"errors\": %x", signer->errors);
+       }
+
+       printf ("}");
+       signer = signer->next;
+    }
+
+    printf ("]");
+
+    talloc_free (ctx_quote);
+}
+
+static void
 format_part_content_json (GMimeObject *part)
 {
     GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
@@ -739,6 +821,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
     params.entire_thread = 0;
     params.raw = 0;
     params.part = -1;
+    params.cryptoctx = NULL;
 
     for (i = 0; i < argc && argv[i][0] == '-'; i++) {
 	if (strcmp (argv[i], "--") == 0) {
@@ -767,6 +850,16 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
 	    params.part = atoi(argv[i] + sizeof ("--part=") - 1);
 	} else if (STRNCMP_LITERAL (argv[i], "--entire-thread") == 0) {
 	    params.entire_thread = 1;
+	} else if (STRNCMP_LITERAL (argv[i], "--verify") == 0) {
+	    if (params.cryptoctx == NULL) {
+		GMimeSession* session = g_object_new(notmuch_gmime_session_get_type(), NULL);
+		if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg")))
+		    fprintf (stderr, "Failed to construct gpg context.\n");
+		else
+		    g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE);
+		g_object_unref (session);
+		session = NULL;
+	    }
 	} else {
 	    fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
 	    return 1;
@@ -824,5 +917,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
     notmuch_query_destroy (query);
     notmuch_database_close (notmuch);
 
+    if (params.cryptoctx)
+	g_object_unref(params.cryptoctx);
+
     return 0;
 }
diff --git a/notmuch.1 b/notmuch.1
index a1c7fa8..daa9c6f 100644
--- a/notmuch.1
+++ b/notmuch.1
@@ -321,6 +321,17 @@ a depth-first walk of the message MIME structure, and are identified
 in the 'json' or 'text' output formats.
 .RE
 
+.RS 4
+.TP 4
+.B \-\-verify
+
+Compute and report the validity of any MIME cryptographic signatures
+found in the selected content (ie. "multipart/signed" parts). Status
+of the signature will be reported (currently only supported with
+--format=json), and the multipart/signed part will be replaced by the
+signed data.
+.RE
+
 A common use of
 .B notmuch show
 is to display a single thread of email messages. For this, use a
diff --git a/notmuch.c b/notmuch.c
index 262d677..cd3cb1b 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -294,6 +294,14 @@ static command_t commands[] = {
       "\t\tmessage MIME structure, and are identified in the 'json' or\n"
       "\t\t'text' output formats.\n"
       "\n"
+      "\t--verify\n"
+      "\n"
+      "\t\tCompute and report the validity of any MIME cryptographic\n"
+      "\t\tsignatures found in the selected content (ie.\n"
+      "\t\t\"multipart/signed\" parts). Status of the signature will be\n"
+      "\t\treported (currently only supported with --format=json) and\n"
+      "\t\tthe multipart/signed part will be replaced by the signed data.\n"
+      "\n"
       "\n"
       "\tA common use of \"notmuch show\" is to display a single\n"
       "\tthread of email messages. For this, use a search term of\n"
diff --git a/show-message.c b/show-message.c
index fbae530..c90f310 100644
--- a/show-message.c
+++ b/show-message.c
@@ -51,9 +51,48 @@ show_message_part (GMimeObject *part,
 
 	if (format->part_start)
 	    format->part_start (part, &(state->part_count));
-	format->part_content (part);
     }
 
+    /* handle PGP/MIME parts */
+    if (GMIME_IS_MULTIPART (part) && params->cryptoctx) {
+	GMimeMultipart *multipart = GMIME_MULTIPART (part);
+	GError* err = NULL;
+
+	if (GMIME_IS_MULTIPART_SIGNED (part))
+	{
+	    if ( g_mime_multipart_get_count (multipart) != 2 ) {
+		/* this violates RFC 3156 section 5, so we won't bother with it. */
+		fprintf (stderr,
+			 "Error: %d part(s) for a multipart/signed message (should be exactly 2)\n",
+			 g_mime_multipart_get_count (multipart));
+	    } else {
+		/* For some reason the GMimeSignatureValidity returned
+		 * here is not a const (inconsistent with that
+		 * returned by
+		 * g_mime_multipart_encrypted_get_signature_validity,
+		 * and therefore needs to be properly disposed of.
+		 * Hopefully the API will become more consistent. */
+		GMimeSignatureValidity *sigvalidity = g_mime_multipart_signed_verify (GMIME_MULTIPART_SIGNED (part), params->cryptoctx, &err);
+		if (!sigvalidity) {
+		    fprintf (stderr, "Failed to verify signed part: %s\n", (err ? err->message : "no error explanation given"));
+		}
+		if ((selected || state->in_zone) && format->part_sigstatus)
+		    format->part_sigstatus (sigvalidity);
+		/* extract only data part, and ignore signature part */
+		part = g_mime_multipart_get_part (multipart, 0);
+		if (sigvalidity)
+		    g_mime_signature_validity_free (sigvalidity);
+	    }
+	}
+
+	if (err)
+	    g_error_free (err);
+    }
+    /* end handle PGP/MIME parts */
+
+    if (selected || state->in_zone)
+	format->part_content (part);
+
     if (GMIME_IS_MULTIPART (part)) {
 	GMimeMultipart *multipart = GMIME_MULTIPART (part);
 	int i;
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 09/11] Add decryption of PGP/MIME-encrypted parts with --decrypt.
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (7 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 08/11] Add signature verification of PGP/MIME-signed parts with --verify Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 10/11] emacs: Add support for PGP/MIME verification/decryption Jameson Graef Rollins
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

This adds support for decrypting PGP/MIME-encrypted parts to
notmuch-show and notmuch-reply.  The --decrypt option implies
--verify.  Once decryption (and possibly signature verification) is
done, a new part_encstatus formatter is emitted, the part_sigstatus
formatter is emitted, and the entire multipart/encrypted part is
replaced by the contents of the encrypted part.

At the moment only a json part_encstatus formatting function is
available, even though decryption is done for all formats.  Emacs
support to follow.
---
 notmuch-client.h |    2 ++
 notmuch-reply.c  |   36 ++++++++++++++++++++++++++++--------
 notmuch-show.c   |   25 ++++++++++++++++++++++++-
 notmuch.1        |   11 +++++++++++
 notmuch.c        |    8 ++++++++
 show-message.c   |   29 ++++++++++++++++++++++++++++-
 6 files changed, 101 insertions(+), 10 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index dc4ed7a..8a27260 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -67,6 +67,7 @@ typedef struct notmuch_show_format {
     const char *body_start;
     void (*part_start) (GMimeObject *part,
 			int *part_count);
+    void (*part_encstatus) (int status);
     void (*part_sigstatus) (const GMimeSignatureValidity* validity);
     void (*part_content) (GMimeObject *part);
     void (*part_end) (GMimeObject *part);
@@ -82,6 +83,7 @@ typedef struct notmuch_show_params {
     int raw;
     int part;
     GMimeCipherContext* cryptoctx;
+    int decrypt;
 } notmuch_show_params_t;
 
 /* There's no point in continuing when we've detected that we've done
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 99bb15f..5265af6 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -34,6 +34,7 @@ static const notmuch_show_format_t format_reply = {
 	    "",
 	        NULL,
 	        NULL,
+	        NULL,
 	        reply_part_content,
 	        NULL,
 	        "",
@@ -438,7 +439,10 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message
 }
 
 static int
-notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_t *query)
+notmuch_reply_format_default(void *ctx,
+			     notmuch_config_t *config,
+			     notmuch_query_t *query,
+			     notmuch_show_params_t *params)
 {
     GMimeMessage *reply;
     notmuch_messages_t *messages;
@@ -446,9 +450,6 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_
     const char *subject, *from_addr = NULL;
     const char *in_reply_to, *orig_references, *references;
     const notmuch_show_format_t *format = &format_reply;
-    notmuch_show_params_t params;
-    params.part = -1;
-    params.cryptoctx = NULL;
 
     for (messages = notmuch_query_search_messages (query);
 	 notmuch_messages_valid (messages);
@@ -508,7 +509,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_
 		notmuch_message_get_header (message, "from"));
 
 	show_message_body (notmuch_message_get_filename (message),
-			   format, &params);
+			   format, params);
 
 	notmuch_message_destroy (message);
     }
@@ -517,7 +518,10 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_
 
 /* This format is currently tuned for a git send-email --notmuch hook */
 static int
-notmuch_reply_format_headers_only(void *ctx, notmuch_config_t *config, notmuch_query_t *query)
+notmuch_reply_format_headers_only(void *ctx,
+				  notmuch_config_t *config,
+				  notmuch_query_t *query,
+				  unused (notmuch_show_params_t *params))
 {
     GMimeMessage *reply;
     notmuch_messages_t *messages;
@@ -579,9 +583,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
     notmuch_query_t *query;
     char *opt, *query_string;
     int i, ret = 0;
-    int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query);
+    int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params);
+    notmuch_show_params_t params;
 
     reply_format_func = notmuch_reply_format_default;
+    params.part = -1;
+    params.cryptoctx = NULL;
 
     for (i = 0; i < argc && argv[i][0] == '-'; i++) {
 	if (strcmp (argv[i], "--") == 0) {
@@ -598,6 +605,16 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
 		fprintf (stderr, "Invalid value for --format: %s\n", opt);
 		return 1;
 	    }
+	} else if ((STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) {
+	    if (params.cryptoctx == NULL) {
+		GMimeSession* session = g_object_new(notmuch_gmime_session_get_type(), NULL);
+		if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg")))
+		    fprintf (stderr, "Failed to construct gpg context.\n");
+		else
+		    g_mime_gpg_context_set_always_trust((GMimeGpgContext*)params.cryptoctx, FALSE);
+		g_object_unref (session);
+		session = NULL;
+	    }
 	} else {
 	    fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
 	    return 1;
@@ -633,11 +650,14 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
 	return 1;
     }
 
-    if (reply_format_func (ctx, config, query) != 0)
+    if (reply_format_func (ctx, config, query, &params) != 0)
 	return 1;
 
     notmuch_query_destroy (query);
     notmuch_database_close (notmuch);
 
+    if (params.cryptoctx)
+	g_object_unref(params.cryptoctx);
+
     return ret;
 }
diff --git a/notmuch-show.c b/notmuch-show.c
index bb54e56..e90f07e 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -45,6 +45,7 @@ static const notmuch_show_format_t format_text = {
 	    "\fbody{\n",
 	        format_part_start_text,
 	        NULL,
+	        NULL,
 	        format_part_content_text,
 	        format_part_end_text,
 	        "",
@@ -66,6 +67,9 @@ format_part_start_json (unused (GMimeObject *part),
 			int *part_count);
 
 static void
+format_part_encstatus_json (int status);
+
+static void
 format_part_sigstatus_json (const GMimeSignatureValidity* validity);
 
 static void
@@ -80,6 +84,7 @@ static const notmuch_show_format_t format_json = {
 	    ", \"headers\": {", format_headers_json, "}",
 	    ", \"body\": [",
 	        format_part_start_json,
+	        format_part_encstatus_json,
 	        format_part_sigstatus_json,
 	        format_part_content_json,
 	        format_part_end_json,
@@ -103,6 +108,7 @@ static const notmuch_show_format_t format_mbox = {
                 NULL,
                 NULL,
                 NULL,
+                NULL,
                 "",
             "",
         "", "",
@@ -119,6 +125,7 @@ static const notmuch_show_format_t format_raw = {
             "",
                 NULL,
                 NULL,
+                NULL,
                 format_part_content_raw,
                 NULL,
                 "",
@@ -496,6 +503,18 @@ format_part_start_json (unused (GMimeObject *part), int *part_count)
 }
 
 static void
+format_part_encstatus_json (int status)
+{
+    printf (", \"encstatus\": [{\"status\": ");
+    if (status) {
+	printf ("\"good\"");
+    } else {
+	printf ("\"bad\"");
+    }
+    printf ("}]");
+}
+
+static void
 format_part_sigstatus_json (const GMimeSignatureValidity* validity)
 {
     printf (", \"sigstatus\": [");
@@ -822,6 +841,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
     params.raw = 0;
     params.part = -1;
     params.cryptoctx = NULL;
+    params.decrypt = 0;
 
     for (i = 0; i < argc && argv[i][0] == '-'; i++) {
 	if (strcmp (argv[i], "--") == 0) {
@@ -850,7 +870,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
 	    params.part = atoi(argv[i] + sizeof ("--part=") - 1);
 	} else if (STRNCMP_LITERAL (argv[i], "--entire-thread") == 0) {
 	    params.entire_thread = 1;
-	} else if (STRNCMP_LITERAL (argv[i], "--verify") == 0) {
+	} else if ((STRNCMP_LITERAL (argv[i], "--verify") == 0) ||
+		   (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) {
 	    if (params.cryptoctx == NULL) {
 		GMimeSession* session = g_object_new(notmuch_gmime_session_get_type(), NULL);
 		if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg")))
@@ -860,6 +881,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
 		g_object_unref (session);
 		session = NULL;
 	    }
+	    if (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)
+		params.decrypt = 1;
 	} else {
 	    fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
 	    return 1;
diff --git a/notmuch.1 b/notmuch.1
index daa9c6f..c1aa4e3 100644
--- a/notmuch.1
+++ b/notmuch.1
@@ -332,6 +332,17 @@ of the signature will be reported (currently only supported with
 signed data.
 .RE
 
+.RS 4
+.TP 4
+.B \-\-decrypt
+
+Decrypt any MIME encrypted parts found in the selected content
+(ie. "multipart/encrypted" parts). Status of the decryption will be
+reported (currently only supported with --format=json) and the
+multipart/encrypted part will be replaced by the decrypted
+content.
+.RE
+
 A common use of
 .B notmuch show
 is to display a single thread of email messages. For this, use a
diff --git a/notmuch.c b/notmuch.c
index cd3cb1b..93f3194 100644
--- a/notmuch.c
+++ b/notmuch.c
@@ -302,6 +302,14 @@ static command_t commands[] = {
       "\t\treported (currently only supported with --format=json) and\n"
       "\t\tthe multipart/signed part will be replaced by the signed data.\n"
       "\n"
+      "\t--decrypt\n"
+      "\n"
+      "\t\tDecrypt any MIME encrypted parts found in the selected content\n"
+      "\t\t(ie. \"multipart/encrypted\" parts). Status of the decryption\n"
+      "\t\twill be reported (currently only supported with --format=json)\n"
+      "\t\tand the multipart/encrypted part will be replaced by the\n"
+      "\t\tdecrypted content.\n"
+      "\n"
       "\n"
       "\tA common use of \"notmuch show\" is to display a single\n"
       "\tthread of email messages. For this, use a search term of\n"
diff --git a/show-message.c b/show-message.c
index c90f310..37252b2 100644
--- a/show-message.c
+++ b/show-message.c
@@ -58,7 +58,34 @@ show_message_part (GMimeObject *part,
 	GMimeMultipart *multipart = GMIME_MULTIPART (part);
 	GError* err = NULL;
 
-	if (GMIME_IS_MULTIPART_SIGNED (part))
+	if (GMIME_IS_MULTIPART_ENCRYPTED (part) && params->decrypt)
+	{
+	    if ( g_mime_multipart_get_count (multipart) != 2 ) {
+		/* this violates RFC 3156 section 4, so we won't bother with it. */
+		fprintf (stderr,
+			 "Error: %d part(s) for a multipart/encrypted message (should be exactly 2)\n",
+			 g_mime_multipart_get_count (multipart));
+	    } else {
+		GMimeMultipartEncrypted *encrypteddata = GMIME_MULTIPART_ENCRYPTED (part);
+		GMimeObject *decryptedpart = g_mime_multipart_encrypted_decrypt (encrypteddata, params->cryptoctx, &err);
+		if (decryptedpart) {
+		    if ((selected || state->in_zone) && format->part_encstatus)
+			format->part_encstatus (1);
+		    const GMimeSignatureValidity *sigvalidity = g_mime_multipart_encrypted_get_signature_validity (encrypteddata);
+		    if (!sigvalidity)
+			fprintf (stderr, "Failed to verify signed part: %s\n", (err ? err->message : "no error explanation given"));
+		    if ((selected || state->in_zone) && format->part_sigstatus)
+			format->part_sigstatus (sigvalidity);
+		    /* swap the part with the decrypted part */
+		    part = decryptedpart;
+		} else {
+		    fprintf (stderr, "Failed to decrypt part: %s\n", (err ? err->message : "no error explanation given"));
+		    if ((selected || state->in_zone) && format->part_encstatus)
+			format->part_encstatus (0);
+		}
+	    }
+	}
+	else if (GMIME_IS_MULTIPART_SIGNED (part))
 	{
 	    if ( g_mime_multipart_get_count (multipart) != 2 ) {
 		/* this violates RFC 3156 section 5, so we won't bother with it. */
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 10/11] emacs: Add support for PGP/MIME verification/decryption
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (8 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 09/11] Add decryption of PGP/MIME-encrypted parts with --decrypt Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-26  1:01 ` [PATCH 11/11] tag signed/encrypted during notmuch new Jameson Graef Rollins
  2011-05-27 10:27 ` normalizing part numbering across PGP/MIME processing Jameson Graef Rollins
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

A new emacs configuration variable "notmuch-crypto-process-mime"
controls the processing of PGP/MIME signatures and encrypted parts.
When this is set true, notmuch-query will use the notmuch show
--decrypt flag to decrypt encrypted messages and/or calculate the
sigstatus of signed messages.  If sigstatus is available, notmuch-show
will place a specially color-coded header at the begining of the
signed message.

Also included is the ability to switch decryption/verification on/off
on the fly, which is bound to M-RET in notmuch-search-mode.
---
 emacs/Makefile.local    |    1 +
 emacs/notmuch-crypto.el |  104 +++++++++++++++++++++++++++++++++++++++++++++++
 emacs/notmuch-lib.el    |    5 ++
 emacs/notmuch-mua.el    |    9 +++-
 emacs/notmuch-query.el  |    7 ++-
 emacs/notmuch-show.el   |   65 ++++++++++++++++++++---------
 emacs/notmuch.el        |   10 ++++-
 7 files changed, 175 insertions(+), 26 deletions(-)
 create mode 100644 emacs/notmuch-crypto.el

diff --git a/emacs/Makefile.local b/emacs/Makefile.local
index 1c09d87..1022777 100644
--- a/emacs/Makefile.local
+++ b/emacs/Makefile.local
@@ -12,6 +12,7 @@ emacs_sources := \
 	$(dir)/notmuch-address.el \
 	$(dir)/notmuch-maildir-fcc.el \
 	$(dir)/notmuch-message.el \
+	$(dir)/notmuch-crypto.el \
 	$(dir)/coolj.el
 
 emacs_images := \
diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el
new file mode 100644
index 0000000..944452b
--- /dev/null
+++ b/emacs/notmuch-crypto.el
@@ -0,0 +1,104 @@
+;; notmuch-crypto.el --- functions for handling display of cryptographic metadata.
+;;
+;; Copyright © Jameson Rollins
+;;
+;; This file is part of Notmuch.
+;;
+;; Notmuch 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 3 of the License, or
+;; (at your option) any later version.
+;;
+;; Notmuch 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 Notmuch.  If not, see <http://www.gnu.org/licenses/>.
+;;
+;; Authors: Jameson Rollins <jrollins@finestructure.net>
+
+(defcustom notmuch-crypto-process-mime nil
+  "Should cryptographic MIME parts be processed?
+
+If this variable is non-nil signatures in multipart/signed
+messages will be verified and multipart/encrypted parts will be
+decrypted.  The result of the crypto operation will be displayed
+in a specially colored header button at the top of the processed
+part.  Signed parts will have variously colored headers depending
+on the success or failure of the verification process and on the
+validity of user ID of the signer.
+
+The effect of setting this variable can be seen temporarily by
+viewing a signed or encrypted message with M-RET in notmuch
+search."
+  :group 'notmuch
+  :type 'boolean)
+
+(define-button-type 'notmuch-crypto-status-button-type
+  'action '(lambda (button) (message (button-get button 'help-echo)))
+  'follow-link t
+  'help-echo "Set notmuch-crypto-process-mime to process cryptographic mime parts."
+  'face '(:foreground "blue")
+  'mouse-face '(:foreground "blue"))
+
+(defun notmuch-crypto-insert-sigstatus-button (sigstatus from)
+  (let* ((status (plist-get sigstatus :status))
+	 (help-msg nil)
+	 (label "multipart/signed: signature not processed")
+	 (face '(:background "red" :foreground "black")))
+    (cond
+     ((string= status "good")
+      ; if userid present, userid has full or greater validity
+      (if (plist-member sigstatus :userid)
+	  (let ((userid (plist-get sigstatus :userid)))
+	    (setq label (concat "Good signature by: " userid))
+	    (setq face '(:background "green" :foreground "black")))
+	(let ((fingerprint (concat "0x" (plist-get sigstatus :fingerprint))))
+	  (setq label (concat "Good signature by key: " fingerprint))
+	  (setq face '(:background "orange" :foreground "black")))))
+     ((string= status "error")
+      (let ((keyid (concat "0x" (plist-get sigstatus :keyid))))
+	(setq label (concat "Unknown key ID " keyid " or unsupported algorithm"))
+	(setq face '(:background "red" :foreground "black"))))
+     ((string= status "bad")
+      (let ((keyid (concat "0x" (plist-get sigstatus :keyid))))
+	(setq label (concat "Bad signature (claimed key ID " keyid ")"))
+	(setq face '(:background "red" :foreground "black"))))
+     (t
+      (setq label "Unknown signature status")
+      (if status (setq label (concat label " \"" status "\"")))))
+    (insert-button
+     (concat "[ " label " ]")
+     :type 'notmuch-crypto-status-button-type
+     'help-echo help-msg
+     'face face
+     'mouse-face face
+     :notmuch-sigstatus sigstatus
+     :notmuch-from from)
+    (insert "\n")))
+
+(defun notmuch-crypto-insert-encstatus-button (encstatus)
+  (let* ((status (plist-get encstatus :status))
+	 (help-msg nil)
+	 (label "multipart/encrypted: decryption not attempted")
+	 (face '(:background "purple" :foreground "black")))
+    (cond
+     ((string= status "good")
+      (setq label "decryption successful"))
+     ((string= status "bad")
+      (setq label "decryption error"))
+     (t
+      (setq label (concat "unknown encstatus \"" status "\""))))
+    (insert-button
+     (concat "[ multipart/encrypted: " label " ]")
+     :type 'notmuch-crypto-status-button-type
+     'help-echo help-msg
+     'face face
+     'mouse-face face)
+    (insert "\n")))
+
+;;
+
+(provide 'notmuch-crypto)
diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el
index cc80fb2..1ced0f1 100644
--- a/emacs/notmuch-lib.el
+++ b/emacs/notmuch-lib.el
@@ -156,5 +156,10 @@ was called."
    "Return non-nil if OBJECT is a mouse click event."
    (memq (event-basic-type object) '(mouse-1 mouse-2 mouse-3 mouse-movement))))
 
+;; This variable is used only buffer local, but it needs to be
+;; declared globally first to avoid compiler warnings.
+(defvar notmuch-show-process-crypto nil)
+(make-variable-buffer-local 'notmuch-show-process-crypto)
+
 (provide 'notmuch-lib)
 
diff --git a/emacs/notmuch-mua.el b/emacs/notmuch-mua.el
index dc7b386..003b313 100644
--- a/emacs/notmuch-mua.el
+++ b/emacs/notmuch-mua.el
@@ -70,12 +70,17 @@ list."
 	notmuch-mua-hidden-headers))
 
 (defun notmuch-mua-reply (query-string)
-  (let (headers body)
+  (let (headers
+	body
+	(args '("reply")))
+    (if notmuch-show-process-crypto
+	(setq args (append args '("--decrypt"))))
+    (setq args (append args (list query-string)))
     ;; This make assumptions about the output of `notmuch reply', but
     ;; really only that the headers come first followed by a blank
     ;; line and then the body.
     (with-temp-buffer
-      (call-process notmuch-command nil t nil "reply" query-string)
+      (apply 'call-process (append (list notmuch-command nil (list t t) nil) args))
       (goto-char (point-min))
       (if (re-search-forward "^$" nil t)
 	  (save-excursion
diff --git a/emacs/notmuch-query.el b/emacs/notmuch-query.el
index 921f624..d66baea 100644
--- a/emacs/notmuch-query.el
+++ b/emacs/notmuch-query.el
@@ -22,17 +22,20 @@
 (require 'notmuch-lib)
 (require 'json)
 
-(defun notmuch-query-get-threads (search-terms &rest options)
+(defun notmuch-query-get-threads (search-terms)
   "Return a list of threads of messages matching SEARCH-TERMS.
 
 A thread is a forest or list of trees. A tree is a two element
 list where the first element is a message, and the second element
 is a possibly empty forest of replies.
 "
-  (let  ((args (append '("show" "--format=json") search-terms))
+  (let  ((args '("show" "--format=json"))
 	 (json-object-type 'plist)
 	 (json-array-type 'list)
 	 (json-false 'nil))
+    (if notmuch-show-process-crypto
+	(setq args (append args '("--decrypt"))))
+    (setq args (append args search-terms))
     (with-temp-buffer
       (progn
 	(apply 'call-process (append (list notmuch-command nil (list t nil) nil) args))
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 9a38d9c..e0cd41f 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -32,6 +32,7 @@
 (require 'notmuch-query)
 (require 'notmuch-wash)
 (require 'notmuch-mua)
+(require 'notmuch-crypto)
 
 (declare-function notmuch-call-notmuch-process "notmuch" (&rest args))
 (declare-function notmuch-fontify-headers "notmuch" nil)
@@ -295,18 +296,20 @@ message at DEPTH in the current thread."
 ;; Functions handling particular MIME parts.
 
 (defun notmuch-show-save-part (message-id nth &optional filename)
-  (with-temp-buffer
-    ;; Always acquires the part via `notmuch part', even if it is
-    ;; available in the JSON output.
-    (insert (notmuch-show-get-bodypart-internal message-id nth))
-    (let ((file (read-file-name
-		 "Filename to save as: "
-		 (or mailcap-download-directory "~/")
-		 nil nil
-		 filename))
-	  (require-final-newline nil)
-          (coding-system-for-write 'no-conversion))
-      (write-region (point-min) (point-max) file))))
+  (let ((process-crypto notmuch-show-process-crypto))
+    (with-temp-buffer
+      (setq notmuch-show-process-crypto process-crypto)
+      ;; Always acquires the part via `notmuch part', even if it is
+      ;; available in the JSON output.
+      (insert (notmuch-show-get-bodypart-internal message-id nth))
+      (let ((file (read-file-name
+		   "Filename to save as: "
+		   (or mailcap-download-directory "~/")
+		   nil nil
+		   filename))
+	    (require-final-newline nil)
+	    (coding-system-for-write 'no-conversion))
+	(write-region (point-min) (point-max) file)))))
 
 (defun notmuch-show-mm-display-part-inline (msg part content-type content)
   "Use the mm-decode/mm-view functions to display a part in the
@@ -551,13 +554,20 @@ current buffer, if possible."
 
 ;; Helper for parts which are generally not included in the default
 ;; JSON output.
-
+;; Uses the buffer-local variable notmuch-show-process-crypto to
+;; determine if parts should be decrypted first.
 (defun notmuch-show-get-bodypart-internal (message-id part-number)
-  (with-temp-buffer
-    (let ((coding-system-for-read 'no-conversion))
-      (call-process notmuch-command nil t nil
-		    "show" "--format=raw" (format "--part=%s" part-number) message-id)
-      (buffer-string))))
+  (let ((args '("show" "--format=raw"))
+	(part-arg (format "--part=%s" part-number)))
+    (setq args (append args (list part-arg)))
+    (if notmuch-show-process-crypto
+	(setq args (append args '("--decrypt"))))
+    (setq args (append args (list message-id)))
+    (with-temp-buffer
+      (let ((coding-system-for-read 'no-conversion))
+	(progn
+	  (apply 'call-process (append (list notmuch-command nil (list t nil) nil) args))
+	  (buffer-string))))))
 
 (defun notmuch-show-get-bodypart-content (msg part nth)
   (or (plist-get part :content)
@@ -578,6 +588,16 @@ current buffer, if possible."
   "Insert the body part PART at depth DEPTH in the current thread."
   (let ((content-type (downcase (plist-get part :content-type)))
 	(nth (plist-get part :id)))
+    ;; add encryption status button if encstatus specified
+    (if (plist-member part :encstatus)
+	(let* ((encstatus (car (plist-get part :encstatus))))
+	  (notmuch-crypto-insert-encstatus-button encstatus)))
+    ;; add signature status button if sigstatus specified
+    (if (plist-member part :sigstatus)
+	(let* ((headers (plist-get msg :headers))
+	       (from (plist-get headers :From))
+	       (sigstatus (car (plist-get part :sigstatus))))
+	  (notmuch-crypto-insert-sigstatus-button sigstatus from)))
     (notmuch-show-insert-bodypart-internal msg part content-type nth depth content-type))
   ;; Some of the body part handlers leave point somewhere up in the
   ;; part, so we make sure that we're down at the end.
@@ -711,9 +731,10 @@ current buffer, if possible."
   (mapc '(lambda (thread) (notmuch-show-insert-thread thread 0)) forest))
 
 (defvar notmuch-show-parent-buffer nil)
+(make-variable-buffer-local 'notmuch-show-parent-buffer)
 
 ;;;###autoload
-(defun notmuch-show (thread-id &optional parent-buffer query-context buffer-name)
+(defun notmuch-show (thread-id &optional parent-buffer query-context buffer-name crypto-switch)
   "Run \"notmuch show\" with the given thread ID and display results.
 
 The optional PARENT-BUFFER is the notmuch-search buffer from
@@ -733,10 +754,14 @@ function is used. "
   (let ((buffer (get-buffer-create (generate-new-buffer-name
 				    (or buffer-name
 					(concat "*notmuch-" thread-id "*")))))
+	(process-crypto (if crypto-switch
+			    (not notmuch-crypto-process-mime)
+			  notmuch-crypto-process-mime))
 	(inhibit-read-only t))
     (switch-to-buffer buffer)
     (notmuch-show-mode)
-    (set (make-local-variable 'notmuch-show-parent-buffer) parent-buffer)
+    (setq notmuch-show-parent-buffer parent-buffer)
+    (setq notmuch-show-process-crypto process-crypto)
     (erase-buffer)
     (goto-char (point-min))
     (save-excursion
diff --git a/emacs/notmuch.el b/emacs/notmuch.el
index 64f72a0..837136d 100644
--- a/emacs/notmuch.el
+++ b/emacs/notmuch.el
@@ -218,6 +218,7 @@ For a mouse binding, return nil."
     (define-key map "-" 'notmuch-search-remove-tag)
     (define-key map "+" 'notmuch-search-add-tag)
     (define-key map (kbd "RET") 'notmuch-search-show-thread)
+    (define-key map (kbd "M-RET") 'notmuch-search-show-thread-crypto-switch)
     map)
   "Keymap for \"notmuch search\" buffers.")
 (fset 'notmuch-search-mode-map notmuch-search-mode-map)
@@ -417,7 +418,11 @@ Complete list of currently available key bindings:
   "Return a list of authors for the current region"
   (notmuch-search-properties-in-region 'notmuch-search-subject beg end))
 
-(defun notmuch-search-show-thread ()
+(defun notmuch-search-show-thread-crypto-switch ()
+  (interactive)
+  (notmuch-search-show-thread t))
+
+(defun notmuch-search-show-thread (&optional crypto-switch)
   "Display the currently selected thread."
   (interactive)
   (let ((thread-id (notmuch-search-find-thread-id))
@@ -433,7 +438,8 @@ Complete list of currently available key bindings:
 			 (concat "*"
 				 (truncate-string-to-width subject 32 nil nil t)
 				 "*")
-			 32 nil nil t)))
+			 32 nil nil t))
+		      crypto-switch)
       (error "End of search results"))))
 
 (defun notmuch-search-reply-to-thread ()
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 11/11] tag signed/encrypted during notmuch new
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (9 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 10/11] emacs: Add support for PGP/MIME verification/decryption Jameson Graef Rollins
@ 2011-05-26  1:01 ` Jameson Graef Rollins
  2011-05-27 10:27 ` normalizing part numbering across PGP/MIME processing Jameson Graef Rollins
  11 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-26  1:01 UTC (permalink / raw)
  To: notmuch

This patch adds the tag "signed" to messages with any multipart/signed
parts, and the tag "encrypted" to messages with any
multipart/encrypted parts.  This only occurs when messages are indexed
during notmuch new, so a database rebuild is required to have old
messages tagged.
---
 lib/index.cc                                       |    6 ++++++
 test/crypto                                        |   16 ++++++++--------
 .../emacs.expected-output/notmuch-hello-view-inbox |    6 +++---
 .../emacs.expected-output/notmuch-search-tag-inbox |    6 +++---
 .../notmuch-show-thread-maildir-storage            |    8 ++++----
 test/multipart                                     |    4 ++--
 test/search                                        |    6 +++---
 test/search-output                                 |    2 ++
 8 files changed, 31 insertions(+), 23 deletions(-)

diff --git a/lib/index.cc b/lib/index.cc
index bdfb8ed..e8e9922 100644
--- a/lib/index.cc
+++ b/lib/index.cc
@@ -325,6 +325,12 @@ _index_mime_part (notmuch_message_t *message,
 	GMimeMultipart *multipart = GMIME_MULTIPART (part);
 	int i;
 
+	if (GMIME_IS_MULTIPART_SIGNED (multipart))
+	  _notmuch_message_add_term (message, "tag", "signed");
+
+	if (GMIME_IS_MULTIPART_ENCRYPTED (multipart))
+	  _notmuch_message_add_term (message, "tag", "encrypted");
+
 	for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
 	    if (GMIME_IS_MULTIPART_SIGNED (multipart)) {
 		/* Don't index the signature. */
diff --git a/test/crypto b/test/crypto
index 3b0f381..c5abcc3 100755
--- a/test/crypto
+++ b/test/crypto
@@ -46,7 +46,7 @@ expected='[[[{"id": "XXXXX",
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
  "To": "test_suite@notmuchmail.org",
@@ -76,7 +76,7 @@ expected='[[[{"id": "XXXXX",
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
  "To": "test_suite@notmuchmail.org",
@@ -106,7 +106,7 @@ expected='[[[{"id": "XXXXX",
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
  "To": "test_suite@notmuchmail.org",
@@ -141,7 +141,7 @@ output=$(notmuch show --format=text --decrypt subject:"test encrypted message 00
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
 expected='\fmessage{ id:XXXXX depth:0 match:1 filename:XXXXX
 \fheader{
-Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (inbox)
+Notmuch Test Suite <test_suite@notmuchmail.org> (2000-01-01) (encrypted inbox)
 Subject: test encrypted message 001
 From: Notmuch Test Suite <test_suite@notmuchmail.org>
 To: test_suite@notmuchmail.org
@@ -172,7 +172,7 @@ expected='[[[{"id": "XXXXX",
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 001",
  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
  "To": "test_suite@notmuchmail.org",
@@ -223,7 +223,7 @@ expected='[[[{"id": "XXXXX",
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 001",
  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
  "To": "test_suite@notmuchmail.org",
@@ -258,7 +258,7 @@ expected='[[[{"id": "XXXXX",
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["encrypted","inbox"],
  "headers": {"Subject": "test encrypted message 002",
  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
  "To": "test_suite@notmuchmail.org",
@@ -309,7 +309,7 @@ expected='[[[{"id": "XXXXX",
  "filename": "YYYYY",
  "timestamp": 946728000,
  "date_relative": "2000-01-01",
- "tags": ["inbox"],
+ "tags": ["inbox","signed"],
  "headers": {"Subject": "test signed message 001",
  "From": "Notmuch Test Suite <test_suite@notmuchmail.org>",
  "To": "test_suite@notmuchmail.org",
diff --git a/test/emacs.expected-output/notmuch-hello-view-inbox b/test/emacs.expected-output/notmuch-hello-view-inbox
index 6472c46..894ae5f 100644
--- a/test/emacs.expected-output/notmuch-hello-view-inbox
+++ b/test/emacs.expected-output/notmuch-hello-view-inbox
@@ -1,16 +1,16 @@
   2009-11-17 [5/5]   Mikhail Gusarov, Carl Worth, Keith Packard  [notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
-  2009-11-17 [7/7]   Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth  [notmuch] Working with Maildir storage? (inbox unread)
+  2009-11-17 [7/7]   Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth  [notmuch] Working with Maildir storage? (inbox signed unread)
   2009-11-17 [2/2]   Alex Botero-Lowry, Carl Worth  [notmuch] preliminary FreeBSD support (attachment inbox unread)
   2009-11-17 [1/1]   Mikhail Gusarov      [notmuch] [PATCH] Handle rename of message file (inbox unread)
   2009-11-17 [2/2]   Keith Packard, Carl Worth    [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
   2009-11-17 [2/2]   Jan Janak, Carl Worth        [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
   2009-11-17 [3/3]   Jan Janak, Carl Worth        [notmuch] What a great idea! (inbox unread)
   2009-11-17 [3/3]   Israel Herraiz, Keith Packard, Carl Worth   [notmuch] New to the list (inbox unread)
-  2009-11-17 [3/3]   Adrian Perez de Castro, Keith Packard, Carl Worth  [notmuch] Introducing myself (inbox unread)
+  2009-11-17 [3/3]   Adrian Perez de Castro, Keith Packard, Carl Worth  [notmuch] Introducing myself (inbox signed unread)
   2009-11-17 [3/3]   Aron Griffis, Keith Packard, Carl Worth     [notmuch] archive (inbox unread)
   2009-11-17 [2/2]   Ingmar Vanhassel, Carl Worth  [notmuch] [PATCH] Typsos (inbox unread)
   2009-11-18 [2/2]   Alex Botero-Lowry, Carl Worth  [notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
-  2009-11-18 [2/2]   Lars Kellogg-Stedman [notmuch] "notmuch help" outputs to stderr? (attachment inbox unread)
+  2009-11-18 [2/2]   Lars Kellogg-Stedman [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
   2009-11-18 [1/1]   Stewart Smith        [notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox unread)
   2009-11-18 [1/1]   Stewart Smith        [notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox unread)
   2009-11-18 [1/1]   Stewart Smith        [notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox unread)
diff --git a/test/emacs.expected-output/notmuch-search-tag-inbox b/test/emacs.expected-output/notmuch-search-tag-inbox
index 2168159..9456ccf 100644
--- a/test/emacs.expected-output/notmuch-search-tag-inbox
+++ b/test/emacs.expected-output/notmuch-search-tag-inbox
@@ -1,13 +1,13 @@
   2009-11-18 [1/1]   Chris Wilson         [notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox unread)
   2009-11-18 [2/2]   Alex Botero-Lowry, Carl Worth  [notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
   2009-11-18 [2/2]   Ingmar Vanhassel, Carl Worth  [notmuch] [PATCH] Typsos (inbox unread)
-  2009-11-18 [3/3]   Adrian Perez de Castro, Keith Packard, Carl Worth  [notmuch] Introducing myself (inbox unread)
+  2009-11-18 [3/3]   Adrian Perez de Castro, Keith Packard, Carl Worth  [notmuch] Introducing myself (inbox signed unread)
   2009-11-18 [3/3]   Israel Herraiz, Keith Packard, Carl Worth   [notmuch] New to the list (inbox unread)
   2009-11-18 [3/3]   Jan Janak, Carl Worth        [notmuch] What a great idea! (inbox unread)
   2009-11-18 [2/2]   Jan Janak, Carl Worth        [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
   2009-11-18 [3/3]   Aron Griffis, Keith Packard, Carl Worth     [notmuch] archive (inbox unread)
   2009-11-18 [2/2]   Keith Packard, Carl Worth    [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
-  2009-11-18 [7/7]   Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth  [notmuch] Working with Maildir storage? (inbox unread)
+  2009-11-18 [7/7]   Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth  [notmuch] Working with Maildir storage? (inbox signed unread)
   2009-11-18 [5/5]   Mikhail Gusarov, Carl Worth, Keith Packard  [notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
   2009-11-18 [2/2]   Keith Packard, Alexander Botero-Lowry    [notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
   2009-11-18 [1/1]   Alexander Botero-Lowry  [notmuch] request for pull (inbox unread)
@@ -17,7 +17,7 @@
   2009-11-18 [1/1]   Stewart Smith        [notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox unread)
   2009-11-18 [1/1]   Stewart Smith        [notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox unread)
   2009-11-18 [1/1]   Stewart Smith        [notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox unread)
-  2009-11-18 [2/2]   Lars Kellogg-Stedman [notmuch] "notmuch help" outputs to stderr? (attachment inbox unread)
+  2009-11-18 [2/2]   Lars Kellogg-Stedman [notmuch] "notmuch help" outputs to stderr? (attachment inbox signed unread)
   2009-11-17 [1/1]   Mikhail Gusarov      [notmuch] [PATCH] Handle rename of message file (inbox unread)
   2009-11-17 [2/2]   Alex Botero-Lowry, Carl Worth  [notmuch] preliminary FreeBSD support (attachment inbox unread)
 End of search results.
diff --git a/test/emacs.expected-output/notmuch-show-thread-maildir-storage b/test/emacs.expected-output/notmuch-show-thread-maildir-storage
index 034d3d4..241b5b7 100644
--- a/test/emacs.expected-output/notmuch-show-thread-maildir-storage
+++ b/test/emacs.expected-output/notmuch-show-thread-maildir-storage
@@ -1,4 +1,4 @@
-Lars Kellogg-Stedman <lars@seas.harvard.edu> (2009-11-17) (inbox)
+Lars Kellogg-Stedman <lars@seas.harvard.edu> (2009-11-17) (inbox signed)
 Subject: [notmuch] Working with Maildir storage?
 To: notmuch@notmuchmail.org
 Date: Tue, 17 Nov 2009 14:00:54 -0500
@@ -39,7 +39,7 @@ _______________________________________________
 notmuch mailing list
 notmuch@notmuchmail.org
 http://notmuchmail.org/mailman/listinfo/notmuch
- Mikhail Gusarov <dottedmag@dottedmag.net> (2009-11-17) (inbox unread)
+ Mikhail Gusarov <dottedmag@dottedmag.net> (2009-11-17) (inbox signed unread)
  Subject: Re: [notmuch] Working with Maildir storage?
  To: notmuch@notmuchmail.org
  Date: Wed, 18 Nov 2009 01:02:38 +0600
@@ -68,7 +68,7 @@ http://notmuchmail.org/mailman/listinfo/notmuch
  notmuch mailing list
  notmuch@notmuchmail.org
  http://notmuchmail.org/mailman/listinfo/notmuch
-  Lars Kellogg-Stedman <lars@seas.harvard.edu> (2009-11-17) (inbox unread)
+  Lars Kellogg-Stedman <lars@seas.harvard.edu> (2009-11-17) (inbox signed unread)
   Subject: Re: [notmuch] Working with Maildir storage?
   To: Mikhail Gusarov <dottedmag@dottedmag.net>
   Cc: notmuch@notmuchmail.org
@@ -151,7 +151,7 @@ http://notmuchmail.org/mailman/listinfo/notmuch
 
    -keith
 
-    Lars Kellogg-Stedman <lars@seas.harvard.edu> (2009-11-18) (inbox unread)
+    Lars Kellogg-Stedman <lars@seas.harvard.edu> (2009-11-18) (inbox signed unread)
     Subject: Re: [notmuch] Working with Maildir storage?
     To: Keith Packard <keithp@keithp.com>
     Cc: notmuch@notmuchmail.org
diff --git a/test/multipart b/test/multipart
index 80da0b4..d712853 100755
--- a/test/multipart
+++ b/test/multipart
@@ -63,7 +63,7 @@ output=$(notmuch show --format=text --part=0 'id:87liy5ap00.fsf@yoom.home.cworth
 test_expect_equal "$output" \
 "\fmessage{ id:87liy5ap00.fsf@yoom.home.cworth.org depth:0 match:1 filename:${MAIL_DIR}/multipart
 \fheader{
-Carl Worth <cworth@cworth.org> (2001-01-05) (attachment inbox unread)
+Carl Worth <cworth@cworth.org> (2001-01-05) (attachment inbox signed unread)
 Subject: Multipart message
 From: Carl Worth <cworth@cworth.org>
 To: cworth@cworth.org
@@ -186,7 +186,7 @@ test_expect_success \
 test_begin_subtest "--format=json --part=0, full message"
 output=$(notmuch show --format=json --part=0 'id:87liy5ap00.fsf@yoom.home.cworth.org')
 test_expect_equal "$output" \
-'{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "filename": "'"${MAIL_DIR}/multipart"'", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Cc": "", "Bcc": "", "Date": "Tue, 05 Jan 2001 15:43:57 -0000"}, "body": [{"id": 1, "content-type": "multipart/signed", "content": [{"id": 2, "content-type": "multipart/mixed", "content": [{"id": 3, "content-type": "message/rfc822", "content": [{"id": 4, "content-type": "text/html"}]}, {"id": 5, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"}, {"id": 6, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}, {"id": 7, "content-type": "application/pgp-signature"}]}]}'
+'{"id": "87liy5ap00.fsf@yoom.home.cworth.org", "match": true, "filename": "'"${MAIL_DIR}/multipart"'", "timestamp": 978709437, "date_relative": "2001-01-05", "tags": ["attachment","inbox","signed","unread"], "headers": {"Subject": "Multipart message", "From": "Carl Worth <cworth@cworth.org>", "To": "cworth@cworth.org", "Cc": "", "Bcc": "", "Date": "Tue, 05 Jan 2001 15:43:57 -0000"}, "body": [{"id": 1, "content-type": "multipart/signed", "content": [{"id": 2, "content-type": "multipart/mixed", "content": [{"id": 3, "content-type": "message/rfc822", "content": [{"id": 4, "content-type": "text/html"}]}, {"id": 5, "content-type": "text/plain", "filename": "attachment", "content": "This is a text attachment.\n"}, {"id": 6, "content-type": "text/plain", "content": "And this message is signed.\n\n-Carl\n"}]}, {"id": 7, "content-type": "application/pgp-signature"}]}]}'
 
 test_begin_subtest "--format=json --part=1, message body"
 output=$(notmuch show --format=json --part=1 'id:87liy5ap00.fsf@yoom.home.cworth.org')
diff --git a/test/search b/test/search
index b180c7f..d2579df 100755
--- a/test/search
+++ b/test/search
@@ -78,13 +78,13 @@ output=$(notmuch search '*' | notmuch_search_sanitize)
 test_expect_equal "$output" "thread:XXX   2009-11-18 [1/1] Chris Wilson; [notmuch] [PATCH 1/2] Makefile: evaluate pkg-config once (inbox unread)
 thread:XXX   2009-11-18 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
 thread:XXX   2009-11-18 [2/2] Ingmar Vanhassel, Carl Worth; [notmuch] [PATCH] Typsos (inbox unread)
-thread:XXX   2009-11-18 [3/3] Adrian Perez de Castro, Keith Packard, Carl Worth; [notmuch] Introducing myself (inbox unread)
+thread:XXX   2009-11-18 [3/3] Adrian Perez de Castro, Keith Packard, Carl Worth; [notmuch] Introducing myself (inbox signed unread)
 thread:XXX   2009-11-18 [3/3] Israel Herraiz, Keith Packard, Carl Worth; [notmuch] New to the list (inbox unread)
 thread:XXX   2009-11-18 [3/3] Jan Janak, Carl Worth; [notmuch] What a great idea! (inbox unread)
 thread:XXX   2009-11-18 [2/2] Jan Janak, Carl Worth; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
 thread:XXX   2009-11-18 [3/3] Aron Griffis, Keith Packard, Carl Worth; [notmuch] archive (inbox unread)
 thread:XXX   2009-11-18 [2/2] Keith Packard, Carl Worth; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
-thread:XXX   2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox unread)
+thread:XXX   2009-11-18 [7/7] Lars Kellogg-Stedman, Mikhail Gusarov, Keith Packard, Carl Worth; [notmuch] Working with Maildir storage? (inbox signed unread)
 thread:XXX   2009-11-18 [5/5] Mikhail Gusarov, Carl Worth, Keith Packard; [notmuch] [PATCH 1/2] Close message file after parsing message headers (inbox unread)
 thread:XXX   2009-11-18 [2/2] Keith Packard, Alexander Botero-Lowry; [notmuch] [PATCH] Create a default notmuch-show-hook that highlights URLs and uses word-wrap (inbox unread)
 thread:XXX   2009-11-18 [1/1] Alexander Botero-Lowry; [notmuch] request for pull (inbox unread)
@@ -94,7 +94,7 @@ thread:XXX   2009-11-18 [1/1] Jan Janak; [notmuch] [PATCH] notmuch new: Support
 thread:XXX   2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH] count_files: sort directory in inode order before statting (inbox unread)
 thread:XXX   2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH 2/2] Read mail directory in inode number order (inbox unread)
 thread:XXX   2009-11-18 [1/1] Stewart Smith; [notmuch] [PATCH] Fix linking with gcc to use g++ to link in C++ libs. (inbox unread)
-thread:XXX   2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] \"notmuch help\" outputs to stderr? (attachment inbox unread)
+thread:XXX   2009-11-18 [2/2] Lars Kellogg-Stedman; [notmuch] \"notmuch help\" outputs to stderr? (attachment inbox signed unread)
 thread:XXX   2009-11-17 [1/1] Mikhail Gusarov; [notmuch] [PATCH] Handle rename of message file (inbox unread)
 thread:XXX   2009-11-17 [2/2] Alex Botero-Lowry, Carl Worth; [notmuch] preliminary FreeBSD support (attachment inbox unread)
 thread:XXX   2000-01-01 [1/1] Notmuch Test Suite; body search (inbox unread)
diff --git a/test/search-output b/test/search-output
index b414993..55dbc81 100755
--- a/test/search-output
+++ b/test/search-output
@@ -270,12 +270,14 @@ test_begin_subtest "notmuch search --output=tags"
 output=$(notmuch search --output=tags '*')
 test_expect_equal "$output" "attachment
 inbox
+signed
 unread"
 
 test_begin_subtest "notmuch search --format=json --output=tags"
 output=$(notmuch search --format=json --output=tags '*')
 test_expect_equal "$output" '["attachment",
 "inbox",
+"signed",
 "unread"]'
 
 test_done
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* normalizing part numbering across PGP/MIME processing
  2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
                   ` (10 preceding siblings ...)
  2011-05-26  1:01 ` [PATCH 11/11] tag signed/encrypted during notmuch new Jameson Graef Rollins
@ 2011-05-27 10:27 ` Jameson Graef Rollins
  2011-05-27 10:27   ` [PATCH 1/4] Do not replace multipart/signed part with content part when doing verification Jameson Graef Rollins
                     ` (2 more replies)
  11 siblings, 3 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-27 10:27 UTC (permalink / raw)
  To: notmuch

Ok.  So I very much hope this patch series satisfies those who were
bothered by the part renumbering that was happening when PGP/MIME
parts were processed.  For signed messages we no longer modify the
parts at all, so numbering always remains constant, and for encrypted
messages the numbering will only change if the encrypted message is
itself multipart.  We'll have to live with the encrypted multipart
renumbering until we have a more sophisticated part numbering scheme.
However, that's a separate issue that can hopefully be dealt with
after the full crypto functionality is pulled.

jamie.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH 1/4] Do not replace multipart/signed part with content part when doing verification.
  2011-05-27 10:27 ` normalizing part numbering across PGP/MIME processing Jameson Graef Rollins
@ 2011-05-27 10:27   ` Jameson Graef Rollins
  2011-05-27 10:27     ` [PATCH 2/4] Render all parts of multipart/encrypted when decrypting Jameson Graef Rollins
  2011-05-27 18:34   ` normalizing part numbering across PGP/MIME processing Daniel Kahn Gillmor
  2011-05-28  0:53   ` Carl Worth
  2 siblings, 1 reply; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-27 10:27 UTC (permalink / raw)
  To: notmuch

Some folks have complained about the part renumbering that occurs when
the entire multipart/signed part is replaced with the part contents
after verification.  This is primarily because it incurs an additional
computational cost to retrieve individual parts, since verification
has to be performed again to ensure that part numbering is consistent.
This patch simply leaves the full multipart/signed part as is.

The emacs crypto test is also updated to reflect this change.
---
 show-message.c |    2 --
 test/crypto    |   24 ++++++++++++++++++++----
 2 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/show-message.c b/show-message.c
index 37252b2..849c686 100644
--- a/show-message.c
+++ b/show-message.c
@@ -105,8 +105,6 @@ show_message_part (GMimeObject *part,
 		}
 		if ((selected || state->in_zone) && format->part_sigstatus)
 		    format->part_sigstatus (sigvalidity);
-		/* extract only data part, and ignore signature part */
-		part = g_mime_multipart_get_part (multipart, 0);
 		if (sigvalidity)
 		    g_mime_signature_validity_free (sigvalidity);
 	    }
diff --git a/test/crypto b/test/crypto
index c5abcc3..ef35c55 100755
--- a/test/crypto
+++ b/test/crypto
@@ -57,8 +57,12 @@ expected='[[[{"id": "XXXXX",
  "sigstatus": [{"status": "good",
  "fingerprint": "'$FINGERPRINT'",
  "created": 946728000}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
  "content-type": "text/plain",
- "content": "This is a test signed message.\n"}]},
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
@@ -88,8 +92,12 @@ expected='[[[{"id": "XXXXX",
  "fingerprint": "'$FINGERPRINT'",
  "created": 946728000,
  "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
  "content-type": "text/plain",
- "content": "This is a test signed message.\n"}]},
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
@@ -117,8 +125,12 @@ expected='[[[{"id": "XXXXX",
  "sigstatus": [{"status": "error",
  "keyid": "'$(echo $FINGERPRINT | cut -c 25-)'",
  "errors": 2}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
  "content-type": "text/plain",
- "content": "This is a test signed message.\n"}]},
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
@@ -320,8 +332,12 @@ expected='[[[{"id": "XXXXX",
  "sigstatus": [{"status": "error",
  "keyid": "6D92612D94E46381",
  "errors": 8}],
+ "content-type": "multipart/signed",
+ "content": [{"id": 2,
  "content-type": "text/plain",
- "content": "This is a test signed message.\n"}]},
+ "content": "This is a test signed message.\n"},
+ {"id": 3,
+ "content-type": "application/pgp-signature"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 2/4] Render all parts of multipart/encrypted when decrypting.
  2011-05-27 10:27   ` [PATCH 1/4] Do not replace multipart/signed part with content part when doing verification Jameson Graef Rollins
@ 2011-05-27 10:27     ` Jameson Graef Rollins
  2011-05-27 10:27       ` [PATCH 3/4] emacs: Do not attempt to render arbitrary application parts Jameson Graef Rollins
  0 siblings, 1 reply; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-27 10:27 UTC (permalink / raw)
  To: notmuch

The primary goal here is to keep the decrypted output as similarly
structured as undecrypted output as possible.  Now, when decrypting
parts, only the original encrypted part is replaced by the it's
decrypted content.  If this part isn't itself a multipart, then all
part numbering should remain consistent during decryption.

The only draw back here is that the useless application/pgp-encrypted
sub-part of the multipart/encrypted part is also emitted.  But this
part can be easily ignored by clients.
---
 show-message.c |   22 ++++++++++++++++------
 test/crypto    |   39 +++++++++++++++++++++++++++------------
 2 files changed, 43 insertions(+), 18 deletions(-)

diff --git a/show-message.c b/show-message.c
index 849c686..7a4bbc2 100644
--- a/show-message.c
+++ b/show-message.c
@@ -34,6 +34,7 @@ show_message_part (GMimeObject *part,
 		   notmuch_show_params_t *params,
 		   int first)
 {
+    GMimeObject *decryptedpart = NULL;
     int selected;
     state->part_count += 1;
 
@@ -67,7 +68,7 @@ show_message_part (GMimeObject *part,
 			 g_mime_multipart_get_count (multipart));
 	    } else {
 		GMimeMultipartEncrypted *encrypteddata = GMIME_MULTIPART_ENCRYPTED (part);
-		GMimeObject *decryptedpart = g_mime_multipart_encrypted_decrypt (encrypteddata, params->cryptoctx, &err);
+		decryptedpart = g_mime_multipart_encrypted_decrypt (encrypteddata, params->cryptoctx, &err);
 		if (decryptedpart) {
 		    if ((selected || state->in_zone) && format->part_encstatus)
 			format->part_encstatus (1);
@@ -76,8 +77,6 @@ show_message_part (GMimeObject *part,
 			fprintf (stderr, "Failed to verify signed part: %s\n", (err ? err->message : "no error explanation given"));
 		    if ((selected || state->in_zone) && format->part_sigstatus)
 			format->part_sigstatus (sigvalidity);
-		    /* swap the part with the decrypted part */
-		    part = decryptedpart;
 		} else {
 		    fprintf (stderr, "Failed to decrypt part: %s\n", (err ? err->message : "no error explanation given"));
 		    if ((selected || state->in_zone) && format->part_encstatus)
@@ -125,9 +124,20 @@ show_message_part (GMimeObject *part,
 	if (selected)
 	    state->in_zone = 1;
 
-	for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
-	    show_message_part (g_mime_multipart_get_part (multipart, i),
-			       state, format, params, i == 0);
+	if (decryptedpart) {
+	    /* We emit the useless application/pgp-encrypted version
+	     * part here only to keep the emitted output as consistent
+	     * as possible between decrypted output and the
+	     * unprocessed multipart/mime. For some strange reason,
+	     * the actual encrypted data is the second part of the
+	     * multipart. */
+	    show_message_part (g_mime_multipart_get_part (multipart, 0), state, format, params, TRUE);
+	    show_message_part (decryptedpart, state, format, params, FALSE);
+	} else {
+	    for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
+		show_message_part (g_mime_multipart_get_part (multipart, i),
+				   state, format, params, i == 0);
+	    }
 	}
 
 	if (selected)
diff --git a/test/crypto b/test/crypto
index ef35c55..6ce51d9 100755
--- a/test/crypto
+++ b/test/crypto
@@ -160,15 +160,20 @@ To: test_suite@notmuchmail.org
 Date: 01 Jan 2000 12:00:00 -0000
 \fheader}
 \fbody{
-\fpart{ ID: 1, Content-type: multipart/mixed
-\fpart{ ID: 2, Content-type: text/plain
+\fpart{ ID: 1, Content-type: multipart/encrypted
+\fpart{ ID: 2, Content-type: application/pgp-encrypted
+Non-text part: application/pgp-encrypted
+\fpart}
+\fpart{ ID: 3, Content-type: multipart/mixed
+\fpart{ ID: 4, Content-type: text/plain
 This is a test encrypted message.
 \fpart}
-\fattachment{ ID: 3, Content-type: application/octet-stream
+\fattachment{ ID: 5, Content-type: application/octet-stream
 Attachment: TESTATTACHMENT (application/octet-stream)
 Non-text part: application/octet-stream
 \fattachment}
 \fpart}
+\fpart}
 \fbody}
 \fmessage}'
 test_expect_equal \
@@ -194,33 +199,37 @@ expected='[[[{"id": "XXXXX",
  "body": [{"id": 1,
  "encstatus": [{"status": "good"}],
  "sigstatus": [],
- "content-type": "multipart/mixed",
+ "content-type": "multipart/encrypted",
  "content": [{"id": 2,
+ "content-type": "application/pgp-encrypted"},
+ {"id": 3,
+ "content-type": "multipart/mixed",
+ "content": [{"id": 4,
  "content-type": "text/plain",
  "content": "This is a test encrypted message.\n"},
- {"id": 3,
+ {"id": 5,
  "content-type": "application/octet-stream",
- "filename": "TESTATTACHMENT"}]}]},
+ "filename": "TESTATTACHMENT"}]}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
     "$expected"
 
-test_begin_subtest "decryption, --format=json, --part=2"
-output=$(notmuch show --format=json --part=2 --decrypt subject:"test encrypted message 001" \
+test_begin_subtest "decryption, --format=json, --part=4"
+output=$(notmuch show --format=json --part=4 --decrypt subject:"test encrypted message 001" \
     | notmuch_json_show_sanitize \
     | sed -e 's|"created": [1234567890]*|"created": 946728000|')
-expected='{"id": 2,
+expected='{"id": 4,
  "content-type": "text/plain",
  "content": "This is a test encrypted message.\n"}'
 test_expect_equal \
     "$output" \
     "$expected"
 
-test_begin_subtest "decrypt attachment (--part=3 --format=raw)"
+test_begin_subtest "decrypt attachment (--part=5 --format=raw)"
 notmuch show \
     --format=raw \
-    --part=3 \
+    --part=5 \
     --decrypt \
     subject:"test encrypted message 001" >OUTPUT
 test_expect_equal_file OUTPUT TESTATTACHMENT
@@ -283,8 +292,12 @@ expected='[[[{"id": "XXXXX",
  "fingerprint": "'$FINGERPRINT'",
  "created": 946728000,
  "userid": " Notmuch Test Suite <test_suite@notmuchmail.org> (INSECURE!)"}],
+ "content-type": "multipart/encrypted",
+ "content": [{"id": 2,
+ "content-type": "application/pgp-encrypted"},
+ {"id": 3,
  "content-type": "text/plain",
- "content": "This is another test encrypted message.\n"}]},
+ "content": "This is another test encrypted message.\n"}]}]},
  []]]]'
 test_expect_equal \
     "$output" \
@@ -297,6 +310,8 @@ expected='From: Notmuch Test Suite <test_suite@notmuchmail.org>
 Subject: Re: test encrypted message 002
 
 On 01 Jan 2000 12:00:00 -0000, Notmuch Test Suite <test_suite@notmuchmail.org> wrote:
+Non-text part: multipart/encrypted
+Non-text part: application/pgp-encrypted
 > This is another test encrypted message.'
 test_expect_equal \
     "$output" \
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 3/4] emacs: Do not attempt to render arbitrary application parts.
  2011-05-27 10:27     ` [PATCH 2/4] Render all parts of multipart/encrypted when decrypting Jameson Graef Rollins
@ 2011-05-27 10:27       ` Jameson Graef Rollins
  2011-05-27 10:27         ` [PATCH 4/4] emacs: Give mutlipart/{signed, encrypted} their own part handler Jameson Graef Rollins
  0 siblings, 1 reply; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-27 10:27 UTC (permalink / raw)
  To: notmuch

We probably shouldn't have been doing this anyway, but we do it here
specifically because we don't want the content of the
application/pgp-encrypted parts to be displayed and cluttering the
message show.
---
 emacs/notmuch-show.el |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index 2f6be59..aa6ddd1 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -524,6 +524,11 @@ current buffer, if possible."
 		nil))
 	  nil))))
 
+(defun notmuch-show-insert-part-application/* (msg part content-type nth depth declared-type
+)
+  ;; do not render random "application" parts
+  (notmuch-show-insert-part-header nth content-type declared-type (plist-get part :filename)))
+
 (defun notmuch-show-insert-part-*/* (msg part content-type nth depth declared-type)
   ;; This handler _must_ succeed - it is the handler of last resort.
   (notmuch-show-insert-part-header nth content-type declared-type (plist-get part :filename))
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [PATCH 4/4] emacs: Give mutlipart/{signed, encrypted} their own part handler.
  2011-05-27 10:27       ` [PATCH 3/4] emacs: Do not attempt to render arbitrary application parts Jameson Graef Rollins
@ 2011-05-27 10:27         ` Jameson Graef Rollins
  2011-05-27 18:52           ` [PATCH] " Jameson Graef Rollins
  0 siblings, 1 reply; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-27 10:27 UTC (permalink / raw)
  To: notmuch

This is the best way to make the displayed output for
decrypted/verified messages clearer.  The special sigstatus and
encstatus buttons are now displayed under the part header button.  The
part header button is also tweaked to provide information to user
about how to proces crypto.
---
 emacs/notmuch-crypto.el |   12 ++++----
 emacs/notmuch-show.el   |   61 +++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 57 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el
index 944452b..cb02840 100644
--- a/emacs/notmuch-crypto.el
+++ b/emacs/notmuch-crypto.el
@@ -46,7 +46,7 @@ search."
 (defun notmuch-crypto-insert-sigstatus-button (sigstatus from)
   (let* ((status (plist-get sigstatus :status))
 	 (help-msg nil)
-	 (label "multipart/signed: signature not processed")
+	 (label "Signature not processed")
 	 (face '(:background "red" :foreground "black")))
     (cond
      ((string= status "good")
@@ -82,17 +82,17 @@ search."
 (defun notmuch-crypto-insert-encstatus-button (encstatus)
   (let* ((status (plist-get encstatus :status))
 	 (help-msg nil)
-	 (label "multipart/encrypted: decryption not attempted")
+	 (label "Decryption not attempted")
 	 (face '(:background "purple" :foreground "black")))
     (cond
      ((string= status "good")
-      (setq label "decryption successful"))
+      (setq label "Decryption successful"))
      ((string= status "bad")
-      (setq label "decryption error"))
+      (setq label "Decryption error"))
      (t
-      (setq label (concat "unknown encstatus \"" status "\""))))
+      (setq label (concat "Unknown encstatus \"" status "\""))))
     (insert-button
-     (concat "[ multipart/encrypted: " label " ]")
+     (concat "[ " label " ]")
      :type 'notmuch-crypto-status-button-type
      'help-echo help-msg
      'face face
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index aa6ddd1..131fc85 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -446,6 +446,57 @@ current buffer, if possible."
       (indent-rigidly start (point) 1)))
   t)
 
+(defun notmuch-show-insert-part-multipart/signed (msg part content-type nth depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type content-type nil)))
+    (button-put button 'face '(:foreground "blue"))
+    ;; add signature status button if sigstatus provided
+    (if (plist-member part :sigstatus)
+	(let* ((headers (plist-get msg :headers))
+	       (from (plist-get headers :From))
+	       (sigstatus (car (plist-get part :sigstatus))))
+	  (notmuch-crypto-insert-sigstatus-button sigstatus from))
+      ;; if we're not adding sigstatus, tell the user how they can get it
+      (button-put button 'help-echo "Set notmuch-crypto-process-mime to process cryptographic mime parts.")))
+
+  (let ((inner-parts (plist-get part :content))
+	(start (point)))
+    ;; Show all of the parts.
+    (mapc (lambda (inner-part)
+	    (notmuch-show-insert-bodypart msg inner-part depth))
+	  inner-parts)
+
+    (when notmuch-show-indent-multipart
+      (indent-rigidly start (point) 1)))
+  t)
+
+(defun notmuch-show-insert-part-multipart/encrypted (msg part content-type nth depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type content-type nil)))
+    (button-put button 'face '(:foreground "blue"))
+    ;; add encryption status button if encstatus specified
+    (if (plist-member part :encstatus)
+	(let ((encstatus (car (plist-get part :encstatus))))
+	  (notmuch-crypto-insert-encstatus-button encstatus))
+      ;; if we're not adding encstatus, tell the user how they can get it
+      (progn
+	(button-put button 'help-echo "Set notmuch-crypto-process-mime to process cryptographic mime parts.")
+	;; add signature status button if sigstatus specified
+	(if (plist-member part :sigstatus)
+	  (let* ((headers (plist-get msg :headers))
+		 (from (plist-get headers :From))
+		 (sigstatus (car (plist-get part :sigstatus))))
+	    (notmuch-crypto-insert-sigstatus-button sigstatus from))))))
+
+  (let ((inner-parts (plist-get part :content))
+	(start (point)))
+    ;; Show all of the parts.
+    (mapc (lambda (inner-part)
+	    (notmuch-show-insert-bodypart msg inner-part depth))
+	  inner-parts)
+
+    (when notmuch-show-indent-multipart
+      (indent-rigidly start (point) 1)))
+  t)
+
 (defun notmuch-show-insert-part-multipart/* (msg part content-type nth depth declared-type)
   (notmuch-show-insert-part-header nth declared-type content-type nil)
   (let ((inner-parts (plist-get part :content))
@@ -593,16 +644,6 @@ current buffer, if possible."
   "Insert the body part PART at depth DEPTH in the current thread."
   (let ((content-type (downcase (plist-get part :content-type)))
 	(nth (plist-get part :id)))
-    ;; add encryption status button if encstatus specified
-    (if (plist-member part :encstatus)
-	(let* ((encstatus (car (plist-get part :encstatus))))
-	  (notmuch-crypto-insert-encstatus-button encstatus)))
-    ;; add signature status button if sigstatus specified
-    (if (plist-member part :sigstatus)
-	(let* ((headers (plist-get msg :headers))
-	       (from (plist-get headers :From))
-	       (sigstatus (car (plist-get part :sigstatus))))
-	  (notmuch-crypto-insert-sigstatus-button sigstatus from)))
     (notmuch-show-insert-bodypart-internal msg part content-type nth depth content-type))
   ;; Some of the body part handlers leave point somewhere up in the
   ;; part, so we make sure that we're down at the end.
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: normalizing part numbering across PGP/MIME processing
  2011-05-27 10:27 ` normalizing part numbering across PGP/MIME processing Jameson Graef Rollins
  2011-05-27 10:27   ` [PATCH 1/4] Do not replace multipart/signed part with content part when doing verification Jameson Graef Rollins
@ 2011-05-27 18:34   ` Daniel Kahn Gillmor
  2011-05-28  0:53   ` Carl Worth
  2 siblings, 0 replies; 28+ messages in thread
From: Daniel Kahn Gillmor @ 2011-05-27 18:34 UTC (permalink / raw)
  To: notmuch

[-- Attachment #1: Type: text/plain, Size: 1093 bytes --]

On Fri, 27 May 2011 03:27:35 -0700, Jameson Graef Rollins <jrollins@finestructure.net> wrote:
> Ok.  So I very much hope this patch series satisfies those who were
> bothered by the part renumbering that was happening when PGP/MIME
> parts were processed.  For signed messages we no longer modify the
> parts at all, so numbering always remains constant, and for encrypted
> messages the numbering will only change if the encrypted message is
> itself multipart.  We'll have to live with the encrypted multipart
> renumbering until we have a more sophisticated part numbering scheme.
> However, that's a separate issue that can hopefully be dealt with
> after the full crypto functionality is pulled.

These patches resolve my outstanding part-numbering concern with the
crypto verification business.  I recommend merging them to the mainline.

Then can we release 0.6 pretty please? :)

There's nothing stopping us from releasing 0.7 if there are more
features pending, but i'd really like to be able to say "please run 0.6
or later to handle verifying cryptographic signatures".

     --dkg

[-- Attachment #2: Type: application/pgp-signature, Size: 965 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH] emacs: Give mutlipart/{signed, encrypted} their own part handler.
  2011-05-27 10:27         ` [PATCH 4/4] emacs: Give mutlipart/{signed, encrypted} their own part handler Jameson Graef Rollins
@ 2011-05-27 18:52           ` Jameson Graef Rollins
  0 siblings, 0 replies; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-27 18:52 UTC (permalink / raw)
  To: notmuch

This is the best way to make the displayed output for
decrypted/verified messages clearer.  The special sigstatus and
encstatus buttons are now displayed under the part header button.  The
part header button is also tweaked to provide information to user
about how to proces crypto.
---

This patch replaces the previous version of this patch (9d7a9e3a) that
was mistakenly not emitting the sigstatus button for decrypted signed
messages.

 emacs/notmuch-crypto.el |   12 ++++----
 emacs/notmuch-show.el   |   60 +++++++++++++++++++++++++++++++++++++++--------
 2 files changed, 56 insertions(+), 16 deletions(-)

diff --git a/emacs/notmuch-crypto.el b/emacs/notmuch-crypto.el
index 944452b..cb02840 100644
--- a/emacs/notmuch-crypto.el
+++ b/emacs/notmuch-crypto.el
@@ -46,7 +46,7 @@ search."
 (defun notmuch-crypto-insert-sigstatus-button (sigstatus from)
   (let* ((status (plist-get sigstatus :status))
 	 (help-msg nil)
-	 (label "multipart/signed: signature not processed")
+	 (label "Signature not processed")
 	 (face '(:background "red" :foreground "black")))
     (cond
      ((string= status "good")
@@ -82,17 +82,17 @@ search."
 (defun notmuch-crypto-insert-encstatus-button (encstatus)
   (let* ((status (plist-get encstatus :status))
 	 (help-msg nil)
-	 (label "multipart/encrypted: decryption not attempted")
+	 (label "Decryption not attempted")
 	 (face '(:background "purple" :foreground "black")))
     (cond
      ((string= status "good")
-      (setq label "decryption successful"))
+      (setq label "Decryption successful"))
      ((string= status "bad")
-      (setq label "decryption error"))
+      (setq label "Decryption error"))
      (t
-      (setq label (concat "unknown encstatus \"" status "\""))))
+      (setq label (concat "Unknown encstatus \"" status "\""))))
     (insert-button
-     (concat "[ multipart/encrypted: " label " ]")
+     (concat "[ " label " ]")
      :type 'notmuch-crypto-status-button-type
      'help-echo help-msg
      'face face
diff --git a/emacs/notmuch-show.el b/emacs/notmuch-show.el
index aa6ddd1..6c498ab 100644
--- a/emacs/notmuch-show.el
+++ b/emacs/notmuch-show.el
@@ -446,6 +446,56 @@ current buffer, if possible."
       (indent-rigidly start (point) 1)))
   t)
 
+(defun notmuch-show-insert-part-multipart/signed (msg part content-type nth depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type content-type nil)))
+    (button-put button 'face '(:foreground "blue"))
+    ;; add signature status button if sigstatus provided
+    (if (plist-member part :sigstatus)
+	(let* ((headers (plist-get msg :headers))
+	       (from (plist-get headers :From))
+	       (sigstatus (car (plist-get part :sigstatus))))
+	  (notmuch-crypto-insert-sigstatus-button sigstatus from))
+      ;; if we're not adding sigstatus, tell the user how they can get it
+      (button-put button 'help-echo "Set notmuch-crypto-process-mime to process cryptographic mime parts.")))
+
+  (let ((inner-parts (plist-get part :content))
+	(start (point)))
+    ;; Show all of the parts.
+    (mapc (lambda (inner-part)
+	    (notmuch-show-insert-bodypart msg inner-part depth))
+	  inner-parts)
+
+    (when notmuch-show-indent-multipart
+      (indent-rigidly start (point) 1)))
+  t)
+
+(defun notmuch-show-insert-part-multipart/encrypted (msg part content-type nth depth declared-type)
+  (let ((button (notmuch-show-insert-part-header nth declared-type content-type nil)))
+    (button-put button 'face '(:foreground "blue"))
+    ;; add encryption status button if encstatus specified
+    (if (plist-member part :encstatus)
+	(let ((encstatus (car (plist-get part :encstatus))))
+	  (notmuch-crypto-insert-encstatus-button encstatus)
+	  ;; add signature status button if sigstatus specified
+	  (if (plist-member part :sigstatus)
+	      (let* ((headers (plist-get msg :headers))
+		     (from (plist-get headers :From))
+		     (sigstatus (car (plist-get part :sigstatus))))
+		(notmuch-crypto-insert-sigstatus-button sigstatus from))))
+      ;; if we're not adding encstatus, tell the user how they can get it
+      (button-put button 'help-echo "Set notmuch-crypto-process-mime to process cryptographic mime parts.")))
+
+  (let ((inner-parts (plist-get part :content))
+	(start (point)))
+    ;; Show all of the parts.
+    (mapc (lambda (inner-part)
+	    (notmuch-show-insert-bodypart msg inner-part depth))
+	  inner-parts)
+
+    (when notmuch-show-indent-multipart
+      (indent-rigidly start (point) 1)))
+  t)
+
 (defun notmuch-show-insert-part-multipart/* (msg part content-type nth depth declared-type)
   (notmuch-show-insert-part-header nth declared-type content-type nil)
   (let ((inner-parts (plist-get part :content))
@@ -593,16 +643,6 @@ current buffer, if possible."
   "Insert the body part PART at depth DEPTH in the current thread."
   (let ((content-type (downcase (plist-get part :content-type)))
 	(nth (plist-get part :id)))
-    ;; add encryption status button if encstatus specified
-    (if (plist-member part :encstatus)
-	(let* ((encstatus (car (plist-get part :encstatus))))
-	  (notmuch-crypto-insert-encstatus-button encstatus)))
-    ;; add signature status button if sigstatus specified
-    (if (plist-member part :sigstatus)
-	(let* ((headers (plist-get msg :headers))
-	       (from (plist-get headers :From))
-	       (sigstatus (car (plist-get part :sigstatus))))
-	  (notmuch-crypto-insert-sigstatus-button sigstatus from)))
     (notmuch-show-insert-bodypart-internal msg part content-type nth depth content-type))
   ;; Some of the body part handlers leave point somewhere up in the
   ;; part, so we make sure that we're down at the end.
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: normalizing part numbering across PGP/MIME processing
  2011-05-27 10:27 ` normalizing part numbering across PGP/MIME processing Jameson Graef Rollins
  2011-05-27 10:27   ` [PATCH 1/4] Do not replace multipart/signed part with content part when doing verification Jameson Graef Rollins
  2011-05-27 18:34   ` normalizing part numbering across PGP/MIME processing Daniel Kahn Gillmor
@ 2011-05-28  0:53   ` Carl Worth
  2011-05-28 21:31     ` Jameson Graef Rollins
  2011-06-03 23:03     ` [PATCH] Always return the empty string if decryption tries to demand a password Daniel Kahn Gillmor
  2 siblings, 2 replies; 28+ messages in thread
From: Carl Worth @ 2011-05-28  0:53 UTC (permalink / raw)
  To: Jameson Graef Rollins, notmuch

[-- Attachment #1: Type: text/plain, Size: 3571 bytes --]

On Fri, 27 May 2011 03:27:35 -0700, Jameson Graef Rollins <jrollins@finestructure.net> wrote:
> Ok.  So I very much hope this patch series satisfies those who were
> bothered by the part renumbering that was happening when PGP/MIME
> parts were processed.  For signed messages we no longer modify the
> parts at all, so numbering always remains constant, and for encrypted
> messages the numbering will only change if the encrypted message is
> itself multipart.

That sounds much better to me. I think the remaining issues I have with
the patch series are very minor and can be applied after the fact. I'd
push the series right now except that I happen to have no network access
at the moment. [I'm queueing up this message for delivery, so if I'm on
top of things when I'm back in range, I'll push right away.]

So, well done, Jameson! You've been extremely patient as I sat on this
patch series for *so* long, and then made you rebuild it so many
times. I hope you think the rebuilds were at least worth it for the much
cleaner final state, (I know that the useless waiting wasn't worth it).

I promise you don't need to rebuild this branch anymore, nor keep asking
me to merge it. Go enjoy a good US-holiday weekend. You've earned it!

That said, here are the (minor) issues I have with the series:

  * More tests should be switched to the new text_expect_equal_file

	This isn't a problem with the series---but will be a nice
	fix. I think the current "notmuch search --output=tags *" is
	broken due to a missing final newline---or at least has been
	broken that way recently. So it will be nice to have this
	support for testing a final newline.

  * The series duplicates some existing code into a new
    emacs_deliver_message

	The previously-existing code should be removed and replaced with
	a call to the new function.

  * Should we set the crypto option to verify/decrypt by default?

	That would certainly be convenient for me at least.

	For people who don't want this, they can set the variable to
	nil. But then they'll still have the following issue:

  * I'm not a fan of the M-RET option for decrypting a message

	If someone is going to have encrypted messages not decrypted by
	default, then they can currently decrypt by opening the message
	with M-RET. But I think in common use, the user is likely to
	only realize too late that they want to decrypt the message.

	So what I'd love to see is a keybinding for decrypting a message
	from the view of the message itself. (One natural place would be
	by activating the button of the encrypted part---but a
	keybinding to review with decryption would be fine too---likely
	easier to code and easier to use.)

  * I can't actually get decryption to work for me. :-(

	When I run "notmuch show --decrypt" on a message encrypted with
	my public key I get a segfault within libgmime, specifically in
	the g_mime_session_request_passwd function.

	My first guess is that this is due to the fact that gpg-agent
	can't be run on my system (Debian unstable):

	$ gpg-agent
	gpg-agent: symbol lookup error: /usr/lib/libassuan.so.0: undefined symbol: gpg_err_set_errno

	I've got a Debian bug report queued up for this.

	I also tried running the same "notmuch show" command without
	gpg-agent installed. How is libgmime supposed to actually
	request a password in a case like this?

	Anyway, I know that not everyone has this same problem with the
	series, so I'm not blocking it for this.

-Carl

-- 
carl.d.worth@intel.com

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: normalizing part numbering across PGP/MIME processing
  2011-05-28  0:53   ` Carl Worth
@ 2011-05-28 21:31     ` Jameson Graef Rollins
  2011-06-03 21:34       ` Carl Worth
  2011-06-03 23:03     ` [PATCH] Always return the empty string if decryption tries to demand a password Daniel Kahn Gillmor
  1 sibling, 1 reply; 28+ messages in thread
From: Jameson Graef Rollins @ 2011-05-28 21:31 UTC (permalink / raw)
  To: Carl Worth, notmuch

[-- Attachment #1: Type: text/plain, Size: 3440 bytes --]

On Fri, 27 May 2011 17:53:44 -0700, Carl Worth <cworth@cworth.org> wrote:
> So, well done, Jameson! You've been extremely patient as I sat on this
> patch series for *so* long, and then made you rebuild it so many
> times. I hope you think the rebuilds were at least worth it for the much
> cleaner final state, (I know that the useless waiting wasn't worth it).

w00t!  Thanks so much, Carl!  I definitely think the whole branch turned
out to be a lot cleaner in the end.

> That said, here are the (minor) issues I have with the series:
> 
>   * More tests should be switched to the new text_expect_equal_file
> 
> 	This isn't a problem with the series---but will be a nice
> 	fix. I think the current "notmuch search --output=tags *" is
> 	broken due to a missing final newline---or at least has been
> 	broken that way recently. So it will be nice to have this
> 	support for testing a final newline.

Yes, I agree.  I'm about to send a patch series to the list that
includes a bunch of random stuff that should be include in 0.6, and it
includes some of these fixes.

>   * Should we set the crypto option to verify/decrypt by default?
> 
> 	That would certainly be convenient for me at least.
> 
> 	For people who don't want this, they can set the variable to
> 	nil. But then they'll still have the following issue:

I don't really have an opinion on this.  I have it set now, so whether
or not it's set by default doesn't make much difference to me.

>   * I'm not a fan of the M-RET option for decrypting a message
> 
> 	If someone is going to have encrypted messages not decrypted by
> 	default, then they can currently decrypt by opening the message
> 	with M-RET. But I think in common use, the user is likely to
> 	only realize too late that they want to decrypt the message.
> 
> 	So what I'd love to see is a keybinding for decrypting a message
> 	from the view of the message itself. (One natural place would be
> 	by activating the button of the encrypted part---but a
> 	keybinding to review with decryption would be fine too---likely
> 	easier to code and easier to use.)

I agree it would definitely be better to have the redisplay happen from
inside the message show.  That would be much cleaner and more intuitive.
It will require a bit of work to add something like a "redisplay" in
notmuch-show, but I see no reason it can't be done.

>   * I can't actually get decryption to work for me. :-(
> 
> 	When I run "notmuch show --decrypt" on a message encrypted with
> 	my public key I get a segfault within libgmime, specifically in
> 	the g_mime_session_request_passwd function.

Yikes!

> 	My first guess is that this is due to the fact that gpg-agent
> 	can't be run on my system (Debian unstable):
> 
> 	$ gpg-agent
> 	gpg-agent: symbol lookup error: /usr/lib/libassuan.so.0: undefined symbol: gpg_err_set_errno
> 
> 	I've got a Debian bug report queued up for this.

hrm, that's very strange, unfortunately I'm not sure what's happening
there.  Bug in gpg-agent, I assume?

> 	I also tried running the same "notmuch show" command without
> 	gpg-agent installed. How is libgmime supposed to actually
> 	request a password in a case like this?

That's a good question, actually, and I don't actually know the answer.

Ok, so more release-candidate/0.6 patches to follow.

Thanks again for pushing all this stuff through, Carl.

jamie.

[-- Attachment #2: Type: application/pgp-signature, Size: 835 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: normalizing part numbering across PGP/MIME processing
  2011-05-28 21:31     ` Jameson Graef Rollins
@ 2011-06-03 21:34       ` Carl Worth
  0 siblings, 0 replies; 28+ messages in thread
From: Carl Worth @ 2011-06-03 21:34 UTC (permalink / raw)
  To: Jameson Graef Rollins, notmuch

[-- Attachment #1: Type: text/plain, Size: 1392 bytes --]

On Sat, 28 May 2011 14:31:08 -0700, Jameson Graef Rollins <jrollins@finestructure.net> wrote:
> On Fri, 27 May 2011 17:53:44 -0700, Carl Worth <cworth@cworth.org> wrote:
> >   * Should we set the crypto option to verify/decrypt by default?
...
> I don't really have an opinion on this.  I have it set now, so whether
> or not it's set by default doesn't make much difference to me.

I'm inclined to set it by default. But I'll wait until I get it fully
working, (which looks to be problems in my environment). See below.

> >   * I can't actually get decryption to work for me. :-(
> > 
> > 	When I run "notmuch show --decrypt" on a message encrypted with
> > 	my public key I get a segfault within libgmime, specifically in
> > 	the g_mime_session_request_passwd function.

I'm still getting this. I'll start debugging libgmime next.

> > 	$ gpg-agent
> > 	gpg-agent: symbol lookup error: /usr/lib/libassuan.so.0: undefined symbol: gpg_err_set_errno

That part I at least figured out. This behavior can be replicated (for me) with:

	LD_LIBRARY_PATH=/usr/lib gpg-agent

or:

	LD_LIBRARY_PATH=/usr/lib:/lib gpg-agent

And it goes away with:

	LD_LIBRARY_PATH=/lib:/usr/lib gpg-agent

It's still a mystifying bug in gpg-agent to me. But I've at least got my
environment to no longer trigger it, and I've opened a Debian bug report
for it at least.

-Carl

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH] Always return the empty string if decryption tries to demand a password
  2011-05-28  0:53   ` Carl Worth
  2011-05-28 21:31     ` Jameson Graef Rollins
@ 2011-06-03 23:03     ` Daniel Kahn Gillmor
  2011-06-03 23:15       ` Carl Worth
  1 sibling, 1 reply; 28+ messages in thread
From: Daniel Kahn Gillmor @ 2011-06-03 23:03 UTC (permalink / raw)
  To: notmuch; +Cc: Daniel Kahn Gillmor

The notmuch binary is not in the business of doing interactive
prompting with the user.  If credentials are needed for decryption,
they should be supplied to the decrypting processes some other way
(e.g. gpg-agent).

Previously, we returned a NULL function pointer for the
request_passwd() function, which may have cause segmentation faults
with some versions of gmime.
---
 notmuch-gmime-session.c |   17 ++++++++++++++++-
 1 files changed, 16 insertions(+), 1 deletions(-)

diff --git a/notmuch-gmime-session.c b/notmuch-gmime-session.c
index d83d9b3..33f2817 100644
--- a/notmuch-gmime-session.c
+++ b/notmuch-gmime-session.c
@@ -39,11 +39,26 @@ notmuch_gmime_session_get_type (void)
     return type;
 }
 
+/* 
+   notmuch never prompts the user for a password.  It always returns
+   an empty string (could it return a NULL pointer instead?)
+
+   If credentials are needed for crypto, they should be supplied via
+   other mechanisms (e.g. gpg-agent, etc)
+ */
+static char *never_request_passwd (unused (GMimeSession *session), unused (const char *prompt),
+				   unused (gboolean secret), unused (const char *item),
+				   unused (GError **err)) {
+    fprintf (stderr, "Credentials needed for crypto; Please use gpg-agent.\n");
+    return g_strdup ("");
+}
+
+
 static void
 notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass)
 {
     GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
     parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
-    session_class->request_passwd = NULL;
+    session_class->request_passwd = never_request_passwd;
 }
 /* END CRUFTY BOILERPLATE */
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH] Always return the empty string if decryption tries to demand a password
  2011-06-03 23:03     ` [PATCH] Always return the empty string if decryption tries to demand a password Daniel Kahn Gillmor
@ 2011-06-03 23:15       ` Carl Worth
  2011-06-03 23:37         ` Daniel Kahn Gillmor
  0 siblings, 1 reply; 28+ messages in thread
From: Carl Worth @ 2011-06-03 23:15 UTC (permalink / raw)
  To: Daniel Kahn Gillmor, notmuch; +Cc: Daniel Kahn Gillmor

[-- Attachment #1: Type: text/plain, Size: 696 bytes --]

On Fri,  3 Jun 2011 19:03:08 -0400, Daniel Kahn Gillmor <dkg@fifthhorseman.net> wrote:
> The notmuch binary is not in the business of doing interactive
> prompting with the user.  If credentials are needed for decryption,
> they should be supplied to the decrypting processes some other way
> (e.g. gpg-agent).
> 
> Previously, we returned a NULL function pointer for the
> request_passwd() function, which may have cause segmentation faults
> with some versions of gmime.

Cool. This fixes my segfaults, so thanks!

> +    return g_strdup ("");

Is the above correct? Or is it a memory leak? (If it's not a leak, then
GMime really has some bizarre ownership semantics.)

-Carl

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* Re: [PATCH] Always return the empty string if decryption tries to demand a password
  2011-06-03 23:15       ` Carl Worth
@ 2011-06-03 23:37         ` Daniel Kahn Gillmor
  2011-06-03 23:57           ` [PATCH] Use stock GMimeSession by default Daniel Kahn Gillmor
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Kahn Gillmor @ 2011-06-03 23:37 UTC (permalink / raw)
  To: notmuch

[-- Attachment #1: Type: text/plain, Size: 1354 bytes --]

On 06/03/2011 07:15 PM, Carl Worth wrote:
> On Fri,  3 Jun 2011 19:03:08 -0400, Daniel Kahn Gillmor <dkg@fifthhorseman.net> wrote:
>> The notmuch binary is not in the business of doing interactive
>> prompting with the user.  If credentials are needed for decryption,
>> they should be supplied to the decrypting processes some other way
>> (e.g. gpg-agent).
>>
>> Previously, we returned a NULL function pointer for the
>> request_passwd() function, which may have cause segmentation faults
>> with some versions of gmime.
> 
> Cool. This fixes my segfaults, so thanks!
> 
>> +    return g_strdup ("");
> 
> Is the above correct? Or is it a memory leak? (If it's not a leak, then
> GMime really has some bizarre ownership semantics.)

yes, this corner of gmime has some really bizarre ownership semantics;
twisty handoffs and callbacks abound :(

Hm, actually, we should just be returning NULL to indicate a failure; i
think that would be preferable, and apparently is documented to be
acceptable:

 http://developer.gnome.org/gmime/stable/GMimeSession.html#g-mime-session-request-passwd

Would you mind amending that patch to just return NULL ?

fwiw, i've just filed https://bugzilla.gnome.org/show_bug.cgi?id=651826
to ask gmime for a hook to let us always request the use of gpg-agent if
it is available.

	--dkg


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 1030 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH] Use stock GMimeSession by default
  2011-06-03 23:37         ` Daniel Kahn Gillmor
@ 2011-06-03 23:57           ` Daniel Kahn Gillmor
  2011-06-03 23:57             ` Daniel Kahn Gillmor
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Kahn Gillmor @ 2011-06-03 23:57 UTC (permalink / raw)
  To: notmuch


This patch supercedes my patch from
1307142188-6551-1-git-send-email-dkg@fifthhorseman.net , and provides
what appears to be a much cleaner approach to achieve the same result.

     --dkg

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [PATCH] Use stock GMimeSession by default
  2011-06-03 23:57           ` [PATCH] Use stock GMimeSession by default Daniel Kahn Gillmor
@ 2011-06-03 23:57             ` Daniel Kahn Gillmor
  2011-06-04  1:11               ` Carl Worth
  0 siblings, 1 reply; 28+ messages in thread
From: Daniel Kahn Gillmor @ 2011-06-03 23:57 UTC (permalink / raw)
  To: notmuch; +Cc: Daniel Kahn Gillmor

Our use of GMimeSession was unneeded boilerplate, and we weren't doing
anything with it.  This simplifies and clarifies that assumption.

If we want to do anything fancier later, the examples in the gmime
source are a reasonable source to work from in defining a new
GMimeSession derivative.

Since GMimeSession is going away in GMime 2.6, though, i don't
recommend using it.
---
 Makefile.local          |    1 -
 notmuch-client.h        |    3 --
 notmuch-gmime-session.c |   49 -----------------------------------------------
 notmuch-reply.c         |    2 +-
 notmuch-show.c          |    2 +-
 5 files changed, 2 insertions(+), 55 deletions(-)
 delete mode 100644 notmuch-gmime-session.c

diff --git a/Makefile.local b/Makefile.local
index f726f1f..8a8832d 100644
--- a/Makefile.local
+++ b/Makefile.local
@@ -246,7 +246,6 @@ notmuch_client_srcs =		\
 	notmuch-show.c		\
 	notmuch-tag.c		\
 	notmuch-time.c		\
-	notmuch-gmime-session.c \
 	query-string.c		\
 	show-message.c		\
 	json.c			\
diff --git a/notmuch-client.h b/notmuch-client.h
index 8a27260..63be337 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -237,7 +237,4 @@ notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
 notmuch_bool_t
 debugger_is_active (void);
 
-GType
-notmuch_gmime_session_get_type (void);
-
 #endif
diff --git a/notmuch-gmime-session.c b/notmuch-gmime-session.c
deleted file mode 100644
index d83d9b3..0000000
--- a/notmuch-gmime-session.c
+++ /dev/null
@@ -1,49 +0,0 @@
-#include "notmuch-client.h"
-
-/* CRUFTY BOILERPLATE for GMimeSession (dkg thinks this will go away once GMime 2.6 comes out) */
-typedef struct _NotmuchGmimeSession NotmuchGmimeSession;
-typedef struct _NotmuchGmimeSessionClass NotmuchGmimeSessionClass;
-
-struct _NotmuchGmimeSession {
-    GMimeSession parent_object;
-};
-
-struct _NotmuchGmimeSessionClass {
-    GMimeSessionClass parent_class;
-};
-
-static void notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass);
-
-static GMimeSessionClass *parent_class = NULL;
-
-GType
-notmuch_gmime_session_get_type (void)
-{
-    static GType type = 0;
-
-    if (!type) {
-	static const GTypeInfo info = {
-	    sizeof (NotmuchGmimeSessionClass),
-	    NULL, /* base_class_init */
-	    NULL, /* base_class_finalize */
-	    (GClassInitFunc) notmuch_gmime_session_class_init,
-	    NULL, /* class_finalize */
-	    NULL, /* class_data */
-	    sizeof (NotmuchGmimeSession),
-	    0,    /* n_preallocs */
-	    NULL, /* object_init */
-	    NULL, /* value_table */
-	};
-	type = g_type_register_static (GMIME_TYPE_SESSION, "NotmuchGmimeSession", &info, 0);
-    }
-    return type;
-}
-
-static void
-notmuch_gmime_session_class_init (NotmuchGmimeSessionClass *klass)
-{
-    GMimeSessionClass *session_class = GMIME_SESSION_CLASS (klass);
-    parent_class = g_type_class_ref (GMIME_TYPE_SESSION);
-    session_class->request_passwd = NULL;
-}
-/* END CRUFTY BOILERPLATE */
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 5265af6..514bbc6 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -607,7 +607,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
 	    }
 	} else if ((STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) {
 	    if (params.cryptoctx == NULL) {
-		GMimeSession* session = g_object_new(notmuch_gmime_session_get_type(), NULL);
+		GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL);
 		if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg")))
 		    fprintf (stderr, "Failed to construct gpg context.\n");
 		else
diff --git a/notmuch-show.c b/notmuch-show.c
index 9267d02..dda83a1 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -899,7 +899,7 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
 	} else if ((STRNCMP_LITERAL (argv[i], "--verify") == 0) ||
 		   (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)) {
 	    if (params.cryptoctx == NULL) {
-		GMimeSession* session = g_object_new(notmuch_gmime_session_get_type(), NULL);
+		GMimeSession* session = g_object_new(g_mime_session_get_type(), NULL);
 		if (NULL == (params.cryptoctx = g_mime_gpg_context_new(session, "gpg")))
 		    fprintf (stderr, "Failed to construct gpg context.\n");
 		else
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* Re: [PATCH] Use stock GMimeSession by default
  2011-06-03 23:57             ` Daniel Kahn Gillmor
@ 2011-06-04  1:11               ` Carl Worth
  0 siblings, 0 replies; 28+ messages in thread
From: Carl Worth @ 2011-06-04  1:11 UTC (permalink / raw)
  To: Daniel Kahn Gillmor, notmuch; +Cc: Daniel Kahn Gillmor

[-- Attachment #1: Type: text/plain, Size: 267 bytes --]

On Fri,  3 Jun 2011 19:57:46 -0400, Daniel Kahn Gillmor <dkg@fifthhorseman.net> wrote:
> Our use of GMimeSession was unneeded boilerplate, and we weren't doing
> anything with it.  This simplifies and clarifies that assumption.

Very nice. This is pushed now.

-Carl

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2011-06-04  1:11 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-26  1:01 New crypto patch series Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 01/11] Simplify reply_part function to eliminate redundant code paths Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 02/11] Integrate reply_part_content function into reply_part function Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 03/11] Use empty strings instead of NULL in format_reply structure Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 04/11] Break up format->part function into part_start and part_content functions Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 05/11] test: new test-lib function to test for equality between files Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 06/11] test: add notmuch_show_sanitize_all function that is a little more aggressive Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 07/11] test: add crypto tests for signature verification and decryption Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 08/11] Add signature verification of PGP/MIME-signed parts with --verify Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 09/11] Add decryption of PGP/MIME-encrypted parts with --decrypt Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 10/11] emacs: Add support for PGP/MIME verification/decryption Jameson Graef Rollins
2011-05-26  1:01 ` [PATCH 11/11] tag signed/encrypted during notmuch new Jameson Graef Rollins
2011-05-27 10:27 ` normalizing part numbering across PGP/MIME processing Jameson Graef Rollins
2011-05-27 10:27   ` [PATCH 1/4] Do not replace multipart/signed part with content part when doing verification Jameson Graef Rollins
2011-05-27 10:27     ` [PATCH 2/4] Render all parts of multipart/encrypted when decrypting Jameson Graef Rollins
2011-05-27 10:27       ` [PATCH 3/4] emacs: Do not attempt to render arbitrary application parts Jameson Graef Rollins
2011-05-27 10:27         ` [PATCH 4/4] emacs: Give mutlipart/{signed, encrypted} their own part handler Jameson Graef Rollins
2011-05-27 18:52           ` [PATCH] " Jameson Graef Rollins
2011-05-27 18:34   ` normalizing part numbering across PGP/MIME processing Daniel Kahn Gillmor
2011-05-28  0:53   ` Carl Worth
2011-05-28 21:31     ` Jameson Graef Rollins
2011-06-03 21:34       ` Carl Worth
2011-06-03 23:03     ` [PATCH] Always return the empty string if decryption tries to demand a password Daniel Kahn Gillmor
2011-06-03 23:15       ` Carl Worth
2011-06-03 23:37         ` Daniel Kahn Gillmor
2011-06-03 23:57           ` [PATCH] Use stock GMimeSession by default Daniel Kahn Gillmor
2011-06-03 23:57             ` Daniel Kahn Gillmor
2011-06-04  1:11               ` Carl Worth

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).