+ GMimeSignatureList *siglist = node->sig_list;
+
+ sp->begin_list (sp);
+
+ if (!siglist) {
+ sp->end (sp);
+ return;
+ }
+
+ int i;
+ for (i = 0; i < g_mime_signature_list_length (siglist); i++) {
+ GMimeSignature *signature = g_mime_signature_list_get_signature (siglist, i);
+
+ sp->begin_map (sp);
+
+ /* status */
+ GMimeSignatureStatus status = g_mime_signature_get_status (signature);
+ sp->map_key (sp, "status");
+ sp->string (sp, signature_status_to_string (status));
+
+ GMimeCertificate *certificate = g_mime_signature_get_certificate (signature);
+ if (status == GMIME_SIGNATURE_STATUS_GOOD) {
+ if (certificate) {
+ sp->map_key (sp, "fingerprint");
+ sp->string (sp, g_mime_certificate_get_fingerprint (certificate));
+ }
+ /* these dates are seconds since the epoch; should we
+ * provide a more human-readable format string? */
+ time_t created = g_mime_signature_get_created (signature);
+ if (created != -1) {
+ sp->map_key (sp, "created");
+ sp->integer (sp, created);
+ }
+ time_t expires = g_mime_signature_get_expires (signature);
+ if (expires > 0) {
+ sp->map_key (sp, "expires");
+ sp->integer (sp, 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 (certificate) {
+ const char *name = g_mime_certificate_get_name (certificate);
+ GMimeCertificateTrust trust = g_mime_certificate_get_trust (certificate);
+ if (name && (trust == GMIME_CERTIFICATE_TRUST_FULLY || trust == GMIME_CERTIFICATE_TRUST_ULTIMATE)) {
+ sp->map_key (sp, "userid");
+ sp->string (sp, name);
+ }
+ }
+ } else if (certificate) {
+ const char *key_id = g_mime_certificate_get_key_id (certificate);
+ if (key_id) {
+ sp->map_key (sp, "keyid");
+ sp->string (sp, key_id);
+ }
+ }
+
+ GMimeSignatureError errors = g_mime_signature_get_errors (signature);
+ if (errors != GMIME_SIGNATURE_ERROR_NONE) {
+ sp->map_key (sp, "errors");
+ sp->integer (sp, errors);
+ }
+
+ sp->end (sp);
+ }
+
+ sp->end (sp);
+}
+
+#else /* GMIME_ATLEAST_26 */
+
+/* Get signature status string (GMime 2.4) */
+static const char*
+signer_status_to_string (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";
+}
+
+/* Signature status sprinter (GMime 2.4) */
+static void
+format_part_sigstatus_sprinter (sprinter_t *sp, mime_node_t *node)
+{
+ const GMimeSignatureValidity* validity = node->sig_validity;
+
+ sp->begin_list (sp);
+
+ if (!validity) {
+ sp->end (sp);
+ return;
+ }
+
+ const GMimeSigner *signer = g_mime_signature_validity_get_signers (validity);
+ while (signer) {
+ sp->begin_map (sp);
+
+ /* status */
+ sp->map_key (sp, "status");
+ sp->string (sp, signer_status_to_string (signer->status));
+
+ if (signer->status == GMIME_SIGNER_STATUS_GOOD)
+ {
+ if (signer->fingerprint) {
+ sp->map_key (sp, "fingerprint");
+ sp->string (sp, signer->fingerprint);
+ }
+ /* these dates are seconds since the epoch; should we
+ * provide a more human-readable format string? */
+ if (signer->created) {
+ sp->map_key (sp, "created");
+ sp->integer (sp, signer->created);
+ }
+ if (signer->expires) {
+ sp->map_key (sp, "expires");
+ sp->integer (sp, 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)) {
+ sp->map_key (sp, "userid");
+ sp->string (sp, signer->name);
+ }
+ }
+ } else {
+ if (signer->keyid) {
+ sp->map_key (sp, "keyid");
+ sp->string (sp, signer->keyid);
+ }
+ }
+ if (signer->errors != GMIME_SIGNER_ERROR_NONE) {
+ sp->map_key (sp, "errors");
+ sp->integer (sp, signer->errors);
+ }
+
+ sp->end (sp);
+ signer = signer->next;
+ }
+
+ sp->end (sp);
+}
+
+#endif /* GMIME_ATLEAST_26 */
+
+static notmuch_status_t
+format_part_text (const void *ctx, sprinter_t *sp, mime_node_t *node,
+ int indent, const notmuch_show_params_t *params)
+{
+ /* 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 notmuch_bool_t leaf = GMIME_IS_PART (node->part);
+ const char *part_type;
+ int i;