Fix bug #1797 “quicksearch could also search the Cc field”
[claws.git] / src / advsearch.c
index 5e7161429eaebd8eca57e7a9f918766ba32bc730..962e9f67f2c996a6ad48a754209e6ec711afe537 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 2012 the Claws Mail team
+ * Copyright (C) 2012-2014 the Claws Mail team
  *
  * 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
@@ -150,6 +150,8 @@ gchar *advsearch_expand_search_string(const gchar *search_string)
                { "a",  "all",                          0,      FALSE,  FALSE },
                { "ag", "age_greater",                  1,      FALSE,  FALSE },
                { "al", "age_lower",                    1,      FALSE,  FALSE },
+               { "agh","age_greater_hours",            1,      FALSE,  FALSE },
+               { "alh","age_lower_hours",              1,      FALSE,  FALSE },
                { "b",  "body_part",                    1,      TRUE,   TRUE  },
                { "B",  "message",                      1,      TRUE,   TRUE  },
                { "c",  "cc",                           1,      TRUE,   TRUE  },
@@ -160,6 +162,7 @@ gchar *advsearch_expand_search_string(const gchar *search_string)
                { "f",  "from",                         1,      TRUE,   TRUE  },
                { "F",  "forwarded",                    0,      FALSE,  FALSE },
                { "h",  "headers_part",                 1,      TRUE,   TRUE  },
+               { "H",  "headers_cont",                 1,      TRUE,   TRUE  },
                { "ha", "has_attachments",              0,      FALSE,  FALSE },
                { "i",  "header \"Message-ID\"",        1,      TRUE,   TRUE  },
                { "I",  "inreplyto",                    1,      TRUE,   TRUE  },
@@ -314,32 +317,6 @@ gchar *advsearch_expand_search_string(const gchar *search_string)
        return returnstr;
 }
 
-// --------------------------
-
-static gchar *expand_tag_search_string(const gchar *search_string)
-{
-       gchar *newstr = NULL;
-       gchar **words = search_string ? g_strsplit(search_string, " ", -1):NULL;
-       gint i = 0;
-       while (words && words[i] && *words[i]) {
-               g_strstrip(words[i]);
-               if (!newstr) {
-                       newstr = g_strdup_printf("tag matchcase \"%s\"", words[i]);
-               } else {
-                       gint o_len = strlen(newstr);
-                       gint s_len = 17; /* strlen("|tag matchcase \"\"") */
-                       gint n_len = s_len + strlen(words[i]);
-                       newstr = g_realloc(newstr, o_len + n_len + 1);
-                       strcpy(newstr + o_len, "|tag matchcase \"");
-                       strcpy(newstr + o_len + (s_len - 1), words[i]);
-                       strcpy(newstr + o_len + (n_len - 1), "\"");
-               }
-               i++;
-       }
-       g_strfreev(words);
-       return newstr;
-}
-
 static void prepare_matcher_extended(AdvancedSearch *search)
 {
        gchar *newstr = advsearch_expand_search_string(search->request.matchstring);
@@ -350,19 +327,52 @@ static void prepare_matcher_extended(AdvancedSearch *search)
        }
 }
 
+#define debug_matcher_list(prefix, list)                                       \
+do {                                                                           \
+       gchar *str = list ? matcherlist_to_string(list) : g_strdup("(NULL)");   \
+                                                                               \
+       debug_print("%s: %s\n", prefix, str);                                   \
+                                                                               \
+       g_free(str);                                                            \
+} while(0)
+
 static void prepare_matcher_tag(AdvancedSearch *search)
 {
-       char *newstr = expand_tag_search_string(search->request.matchstring);
-       search->predicate = matcher_parser_get_cond(newstr, &search->is_fast);
-       g_free(newstr);
+       gchar **words = search->request.matchstring 
+                       ? g_strsplit(search->request.matchstring, " ", -1)
+                       : NULL;
+       gint i = 0;
+
+       if (search->predicate == NULL) {
+               search->predicate = g_new0(MatcherList, 1);
+               search->predicate->bool_and = FALSE;
+               search->is_fast = TRUE;
+       }
+
+       while (words && words[i] && *words[i]) {
+               MatcherProp *matcher;
+
+               g_strstrip(words[i]);
+
+               matcher = matcherprop_new(MATCHCRITERIA_TAG, NULL,
+                                         MATCHTYPE_MATCHCASE, words[i], 0);
+
+               search->predicate->matchers = g_slist_prepend(search->predicate->matchers, matcher);
+
+               i++;
+       }
+       g_strfreev(words);
 }
 
 static void prepare_matcher_header(AdvancedSearch *search, gint match_header)
 {
        MatcherProp *matcher;
 
-       if (search->predicate == NULL)
+       if (search->predicate == NULL) {
                search->predicate = g_new0(MatcherList, 1);
+               search->predicate->bool_and = FALSE;
+               search->is_fast = TRUE;
+       }
 
        matcher = matcherprop_new(match_header, NULL, MATCHTYPE_MATCHCASE,
                        search->request.matchstring, 0);
@@ -373,10 +383,20 @@ static void prepare_matcher_header(AdvancedSearch *search, gint match_header)
 static void prepare_matcher_mixed(AdvancedSearch *search)
 {
        prepare_matcher_tag(search);
+       debug_matcher_list("tag matcher list", search->predicate);
+
+       /* we want an OR search */
+       if (search->predicate)
+               search->predicate->bool_and = FALSE;
 
        prepare_matcher_header(search, MATCHCRITERIA_SUBJECT);
+       debug_matcher_list("tag + subject matcher list", search->predicate);
        prepare_matcher_header(search, MATCHCRITERIA_FROM);
+       debug_matcher_list("tag + subject + from matcher list", search->predicate);
        prepare_matcher_header(search, MATCHCRITERIA_TO);
+       debug_matcher_list("tag + subject + from + to matcher list", search->predicate);
+       prepare_matcher_header(search, MATCHCRITERIA_CC);
+       debug_matcher_list("tag + subject + from + to + cc matcher list", search->predicate);
 }
 
 static void prepare_matcher(AdvancedSearch *search)
@@ -398,26 +418,32 @@ static void prepare_matcher(AdvancedSearch *search)
        switch (search->request.type) {
                case ADVANCED_SEARCH_SUBJECT:
                        prepare_matcher_header(search, MATCHCRITERIA_SUBJECT);
+                       debug_matcher_list("subject search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_FROM:
                        prepare_matcher_header(search, MATCHCRITERIA_FROM);
+                       debug_matcher_list("from search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_TO:
                        prepare_matcher_header(search, MATCHCRITERIA_TO);
+                       debug_matcher_list("to search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_TAG:
-                       prepare_matcher_header(search, MATCHCRITERIA_TAG);
+                       prepare_matcher_tag(search);
+                       debug_matcher_list("tag search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_MIXED:
                        prepare_matcher_mixed(search);
+                       debug_matcher_list("mixed search", search->predicate);
                        break;
 
                case ADVANCED_SEARCH_EXTENDED:
                        prepare_matcher_extended(search);
+                       debug_matcher_list("extended search", search->predicate);
                        break;
 
                default:
@@ -487,9 +513,7 @@ static gboolean search_impl(MsgInfoList **messages, AdvancedSearch* search,
                MsgNumberList *msgnums = NULL;
                MsgNumberList *cur;
                MsgInfoList *msgs = NULL;
-               gboolean can_search_on_server = 
-                               folderItem->folder->klass->supports_server_search 
-                               && !prefs_common.work_offline;
+               gboolean can_search_on_server = folderItem->folder->klass->supports_server_search;
 
                if (!search_filter_folder(&msgnums, search, folderItem,
                                          can_search_on_server)) {