diff --git a/src/Makefile.am b/src/Makefile.am index 5ae6a3a9..e0328f72 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -67,13 +67,16 @@ libmu_la_SOURCES= \ mu-msg-fields.h \ mu-msg-flags.c \ mu-msg-flags.h \ - mu-msg-gmime.c \ - mu-msg-gmime.h \ + mu-msg-prio.h \ + mu-msg-status.h \ + mu-msg.c \ + mu-msg.h \ + mu-msg-priv.h \ mu-msg-iter-xapian-priv.hh \ mu-msg-iter-xapian.cc \ mu-msg-iter-xapian.h \ - mu-msg-part-info.c \ - mu-msg-part-info.h \ + mu-msg-part.c \ + mu-msg-part.h \ mu-msg-str.c \ mu-msg-str.h \ mu-msg.h \ diff --git a/src/mu-cmd-extract.c b/src/mu-cmd-extract.c index f13951a3..0b645d3b 100644 --- a/src/mu-cmd-extract.c +++ b/src/mu-cmd-extract.c @@ -1,5 +1,5 @@ /* -** Copyright (C) 2010 Dirk-Jan C. Binnema +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -17,27 +17,29 @@ ** */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif /*HAVE_CONFIG_H*/ #include -#include "mu-msg-gmime.h" +#include "mu-msg.h" +#include "mu-msg-part.h" #include "mu-msg-str.h" #include "mu-cmd.h" - static gboolean save_part (const char* path, unsigned idx) { - MuMsgGMime* msg; + MuMsg* msg; - msg = mu_msg_gmime_new (path, NULL); + msg = mu_msg_new (path, NULL); if (!msg) return FALSE; - mu_msg_gmime_mime_part_save (msg, idx, NULL, TRUE); /* FIXME */ + mu_msg_mime_part_save (msg, idx, NULL, TRUE); /* FIXME */ - mu_msg_gmime_destroy (msg); + mu_msg_destroy (msg); return TRUE; } @@ -45,7 +47,7 @@ save_part (const char* path, unsigned idx) static void -each_part (MuMsgPartInfo* part, gpointer user_data) +each_part (MuMsgPart *part, gpointer user_data) { g_print ("%u %s %s/%s [%s]\n", part->index, @@ -59,15 +61,15 @@ each_part (MuMsgPartInfo* part, gpointer user_data) static gboolean show_parts (const char* path) { - MuMsgGMime* msg; + MuMsg* msg; - msg = mu_msg_gmime_new (path, NULL); + msg = mu_msg_new (path, NULL); if (!msg) return FALSE; - mu_msg_gmime_msg_part_infos_foreach (msg, each_part, NULL); + mu_msg_msg_part_foreach (msg, each_part, NULL); - mu_msg_gmime_destroy (msg); + mu_msg_destroy (msg); return TRUE; @@ -82,12 +84,12 @@ mu_cmd_extract (MuConfigOptions *opts) /* note: params[0] will be 'view' */ if (!opts->params[0] || !opts->params[1]) { - g_printerr ("missing file to extract\n"); + g_warning ("missing mail file to extract something from"); return FALSE; } - mu_msg_gmime_init(); + mu_msg_init(); - rv = FALSE; + rv = TRUE; if (!opts->params[2]) /* no explicit part, show, don't save */ rv = show_parts (opts->params[1]); else { @@ -95,20 +97,20 @@ mu_cmd_extract (MuConfigOptions *opts) for (i = 2; opts->params[i]; ++i) { unsigned idx = atoi (opts->params[i]); if (idx == 0) { - g_printerr ("not a valid index: %s", opts->params[i]); + g_warning ("not a valid index: %s", opts->params[i]); rv = FALSE; break; } if (!save_part (opts->params[1], idx)) { - g_printerr ("failed to save part %d of %s", idx, + g_warning ("failed to save part %d of %s", idx, opts->params[1]); rv = FALSE; break; } } } - - mu_msg_gmime_uninit(); + + mu_msg_uninit(); return rv; } diff --git a/src/mu-cmd-find.c b/src/mu-cmd-find.c index efdb562f..899b8901 100644 --- a/src/mu-cmd-find.c +++ b/src/mu-cmd-find.c @@ -1,5 +1,5 @@ /* -** Copyright (C) 2010 Dirk-Jan C. Binnema +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -17,7 +17,9 @@ ** */ +#ifdef HAVE_CONFIG_H #include "config.h" +#endif /*HAVE_CONFIG_H*/ #include #include @@ -26,7 +28,7 @@ #include #include -#include "mu-msg-gmime.h" +#include "mu-msg.h" #include "mu-maildir.h" #include "mu-index.h" #include "mu-query-xapian.h" @@ -74,14 +76,14 @@ display_field (MuMsgIterXapian *iter, const MuMsgField* field) case MU_MSG_FIELD_TYPE_INT: - if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_PRIORITY) { + if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_PRIO) { val = mu_msg_iter_xapian_get_field_numeric (iter, field); - return mu_msg_str_prio ((MuMsgPriority)val); + return mu_msg_str_prio ((MuMsgPrio)val); } if (mu_msg_field_id(field) == MU_MSG_FIELD_ID_FLAGS) { val = mu_msg_iter_xapian_get_field_numeric (iter, field); - return mu_msg_str_flags_s ((MuMsgPriority)val); + return mu_msg_str_flags_s ((MuMsgPrio)val); } return mu_msg_iter_xapian_get_field (iter, field); /* as string */ @@ -120,18 +122,18 @@ static void print_summary (MuMsgIterXapian *iter, size_t summary_len) { const char *summ; - MuMsgGMime *msg; + MuMsg *msg; - msg = mu_msg_iter_xapian_get_msg_gmime (iter); + msg = mu_msg_iter_xapian_get_msg (iter); if (!msg) { g_warning ("%s: failed to create msg object", __FUNCTION__); return; } - summ = mu_msg_gmime_get_summary (msg, summary_len); + summ = mu_msg_get_summary (msg, summary_len); g_print ("Summary: %s\n", summ ? summ : ""); - mu_msg_gmime_destroy (msg); + mu_msg_destroy (msg); } @@ -341,19 +343,19 @@ mu_cmd_find (MuConfigOptions *opts) /* first param is 'query', search params are after that */ params = (const gchar**)&opts->params[1]; - mu_msg_gmime_init(); + mu_msg_init(); xapian = mu_query_xapian_new (opts->xpath); if (!xapian) { g_printerr ("Failed to create a Xapian query\n"); - mu_msg_gmime_uninit (); + mu_msg_uninit (); return FALSE; } rv = do_output (xapian, opts, params); mu_query_xapian_destroy (xapian); - mu_msg_gmime_uninit(); + mu_msg_uninit(); return rv; } diff --git a/src/mu-cmd-index.c b/src/mu-cmd-index.c index fca67c2f..9e95cca1 100644 --- a/src/mu-cmd-index.c +++ b/src/mu-cmd-index.c @@ -27,7 +27,7 @@ #include "mu-util.h" #include "mu-util-xapian.h" -#include "mu-msg-gmime.h" +#include "mu-msg.h" #include "mu-index.h" #include "mu-cmd.h" @@ -205,13 +205,13 @@ run_index (MuIndex *midx, const char* maildir, MuIndexStats *stats, MuResult rv; mu_index_stats_clear (stats); - mu_msg_gmime_init (); + mu_msg_init (); rv = mu_index_run (midx, maildir, reindex, stats, quiet ? index_msg_silent_cb :index_msg_cb, NULL, NULL); - mu_msg_gmime_init (); + mu_msg_init (); return rv; } diff --git a/src/mu-cmd-mkdir.h b/src/mu-cmd-mkdir.h new file mode 100644 index 00000000..a6c4c598 --- /dev/null +++ b/src/mu-cmd-mkdir.h @@ -0,0 +1,36 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_CMD_MKDIR_H__ +#define __MU_CMD_MKDIR_H__ + +#include +#include "mu-config.h" + +/** + * execute the 'mkdir' command + * + * @param opts configuration options + * + * @return TRUE if the command succeede, FALSE otherwise + */ +gboolean mu_cmd_mkdir (MuConfigOptions *opts); + + +#endif /*__MU_CMD_VIEW_H__*/ diff --git a/src/mu-cmd-view.c b/src/mu-cmd-view.c index 648ce4ce..d5b71deb 100644 --- a/src/mu-cmd-view.c +++ b/src/mu-cmd-view.c @@ -25,7 +25,7 @@ #include #include -#include "mu-msg-gmime.h" +#include "mu-msg.h" #include "mu-msg-str.h" #include "mu-cmd.h" @@ -36,41 +36,41 @@ static gboolean view_file (const gchar *path, const gchar *fields, size_t summary_len) { - MuMsgGMime* msg; + MuMsg* msg; const char *field; time_t date; - msg = mu_msg_gmime_new (path, NULL); + msg = mu_msg_new (path, NULL); if (!msg) return FALSE; - field = mu_msg_gmime_get_from (msg); + field = mu_msg_get_from (msg); if (field) g_print ("From: %s\n", field); - field = mu_msg_gmime_get_to (msg); + field = mu_msg_get_to (msg); if (field) g_print ("To: %s\n", field); - field = mu_msg_gmime_get_cc (msg); + field = mu_msg_get_cc (msg); if (field) g_print ("Cc: %s\n", field); - field = mu_msg_gmime_get_subject (msg); + field = mu_msg_get_subject (msg); if (field) g_print ("Subject: %s\n", field); - date = mu_msg_gmime_get_date (msg); + date = mu_msg_get_date (msg); if (date) g_print ("Date: %s\n", mu_msg_str_date_s (date)); if (summary_len > 0) { - field = mu_msg_gmime_get_summary (msg, summary_len); + field = mu_msg_get_summary (msg, summary_len); g_print ("Summary: %s\n", field ? field : ""); } else { - field = mu_msg_gmime_get_body_text (msg); + field = mu_msg_get_body_text (msg); if (field) g_print ("\n%s\n", field); else @@ -78,7 +78,7 @@ view_file (const gchar *path, const gchar *fields, size_t summary_len) g_debug ("No text body found for %s", path); } - mu_msg_gmime_destroy (msg); + mu_msg_destroy (msg); return TRUE; } @@ -97,14 +97,14 @@ mu_cmd_view (MuConfigOptions *opts) return FALSE; } - mu_msg_gmime_init(); + mu_msg_init(); rv = TRUE; for (i = 1; opts->params[i] && rv; ++i) rv = view_file (opts->params[i], NULL, opts->summary_len); - mu_msg_gmime_uninit(); + mu_msg_uninit(); return rv; } diff --git a/src/mu-cmd-view.h b/src/mu-cmd-view.h new file mode 100644 index 00000000..41e7c829 --- /dev/null +++ b/src/mu-cmd-view.h @@ -0,0 +1,28 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_CMD_VIEW_H__ +#define __MU_CMD_VIEW_H__ + +#include +#include "mu-config.h" + + + +#endif /*__MU_CMD_VIEW_H__*/ diff --git a/src/mu-index.c b/src/mu-index.c index 70604024..a906a1eb 100644 --- a/src/mu-index.c +++ b/src/mu-index.c @@ -97,7 +97,7 @@ insert_or_update_maybe (const char* fullpath, const char* mdir, time_t filestamp, MuIndexCallbackData *data, gboolean *updated) { - MuMsgGMime *msg; + MuMsg *msg; *updated = FALSE; @@ -125,7 +125,7 @@ insert_or_update_maybe (const char* fullpath, const char* mdir, } while (0); - msg = mu_msg_gmime_new (fullpath, mdir); + msg = mu_msg_new (fullpath, mdir); if (!msg) { g_warning ("%s: failed to create mu_msg for %s", __FUNCTION__, fullpath); @@ -139,7 +139,7 @@ insert_or_update_maybe (const char* fullpath, const char* mdir, /* ignore...*/ } - mu_msg_gmime_destroy (msg); + mu_msg_destroy (msg); *updated = TRUE; return MU_OK; diff --git a/src/mu-msg-contact.c b/src/mu-msg-contact.c index bd802315..1724baaa 100644 --- a/src/mu-msg-contact.c +++ b/src/mu-msg-contact.c @@ -22,57 +22,110 @@ #endif /*HAVE_CONFIG_H*/ #include +#include + +#include "mu-msg-priv.h" +#include "mu-msg.h" + #include "mu-msg-contact.h" +#include "mu-util.h" + -MuMsgContact* -mu_msg_contact_new (const char *name, const char* address, - MuMsgContactType ctype) +static gboolean +fill_contact (MuMsgContact *contact, InternetAddress *addr, + MuMsgContactType ctype) { - MuMsgContact *ct; + if (!addr) + return FALSE; - g_return_val_if_fail (ctype == MU_MSG_CONTACT_TYPE_TO || - ctype == MU_MSG_CONTACT_TYPE_FROM || - ctype == MU_MSG_CONTACT_TYPE_CC || - ctype == MU_MSG_CONTACT_TYPE_BCC, - NULL); + contact->name = (char*)internet_address_get_name (addr); + contact->type = ctype; - ct = g_slice_new (MuMsgContact); - ct->name = name ? g_strdup(name) : NULL; - ct->address = address ? g_strdup(address) : NULL; - ct->type = ctype; - - return ct; + /* we only support internet addresses; + * if we don't check, g_mime hits an assert + */ + contact->address = (char*)internet_address_mailbox_get_addr + (INTERNET_ADDRESS_MAILBOX(addr)); + + return TRUE; } -void -mu_msg_contact_destroy (MuMsgContact *ct) +static void +address_list_foreach (InternetAddressList *addrlist, + MuMsgContactType ctype, + MuMsgContactForeachFunc func, + gpointer user_data) { - if (ct) { - g_free (ct->name); - g_free (ct->address); + int i; + + if (!addrlist) + return; + + for (i = 0; i != internet_address_list_length(addrlist); ++i) { + + MuMsgContact contact; + if (!fill_contact(&contact, + internet_address_list_get_address (addrlist, i), + ctype)) { + MU_WRITE_LOG ("ignoring contact"); + continue; + } + + if (!(func)(&contact, user_data)) + break; } - g_slice_free (MuMsgContact, ct); + return; } - -void -mu_msg_contacts_foreach (GSList *lst, - MuMsgContactForeachFunc func, - gpointer user_data) + +static void +get_contacts_from (MuMsg *msg, MuMsgContactForeachFunc func, + gpointer user_data) { - while (lst && func((MuMsgContact*)lst->data, user_data)) - lst = g_slist_next(lst); -} - + InternetAddressList *lst; + /* we go through this whole excercise of trying to get a *list* + * of 'From:' address (usually there is only one...), because + * internet_address_parse_string has the nice side-effect of + * splitting in names and addresses for us */ + lst = internet_address_list_parse_string ( + g_mime_message_get_sender (msg->_mime_msg)); + if (lst) { + address_list_foreach (lst, MU_MSG_CONTACT_TYPE_FROM, + func, user_data); + g_object_unref (G_OBJECT(lst)); + } +} + void -mu_msg_contacts_free (GSList *lst) +mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func, + gpointer user_data) { - g_slist_foreach (lst, (GFunc)mu_msg_contact_destroy, NULL); - g_slist_free (lst); + int i; + struct { + GMimeRecipientType _gmime_type; + MuMsgContactType _type; + } ctypes[] = { + {GMIME_RECIPIENT_TYPE_TO, MU_MSG_CONTACT_TYPE_TO}, + {GMIME_RECIPIENT_TYPE_CC, MU_MSG_CONTACT_TYPE_CC}, + {GMIME_RECIPIENT_TYPE_BCC, MU_MSG_CONTACT_TYPE_BCC}, + }; + + g_return_if_fail (func && msg); + + /* first, get the from address(es) */ + get_contacts_from (msg, func, user_data); + + /* get to, cc, bcc */ + for (i = 0; i != G_N_ELEMENTS(ctypes); ++i) { + InternetAddressList *addrlist; + addrlist = g_mime_message_get_recipients (msg->_mime_msg, + ctypes[i]._gmime_type); + address_list_foreach (addrlist, ctypes[i]._type, func, user_data); + } } diff --git a/src/mu-msg-contact.h b/src/mu-msg-contact.h index d638ee68..dcfeee60 100644 --- a/src/mu-msg-contact.h +++ b/src/mu-msg-contact.h @@ -21,6 +21,7 @@ #define __MU_MSG_CONTACT_H__ #include +#include "mu-msg.h" enum _MuMsgContactType { /* Reply-To:? */ MU_MSG_CONTACT_TYPE_TO, @@ -38,28 +39,6 @@ struct _MuMsgContact { }; typedef struct _MuMsgContact MuMsgContact; - -/** - * create a new MuMsgContact instance - * - * @param name name of the contact (or NULL) - * @param addr address of the contact (or NULL) - * @param ctype a valid contact type - * - * @return a new MuMsgContact instance; use mu_msg_contact_destroy - * when finished. - */ -MuMsgContact *mu_msg_contact_new (const char *name, const char *addr, - MuMsgContactType ctype); - -/** - * destroy a MuMsgContact - * - * @param ct a MuMsgContact, or NULL - */ -void mu_msg_contact_destroy (MuMsgContact *ct); - - /** * macro to get the name of a contact * @@ -90,33 +69,27 @@ void mu_msg_contact_destroy (MuMsgContact *ct); /** * callback function - * + * * @param contact * @param user_data a user provided data pointer - * + * * @return TRUE if we should continue the foreach, FALSE otherwise */ typedef gboolean (*MuMsgContactForeachFunc) (MuMsgContact* contact, gpointer user_data); -/** - * call a function for each MuMsgContact in the list - * - * @param lst a list of MuMsgContact objects - * @param func a callback function - * @param user_data user pointer, passed to the callback - */ -void mu_msg_contacts_foreach (GSList *lst, - MuMsgContactForeachFunc func, - gpointer user_data); /** - * free a list of MuMsgContact objects + * call a function for each of the contacts in a message + * + * @param msg a valid MuMsgGMime* instance + * @param func a callback function to call for each contact; when + * the callback does not return TRUE, it won't be called again + * @param user_data a user-provide pointer that will be passed to the callback * - * @param lst list of MuMsgContact object */ -void mu_msg_contacts_free (GSList *lst); - +void mu_msg_contact_foreach (MuMsg *msg, MuMsgContactForeachFunc func, + gpointer user_data); #endif /*__MU_MSG_CONTACT_H__*/ diff --git a/src/mu-msg-fields.c b/src/mu-msg-fields.c index d2c0fe77..5324b954 100644 --- a/src/mu-msg-fields.c +++ b/src/mu-msg-fields.c @@ -99,7 +99,7 @@ static const MuMsgField FIELD_DATA[] = { }, { - MU_MSG_FIELD_ID_PRIORITY, + MU_MSG_FIELD_ID_PRIO, MU_MSG_FIELD_TYPE_INT, "prio", "p", "P", FLAG_GMIME | FLAG_XAPIAN_VALUE diff --git a/src/mu-msg-fields.h b/src/mu-msg-fields.h index 8ce47130..a114b276 100644 --- a/src/mu-msg-fields.h +++ b/src/mu-msg-fields.h @@ -34,7 +34,7 @@ enum _MuMsgFieldId { MU_MSG_FIELD_ID_FROM, MU_MSG_FIELD_ID_PATH, MU_MSG_FIELD_ID_MAILDIR, - MU_MSG_FIELD_ID_PRIORITY, + MU_MSG_FIELD_ID_PRIO, MU_MSG_FIELD_ID_SIZE, MU_MSG_FIELD_ID_SUBJECT, MU_MSG_FIELD_ID_TO, diff --git a/src/mu-msg-gmime.h b/src/mu-msg-gmime.h deleted file mode 100644 index 5b636893..00000000 --- a/src/mu-msg-gmime.h +++ /dev/null @@ -1,375 +0,0 @@ -/* -** Copyright (C) 2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify -** it under the terms of the GNU General Public License as published by -** the Free Software Foundation; either version 3 of the License, or -** (at your option) any later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#ifndef __MU_MSG_GMIME_H__ -#define __MU_MSG_GMIME_H__ - -#include "mu-msg.h" -#include "mu-msg-contact.h" -#include "mu-msg-part-info.h" - -G_BEGIN_DECLS - -struct _MuMsgGMime; -typedef struct _MuMsgGMime MuMsgGMime; - -/** - * initialize the message parsing system; this function must be called - * before doing any message parsing (ie., any of the other - * mu_msg_gmime functions). when done with the message parsing system, - * call mu_msg_gmime_uninit. Note: calling this function on an already - * initialized system has no effect - */ -void mu_msg_gmime_init (void); - -/** - * uninitialize the messge parsing system that has previously been - * initialized with mu_msg_init. not calling mu_msg_uninit after - * mu_msg_init has been called will lead to memory leakage. Note: - * calling mu_msg_uninit on an uninitialized system has no - * effect - */ -void mu_msg_gmime_uninit (void); - - -/** - * create a new MuMsgGMime* instance which parses a message and provides - * read access to its properties; call mu_msg_destroy when done with it. - * - * @param path full path to an email message file - * - * @param mdir the maildir for this message; ie, if the path is - * ~/Maildir/foo/bar/cur/msg, the maildir would be foo/bar; you can - * pass NULL for this parameter, in which case some maildir-specific - * information is not available. - * - * @return a new MuMsgGMime instance or NULL in case of error - */ -MuMsgGMime* mu_msg_gmime_new (const char* filepath, - const char *maildir); - - -/** - * destroy a MuMsgGMime* instance; call this function when done with - * a MuMsgGMime - * - * @param msg a MuMsgGMime* instance or NULL - */ -void mu_msg_gmime_destroy (MuMsgGMime *msg); - - - -/** - * get the plain text body of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the plain text body or NULL in case of error or if there is no - * such body. the returned string should *not* be modified or freed. - * The returned data is in UTF8 or NULL. - */ -const char* mu_msg_gmime_get_body_text (MuMsgGMime *msg); - - -/** - * get the html body of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the html body or NULL in case of error or if there is no - * such body. the returned string should *not* be modified or freed. - */ -const char* mu_msg_gmime_get_body_html (MuMsgGMime *msg); - - -/** - * get a summary of the body of this message; a summary takes up to - * the first @max_lines from the message, and replaces newlines - * etc. with single whitespace characters. This only works if there's - * a text-body for the message - * - * @param msg a valid MuMsgGMime* instance - * @param max_lines the max number of lines to summarize - * - * @return the summary of the message or NULL in case of error or if - * there is no such body. the returned string should *not* be modified - * or freed. When called multiple times, the function will always - * return the same summary, regardless of a different max_lines value. - */ -const char* mu_msg_gmime_get_summary (MuMsgGMime *msg, size_t max_lines); - -struct _MuMsgGMimeAttach { - unsigned index; /* index of the attachment (names may not be unique) */ - const char* name; /* name of the attachment */ - size_t size; /* size in bytes, or 0 if not available */ - const char* mime_type; /* the mime type */ -}; -typedef struct _MuMsgMimePart MuMsgMimePart; - -typedef gboolean (*MuMsgMimePartForeachFunc) (MuMsgMimePart *part, gpointer data); -/** - * call a user function for each attachment found in the message. the - * function will be calle d for each attachment and as long a the - * user-function returns TRUE - * - * @param msg a valid MuMsgGMime - * @param the function to call (callback) - * @param user_data a user pointer which will be passed to the callback function - * - * @return a list of attachment - */ -void mu_msg_gmime_mime_part_foreach (MuMsgGMime* msg, - MuMsgMimePartForeachFunc func, - gpointer user_data); - -/** - * save a specific attachment to some targetdir - * - * @param msg a valid MuMsgGMime instance - * @param wanted_idx index of the attachment you want to save - * @param targetdir filesystem directory to save the attachment - * @param overwrite existing files? - * - * @return TRUE if saving succeeded, FALSE otherwise - */ -gboolean -mu_msg_gmime_mime_part_save (MuMsgGMime *msg, int wanted_idx, - const char *targetdir, gboolean overwrite); - -/** - * get the sender (From:) of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the sender of this Message or NULL in case of error or if there - * is no sender. the returned string should *not* be modified or freed. - */ -const char* mu_msg_gmime_get_from (MuMsgGMime *msg); - - -/** - * get the recipients (To:) of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the sender of this Message or NULL in case of error or if there - * are no recipients. the returned string should *not* be modified or freed. - */ -const char* mu_msg_gmime_get_to (MuMsgGMime *msg); - - -/** - * get the carbon-copy recipients (Cc:) of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the Cc: recipients of this Message or NULL in case of error or if - * there are no such recipients. the returned string should *not* be modified - * or freed. - */ -const char* mu_msg_gmime_get_cc (MuMsgGMime *msg); - -/** - * get the file system path of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the path of this Message or NULL in case of error. - * the returned string should *not* be modified or freed. - */ -const char* mu_msg_gmime_get_path (MuMsgGMime *msg); - - -/** - * get the maildir this message lives in; ie, if the path is - * ~/Maildir/foo/bar/cur/msg, the maildir would be foo/bar - * - * @param msg a valid MuMsgGMime* instance - * - * @return the maildir requested or NULL in case of error. The returned - * string should *not* be modified or freed. - */ -const char* mu_msg_gmime_get_maildir (MuMsgGMime *msg); - - -/** - * get the subject of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the subject of this Message or NULL in case of error or if there - * is no subject. the returned string should *not* be modified or freed. - */ -const char* mu_msg_gmime_get_subject (MuMsgGMime *msg); - -/** - * get the Message-Id of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the Message-Id of this Message (without the enclosing <>) - * or NULL in case of error or if there is none. the returned string - * should *not* be modified or freed. - */ -const char* mu_msg_gmime_get_msgid (MuMsgGMime *msg); - - -/** - * get any arbitrary header from this message - * - * @param msg a valid MuMsgGMime* instance - * @header the header requested - * - * @return the header requested or NULL in case of error or if there - * is no such header. the returned string should *not* be modified or freed. - */ -const char* mu_msg_gmime_get_header (MuMsgGMime *msg, - const char* header); - -/** - * get the message date/time (the Date: field) as time_t, using UTC - * - * @param msg a valid MuMsgGMime* instance - * - * @return message date/time or 0 in case of error or if there - * is no such header. - */ -time_t mu_msg_gmime_get_date (MuMsgGMime *msg); - -/** - * get the flags for this message - * - * @param msg valid MuMsgGMime* instance - * - * @return the fileflags as logically OR'd #Mu MsgFlags or 0 if - * there are none. - */ -MuMsgFlags mu_msg_gmime_get_flags (MuMsgGMime *msg); - - -/** - * get the file size in bytes of this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the filesize - */ -size_t mu_msg_gmime_get_size (MuMsgGMime *msg); - - -/** - * get some field value as string - * - * @param msg a valid MuMsgGmime instance - * @param field the field to retrieve; it must be a string-typed field - * - * @return a string that should not be freed - */ -const char* mu_msg_gmime_get_field_string (MuMsgGMime *msg, - const MuMsgField* field); - -/** - * get some field value as string - * - * @param msg a valid MuMsgGmime instance - * @param field the field to retrieve; it must be a numeric field - * - * @return a string that should not be freed - */ -gint64 mu_msg_gmime_get_field_numeric (MuMsgGMime *msg, - const MuMsgField* field); - -/** - * get the message priority for this message (MU_MSG_PRIORITY_LOW, - * MU_MSG_PRIORITY_NORMAL or MU_MSG_PRIORITY_HIGH) the X-Priority, - * X-MSMailPriority, Importance and Precedence header are checked, in - * that order. if no known or explicit priority is set, - * MU_MSG_PRIORITY_NORMAL is assumed - * - * @param msg a valid MuMsgGMime* instance - * - * @return the message priority (!= 0) or 0 in case of error - */ -MuMsgPriority mu_msg_gmime_get_priority (MuMsgGMime *msg); - -/** - * get the timestamp (mtime) for the file containing this message - * - * @param msg a valid MuMsgGMime* instance - * - * @return the timestamp or 0 in case of error - */ -time_t mu_msg_gmime_get_timestamp (MuMsgGMime *msg); - - - - -/** - * get a list of contacts (MuMsgContact) for this message; you can use - * GSList functions or mu_msg_contact_list_foreach to read the items. - * - * @param msg a valid MuMsgGMime* instance - * - * @return a list of contacts for this message; use - * mu_msg_contacts_free to free it when done - */ -GSList * mu_msg_gmime_get_contacts (MuMsgGMime *msg); - - -/** - * call a function for each of the contacts in a message - * - * @param msg a valid MuMsgGMime* instance - * @param func a callback function to call for each contact; when - * the callback does not return TRUE, it won't be called again - * @param user_data a user-provide pointer that will be passed to the callback - * - */ -void mu_msg_gmime_contacts_foreach (MuMsgGMime *msg, - MuMsgContactForeachFunc func, - gpointer user_data); - -/* /\** */ -/* * get a list of message part info objects (MuMsgPartInfo) for this */ -/* * message; you can use GSList functions or */ -/* * mu_msg_part_info_list_foreach to read the items. */ -/* * */ -/* * @param msg a valid MuMsgGMime* instance */ -/* * */ -/* * @return a list of contacts for this message; use */ -/* * mu_msg_part_infos_free to free it when done */ -/* *\/ */ -/* GSList *mu_msg_gmime_get_part_infos (MuMsgGMime *msg); */ - - -/** - * call a function for each of the contacts in a message - * - * @param msg a valid MuMsgGMime* instance - * @param func a callback function to call for each contact; when - * the callback does not return TRUE, it won't be called again - * @param user_data a user-provide pointer that will be passed to the callback - * - */ -void mu_msg_gmime_msg_part_infos_foreach (MuMsgGMime *msg, - MuMsgPartInfoForeachFunc func, - gpointer user_data); -G_END_DECLS - -#endif /*__MU_MSG_GIME_H__*/ diff --git a/src/mu-msg-iter-xapian-priv.hh b/src/mu-msg-iter-xapian-priv.hh index 7245dd55..59daf660 100644 --- a/src/mu-msg-iter-xapian-priv.hh +++ b/src/mu-msg-iter-xapian-priv.hh @@ -1,5 +1,5 @@ /* -** Copyright (C) 2010 Dirk-Jan C. Binnema +** Copyright (C) 22010 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by diff --git a/src/mu-msg-iter-xapian.cc b/src/mu-msg-iter-xapian.cc index e51e3e04..9791a793 100644 --- a/src/mu-msg-iter-xapian.cc +++ b/src/mu-msg-iter-xapian.cc @@ -1,5 +1,5 @@ /* -** Copyright (C) 2010 Dirk-Jan C. Binnema +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by @@ -80,11 +80,11 @@ mu_msg_iter_xapian_destroy (MuMsgIterXapian *iter) } -MuMsgGMime* -mu_msg_iter_xapian_get_msg_gmime (MuMsgIterXapian *iter) +MuMsg* +mu_msg_iter_xapian_get_msg (MuMsgIterXapian *iter) { const char *path; - MuMsgGMime *msg; + MuMsg *msg; g_return_val_if_fail (iter, NULL); @@ -94,7 +94,7 @@ mu_msg_iter_xapian_get_msg_gmime (MuMsgIterXapian *iter) return NULL; } - msg = mu_msg_gmime_new (path, NULL); + msg = mu_msg_new (path, NULL); if (!msg) { g_warning ("%s: failed to create msg object", __FUNCTION__); return NULL; @@ -297,9 +297,8 @@ mu_msg_iter_xapian_get_flags (MuMsgIterXapian *iter) return (MuMsgFlags) get_field_number (iter, MU_MSG_FIELD_ID_FLAGS); } -MuMsgPriority -mu_msg_iter_xapian_get_priority (MuMsgIterXapian *iter) +MuMsgPrio +mu_msg_iter_xapian_get_prio (MuMsgIterXapian *iter) { - return (MuMsgPriority) get_field_number (iter, - MU_MSG_FIELD_ID_PRIORITY); + return (MuMsgPrio) get_field_number (iter, MU_MSG_FIELD_ID_PRIO); } diff --git a/src/mu-msg-iter-xapian.h b/src/mu-msg-iter-xapian.h index 5c939093..13662395 100644 --- a/src/mu-msg-iter-xapian.h +++ b/src/mu-msg-iter-xapian.h @@ -21,7 +21,6 @@ #define __MU_MSG_ITER_XAPIAN_H__ #include "mu-msg.h" -#include "mu-msg-gmime.h" G_BEGIN_DECLS @@ -60,7 +59,7 @@ void mu_msg_iter_xapian_destroy (MuMsgIterXapian *iter); /** - * get the corresponding GMime message for this iter; this requires + * get the corresponding MuMsg for this iter; this requires * the corresponding message file to be present at the expected place * * @param iter a valid MuMsgIterXapian instance @@ -68,7 +67,7 @@ void mu_msg_iter_xapian_destroy (MuMsgIterXapian *iter); * @return a MuMsgGMime instance, or NULL in case of error. Use * mu_msg_gmime_destroy when the instance is no longer needed */ -MuMsgGMime* mu_msg_iter_xapian_get_msg_gmime (MuMsgIterXapian *iter); +MuMsg* mu_msg_iter_xapian_get_msg (MuMsgIterXapian *iter); /** * get the document id for the current message @@ -169,9 +168,9 @@ MuMsgFlags mu_msg_iter_xapian_get_flags (MuMsgIterXapian *iter); * * @param iter a valid MuMsgIterXapian iterator * - * @return the message priority, or MU_MSG_PRIORITY_NONE + * @return the message priority, or MU_MSG_PRIO_NONE */ -MuMsgPriority mu_msg_iter_xapian_get_priority (MuMsgIterXapian *iter); +MuMsgPrio mu_msg_iter_xapian_get_prio (MuMsgIterXapian *iter); /** diff --git a/src/mu-msg-part-info.c b/src/mu-msg-part-info.c deleted file mode 100644 index 88a938ca..00000000 --- a/src/mu-msg-part-info.c +++ /dev/null @@ -1,70 +0,0 @@ -/* -** Copyright (C) 2008-2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /*HAVE_CONFIG_H*/ - -#include "mu-msg-part-info.h" - -MuMsgPartInfo* -mu_msg_part_info_new (void) -{ - return g_slice_new0 (MuMsgPartInfo); -} - - -void -mu_msg_part_info_destroy (MuMsgPartInfo *pi) -{ - if (!pi) - return; - - if (pi->own_members) { - g_free (pi->content_id); - g_free (pi->type); - g_free (pi->subtype); - /* g_free (pi->content_type); */ - g_free (pi->file_name); - g_free (pi->disposition); - } - - g_slice_free (MuMsgPartInfo, pi); -} - - - -void -mu_msg_part_infos_foreach (GSList *lst, - MuMsgPartInfoForeachFunc func, - gpointer user_data) -{ - for (; lst ; lst = g_slist_next (lst)) - func((MuMsgPartInfo*)lst->data, user_data); -} - - -void -mu_msg_part_infos_free (GSList *lst) -{ - g_slist_foreach (lst, (GFunc)mu_msg_part_info_destroy, NULL); - g_slist_free (lst); -} - - diff --git a/src/mu-msg-part.c b/src/mu-msg-part.c new file mode 100644 index 00000000..8e4f9dd5 --- /dev/null +++ b/src/mu-msg-part.c @@ -0,0 +1,179 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify it +** under the terms of the GNU General Public License as published by the +** Free Software Foundation; either version 3, or (at your option) any +** later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /*HAVE_CONFIG_H*/ + +#include +#include + +#include "mu-util.h" +#include "mu-msg-priv.h" +#include "mu-msg-part.h" + +struct _PartData { + unsigned _idx; + MuMsgPartForeachFunc _func; + gpointer _user_data; +}; +typedef struct _PartData PartData; + + +static void +part_foreach_cb (GMimeObject *parent, GMimeObject *part, PartData *pdata) +{ + GMimeContentType *ct; + MuMsgPart pi; + + memset (&pi, 0, sizeof pi); + pi.index = pdata->_idx++; + pi.content_id = (char*)g_mime_object_get_content_id (part); + + ct = g_mime_object_get_content_type (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); + } + + if (GMIME_IS_PART(part)) { + pi.disposition = (char*)g_mime_object_get_disposition (part); + pi.file_name = (char*)g_mime_part_get_filename (GMIME_PART(part)); + } + + pdata->_func(&pi, pdata->_user_data); +} + + + +void +mu_msg_msg_part_foreach (MuMsg *msg, + MuMsgPartForeachFunc func, + gpointer user_data) +{ + PartData pdata; + + g_return_if_fail (msg); + g_return_if_fail (GMIME_IS_OBJECT(msg->_mime_msg)); + + pdata._idx = 0; + pdata._func = func; + pdata._user_data = user_data; + + g_mime_message_foreach (msg->_mime_msg, + (GMimeObjectForeachFunc)part_foreach_cb, + &pdata); +} + + +struct _SavePartData { + guint idx, wanted_idx; + const gchar* targetdir; + gboolean overwrite; + gboolean stream; + gboolean result; +}; +typedef struct _SavePartData SavePartData; + + +static gboolean +save_part (GMimeObject *part, const char *filename, + const char *targetdir, gboolean overwrite) +{ + int fd, rv; + GMimeDataWrapper *wrapper; + GMimeStream *stream; + + rv = TRUE; + fd = mu_util_create_writeable_fd (filename, targetdir, + overwrite); + if (fd == -1) { + g_warning ("error saving file %s%s %s", + filename, errno != 0 ? ":" : "", + errno != 0 ? strerror(errno) : ""); + return FALSE; + } + + stream = g_mime_stream_fs_new (fd); + if (!stream) { + g_warning ("%s: failed to create stream", __FUNCTION__); + close (fd); + return FALSE; + } + + g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), + TRUE); /* GMimeStream will close fd */ + + wrapper = g_mime_part_get_content_object (GMIME_PART(part)); + if (!wrapper) { + g_object_unref (G_OBJECT(stream)); + g_warning ("%s: failed to create wrapper", __FUNCTION__); + return FALSE; + } + + rv = g_mime_data_wrapper_write_to_stream (wrapper, stream); + g_object_unref (G_OBJECT(stream)); + + return rv == -1 ? FALSE : TRUE; +} + + + +static void +part_foreach_save_cb (GMimeObject *parent, GMimeObject *part, + SavePartData *spd) +{ + const gchar* filename; + + /* did we find the right part yet? */ + if (spd->result || spd->wanted_idx != spd->idx++) + return; + + if (!GMIME_IS_PART(part)) + return; + + filename = g_mime_part_get_filename (GMIME_PART(part)); + if (filename) { + spd->result = save_part (part, filename, + spd->targetdir, + spd->overwrite); + } else + spd->result = FALSE; +} + + + +gboolean +mu_msg_mime_part_save (MuMsg *msg, int wanted_idx, + const char *targetdir, gboolean overwrite) +{ + SavePartData spd; + spd.idx = 0; + spd.wanted_idx = wanted_idx; + spd.targetdir = targetdir; + spd.overwrite = overwrite; + spd.stream = FALSE; + spd.result = FALSE; + + g_mime_message_foreach (msg->_mime_msg, + (GMimeObjectForeachFunc)part_foreach_save_cb, + &spd); + return spd.result; +} + diff --git a/src/mu-msg-part-info.h b/src/mu-msg-part.h similarity index 53% rename from src/mu-msg-part-info.h rename to src/mu-msg-part.h index 92055023..cca58e41 100644 --- a/src/mu-msg-part-info.h +++ b/src/mu-msg-part.h @@ -17,12 +17,12 @@ ** */ -#ifndef __MU_MSG_PART_INFO_H__ -#define __MU_MSG_PART_INFO_H__ +#ifndef __MU_MSG_PART_H__ +#define __MU_MSG_PART_H__ #include -struct _MuMsgPartInfo { +struct _MuMsgPart { /* index of this message */ unsigned index; @@ -40,7 +40,7 @@ struct _MuMsgPartInfo { char *file_name; /* usually, "attachment" or "inline"; use - * mu_msg_part_info_is_(attachment|inline) + * mu_msg_part_is_(attachment|inline) * to test */ char *disposition; @@ -49,75 +49,45 @@ struct _MuMsgPartInfo { gpointer data; /* opaque data */ - /* if TRUE, mu_msg_part_info_destroy will free the member vars + /* if TRUE, mu_msg_part_destroy will free the member vars * as well*/ gboolean own_members; }; -typedef struct _MuMsgPartInfo MuMsgPartInfo; - - -/** - * create a new MuMsgPartInfo instance; this just allocates the - * memory, you'll have to fill it yourself - * - * - * @return a new MuMsgPartInfo instance; use mu_msg_part_info_destroy - * when finished. - */ -MuMsgPartInfo *mu_msg_part_info_new (void); - -/** - * destroy a MuMsgPartInfo object - * - * @param ct a MuMsgPartInfo object, or NULL - */ -void mu_msg_part_info_destroy (MuMsgPartInfo *pinfo); +typedef struct _MuMsgPart MuMsgPart; /** * macro to get the file name for this mime-part * - * @param pi a MuMsgPartInfo instance + * @param pi a MuMsgPart instance * * @return the file name */ -#define mu_msg_part_info_file_name(pi) ((pi)->file_name) +#define mu_msg_part_file_name(pi) ((pi)->file_name) /** * macro to get the file name for this mime-part * - * @param pi a MuMsgPartInfo instance + * @param pi a MuMsgPart instance * * @return the file name */ #define mu_msg_part_content_type(pi) ((pi)->content_type) -/** - * callback function - * - * @param a msg part info object - * @param user_data a user provided data pointer - * - */ -typedef void (*MuMsgPartInfoForeachFunc) (MuMsgPartInfo* part, - gpointer user_data); +typedef void (*MuMsgPartForeachFunc) (MuMsgPart *part, gpointer data); /** - * call a function for each MuMsgPartInfo (MIME-part) in the list + * call a function for each of the contacts in a message + * + * @param msg a valid MuMsg* instance + * @param func a callback function to call for each contact; when + * the callback does not return TRUE, it won't be called again + * @param user_data a user-provide pointer that will be passed to the callback * - * @param lst a list of MuMsgPartInfo objects - * @param func a callback function - * @param user_data user pointer, passed to the callback */ -void mu_msg_part_infos_foreach (GSList *lst, - MuMsgPartInfoForeachFunc func, - gpointer user_data); +void mu_msg_msg_part_foreach (MuMsg *msg, + MuMsgPartForeachFunc func, + gpointer user_data); -/** - * free a list of MuMsgPartInfo objects - * - * @param lst list of MuMsgPartInfo object - */ -void mu_msg_part_infos_free (GSList *lst); -#endif /*__MU_MSG_PART_INFO_H__*/ +#endif /*__MU_MSG_PART_H__*/ diff --git a/src/mu-msg-prio.h b/src/mu-msg-prio.h new file mode 100644 index 00000000..caddc668 --- /dev/null +++ b/src/mu-msg-prio.h @@ -0,0 +1,32 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_PRIO_H__ +#define __MU_MSG_PRIO_H__ + +enum _MuMsgPrio { + MU_MSG_PRIO_NONE = 0, + + MU_MSG_PRIO_LOW = 1, + MU_MSG_PRIO_NORMAL = 2, + MU_MSG_PRIO_HIGH = 3 +}; +typedef enum _MuMsgPrio MuMsgPrio; + +#endif /*__MU_MSG_PRIO_H__*/ diff --git a/src/mu-msg-priv.h b/src/mu-msg-priv.h new file mode 100644 index 00000000..7211aa92 --- /dev/null +++ b/src/mu-msg-priv.h @@ -0,0 +1,60 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_PRIV_H__ +#define __MU_MSG_PRIV_H__ + +#include +#include + +#include "mu-msg.h" + +/* we put the the MuMsg definition in this separate -priv file, so we + * can split the mu_msg implementations over separate files */ + +enum _StringFields { + + HTML_FIELD = 0, /* body as HTML */ + TEXT_FIELD, /* body as plain text */ + SUMMARY_FIELD, /* body summary */ + + TO_FIELD, /* To: */ + CC_FIELD, /* Cc: */ + + PATH_FIELD, /* full path */ + MDIR_FIELD, /* the maildir */ + + FLAGS_FIELD_STR, /* message flags */ + + FIELD_NUM +}; +typedef enum _StringFields StringFields; + +struct _MuMsg { + GMimeMessage *_mime_msg; + MuMsgFlags _flags; + + char* _fields[FIELD_NUM]; + + size_t _size; + time_t _timestamp; + MuMsgPrio _prio; +}; + +#endif /*__MU_MSG_PRIV_H__*/ diff --git a/src/mu-msg-status.h b/src/mu-msg-status.h new file mode 100644 index 00000000..c6afc2be --- /dev/null +++ b/src/mu-msg-status.h @@ -0,0 +1,34 @@ +/* +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 3 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software Foundation, +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** +*/ + +#ifndef __MU_MSG_STATUS_H__ +#define __MU_MSG_STATUS_H__ + +/* what kind of message is this; use by the indexer */ +enum _MuMsgStatus { + MU_MSG_STATUS_NEW, /* message is new */ + MU_MSG_STATUS_UPDATE, /* message is to be updated */ + MU_MSG_STATUS_CLEANUP, /* message is to be cleaned up from db */ + MU_MSG_STATUS_CLEANED_UP, /* message has been cleaned up from db */ + MU_MSG_STATUS_EXISTS, /* message exists (will not be cleaned up) */ + MU_MSG_STATUS_UPTODATE /* message is up-to-date */ +}; +typedef enum _MuMsgStatus MuMsgStatus; + +#endif /*__MU_MSG_STATUS_H__*/ diff --git a/src/mu-msg-str.c b/src/mu-msg-str.c index af0c8a4c..69792b2c 100644 --- a/src/mu-msg-str.c +++ b/src/mu-msg-str.c @@ -85,18 +85,18 @@ mu_msg_str_flags (MuMsgFlags flags) } const char* -mu_msg_str_prio (MuMsgPriority prio) +mu_msg_str_prio (MuMsgPrio prio) { switch (prio) { - case MU_MSG_PRIORITY_LOW: + case MU_MSG_PRIO_LOW: return "low"; - case MU_MSG_PRIORITY_NONE: - case MU_MSG_PRIORITY_NORMAL: + case MU_MSG_PRIO_NONE: + case MU_MSG_PRIO_NORMAL: return "normal"; - case MU_MSG_PRIORITY_HIGH: + case MU_MSG_PRIO_HIGH: return "high"; default: diff --git a/src/mu-msg-str.h b/src/mu-msg-str.h index 753e7dfc..e6ab8104 100644 --- a/src/mu-msg-str.h +++ b/src/mu-msg-str.h @@ -89,7 +89,7 @@ char* mu_msg_str_flags (MuMsgFlags flags) G_GNUC_WARN_UNUSED_RESULT; * @return a string representation of the priority; see above * for what to do with it, or NULL in case of error */ -const char* mu_msg_str_prio (MuMsgPriority prio) G_GNUC_CONST; +const char* mu_msg_str_prio (MuMsgPrio prio) G_GNUC_CONST; #endif /*__MU_MSG_STR_H__*/ diff --git a/src/mu-msg-gmime.c b/src/mu-msg.c similarity index 59% rename from src/mu-msg-gmime.c rename to src/mu-msg.c index 61312747..6b439e31 100644 --- a/src/mu-msg-gmime.c +++ b/src/mu-msg.c @@ -27,42 +27,14 @@ #include #include "mu-util.h" -#include "mu-msg-gmime.h" - -enum _StringFields { - - HTML_FIELD = 0, /* body as HTML */ - TEXT_FIELD, /* body as plain text */ - SUMMARY_FIELD, /* body summary */ - - TO_FIELD, /* To: */ - CC_FIELD, /* Cc: */ - - PATH_FIELD, /* full path */ - MDIR_FIELD, /* the maildir */ - - FLAGS_FIELD_STR, /* message flags */ - - FIELD_NUM -}; -typedef enum _StringFields StringFields; - -struct _MuMsgGMime { - GMimeMessage *_mime_msg; - MuMsgFlags _flags; - - char* _fields[FIELD_NUM]; - - size_t _size; - time_t _timestamp; - MuMsgPriority _prio; -}; +#include "mu-msg-priv.h" /* include before mu-msg.h */ +#include "mu-msg.h" void -mu_msg_gmime_destroy (MuMsgGMime *msg) +mu_msg_destroy (MuMsg *msg) { int i; @@ -77,12 +49,12 @@ mu_msg_gmime_destroy (MuMsgGMime *msg) for (i = 0; i != FIELD_NUM; ++i) g_free (msg->_fields[i]); - g_slice_free (MuMsgGMime, msg); + g_slice_free (MuMsg, msg); } static gboolean -init_file_metadata (MuMsgGMime* msg, const char* path, const gchar* mdir) +init_file_metadata (MuMsg* msg, const char* path, const gchar* mdir) { struct stat statbuf; @@ -117,16 +89,16 @@ init_file_metadata (MuMsgGMime* msg, const char* path, const gchar* mdir) static gboolean -init_mime_msg (MuMsgGMime *msg) +init_mime_msg (MuMsg *msg) { FILE *file; GMimeStream *stream; GMimeParser *parser; - file = fopen (mu_msg_gmime_get_path(msg), "r"); + file = fopen (mu_msg_get_path(msg), "r"); if (!file) { g_warning ("%s:cannot open %s: %s", - __FUNCTION__, mu_msg_gmime_get_path(msg), + __FUNCTION__, mu_msg_get_path(msg), strerror (errno)); return FALSE; } @@ -156,24 +128,24 @@ init_mime_msg (MuMsgGMime *msg) } -MuMsgGMime* -mu_msg_gmime_new (const char* filepath, const gchar* mdir) +MuMsg* +mu_msg_new (const char* filepath, const gchar* mdir) { - MuMsgGMime *msg; + MuMsg *msg; g_return_val_if_fail (filepath, NULL); - msg = g_slice_new0 (MuMsgGMime); + msg = g_slice_new0 (MuMsg); if (!msg) return NULL; if (!init_file_metadata(msg, filepath, mdir)) { - mu_msg_gmime_destroy (msg); + mu_msg_destroy (msg); return NULL; } if (!init_mime_msg(msg)) { - mu_msg_gmime_destroy (msg); + mu_msg_destroy (msg); return NULL; } @@ -182,7 +154,7 @@ mu_msg_gmime_new (const char* filepath, const gchar* mdir) const char* -mu_msg_gmime_get_path (MuMsgGMime *msg) +mu_msg_get_path (MuMsg *msg) { g_return_val_if_fail (msg, NULL); @@ -191,7 +163,7 @@ mu_msg_gmime_get_path (MuMsgGMime *msg) const char* -mu_msg_gmime_get_subject (MuMsgGMime *msg) +mu_msg_get_subject (MuMsg *msg) { g_return_val_if_fail (msg, NULL); @@ -199,7 +171,7 @@ mu_msg_gmime_get_subject (MuMsgGMime *msg) } const char* -mu_msg_gmime_get_msgid (MuMsgGMime *msg) +mu_msg_get_msgid (MuMsg *msg) { g_return_val_if_fail (msg, NULL); @@ -208,7 +180,7 @@ mu_msg_gmime_get_msgid (MuMsgGMime *msg) const char* -mu_msg_gmime_get_maildir (MuMsgGMime *msg) +mu_msg_get_maildir (MuMsg *msg) { g_return_val_if_fail (msg, NULL); @@ -218,7 +190,7 @@ mu_msg_gmime_get_maildir (MuMsgGMime *msg) const char* -mu_msg_gmime_get_from (MuMsgGMime *msg) +mu_msg_get_from (MuMsg *msg) { g_return_val_if_fail (msg, NULL); @@ -227,7 +199,7 @@ mu_msg_gmime_get_from (MuMsgGMime *msg) static const char* -get_recipient (MuMsgGMime *msg, GMimeRecipientType rtype, StringFields field) +get_recipient (MuMsg *msg, GMimeRecipientType rtype, StringFields field) { /* can only be set once */ if (!msg->_fields[field]) { @@ -250,14 +222,14 @@ get_recipient (MuMsgGMime *msg, GMimeRecipientType rtype, StringFields field) const char* -mu_msg_gmime_get_to (MuMsgGMime *msg) +mu_msg_get_to (MuMsg *msg) { g_return_val_if_fail (msg, NULL); return get_recipient (msg, GMIME_RECIPIENT_TYPE_TO, TO_FIELD); } const char* -mu_msg_gmime_get_cc (MuMsgGMime *msg) +mu_msg_get_cc (MuMsg *msg) { g_return_val_if_fail (msg, NULL); return get_recipient (msg, GMIME_RECIPIENT_TYPE_CC, CC_FIELD); @@ -265,7 +237,7 @@ mu_msg_gmime_get_cc (MuMsgGMime *msg) time_t -mu_msg_gmime_get_date (MuMsgGMime *msg) +mu_msg_get_date (MuMsg *msg) { time_t t; @@ -311,7 +283,7 @@ msg_cflags_cb (GMimeObject *parent, GMimeObject *part, MuMsgFlags *flags) static MuMsgFlags -get_content_flags (MuMsgGMime *msg) +get_content_flags (MuMsg *msg) { GMimeContentType *ctype; MuMsgFlags flags = 0; @@ -349,13 +321,13 @@ get_content_flags (MuMsgGMime *msg) MuMsgFlags -mu_msg_gmime_get_flags (MuMsgGMime *msg) +mu_msg_get_flags (MuMsg *msg) { g_return_val_if_fail (msg, MU_MSG_FLAG_UNKNOWN); if (msg->_flags == MU_MSG_FLAG_UNKNOWN) { msg->_flags = 0; - msg->_flags = mu_msg_flags_from_file (mu_msg_gmime_get_path(msg)); + msg->_flags = mu_msg_flags_from_file (mu_msg_get_path(msg)); msg->_flags |= get_content_flags (msg); } @@ -364,7 +336,7 @@ mu_msg_gmime_get_flags (MuMsgGMime *msg) size_t -mu_msg_gmime_get_size (MuMsgGMime *msg) +mu_msg_get_size (MuMsg *msg) { g_return_val_if_fail (msg, -1); @@ -385,7 +357,7 @@ to_lower (char *s) static char* -get_prio_str (MuMsgGMime *msg) +get_prio_str (MuMsg *msg) { const char *str; GMimeObject *obj; @@ -406,26 +378,26 @@ get_prio_str (MuMsgGMime *msg) } -static MuMsgPriority +static MuMsgPrio parse_prio_str (const char* priostr) { int i; struct { const char* _str; - MuMsgPriority _prio; + MuMsgPrio _prio; } str_prio[] = { - { "high", MU_MSG_PRIORITY_HIGH }, - { "1", MU_MSG_PRIORITY_HIGH }, - { "2", MU_MSG_PRIORITY_HIGH }, + { "high", MU_MSG_PRIO_HIGH }, + { "1", MU_MSG_PRIO_HIGH }, + { "2", MU_MSG_PRIO_HIGH }, - { "normal", MU_MSG_PRIORITY_NORMAL }, - { "3", MU_MSG_PRIORITY_NORMAL }, + { "normal", MU_MSG_PRIO_NORMAL }, + { "3", MU_MSG_PRIO_NORMAL }, - { "low", MU_MSG_PRIORITY_LOW }, - { "list", MU_MSG_PRIORITY_LOW }, - { "bulk", MU_MSG_PRIORITY_LOW }, - { "4", MU_MSG_PRIORITY_LOW }, - { "5", MU_MSG_PRIORITY_LOW } + { "low", MU_MSG_PRIO_LOW }, + { "list", MU_MSG_PRIO_LOW }, + { "bulk", MU_MSG_PRIO_LOW }, + { "4", MU_MSG_PRIO_LOW }, + { "5", MU_MSG_PRIO_LOW } }; for (i = 0; i != G_N_ELEMENTS(str_prio); ++i) @@ -433,24 +405,24 @@ parse_prio_str (const char* priostr) return str_prio[i]._prio; /* e.g., last-fm uses 'fm-user'... as precedence */ - return MU_MSG_PRIORITY_NORMAL; + return MU_MSG_PRIO_NORMAL; } -MuMsgPriority -mu_msg_gmime_get_priority (MuMsgGMime *msg) +MuMsgPrio +mu_msg_get_prio (MuMsg *msg) { char* priostr; - MuMsgPriority prio; + MuMsgPrio prio; g_return_val_if_fail (msg, 0); - if (msg->_prio != MU_MSG_PRIORITY_NONE) + if (msg->_prio != MU_MSG_PRIO_NONE) return msg->_prio; priostr = get_prio_str (msg); if (!priostr) - return MU_MSG_PRIORITY_NORMAL; + return MU_MSG_PRIO_NORMAL; prio = parse_prio_str (priostr); @@ -461,7 +433,7 @@ mu_msg_gmime_get_priority (MuMsgGMime *msg) const char* -mu_msg_gmime_get_header (MuMsgGMime *msg, const char* header) +mu_msg_get_header (MuMsg *msg, const char* header) { g_return_val_if_fail (msg, NULL); g_return_val_if_fail (header, NULL); @@ -472,7 +444,7 @@ mu_msg_gmime_get_header (MuMsgGMime *msg, const char* header) time_t -mu_msg_gmime_get_timestamp (MuMsgGMime *msg) +mu_msg_get_timestamp (MuMsg *msg) { g_return_val_if_fail (msg, 0); @@ -666,7 +638,7 @@ cleanup: static char* -get_body (MuMsgGMime *msg, gboolean want_html) +get_body (MuMsg *msg, gboolean want_html) { GetBodyData data; @@ -690,7 +662,7 @@ get_body (MuMsgGMime *msg, gboolean want_html) } const char* -mu_msg_gmime_get_body_html (MuMsgGMime *msg) +mu_msg_get_body_html (MuMsg *msg) { g_return_val_if_fail (msg, NULL); @@ -702,7 +674,7 @@ mu_msg_gmime_get_body_html (MuMsgGMime *msg) const char* -mu_msg_gmime_get_body_text (MuMsgGMime *msg) +mu_msg_get_body_text (MuMsg *msg) { g_return_val_if_fail (msg, NULL); @@ -751,7 +723,7 @@ summarize (const char* str, size_t max_lines) const char* -mu_msg_gmime_get_summary (MuMsgGMime *msg, size_t max_lines) +mu_msg_get_summary (MuMsg *msg, size_t max_lines) { const char *body; @@ -763,7 +735,7 @@ mu_msg_gmime_get_summary (MuMsgGMime *msg, size_t max_lines) return msg->_fields[SUMMARY_FIELD]; /* nope; calculate it */ - body = mu_msg_gmime_get_body_text (msg); + body = mu_msg_get_body_text (msg); if (!body) return NULL; /* there was no text body */ @@ -772,7 +744,7 @@ mu_msg_gmime_get_summary (MuMsgGMime *msg, size_t max_lines) const char* -mu_msg_gmime_get_field_string (MuMsgGMime *msg, const MuMsgField* field) +mu_msg_get_field_string (MuMsg *msg, const MuMsgField* field) { MuMsgFieldId id; @@ -781,22 +753,22 @@ mu_msg_gmime_get_field_string (MuMsgGMime *msg, const MuMsgField* field) g_return_val_if_fail (id != MU_MSG_FIELD_ID_NONE, NULL); switch (id) { - case MU_MSG_FIELD_ID_BODY_TEXT: return mu_msg_gmime_get_body_text (msg); - case MU_MSG_FIELD_ID_BODY_HTML: return mu_msg_gmime_get_body_html (msg); - case MU_MSG_FIELD_ID_CC: return mu_msg_gmime_get_cc (msg); - case MU_MSG_FIELD_ID_FROM: return mu_msg_gmime_get_from (msg); - case MU_MSG_FIELD_ID_PATH: return mu_msg_gmime_get_path (msg); - case MU_MSG_FIELD_ID_SUBJECT: return mu_msg_gmime_get_subject (msg); - case MU_MSG_FIELD_ID_TO: return mu_msg_gmime_get_to (msg); - case MU_MSG_FIELD_ID_MSGID: return mu_msg_gmime_get_msgid (msg); - case MU_MSG_FIELD_ID_MAILDIR: return mu_msg_gmime_get_maildir (msg); + case MU_MSG_FIELD_ID_BODY_TEXT: return mu_msg_get_body_text (msg); + case MU_MSG_FIELD_ID_BODY_HTML: return mu_msg_get_body_html (msg); + case MU_MSG_FIELD_ID_CC: return mu_msg_get_cc (msg); + case MU_MSG_FIELD_ID_FROM: return mu_msg_get_from (msg); + case MU_MSG_FIELD_ID_PATH: return mu_msg_get_path (msg); + case MU_MSG_FIELD_ID_SUBJECT: return mu_msg_get_subject (msg); + case MU_MSG_FIELD_ID_TO: return mu_msg_get_to (msg); + case MU_MSG_FIELD_ID_MSGID: return mu_msg_get_msgid (msg); + case MU_MSG_FIELD_ID_MAILDIR: return mu_msg_get_maildir (msg); default: g_return_val_if_reached (NULL); } } gint64 -mu_msg_gmime_get_field_numeric (MuMsgGMime *msg, const MuMsgField* field) +mu_msg_get_field_numeric (MuMsg *msg, const MuMsgField* field) { MuMsgFieldId id; @@ -806,13 +778,13 @@ mu_msg_gmime_get_field_numeric (MuMsgGMime *msg, const MuMsgField* field) switch (id) { case MU_MSG_FIELD_ID_DATE: - return mu_msg_gmime_get_date(msg); + return mu_msg_get_date(msg); case MU_MSG_FIELD_ID_FLAGS: - return mu_msg_gmime_get_flags(msg); - case MU_MSG_FIELD_ID_PRIORITY: - return mu_msg_gmime_get_priority(msg); + return mu_msg_get_flags(msg); + case MU_MSG_FIELD_ID_PRIO: + return mu_msg_get_prio(msg); case MU_MSG_FIELD_ID_SIZE: - return mu_msg_gmime_get_size(msg); + return mu_msg_get_size(msg); default: g_warning ("%s: %u", __FUNCTION__, (guint)id); g_return_val_if_reached (0); @@ -820,139 +792,12 @@ mu_msg_gmime_get_field_numeric (MuMsgGMime *msg, const MuMsgField* field) } -static gboolean -fill_contact (MuMsgContact *contact, InternetAddress *addr, - MuMsgContactType ctype) -{ - if (!addr) - return FALSE; - - contact->name = (char*)internet_address_get_name (addr); - contact->type = ctype; - - /* we only support internet addresses; - * if we don't check, g_mime hits an assert - */ - contact->address = (char*)internet_address_mailbox_get_addr - (INTERNET_ADDRESS_MAILBOX(addr)); - - return TRUE; -} - - -static void -address_list_foreach (InternetAddressList *addrlist, - MuMsgContactType ctype, - MuMsgContactForeachFunc func, - gpointer user_data) -{ - int i; - - if (!addrlist) - return; - - for (i = 0; i != internet_address_list_length(addrlist); ++i) { - - MuMsgContact contact; - if (!fill_contact(&contact, - internet_address_list_get_address (addrlist, i), - ctype)) { - MU_WRITE_LOG ("ignoring contact"); - continue; - } - - if (!(func)(&contact, user_data)) - break; - } - - return; -} - - - -static void -get_contacts_from (MuMsgGMime *msg, MuMsgContactForeachFunc func, - gpointer user_data) -{ - InternetAddressList *lst; - - /* we go through this whole excercise of trying to get a *list* - * of 'From:' address (usually there is only one...), because - * internet_address_parse_string has the nice side-effect of - * splitting in names and addresses for us */ - lst = internet_address_list_parse_string ( - g_mime_message_get_sender (msg->_mime_msg)); - if (lst) { - address_list_foreach (lst, MU_MSG_CONTACT_TYPE_FROM, - func, user_data); - g_object_unref (G_OBJECT(lst)); - } -} - - -void -mu_msg_gmime_contacts_foreach (MuMsgGMime *msg, MuMsgContactForeachFunc func, - gpointer user_data) -{ - int i; - struct { - GMimeRecipientType _gmime_type; - MuMsgContactType _type; - } ctypes[] = { - {GMIME_RECIPIENT_TYPE_TO, MU_MSG_CONTACT_TYPE_TO}, - {GMIME_RECIPIENT_TYPE_CC, MU_MSG_CONTACT_TYPE_CC}, - {GMIME_RECIPIENT_TYPE_BCC, MU_MSG_CONTACT_TYPE_BCC}, - }; - - g_return_if_fail (func && msg); - - /* first, get the from address(es) */ - get_contacts_from (msg, func, user_data); - - /* get to, cc, bcc */ - for (i = 0; i != G_N_ELEMENTS(ctypes); ++i) { - InternetAddressList *addrlist; - addrlist = g_mime_message_get_recipients (msg->_mime_msg, - ctypes[i]._gmime_type); - address_list_foreach (addrlist, ctypes[i]._type, func, user_data); - } -} - - -static gboolean -each_contact (MuMsgContact *contact, GSList **lst) -{ - MuMsgContact *ct; - - ct = mu_msg_contact_new (mu_msg_contact_name(contact), - mu_msg_contact_address (contact), - mu_msg_contact_type (contact)); - - *lst = g_slist_append (*lst, ct); - return TRUE; -} - - -GSList * -mu_msg_gmime_get_contacts (MuMsgGMime *msg) -{ - GSList *contacts; - - g_return_val_if_fail (msg, NULL); - - contacts = NULL; - mu_msg_gmime_contacts_foreach (msg, - (MuMsgContactForeachFunc)each_contact, - &contacts); - return contacts; -} - static gboolean _initialized = FALSE; void -mu_msg_gmime_init (void) +mu_msg_init (void) { if (!_initialized) { g_mime_init(0); @@ -963,7 +808,7 @@ mu_msg_gmime_init (void) void -mu_msg_gmime_uninit (void) +mu_msg_uninit (void) { if (_initialized) { g_mime_shutdown(); @@ -972,153 +817,3 @@ mu_msg_gmime_uninit (void) } } -struct _PartData { - unsigned _idx; - MuMsgPartInfoForeachFunc _func; - gpointer _user_data; -}; -typedef struct _PartData PartData; - - -static void -part_foreach_cb (GMimeObject *parent, GMimeObject *part, PartData *pdata) -{ - GMimeContentType *ct; - MuMsgPartInfo pi; - - memset (&pi, 0, sizeof pi); - pi.index = pdata->_idx++; - pi.content_id = (char*)g_mime_object_get_content_id (part); - - ct = g_mime_object_get_content_type (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); - } - - if (GMIME_IS_PART(part)) { - pi.disposition = (char*)g_mime_object_get_disposition (part); - pi.file_name = (char*)g_mime_part_get_filename (GMIME_PART(part)); - } - - pdata->_func(&pi, pdata->_user_data); -} - - - -void -mu_msg_gmime_msg_part_infos_foreach (MuMsgGMime *msg, - MuMsgPartInfoForeachFunc func, - gpointer user_data) -{ - PartData pdata; - - g_return_if_fail (msg); - g_return_if_fail (GMIME_IS_OBJECT(msg->_mime_msg)); - - pdata._idx = 0; - pdata._func = func; - pdata._user_data = user_data; - - g_mime_message_foreach (msg->_mime_msg, - (GMimeObjectForeachFunc)part_foreach_cb, - &pdata); -} - - -struct _SavePartData { - guint idx, wanted_idx; - const gchar* targetdir; - gboolean overwrite; - gboolean stream; - gboolean result; -}; -typedef struct _SavePartData SavePartData; - - -static gboolean -save_part (GMimeObject *part, const char *filename, - const char *targetdir, gboolean overwrite) -{ - int fd, rv; - GMimeDataWrapper *wrapper; - GMimeStream *stream; - - rv = TRUE; - fd = mu_util_create_writeable_fd (filename, targetdir, - overwrite); - if (fd == -1) { - g_warning ("error saving file %s%s %s", - filename, errno != 0 ? ":" : "", - errno != 0 ? strerror(errno) : ""); - return FALSE; - } - - stream = g_mime_stream_fs_new (fd); - if (!stream) { - g_warning ("%s: failed to create stream", __FUNCTION__); - close (fd); - return FALSE; - } - - g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), - TRUE); /* GMimeStream will close fd */ - - wrapper = g_mime_part_get_content_object (GMIME_PART(part)); - if (!wrapper) { - g_object_unref (G_OBJECT(stream)); - g_warning ("%s: failed to create wrapper", __FUNCTION__); - return FALSE; - } - - rv = g_mime_data_wrapper_write_to_stream (wrapper, stream); - g_object_unref (G_OBJECT(rv)); - - return rv == -1 ? FALSE : TRUE; -} - - - -static void -part_foreach_save_cb (GMimeObject *parent, GMimeObject *part, - SavePartData *spd) -{ - const gchar* filename; - - /* did we find the right part yet? */ - if (spd->result || spd->wanted_idx != spd->idx++) - return; - - if (!GMIME_IS_PART(part)) - return; - - filename = g_mime_part_get_filename (GMIME_PART(part)); - if (filename) { - spd->result = save_part (part, filename, - spd->targetdir, - spd->overwrite); - } else - spd->result = FALSE; -} - - - -gboolean -mu_msg_gmime_mime_part_save (MuMsgGMime *msg, int wanted_idx, - const char *targetdir, gboolean overwrite) -{ - SavePartData spd; - spd.idx = 0; - spd.wanted_idx = wanted_idx; - spd.targetdir = targetdir; - spd.overwrite = overwrite; - spd.stream = FALSE; - spd.result = FALSE; - - g_mime_message_foreach (msg->_mime_msg, - (GMimeObjectForeachFunc)part_foreach_save_cb, - &spd); - - return spd.result; -} - diff --git a/src/mu-msg.h b/src/mu-msg.h index 4026689b..076a56d1 100644 --- a/src/mu-msg.h +++ b/src/mu-msg.h @@ -22,25 +22,280 @@ #include "mu-msg-flags.h" #include "mu-msg-fields.h" +#include "mu-msg-status.h" +#include "mu-msg-prio.h" -/* what kind of message is this; use by the indexer */ -enum _MuMsgStatus { - MU_MSG_STATUS_NEW, /* message is new */ - MU_MSG_STATUS_UPDATE, /* message is to be updated */ - MU_MSG_STATUS_CLEANUP, /* message is to be cleaned up from db */ - MU_MSG_STATUS_CLEANED_UP, /* message has been cleaned up from db */ - MU_MSG_STATUS_EXISTS, /* message exists (will not be cleaned up) */ - MU_MSG_STATUS_UPTODATE /* message is up-to-date */ -}; -typedef enum _MuMsgStatus MuMsgStatus; +G_BEGIN_DECLS -enum _MuMsgPriority { - MU_MSG_PRIORITY_NONE = 0, +struct _MuMsg; +typedef struct _MuMsg MuMsg; - MU_MSG_PRIORITY_LOW = 1, - MU_MSG_PRIORITY_NORMAL = 2, - MU_MSG_PRIORITY_HIGH = 3 -}; -typedef enum _MuMsgPriority MuMsgPriority; +/** + * initialize the message parsing system; this function must be called + * before doing any message parsing (ie., any of the other + * mu_msg functions). when done with the message parsing system, + * call mu_msg_uninit. Note: calling this function on an already + * initialized system has no effect + */ +void mu_msg_init (void); + +/** + * uninitialize the messge parsing system that has previously been + * initialized with mu_msg_init. not calling mu_msg_uninit after + * mu_msg_init has been called will lead to memory leakage. Note: + * calling mu_msg_uninit on an uninitialized system has no + * effect + */ +void mu_msg_uninit (void); + + +/** + * create a new MuMsg* instance which parses a message and provides + * read access to its properties; call mu_msg_destroy when done with it. + * + * @param path full path to an email message file + * + * @param mdir the maildir for this message; ie, if the path is + * ~/Maildir/foo/bar/cur/msg, the maildir would be foo/bar; you can + * pass NULL for this parameter, in which case some maildir-specific + * information is not available. + * + * @return a new MuMsg instance or NULL in case of error + */ +MuMsg* mu_msg_new (const char* filepath, + const char *maildir); + + +/** + * destroy a MuMsg* instance; call this function when done with + * a MuMsg + * + * @param msg a MuMsg* instance or NULL + */ +void mu_msg_destroy (MuMsg *msg); + + +/** + * get the plain text body of this message + * + * @param msg a valid MuMsg* instance + * + * @return the plain text body or NULL in case of error or if there is no + * such body. the returned string should *not* be modified or freed. + * The returned data is in UTF8 or NULL. + */ +const char* mu_msg_get_body_text (MuMsg *msg); + + +/** + * get the html body of this message + * + * @param msg a valid MuMsg* instance + * + * @return the html body or NULL in case of error or if there is no + * such body. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_body_html (MuMsg *msg); + + +/** + * get a summary of the body of this message; a summary takes up to + * the first @max_lines from the message, and replaces newlines + * etc. with single whitespace characters. This only works if there's + * a text-body for the message + * + * @param msg a valid MuMsg* instance + * @param max_lines the max number of lines to summarize + * + * @return the summary of the message or NULL in case of error or if + * there is no such body. the returned string should *not* be modified + * or freed. When called multiple times, the function will always + * return the same summary, regardless of a different max_lines value. + */ +const char* mu_msg_get_summary (MuMsg *msg, size_t max_lines); + +/** + * save a specific attachment to some targetdir + * + * @param msg a valid MuMsg instance + * @param wanted_idx index of the attachment you want to save + * @param targetdir filesystem directory to save the attachment + * @param overwrite existing files? + * + * @return TRUE if saving succeeded, FALSE otherwise + */ +gboolean +mu_msg_mime_part_save (MuMsg *msg, int wanted_idx, + const char *targetdir, gboolean overwrite); + +/** + * get the sender (From:) of this message + * + * @param msg a valid MuMsg* instance + * + * @return the sender of this Message or NULL in case of error or if there + * is no sender. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_from (MuMsg *msg); + + +/** + * get the recipients (To:) of this message + * + * @param msg a valid MuMsg* instance + * + * @return the sender of this Message or NULL in case of error or if there + * are no recipients. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_to (MuMsg *msg); + + +/** + * get the carbon-copy recipients (Cc:) of this message + * + * @param msg a valid MuMsg* instance + * + * @return the Cc: recipients of this Message or NULL in case of error or if + * there are no such recipients. the returned string should *not* be modified + * or freed. + */ +const char* mu_msg_get_cc (MuMsg *msg); + +/** + * get the file system path of this message + * + * @param msg a valid MuMsg* instance + * + * @return the path of this Message or NULL in case of error. + * the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_path (MuMsg *msg); + + +/** + * get the maildir this message lives in; ie, if the path is + * ~/Maildir/foo/bar/cur/msg, the maildir would be foo/bar + * + * @param msg a valid MuMsg* instance + * + * @return the maildir requested or NULL in case of error. The returned + * string should *not* be modified or freed. + */ +const char* mu_msg_get_maildir (MuMsg *msg); + + +/** + * get the subject of this message + * + * @param msg a valid MuMsg* instance + * + * @return the subject of this Message or NULL in case of error or if there + * is no subject. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_subject (MuMsg *msg); + +/** + * get the Message-Id of this message + * + * @param msg a valid MuMsg* instance + * + * @return the Message-Id of this Message (without the enclosing <>) + * or NULL in case of error or if there is none. the returned string + * should *not* be modified or freed. + */ +const char* mu_msg_get_msgid (MuMsg *msg); + + +/** + * get any arbitrary header from this message + * + * @param msg a valid MuMsg* instance + * @header the header requested + * + * @return the header requested or NULL in case of error or if there + * is no such header. the returned string should *not* be modified or freed. + */ +const char* mu_msg_get_header (MuMsg *msg, + const char* header); + +/** + * get the message date/time (the Date: field) as time_t, using UTC + * + * @param msg a valid MuMsg* instance + * + * @return message date/time or 0 in case of error or if there + * is no such header. + */ +time_t mu_msg_get_date (MuMsg *msg); + +/** + * get the flags for this message + * + * @param msg valid MuMsg* instance + * + * @return the fileflags as logically OR'd #Mu MsgFlags or 0 if + * there are none. + */ +MuMsgFlags mu_msg_get_flags (MuMsg *msg); + + +/** + * get the file size in bytes of this message + * + * @param msg a valid MuMsg* instance + * + * @return the filesize + */ +size_t mu_msg_get_size (MuMsg *msg); + + +/** + * get some field value as string + * + * @param msg a valid MuMsg instance + * @param field the field to retrieve; it must be a string-typed field + * + * @return a string that should not be freed + */ +const char* mu_msg_get_field_string (MuMsg *msg, + const MuMsgField* field); + +/** + * get some field value as string + * + * @param msg a valid MuMsg instance + * @param field the field to retrieve; it must be a numeric field + * + * @return a string that should not be freed + */ +gint64 mu_msg_get_field_numeric (MuMsg *msg, + const MuMsgField* field); + +/** + * get the message priority for this message (MU_MSG_PRIO_LOW, + * MU_MSG_PRIO_NORMAL or MU_MSG_PRIO_HIGH) the X-Priority, + * X-MSMailPriority, Importance and Precedence header are checked, in + * that order. if no known or explicit priority is set, + * MU_MSG_PRIO_NORMAL is assumed + * + * @param msg a valid MuMsg* instance + * + * @return the message priority (!= 0) or 0 in case of error + */ +MuMsgPrio mu_msg_get_prio (MuMsg *msg); + +/** + * get the timestamp (mtime) for the file containing this message + * + * @param msg a valid MuMsg* instance + * + * @return the timestamp or 0 in case of error + */ +time_t mu_msg_get_timestamp (MuMsg *msg); + + + + +G_END_DECLS #endif /*__MU_MSG_H__*/ diff --git a/src/mu-store-xapian.cc b/src/mu-store-xapian.cc index 9c372956..ac0cdd81 100644 --- a/src/mu-store-xapian.cc +++ b/src/mu-store-xapian.cc @@ -25,7 +25,6 @@ #include #include "mu-msg.h" -#include "mu-msg-gmime.h" #include "mu-store-xapian.h" #include "mu-util.h" @@ -170,11 +169,11 @@ mu_store_xapian_flush (MuStoreXapian *store) static void -add_terms_values_number (Xapian::Document& doc, MuMsgGMime *msg, +add_terms_values_number (Xapian::Document& doc, MuMsg *msg, const MuMsgField* field) { const std::string pfx (mu_msg_field_xapian_prefix(field), 1); - gint64 num = mu_msg_gmime_get_field_numeric (msg, field); + gint64 num = mu_msg_get_field_numeric (msg, field); const std::string numstr (Xapian::sortable_serialise((double)num)); doc.add_value ((Xapian::valueno)mu_msg_field_id(field), numstr); @@ -182,12 +181,12 @@ add_terms_values_number (Xapian::Document& doc, MuMsgGMime *msg, } static void -add_terms_values_string (Xapian::Document& doc, MuMsgGMime *msg, +add_terms_values_string (Xapian::Document& doc, MuMsg *msg, const MuMsgField* field) { const char* str; - str = mu_msg_gmime_get_field_string (msg, field); + str = mu_msg_get_field_string (msg, field); if (!str) return; @@ -213,17 +212,17 @@ add_terms_values_string (Xapian::Document& doc, MuMsgGMime *msg, } static void -add_terms_values_body (Xapian::Document& doc, MuMsgGMime *msg, +add_terms_values_body (Xapian::Document& doc, MuMsg *msg, const MuMsgField* field) { const char *str; - if (mu_msg_gmime_get_flags(msg) & MU_MSG_FLAG_ENCRYPTED) + if (mu_msg_get_flags(msg) & MU_MSG_FLAG_ENCRYPTED) return; /* don't store encrypted bodies */ - str = mu_msg_gmime_get_body_text (msg); + str = mu_msg_get_body_text (msg); if (!str) /* FIXME: html->txt fallback needed */ - str = mu_msg_gmime_get_body_html (msg); + str = mu_msg_get_body_html (msg); if (!str) return; /* no body... */ @@ -235,7 +234,7 @@ add_terms_values_body (Xapian::Document& doc, MuMsgGMime *msg, struct _MsgDoc { Xapian::Document *_doc; - MuMsgGMime *_msg; + MuMsg *_msg; }; typedef struct _MsgDoc MsgDoc; @@ -284,15 +283,15 @@ get_message_uid (const char* path) } static std::string -get_message_uid (MuMsgGMime *msg) +get_message_uid (MuMsg *msg) { - return get_message_uid (mu_msg_gmime_get_path(msg)); + return get_message_uid (mu_msg_get_path(msg)); } MuResult -mu_store_xapian_store (MuStoreXapian *store, MuMsgGMime *msg) +mu_store_xapian_store (MuStoreXapian *store, MuMsg *msg) { g_return_val_if_fail (store, MU_ERROR); g_return_val_if_fail (msg, MU_ERROR); diff --git a/src/mu-store-xapian.h b/src/mu-store-xapian.h index 7fbd4d6c..810b7181 100644 --- a/src/mu-store-xapian.h +++ b/src/mu-store-xapian.h @@ -1,5 +1,5 @@ /* -** Copyright (C) 2010 Dirk-Jan C. Binnema +** Copyright (C) 2008-2010 Dirk-Jan C. Binnema ** ** This program is free software; you can redistribute it and/or modify it ** under the terms of the GNU General Public License as published by the @@ -24,7 +24,7 @@ #include #include "mu-result.h" -#include "mu-msg-gmime.h" +#include "mu-msg.h" G_BEGIN_DECLS @@ -85,8 +85,7 @@ void mu_store_xapian_flush (MuStoreXapian *store); * * @return TRUE if it succeeded, FALSE otherwise */ -MuResult mu_store_xapian_store (MuStoreXapian *store, - MuMsgGMime *msg); +MuResult mu_store_xapian_store (MuStoreXapian *store, MuMsg *msg); /** diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am index 87349957..68a85902 100644 --- a/src/tests/Makefile.am +++ b/src/tests/Makefile.am @@ -44,9 +44,9 @@ TEST_PROGS += test-mu-query test_mu_query_SOURCES= test-mu-query.c dummy.cc test_mu_query_LDADD= libtestmucommon.la -TEST_PROGS += test-mu-msg-gmime -test_mu_msg_gmime_SOURCES= test-mu-msg-gmime.c -test_mu_msg_gmime_LDADD= libtestmucommon.la +TEST_PROGS += test-mu-msg +test_mu_msg_SOURCES= test-mu-msg.c +test_mu_msg_LDADD= libtestmucommon.la libtestmucommon_la_SOURCES= \ diff --git a/src/tests/test-mu-msg-gmime.c b/src/tests/test-mu-msg-gmime.c deleted file mode 100644 index d1f99e84..00000000 --- a/src/tests/test-mu-msg-gmime.c +++ /dev/null @@ -1,209 +0,0 @@ -/* -** Copyright (C) 2008-2010 Dirk-Jan C. Binnema -** -** This program is free software; you can redistribute it and/or modify it -** under the terms of the GNU General Public License as published by the -** Free Software Foundation; either version 3, or (at your option) any -** later version. -** -** This program is distributed in the hope that it will be useful, -** but WITHOUT ANY WARRANTY; without even the implied warranty of -** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -** GNU General Public License for more details. -** -** You should have received a copy of the GNU General Public License -** along with this program; if not, write to the Free Software Foundation, -** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -** -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif /*HAVE_CONFIG_H*/ - -#include -#include -#include -#include - -#include - -#include "test-mu-common.h" -#include "src/mu-msg-gmime.h" - -static gchar* -get_mailpath (unsigned idx) -{ - const char* mailfile; - - switch (idx) { - case 1: mailfile = "cur/1220863042.12663_1.mindcrime!2,S"; break; - case 2: mailfile = "cur/1220863087.12663_19.mindcrime!2,S"; break; - default: mailfile = NULL; - } - - if (mailfile) - return g_strdup_printf ("%s/%s", MU_TESTMAILDIR, mailfile); - else - return NULL; -} - - -static gboolean -each_contact (MuMsgContact *contact, GSList **lst) -{ - char *addr; - addr = g_strdup_printf ("%s <%s>", - contact->name ? contact->name : "", - contact->address ? contact->address : ""); - - *lst = g_slist_append (*lst, addr); - return TRUE; -} - - -static void -test_mu_msg_gmime_01 (void) -{ - char *mfile; - MuMsgGMime *msg; - GSList *lst; - - mu_msg_gmime_init (); - mfile = get_mailpath (1); - - msg = mu_msg_gmime_new (mfile, NULL); - - g_assert_cmpstr (mu_msg_gmime_get_to(msg), - ==, "Donald Duck "); - g_assert_cmpstr (mu_msg_gmime_get_subject(msg), - ==, "gcc include search order"); - g_assert_cmpstr (mu_msg_gmime_get_from(msg), - ==, "Mickey Mouse "); - g_assert_cmpstr (mu_msg_gmime_get_msgid(msg), - ==, "3BE9E6535E3029448670913581E7A1A20D852173@" - "emss35m06.us.lmco.com"); - g_assert_cmpstr (mu_msg_gmime_get_header(msg, "Mailing-List"), - ==, "contact gcc-help-help@gcc.gnu.org; run by ezmlm"); - g_assert_cmpuint (mu_msg_gmime_get_priority(msg), /* 'klub' */ - ==, MU_MSG_PRIORITY_NORMAL); - g_assert_cmpuint (mu_msg_gmime_get_date(msg), - ==, 1217530645); - { - GSList *lst, *cur; - lst = mu_msg_gmime_get_contacts (msg); - g_assert_cmpuint (g_slist_length(lst),==, 2); - cur = lst; - - g_assert_cmpstr (mu_msg_contact_name ((MuMsgContact*)cur->data), - ==, "Mickey Mouse"); - g_assert_cmpstr (mu_msg_contact_address ((MuMsgContact*)cur->data), - ==, "anon@example.com"); - - cur = g_slist_next (cur); - - g_assert_cmpstr (mu_msg_contact_name ((MuMsgContact*)cur->data), - ==, "Donald Duck"); - g_assert_cmpstr (mu_msg_contact_address ((MuMsgContact*)cur->data), - ==, "gcc-help@gcc.gnu.org"); - - - mu_msg_contacts_free (lst); - } - - mu_msg_gmime_destroy (msg); - - g_free (mfile); - mu_msg_gmime_uninit (); -} - - - -static void -test_mu_msg_gmime_02 (void) -{ - char *mfile; - MuMsgGMime *msg; - GSList *lst; - - mu_msg_gmime_init (); - mfile = get_mailpath (2); - - msg = mu_msg_gmime_new (mfile, NULL); - - g_assert_cmpstr (mu_msg_gmime_get_to(msg), - ==, "help-gnu-emacs@gnu.org"); - g_assert_cmpstr (mu_msg_gmime_get_subject(msg), - ==, "Re: Learning LISP; Scheme vs elisp."); - g_assert_cmpstr (mu_msg_gmime_get_from(msg), - ==, "anon@example.com"); - g_assert_cmpstr (mu_msg_gmime_get_msgid(msg), - ==, "r6bpm5-6n6.ln1@news.ducksburg.com"); - g_assert_cmpstr (mu_msg_gmime_get_header(msg, "Errors-To"), - ==, "help-gnu-emacs-bounces+xxxx.klub=gmail.com@gnu.org"); - g_assert_cmpuint (mu_msg_gmime_get_priority(msg), /* 'low' */ - ==, MU_MSG_PRIORITY_LOW); - g_assert_cmpuint (mu_msg_gmime_get_date(msg), - ==, 1218051515); - - { - GSList *lst, *cur; - lst = mu_msg_gmime_get_contacts (msg); - g_assert_cmpuint (g_slist_length(lst),==, 2); - cur = lst; - - g_assert_cmpstr (mu_msg_contact_name ((MuMsgContact*)cur->data), - ==, NULL); - g_assert_cmpstr (mu_msg_contact_address ((MuMsgContact*)cur->data), - ==, "anon@example.com"); - - cur = g_slist_next (cur); - - g_assert_cmpstr (mu_msg_contact_name ((MuMsgContact*)cur->data), - ==, NULL); - g_assert_cmpstr (mu_msg_contact_address ((MuMsgContact*)cur->data), - ==, "help-gnu-emacs@gnu.org"); - - - mu_msg_contacts_free (lst); - } - - - mu_msg_gmime_destroy (msg); - - g_free (mfile); - mu_msg_gmime_uninit (); -} - - - - -static gboolean -ignore_error (const char* log_domain, GLogLevelFlags log_level, const gchar* msg, - gpointer user_data) -{ - return FALSE; /* don't abort */ -} - -static void -shutup (void) {} - - - -int -main (int argc, char *argv[]) -{ - g_test_init (&argc, &argv, NULL); - - /* mu_msg_str_date */ - g_test_add_func ("/mu-msg-gmime/mu-msg-gmime-01", - test_mu_msg_gmime_01); - g_test_add_func ("/mu-msg-gmime/mu-msg-gmime-02", - test_mu_msg_gmime_02); - - g_log_set_handler (NULL, - G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL| G_LOG_FLAG_RECURSION, - (GLogFunc)shutup, NULL); - - return g_test_run (); -} diff --git a/src/tests/test-mu-msg-str.c b/src/tests/test-mu-msg-str.c index 39ea2746..c8e1871f 100644 --- a/src/tests/test-mu-msg-str.c +++ b/src/tests/test-mu-msg-str.c @@ -102,9 +102,9 @@ test_mu_msg_str_size_02 (void) static void test_mu_msg_str_prio_01 (void) { - g_assert_cmpstr (mu_msg_str_prio(MU_MSG_PRIORITY_LOW), ==, "low"); - g_assert_cmpstr (mu_msg_str_prio(MU_MSG_PRIORITY_NORMAL), ==, "normal"); - g_assert_cmpstr (mu_msg_str_prio(MU_MSG_PRIORITY_HIGH), ==, "high"); + g_assert_cmpstr (mu_msg_str_prio(MU_MSG_PRIO_LOW), ==, "low"); + g_assert_cmpstr (mu_msg_str_prio(MU_MSG_PRIO_NORMAL), ==, "normal"); + g_assert_cmpstr (mu_msg_str_prio(MU_MSG_PRIO_HIGH), ==, "high"); }