static int notmuch_reply_format_sprinter(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params, notmuch_bool_t reply_all, sprinter_t *sp) { GMimeMessage *reply; notmuch_messages_t *messages; notmuch_message_t *message; mime_node_t *node; unsigned count; notmuch_status_t status; status = notmuch_query_count_messages_st (query, &count); if (print_status_query ("notmuch reply", query, status)) return 1; if (count != 1) { fprintf (stderr, "Error: search term did not match precisely one message.\n"); return 1; } status = notmuch_query_search_messages_st (query, &messages); if (print_status_query ("notmuch reply", query, status)) return 1; message = notmuch_messages_get (messages); if (mime_node_open (ctx, message, &(params->crypto), &node) != NOTMUCH_STATUS_SUCCESS) return 1; reply = create_reply_message (ctx, config, message, reply_all); if (!reply) return 1; sp->begin_map (sp); /* The headers of the reply message we've created */ sp->map_key (sp, "reply-headers"); format_headers_sprinter (sp, reply, TRUE); g_object_unref (G_OBJECT (reply)); reply = NULL; /* Start the original */ sp->map_key (sp, "original"); format_part_sprinter (ctx, sp, node, TRUE, TRUE, FALSE); /* End */ sp->end (sp); notmuch_message_destroy (message); return 0; }
void format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node, notmuch_bool_t first, notmuch_bool_t output_body, notmuch_bool_t include_html) { /* Any changes to the JSON or S-Expression format should be * reflected in the file devel/schemata. */ if (node->envelope_file) { sp->begin_map (sp); format_message_sprinter (sp, node->envelope_file); sp->map_key (sp, "headers"); format_headers_sprinter (sp, GMIME_MESSAGE (node->part), FALSE); if (output_body) { sp->map_key (sp, "body"); sp->begin_list (sp); format_part_sprinter (ctx, sp, mime_node_child (node, 0), first, TRUE, include_html); sp->end (sp); } sp->end (sp); return; } /* The disposition and content-type metadata are associated with * the envelope for message parts */ GMimeObject *meta = node->envelope_part ? GMIME_OBJECT (node->envelope_part) : node->part; GMimeContentType *content_type = g_mime_object_get_content_type (meta); const char *cid = g_mime_object_get_content_id (meta); const char *filename = GMIME_IS_PART (node->part) ? g_mime_part_get_filename (GMIME_PART (node->part)) : NULL; int nclose = 0; int i; sp->begin_map (sp); sp->map_key (sp, "id"); sp->integer (sp, node->part_num); if (node->decrypt_attempted) { sp->map_key (sp, "encstatus"); sp->begin_list (sp); sp->begin_map (sp); sp->map_key (sp, "status"); sp->string (sp, node->decrypt_success ? "good" : "bad"); sp->end (sp); sp->end (sp); } if (node->verify_attempted) { sp->map_key (sp, "sigstatus"); format_part_sigstatus_sprinter (sp, node); } sp->map_key (sp, "content-type"); sp->string (sp, g_mime_content_type_to_string (content_type)); if (cid) { sp->map_key (sp, "content-id"); sp->string (sp, cid); } if (filename) { sp->map_key (sp, "filename"); sp->string (sp, filename); } if (GMIME_IS_PART (node->part)) { /* For non-HTML text parts, we include the content in the * JSON. Since JSON must be Unicode, we handle charset * decoding here and do not report a charset to the caller. * For text/html parts, we do not include the content unless * the --include-html option has been passed. If a html part * is not included, it can be requested directly. This makes * charset decoding the responsibility on the caller so we * report the charset for text/html parts. */ if (g_mime_content_type_is_type (content_type, "text", "*") && (include_html || ! g_mime_content_type_is_type (content_type, "text", "html"))) { GMimeStream *stream_memory = g_mime_stream_mem_new (); GByteArray *part_content; show_text_part_content (node->part, stream_memory, 0); part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory)); sp->map_key (sp, "content"); sp->string_len (sp, (char *) part_content->data, part_content->len); g_object_unref (stream_memory); } else { format_omitted_part_meta_sprinter (sp, meta, GMIME_PART (node->part)); } } else if (GMIME_IS_MULTIPART (node->part)) { sp->map_key (sp, "content"); sp->begin_list (sp); nclose = 1; } else if (GMIME_IS_MESSAGE (node->part)) { sp->map_key (sp, "content"); sp->begin_list (sp); sp->begin_map (sp); sp->map_key (sp, "headers"); format_headers_sprinter (sp, GMIME_MESSAGE (node->part), FALSE); sp->map_key (sp, "body"); sp->begin_list (sp); nclose = 3; } for (i = 0; i < node->nchildren; i++) format_part_sprinter (ctx, sp, mime_node_child (node, i), i == 0, TRUE, include_html); /* Close content structures */ for (i = 0; i < nclose; i++) sp->end (sp); /* Close part map */ sp->end (sp); }