X-Git-Url: http://git.maemo.org/git/?p=modest;a=blobdiff_plain;f=src%2Fmodest-search.c;h=32f387f49e8e348da8cc7cb8306452e56541932f;hp=726715c170196f5e52b1c8d8ccd3848f4d9a124d;hb=06941d1065d0885758d057108e8f6b317a02d952;hpb=5b0c8c90a92f9f4a0fa01fc8011c97cb21c35f45 diff --git a/src/modest-search.c b/src/modest-search.c index 726715c..32f387f 100644 --- a/src/modest-search.c +++ b/src/modest-search.c @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include @@ -50,8 +52,10 @@ #include "modest-account-mgr.h" #include "modest-tny-account-store.h" #include "modest-tny-account.h" +#include "modest-tny-folder.h" #include "modest-search.h" #include "modest-runtime.h" +#include "modest-platform.h" static gchar * g_strdup_or_null (const gchar *str) @@ -79,6 +83,7 @@ add_hit (GList *list, TnyHeader *header, TnyFolder *folder) hit = g_slice_new0 (ModestSearchHit); furl = tny_folder_get_url_string (folder); + printf ("DEBUG: %s: folder URL=%s\n", __FUNCTION__, furl); if (!furl) { g_warning ("%s: tny_folder_get_url_string(): returned NULL for folder. Folder name=%s\n", __FUNCTION__, tny_folder_get_name (folder)); } @@ -93,77 +98,100 @@ add_hit (GList *list, TnyHeader *header, TnyFolder *folder) } msg_url = g_strdup_printf ("%s/%s", furl, uid); + g_free (furl); subject = tny_header_get_subject (header); sender = tny_header_get_from (header); - + flags = tny_header_get_flags (header); hit->msgid = msg_url; hit->subject = g_strdup_or_null (subject); hit->sender = g_strdup_or_null (sender); - hit->folder = furl; /* We just provide our new instance instead of copying it and freeing it. */ + hit->folder = g_strdup_or_null (tny_folder_get_name (folder)); hit->msize = tny_header_get_message_size (header); hit->has_attachment = flags & TNY_HEADER_FLAG_ATTACHMENTS; hit->is_unread = ! (flags & TNY_HEADER_FLAG_SEEN); - hit->timestamp = tny_header_get_date_received (header); + hit->timestamp = MIN (tny_header_get_date_received (header), tny_header_get_date_sent (header)); return g_list_prepend (list, hit); } +/** Call this until it returns FALSE or nread is set to 0. + * + * @result: FALSE is something failed. */ static gboolean read_chunk (TnyStream *stream, char *buffer, gsize count, gsize *nread) { - gsize _nread; - gssize res; + gsize _nread = 0; + gssize res = 0; - _nread = 0; while (_nread < count) { res = tny_stream_read (stream, buffer + _nread, count - _nread); - if (res == -1) { + if (res == -1) { /* error */ *nread = _nread; return FALSE; } - if (res == 0) - break; - _nread += res; + + if (res == 0) { /* no more bytes read. */ + *nread = _nread; + return TRUE; + } } *nread = _nread; return TRUE; - - } #ifdef MODEST_HAVE_OGS static gboolean search_mime_part_ogs (TnyMimePart *part, ModestSearch *search) { - TnyStream *stream; + TnyStream *stream = NULL; char buffer[4096]; - gsize len; - gsize nread; - gboolean is_html = FALSE; - gboolean found; - gboolean res; - - - if (! tny_mime_part_content_type_is (part, "text/ *") || - ! (is_html = tny_mime_part_content_type_is (part, "text/html"))) { - return FALSE; + const gsize len = sizeof (buffer); + gsize nread = 0; + gboolean is_text_html = FALSE; + gboolean found = FALSE; + gboolean res = FALSE; + + gboolean is_text = tny_mime_part_content_type_is (part, "text/*"); + if (!is_text) { + g_debug ("%s: tny_mime_part_content_type_is() failed to find a " + "text/* MIME part. Content type is %s", + __FUNCTION__, "Unknown (calling tny_mime_part_get_content_type(part) causes a deadlock)"); + + /* Retry with specific MIME types, because the wildcard seems to fail + * in tinymail. + * Actually I'm not sure anymore that it fails, so we could probalby + * remove this later: murrayc */ + is_text = ( + tny_mime_part_content_type_is (part, "text/plain") || + tny_mime_part_content_type_is (part, "text/html") ); + + if (is_text) { + g_debug ("%s: Retryting with text/plain or text/html succeeded", + __FUNCTION__); + } + } + + if (!is_text) { + return FALSE; } + + is_text_html = tny_mime_part_content_type_is (part, "text/html"); - found = FALSE; - len = sizeof (buffer); stream = tny_mime_part_get_stream (part); - while ((res = read_chunk (stream, buffer, len, &nread))) { - - if (is_html) { + res = read_chunk (stream, buffer, len, &nread); + while (res && (nread > 0)) { + /* search->text_searcher was instantiated in modest_search_folder(). */ + + if (is_text_html) { found = ogs_text_searcher_search_html (search->text_searcher, buffer, @@ -178,7 +206,9 @@ search_mime_part_ogs (TnyMimePart *part, ModestSearch *search) if (found) { break; } - + + nread = 0; + res = read_chunk (stream, buffer, len, &nread); } if (!found) { @@ -186,10 +216,22 @@ search_mime_part_ogs (TnyMimePart *part, ModestSearch *search) } ogs_text_searcher_reset (search->text_searcher); + + /* debug stuff: + if (!found) { + buffer[len -1] = 0; + printf ("DEBUG: %s: query %s was not found in message text: %s\n", + __FUNCTION__, search->query, buffer); + + } else { + printf ("DEBUG: %s: found.\n", __FUNCTION__); + } + */ return found; } -#endif /*MODEST_HAVE_OGS*/ + +#else static gboolean search_mime_part_strcmp (TnyMimePart *part, ModestSearch *search) @@ -202,7 +244,8 @@ search_mime_part_strcmp (TnyMimePart *part, ModestSearch *search) gboolean found; gboolean res; - if (! tny_mime_part_content_type_is (part, "text/ *")) { + if (! tny_mime_part_content_type_is (part, "text/*")) { + g_debug ("%s: No text MIME part found.\n", __FUNCTION__); return FALSE; } @@ -255,7 +298,7 @@ search_mime_part_strcmp (TnyMimePart *part, ModestSearch *search) buffer, TRUE); - if (found) { + if ((found)||(nread == 0)) { break; } @@ -267,6 +310,7 @@ done: g_object_unref (stream); return found; } +#endif /*MODEST_HAVE_OGS*/ static gboolean search_string (const char *what, @@ -295,25 +339,70 @@ search_string (const char *what, } +static gboolean search_mime_part_and_child_parts (TnyMimePart *part, ModestSearch *search) +{ + gboolean found = FALSE; + #ifdef MODEST_HAVE_OGS + found = search_mime_part_ogs (part, search); + #else + found = search_mime_part_strcmp (part, search); + #endif + + if (found) { + return found; + } + + /* Check the child part too, recursively: */ + TnyList *child_parts = tny_simple_list_new (); + tny_mime_part_get_parts (TNY_MIME_PART (part), child_parts); + + TnyIterator *piter = tny_list_create_iterator (child_parts); + while (!found && !tny_iterator_is_done (piter)) { + TnyMimePart *pcur = (TnyMimePart *) tny_iterator_get_current (piter); + if (pcur) { + found = search_mime_part_and_child_parts (pcur, search); + + g_object_unref (pcur); + } + + tny_iterator_next (piter); + } + + g_object_unref (piter); + g_object_unref (child_parts); + + return found; +} /** * modest_search: * @folder: a #TnyFolder instance * @search: a #ModestSearch query * - * This operation will search @folder for headers that match the query @search. + * This operation will search @folder for headers that match the query @search, + * if the folder itself matches the query. * It will return a doubly linked list with URIs that point to the message. **/ GList * modest_search_folder (TnyFolder *folder, ModestSearch *search) { + /* Check that we should be searching this folder. */ + /* Note that we don't try to search sub-folders. + * Maybe we should, but that should be specified. */ + if (search->folder && strlen (search->folder)) { + if (!strcmp (search->folder, "outbox")) { + if (modest_tny_folder_guess_folder_type (folder) != TNY_FOLDER_TYPE_OUTBOX) { + return NULL; + } + } else if (strcmp (tny_folder_get_id (folder), search->folder) != 0) { + return NULL; + } + } + GList *retval = NULL; - TnyIterator *iter; - TnyList *list; - gboolean (*part_search_func) (TnyMimePart *part, ModestSearch *search); - - part_search_func = search_mime_part_strcmp; - + TnyIterator *iter = NULL; + TnyList *list = NULL; + #ifdef MODEST_HAVE_OGS if (search->flags & MODEST_SEARCH_USE_OGS) { @@ -324,27 +413,36 @@ modest_search_folder (TnyFolder *folder, ModestSearch *search) ogs_text_searcher_parse_query (text_searcher, search->query); search->text_searcher = text_searcher; } - - part_search_func = search_mime_part_ogs; } #endif list = tny_simple_list_new (); - tny_folder_get_headers (folder, list, FALSE, NULL); + GError *error = NULL; + tny_folder_get_headers (folder, list, FALSE /* don't refresh */, &error); + if (error) { + g_warning ("%s: tny_folder_get_headers() failed with error=%s.\n", + __FUNCTION__, error->message); + g_error_free (error); + error = NULL; + } iter = tny_list_create_iterator (list); while (!tny_iterator_is_done (iter)) { TnyHeader *cur = (TnyHeader *) tny_iterator_get_current (iter); - time_t t = tny_header_get_date_sent (cur); + const time_t t = tny_header_get_date_sent (cur); gboolean found = FALSE; + /* Ignore deleted (not yet expunged) emails: */ + if (tny_header_get_flags(cur) & TNY_HEADER_FLAG_DELETED) + goto go_next; + if (search->flags & MODEST_SEARCH_BEFORE) - if (!(t <= search->before)) + if (!(t <= search->end_date)) goto go_next; if (search->flags & MODEST_SEARCH_AFTER) - if (!(t >= search->after)) + if (!(t >= search->start_date)) goto go_next; if (search->flags & MODEST_SEARCH_SIZE) @@ -380,8 +478,6 @@ modest_search_folder (TnyFolder *folder, ModestSearch *search) TnyHeaderFlags flags; GError *err = NULL; TnyMsg *msg = NULL; - TnyIterator *piter; - TnyList *parts; flags = tny_header_get_flags (cur); @@ -398,27 +494,17 @@ modest_search_folder (TnyFolder *folder, ModestSearch *search) if (msg) { g_object_unref (msg); } - } - - parts = tny_simple_list_new (); - tny_mime_part_get_parts (TNY_MIME_PART (msg), parts); - - piter = tny_list_create_iterator (parts); - while (!found && !tny_iterator_is_done (piter)) { - TnyMimePart *pcur = (TnyMimePart *) tny_iterator_get_current (piter); - - if ((found = part_search_func (pcur, search))) { - retval = add_hit (retval, cur, folder); + } else { + + found = search_mime_part_and_child_parts (TNY_MIME_PART (msg), + search); + if (found) { + retval = add_hit (retval, cur, folder); } - - g_object_unref (pcur); - tny_iterator_next (piter); } - - g_object_unref (piter); - g_object_unref (parts); - g_object_unref (msg); - + + if (msg) + g_object_unref (msg); } go_next: @@ -455,34 +541,41 @@ modest_search_account (TnyAccount *account, ModestSearch *search) iter = tny_list_create_iterator (folders); while (!tny_iterator_is_done (iter)) { - TnyFolder *folder; - GList *res; + TnyFolder *folder = NULL; + GList *res = NULL; folder = TNY_FOLDER (tny_iterator_get_current (iter)); + if (folder) { + /* g_debug ("DEBUG: %s: searching folder %s.", + __FUNCTION__, tny_folder_get_name (folder)); */ - res = modest_search_folder (folder, search); + res = modest_search_folder (folder, search); - if (res != NULL) { - if (hits == NULL) { - hits = res; - } else { - hits = g_list_concat (hits, res); + if (res != NULL) { + if (hits == NULL) { + hits = res; + } else { + hits = g_list_concat (hits, res); + } } + + g_object_unref (folder); } - g_object_unref (folder); tny_iterator_next (iter); } g_object_unref (iter); g_object_unref (folders); + /* printf ("DEBUG: %s: hits length = %d\n", __FUNCTION__, g_list_length (hits)); */ return hits; } GList * modest_search_all_accounts (ModestSearch *search) { + /* printf ("DEBUG: %s: query=%s\n", __FUNCTION__, search->query); */ ModestTnyAccountStore *astore; TnyList *accounts; TnyIterator *iter; @@ -498,31 +591,40 @@ modest_search_all_accounts (ModestSearch *search) iter = tny_list_create_iterator (accounts); while (!tny_iterator_is_done (iter)) { - TnyAccount *account; - GList *res; + TnyAccount *account = NULL; + GList *res = NULL; account = TNY_ACCOUNT (tny_iterator_get_current (iter)); - - g_debug ("DEBUG: %s: Searching account %s", - __FUNCTION__, tny_account_get_name (account)); - res = modest_search_account (account, search); - - if (res != NULL) { - - if (hits == NULL) { - hits = res; - } else { - hits = g_list_concat (hits, res); + if (account) { + /* g_debug ("DEBUG: %s: Searching account %s", + __FUNCTION__, tny_account_get_name (account)); */ + + /* Give the account time to go online if necessary, + * for instance if this is immediately after startup, + * after D-Bus activation: */ + modest_platform_check_and_wait_for_account_is_online (account); + + /* Search: */ + res = modest_search_account (account, search); + + if (res != NULL) { + if (hits == NULL) { + hits = res; + } else { + hits = g_list_concat (hits, res); + } } + + g_object_unref (account); } - g_object_unref (account); tny_iterator_next (iter); } g_object_unref (accounts); g_object_unref (iter); + /* printf ("DEBUG: %s: end: hits length=%d\n", __FUNCTION__, g_list_length(hits)); */ return hits; }