* crypto: decryption support (WIP)
This commit is contained in:
@ -21,6 +21,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif /*HAVE_CONFIG_H*/
|
#endif /*HAVE_CONFIG_H*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "mu-msg.h"
|
#include "mu-msg.h"
|
||||||
#include "mu-msg-priv.h"
|
#include "mu-msg-priv.h"
|
||||||
#include "mu-msg-part.h"
|
#include "mu-msg-part.h"
|
||||||
@ -31,74 +33,138 @@
|
|||||||
#include <gmime/gmime.h>
|
#include <gmime/gmime.h>
|
||||||
#include <gmime/gmime-multipart-signed.h>
|
#include <gmime/gmime-multipart-signed.h>
|
||||||
|
|
||||||
static gboolean
|
#define CALLBACK_DATA "callback-data"
|
||||||
dummy_password_requester (GMimeCryptoContext *ctx, const char *user_id,
|
|
||||||
const char* prompt_ctx, gboolean reprompt,
|
|
||||||
GMimeStream *response, GError **err)
|
|
||||||
{
|
|
||||||
g_print ("password requested\n");
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
|
struct _CallbackData {
|
||||||
|
MuMsgPartPasswordFunc pw_func;
|
||||||
|
gpointer user_data;
|
||||||
|
};
|
||||||
|
typedef struct _CallbackData CallbackData;
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
password_requester (GMimeCryptoContext *ctx, const char *user_id,
|
||||||
|
const char* prompt_ctx, gboolean reprompt,
|
||||||
|
GMimeStream *response, GError **err)
|
||||||
|
{
|
||||||
|
CallbackData *cbdata;
|
||||||
|
gchar *password;
|
||||||
|
ssize_t written;
|
||||||
|
|
||||||
|
cbdata = g_object_get_data (G_OBJECT(ctx), CALLBACK_DATA);
|
||||||
|
g_return_val_if_fail (cbdata, FALSE);
|
||||||
|
|
||||||
|
password = cbdata->pw_func (user_id, prompt_ctx, reprompt,
|
||||||
|
cbdata->user_data);
|
||||||
|
if (!password)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
written = g_mime_stream_write_string (response, password);
|
||||||
|
if (written != -1)
|
||||||
|
written = g_mime_stream_write_string (response, "\n");
|
||||||
|
if (written == -1)
|
||||||
|
mu_util_g_set_error (err, MU_ERROR_CRYPTO,
|
||||||
|
"writing password to mime stream failed");
|
||||||
|
|
||||||
|
if (g_mime_stream_flush (response) != 0)
|
||||||
|
g_printerr ("error flushing stream!\n");
|
||||||
|
|
||||||
|
memset (password, 0, strlen(password));
|
||||||
|
g_free (password);
|
||||||
|
|
||||||
|
return written != -1 ? TRUE : FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GMimeCryptoContext*
|
static char*
|
||||||
|
dummy_password_func (const char *user_id, const char *prompt_ctx,
|
||||||
|
gboolean reprompt, gpointer user_data)
|
||||||
|
{
|
||||||
|
g_print ("password requested for %s (%s) %s\n",
|
||||||
|
user_id, prompt_ctx, reprompt ? "again" : "");
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static GMimeCryptoContext*
|
||||||
get_gpg_crypto_context (MuMsgOptions opts, GError **err)
|
get_gpg_crypto_context (MuMsgOptions opts, GError **err)
|
||||||
{
|
{
|
||||||
GMimeCryptoContext *ctx;
|
GMimeCryptoContext *cctx;
|
||||||
const char *prog;
|
const char *prog;
|
||||||
|
|
||||||
ctx = NULL;
|
cctx = NULL;
|
||||||
|
|
||||||
prog = g_getenv ("MU_GPG_PATH");
|
prog = g_getenv ("MU_GPG_PATH");
|
||||||
if (prog)
|
if (prog)
|
||||||
ctx = g_mime_gpg_context_new (
|
cctx = g_mime_gpg_context_new (
|
||||||
(GMimePasswordRequestFunc)dummy_password_requester,
|
(GMimePasswordRequestFunc)password_requester, prog);
|
||||||
prog);
|
|
||||||
else {
|
else {
|
||||||
char *path;
|
char *path;
|
||||||
path = g_find_program_in_path ("gpg");
|
path = g_find_program_in_path ("gpg");
|
||||||
if (path)
|
if (path)
|
||||||
ctx = g_mime_gpg_context_new (
|
cctx = g_mime_gpg_context_new (
|
||||||
(GMimePasswordRequestFunc)dummy_password_requester,
|
password_requester, path);
|
||||||
path);
|
|
||||||
g_free (path);
|
g_free (path);
|
||||||
}
|
}
|
||||||
if (!ctx) {
|
if (!cctx) {
|
||||||
mu_util_g_set_error (err, MU_ERROR,
|
mu_util_g_set_error (err, MU_ERROR,
|
||||||
"failed to get GPG crypto context");
|
"failed to get GPG crypto context");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mime_gpg_context_set_use_agent
|
g_mime_gpg_context_set_use_agent
|
||||||
(GMIME_GPG_CONTEXT(ctx),
|
(GMIME_GPG_CONTEXT(cctx),
|
||||||
opts & MU_MSG_OPTION_USE_AGENT);
|
opts & MU_MSG_OPTION_USE_AGENT ? TRUE:FALSE);
|
||||||
g_mime_gpg_context_set_always_trust
|
|
||||||
(GMIME_GPG_CONTEXT(ctx), FALSE);
|
|
||||||
g_mime_gpg_context_set_auto_key_retrieve
|
g_mime_gpg_context_set_auto_key_retrieve
|
||||||
(GMIME_GPG_CONTEXT(ctx),
|
(GMIME_GPG_CONTEXT(cctx),
|
||||||
opts & MU_MSG_OPTION_AUTO_RETRIEVE_KEY);
|
opts & MU_MSG_OPTION_AUTO_RETRIEVE_KEY ? TRUE:FALSE);
|
||||||
|
g_mime_gpg_context_set_always_trust
|
||||||
|
(GMIME_GPG_CONTEXT(cctx), FALSE);
|
||||||
|
|
||||||
return ctx;
|
return cctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
GMimeCryptoContext*
|
static GMimeCryptoContext*
|
||||||
get_pkcs7_crypto_context (MuMsgOptions opts, GError **err)
|
get_pkcs7_crypto_context (MuMsgOptions opts, GError **err)
|
||||||
{
|
{
|
||||||
GMimeCryptoContext *ctx;
|
GMimeCryptoContext *cctx;
|
||||||
|
|
||||||
ctx = g_mime_pkcs7_context_new
|
cctx = g_mime_pkcs7_context_new (password_requester);
|
||||||
((GMimePasswordRequestFunc)dummy_password_requester);
|
if (!cctx) {
|
||||||
if (!ctx) {
|
|
||||||
mu_util_g_set_error (err, MU_ERROR,
|
mu_util_g_set_error (err, MU_ERROR,
|
||||||
"failed to get PKCS7 crypto context");
|
"failed to get PKCS7 crypto context");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_mime_pkcs7_context_set_always_trust
|
g_mime_pkcs7_context_set_always_trust
|
||||||
(GMIME_PKCS7_CONTEXT(ctx), FALSE);
|
(GMIME_PKCS7_CONTEXT(cctx), FALSE);
|
||||||
|
|
||||||
return ctx;
|
return cctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static GMimeCryptoContext*
|
||||||
|
get_crypto_context (MuMsgOptions opts, MuMsgPartPasswordFunc password_func,
|
||||||
|
gpointer user_data, GError **err)
|
||||||
|
{
|
||||||
|
CallbackData *cbdata;
|
||||||
|
GMimeCryptoContext *cctx;
|
||||||
|
|
||||||
|
if (opts & MU_MSG_OPTION_USE_PKCS7)
|
||||||
|
cctx = get_pkcs7_crypto_context (opts, err);
|
||||||
|
else
|
||||||
|
cctx = get_gpg_crypto_context (opts, err);
|
||||||
|
|
||||||
|
/* use gobject to pass data to the callback func */
|
||||||
|
cbdata = g_new0 (CallbackData, 1);
|
||||||
|
cbdata->pw_func = password_func;
|
||||||
|
cbdata->user_data = user_data;
|
||||||
|
|
||||||
|
g_object_set_data_full (G_OBJECT(cctx), CALLBACK_DATA,
|
||||||
|
cbdata, (GDestroyNotify)g_free);
|
||||||
|
return cctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -266,13 +332,11 @@ mu_msg_mime_sig_infos (GMimeMultipartSigned *sigmpart, MuMsgOptions opts,
|
|||||||
return NULL; /* error */
|
return NULL; /* error */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opts & MU_MSG_OPTION_USE_PKCS7)
|
/* dummy is good, since we don't need a password when checking
|
||||||
cctx = get_pkcs7_crypto_context (opts, err);
|
* signatures */
|
||||||
else
|
cctx = get_crypto_context (opts, dummy_password_func, NULL, err);
|
||||||
cctx = get_gpg_crypto_context (opts, err);
|
|
||||||
|
|
||||||
/* return a fake siginfos with the error */
|
if (!cctx) /* return a fake siginfos with the error */
|
||||||
if (!cctx)
|
|
||||||
return error_sig_infos (); /* error */
|
return error_sig_infos (); /* error */
|
||||||
|
|
||||||
sigs = g_mime_multipart_signed_verify (sigmpart, cctx, err);
|
sigs = g_mime_multipart_signed_verify (sigmpart, cctx, err);
|
||||||
@ -313,7 +377,7 @@ mu_msg_part_free_sig_infos (GSList *siginfos)
|
|||||||
* - if not, the verdic is MU_MSG_PART_SIG_STATUS_UNKNOWN
|
* - if not, the verdic is MU_MSG_PART_SIG_STATUS_UNKNOWN
|
||||||
*/
|
*/
|
||||||
MuMsgPartSigStatus
|
MuMsgPartSigStatus
|
||||||
mu_msg_mime_sig_infos_verdict (GSList *sig_infos)
|
mu_msg_part_sig_infos_verdict (GSList *sig_infos)
|
||||||
{
|
{
|
||||||
GSList *cur;
|
GSList *cur;
|
||||||
MuMsgPartSigStatus status;
|
MuMsgPartSigStatus status;
|
||||||
@ -457,3 +521,120 @@ mu_msg_part_sig_info_to_string (MuMsgPartSigInfo *info)
|
|||||||
|
|
||||||
return g_string_free (gstr, FALSE);
|
return g_string_free (gstr, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct _MuMsgDecryptedPart {
|
||||||
|
GMimeObject *decrypted;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct _PartData {
|
||||||
|
MuMsgPartDecryptForeachFunc func;
|
||||||
|
gpointer user_data;
|
||||||
|
GMimeCryptoContext *cctx;
|
||||||
|
GError *err;
|
||||||
|
};
|
||||||
|
typedef struct _PartData PartData;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
each_encpart (GMimeObject *parent, GMimeObject *part, PartData *pdata)
|
||||||
|
{
|
||||||
|
MuMsgDecryptedPart dpart;
|
||||||
|
|
||||||
|
if (pdata->err)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!GMIME_IS_MULTIPART_ENCRYPTED (part))
|
||||||
|
return; /* nothing to do for this part */
|
||||||
|
|
||||||
|
dpart.decrypted =
|
||||||
|
g_mime_multipart_encrypted_decrypt (
|
||||||
|
GMIME_MULTIPART_ENCRYPTED(part),
|
||||||
|
pdata->cctx, NULL, &pdata->err);
|
||||||
|
if (!dpart.decrypted || pdata->err) {
|
||||||
|
if (!pdata->err)
|
||||||
|
mu_util_g_set_error
|
||||||
|
(&pdata->err,
|
||||||
|
MU_ERROR_CRYPTO,
|
||||||
|
"decryption failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pdata->func (&dpart, pdata->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
mu_msg_part_decrypt_foreach (MuMsg *msg, MuMsgPartDecryptForeachFunc func,
|
||||||
|
MuMsgPartPasswordFunc password_func,
|
||||||
|
gpointer user_data, MuMsgOptions opts, GError **err)
|
||||||
|
{
|
||||||
|
PartData pdata;
|
||||||
|
|
||||||
|
g_return_val_if_fail (msg, FALSE);
|
||||||
|
g_return_val_if_fail (func, FALSE);
|
||||||
|
g_return_val_if_fail (password_func, FALSE);
|
||||||
|
|
||||||
|
if (!mu_msg_load_msg_file (msg, err))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pdata.func = func;
|
||||||
|
pdata.user_data = user_data;
|
||||||
|
pdata.err = NULL;
|
||||||
|
pdata.cctx = get_crypto_context (opts, password_func,
|
||||||
|
user_data, err);
|
||||||
|
if (!pdata.cctx)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_mime_message_foreach (msg->_file->_mime_msg,
|
||||||
|
(GMimeObjectForeachFunc)each_encpart,
|
||||||
|
&pdata);
|
||||||
|
if (pdata.err) {
|
||||||
|
*err = pdata.err;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (pdata.cctx);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
mu_msg_decrypted_part_to_string (MuMsgDecryptedPart *dpart, GError **err)
|
||||||
|
{
|
||||||
|
GMimePart *part;
|
||||||
|
gboolean not_ok;
|
||||||
|
gchar *str;
|
||||||
|
|
||||||
|
g_return_val_if_fail (dpart, NULL);
|
||||||
|
|
||||||
|
if (!GMIME_IS_PART(dpart->decrypted)) {
|
||||||
|
mu_util_g_set_error (err, MU_ERROR_CRYPTO,
|
||||||
|
"wrong mime-type");
|
||||||
|
return NULL; /* can only convert parts to string*/
|
||||||
|
}
|
||||||
|
part = GMIME_PART(dpart->decrypted);
|
||||||
|
str = mu_msg_mime_part_to_string (part, ¬_ok);
|
||||||
|
|
||||||
|
if (not_ok) {
|
||||||
|
g_free (str);
|
||||||
|
mu_util_g_set_error (err, MU_ERROR_CRYPTO,
|
||||||
|
"failed to convert part to string");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
mu_msg_decrypted_part_to_file (MuMsgDecryptedPart *dpart, const char *path,
|
||||||
|
GError **err)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (dpart, FALSE);
|
||||||
|
g_return_val_if_fail (path, FALSE);
|
||||||
|
|
||||||
|
return mu_msg_part_mime_save_object (dpart->decrypted, path, FALSE, FALSE,
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
|||||||
@ -80,7 +80,7 @@ const char* mu_msg_part_sig_status_to_string (MuMsgPartSigStatus status);
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* summarize the signatures to one status:
|
* summarize the signature checks to one status:
|
||||||
*
|
*
|
||||||
* - if there's any signature with MU_MSG_PART_SIG_STATUS_(ERROR|FAIL),
|
* - if there's any signature with MU_MSG_PART_SIG_STATUS_(ERROR|FAIL),
|
||||||
* the verdict is MU_MSG_PART_SIG_STATUS_ERROR
|
* the verdict is MU_MSG_PART_SIG_STATUS_ERROR
|
||||||
@ -94,7 +94,7 @@ const char* mu_msg_part_sig_status_to_string (MuMsgPartSigStatus status);
|
|||||||
*
|
*
|
||||||
* @return the status
|
* @return the status
|
||||||
*/
|
*/
|
||||||
MuMsgPartSigStatus mu_msg_mime_sig_infos_verdict (GSList *sig_infos);
|
MuMsgPartSigStatus mu_msg_part_sig_infos_verdict (GSList *sig_infos);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -125,4 +125,81 @@ char* mu_msg_part_sig_info_to_string (MuMsgPartSigInfo *info)
|
|||||||
*/
|
*/
|
||||||
void mu_msg_part_free_sig_infos (GSList *siginfos);
|
void mu_msg_part_free_sig_infos (GSList *siginfos);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* below function only do anything useful if mu was built with crypto
|
||||||
|
* support
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _MuMsgDecryptedPart;
|
||||||
|
typedef struct _MuMsgDecryptedPart MuMsgDecryptedPart;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* callback function to provide decrypted message parts
|
||||||
|
*
|
||||||
|
* @param dpart a decrypted par
|
||||||
|
* @param user_data user pointer (as passed to mu_msg_part_decrypt_foreach)
|
||||||
|
*/
|
||||||
|
typedef void (*MuMsgPartDecryptForeachFunc) (MuMsgDecryptedPart *dpart,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* callback function to retrieve a password from the user
|
||||||
|
*
|
||||||
|
* @param user_id the user name / id to get the password for
|
||||||
|
* @param prompt_ctx a string containing some helpful context for the prompt
|
||||||
|
* @param reprompt whether this is a reprompt after an earlier, incorrect password
|
||||||
|
* @param user_data the user_data pointer passed to mu_msg_part_decrypt_foreach
|
||||||
|
*
|
||||||
|
* @return a newly allocated (g_free'able) string
|
||||||
|
*/
|
||||||
|
typedef char* (*MuMsgPartPasswordFunc) (const char *user_id, const char *prompt_ctx,
|
||||||
|
gboolean reprompt, gpointer user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* go through all MIME-parts for this message, and decrypted all parts
|
||||||
|
* that are encrypted. After decryption,
|
||||||
|
*
|
||||||
|
* If mu was built without crypto support, function does nothing.
|
||||||
|
*
|
||||||
|
* @param msg a valid MuMsg instance
|
||||||
|
* @param fun a callback function called for each decrypted part
|
||||||
|
* @param password_func a callback func called to retrieve a password from user
|
||||||
|
* @param user_data user data which passed to the callback function
|
||||||
|
* @param opts options
|
||||||
|
* @param err receives error information
|
||||||
|
*
|
||||||
|
* @return TRUE if function succeeded, FALSE otherwise
|
||||||
|
*/
|
||||||
|
gboolean mu_msg_part_decrypt_foreach (MuMsg *msg, MuMsgPartDecryptForeachFunc func,
|
||||||
|
MuMsgPartPasswordFunc password_func,
|
||||||
|
gpointer user_data, MuMsgOptions opts,
|
||||||
|
GError **err);
|
||||||
|
/**
|
||||||
|
* convert the decrypted part to a string.
|
||||||
|
*
|
||||||
|
* @param dpart decrypted part
|
||||||
|
* @param err receives error information
|
||||||
|
*
|
||||||
|
* @return decrypted part as a string (g_free after use), or NULL
|
||||||
|
*/
|
||||||
|
char* mu_msg_decrypted_part_to_string (MuMsgDecryptedPart *dpart, GError **err);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write the decrypted part to a file.
|
||||||
|
*
|
||||||
|
* @param dpart decrypted part
|
||||||
|
* @param path path to write it to
|
||||||
|
* @param err receives error information
|
||||||
|
*
|
||||||
|
* @return TRUE if it succeeded, FALSE otherwise
|
||||||
|
*/
|
||||||
|
gboolean mu_msg_decrypted_part_to_file (MuMsgDecryptedPart *dpart, const char *path,
|
||||||
|
GError **err);
|
||||||
|
|
||||||
#endif /*__MU_MSG_CRYPTO_H__*/
|
#endif /*__MU_MSG_CRYPTO_H__*/
|
||||||
|
|||||||
@ -242,13 +242,11 @@ msg_part_free (MuMsgPart *pi)
|
|||||||
#endif /*BUILD_CRYPTO*/
|
#endif /*BUILD_CRYPTO*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef BUILD_CRYPTO
|
||||||
static void
|
static void
|
||||||
check_signature_maybe (GMimeObject *parent, GMimeObject *mobj, MuMsgPart *pi,
|
check_signature_maybe (GMimeObject *parent, GMimeObject *mobj, MuMsgPart *pi,
|
||||||
MuMsgOptions opts)
|
MuMsgOptions opts)
|
||||||
{
|
{
|
||||||
#ifdef BUILD_CRYPTO
|
|
||||||
|
|
||||||
GMimeContentType *ctype;
|
GMimeContentType *ctype;
|
||||||
GError *err;
|
GError *err;
|
||||||
gboolean pkcs7;
|
gboolean pkcs7;
|
||||||
@ -275,10 +273,10 @@ check_signature_maybe (GMimeObject *parent, GMimeObject *mobj, MuMsgPart *pi,
|
|||||||
g_warning ("error verifying signature: %s", err->message);
|
g_warning ("error verifying signature: %s", err->message);
|
||||||
g_clear_error (&err);
|
g_clear_error (&err);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif /*BUILD_CRYPTO*/
|
#endif /*BUILD_CRYPTO*/
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -307,7 +305,9 @@ part_foreach_cb (GMimeObject *parent, GMimeObject *mobj, PartData *pdata)
|
|||||||
return;
|
return;
|
||||||
rv = init_msg_part_from_mime_message_part (mmsg, &pi);
|
rv = init_msg_part_from_mime_message_part (mmsg, &pi);
|
||||||
if (rv && (pdata->_opts && MU_MSG_OPTION_RECURSE_RFC822))
|
if (rv && (pdata->_opts && MU_MSG_OPTION_RECURSE_RFC822))
|
||||||
/* NOTE: this screws up the counting (pdata->_idx) */
|
/* NOTE: this screws up the counting
|
||||||
|
* (pdata->_idx); happily, we only use it
|
||||||
|
* where we don't care about that */
|
||||||
g_mime_message_foreach /* recurse */
|
g_mime_message_foreach /* recurse */
|
||||||
(mmsg, (GMimeObjectForeachFunc)part_foreach_cb,
|
(mmsg, (GMimeObjectForeachFunc)part_foreach_cb,
|
||||||
pdata);
|
pdata);
|
||||||
@ -315,8 +315,10 @@ part_foreach_cb (GMimeObject *parent, GMimeObject *mobj, PartData *pdata)
|
|||||||
rv = FALSE; /* ignore */
|
rv = FALSE; /* ignore */
|
||||||
|
|
||||||
/* if we have crypto support, check the signature if there is one */
|
/* if we have crypto support, check the signature if there is one */
|
||||||
|
#ifdef BUILD_CRYPTO
|
||||||
if (pdata->_opts & MU_MSG_OPTION_CHECK_SIGNATURES)
|
if (pdata->_opts & MU_MSG_OPTION_CHECK_SIGNATURES)
|
||||||
check_signature_maybe (parent, mobj, &pi, pdata->_opts);
|
check_signature_maybe (parent, mobj, &pi, pdata->_opts);
|
||||||
|
#endif /*BUILD_CRYPTO*/
|
||||||
|
|
||||||
if (rv)
|
if (rv)
|
||||||
pdata->_func(pdata->_msg, &pi, pdata->_user_data);
|
pdata->_func(pdata->_msg, &pi, pdata->_user_data);
|
||||||
@ -352,7 +354,7 @@ mu_msg_part_foreach (MuMsg *msg, MuMsgPartForeachFunc func, gpointer user_data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
gboolean
|
||||||
write_part_to_fd (GMimePart *part, int fd, GError **err)
|
write_part_to_fd (GMimePart *part, int fd, GError **err)
|
||||||
{
|
{
|
||||||
GMimeStream *stream;
|
GMimeStream *stream;
|
||||||
@ -416,9 +418,9 @@ write_object_to_fd (GMimeObject *obj, int fd, GError **err)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static gboolean
|
gboolean
|
||||||
save_mime_object (GMimeObject *obj, const char *fullpath,
|
mu_msg_part_mime_save_object (GMimeObject *obj, const char *fullpath,
|
||||||
gboolean overwrite, gboolean use_existing, GError **err)
|
gboolean overwrite, gboolean use_existing, GError **err)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
gboolean rv;
|
gboolean rv;
|
||||||
@ -498,7 +500,6 @@ mu_msg_part_filepath (MuMsg *msg, const char* targetdir, guint partidx,
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gchar*
|
gchar*
|
||||||
mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
||||||
{
|
{
|
||||||
@ -556,8 +557,8 @@ mu_msg_part_save (MuMsg *msg, const char *fullpath, guint partidx,
|
|||||||
partidx);
|
partidx);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
} else
|
} else
|
||||||
return save_mime_object (part, fullpath, overwrite,
|
return mu_msg_part_mime_save_object (part, fullpath, overwrite,
|
||||||
use_cached, err);
|
use_cached, err);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -76,6 +76,23 @@ struct _MuMsg {
|
|||||||
gchar* mu_msg_mime_part_to_string (GMimePart *part, gboolean *err);
|
gchar* mu_msg_mime_part_to_string (GMimePart *part, gboolean *err);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write a GMimeObject to a file
|
||||||
|
*
|
||||||
|
* @param obj a GMimeObject
|
||||||
|
* @param fullpath full file path
|
||||||
|
* @param overwrite allow overwriting existing file
|
||||||
|
* @param if file already exist, don't bother to write
|
||||||
|
* @param err receives error information
|
||||||
|
*
|
||||||
|
* @return TRUE if writing succeeded, FALSE otherwise.
|
||||||
|
*/
|
||||||
|
gboolean mu_msg_part_mime_save_object (GMimeObject *obj, const char *fullpath,
|
||||||
|
gboolean overwrite, gboolean use_existing,
|
||||||
|
GError **err);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the MIME part that's probably the body of the message (heuristic)
|
* get the MIME part that's probably the body of the message (heuristic)
|
||||||
*
|
*
|
||||||
@ -87,6 +104,9 @@ gchar* mu_msg_mime_part_to_string (GMimePart *part, gboolean *err);
|
|||||||
GMimePart* mu_msg_mime_get_body_part (GMimeMessage *msg, gboolean want_html);
|
GMimePart* mu_msg_mime_get_body_part (GMimeMessage *msg, gboolean want_html);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef BUILD_CRYPTO
|
#ifdef BUILD_CRYPTO
|
||||||
/**
|
/**
|
||||||
* get signature information for the mime part
|
* get signature information for the mime part
|
||||||
@ -100,6 +120,22 @@ GMimePart* mu_msg_mime_get_body_part (GMimeMessage *msg, gboolean want_html);
|
|||||||
*/
|
*/
|
||||||
GSList* mu_msg_mime_sig_infos (GMimeMultipartSigned *sigmpart,
|
GSList* mu_msg_mime_sig_infos (GMimeMultipartSigned *sigmpart,
|
||||||
MuMsgOptions opts, GError **err);
|
MuMsgOptions opts, GError **err);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decrypt the given mime part
|
||||||
|
*
|
||||||
|
* @param encpart
|
||||||
|
* @param opts
|
||||||
|
* @param err
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
char* mu_msg_mime_decrypt (GMimeMultipartEncrypted *encpart,
|
||||||
|
MuMsgOptions opts, GError **err);
|
||||||
|
|
||||||
|
|
||||||
#endif /*BUILD_CRYPTO*/
|
#endif /*BUILD_CRYPTO*/
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|||||||
@ -242,7 +242,7 @@ elvis (const char *s1, const char *s2)
|
|||||||
static const char*
|
static const char*
|
||||||
sig_verdict (GSList *sig_infos)
|
sig_verdict (GSList *sig_infos)
|
||||||
{
|
{
|
||||||
switch (mu_msg_mime_sig_infos_verdict (sig_infos)) {
|
switch (mu_msg_part_sig_infos_verdict (sig_infos)) {
|
||||||
case MU_MSG_PART_SIG_STATUS_GOOD:
|
case MU_MSG_PART_SIG_STATUS_GOOD:
|
||||||
return ":signature good";
|
return ":signature good";
|
||||||
case MU_MSG_PART_SIG_STATUS_BAD:
|
case MU_MSG_PART_SIG_STATUS_BAD:
|
||||||
|
|||||||
@ -414,6 +414,9 @@ enum _MuError {
|
|||||||
MU_ERROR_CONTACTS = 50,
|
MU_ERROR_CONTACTS = 50,
|
||||||
MU_ERROR_CONTACTS_CANNOT_RETRIEVE = 51,
|
MU_ERROR_CONTACTS_CANNOT_RETRIEVE = 51,
|
||||||
|
|
||||||
|
/* crypto related errors */
|
||||||
|
MU_ERROR_CRYPTO = 60,
|
||||||
|
|
||||||
|
|
||||||
/* File errors */
|
/* File errors */
|
||||||
/* generic file-related error */
|
/* generic file-related error */
|
||||||
|
|||||||
Reference in New Issue
Block a user