[notmuch] [PATCH] initial proof of concept patch to output a message in json

david at tethera.net david at tethera.net
Sun Dec 13 15:31:11 PST 2009


From: David Bremner <bremner at unb.ca>

---

Like I said in the apology/introduction, I don't claim this patch is
ready for the master branch; hence the complete lack of sensible
commit message.  But it does give some idea about what would be
required. In particular definitely more things will have to be passed
around.

 configure        |    2 +-
 notmuch-client.h |    2 +-
 notmuch-reply.c  |    4 +-
 notmuch-show.c   |  110 ++++++++++++++++++++++++++---------------------------
 show-message.c   |   12 +++---
 5 files changed, 64 insertions(+), 66 deletions(-)

diff --git a/configure b/configure
index fa8e142..34587a5 100755
--- a/configure
+++ b/configure
@@ -291,5 +291,5 @@ CONFIGURE_CFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)      \\
 CONFIGURE_CXXFLAGS = -DHAVE_GETLINE=\$(HAVE_GETLINE) \$(GMIME_CFLAGS)    \\
 		     \$(TALLOC_CFLAGS) -DHAVE_VALGRIND=\$(HAVE_VALGRIND) \\
 		     \$(VALGRIND_CFLAGS) \$(XAPIAN_CXXFLAGS)
-CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS)
+CONFIGURE_LDFLAGS =  \$(GMIME_LDFLAGS) \$(TALLOC_LDFLAGS) \$(XAPIAN_LDFLAGS) -ljansson
 EOF
diff --git a/notmuch-client.h b/notmuch-client.h
index 50a30fe..6600ed4 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -141,7 +141,7 @@ query_string_from_args (void *ctx, int argc, char *argv[]);
 
 notmuch_status_t
 show_message_body (const char *filename,
-		   void (*show_part) (GMimeObject *part, int *part_count));
+		   void (*show_part) (GMimeObject *part, int *part_count, void *arg), void *output);
 
 /* notmuch-config.c */
 
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 0cda72d..29a6517 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -63,7 +63,7 @@ reply_part_content (GMimeObject *part)
 }
 
 static void
-reply_part (GMimeObject *part, int *part_count)
+reply_part (GMimeObject *part, int *part_count, unused(void *arg))
 {
     GMimeContentDisposition *disposition;
     GMimeContentType *content_type;
@@ -282,7 +282,7 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_
 		notmuch_message_get_header (message, "date"),
 		notmuch_message_get_header (message, "from"));
 
-	show_message_body (notmuch_message_get_filename (message), reply_part);
+	show_message_body (notmuch_message_get_filename (message), reply_part,NULL);
 
 	notmuch_message_destroy (message);
     }
diff --git a/notmuch-show.c b/notmuch-show.c
index 376aacd..4f00675 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -18,8 +18,11 @@
  * Author: Carl Worth <cworth at cworth.org>
  */
 
+#include <jansson.h>
 #include "notmuch-client.h"
 
+json_t *show_part_content (GMimeObject *part);
+
 static const char *
 _get_tags_as_string (void *ctx, notmuch_message_t *message)
 {
@@ -66,19 +69,23 @@ _get_one_line_summary (void *ctx, notmuch_message_t *message)
 			    from, relative_date, tags);
 }
 
-static void
+json_t *
 show_part_content (GMimeObject *part)
 {
-    GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
+    GMimeStream *stream_out = g_mime_stream_mem_new ();
     GMimeStream *stream_filter = NULL;
     GMimeDataWrapper *wrapper;
+    GByteArray *content_data;
+
+    guint8 terminator[]={0};
     const char *charset;
+    json_t *content;
 
     charset = g_mime_object_get_content_type_parameter (part, "charset");
-
-    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 (stream_out) {
+	g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_out), FALSE);
+	stream_filter = g_mime_stream_filter_new(stream_out);
 	g_mime_stream_filter_add(GMIME_STREAM_FILTER(stream_filter),
 				 g_mime_filter_crlf_new(FALSE, FALSE));
         if (charset) {
@@ -90,60 +97,50 @@ show_part_content (GMimeObject *part)
     wrapper = g_mime_part_get_content_object (GMIME_PART (part));
     if (wrapper && stream_filter)
 	g_mime_data_wrapper_write_to_stream (wrapper, stream_filter);
+
+    content_data = g_mime_stream_mem_get_byte_array ((GMimeStreamMem *)stream_out);
+    g_byte_array_append(content_data, terminator,1);
+    content = json_string (content_data->data);
     if (stream_filter)
 	g_object_unref(stream_filter);
-    if (stream_stdout)
-	g_object_unref(stream_stdout);
+    if (stream_out)
+	g_object_unref(stream_out);
+    
+    return content;
 }
 
 static void
-show_part (GMimeObject *part, int *part_count)
+show_part (GMimeObject *part, int *part_count, void *output_arg)
 {
     GMimeContentDisposition *disposition;
     GMimeContentType *content_type;
+    json_t *output = output_arg;
+    json_t *part_obj=json_object();
 
     disposition = g_mime_object_get_content_disposition (part);
+    content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
+
+    json_object_set (part_obj, "id", json_integer (*part_count));
+    json_object_set (part_obj, "content-type", 
+		     json_string(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));
-	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));
-
-	if (g_mime_content_type_is_type (content_type, "text", "*") &&
-	    !g_mime_content_type_is_type (content_type, "text", "html"))
-	{
-	    show_part_content (part);
-	}
+    	const char *filename = g_mime_part_get_filename (GMIME_PART (part));
 
-	printf ("\fattachment}\n");
+	json_object_set (part_obj, "filename", 
+			 json_string (filename));
 
-	return;
-    }
+    };
 
-    content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
 
-    printf ("\fpart{ ID: %d, Content-type: %s\n",
-	    *part_count,
-	    g_mime_content_type_to_string (content_type));
+    if (g_mime_content_type_is_type (content_type, "text", "*"))
+	json_object_set (part_obj, "text", show_part_content (part));
+	
 
-    if (g_mime_content_type_is_type (content_type, "text", "*") &&
-	!g_mime_content_type_is_type (content_type, "text", "html"))
-    {
-	show_part_content (part);
-    }
-    else
-    {
-	printf ("Non-text part: %s\n",
-		g_mime_content_type_to_string (content_type));
-    }
+    json_array_append(output,part_obj);
 
-    printf ("\fpart}\n");
 }
 
 static void
@@ -154,32 +151,33 @@ show_message (void *ctx, notmuch_message_t *message, int indent)
     };
     const char *name, *value;
     unsigned int i;
+    json_t *message_obj=json_object();
+    json_t *header_obj=json_object();
+    json_t *parts=json_array();
 
-    printf ("\fmessage{ id:%s depth:%d match:%d filename:%s\n",
-	    notmuch_message_get_message_id (message),
-	    indent,
-	    notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH),
-	    notmuch_message_get_filename (message));
+    // all of these calls need return-value checking
+    json_object_set(message_obj,"id",json_string (notmuch_message_get_message_id (message)));
+    json_object_set(message_obj,"depth",json_integer (indent));
+    json_object_set(message_obj,"match",
+		    notmuch_message_get_flag (message, NOTMUCH_MESSAGE_FLAG_MATCH) ? json_true() : json_false());
+    json_object_set(message_obj,"filename",json_string (notmuch_message_get_filename (message)));
 
-    printf ("\fheader{\n");
-
-    printf ("%s\n", _get_one_line_summary (ctx, message));
+    json_object_set(header_obj,"summary", json_string (_get_one_line_summary (ctx, message)));
 
     for (i = 0; i < ARRAY_SIZE (headers); i++) {
 	name = headers[i];
 	value = notmuch_message_get_header (message, name);
 	if (value)
-	    printf ("%s: %s\n", name, value);
+	  json_object_set (header_obj, name, json_string (value));
     }
 
-    printf ("\fheader}\n");
-    printf ("\fbody{\n");
-
-    show_message_body (notmuch_message_get_filename (message), show_part);
+    json_object_set (message_obj, "header", header_obj);
 
-    printf ("\fbody}\n");
+    show_message_body (notmuch_message_get_filename (message), show_part, parts);
+    
+    json_object_set (message_obj, "parts", parts);
+    json_dumpf(message_obj,stdout,JSON_INDENT(4));
 
-    printf ("\fmessage}\n");
 }
 
 
diff --git a/show-message.c b/show-message.c
index 784981b..e41f51c 100644
--- a/show-message.c
+++ b/show-message.c
@@ -24,7 +24,7 @@
 
 static void
 show_message_part (GMimeObject *part, int *part_count,
-		   void (*show_part) (GMimeObject *part, int *part_count))
+		   void (*show_part) (GMimeObject *part, int *part_count, void *argument), void *output)
 {
     *part_count = *part_count + 1;
 
@@ -34,7 +34,7 @@ show_message_part (GMimeObject *part, int *part_count,
 
 	for (i = 0; i < g_mime_multipart_get_count (multipart); i++) {
 	    show_message_part (g_mime_multipart_get_part (multipart, i),
-			       part_count, show_part);
+			       part_count, show_part, output);
 	}
 	return;
     }
@@ -45,7 +45,7 @@ show_message_part (GMimeObject *part, int *part_count,
 	mime_message = g_mime_message_part_get_message (GMIME_MESSAGE_PART (part));
 
 	show_message_part (g_mime_message_get_mime_part (mime_message),
-			   part_count, show_part);
+			   part_count, show_part, output);
 
 	return;
     }
@@ -56,12 +56,12 @@ show_message_part (GMimeObject *part, int *part_count,
 	return;
     }
 
-    (*show_part) (part, part_count);
+    (*show_part) (part, part_count, output);
 }
 
 notmuch_status_t
 show_message_body (const char *filename,
-		   void (*show_part) (GMimeObject *part, int *part_count))
+		   void (*show_part) (GMimeObject *part, int *part_count, void *argument), void *output)
 {
     GMimeStream *stream = NULL;
     GMimeParser *parser = NULL;
@@ -85,7 +85,7 @@ show_message_body (const char *filename,
     mime_message = g_mime_parser_construct_message (parser);
 
     show_message_part (g_mime_message_get_mime_part (mime_message),
-		       &part_count, show_part);
+		       &part_count, show_part, output);
 
   DONE:
     if (mime_message)
-- 
1.6.5.3



More information about the notmuch mailing list