mirror of https://github.com/djcb/mu.git
* MuMsgPart refactoring / cleanups
This commit is contained in:
parent
c403f0a9c0
commit
6a7562422f
|
@ -518,9 +518,12 @@ gchar*
|
|||
mu_msg_mime_part_to_string (GMimePart *part, gboolean *err)
|
||||
{
|
||||
GMimeDataWrapper *wrapper;
|
||||
GMimeStream *stream = NULL;
|
||||
GMimeStream *stream;
|
||||
ssize_t buflen;
|
||||
char *buffer = NULL;
|
||||
char *buffer;
|
||||
|
||||
buffer = NULL;
|
||||
stream = NULL;
|
||||
|
||||
*err = TRUE; /* guilty until proven innocent */
|
||||
g_return_val_if_fail (GMIME_IS_PART(part), NULL);
|
||||
|
@ -548,13 +551,10 @@ mu_msg_mime_part_to_string (GMimePart *part, gboolean *err)
|
|||
|
||||
/* convert_to_utf8 will free the old 'buffer' if needed */
|
||||
buffer = convert_to_utf8 (part, buffer);
|
||||
|
||||
*err = FALSE;
|
||||
|
||||
cleanup:
|
||||
if (stream)
|
||||
g_object_unref (G_OBJECT(stream));
|
||||
|
||||
g_clear_object (&stream);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
@ -583,33 +583,30 @@ mu_msg_mime_get_body_part (GMimeMessage *msg, gboolean decrypt,
|
|||
|
||||
|
||||
static char*
|
||||
get_body (MuMsgFile *self, gboolean want_html)
|
||||
get_body (MuMsgFile *self, gboolean decrypt, gboolean want_html)
|
||||
{
|
||||
GMimePart *part;
|
||||
gboolean err;
|
||||
gchar *str;
|
||||
|
||||
g_return_val_if_fail (self, NULL);
|
||||
g_return_val_if_fail (GMIME_IS_MESSAGE(self->_mime_msg), NULL);
|
||||
|
||||
part = mu_msg_mime_get_body_part (self->_mime_msg,
|
||||
self->_auto_decrypt,
|
||||
want_html);
|
||||
if (GMIME_IS_PART(part)) {
|
||||
gboolean err;
|
||||
gchar *str;
|
||||
decrypt, want_html);
|
||||
if (!GMIME_IS_PART(part))
|
||||
return NULL;
|
||||
|
||||
err = FALSE;
|
||||
str = mu_msg_mime_part_to_string (part, &err);
|
||||
err = FALSE;
|
||||
str = mu_msg_mime_part_to_string (part, &err);
|
||||
|
||||
/* note, str may be NULL (no body), but that's not necessarily
|
||||
* an error; we only warn when an actual error occured */
|
||||
if (err)
|
||||
g_warning ("error occured while retrieving %s body "
|
||||
"for message %s",
|
||||
want_html ? "html" : "text", self->_path);
|
||||
return str;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
/* note, str may be NULL (no body), but that's not necessarily
|
||||
* an error; we only warn when an actual error occured */
|
||||
if (err)
|
||||
g_warning ("error occured while retrieving %s body "
|
||||
"for message %s",
|
||||
want_html ? "html" : "text", self->_path);
|
||||
return str;
|
||||
}
|
||||
|
||||
|
||||
|
@ -657,7 +654,7 @@ append_text (GMimeObject *parent, GMimeObject *part, gchar **txt)
|
|||
* all text/plain parts with inline disposition
|
||||
*/
|
||||
static char*
|
||||
get_concatenated_text (MuMsgFile *self)
|
||||
get_concatenated_text (MuMsgFile *self, gboolean decrypt)
|
||||
{
|
||||
char *txt;
|
||||
|
||||
|
@ -665,9 +662,9 @@ get_concatenated_text (MuMsgFile *self)
|
|||
g_return_val_if_fail (GMIME_IS_MESSAGE(self->_mime_msg), NULL);
|
||||
|
||||
txt = NULL;
|
||||
mu_mime_message_foreach (self->_mime_msg, self->_auto_decrypt,
|
||||
mu_mime_message_foreach (self->_mime_msg, decrypt,
|
||||
(GMimeObjectForeachFunc)append_text,
|
||||
&txt);
|
||||
&txt);
|
||||
return txt;
|
||||
}
|
||||
|
||||
|
@ -766,8 +763,7 @@ recipient_type (MuMsgFieldId mfid)
|
|||
|
||||
|
||||
char*
|
||||
mu_msg_file_get_str_field (MuMsgFile *self, MuMsgFieldId mfid,
|
||||
gboolean *do_free)
|
||||
mu_msg_file_get_str_field (MuMsgFile *self, MuMsgFieldId mfid, gboolean *do_free)
|
||||
{
|
||||
g_return_val_if_fail (self, NULL);
|
||||
g_return_val_if_fail (mu_msg_field_is_string(mfid), NULL);
|
||||
|
@ -785,9 +781,9 @@ mu_msg_file_get_str_field (MuMsgFile *self, MuMsgFieldId mfid,
|
|||
return get_recipient (self, recipient_type(mfid));
|
||||
|
||||
case MU_MSG_FIELD_ID_BODY_TEXT: *do_free = TRUE;
|
||||
return get_concatenated_text (self);
|
||||
return get_concatenated_text (self, TRUE); /* FIXME: decrypt ? */
|
||||
case MU_MSG_FIELD_ID_BODY_HTML: *do_free = TRUE;
|
||||
return get_body (self, TRUE);
|
||||
return get_body (self, TRUE, TRUE); /* FIXME: decrypt ? */
|
||||
|
||||
case MU_MSG_FIELD_ID_FROM:
|
||||
return (char*)maybe_cleanup
|
||||
|
@ -889,27 +885,19 @@ typedef struct _ForeachData ForeachData;
|
|||
static void
|
||||
foreach_cb (GMimeObject *parent, GMimeObject *part, ForeachData *fdata)
|
||||
{
|
||||
/* invoke the callback function */
|
||||
fdata->user_func (parent, part, fdata->user_data);
|
||||
|
||||
#ifdef BUILD_CRYPTO
|
||||
/* maybe iterate over decrypted parts */
|
||||
if (fdata->decrypt &&
|
||||
GMIME_IS_MULTIPART_ENCRYPTED (part)) {
|
||||
|
||||
GError *err;
|
||||
GMimeObject *dec;
|
||||
|
||||
err = NULL;
|
||||
dec = mu_msg_crypto_decrypt_part
|
||||
(GMIME_MULTIPART_ENCRYPTED(part),
|
||||
MU_MSG_OPTION_NONE, &err);
|
||||
if (!dec||err) {
|
||||
g_printerr ("crypto error: %s\n",
|
||||
err ? err->message : "something went wrong");
|
||||
g_clear_error(&err);
|
||||
g_clear_object(&dec);
|
||||
MU_MSG_OPTION_NONE, NULL, NULL, NULL);
|
||||
if (!dec)
|
||||
return;
|
||||
}
|
||||
|
||||
if (GMIME_IS_MULTIPART (dec))
|
||||
g_mime_multipart_foreach (
|
||||
|
@ -936,7 +924,6 @@ mu_mime_message_foreach (GMimeMessage *msg, gboolean decrypt,
|
|||
|
||||
fdata.user_func = func;
|
||||
fdata.user_data = user_data;
|
||||
fdata.decrypt = decrypt;
|
||||
|
||||
g_mime_message_foreach
|
||||
(msg,
|
||||
|
|
|
@ -27,11 +27,11 @@ typedef struct _MuMsgFile MuMsgFile;
|
|||
|
||||
/**
|
||||
* create a new message from a file
|
||||
*
|
||||
*
|
||||
* @param path full path to the message
|
||||
* @param mdir
|
||||
* @param err error to receive (when function returns NULL), or NULL
|
||||
*
|
||||
*
|
||||
* @return a new MuMsg, or NULL in case of error
|
||||
*/
|
||||
MuMsgFile *mu_msg_file_new (const char *path,
|
||||
|
@ -49,10 +49,10 @@ void mu_msg_file_destroy (MuMsgFile *self);
|
|||
|
||||
/**
|
||||
* get a specific header
|
||||
*
|
||||
*
|
||||
* @param self a MuMsgFile instance
|
||||
* @param header a header (e.g. 'X-Mailer' or 'List-Id')
|
||||
*
|
||||
*
|
||||
* @return the value of the header or NULL if not found. Note, only
|
||||
* valid as long as this MuMsgFile is valid -- before
|
||||
* mu_msg_file_destroy
|
||||
|
@ -62,7 +62,7 @@ const char* mu_msg_file_get_header (MuMsgFile *self, const char *header);
|
|||
|
||||
/**
|
||||
* get a string value for this message
|
||||
*
|
||||
*
|
||||
* @param self a valid MuMsgFile
|
||||
* @param msfid the message field id to get (must be of type string)
|
||||
* @param do_free receives TRUE or FALSE, conveying if this string
|
||||
|
@ -70,7 +70,7 @@ const char* mu_msg_file_get_header (MuMsgFile *self, const char *header);
|
|||
* this function should be treated as if it were returning a const
|
||||
* char*, and note that in that case the string is only valid as long
|
||||
* as the MuMsgFile is alive, ie. before mu_msg_file_destroy
|
||||
*
|
||||
*
|
||||
* @return a string, or NULL
|
||||
*/
|
||||
char* mu_msg_file_get_str_field (MuMsgFile *self,
|
||||
|
@ -81,7 +81,7 @@ char* mu_msg_file_get_str_field (MuMsgFile *self,
|
|||
|
||||
/**
|
||||
* get a string-list value for this message
|
||||
*
|
||||
*
|
||||
* @param self a valid MuMsgFile
|
||||
* @param msfid the message field id to get (must be of type string-list)
|
||||
* @param do_free receives TRUE or FALSE, conveying if this string
|
||||
|
@ -89,7 +89,7 @@ char* mu_msg_file_get_str_field (MuMsgFile *self,
|
|||
* this function should be treated as if it were returning a const
|
||||
* GSList*, and note that in that case the string is only valid as long
|
||||
* as the MuMsgFile is alive, ie. before mu_msg_file_destroy
|
||||
*
|
||||
*
|
||||
* @return a GSList*, or NULL
|
||||
*/
|
||||
GSList* mu_msg_file_get_str_list_field (MuMsgFile *self,
|
||||
|
@ -102,10 +102,10 @@ GSList* mu_msg_file_get_str_list_field (MuMsgFile *self,
|
|||
/**
|
||||
* get a numeric value for this message -- the return value should be
|
||||
* cast into the actual type, e.g., time_t, MuMsgPrio etc.
|
||||
*
|
||||
*
|
||||
* @param self a valid MuMsgFile
|
||||
* @param msfid the message field id to get (must be string-based one)
|
||||
*
|
||||
*
|
||||
* @return the numeric value, or -1 in case of error
|
||||
*/
|
||||
gint64 mu_msg_file_get_num_field (MuMsgFile *self, MuMsgFieldId mfid);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
/* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/
|
||||
|
||||
/*
|
||||
** Copyright (C) 2008-2012 Dirk-Jan C. Binnema <djcb@djcbsoftware.nl>
|
||||
**
|
||||
|
@ -36,63 +35,71 @@
|
|||
#endif /*BUILD_CRYPTO*/
|
||||
|
||||
|
||||
struct _FindPartData {
|
||||
guint idx, wanted_idx;
|
||||
GMimeObject *part;
|
||||
struct _DoData {
|
||||
GMimeObject *mime_obj;
|
||||
unsigned index;
|
||||
};
|
||||
typedef struct _FindPartData FindPartData;
|
||||
|
||||
|
||||
/* is this either a leaf part or an embedded message? */
|
||||
static gboolean
|
||||
is_part_or_message_part (GMimeObject *part)
|
||||
{
|
||||
return GMIME_IS_PART(part) || GMIME_IS_MESSAGE_PART (part);
|
||||
}
|
||||
|
||||
typedef struct _DoData DoData;
|
||||
|
||||
static void
|
||||
find_part_cb (GMimeObject *parent, GMimeObject *part, FindPartData *fpdata)
|
||||
do_it_with_index (MuMsg *msg, MuMsgPart *part, DoData *ddata)
|
||||
{
|
||||
/* ignore other parts */
|
||||
if (!is_part_or_message_part (part))
|
||||
if (ddata->mime_obj)
|
||||
return;
|
||||
|
||||
/* g_printerr ("%u Type-name: %s\n", */
|
||||
/* fpdata->idx, G_OBJECT_TYPE_NAME((GObject*)part)); */
|
||||
|
||||
if (fpdata->part || fpdata->wanted_idx != fpdata->idx++)
|
||||
return; /* not yet found */
|
||||
|
||||
fpdata->part = part;
|
||||
if (part->index == ddata->index)
|
||||
ddata->mime_obj = (GMimeObject*)part->data;
|
||||
}
|
||||
|
||||
static GMimeObject*
|
||||
find_part (MuMsg* msg, guint partidx)
|
||||
get_mime_object_at_index (MuMsg *msg, MuMsgOptions opts, unsigned index)
|
||||
{
|
||||
FindPartData fpdata;
|
||||
DoData ddata;
|
||||
|
||||
fpdata.wanted_idx = partidx;
|
||||
fpdata.idx = 0;
|
||||
fpdata.part = NULL;
|
||||
ddata.mime_obj = NULL;
|
||||
ddata.index = index;
|
||||
|
||||
mu_mime_message_foreach (msg->_file->_mime_msg,
|
||||
mu_msg_get_auto_decrypt(msg),
|
||||
(GMimeObjectForeachFunc)find_part_cb,
|
||||
&fpdata);
|
||||
return fpdata.part;
|
||||
mu_msg_part_foreach (msg, opts,
|
||||
(MuMsgPartForeachFunc)do_it_with_index,
|
||||
&ddata);
|
||||
|
||||
return ddata.mime_obj;
|
||||
}
|
||||
|
||||
struct _PartData {
|
||||
MuMsg *_msg;
|
||||
unsigned _idx;
|
||||
MuMsgPartForeachFunc _func;
|
||||
gpointer _user_data;
|
||||
GMimePart *_body_part;
|
||||
MuMsgOptions _opts;
|
||||
};
|
||||
typedef struct _PartData PartData;
|
||||
|
||||
typedef gboolean (*MuMsgPartMatchFunc) (MuMsgPart *, gpointer);
|
||||
struct _MatchData {
|
||||
MuMsgPartMatchFunc match_func;
|
||||
gpointer user_data;
|
||||
int index;
|
||||
};
|
||||
typedef struct _MatchData MatchData;
|
||||
|
||||
static void
|
||||
check_match (MuMsg *msg, MuMsgPart *part, MatchData *mdata)
|
||||
{
|
||||
if (mdata->index != -1)
|
||||
return;
|
||||
|
||||
if (mdata->match_func (part, mdata->user_data))
|
||||
mdata->index = part->index;
|
||||
}
|
||||
|
||||
int
|
||||
get_matching_part_index (MuMsg *msg, MuMsgOptions opts,
|
||||
MuMsgPartMatchFunc func, gpointer user_data)
|
||||
{
|
||||
MatchData mdata;
|
||||
|
||||
mdata.match_func = func;
|
||||
mdata.user_data = user_data;
|
||||
mdata.index = -1;
|
||||
|
||||
mu_msg_part_foreach (msg, opts,
|
||||
(MuMsgPartForeachFunc)check_match,
|
||||
&mdata);
|
||||
return mdata.index;
|
||||
}
|
||||
|
||||
|
||||
struct _TxtData {
|
||||
|
@ -101,12 +108,10 @@ struct _TxtData {
|
|||
};
|
||||
typedef struct _TxtData TxtData;
|
||||
|
||||
static gchar *mime_message_to_string (GMimeMessage *mimemsg,
|
||||
gboolean decrypt);
|
||||
static gchar *mime_message_to_string (GMimeMessage *mimemsg, gboolean decrypt);
|
||||
|
||||
static void
|
||||
each_mime_part_get_text (GMimeObject *parent, GMimeObject *part,
|
||||
TxtData *tdata)
|
||||
each_mime_part_get_text (GMimeObject *parent, GMimeObject *part, TxtData *tdata)
|
||||
{
|
||||
char *txt;
|
||||
txt = NULL;
|
||||
|
@ -186,16 +191,15 @@ mu_msg_part_get_text (MuMsg *msg, MuMsgPart *self, gboolean *err)
|
|||
|
||||
if (GMIME_IS_PART(mobj)) {
|
||||
/* ignore all but plain text */
|
||||
if ((strcasecmp (self->type, "text") == 0) &&
|
||||
(strcasecmp (self->subtype, "plain") == 0))
|
||||
if ((strcasecmp (self->type, "text") != 0) ||
|
||||
(strcasecmp (self->subtype, "plain") != 0))
|
||||
return NULL;
|
||||
return mu_msg_mime_part_to_string ((GMimePart*)mobj, err);
|
||||
}
|
||||
|
||||
if (GMIME_IS_MESSAGE(mobj))
|
||||
return mime_message_to_string ((GMimeMessage*)mobj,
|
||||
mu_msg_get_auto_decrypt(msg));
|
||||
g_return_val_if_reached (NULL);
|
||||
return mime_message_to_string ((GMimeMessage*)mobj,TRUE);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -209,7 +213,7 @@ get_part_size (GMimePart *part)
|
|||
GMimeStream *stream;
|
||||
|
||||
wrapper = g_mime_part_get_content_object (part);
|
||||
if (!wrapper)
|
||||
if (!GMIME_IS_DATA_WRAPPER(wrapper))
|
||||
return -1;
|
||||
|
||||
stream = g_mime_data_wrapper_get_stream (wrapper);
|
||||
|
@ -218,212 +222,324 @@ get_part_size (GMimePart *part)
|
|||
else
|
||||
return g_mime_stream_length (stream);
|
||||
|
||||
/* NOTE: it seems we shouldn't unref stream/wrapper */
|
||||
/* NOTE: stream/wrapper are owned by gmime, no unreffing */
|
||||
}
|
||||
|
||||
|
||||
#ifdef BUILD_CRYPTO
|
||||
static void
|
||||
check_signature_maybe (GMimeObject *parent, GMimeObject *mobj, MuMsgPart *pi,
|
||||
MuMsgOptions opts)
|
||||
/* #ifdef BUILD_CRYPTO */
|
||||
/* static void */
|
||||
/* check_signature_maybe (GMimeObject *parent, GMimeObject *mobj, MuMsgPart *pi, */
|
||||
/* MuMsgOptions opts) */
|
||||
/* { */
|
||||
/* GMimeContentType *ctype; */
|
||||
/* GError *err; */
|
||||
/* gboolean pkcs7; */
|
||||
|
||||
/* if (!GMIME_IS_MULTIPART_SIGNED (parent)) */
|
||||
/* return; */
|
||||
|
||||
/* ctype = g_mime_object_get_content_type (mobj); */
|
||||
/* if (g_mime_content_type_is_type */
|
||||
/* (ctype, "application", "pgp-signature")) */
|
||||
/* pkcs7 = FALSE; */
|
||||
/* else if (g_mime_content_type_is_type */
|
||||
/* (ctype, "application", "x-pkcs7-signature")) */
|
||||
/* pkcs7 = TRUE; */
|
||||
/* else return; /\* don't know how to handle other kinds *\/ */
|
||||
|
||||
/* if (pkcs7) */
|
||||
/* opts |= MU_MSG_OPTION_USE_PKCS7; /\* gpg is the default *\/ */
|
||||
|
||||
/* err = NULL; */
|
||||
/* pi->sig_infos = mu_msg_mime_sig_infos */
|
||||
/* (GMIME_MULTIPART_SIGNED (parent), opts, &err); */
|
||||
/* if (err) { */
|
||||
/* g_warning ("error verifying signature: %s", err->message); */
|
||||
/* g_clear_error (&err); */
|
||||
/* } */
|
||||
/* } */
|
||||
|
||||
|
||||
|
||||
/* #endif /\*BUILD_CRYPTO*\/ */
|
||||
|
||||
/* static gboolean */
|
||||
/* init_msg_part_from_mime_part (MuMsgOptions opts, GMimeObject *parent, */
|
||||
/* GMimePart *part, MuMsgPart *pi) */
|
||||
/* { */
|
||||
/* const gchar *fname, *descr; */
|
||||
/* GMimeContentType *ct; */
|
||||
|
||||
/* ct = g_mime_object_get_content_type ((GMimeObject*)part); */
|
||||
/* if (GMIME_IS_CONTENT_TYPE(ct)) { */
|
||||
/* pi->type = (char*)g_mime_content_type_get_media_type (ct); */
|
||||
/* pi->subtype = (char*)g_mime_content_type_get_media_subtype (ct); */
|
||||
/* } */
|
||||
|
||||
/* pi->disposition = (char*)g_mime_object_get_disposition */
|
||||
/* ((GMimeObject*)part); */
|
||||
|
||||
/* fname = g_mime_part_get_filename (part); */
|
||||
/* pi->file_name = fname ? mu_str_utf8ify (fname) : NULL; */
|
||||
|
||||
/* descr = g_mime_part_get_content_description (part); */
|
||||
/* pi->description = descr ? mu_str_utf8ify (descr) : NULL; */
|
||||
/* pi->size = get_part_size (part); */
|
||||
/* pi->part_type = MU_MSG_PART_TYPE_LEAF; */
|
||||
|
||||
/* if (!pi->disposition || */
|
||||
/* g_ascii_strcasecmp (pi->disposition, */
|
||||
/* GMIME_DISPOSITION_INLINE) == 0) */
|
||||
/* pi->part_type |= MU_MSG_PART_TYPE_INLINE; */
|
||||
|
||||
/* if (GMIME_IS_MULTIPART_SIGNED (parent)) */
|
||||
/* pi->part_type |= MU_MSG_PART_TYPE_SIGNED; */
|
||||
|
||||
/* /\* if we have crypto support, check the signature if there is one *\/ */
|
||||
/* #ifdef BUILD_CRYPTO */
|
||||
/* if (opts & MU_MSG_OPTION_CHECK_SIGNATURES) */
|
||||
/* check_signature_maybe (parent, (GMimeObject*)part, */
|
||||
/* pi, opts); */
|
||||
/* #endif /\*BUILD_CRYPTO*\/ */
|
||||
|
||||
/* return TRUE; */
|
||||
/* } */
|
||||
|
||||
static char*
|
||||
mime_part_get_filename (GMimeObject *mobj, unsigned index,
|
||||
gboolean construct_if_needed)
|
||||
{
|
||||
GMimeContentType *ctype;
|
||||
GError *err;
|
||||
gboolean pkcs7;
|
||||
gchar *fname, *cur;
|
||||
|
||||
if (!GMIME_IS_MULTIPART_SIGNED (parent))
|
||||
return;
|
||||
|
||||
ctype = g_mime_object_get_content_type (mobj);
|
||||
if (g_mime_content_type_is_type
|
||||
(ctype, "application", "pgp-signature"))
|
||||
pkcs7 = FALSE;
|
||||
else if (g_mime_content_type_is_type
|
||||
(ctype, "application", "x-pkcs7-signature"))
|
||||
pkcs7 = TRUE;
|
||||
else return; /* don't know how to handle other kinds */
|
||||
|
||||
if (pkcs7)
|
||||
opts |= MU_MSG_OPTION_USE_PKCS7; /* gpg is the default */
|
||||
|
||||
err = NULL;
|
||||
pi->sig_infos = mu_msg_mime_sig_infos
|
||||
(GMIME_MULTIPART_SIGNED (parent), opts, &err);
|
||||
if (err) {
|
||||
g_warning ("error verifying signature: %s", err->message);
|
||||
g_clear_error (&err);
|
||||
if (GMIME_IS_PART (mobj)) {
|
||||
/* the easy case: the part has a filename */
|
||||
fname = (gchar*)g_mime_part_get_filename (GMIME_PART(mobj));
|
||||
if (fname) /* don't include directory components */
|
||||
fname = g_path_get_basename (fname);
|
||||
}
|
||||
|
||||
if (!fname && !construct_if_needed)
|
||||
return NULL;
|
||||
|
||||
if (GMIME_IS_MESSAGE_PART(mobj)) {
|
||||
GMimeMessage *msg;
|
||||
const char *subj;
|
||||
msg = g_mime_message_part_get_message
|
||||
(GMIME_MESSAGE_PART(mobj));
|
||||
subj = g_mime_message_get_subject (msg);
|
||||
fname = g_strdup_printf ("%s.eml", subj ? subj : "message");
|
||||
}
|
||||
|
||||
if (!fname)
|
||||
fname = g_strdup_printf ("%u.part", index);
|
||||
|
||||
/* remove slashes, spaces, colons... */
|
||||
for (cur = fname; *cur; ++cur)
|
||||
if (*cur == '/' || *cur == ' ' || *cur == ':')
|
||||
*cur = '-';
|
||||
return fname;
|
||||
}
|
||||
|
||||
|
||||
char*
|
||||
mu_msg_part_get_filename (MuMsgPart *mpart, gboolean construct_if_needed)
|
||||
{
|
||||
g_return_val_if_fail (mpart, NULL);
|
||||
g_return_val_if_fail (GMIME_IS_OBJECT(mpart->data), NULL);
|
||||
|
||||
#endif /*BUILD_CRYPTO*/
|
||||
return mime_part_get_filename ((GMimeObject*)mpart->data,
|
||||
mpart->index, construct_if_needed);
|
||||
}
|
||||
|
||||
|
||||
static MuMsgPartType
|
||||
get_disposition (GMimeObject *mobj)
|
||||
{
|
||||
const char *disp;
|
||||
|
||||
disp = g_mime_object_get_disposition (mobj);
|
||||
if (!disp)
|
||||
return MU_MSG_PART_TYPE_NONE;
|
||||
|
||||
if (strcasecmp (disp, GMIME_DISPOSITION_ATTACHMENT) == 0)
|
||||
return MU_MSG_PART_TYPE_ATTACHMENT;
|
||||
|
||||
if (strcasecmp (disp, GMIME_DISPOSITION_INLINE) == 0)
|
||||
return MU_MSG_PART_TYPE_INLINE;
|
||||
|
||||
return MU_MSG_PART_TYPE_NONE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
init_msg_part_from_mime_part (MuMsgOptions opts, GMimeObject *parent,
|
||||
GMimePart *part, MuMsgPart *pi)
|
||||
handle_children (MuMsg *msg,
|
||||
GMimeObject *mobj, MuMsgOptions opts,
|
||||
unsigned index, MuMsgPartForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
/* call 'func' with information about this MIME-part */
|
||||
static gboolean
|
||||
handle_signed_part (MuMsg *msg,
|
||||
GMimeMultipartSigned *part, GMimeObject *parent,
|
||||
MuMsgOptions opts, unsigned index,
|
||||
MuMsgPartForeachFunc func, gpointer user_data)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* call 'func' with information about this MIME-part */
|
||||
static gboolean
|
||||
handle_encrypted_part (MuMsg *msg,
|
||||
GMimeMultipartEncrypted *part, GMimeObject *parent,
|
||||
MuMsgOptions opts, unsigned index,
|
||||
MuMsgPartForeachFunc func, gpointer user_data)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* call 'func' with information about this MIME-part */
|
||||
static gboolean
|
||||
handle_part (MuMsg *msg, GMimePart *part, GMimeObject *parent,
|
||||
MuMsgOptions opts, unsigned index,
|
||||
MuMsgPartForeachFunc func, gpointer user_data)
|
||||
{
|
||||
const gchar *fname, *descr;
|
||||
GMimeContentType *ct;
|
||||
MuMsgPart msgpart;
|
||||
|
||||
memset (&msgpart, 0, sizeof(MuMsgPart));
|
||||
|
||||
ct = g_mime_object_get_content_type ((GMimeObject*)part);
|
||||
if (GMIME_IS_CONTENT_TYPE(ct)) {
|
||||
pi->type = (char*)g_mime_content_type_get_media_type (ct);
|
||||
pi->subtype = (char*)g_mime_content_type_get_media_subtype (ct);
|
||||
msgpart.type = g_mime_content_type_get_media_type (ct);
|
||||
msgpart.subtype = g_mime_content_type_get_media_subtype (ct);
|
||||
}
|
||||
|
||||
pi->disposition = (char*)g_mime_object_get_disposition
|
||||
((GMimeObject*)part);
|
||||
msgpart.size = get_part_size (part);
|
||||
|
||||
fname = g_mime_part_get_filename (part);
|
||||
pi->file_name = fname ? mu_str_utf8ify (fname) : NULL;
|
||||
msgpart.part_type = MU_MSG_PART_TYPE_LEAF;
|
||||
msgpart.part_type |= get_disposition ((GMimeObject*)part);
|
||||
|
||||
descr = g_mime_part_get_content_description (part);
|
||||
pi->description = descr ? mu_str_utf8ify (descr) : NULL;
|
||||
pi->size = get_part_size (part);
|
||||
pi->part_type = MU_MSG_PART_TYPE_LEAF;
|
||||
/* a top-level non-attachment text part is probably a body */
|
||||
if ((!parent || GMIME_IS_MESSAGE(parent)) &&
|
||||
((msgpart.part_type & MU_MSG_PART_TYPE_ATTACHMENT) == 0) &&
|
||||
g_strcmp0 (msgpart.type, "text") == 0)
|
||||
msgpart.part_type |= MU_MSG_PART_TYPE_BODY;
|
||||
|
||||
if (!pi->disposition ||
|
||||
g_ascii_strcasecmp (pi->disposition,
|
||||
GMIME_DISPOSITION_INLINE) == 0)
|
||||
pi->part_type |= MU_MSG_PART_TYPE_INLINE;
|
||||
msgpart.data = (gpointer)part;
|
||||
msgpart.index = index;
|
||||
|
||||
if (GMIME_IS_MULTIPART_SIGNED (parent))
|
||||
pi->part_type |= MU_MSG_PART_TYPE_SIGNED;
|
||||
if (GMIME_IS_MULTIPART_ENCRYPTED (parent))
|
||||
pi->part_type |= MU_MSG_PART_TYPE_ENCRYPTED;
|
||||
|
||||
/* if we have crypto support, check the signature if there is one */
|
||||
#ifdef BUILD_CRYPTO
|
||||
if (opts & MU_MSG_OPTION_CHECK_SIGNATURES)
|
||||
check_signature_maybe (parent, (GMimeObject*)part,
|
||||
pi, opts);
|
||||
#endif /*BUILD_CRYPTO*/
|
||||
func (msg, &msgpart, user_data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
get_filename_for_mime_message_part (GMimeMessage *mmsg)
|
||||
|
||||
/* call 'func' with information about this MIME-part */
|
||||
static gboolean
|
||||
handle_message_part (MuMsg *msg, GMimeMessagePart *mmsg, GMimeObject *parent,
|
||||
MuMsgOptions opts, unsigned index,
|
||||
MuMsgPartForeachFunc func, gpointer user_data)
|
||||
{
|
||||
gchar *name, *cur;
|
||||
MuMsgPart msgpart;
|
||||
memset (&msgpart, 0, sizeof(MuMsgPart));
|
||||
|
||||
name = (char*)g_mime_message_get_subject (mmsg);
|
||||
if (!name)
|
||||
name = "message";
|
||||
msgpart.type = "message";
|
||||
msgpart.subtype = "rfc822";
|
||||
msgpart.index = index;
|
||||
|
||||
name = g_strconcat (name, ".eml", NULL);
|
||||
/* msgpart.size = 0; /\* maybe calculate this? *\/ */
|
||||
|
||||
/* remove slashes... */
|
||||
for (cur = name ; *cur; ++cur) {
|
||||
if (*cur == '/' || *cur == ' ' || *cur == ':')
|
||||
*cur = '-';
|
||||
msgpart.part_type = MU_MSG_PART_TYPE_MESSAGE;
|
||||
msgpart.part_type |= get_disposition ((GMimeObject*)mmsg);
|
||||
|
||||
msgpart.data = (gpointer)mmsg;
|
||||
|
||||
func (msg, &msgpart, user_data);
|
||||
|
||||
if (opts & MU_MSG_OPTION_RECURSE_RFC822) {
|
||||
GMimeMessage *mime_msg;
|
||||
mime_msg = g_mime_message_part_get_message (mmsg);
|
||||
return handle_children
|
||||
(msg,
|
||||
(GMimeObject*)mime_msg,
|
||||
opts, index, func, user_data);
|
||||
}
|
||||
|
||||
return name;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
init_msg_part_from_mime_message_part (GMimeMessage *mmsg, MuMsgPart *pi)
|
||||
handle_mime_object (MuMsg *msg,
|
||||
GMimeObject *mobj, GMimeObject *parent, MuMsgOptions opts,
|
||||
unsigned index, MuMsgPartForeachFunc func, gpointer user_data)
|
||||
{
|
||||
pi->disposition = GMIME_DISPOSITION_ATTACHMENT;
|
||||
|
||||
/* pseudo-file name... */
|
||||
pi->file_name = get_filename_for_mime_message_part (mmsg);
|
||||
pi->description = g_strdup ("message");
|
||||
pi->type = "message";
|
||||
pi->subtype = "rfc822";
|
||||
pi->size = 0;
|
||||
pi->part_type = MU_MSG_PART_TYPE_MESSAGE;
|
||||
if (GMIME_IS_PART (mobj))
|
||||
return handle_part
|
||||
(msg, GMIME_PART(mobj), parent,
|
||||
opts, index, func, user_data);
|
||||
else if (GMIME_IS_MESSAGE_PART (mobj))
|
||||
return handle_message_part
|
||||
(msg, GMIME_MESSAGE_PART(mobj),
|
||||
parent, opts, index, func, user_data);
|
||||
else if (GMIME_IS_MULTIPART_SIGNED (mobj))
|
||||
return handle_signed_part
|
||||
(msg, GMIME_MULTIPART_SIGNED (mobj),
|
||||
parent, opts, index, func, user_data);
|
||||
else if (GMIME_IS_MULTIPART_ENCRYPTED (mobj))
|
||||
return handle_encrypted_part
|
||||
(msg, GMIME_MULTIPART_ENCRYPTED (mobj),
|
||||
parent, opts, index, func, user_data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
msg_part_free (MuMsgPart *pi)
|
||||
static gboolean
|
||||
handle_children (MuMsg *msg,
|
||||
GMimeObject *mobj, MuMsgOptions opts,
|
||||
unsigned index, MuMsgPartForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (!pi)
|
||||
return;
|
||||
|
||||
g_free (pi->file_name);
|
||||
g_free (pi->description);
|
||||
|
||||
#ifdef BUILD_CRYPTO
|
||||
mu_msg_part_free_sig_infos (pi->sig_infos);
|
||||
#endif /*BUILD_CRYPTO*/
|
||||
}
|
||||
|
||||
static void
|
||||
part_foreach_cb (GMimeObject *parent, GMimeObject *mobj, PartData *pdata)
|
||||
{
|
||||
MuMsgPart pi;
|
||||
gboolean rv;
|
||||
GMimePartIter *iter;
|
||||
|
||||
/* ignore other non-leaf / message parts */
|
||||
if (!is_part_or_message_part (mobj))
|
||||
return;
|
||||
/* the children */
|
||||
iter = g_mime_part_iter_new (mobj);
|
||||
|
||||
memset (&pi, 0, sizeof(pi));
|
||||
pi.index = pdata->_idx++;
|
||||
pi.content_id = (char*)g_mime_object_get_content_id (mobj);
|
||||
if (!iter)
|
||||
return FALSE;
|
||||
for (rv = TRUE; rv && g_mime_part_iter_is_valid (iter);
|
||||
g_mime_part_iter_next (iter), index++)
|
||||
rv = handle_mime_object (
|
||||
msg, g_mime_part_iter_get_current (iter),
|
||||
g_mime_part_iter_get_parent (iter),
|
||||
opts, index, func, user_data);
|
||||
|
||||
if (GMIME_IS_PART(mobj)) {
|
||||
pi.data = (gpointer)mobj;
|
||||
rv = init_msg_part_from_mime_part
|
||||
(pdata->_opts, parent, (GMimePart*)mobj, &pi);
|
||||
g_mime_part_iter_free (iter);
|
||||
|
||||
/* check if this is the body part */
|
||||
if (rv && (void*)pdata->_body_part == (void*)mobj)
|
||||
pi.part_type |= MU_MSG_PART_TYPE_BODY;
|
||||
|
||||
} else if (GMIME_IS_MESSAGE_PART(mobj)) {
|
||||
|
||||
GMimeMessage *mmsg;
|
||||
mmsg = g_mime_message_part_get_message ((GMimeMessagePart*)mobj);
|
||||
if (!mmsg)
|
||||
return;
|
||||
/* use the message, not the message part */
|
||||
pi.data = (gpointer)mmsg;
|
||||
rv = init_msg_part_from_mime_message_part (mmsg, &pi);
|
||||
|
||||
} else
|
||||
rv = FALSE; /* ignore */
|
||||
|
||||
if (rv)
|
||||
pdata->_func(pdata->_msg, &pi, pdata->_user_data);
|
||||
|
||||
msg_part_free (&pi);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
mu_msg_part_foreach (MuMsg *msg, MuMsgPartForeachFunc func, gpointer user_data,
|
||||
MuMsgOptions opts)
|
||||
gboolean
|
||||
mu_msg_part_foreach (MuMsg *msg, MuMsgOptions opts,
|
||||
MuMsgPartForeachFunc func, gpointer user_data)
|
||||
{
|
||||
PartData pdata;
|
||||
GMimeMessage *mime_msg;
|
||||
GMimeObject *toplevel;
|
||||
unsigned idx;
|
||||
|
||||
g_return_if_fail (msg);
|
||||
g_return_val_if_fail (msg, FALSE);
|
||||
|
||||
if (!mu_msg_load_msg_file (msg, NULL))
|
||||
return;
|
||||
return FALSE;
|
||||
|
||||
mime_msg = msg->_file->_mime_msg;
|
||||
idx = 0;
|
||||
toplevel = g_mime_message_get_mime_part
|
||||
(GMIME_MESSAGE(msg->_file->_mime_msg));
|
||||
if (!toplevel || !handle_mime_object
|
||||
(msg, toplevel, NULL, opts, idx++, func, user_data))
|
||||
return FALSE;
|
||||
|
||||
pdata._msg = msg;
|
||||
pdata._idx = 0;
|
||||
pdata._body_part = mu_msg_mime_get_body_part
|
||||
(mime_msg, mu_msg_get_auto_decrypt(msg), FALSE);
|
||||
pdata._func = func;
|
||||
pdata._user_data = user_data;
|
||||
pdata._opts = opts;
|
||||
|
||||
mu_mime_message_foreach (msg->_file->_mime_msg,
|
||||
mu_msg_get_auto_decrypt(msg),
|
||||
(GMimeObjectForeachFunc)part_foreach_cb,
|
||||
&pdata);
|
||||
return handle_children (msg, toplevel, opts, idx, func,
|
||||
user_data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -490,13 +606,16 @@ write_object_to_fd (GMimeObject *obj, int fd, GError **err)
|
|||
}
|
||||
|
||||
|
||||
|
||||
gboolean
|
||||
mu_msg_part_mime_save_object (GMimeObject *obj, const char *fullpath,
|
||||
gboolean overwrite, gboolean use_existing, GError **err)
|
||||
static gboolean
|
||||
save_object (GMimeObject *obj, MuMsgOptions opts, const char *fullpath,
|
||||
GError **err)
|
||||
{
|
||||
int fd;
|
||||
gboolean rv;
|
||||
gboolean use_existing, overwrite;
|
||||
|
||||
use_existing = opts & MU_MSG_OPTION_USE_EXISTING;
|
||||
overwrite = opts & MU_MSG_OPTION_OVERWRITE;
|
||||
|
||||
/* don't try to overwrite when we already have it; useful when
|
||||
* you're sure it's not a different file with the same name */
|
||||
|
@ -529,41 +648,25 @@ mu_msg_part_mime_save_object (GMimeObject *obj, const char *fullpath,
|
|||
|
||||
|
||||
gchar*
|
||||
mu_msg_part_filepath (MuMsg *msg, const char* targetdir, guint partidx,
|
||||
GError **err)
|
||||
mu_msg_part_get_path (MuMsg *msg, MuMsgOptions opts,
|
||||
const char* targetdir, unsigned index, GError **err)
|
||||
{
|
||||
char *fname, *filepath;
|
||||
GMimeObject* mobj;
|
||||
|
||||
g_return_val_if_fail (msg, NULL);
|
||||
|
||||
if (!mu_msg_load_msg_file (msg, NULL))
|
||||
return NULL;
|
||||
|
||||
if (!(mobj = find_part (msg, partidx))) {
|
||||
mu_util_g_set_error (err,MU_ERROR_GMIME,
|
||||
"cannot find part %u", partidx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (GMIME_IS_PART (mobj)) {
|
||||
/* the easy case: the part has a filename */
|
||||
fname = (gchar*)g_mime_part_get_filename (GMIME_PART(mobj));
|
||||
if (fname) /* security: don't includ directory
|
||||
* components */
|
||||
fname = g_path_get_basename (fname);
|
||||
else
|
||||
fname = g_strdup_printf ("%x-part-%u",
|
||||
g_str_hash (mu_msg_get_path (msg)),
|
||||
partidx);
|
||||
} else if (GMIME_IS_MESSAGE_PART(mobj))
|
||||
fname = get_filename_for_mime_message_part
|
||||
(g_mime_message_part_get_message
|
||||
((GMimeMessagePart*)mobj));
|
||||
else {
|
||||
mobj = get_mime_object_at_index (msg, opts, index);
|
||||
if (!mobj){
|
||||
mu_util_g_set_error (err, MU_ERROR_GMIME,
|
||||
"part %u cannot be saved", partidx);
|
||||
"cannot find part %u", index);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fname = mime_part_get_filename (mobj, index, TRUE);
|
||||
filepath = g_build_path (G_DIR_SEPARATOR_S, targetdir ? targetdir : "",
|
||||
fname, NULL);
|
||||
g_free (fname);
|
||||
|
@ -574,7 +677,8 @@ mu_msg_part_filepath (MuMsg *msg, const char* targetdir, guint partidx,
|
|||
|
||||
|
||||
gchar*
|
||||
mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
||||
mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts, guint partid,
|
||||
GError **err)
|
||||
{
|
||||
char *dirname, *filepath;
|
||||
const char* path;
|
||||
|
@ -585,8 +689,6 @@ mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
|||
return NULL;
|
||||
|
||||
path = mu_msg_get_path (msg);
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
/* g_compute_checksum_for_string may be better, but requires
|
||||
* rel. new glib (2.16) */
|
||||
|
@ -596,61 +698,56 @@ mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
|||
partid);
|
||||
|
||||
if (!mu_util_create_dir_maybe (dirname, 0700, FALSE)) {
|
||||
mu_util_g_set_error (err, MU_ERROR_FILE, "failed to create dir %s",
|
||||
dirname);
|
||||
g_free (dirname);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
filepath = mu_msg_part_filepath (msg, dirname, partid, NULL);
|
||||
filepath = mu_msg_part_get_path (msg, opts, dirname, partid, err);
|
||||
g_free (dirname);
|
||||
if (!filepath)
|
||||
g_warning ("%s: could not get filename", __FUNCTION__);
|
||||
|
||||
return filepath;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
mu_msg_part_save (MuMsg *msg, const char *fullpath, guint partidx,
|
||||
gboolean overwrite, gboolean use_cached, GError **err)
|
||||
mu_msg_part_save (MuMsg *msg, MuMsgOptions opts,
|
||||
const char *fullpath, guint partidx, GError **err)
|
||||
{
|
||||
GMimeObject *part;
|
||||
|
||||
g_return_val_if_fail (msg, FALSE);
|
||||
g_return_val_if_fail (fullpath, FALSE);
|
||||
g_return_val_if_fail (!overwrite||!use_cached, FALSE);
|
||||
g_return_val_if_fail (!((opts & MU_MSG_OPTION_OVERWRITE) &&
|
||||
(opts & MU_MSG_OPTION_USE_EXISTING)), FALSE);
|
||||
|
||||
if (!mu_msg_load_msg_file (msg, err))
|
||||
return FALSE;
|
||||
|
||||
part = find_part (msg, partidx);
|
||||
if (!is_part_or_message_part (part)) {
|
||||
part = get_mime_object_at_index (msg, opts, partidx);
|
||||
if (!GMIME_IS_PART(part) || GMIME_IS_MESSAGE_PART(part)) {
|
||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_GMIME,
|
||||
"unexpected type %s for part %u",
|
||||
G_OBJECT_TYPE_NAME((GObject*)part),
|
||||
partidx);
|
||||
return FALSE;
|
||||
} else
|
||||
return mu_msg_part_mime_save_object (part, fullpath, overwrite,
|
||||
use_cached, err);
|
||||
}
|
||||
|
||||
return save_object (part, opts, fullpath, err);
|
||||
}
|
||||
|
||||
|
||||
gchar*
|
||||
mu_msg_part_save_temp (MuMsg *msg, guint partidx, GError **err)
|
||||
mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts, guint partidx, GError **err)
|
||||
{
|
||||
gchar *filepath;
|
||||
gboolean rv;
|
||||
|
||||
filepath = mu_msg_part_filepath_cache (msg, partidx);
|
||||
if (!filepath) {
|
||||
g_set_error (err, MU_ERROR_DOMAIN, MU_ERROR_FILE,
|
||||
"Could not get temp filepath");
|
||||
filepath = mu_msg_part_get_cache_path (msg, opts, partidx, err);
|
||||
if (!filepath)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rv = mu_msg_part_save (msg, filepath, partidx, FALSE, TRUE, err);
|
||||
if (!rv) {
|
||||
if (!mu_msg_part_save (msg, opts, filepath, partidx, err)) {
|
||||
g_free (filepath);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -658,59 +755,18 @@ mu_msg_part_save_temp (MuMsg *msg, guint partidx, GError **err)
|
|||
return filepath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
typedef gboolean (*MatchFunc) (GMimeObject *part, gpointer data);
|
||||
|
||||
struct _MatchData {
|
||||
MatchFunc _matcher;
|
||||
gpointer _user_data;
|
||||
gint _idx, _found_idx;
|
||||
};
|
||||
typedef struct _MatchData MatchData;
|
||||
|
||||
static void
|
||||
part_match_foreach_cb (GMimeObject *parent, GMimeObject *part,
|
||||
MatchData *mdata)
|
||||
{
|
||||
if (mdata->_found_idx < 0)
|
||||
if (mdata->_matcher (part, mdata->_user_data))
|
||||
mdata->_found_idx = mdata->_idx;
|
||||
|
||||
++mdata->_idx;
|
||||
}
|
||||
|
||||
static int
|
||||
msg_part_find_idx (GMimeMessage *mimemsg, gboolean auto_decrypt,
|
||||
MatchFunc func, gpointer user_data)
|
||||
{
|
||||
MatchData mdata;
|
||||
|
||||
g_return_val_if_fail (mimemsg, -1);
|
||||
g_return_val_if_fail (GMIME_IS_MESSAGE(mimemsg), -1);
|
||||
|
||||
mdata._idx = 0;
|
||||
mdata._found_idx = -1;
|
||||
mdata._matcher = func;
|
||||
mdata._user_data = user_data;
|
||||
|
||||
mu_mime_message_foreach (mimemsg, auto_decrypt,
|
||||
(GMimeObjectForeachFunc)part_match_foreach_cb,
|
||||
&mdata);
|
||||
|
||||
return mdata._found_idx;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
match_content_id (GMimeObject *part, const char *cid)
|
||||
match_cid (MuMsgPart *mpart, const char *cid)
|
||||
{
|
||||
return g_strcmp0 (g_mime_object_get_content_id (part),
|
||||
cid) == 0 ? TRUE : FALSE;
|
||||
const char *this_cid;
|
||||
|
||||
this_cid = g_mime_object_get_content_id ((GMimeObject*)mpart->data);
|
||||
|
||||
return g_strcmp0 (this_cid, cid) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
mu_msg_part_find_cid (MuMsg *msg, const char* sought_cid)
|
||||
mu_msg_find_index_for_cid (MuMsg *msg, MuMsgOptions opts, const char *sought_cid)
|
||||
{
|
||||
const char* cid;
|
||||
|
||||
|
@ -723,53 +779,43 @@ mu_msg_part_find_cid (MuMsg *msg, const char* sought_cid)
|
|||
cid = g_str_has_prefix (sought_cid, "cid:") ?
|
||||
sought_cid + 4 : sought_cid;
|
||||
|
||||
return msg_part_find_idx (msg->_file->_mime_msg,
|
||||
mu_msg_get_auto_decrypt(msg),
|
||||
(MatchFunc)match_content_id,
|
||||
(gpointer)(char*)cid);
|
||||
return get_matching_part_index (msg, opts,
|
||||
(MuMsgPartMatchFunc)match_cid,
|
||||
(gpointer)(char*)cid);
|
||||
}
|
||||
|
||||
struct _MatchData2 {
|
||||
GSList *_lst;
|
||||
struct _RxMatchData {
|
||||
GSList *_lst;
|
||||
const GRegex *_rx;
|
||||
guint _idx;
|
||||
};
|
||||
typedef struct _MatchData2 MatchData2;
|
||||
typedef struct _RxMatchData RxMatchData;
|
||||
|
||||
|
||||
static void
|
||||
match_filename_rx (GMimeObject *parent, GMimeObject *part, MatchData2 *mdata)
|
||||
match_filename_rx (MuMsg *msg, MuMsgPart *mpart, RxMatchData *mdata)
|
||||
{
|
||||
const char *fname;
|
||||
char *fname;
|
||||
|
||||
/* ignore other parts -- we need this guard so the counting of
|
||||
* parts is the same as in other functions for dealing with
|
||||
* msg parts (this is needed since we expose the numbers to
|
||||
* the user) */
|
||||
if (!is_part_or_message_part (part))
|
||||
fname = mu_msg_part_get_filename (mpart, FALSE);
|
||||
if (!fname)
|
||||
return;
|
||||
|
||||
fname = g_mime_part_get_filename (GMIME_PART(part));
|
||||
if (!fname) {
|
||||
++mdata->_idx;
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_regex_match (mdata->_rx, fname, 0, NULL))
|
||||
mdata->_lst = g_slist_prepend (mdata->_lst,
|
||||
GUINT_TO_POINTER(mdata->_idx++));
|
||||
GUINT_TO_POINTER(mpart->index));
|
||||
g_free (fname);
|
||||
}
|
||||
|
||||
|
||||
GSList*
|
||||
mu_msg_part_find_files (MuMsg *msg, const GRegex *pattern)
|
||||
mu_msg_find_files (MuMsg *msg, MuMsgOptions opts, const GRegex *pattern)
|
||||
{
|
||||
MatchData2 mdata;
|
||||
RxMatchData mdata;
|
||||
|
||||
g_return_val_if_fail (msg, NULL);
|
||||
g_return_val_if_fail (pattern, NULL);
|
||||
|
||||
|
||||
if (!mu_msg_load_msg_file (msg, NULL))
|
||||
return NULL;
|
||||
|
||||
|
@ -777,17 +823,15 @@ mu_msg_part_find_files (MuMsg *msg, const GRegex *pattern)
|
|||
mdata._rx = pattern;
|
||||
mdata._idx = 0;
|
||||
|
||||
mu_mime_message_foreach (msg->_file->_mime_msg,
|
||||
mu_msg_get_auto_decrypt(msg),
|
||||
(GMimeObjectForeachFunc)match_filename_rx,
|
||||
&mdata);
|
||||
mu_msg_part_foreach (msg, opts,
|
||||
(MuMsgPartForeachFunc)match_filename_rx,
|
||||
&mdata);
|
||||
return mdata._lst;
|
||||
}
|
||||
|
||||
|
||||
gboolean
|
||||
mu_msg_part_looks_like_attachment (MuMsgPart *part,
|
||||
gboolean include_inline)
|
||||
mu_msg_part_looks_like_attachment (MuMsgPart *part, gboolean include_inline)
|
||||
{
|
||||
g_return_val_if_fail (part, FALSE);
|
||||
|
||||
|
|
|
@ -38,10 +38,14 @@ enum _MuMsgPartType {
|
|||
MU_MSG_PART_TYPE_MESSAGE = 1 << 2,
|
||||
/* disposition inline? */
|
||||
MU_MSG_PART_TYPE_INLINE = 1 << 3,
|
||||
/* disposition attachment? */
|
||||
MU_MSG_PART_TYPE_ATTACHMENT = 1 << 4,
|
||||
/* a signed part? */
|
||||
MU_MSG_PART_TYPE_SIGNED = 1 << 5,
|
||||
/* an encrypted part? */
|
||||
MU_MSG_PART_TYPE_ENCRYPTED = 1 << 6
|
||||
MU_MSG_PART_TYPE_ENCRYPTED = 1 << 6,
|
||||
/* a decrypted part? */
|
||||
MU_MSG_PART_TYPE_DECRYPTED = 1 << 7
|
||||
};
|
||||
typedef enum _MuMsgPartType MuMsgPartType;
|
||||
|
||||
|
@ -52,22 +56,11 @@ struct _MuMsgPart {
|
|||
unsigned index;
|
||||
|
||||
/* cid */
|
||||
char *content_id;
|
||||
/* const char *content_id; */
|
||||
|
||||
/* content-type: type/subtype, ie. text/plain */
|
||||
char *type;
|
||||
char *subtype;
|
||||
/* full content-type, e.g. image/jpeg */
|
||||
/* char *content_type; */
|
||||
|
||||
/* the file name (if any) */
|
||||
char *file_name;
|
||||
|
||||
/* description (if any) */
|
||||
char *description;
|
||||
|
||||
/* usually, "attachment" or "inline" */
|
||||
char *disposition;
|
||||
const char *type;
|
||||
const char *subtype;
|
||||
|
||||
/* size of the part; or < 0 if unknown */
|
||||
ssize_t size;
|
||||
|
@ -78,41 +71,20 @@ struct _MuMsgPart {
|
|||
|
||||
/* crypto stuff */
|
||||
GSList *sig_infos; /* list of MuMsgPartSig */
|
||||
|
||||
/* if TRUE, mu_msg_part_destroy will free the member vars
|
||||
* as well*/
|
||||
gboolean own_members;
|
||||
};
|
||||
};
|
||||
typedef struct _MuMsgPart MuMsgPart;
|
||||
|
||||
/**
|
||||
* macro to get the file name for this mime-part
|
||||
* get some appropriate file name for the mime-part
|
||||
*
|
||||
* @param pi a MuMsgPart instance
|
||||
* @param mpart a MuMsgPart
|
||||
* @param construct_if_needed if there is no
|
||||
* real filename, construct one.
|
||||
*
|
||||
* @return the file name
|
||||
* @return the file name (free with g_free)
|
||||
*/
|
||||
#define mu_msg_part_file_name(pi) ((pi)->file_name)
|
||||
|
||||
|
||||
/**
|
||||
* macro to get the description for this mime-part
|
||||
*
|
||||
* @param pi a MuMsgPart instance
|
||||
*
|
||||
* @return the description
|
||||
*/
|
||||
#define mu_msg_part_description(pi) ((pi)->description)
|
||||
|
||||
|
||||
/**
|
||||
* macro to get the content-id (cid) for this mime-part
|
||||
*
|
||||
* @param pi a MuMsgPart instance
|
||||
*
|
||||
* @return the file name
|
||||
*/
|
||||
#define mu_msg_part_content_id(pi) ((pi)->content_id)
|
||||
char *mu_msg_part_get_filename (MuMsgPart *mpart, gboolean construct_if_needed)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -123,7 +95,8 @@ typedef struct _MuMsgPart MuMsgPart;
|
|||
*
|
||||
* @return utf8 string for this MIME part, to be freed by caller
|
||||
*/
|
||||
char* mu_msg_part_get_text (MuMsg *msg, MuMsgPart *part, gboolean *err);
|
||||
char* mu_msg_part_get_text (MuMsg *msg, MuMsgPart *part, gboolean *err)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -142,16 +115,17 @@ gboolean mu_msg_part_looks_like_attachment (MuMsgPart *part,
|
|||
* save a specific attachment to some targetdir
|
||||
*
|
||||
* @param msg a valid MuMsg instance
|
||||
* @param opts mu-message options (OVERWRITE/USE_EXISTING)
|
||||
* @gchar filepath the filepath to save
|
||||
* @param partidx index of the attachment you want to save
|
||||
* @param overwrite overwrite existing files?
|
||||
* @param don't raise error when the file already exists
|
||||
* @param err receives error information (when function returns NULL)
|
||||
*
|
||||
* @return full path to the message part saved or NULL in case or error; free with g_free
|
||||
* @return full path to the message part saved or NULL in case or
|
||||
* error; free with g_free
|
||||
*/
|
||||
gboolean mu_msg_part_save (MuMsg *msg, const char *filepath, guint partidx,
|
||||
gboolean overwrite, gboolean use_cached, GError **err);
|
||||
gboolean mu_msg_part_save (MuMsg *msg, MuMsgOptions opts,
|
||||
const char *filepath, guint partidx,
|
||||
GError **err);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -159,13 +133,15 @@ gboolean mu_msg_part_save (MuMsg *msg, const char *filepath, guint partidx,
|
|||
* this file
|
||||
*
|
||||
* @param msg a MuMsg message
|
||||
* @param opts mu-message options (OVERWRITE/USE_EXISTING)
|
||||
* @param partidx index of the part to save
|
||||
* @param err receives error information if any
|
||||
*
|
||||
* @return the full path to the temp file, or NULL in case of error
|
||||
*/
|
||||
gchar* mu_msg_part_save_temp (MuMsg *msg, guint partidx, GError **err);
|
||||
|
||||
gchar* mu_msg_part_save_temp (MuMsg *msg, MuMsgOptions opts,
|
||||
guint partidx, GError **err)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
|
||||
|
@ -175,14 +151,17 @@ gchar* mu_msg_part_save_temp (MuMsg *msg, guint partidx, GError **err);
|
|||
* name based on the partidx and the message path
|
||||
*
|
||||
* @param msg a msg
|
||||
* @param opts mu-message options
|
||||
* @param targetdir where to store the part
|
||||
* @param partidx the part for which to determine a filename
|
||||
* @param err receives error information (when function returns NULL)
|
||||
*
|
||||
* @return a filepath (g_free when done with it) or NULL in case of error
|
||||
*/
|
||||
gchar* mu_msg_part_filepath (MuMsg *msg, const char* targetdir,
|
||||
guint partidx, GError **err) G_GNUC_WARN_UNUSED_RESULT;
|
||||
gchar* mu_msg_part_get_path (MuMsg *msg, MuMsgOptions opts,
|
||||
const char* targetdir,
|
||||
guint partidx, GError **err)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -193,11 +172,14 @@ gchar* mu_msg_part_filepath (MuMsg *msg, const char* targetdir,
|
|||
* Will create the directory if needed.
|
||||
*
|
||||
* @param msg a msg
|
||||
* @param opts mu-message options
|
||||
* @param partidx the part for which to determine a filename
|
||||
* @param err receives error information (when function returns NULL)
|
||||
*
|
||||
* @return a filepath (g_free when done with it) or NULL in case of error
|
||||
*/
|
||||
gchar* mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
||||
gchar* mu_msg_part_get_cache_path (MuMsg *msg, MuMsgOptions opts,
|
||||
guint partidx, GError **err)
|
||||
G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
|
||||
|
@ -209,7 +191,7 @@ gchar* mu_msg_part_filepath_cache (MuMsg *msg, guint partid)
|
|||
*
|
||||
* @return the part index number of the found part, or -1 if it was not found
|
||||
*/
|
||||
int mu_msg_part_find_cid (MuMsg *msg, const char* content_id);
|
||||
int mu_msg_find_index_for_cid (MuMsg *msg, MuMsgOptions opts, const char* content_id);
|
||||
|
||||
|
||||
|
||||
|
@ -217,16 +199,17 @@ int mu_msg_part_find_cid (MuMsg *msg, const char* content_id);
|
|||
* retrieve a list of indices for mime-parts with filenames matching a regex
|
||||
*
|
||||
* @param msg a message
|
||||
* @param opts
|
||||
* @param a regular expression to match the filename with
|
||||
*
|
||||
* @return a list with indices for the files matching the pattern; the
|
||||
* indices are the GPOINTER_TO_UINT(lst->data) of the list. They must
|
||||
* be freed with g_slist_free
|
||||
*/
|
||||
GSList* mu_msg_part_find_files (MuMsg *msg, const GRegex *pattern);
|
||||
GSList* mu_msg_find_files (MuMsg *msg, MuMsgOptions opts, const GRegex *pattern);
|
||||
|
||||
|
||||
typedef void (*MuMsgPartForeachFunc) (MuMsg*, MuMsgPart*, gpointer);
|
||||
typedef void (*MuMsgPartForeachFunc) (MuMsg *msg, MuMsgPart*, gpointer);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -239,8 +222,8 @@ typedef void (*MuMsgPartForeachFunc) (MuMsg*, MuMsgPart*, gpointer);
|
|||
* @param options, bit-wise OR'ed
|
||||
*
|
||||
*/
|
||||
void mu_msg_part_foreach (MuMsg *msg, MuMsgPartForeachFunc func, gpointer user_data,
|
||||
MuMsgOptions opts);
|
||||
gboolean mu_msg_part_foreach (MuMsg *msg, MuMsgOptions opts,
|
||||
MuMsgPartForeachFunc func, gpointer user_data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
|
|
@ -44,9 +44,6 @@ struct _MuMsgFile {
|
|||
char _path [PATH_MAX + 1];
|
||||
char _maildir [PATH_MAX + 1];
|
||||
|
||||
/* whether to attemp to automagically decrypt encrypted parts */
|
||||
gboolean _auto_decrypt;
|
||||
|
||||
/* list where we push allocated strings so we can
|
||||
* free them when the struct gets destroyed
|
||||
*/
|
||||
|
@ -79,20 +76,20 @@ struct _MuMsg {
|
|||
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);
|
||||
/* /\** */
|
||||
/* * 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); */
|
||||
|
||||
|
||||
|
||||
|
@ -111,14 +108,18 @@ GMimePart* mu_msg_mime_get_body_part (GMimeMessage *msg, gboolean decrypt,
|
|||
|
||||
/**
|
||||
* Like g_mime_message_foreach, but will recurse into encrypted parts
|
||||
* if @param decrypt is TRUE and mu was built with crypto support
|
||||
*
|
||||
* @param msg
|
||||
* @param msg a GMimeMessage
|
||||
* @param decrypt whether to try to automatically decrypt
|
||||
* @param func
|
||||
* @param user_data
|
||||
* @param func user callback function for each part
|
||||
* @param user_data user point passed to callback function
|
||||
* @param err receives error information
|
||||
*
|
||||
*/
|
||||
void mu_mime_message_foreach (GMimeMessage *msg, gboolean decrypt,
|
||||
GMimeObjectForeachFunc func, gpointer user_data);
|
||||
GMimeObjectForeachFunc func,
|
||||
gpointer user_data);
|
||||
|
||||
#ifdef BUILD_CRYPTO
|
||||
/**
|
||||
|
@ -134,32 +135,32 @@ void mu_mime_message_foreach (GMimeMessage *msg, gboolean decrypt,
|
|||
GSList* mu_msg_mime_sig_infos (GMimeMultipartSigned *sigmpart,
|
||||
MuMsgOptions opts, GError **err);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* decrypt the given mime part
|
||||
* callback function to retrieve a password from the user
|
||||
*
|
||||
* @param encpart
|
||||
* @param opts
|
||||
* @param err
|
||||
* @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
|
||||
* @return a newly allocated (g_free'able) string
|
||||
*/
|
||||
char* mu_msg_mime_decrypt (GMimeMultipartEncrypted *encpart,
|
||||
MuMsgOptions opts, GError **err);
|
||||
|
||||
|
||||
typedef char* (*MuMsgPartPasswordFunc) (const char *user_id, const char *prompt_ctx,
|
||||
gboolean reprompt, gpointer user_data);
|
||||
|
||||
/**
|
||||
* decrypt the given encrypted mime multipart
|
||||
*
|
||||
* @param enc encrypted part
|
||||
* @param opts options
|
||||
* @param password_func callback function to retrieve as password (or NULL)
|
||||
* @param user_data pointer passed to the password func
|
||||
* @param err receives error data
|
||||
*
|
||||
* @return the decrypted part, or NULL in case of error
|
||||
*/
|
||||
GMimeObject* mu_msg_crypto_decrypt_part (GMimeMultipartEncrypted *enc, MuMsgOptions opts,
|
||||
MuMsgPartPasswordFunc func, gpointer user_data,
|
||||
GError **err);
|
||||
#endif /*BUILD_CRYPTO*/
|
||||
|
||||
|
|
Loading…
Reference in New Issue