Merge branch 'master' of github.com:djcb/mu

This commit is contained in:
djcb 2015-03-06 00:14:59 +02:00
commit 9d8dfcaedd
8 changed files with 117 additions and 48 deletions

View File

@ -115,7 +115,7 @@ get_gpg (GError **err)
}
return g_strdup (envpath);
}
if (!(path = g_find_program_in_path ("gpg")) &&
!(path = g_find_program_in_path ("gpg2"))) {
mu_util_g_set_error (err, MU_ERROR, "gpg/gpg2 not found");
@ -134,7 +134,7 @@ get_gpg_crypto_context (MuMsgOptions opts, GError **err)
cctx = NULL;
if (!(gpg = get_gpg (err)))
return NULL;
cctx = g_mime_gpg_context_new (
(GMimePasswordRequestFunc)password_requester, gpg);
g_free (gpg);
@ -165,7 +165,7 @@ get_crypto_context (MuMsgOptions opts, MuMsgPartPasswordFunc password_func,
cctx = get_gpg_crypto_context (opts, err);
if (!cctx)
return NULL;
/* use gobject to pass data to the callback func */
cbdata = g_new0 (CallbackData, 1);
cbdata->pw_func = password_func ? password_func : dummy_password_func;
@ -355,21 +355,32 @@ mu_msg_part_sig_status_report_destroy (MuMsgPartSigStatusReport *report)
}
MuMsgPartSigStatusReport*
static inline void
tag_with_sig_status(GObject *part,
MuMsgPartSigStatusReport *report)
{
g_object_set_data_full
(part, SIG_STATUS_REPORT, report,
(GDestroyNotify)mu_msg_part_sig_status_report_destroy);
}
void
mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, MuMsgOptions opts,
GError **err)
{
/* the signature status */
MuMsgPartSigStatusReport *report;
GMimeCryptoContext *ctx;
GMimeSignatureList *sigs;
g_return_val_if_fail (GMIME_IS_MULTIPART_SIGNED(sig), NULL);
g_return_if_fail (GMIME_IS_MULTIPART_SIGNED(sig));
ctx = get_crypto_context (opts, NULL, NULL, err);
if (!ctx) {
mu_util_g_set_error (err, MU_ERROR_CRYPTO,
"failed to get crypto context");
return NULL;
return;
}
sigs = g_mime_multipart_signed_verify (sig, ctx, err);
@ -378,13 +389,42 @@ mu_msg_crypto_verify_part (GMimeMultipartSigned *sig, MuMsgOptions opts,
if (err && !*err)
mu_util_g_set_error (err, MU_ERROR_CRYPTO,
"verification failed");
return NULL;
return;
}
report = get_status_report (sigs);
g_mime_signature_list_clear (sigs);
return report;
/* tag this part with the signature status check */
tag_with_sig_status(G_OBJECT(sig), report);
}
static inline void
check_decrypt_result(GMimeMultipartEncrypted *part, GMimeDecryptResult *res,
GError **err)
{
GMimeSignatureList *sigs;
MuMsgPartSigStatusReport *report;
if (res) {
/* Check if the decrypted part had any embed signatures */
sigs = res->signatures;
if (sigs) {
report = get_status_report (sigs);
g_mime_signature_list_clear (sigs);
/* tag this part with the signature status check */
tag_with_sig_status(G_OBJECT(part), report);
}
else {
if (err && !*err)
mu_util_g_set_error (err, MU_ERROR_CRYPTO,
"verification failed");
}
g_object_unref (res);
}
}
@ -417,10 +457,7 @@ mu_msg_crypto_decrypt_part (GMimeMultipartEncrypted *enc, MuMsgOptions opts,
dec = g_mime_multipart_encrypted_decrypt (enc, ctx, &res, err);
g_object_unref (ctx);
/* we don't use the 3rd param 'res' * (GMimeDecryptResult),
* but we must unref it. */
if (res)
g_object_unref (res);
check_decrypt_result(enc, res, err);
if (!dec) {
if (err && !*err)

View File

@ -287,6 +287,8 @@ msg_cflags_cb (GMimeObject *parent, GMimeObject *part, MuFlags *flags)
if (GMIME_IS_MULTIPART_SIGNED(part))
*flags |= MU_FLAG_SIGNED;
/* FIXME: An encrypted part might be signed at the same time.
* In that case the signed flag is lost. */
if (GMIME_IS_MULTIPART_ENCRYPTED(part))
*flags |= MU_FLAG_ENCRYPTED;

View File

@ -316,30 +316,18 @@ get_disposition (GMimeObject *mobj)
return MU_MSG_PART_TYPE_NONE;
}
#define SIG_STATUS_REPORT "sig-status-report"
/* call 'func' with information about this MIME-part */
static gboolean
static inline void
check_signature (MuMsg *msg, GMimeMultipartSigned *part, MuMsgOptions opts)
{
/* the signature status */
MuMsgPartSigStatusReport *sigrep;
GError *err;
err = NULL;
sigrep = mu_msg_crypto_verify_part (part, opts, &err);
err = NULL;
mu_msg_crypto_verify_part (part, opts, &err);
if (err) {
g_warning ("error verifying signature: %s", err->message);
g_clear_error (&err);
}
/* tag this part with the signature status check */
g_object_set_data_full
(G_OBJECT(part), SIG_STATUS_REPORT,
sigrep,
(GDestroyNotify)mu_msg_part_sig_status_report_destroy);
return TRUE;
}
@ -454,14 +442,20 @@ handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent,
msgpart.part_type |= MU_MSG_PART_TYPE_TEXT_HTML;
}
/* put the verification info in the pgp-signature part */
/* put the verification info in the pgp-signature and every
* descendent of a pgp-encrypted part */
msgpart.sig_status_report = NULL;
if (g_ascii_strcasecmp (msgpart.subtype, "pgp-signature") == 0)
if (g_ascii_strcasecmp (msgpart.subtype, "pgp-signature") == 0 ||
decrypted) {
msgpart.sig_status_report =
(MuMsgPartSigStatusReport*)
g_object_get_data (G_OBJECT(parent),
SIG_STATUS_REPORT);
if (msgpart.sig_status_report)
msgpart.part_type |= MU_MSG_PART_TYPE_SIGNED;
}
msgpart.data = (gpointer)part;
msgpart.index = (*index)++;
@ -501,7 +495,7 @@ handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart,
if (mmsg)
return handle_mime_object (msg,
mmsg->mime_part,
(GMimeObject *) mmsg,
parent,
opts,
index,
decrypted,
@ -513,8 +507,8 @@ handle_message_part (MuMsg *msg, GMimeMessagePart *mimemsgpart,
}
static gboolean
handle_multipart (MuMsg *msg, GMimeMultipart *mpart, MuMsgOptions opts,
unsigned *index, gboolean decrypted,
handle_multipart (MuMsg *msg, GMimeMultipart *mpart, GMimeObject *parent,
MuMsgOptions opts, unsigned *index, gboolean decrypted,
MuMsgPartForeachFunc func, gpointer user_data)
{
gboolean res;
@ -524,7 +518,7 @@ handle_multipart (MuMsg *msg, GMimeMultipart *mpart, MuMsgOptions opts,
res = TRUE;
for (i = 0; i < mpart->children->len; i++) {
part = (GMimeObject *) mpart->children->pdata[i];
res &= handle_mime_object (msg, part, (GMimeObject *) mpart,
res &= handle_mime_object (msg, part, parent,
opts, index, decrypted,
func, user_data);
}
@ -548,15 +542,11 @@ handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent,
parent, opts, index, decrypted, func, user_data);
else if ((opts & MU_MSG_OPTION_VERIFY) &&
GMIME_IS_MULTIPART_SIGNED (mobj)) {
gboolean verified, multipart;
verified = check_signature
check_signature
(msg, GMIME_MULTIPART_SIGNED (mobj), opts);
multipart = handle_multipart
(msg, GMIME_MULTIPART (mobj), opts,
return handle_multipart
(msg, GMIME_MULTIPART (mobj), mobj, opts,
index, decrypted, func, user_data);
return verified && multipart;
} else if ((opts & MU_MSG_OPTION_DECRYPT) &&
GMIME_IS_MULTIPART_ENCRYPTED (mobj))
return handle_encrypted_part
@ -564,7 +554,7 @@ handle_mime_object (MuMsg *msg, GMimeObject *mobj, GMimeObject *parent,
opts, index, func, user_data);
else if (GMIME_IS_MULTIPART (mobj))
return handle_multipart
(msg, GMIME_MULTIPART (mobj), opts,
(msg, GMIME_MULTIPART (mobj), parent, opts,
index, decrypted, func, user_data);
return TRUE;
}

View File

@ -25,6 +25,8 @@
#include <glib.h>
#include <unistd.h> /* for ssize_t */
#define SIG_STATUS_REPORT "sig-status-report"
G_BEGIN_DECLS
enum _MuMsgPartType {

View File

@ -115,10 +115,9 @@ typedef char* (*MuMsgPartPasswordFunc) (const char *user_id, const char *promp
*
* @return a status report object, free with mu_msg_part_sig_status_report_destroy
*/
MuMsgPartSigStatusReport* mu_msg_crypto_verify_part (GMimeMultipartSigned *sig,
MuMsgOptions opts,
GError **err)
G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT;
void mu_msg_crypto_verify_part (GMimeMultipartSigned *sig,
MuMsgOptions opts,
GError **err);
/**
* decrypt the given encrypted mime multipart

View File

@ -90,7 +90,7 @@ assert_no_dups (MuMsgIter *iter)
/* note: this also *moves the iter* */
static guint
run_and_count_matches (const char *xpath, const char *query)
run_and_count_matches_with_query_flags (const char *xpath, const char *query, MuQueryFlags flags)
{
MuQuery *mquery;
MuMsgIter *iter;
@ -131,7 +131,7 @@ run_and_count_matches (const char *xpath, const char *query)
iter = mu_query_run (mquery, query, MU_MSG_FIELD_ID_NONE, -1,
MU_QUERY_FLAG_NONE, NULL);
flags, NULL);
mu_query_destroy (mquery);
g_assert (iter);
@ -155,6 +155,12 @@ run_and_count_matches (const char *xpath, const char *query)
return count1;
}
static guint
run_and_count_matches (const char *xpath, const char *query)
{
return run_and_count_matches_with_query_flags (xpath, query, MU_QUERY_FLAG_NONE);
}
typedef struct {
const char *query;
size_t count; /* expected number of matches */
@ -629,6 +635,32 @@ test_mu_query_tags_02 (void)
}
}
/* Tests for https://github.com/djcb/mu/issues/380
On certain platforms, something goes wrong during compilation and
the --related option doesn't work.
*/
static void
test_mu_query_threads_compilation_error (void)
{
gchar *xpath;
xpath = fill_database (MU_TESTMAILDIR);
g_assert (xpath != NULL);
g_assert_cmpuint (run_and_count_matches_with_query_flags
(xpath, "msgid:uwsireh25.fsf@one.dot.net",
MU_QUERY_FLAG_NONE),
==, 1);
g_assert_cmpuint (run_and_count_matches_with_query_flags
(xpath, "msgid:uwsireh25.fsf@one.dot.net",
MU_QUERY_FLAG_INCLUDE_RELATED),
==, 3);
g_free (xpath);
}
static void
test_mu_query_preprocess (void)
@ -711,6 +743,9 @@ main (int argc, char *argv[])
g_test_add_func ("/mu-query/test-mu-query-tags_02",
test_mu_query_tags_02);
g_test_add_func ("/mu-query/test-mu-query-threads-compilation-error",
test_mu_query_threads_compilation_error);
if (!g_test_verbose())
g_log_set_handler (NULL,
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL|

View File

@ -47,6 +47,10 @@
;;
(define-key map "U" 'mu4e-update-mail-and-index)
(define-key map (kbd "C-S-u") 'mu4e-update-mail-and-index)
;; for terminal users
(define-key map (kbd "C-c C-u") 'mu4e-update-mail-and-index)
(define-key map "S" 'mu4e-interrupt-update-mail)
(define-key map (kbd "C-S-u") 'mu4e-update-mail-and-index)

View File

@ -61,7 +61,7 @@ Common values are \"offlineimap\", \"fetchmail\" and \"mbsync\",
but you use arbitrary shell-commands. If you set it to
\"true\" (the default), the command won't don't anything, which is
useful if you get your mail without the need to explicitly run any
scripts, for example when running yout own mail-server."
scripts, for example when running your own mail-server."
:type 'string
:group 'mu4e
:safe 'stringp)