]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: mail_search_arg_to_imap() - remove () around a single flag/keyword
authorTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 13 Apr 2017 10:57:41 +0000 (13:57 +0300)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Thu, 20 Apr 2017 18:56:17 +0000 (21:56 +0300)
src/lib-storage/mail-search-args-cmdline.c
src/lib-storage/mail-search-args-imap.c
src/lib-storage/test-mail-search-args-imap.c
src/lib-storage/test-mail-search-args-simplify.c

index 003b1dec57342a582adbc919c6344a076180d7c3..a2aef1d736a64b7a5537d4277090bf12c6666b2a 100644 (file)
@@ -46,8 +46,10 @@ mail_search_arg_to_cmdline(string_t *dest, const struct mail_search_arg *arg)
                new_arg.match_not = FALSE;
                if (!mail_search_arg_to_imap(dest, &new_arg, &error))
                        i_unreached();
-               str_insert(dest, pos+1, " ");
-               str_insert(dest, str_len(dest)-1, " ");
+               if (str_c(dest)[pos] == '(') {
+                       str_insert(dest, pos+1, " ");
+                       str_insert(dest, str_len(dest)-1, " ");
+               }
                return;
        }
        case SEARCH_INTHREAD:
index 509c9e3da9a0a58845e92ac8668096914ced2799..c0d6e412084914db71e4d8714f89396e8d1fdfa2 100644 (file)
@@ -51,6 +51,31 @@ mail_search_arg_to_imap_date(string_t *dest, const struct mail_search_arg *arg)
        return TRUE;
 }
 
+static void
+mail_search_arg_to_imap_flags(string_t *dest, enum mail_flags flags)
+{
+       static const char *flag_names[] = {
+               "ANSWERED", "FLAGGED", "DELETED", "SEEN", "DRAFT", "RECENT"
+       };
+       unsigned int count = 0, start_pos = str_len(dest);
+
+       str_append_c(dest, '(');
+       for (unsigned int i = 0; i < N_ELEMENTS(flag_names); i++) {
+               if ((flags & (1 << i)) != 0) {
+                       str_append(dest, flag_names[i]);
+                       str_append_c(dest, ' ');
+                       count++;
+               }
+       }
+       i_assert(count > 0);
+
+       str_truncate(dest, str_len(dest)-1);
+       if (count == 1)
+               str_delete(dest, start_pos, 1);
+       else
+               str_append_c(dest, ')');
+}
+
 bool mail_search_arg_to_imap(string_t *dest, const struct mail_search_arg *arg,
                             const char **error_r)
 {
@@ -81,28 +106,14 @@ bool mail_search_arg_to_imap(string_t *dest, const struct mail_search_arg *arg,
                imap_write_seq_range(dest, &arg->value.seqset);
                break;
        case SEARCH_FLAGS:
-               i_assert((arg->value.flags & MAIL_FLAGS_MASK) != 0);
-               str_append_c(dest, '(');
-               if ((arg->value.flags & MAIL_ANSWERED) != 0)
-                       str_append(dest, "ANSWERED ");
-               if ((arg->value.flags & MAIL_FLAGGED) != 0)
-                       str_append(dest, "FLAGGED ");
-               if ((arg->value.flags & MAIL_DELETED) != 0)
-                       str_append(dest, "DELETED ");
-               if ((arg->value.flags & MAIL_SEEN) != 0)
-                       str_append(dest, "SEEN ");
-               if ((arg->value.flags & MAIL_DRAFT) != 0)
-                       str_append(dest, "DRAFT ");
-               if ((arg->value.flags & MAIL_RECENT) != 0)
-                       str_append(dest, "RECENT ");
-               str_truncate(dest, str_len(dest)-1);
-               str_append_c(dest, ')');
+               mail_search_arg_to_imap_flags(dest, arg->value.flags);
                break;
        case SEARCH_KEYWORDS: {
                const struct mail_keywords *kw = arg->initialized.keywords;
                const ARRAY_TYPE(keywords) *names_arr;
                const char *const *namep;
-               unsigned int i;
+               unsigned int i, count = 0;
+               size_t start_pos = str_len(dest);
 
                if (kw == NULL) {
                        /* uninitialized */
@@ -118,8 +129,12 @@ bool mail_search_arg_to_imap(string_t *dest, const struct mail_search_arg *arg,
                        if (i > 0)
                                str_append_c(dest, ' ');
                        str_printfa(dest, "KEYWORD %s", *namep);
+                       count++;
                }
-               str_append_c(dest, ')');
+               if (count == 1)
+                       str_delete(dest, start_pos, 1);
+               else
+                       str_append_c(dest, ')');
                break;
        }
 
index ac64b5d65aea0bec23703a079a86268933874ac8..3544f3da90f09a212cf7aea8ac3dc9f580f36ebe 100644 (file)
@@ -17,7 +17,7 @@ static struct {
        { "1,5:6,10:15", NULL },
        { "UID 1,5:6,10:15", NULL },
        { "ANSWERED FLAGGED DELETED SEEN DRAFT RECENT",
-         "(ANSWERED) (FLAGGED) (DELETED) (SEEN) (DRAFT) (RECENT)" },
+         "ANSWERED FLAGGED DELETED SEEN DRAFT RECENT" },
        { "KEYWORD foo KEYWORD bar", NULL },
        { "BEFORE 20-May-2015", "BEFORE \"20-May-2015\"" },
        { "ON 20-May-2015", "ON \"20-May-2015\"" },
@@ -54,11 +54,11 @@ static struct {
        { "MODSEQ /flags/\\Seen all 0", NULL },
        { "MODSEQ /flags/\\Seen priv 0", NULL },
        { "MODSEQ /flags/\\Seen shared 0", NULL },
-       { "INTHREAD REFERENCES seen", "INTHREAD REFERENCES ((SEEN))" },
-       { "INTHREAD ORDEREDSUBJECT seen", "INTHREAD ORDEREDSUBJECT ((SEEN))" },
-       { "INTHREAD REFS seen", "INTHREAD REFS ((SEEN))" },
+       { "INTHREAD REFERENCES seen", "INTHREAD REFERENCES (SEEN)" },
+       { "INTHREAD ORDEREDSUBJECT seen", "INTHREAD ORDEREDSUBJECT (SEEN)" },
+       { "INTHREAD REFS seen", "INTHREAD REFS (SEEN)" },
        { "INTHREAD REFS ( OR text foo OR keyword bar seen )",
-         "INTHREAD REFS (((OR TEXT foo OR KEYWORD bar (SEEN))))" },
+         "INTHREAD REFS (((OR TEXT foo OR KEYWORD bar SEEN)))" },
        { "X-GUID foo", NULL },
        { "X-MAILBOX foo", NULL },
        { "X-REAL-UID 1,5:6,10:15", NULL },
index 44f1e21656531f22019bf641b3d172c901ce92c4..02b8091d9135f89efbdfdb1feb9c64fa845a35af 100644 (file)
@@ -39,11 +39,11 @@ struct {
        { "NOT ( TEXT foo TEXT bar )", "(OR NOT TEXT foo NOT TEXT bar)" },
 
        { "ANSWERED FLAGGED SEEN", "(ANSWERED FLAGGED SEEN)" },
-       { "OR ( ANSWERED FLAGGED SEEN ) DRAFT", "(OR (ANSWERED FLAGGED SEEN) (DRAFT))" },
+       { "OR ( ANSWERED FLAGGED SEEN ) DRAFT", "(OR (ANSWERED FLAGGED SEEN) DRAFT)" },
        { "ANSWERED TEXT foo FLAGGED SEEN", "(ANSWERED FLAGGED SEEN) TEXT foo" },
        { "NOT ( ANSWERED FLAGGED SEEN )", "NOT (ANSWERED FLAGGED SEEN)" },
        { "OR NOT ANSWERED OR NOT FLAGGED NOT SEEN", "NOT (ANSWERED FLAGGED SEEN)" },
-       { "ANSWERED NOT FLAGGED SEEN NOT DRAFT", "(ANSWERED SEEN) NOT (FLAGGED) NOT (DRAFT)" },
+       { "ANSWERED NOT FLAGGED SEEN NOT DRAFT", "(ANSWERED SEEN) NOT FLAGGED NOT DRAFT" },
        { "OR NOT ANSWERED NOT SEEN", "NOT (ANSWERED SEEN)" },
 
        { "KEYWORD foo", "KEYWORD foo" },