]> git.notmuchmail.org Git - notmuch/blobdiff - notmuch-show.c
Reduce some excessive indentation.
[notmuch] / notmuch-show.c
index 363cdbfed7760207d30516e89cc1e8d158c043a1..b9a41cc653e4bab6f277e85d7d9d173a33711b7f 100644 (file)
@@ -44,6 +44,8 @@ static const notmuch_show_format_t format_text = {
            "\fheader{\n", format_headers_text, "\fheader}\n",
            "\fbody{\n",
                format_part_start_text,
+               NULL,
+               NULL,
                format_part_content_text,
                format_part_end_text,
                "",
@@ -64,6 +66,12 @@ static void
 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
 format_part_content_json (GMimeObject *part);
 
@@ -76,6 +84,8 @@ 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,
                ", ",
@@ -94,6 +104,8 @@ static const notmuch_show_format_t format_mbox = {
         "", format_message_mbox,
             "", NULL, "",
             "",
+                NULL,
+                NULL,
                 NULL,
                 NULL,
                 NULL,
@@ -111,6 +123,8 @@ static const notmuch_show_format_t format_raw = {
        "", NULL,
            "", NULL, "",
             "",
+                NULL,
+                NULL,
                 NULL,
                 format_part_content_raw,
                 NULL,
@@ -360,33 +374,42 @@ format_headers_json (const void *ctx, notmuch_message_t *message)
     talloc_free (ctx_quote);
 }
 
+/* Write a MIME text part out to the given stream.
+ *
+ * Both line-ending conversion (CRLF->LF) and charset conversion ( ->
+ * UTF-8) will be performed, so it is inappropriate to call this
+ * function with a non-text part. Doing so will trigger an internal
+ * error.
+ */
 static void
-show_part_content (GMimeObject *part, GMimeStream *stream_out)
+show_text_part_content (GMimeObject *part, GMimeStream *stream_out)
 {
+    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));
     GMimeStream *stream_filter = NULL;
     GMimeDataWrapper *wrapper;
     const char *charset;
 
-    /* do nothing if this is a multipart */
-    if (GMIME_IS_MULTIPART (part) || GMIME_IS_MESSAGE_PART (part))
+    if (! g_mime_content_type_is_type (content_type, "text", "*"))
+       INTERNAL_ERROR ("Illegal request to format non-text part (%s) as text.",
+                       g_mime_content_type_to_string (content_type));
+
+    if (stream_out == NULL)
        return;
 
-    charset = g_mime_object_get_content_type_parameter (part, "charset");
+    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 (stream_out) {
-       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) {
-           GMimeFilter *charset_filter;
-           charset_filter = g_mime_filter_charset_new (charset, "UTF-8");
-           /* This result can be NULL for things like "unknown-8bit".
-            * Don't set a NULL filter as that makes GMime print
-            * annoying assertion-failure messages on stderr. */
-           if (charset_filter)
-               g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter),
-                                         charset_filter);
-       }
+    charset = g_mime_object_get_content_type_parameter (part, "charset");
+    if (charset) {
+       GMimeFilter *charset_filter;
+       charset_filter = g_mime_filter_charset_new (charset, "UTF-8");
+       /* This result can be NULL for things like "unknown-8bit".
+        * Don't set a NULL filter as that makes GMime print
+        * annoying assertion-failure messages on stderr. */
+       if (charset_filter)
+           g_mime_stream_filter_add (GMIME_STREAM_FILTER (stream_filter),
+                                     charset_filter);
     }
 
     wrapper = g_mime_part_get_content_object (GMIME_PART (part));
@@ -396,6 +419,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)
 {
@@ -433,7 +472,7 @@ format_part_content_text (GMimeObject *part)
        !g_mime_content_type_is_type (content_type, "text", "html"))
     {
        g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream_stdout), FALSE);
-       show_part_content (part, stream_stdout);
+       show_text_part_content (part, stream_stdout);
        g_object_unref(stream_stdout);
     }
     else if (g_mime_content_type_is_type (content_type, "multipart", "*") ||
@@ -472,6 +511,77 @@ format_part_start_json (unused (GMimeObject *part), int *part_count)
     printf ("{\"id\": %d", *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\": [");
+
+    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)
 {
@@ -499,7 +609,7 @@ format_part_content_json (GMimeObject *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, stream_memory);
+       show_text_part_content (part, stream_memory);
        part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory));
 
        printf (", \"content\": %s", json_quote_chararray (ctx, (char *) part_content->data, part_content->len));
@@ -532,10 +642,25 @@ format_part_end_json (GMimeObject *part)
 static void
 format_part_content_raw (GMimeObject *part)
 {
-    GMimeStream *stream_stdout = g_mime_stream_file_new (stdout);
+    GMimeStream *stream_stdout;
+    GMimeStream *stream_filter = NULL;
+    GMimeDataWrapper *wrapper;
+
+    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);
+
+    stream_filter = g_mime_stream_filter_new (stream_stdout);
+
+    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
@@ -739,6 +864,8 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
     params.entire_thread = 0;
     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) {
@@ -767,6 +894,19 @@ 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) ||
+                  (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;
+           }
+           if (STRNCMP_LITERAL (argv[i], "--decrypt") == 0)
+               params.decrypt = 1;
        } else {
            fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
            return 1;
@@ -824,5 +964,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;
 }