From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 75E29431FBC for ; Sun, 13 Dec 2009 15:31:26 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id p-ng2RJCiUhY for ; Sun, 13 Dec 2009 15:31:25 -0800 (PST) Received: from pivot.cs.unb.ca (pivot.cs.unb.ca [131.202.240.57]) by olra.theworths.org (Postfix) with ESMTP id 04CB2431FAE for ; Sun, 13 Dec 2009 15:31:25 -0800 (PST) Received: from fctnnbsc30w-142167182194.pppoe-dynamic.high-speed.nb.bellaliant.net ([142.167.182.194] helo=localhost) by pivot.cs.unb.ca with esmtpsa (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1NJxuO-00061k-5h; Sun, 13 Dec 2009 19:31:24 -0400 Received: from bremner by localhost with local (Exim 4.69) (envelope-from ) id 1NJxuI-0001Du-C1; Sun, 13 Dec 2009 19:31:18 -0400 From: david@tethera.net To: notmuch@notmuchmail.org Date: Sun, 13 Dec 2009 19:31:11 -0400 Message-Id: <1260747071-4656-1-git-send-email-david@tethera.net> X-Mailer: git-send-email 1.6.5.3 X-Sender-Verified: bremner@pivot.cs.unb.ca Cc: David Bremner Subject: [PATCH] initial proof of concept patch to output a message in json X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 13 Dec 2009 23:31:26 -0000 From: David Bremner --- 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 */ +#include #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