From 628d154a2ca0398fe63e586ebc7b206e7b6522ab Mon Sep 17 00:00:00 2001 From: "Dirk-Jan C. Binnema" Date: Mon, 12 Sep 2011 20:38:40 +0300 Subject: [PATCH] * minor / cosmetic changes --- configure.ac | 3 +- libmuguile/mu-guile-store.c | 10 ++- src/mu-config.h | 4 +- src/mu-container.c | 134 +++++++++++++++++++----------------- src/mu-index.c | 27 ++++---- src/mu-log.c | 3 +- src/mu-msg-part.c | 102 +++++++++++++++------------ src/mu-store.h | 32 +++++++-- src/mu-str.c | 131 +++++++++++++++++------------------ src/mu-threader.c | 2 +- src/mu-util.h | 3 +- 11 files changed, 245 insertions(+), 206 deletions(-) diff --git a/configure.ac b/configure.ac index 8767a920..de09cef6 100644 --- a/configure.ac +++ b/configure.ac @@ -272,7 +272,7 @@ AS_IF([test "x$PMCCABE" = "xno"],[ *** Please install it if you want to run the automated code checks]) ],[have_pmccabe="yes"]) -#toys/procmule/Makefile + AC_CONFIG_FILES([ Makefile @@ -284,6 +284,7 @@ toys/Makefile toys/mug/Makefile toys/mug2/Makefile toys/muile/Makefile +toys/procmule/Makefile man/Makefile m4/Makefile contrib/Makefile diff --git a/libmuguile/mu-guile-store.c b/libmuguile/mu-guile-store.c index 190a4205..d4a508d4 100644 --- a/libmuguile/mu-guile-store.c +++ b/libmuguile/mu-guile-store.c @@ -42,9 +42,7 @@ get_query (void) if (!query) { mu_guile_g_error ("", err); - if (err) - g_error_free (err); - return NULL; + g_clear_error (&err); } return query; @@ -60,10 +58,9 @@ get_query_iter (MuQuery *query, const char* expr) err = NULL; iter = mu_query_run (query, expr, FALSE, MU_MSG_FIELD_ID_NONE, TRUE, &err); - if (err) { + if (!iter) { mu_guile_g_error ("", err); - g_error_free (err); - return NULL; + g_clear_error (&err); } return iter; @@ -80,6 +77,7 @@ call_func (SCM FUNC, MuMsgIter *iter, const char* func_name) msgsmob = mu_guile_msg_to_scm (mu_msg_ref(msg)); scm_call_1 (FUNC, msgsmob); + } diff --git a/src/mu-config.h b/src/mu-config.h index d2e8484d..4c9e82af 100644 --- a/src/mu-config.h +++ b/src/mu-config.h @@ -53,7 +53,7 @@ enum _MuConfigFormat { /* for find */ MU_CONFIG_FORMAT_LINKS, /* output as symlinks */ MU_CONFIG_FORMAT_XML, /* output xml */ - MU_CONFIG_FORMAT_XQUERY, /* output the xapian query */ + MU_CONFIG_FORMAT_XQUERY /* output the xapian query */ }; typedef enum _MuConfigFormat MuConfigFormat; @@ -72,7 +72,7 @@ enum _MuConfigCmd { MU_CONFIG_CMD_REMOVE, MU_CONFIG_CMD_SERVER, - MU_CONFIG_CMD_NONE, + MU_CONFIG_CMD_NONE }; typedef enum _MuConfigCmd MuConfigCmd; diff --git a/src/mu-container.c b/src/mu-container.c index 6a9d1c64..cf4a6af4 100644 --- a/src/mu-container.c +++ b/src/mu-container.c @@ -29,7 +29,7 @@ * path data structure, to determine the thread paths mentioned above; * the path is filled as we're traversing the tree of MuContainers * (messages) - */ + */ struct _Path { int *_data; guint _len; @@ -47,14 +47,14 @@ mu_container_new (MuMsg *msg, guint docid, const char *msgid) MuContainer *c; g_return_val_if_fail (!msg || docid != 0, NULL); - + c = g_slice_new0 (MuContainer); if (msg) c->msg = mu_msg_ref (msg); - + c->docid = docid; c->msgid = msgid; - + return c; } @@ -82,7 +82,7 @@ set_parent (MuContainer *c, MuContainer *parent) static MuContainer* find_last (MuContainer *c) -{ +{ while (c && c->next) c = c->next; @@ -111,11 +111,11 @@ assert_no_duplicates (MuContainer *c) GHashTable *hash; hash = g_hash_table_new (g_direct_hash, g_direct_equal); - + mu_container_foreach (c, (MuContainerForeachFunc)check_dup, hash); - + g_hash_table_destroy (hash); } #endif @@ -125,18 +125,18 @@ MuContainer* mu_container_append_siblings (MuContainer *c, MuContainer *sibling) { g_assert (c); - + g_return_val_if_fail (c, NULL); g_return_val_if_fail (sibling, NULL); g_return_val_if_fail (c != sibling, NULL); /* assert_no_duplicates (c); */ - + set_parent (sibling, c->parent); (find_last(c))->next = sibling; /* assert_no_duplicates (c); */ - + return c; } @@ -144,25 +144,25 @@ MuContainer* mu_container_remove_sibling (MuContainer *c, MuContainer *sibling) { MuContainer *cur, *prev; - + g_return_val_if_fail (c, NULL); g_return_val_if_fail (sibling, NULL); - + for (prev = NULL, cur = c; cur; cur = cur->next) { - + if (cur == sibling) { if (!prev) c = cur->next; - else + else prev->next = cur->next; break; } - prev = cur; + prev = cur; } return c; } - + MuContainer* mu_container_append_children (MuContainer *c, MuContainer *child) { @@ -171,7 +171,7 @@ mu_container_append_children (MuContainer *c, MuContainer *child) g_return_val_if_fail (c != child, NULL); /* assert_no_duplicates (c); */ - + set_parent (child, c); if (!c->child) c->child = child; @@ -179,7 +179,7 @@ mu_container_append_children (MuContainer *c, MuContainer *child) c->child = mu_container_append_siblings (c->child, child); /* assert_no_duplicates (c->child); */ - + return c; } @@ -210,7 +210,7 @@ mu_container_path_foreach_real (MuContainer *c, guint level, Path *path, path_inc (path, level); func (c, user_data, path); - + /* children */ mu_container_path_foreach_real (c->child, level + 1, path, func, user_data); @@ -223,9 +223,9 @@ mu_container_path_foreach (MuContainer *c, MuContainerPathForeachFunc func, gpointer user_data) { Path *path; - + path = path_new (100); - + mu_container_path_foreach_real (c, 0, path, func, user_data); path_destroy (path); @@ -237,17 +237,17 @@ mu_container_foreach (MuContainer *c, MuContainerForeachFunc func, gpointer user_data) { g_return_val_if_fail (func, FALSE); - + if (!c) return TRUE; - + if (!mu_container_foreach (c->child, func, user_data)) return FALSE; /* recurse into children */ - - /* recurse into siblings */ + + /* recurse into siblings */ if (!mu_container_foreach (c->next, func, user_data)) return FALSE; - + return func (c, user_data); } @@ -275,9 +275,9 @@ mu_container_to_list (MuContainer *c) { GSList *lst; - for (lst = NULL; c; c = c->next) + for (lst = NULL; c; c = c->next) lst = g_slist_prepend (lst, c); - + return lst; } @@ -294,7 +294,7 @@ mu_container_from_list (GSList *lst) cur->next = lst ? (MuContainer*)lst->data : NULL; cur=cur->next; } - + return c; } @@ -312,7 +312,7 @@ sort_func_wrapper (MuContainer *a, MuContainer *b, SortFuncData *data) MuContainer *a1, *b1; /* use the first non-empty 'left child' message if this one - * is */ + * is */ for (a1 = a; a1->msg == NULL && a1->child != NULL; a1 = a1->child); for (b1 = b; b1->msg == NULL && b1->child != NULL; b1 = b1->child); @@ -322,11 +322,11 @@ sort_func_wrapper (MuContainer *a, MuContainer *b, SortFuncData *data) return 1; else if (!b1->msg) return -1; - + if (data->invert) return mu_msg_cmp (b1->msg, a1->msg, data->mfid); else - return mu_msg_cmp (a1->msg, b1->msg, data->mfid); + return mu_msg_cmp (a1->msg, b1->msg, data->mfid); } static MuContainer* @@ -334,22 +334,22 @@ mu_container_sort_real (MuContainer *c, SortFuncData *sfdata) { GSList *lst; MuContainer *cur; - + if (!c) return NULL; - for (cur = c; cur; cur = cur->next) + for (cur = c; cur; cur = cur->next) if (cur->child) cur->child = mu_container_sort_real (cur->child, sfdata); - + /* sort siblings */ lst = mu_container_to_list (c); lst = g_slist_sort_with_data(lst, (GCompareDataFunc)sort_func_wrapper, - sfdata); + sfdata); c = mu_container_from_list (lst); g_slist_free (lst); - + return c; } @@ -358,14 +358,18 @@ MuContainer* mu_container_sort (MuContainer *c, MuMsgFieldId mfid, gpointer user_data, gboolean invert) { - - SortFuncData sfdata = { mfid, invert, user_data }; + + SortFuncData sfdata; + + sfdata.mfid = mfid; + sfdata.invert = invert; + sfdata.user_data = user_data; g_return_val_if_fail (c, NULL); g_return_val_if_fail (mu_msg_field_id_is_valid(mfid), NULL); - + return mu_container_sort_real (c, &sfdata); -} +} static gboolean @@ -384,7 +388,7 @@ mu_container_reachable (MuContainer *haystack, MuContainer *needle) if (!mu_container_foreach (haystack, (MuContainerForeachFunc)unequal, needle)) return TRUE; - + return FALSE; } @@ -393,14 +397,14 @@ static gboolean dump_container (MuContainer *c) { const gchar* subject; - + if (!c) { g_print ("\n"); return TRUE; } - + subject = (c->msg) ? mu_msg_get_subject (c->msg) : ""; - + g_print ("[%s][%s m:%p p:%p docid:%u %s]\n",c->msgid, subject, (void*)c, (void*)c->parent, c->docid, c->msg ? mu_msg_get_path (c->msg) : ""); @@ -429,10 +433,10 @@ path_new (guint initial) Path *p; p = g_slice_new0 (Path); - + p->_data = g_new0 (int, initial); p->_len = initial; - + return p; } @@ -441,7 +445,7 @@ path_destroy (Path *p) { if (!p) return; - + g_free (p->_data); g_slice_free (Path, p); } @@ -454,7 +458,7 @@ path_inc (Path *p, guint index) memset (&p->_data[p->_len], 0, p->_len); p->_len *= 2; } - + ++p->_data[index]; p->_data[index + 1] = 0; } @@ -468,13 +472,13 @@ path_to_string (Path *p, const char* frmt) if (!p->_data) return NULL; - + for (u = 0, str = NULL; p->_data[u] != 0; ++u) { char segm[16]; snprintf (segm, sizeof(segm), frmt, p->_data[u] - 1); - - if (!str) + + if (!str) str = g_strdup (segm); else { gchar *tmp; @@ -483,7 +487,7 @@ path_to_string (Path *p, const char* frmt) str = tmp; } } - + return str; } @@ -493,7 +497,7 @@ thread_info_new (gchar *threadpath, gboolean root, gboolean child, gboolean empty_parent, gboolean is_dup) { MuMsgIterThreadInfo *ti; - + ti = g_slice_new (MuMsgIterThreadInfo); ti->threadpath = threadpath; @@ -502,7 +506,7 @@ thread_info_new (gchar *threadpath, gboolean root, gboolean child, ti->prop |= child ? MU_MSG_ITER_THREAD_PROP_FIRST_CHILD : 0; ti->prop |= empty_parent ? MU_MSG_ITER_THREAD_PROP_EMPTY_PARENT : 0; ti->prop |= is_dup ? MU_MSG_ITER_THREAD_PROP_DUP : 0; - + return ti; } @@ -528,14 +532,14 @@ add_to_thread_info_hash (GHashTable *thread_info_hash, MuContainer *c, char *threadpath) { gboolean is_root, first_child, empty_parent, is_dup; - + /* 'root' means we're a child of the dummy root-container */ is_root = (c->parent == NULL); - + first_child = is_root ? FALSE : (c->parent->child == c); - empty_parent = is_root ? FALSE : (!c->parent->msg); + empty_parent = is_root ? FALSE : (!c->parent->msg); is_dup = c->flags & MU_CONTAINER_FLAG_DUP; - + g_hash_table_insert (thread_info_hash, GUINT_TO_POINTER(c->docid), thread_info_new (threadpath, @@ -552,21 +556,21 @@ thread_segment_format_string (size_t matchnum) { unsigned digitnum; static char frmt[16]; - + /* get the number of digits needed in a hex-representation of * matchnum */ digitnum = (unsigned) (ceil (log(matchnum)/log(16))); snprintf (frmt, sizeof(frmt),"%%0%ux", digitnum); - + return frmt; } static gboolean add_thread_info (MuContainer *c, ThreadInfo *ti, Path *path) -{ +{ gchar *pathstr; - pathstr = path_to_string (path, ti->format); + pathstr = path_to_string (path, ti->format); add_to_thread_info_hash (ti->hash, c, pathstr); return TRUE; @@ -580,14 +584,14 @@ mu_container_thread_info_hash_new (MuContainer *root_set, size_t matchnum) g_return_val_if_fail (root_set, NULL); g_return_val_if_fail (matchnum > 0, NULL); - + /* create hash docid => thread-info */ ti.hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)thread_info_destroy); ti.format = thread_segment_format_string (matchnum); - + mu_container_path_foreach (root_set, (MuContainerPathForeachFunc)add_thread_info, &ti); diff --git a/src/mu-index.c b/src/mu-index.c index 69c5eff6..f024e788 100644 --- a/src/mu-index.c +++ b/src/mu-index.c @@ -137,26 +137,29 @@ insert_or_update_maybe (const char* fullpath, const char* mdir, err = NULL; msg = mu_msg_new_from_file (fullpath, mdir, &err); - if ((G_UNLIKELY(!msg))) { - g_warning ("%s: failed to create mu_msg for %s", - __FUNCTION__, fullpath); - return MU_ERROR; - } + if ((G_UNLIKELY(!msg))) + goto errexit; /* we got a valid id; scan the message contents as well */ - if (G_UNLIKELY((!mu_store_store_msg (data->_store, msg, TRUE)))) { - g_warning ("%s: storing content %s failed", __FUNCTION__, - fullpath); - return MU_ERROR; - } + if (G_UNLIKELY((!mu_store_add_msg (data->_store, msg, TRUE, &err)))) + goto errexit; mu_msg_unref (msg); *updated = TRUE; - return MU_OK; + +errexit: + { + MuError me; + me = err ? err->code : MU_ERROR; + g_clear_error (&err); + if (msg) + mu_msg_unref (msg); + return me; + } } -static MuError + static MuError run_msg_callback_maybe (MuIndexCallbackData *data) { MuError result; diff --git a/src/mu-log.c b/src/mu-log.c index 12260ed3..cf0ff367 100644 --- a/src/mu-log.c +++ b/src/mu-log.c @@ -235,7 +235,8 @@ log_write (const char* domain, GLogLevelFlags level, /* get the time/date string */ now = time(NULL); - strftime (timebuf, sizeof(timebuf), "%F %T", localtime(&now)); + strftime (timebuf, sizeof(timebuf), "%Y-%m-%d %H:%M:%S", + localtime(&now)); /* now put it all together */ len = snprintf (buf, sizeof(buf), "%s [%s] %s\n", timebuf, diff --git a/src/mu-msg-part.c b/src/mu-msg-part.c index 6ead9257..7d80ef50 100644 --- a/src/mu-msg-part.c +++ b/src/mu-msg-part.c @@ -54,7 +54,7 @@ find_part (MuMsg* msg, guint partidx) fpdata.wanted_idx = partidx; fpdata.idx = 0; fpdata.part = NULL; - + g_mime_message_foreach (msg->_file->_mime_msg, (GMimeObjectForeachFunc)find_part_cb, &fpdata); @@ -84,15 +84,15 @@ part_foreach_cb (GMimeObject *parent, GMimeObject *part, PartData *pdata) 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.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(pdata->_msg, &pi, pdata->_user_data); + + pdata->_func(pdata->_msg, &pi, pdata->_user_data); } void @@ -100,16 +100,27 @@ mu_msg_part_foreach (MuMsg *msg, MuMsgPartForeachFunc func, gpointer user_data) { PartData pdata; - + g_return_if_fail (msg); - g_return_if_fail (msg->_file); + + /* if we don't have a file yet, we need to open it now... */ + if (!msg->_file) { + GError *err; + err = NULL; + msg->_file = mu_msg_file_new (mu_msg_get_path(msg), NULL, + &err); + if (!msg->_file) { + MU_HANDLE_G_ERROR(err); /* will free it */ + return; + } + } g_return_if_fail (GMIME_IS_OBJECT(msg->_file->_mime_msg)); pdata._msg = msg; pdata._idx = 0; pdata._func = func; pdata._user_data = user_data; - + g_mime_message_foreach (msg->_file->_mime_msg, (GMimeObjectForeachFunc)part_foreach_cb, &pdata); @@ -117,35 +128,38 @@ mu_msg_part_foreach (MuMsg *msg, MuMsgPartForeachFunc func, static gboolean -write_to_stream (GMimeObject *part, int fd) +write_to_stream (GMimeObject *part, int fd, GError **err) { GMimeStream *stream; GMimeDataWrapper *wrapper; gboolean rv; - + stream = g_mime_stream_fs_new (fd); if (!GMIME_IS_STREAM(stream)) { - g_critical ("%s: failed to create stream",__FUNCTION__); + g_set_error (err, 0, MU_ERROR_GMIME, + "failed to create stream"); return FALSE; } g_mime_stream_fs_set_owner (GMIME_STREAM_FS(stream), FALSE); - + wrapper = g_mime_part_get_content_object (GMIME_PART(part)); if (!GMIME_IS_DATA_WRAPPER(wrapper)) { - g_critical ("%s: failed to create wrapper", __FUNCTION__); + g_set_error (err, 0, MU_ERROR_GMIME, + "failed to create wrapper"); g_object_unref (stream); return FALSE; } g_object_ref (part); /* FIXME: otherwise, the unrefs below * give errors...*/ - + rv = g_mime_data_wrapper_write_to_stream (wrapper, stream); if (!rv) - g_critical ("%s: failed to write to stream", __FUNCTION__); - + g_set_error (err, 0, MU_ERROR_GMIME, + "failed to write to stream"); + g_object_unref (wrapper); g_object_unref (stream); - + return rv; } @@ -156,12 +170,12 @@ save_part (GMimeObject *part, const char *fullpath, { int fd; gboolean rv; - + /* 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 */ if (use_existing && access (fullpath, F_OK) == 0) return TRUE; - + /* ok, try to create the file */ fd = mu_util_create_writeable_fd (fullpath, 0600, overwrite); if (fd == -1) { @@ -169,17 +183,17 @@ save_part (GMimeObject *part, const char *fullpath, "could not open '%s' for writing: %s", fullpath, errno ? strerror(errno) : "error"); return FALSE; - } + } - rv = write_to_stream (part, fd); - if (close (fd) != 0) { + rv = write_to_stream (part, fd, err); + if (close (fd) != 0 && !err) { /* don't write on top of old err */ g_set_error (err, 0, MU_ERROR_FILE, "could not close '%s': %s", fullpath, errno ? strerror(errno) : "error"); return FALSE; } - return TRUE; + return rv; } @@ -194,7 +208,7 @@ mu_msg_part_filepath (MuMsg *msg, const char* targetdir, guint partidx) g_warning ("%s: cannot find part %u", __FUNCTION__, partidx); return NULL; } - + /* the easy case: the part has a filename */ fname = (gchar*)g_mime_part_get_filename (GMIME_PART(part)); if (fname) /* security: don't include any directory components... */ @@ -218,9 +232,9 @@ mu_msg_part_filepath_cache (MuMsg *msg, guint partid) { char *dirname, *filepath; const char* path; - + g_return_val_if_fail (msg, NULL); - + path = mu_msg_get_path (msg); if (!path) return NULL; @@ -231,7 +245,7 @@ mu_msg_part_filepath_cache (MuMsg *msg, guint partid) mu_util_cache_dir(), G_DIR_SEPARATOR, g_str_hash (path), G_DIR_SEPARATOR, partid); - + if (!mu_util_create_dir_maybe (dirname, 0700, FALSE)) { g_free (dirname); return NULL; @@ -239,9 +253,9 @@ mu_msg_part_filepath_cache (MuMsg *msg, guint partid) filepath = mu_msg_part_filepath (msg, dirname, partid); g_free (dirname); - if (!filepath) + if (!filepath) g_warning ("%s: could not get filename", __FUNCTION__); - + return filepath; } @@ -251,18 +265,18 @@ mu_msg_part_save (MuMsg *msg, const char *fullpath, guint partidx, gboolean overwrite, gboolean use_cached, 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); - + part = find_part (msg, partidx); if (!GMIME_IS_PART(part)) { g_set_error (err, 0, MU_ERROR_GMIME, "cannot find part %u", partidx); return FALSE; } - + if (!save_part (part, fullpath, overwrite, use_cached, err)) return FALSE; @@ -284,7 +298,7 @@ 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; } @@ -292,15 +306,15 @@ static int msg_part_find_idx (GMimeMessage *msg, MatchFunc func, gpointer user_data) { MatchData mdata; - + g_return_val_if_fail (msg, -1); g_return_val_if_fail (GMIME_IS_MESSAGE(msg), -1); - + mdata._idx = 0; mdata._found_idx = -1; mdata._matcher = func; mdata._user_data = user_data; - + g_mime_message_foreach (msg, (GMimeObjectForeachFunc)part_match_foreach_cb, &mdata); @@ -320,13 +334,13 @@ int mu_msg_part_find_cid (MuMsg *msg, const char* sought_cid) { const char* cid; - + g_return_val_if_fail (msg, -1); g_return_val_if_fail (sought_cid, -1); - + cid = g_str_has_prefix (sought_cid, "cid:") ? - sought_cid + 4 : sought_cid; - + sought_cid + 4 : sought_cid; + return msg_part_find_idx (msg->_file->_mime_msg, (MatchFunc)match_content_id, (gpointer)cid); @@ -344,14 +358,14 @@ static void match_filename_rx (GMimeObject *parent, GMimeObject *part, MatchData2 *mdata) { const char *fname; - + if (!GMIME_IS_PART(part)) goto leave; - + fname = g_mime_part_get_filename (GMIME_PART(part)); if (!fname) goto leave; - + if (g_regex_match (mdata->_rx, fname, 0, NULL)) mdata->_lst = g_slist_prepend (mdata->_lst, GUINT_TO_POINTER(mdata->_idx)); @@ -364,14 +378,14 @@ GSList* mu_msg_part_find_files (MuMsg *msg, const GRegex *pattern) { MatchData2 mdata; - + g_return_val_if_fail (msg, NULL); g_return_val_if_fail (pattern, NULL); mdata._lst = NULL; mdata._rx = pattern; mdata._idx = 0; - + g_mime_message_foreach (msg->_file->_mime_msg, (GMimeObjectForeachFunc)match_filename_rx, &mdata); diff --git a/src/mu-store.h b/src/mu-store.h index a7fdf0d1..447995fa 100644 --- a/src/mu-store.h +++ b/src/mu-store.h @@ -161,6 +161,8 @@ const char* mu_store_version (MuStore *store); */ void mu_store_flush (MuStore *store); +#define MU_STORE_INVALID_DOCID 0 + /** * store an email message in the XapianStore * @@ -172,10 +174,11 @@ void mu_store_flush (MuStore *store); * of a initial fill or rebuild of the database), we can set 'replace' * to FALSE for a couple% performance gain * - * @return TRUE if it succeeded, FALSE otherwise + * @return the docid of the stored message, or 0 + * (MU_STORE_INVALID_DOCID) in case of error */ -gboolean mu_store_store_msg (MuStore *store, MuMsg *msg, gboolean replace); - +unsigned mu_store_add_msg (MuStore *store, MuMsg *msg, gboolean replace, + GError **err); /** * store an email message in the XapianStore; similar to @@ -185,12 +188,13 @@ gboolean mu_store_store_msg (MuStore *store, MuMsg *msg, gboolean replace); * @param store a valid store * @param path full filesystem path to a valid message * - * @return TRUE if it succeeded, FALSE otherwise + * @return the docid of the stored message, or 0 + * (MU_STORE_INVALID_DOCID) in case of error */ -gboolean mu_store_store_path (MuStore *store, const char *path); +unsigned mu_store_add_path (MuStore *store, const char *path, GError **err); /** - * remove a message from the database + * remove a message from the database based on its path * * @param store a valid store * @param msgpath path of the message (note, this is only used to @@ -340,6 +344,22 @@ gboolean mu_store_clear (MuStore *store, GError **err); */ gboolean mu_store_database_is_locked (const gchar *xpath); + + +/** + * get a specific message, based on its Xapian docid + * + * @param self a valid MuQuery instance + * @param docid the Xapian docid for the wanted message + * @param err receives error information, or NULL + * + * @return a MuMsg instance (use mu_msg_unref when done with it), or + * NULL in case of error + */ +MuMsg* mu_store_get_msg (MuStore *self, unsigned docid, GError **err); + + + G_END_DECLS #endif /*__MU_STORE_H__*/ diff --git a/src/mu-str.c b/src/mu-str.c index dbd71730..ef6c30be 100644 --- a/src/mu-str.c +++ b/src/mu-str.c @@ -1,22 +1,22 @@ /* -*-mode: c; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-*/ -/* +/* ** Copyright (C) 2008-2011 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. -** +** Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +** */ @@ -66,11 +66,11 @@ mu_str_size_s (size_t s) g_snprintf(buf, sizeof(buf), "%.1f kB", (double)s/(1000)); #endif /*HAVE_GLIB216*/ - + return buf; } -char* +char* mu_str_size (size_t s) { return g_strdup (mu_str_size_s(s)); @@ -98,7 +98,7 @@ mu_str_summarize (const char* str, size_t max_lines) g_return_val_if_fail (str, NULL); g_return_val_if_fail (max_lines > 0, NULL); - + /* len for summary <= original len */ summary = g_new (gchar, strlen(str) + 1); @@ -134,7 +134,7 @@ static void cleanup_contact (char *contact) { char *c, *c2; - + /* replace "'<> with space */ for (c2 = contact; *c2; ++c2) if (*c2 == '"' || *c2 == '\'' || *c2 == '<' || *c2 == '>') @@ -145,7 +145,7 @@ cleanup_contact (char *contact) c = g_strstr_len (contact, -1, "("); if (c && c - contact > 5) *c = '\0'; - + g_strstrip (contact); } @@ -156,7 +156,7 @@ mu_str_display_contact_s (const char *str) { static gchar contact[255]; gchar *c, *c2; - + str = str ? str : ""; g_strlcpy (contact, str, sizeof(contact)); @@ -173,7 +173,7 @@ mu_str_display_contact_s (const char *str) } cleanup_contact (contact); - + return contact; } @@ -201,7 +201,7 @@ each_check_prefix (MuMsgFieldId mfid, CheckPrefix *cpfx) if (!cpfx || cpfx->match) return; - + field_shortcut = mu_msg_field_shortcut (mfid); if (field_shortcut == cpfx->pfx[0] && cpfx->pfx[1] == ':') { cpfx->match = TRUE; @@ -223,10 +223,10 @@ static gboolean is_xapian_prefix (const char *q, const char *colon) { const char *cur; - + if (colon == q) return FALSE; /* : at beginning, not a prefix */ - + /* track back from colon until a boundary or beginning of the * str */ for (cur = colon - 1; cur >= q; --cur) { @@ -239,15 +239,15 @@ is_xapian_prefix (const char *q, const char *colon) cpfx.pfx = cur; cpfx.len = (colon - cur); cpfx.match = FALSE; - + mu_msg_field_foreach ((MuMsgFieldForEachFunc) each_check_prefix, &cpfx); - + return (cpfx.match); } } - + return FALSE; } @@ -261,10 +261,10 @@ mu_str_size_parse_bkm (const char* str) if (!isdigit(str[0])) return -1; - + num = atoi(str); for (++str; isdigit(*str); ++str); - + switch (tolower(*str)) { case '\0': case 'b' : return num; /* bytes */ @@ -284,12 +284,12 @@ mu_str_from_list (const GSList *lst, char sepa) char *str; g_return_val_if_fail (sepa, NULL); - + for (cur = lst, str = NULL; cur; cur = g_slist_next(cur)) { char *tmp; /* two extra dummy '\0' so -Wstack-protector won't complain */ - char sep[4] = { '\0', '\0', '\0', '\0' }; + char sep[4] = { '\0', '\0', '\0', '\0' }; sep[0] = cur->next ? sepa : '\0'; tmp = g_strdup_printf ("%s%s%s", @@ -299,7 +299,7 @@ mu_str_from_list (const GSList *lst, char sepa) g_free (str); str = tmp; } - + return str; } @@ -309,10 +309,10 @@ mu_str_to_list (const char *str, char sepa, gboolean strip) GSList *lst; gchar **strs, **cur; /* two extra dummy '\0' so -Wstack-protector won't complain */ - char sep[4] = { '\0', '\0', '\0', '\0' }; - + char sep[4] = { '\0', '\0', '\0', '\0' }; + g_return_val_if_fail (sepa, NULL); - + if (!str) return NULL; @@ -324,10 +324,10 @@ mu_str_to_list (const char *str, char sepa, gboolean strip) elm = g_strdup(*cur); if (strip) elm = g_strstrip (elm); - + lst = g_slist_prepend (lst, elm); } - + lst = g_slist_reverse (lst); g_strfreev (strs); @@ -341,12 +341,12 @@ eat_esc_string (char **strlst) char *str; gboolean quoted; GString *gstr; - + str = g_strchug (*strlst); gstr = g_string_sized_new (strlen(str)); - + for (quoted = FALSE; *str; ++str) { - + if (*str == '"') { quoted = !quoted; continue; @@ -360,7 +360,7 @@ eat_esc_string (char **strlst) } else if (*str == ' ') { ++str; goto leave; - } else + } else g_string_append_c (gstr, *str); } leave: @@ -377,15 +377,17 @@ GSList* mu_str_esc_to_list (const char *strings) { GSList *lst; - char *str, *mystrings, *freeme; - + char *mystrings, *freeme; + const char* cur; + g_return_val_if_fail (strings, NULL); - freeme = mystrings = g_strdup (strings); - mystrings = g_strdup(g_strchug(mystrings)); - lst = NULL; - + for (cur = strings; *cur && (*cur == ' ' || *cur == '\t'); ++cur); + freeme = mystrings = g_strdup (cur); + + lst = NULL; do { + gchar *str; str = eat_esc_string (&mystrings); if (str) lst = g_slist_prepend (lst, str); @@ -402,7 +404,7 @@ void mu_str_free_list (GSList *lst) { g_slist_foreach (lst, (GFunc)g_free, NULL); - g_slist_free (lst); + g_slist_free (lst); } const gchar* @@ -433,14 +435,9 @@ char* mu_str_ascii_xapian_escape_in_place (char *query) { gchar *cur; - gboolean replace_dot; - + g_return_val_if_fail (query, NULL); - /* only replace the '.' if the string looks like an e-mail - * address or msg-id */ - replace_dot = (g_strstr_len(query, -1, "@") != NULL); - for (cur = query; *cur; ++cur) { *cur = tolower(*cur); @@ -451,7 +448,7 @@ mu_str_ascii_xapian_escape_in_place (char *query) *cur = '_'; break; case '.': { /* don't replace a final cur */ - if (cur[1]== ' ' || cur[1]=='\t' || cur[1]== '.') + if (cur[1]== ' ' || cur[1]=='\t' || cur[1]== '.') ++cur; else if (cur[1] == '\0') break; @@ -463,13 +460,13 @@ mu_str_ascii_xapian_escape_in_place (char *query) /* if there's a registered xapian prefix before the * ':', don't touch it. Otherwise replace ':' with * a space'... ugh yuck ugly... - */ + */ if (!is_xapian_prefix (query, cur)) *cur = '_'; break; } } - + return query; } @@ -487,12 +484,12 @@ const char* mu_str_fullpath_s (const char* path, const char* name) { static char buf[PATH_MAX + 1]; - + g_return_val_if_fail (path, NULL); - + snprintf (buf, sizeof(buf), "%s%c%s", path, G_DIR_SEPARATOR, name ? name : ""); - + return buf; } @@ -502,14 +499,14 @@ mu_str_escape_c_literal (const gchar* str, gboolean in_quotes) { const char* cur; GString *tmp; - + g_return_val_if_fail (str, NULL); - + tmp = g_string_sized_new (2 * strlen(str)); if (in_quotes) g_string_append_c (tmp, '"'); - + for (cur = str; *cur; ++cur) switch (*cur) { case '\\': tmp = g_string_append (tmp, "\\\\"); break; @@ -547,10 +544,10 @@ mu_str_convert_to_utf8 (const char* buffer, const char *charset) g_return_val_if_fail (buffer, NULL); g_return_val_if_fail (charset, NULL ); - + err = NULL; utf8 = g_convert_with_fallback (buffer, -1, "UTF-8", - charset, NULL, + charset, NULL, NULL, NULL, &err); if (!utf8) { g_debug ("%s: conversion failed from %s: %s", @@ -558,7 +555,7 @@ mu_str_convert_to_utf8 (const char* buffer, const char *charset) if (err) g_error_free (err); } - + return utf8; } @@ -571,9 +568,9 @@ mu_str_guess_last_name (const char *name) if (!name) return g_strdup (""); - + lastsp = g_strrstr (name, " "); - + return g_strdup (lastsp ? lastsp + 1 : ""); } @@ -585,7 +582,7 @@ mu_str_guess_first_name (const char *name) if (!name) return g_strdup (""); - + lastsp = g_strrstr (name, " "); if (lastsp) @@ -603,9 +600,9 @@ cleanup_str (const char* str) if (mu_str_is_empty(str)) return g_strdup (""); - + s = g_new0 (char, strlen(str) + 1); - + for (cur = str, i = 0; *cur; ++cur) { if (ispunct(*cur) || isspace(*cur)) continue; @@ -622,17 +619,17 @@ mu_str_guess_nick (const char* name) { gchar *fname, *lname, *nick; gchar initial[7]; - + fname = mu_str_guess_first_name (name); lname = mu_str_guess_last_name (name); - + /* if there's no last name, use first name as the nick */ if (mu_str_is_empty(fname) || mu_str_is_empty(lname)) { g_free (lname); nick = fname; goto leave; } - + memset (initial, 0, sizeof(initial)); /* couldn't we get an initial for the last name? */ if (g_unichar_to_utf8 (g_utf8_get_char (lname), initial) == 0) { @@ -644,7 +641,7 @@ mu_str_guess_nick (const char* name) nick = g_strdup_printf ("%s%s", fname, initial); g_free (fname); g_free (lname); - + leave: { gchar *tmp; @@ -652,6 +649,6 @@ leave: g_free (nick); nick = tmp; } - + return nick; } diff --git a/src/mu-threader.c b/src/mu-threader.c index fd29d145..ff2c0a1f 100644 --- a/src/mu-threader.c +++ b/src/mu-threader.c @@ -85,7 +85,7 @@ mu_threader_calculate (MuMsgIter *iter, size_t matchnum, MuMsgFieldId sortfield) NULL, FALSE); /* step 5: group root set by subject */ - //group_root_set_by_subject (root_set); + /* group_root_set_by_subject (root_set); */ /* sort */ mu_msg_iter_reset (iter); /* go all the way back */ diff --git a/src/mu-util.h b/src/mu-util.h index 58275490..2065714c 100644 --- a/src/mu-util.h +++ b/src/mu-util.h @@ -418,9 +418,10 @@ enum _MuError { MU_ERROR_FILE_INVALID_SOURCE = 79, MU_ERROR_FILE_TARGET_EQUALS_SOURCE = 80, MU_ERROR_FILE_CANNOT_WRITE = 81, + MU_ERROR_FILE_CANNOT_UNLINK = 82, /* not really an error, used in callbacks */ - MU_STOP = 99, + MU_STOP = 99 }; typedef enum _MuError MuError;