diff --git a/devel/schemata b/devel/schemata index 72feb7b7..28332c6b 100644 --- a/devel/schemata +++ b/devel/schemata @@ -4,9 +4,9 @@ format (currently JSON and S-Expressions). []'s indicate lists. List items can be marked with a '?', meaning they are optional; or a '*', meaning there can be zero or more of that item. {}'s indicate an object that maps from field identifiers to -values. An object field marked '?' is optional. |'s indicate -alternates (e.g., int|string means something can be an int or a -string). +values. An object field marked '?' is optional; one marked with '*' +can repeat (with a different name). |'s indicate alternates (e.g., +int|string means something can be an int or a string). For S-Expression output, lists are printed delimited by () instead of []. Objects are printed as p-lists, i.e. lists where the keys and values @@ -48,6 +48,9 @@ threadid = string # Message ID, sans "id:" messageid = string +# E-mail header name, sans trailing colon, like "Subject" or "In-Reply-To" +header_name = string + notmuch show schema ------------------- @@ -88,9 +91,15 @@ crypto = { status: sigstatus, # was the set of signatures described under encrypted cover? encrypted: bool, + # which of the headers is covered by sigstatus? + headers: [header_name*] }, decrypted?: { status: msgdecstatus, + # map encrypted headers that differed from the outside headers. + # the value of each item in the map is what that field showed externally + # (maybe null if it was not present in the external headers). + header-mask: { header_name*: string|null } } } diff --git a/notmuch-show.c b/notmuch-show.c index b1f6a4bb..4dfe9c1d 100644 --- a/notmuch-show.c +++ b/notmuch-show.c @@ -645,6 +645,12 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node, sp->map_key (sp, "encrypted"); sp->boolean (sp, msg_crypto->signature_encrypted); } + if (msg_crypto->payload_subject) { + sp->map_key (sp, "headers"); + sp->begin_list (sp); + sp->string (sp, "Subject"); + sp->end (sp); + } sp->end (sp); } if (msg_crypto->decryption_status != NOTMUCH_MESSAGE_DECRYPTED_NONE) { @@ -652,6 +658,21 @@ format_part_sprinter (const void *ctx, sprinter_t *sp, mime_node_t *node, sp->begin_map (sp); sp->map_key (sp, "status"); sp->string (sp, msg_crypto->decryption_status == NOTMUCH_MESSAGE_DECRYPTED_FULL ? "full" : "partial"); + + if (msg_crypto->payload_subject) { + const char *subject = g_mime_message_get_subject GMIME_MESSAGE (node->part); + if (subject == NULL || strcmp (subject, msg_crypto->payload_subject)) { + /* protected subject differs from the external header */ + sp->map_key (sp, "header-mask"); + sp->begin_map (sp); + sp->map_key (sp, "Subject"); + if (subject == NULL) + sp->null (sp); + else + sp->string (sp, subject); + sp->end (sp); + } + } sp->end (sp); } } diff --git a/test/T356-protected-headers.sh b/test/T356-protected-headers.sh index 8a8fef6a..68d431e9 100755 --- a/test/T356-protected-headers.sh +++ b/test/T356-protected-headers.sh @@ -22,7 +22,7 @@ test_json_nodes <<<"$output" \ test_begin_subtest "verify protected header is visible with decryption" output=$(notmuch show --decrypt=true --format=json id:protected-header@crypto.notmuchmail.org) test_json_nodes <<<"$output" \ - 'crypto:[0][0][0]["crypto"]={"decrypted": {"status": "full"}}' \ + 'crypto:[0][0][0]["crypto"]={"decrypted": {"status": "full", "header-mask": {"Subject": "Subject Unavailable"}}}' \ 'subject:[0][0][0]["headers"]["Subject"]="This is a protected header"' test_begin_subtest "misplaced protected headers should not be made visible during decryption" @@ -58,7 +58,7 @@ test_json_nodes <<<"$output" \ test_begin_subtest "verify nested message/rfc822 protected header is visible" output=$(notmuch show --decrypt=true --format=json id:nested-rfc822-message@crypto.notmuchmail.org) test_json_nodes <<<"$output" \ - 'crypto:[0][0][0]["crypto"]={"decrypted": {"status": "full"}}' \ + 'crypto:[0][0][0]["crypto"]={"decrypted": {"status": "full", "header-mask": {"Subject": "Subject Unavailable"}}}' \ 'subject:[0][0][0]["headers"]["Subject"]="This is a message using draft-melnikov-smime-header-signing"' test_done