Add Decryption field

Add a decryption field of the form

Decryption: 2 part(s) decrypted 1 part(s) failed

Meaning that 2 encrypted mime parts where successfully decrypted and 1
part failed.  Note that the number 2 refers to the number of
successfully decrypted mime parts and not the number of successfully
decrypted encryptes multiparts, i.e., if an encrypted multipart
contains 4 parts and decryption is successful the field will be

Decryption: 4 part(s) decrypted

TODO: Add details button listing the names and indexes of the
decrypted (or not) mime-parts
This commit is contained in:
Foivos S. Zakkak 2014-10-19 03:20:21 +03:00
parent ae75060b6a
commit 2d843ca887
4 changed files with 85 additions and 30 deletions

View File

@ -153,11 +153,10 @@ accumulate_text (MuMsg *msg, MuMsgPart *part, GString **gstrp)
} }
/* declaration, so we can use it earlier */ /* declaration, so we can use it earlier */
static gboolean handle_mime_object (MuMsg *msg, static gboolean
GMimeObject *mobj, GMimeObject *parent, handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent,
MuMsgOptions opts, MuMsgOptions opts, unsigned *index, gboolean decrypted,
unsigned *index, MuMsgPartForeachFunc func, MuMsgPartForeachFunc func, gpointer user_data);
gpointer user_data);
static char* static char*
get_text_from_mime_msg (MuMsg *msg, GMimeMessage *mmsg, MuMsgOptions opts) get_text_from_mime_msg (MuMsg *msg, GMimeMessage *mmsg, MuMsgOptions opts)
@ -172,6 +171,7 @@ get_text_from_mime_msg (MuMsg *msg, GMimeMessage *mmsg, MuMsgOptions opts)
(GMimeObject *) mmsg, (GMimeObject *) mmsg,
opts, opts,
&index, &index,
FALSE,
(MuMsgPartForeachFunc)accumulate_text, (MuMsgPartForeachFunc)accumulate_text,
&gstr); &gstr);
@ -375,8 +375,7 @@ get_console_pw (const char* user_id, const char *prompt_ctx,
static gboolean static gboolean
handle_encrypted_part (MuMsg *msg, handle_encrypted_part (MuMsg *msg, GMimeMultipartEncrypted *part,
GMimeMultipartEncrypted *part, GMimeObject *parent,
MuMsgOptions opts, unsigned *index, MuMsgOptions opts, unsigned *index,
MuMsgPartForeachFunc func, gpointer user_data) MuMsgPartForeachFunc func, gpointer user_data)
{ {
@ -399,20 +398,20 @@ handle_encrypted_part (MuMsg *msg,
} }
if (dec) { if (dec) {
rv = handle_mime_object (msg, dec, parent, opts, rv = handle_mime_object (msg, dec, (GMimeObject *) part,
index, func, user_data); opts, index, TRUE, func, user_data);
g_object_unref (dec); g_object_unref (dec);
} else { } else {
// On failure to decrypt, list the encrypted part as // On failure to decrypt list the encrypted part as an
// an attachment // attachment
GMimeObject *encrypted; GMimeObject *encrypted;
encrypted = g_mime_multipart_get_part (GMIME_MULTIPART (part), 1); encrypted = g_mime_multipart_get_part (GMIME_MULTIPART (part), 1);
g_return_val_if_fail (GMIME_IS_PART(encrypted), FALSE); g_return_val_if_fail (GMIME_IS_PART(encrypted), FALSE);
rv = handle_mime_object (msg, encrypted, parent, opts, rv = handle_mime_object (msg, encrypted, (GMimeObject *) part,
index, func, user_data); opts, index, FALSE, func, user_data);
} }
return rv; return rv;
@ -423,7 +422,7 @@ handle_encrypted_part (MuMsg *msg,
/* call 'func' with information about this MIME-part */ /* call 'func' with information about this MIME-part */
static gboolean static gboolean
handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent, handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent,
MuMsgOptions opts, unsigned *index, MuMsgOptions opts, unsigned *index, gboolean decrypted,
MuMsgPartForeachFunc func, gpointer user_data) MuMsgPartForeachFunc func, gpointer user_data)
{ {
GMimeContentType *ct; GMimeContentType *ct;
@ -434,6 +433,12 @@ handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent,
msgpart.size = get_part_size (part); msgpart.size = get_part_size (part);
msgpart.part_type = MU_MSG_PART_TYPE_LEAF; msgpart.part_type = MU_MSG_PART_TYPE_LEAF;
msgpart.part_type |= get_disposition ((GMimeObject*)part); msgpart.part_type |= get_disposition ((GMimeObject*)part);
if (decrypted)
msgpart.part_type |= MU_MSG_PART_TYPE_DECRYPTED;
else if ((opts & MU_MSG_OPTION_DECRYPT) &&
GMIME_IS_MULTIPART_ENCRYPTED (parent))
msgpart.part_type |= MU_MSG_PART_TYPE_ENCRYPTED;
ct = g_mime_object_get_content_type ((GMimeObject*)part); ct = g_mime_object_get_content_type ((GMimeObject*)part);
if (GMIME_IS_CONTENT_TYPE(ct)) { if (GMIME_IS_CONTENT_TYPE(ct)) {
@ -466,7 +471,7 @@ handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent,
/* call 'func' with information about this MIME-part */ /* call 'func' with information about this MIME-part */
static gboolean static gboolean
handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart, GMimeObject *parent, handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart, GMimeObject *parent,
MuMsgOptions opts, unsigned *index, MuMsgOptions opts, unsigned *index, gboolean decrypted,
MuMsgPartForeachFunc func, gpointer user_data) MuMsgPartForeachFunc func, gpointer user_data)
{ {
MuMsgPart msgpart; MuMsgPart msgpart;
@ -494,6 +499,7 @@ handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart, GMimeObject *par
(GMimeObject *) mmsg, (GMimeObject *) mmsg,
opts, opts,
index, index,
decrypted,
func, func,
user_data); user_data);
} }
@ -503,7 +509,8 @@ handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart, GMimeObject *par
static gboolean static gboolean
handle_multipart (MuMsg *msg, GMimeMultipart *mpart, MuMsgOptions opts, handle_multipart (MuMsg *msg, GMimeMultipart *mpart, MuMsgOptions opts,
unsigned *index, MuMsgPartForeachFunc func, gpointer user_data) unsigned *index, gboolean decrypted,
MuMsgPartForeachFunc func, gpointer user_data)
{ {
gboolean res; gboolean res;
GMimeObject *part; GMimeObject *part;
@ -513,7 +520,8 @@ handle_multipart (MuMsg *msg, GMimeMultipart *mpart, MuMsgOptions opts,
for (i = 0; i < mpart->children->len; i++) { for (i = 0; i < mpart->children->len; i++) {
part = (GMimeObject *) mpart->children->pdata[i]; part = (GMimeObject *) mpart->children->pdata[i];
res &= handle_mime_object (msg, part, (GMimeObject *) mpart, res &= handle_mime_object (msg, part, (GMimeObject *) mpart,
opts, index, func, user_data); opts, index, decrypted,
func, user_data);
} }
return res; return res;
@ -521,18 +529,18 @@ handle_multipart (MuMsg *msg, GMimeMultipart *mpart, MuMsgOptions opts,
static gboolean static gboolean
handle_mime_object (MuMsg *msg, handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent,
GMimeObject *mobj, GMimeObject *parent, MuMsgOptions opts, MuMsgOptions opts, unsigned *index, gboolean decrypted,
unsigned *index, MuMsgPartForeachFunc func, gpointer user_data) MuMsgPartForeachFunc func, gpointer user_data)
{ {
if (GMIME_IS_PART (mobj)) if (GMIME_IS_PART (mobj))
return handle_part return handle_part
(msg, GMIME_PART(mobj), parent, (msg, GMIME_PART(mobj), parent,
opts, index, func, user_data); opts, index, decrypted, func, user_data);
else if (GMIME_IS_MESSAGE_PART (mobj)) else if (GMIME_IS_MESSAGE_PART (mobj))
return handle_message_part return handle_message_part
(msg, GMIME_MESSAGE_PART(mobj), (msg, GMIME_MESSAGE_PART(mobj),
parent, opts, index, func, user_data); parent, opts, index, decrypted, func, user_data);
else if ((opts & MU_MSG_OPTION_VERIFY) && else if ((opts & MU_MSG_OPTION_VERIFY) &&
GMIME_IS_MULTIPART_SIGNED (mobj)) { GMIME_IS_MULTIPART_SIGNED (mobj)) {
gboolean verified, signedpart; gboolean verified, signedpart;
@ -543,18 +551,18 @@ handle_mime_object (MuMsg *msg,
// Only process the first part (the second one is the signature) // Only process the first part (the second one is the signature)
signedpart = handle_mime_object signedpart = handle_mime_object
(msg, g_mime_multipart_get_part (GMIME_MULTIPART (mobj), 0), (msg, g_mime_multipart_get_part (GMIME_MULTIPART (mobj), 0),
mobj, opts, index, func, user_data); mobj, opts, index, decrypted, func, user_data);
return verified && signedpart; return verified && signedpart;
} else if ((opts & MU_MSG_OPTION_DECRYPT) && } else if ((opts & MU_MSG_OPTION_DECRYPT) &&
GMIME_IS_MULTIPART_ENCRYPTED (mobj)) GMIME_IS_MULTIPART_ENCRYPTED (mobj))
return handle_encrypted_part return handle_encrypted_part
(msg, GMIME_MULTIPART_ENCRYPTED (mobj), (msg, GMIME_MULTIPART_ENCRYPTED (mobj),
parent, opts, index, func, user_data); opts, index, func, user_data);
else if (GMIME_IS_MULTIPART (mobj)) else if (GMIME_IS_MULTIPART (mobj))
return handle_multipart return handle_multipart
(msg, GMIME_MULTIPART (mobj), (msg, GMIME_MULTIPART (mobj), opts,
opts, index, func, user_data); index, decrypted, func, user_data);
return TRUE; return TRUE;
} }
@ -576,6 +584,7 @@ mu_msg_part_foreach (MuMsg *msg, MuMsgOptions opts,
(GMimeObject *) msg->_file->_mime_msg, (GMimeObject *) msg->_file->_mime_msg,
opts, opts,
&index, &index,
FALSE,
func, func,
user_data); user_data);
} }

View File

@ -300,6 +300,21 @@ sig_verdict (MuMsgPart *mpart)
} }
} }
static const char*
dec_verdict (MuMsgPart *mpart)
{
MuMsgPartType ptype;
ptype = mpart->part_type;
if (ptype & MU_MSG_PART_TYPE_DECRYPTED)
return ":decryption succeeded";
else if (ptype & MU_MSG_PART_TYPE_ENCRYPTED)
return ":decryption failed";
else
return "";
}
static gchar * static gchar *
get_part_type_string (MuMsgPartType ptype) get_part_type_string (MuMsgPartType ptype)
@ -348,7 +363,7 @@ each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo)
tmp = g_strdup_printf tmp = g_strdup_printf
("%s(:index %d :name \"%s\" :mime-type \"%s/%s\"%s%s " ("%s(:index %d :name \"%s\" :mime-type \"%s/%s\"%s%s "
":type %s " ":type %s "
":attachment %s :size %i %s)", ":attachment %s :size %i %s %s)",
pinfo->parts ? pinfo->parts: "", pinfo->parts ? pinfo->parts: "",
part->index, part->index,
name ? name : "noname", name ? name : "noname",
@ -358,7 +373,8 @@ each_part (MuMsg *msg, MuMsgPart *part, PartInfo *pinfo)
parttype, parttype,
mu_msg_part_maybe_attachment (part) ? "t" : "nil", mu_msg_part_maybe_attachment (part) ? "t" : "nil",
(int)part->size, (int)part->size,
sig_verdict (part)); sig_verdict (part),
dec_verdict (part));
g_free (pinfo->parts); g_free (pinfo->parts);
pinfo->parts = tmp; pinfo->parts = tmp;

View File

@ -625,6 +625,11 @@ mu4e-compose-mode."
:shortname "Sgn" :shortname "Sgn"
:help "Check for the cryptographic signature" :help "Check for the cryptographic signature"
:sortable nil)) :sortable nil))
(:decryption .
( :name "Decryption"
:shortname "Dec"
:help "Check the cryptographic decryption status"
:sortable nil))
(:size . (:size .
( :name "Size" ( :name "Size"
:shortname "Size" :shortname "Size"

View File

@ -50,7 +50,8 @@
:group 'mu4e) :group 'mu4e)
(defcustom mu4e-view-fields (defcustom mu4e-view-fields
'(:from :to :cc :subject :flags :date :maildir :mailing-list :tags :attachments :signature) '(:from :to :cc :subject :flags :date :maildir :mailing-list :tags
:attachments :signature :decryption)
"Header fields to display in the message view buffer. "Header fields to display in the message view buffer.
For the complete list of available headers, see `mu4e-header-info'." For the complete list of available headers, see `mu4e-header-info'."
:type (list 'symbol) :type (list 'symbol)
@ -227,6 +228,8 @@ found."
(:attachments (mu4e~view-construct-attachments-header msg)) (:attachments (mu4e~view-construct-attachments-header msg))
;; pgp-signatures ;; pgp-signatures
(:signature (mu4e~view-construct-signature-header msg)) (:signature (mu4e~view-construct-signature-header msg))
;; pgp-decryption
(:decryption (mu4e~view-construct-decryption-header msg))
(t (mu4e~view-construct-header field (t (mu4e~view-construct-header field
(mu4e~view-custom-field msg field)))))) (mu4e~view-custom-field msg field))))))
mu4e-view-fields "") mu4e-view-fields "")
@ -403,6 +406,28 @@ add text-properties to VAL."
(val (when val (concat val " (" btn ")")))) (val (when val (concat val " (" btn ")"))))
(mu4e~view-construct-header :signature val t))) (mu4e~view-construct-header :signature val t)))
(defun mu4e~view-construct-decryption-header (msg)
"Construct a Decryption: header, if there are any encrypted parts."
(let* ((parts (mu4e-message-field msg :parts))
(verdicts
(remove-if 'null
(mapcar (lambda (part) (mu4e-message-part-field part :decryption))
parts)))
(succeeded (remove-if (lambda (v) (eq v 'failed)) verdicts))
(failed (remove-if (lambda (v) (eq v 'succeeded)) verdicts))
(succ (when succeeded
(propertize
(concat (number-to-string (length succeeded))
" part(s) decrypted")
'face 'mu4e-ok-face)))
(fail (when failed
(propertize
(concat (number-to-string (length failed))
" part(s) failed")
'face 'mu4e-warning-face)))
(val (concat succ fail)))
(mu4e~view-construct-header :decryption val t)))
(defun mu4e~view-open-attach-from-binding () (defun mu4e~view-open-attach-from-binding ()
"Open the attachement at point, or click location." "Open the attachement at point, or click location."
(interactive) (interactive)