changeset 21962:65c149bea418

lib-storage: mail_search_arg_to_imap() - remove () around a single flag/keyword
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Thu, 13 Apr 2017 13:57:41 +0300
parents 3ef294f37e92
children a73fb37621df
files 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
diffstat 4 files changed, 44 insertions(+), 27 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/mail-search-args-cmdline.c	Thu Apr 13 13:04:25 2017 +0300
+++ b/src/lib-storage/mail-search-args-cmdline.c	Thu Apr 13 13:57:41 2017 +0300
@@ -46,8 +46,10 @@
 		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:
--- a/src/lib-storage/mail-search-args-imap.c	Thu Apr 13 13:04:25 2017 +0300
+++ b/src/lib-storage/mail-search-args-imap.c	Thu Apr 13 13:57:41 2017 +0300
@@ -51,6 +51,31 @@
 	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 @@
 		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 @@
 			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;
 	}
 
--- a/src/lib-storage/test-mail-search-args-imap.c	Thu Apr 13 13:04:25 2017 +0300
+++ b/src/lib-storage/test-mail-search-args-imap.c	Thu Apr 13 13:57:41 2017 +0300
@@ -17,7 +17,7 @@
 	{ "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 @@
 	{ "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 },
--- a/src/lib-storage/test-mail-search-args-simplify.c	Thu Apr 13 13:04:25 2017 +0300
+++ b/src/lib-storage/test-mail-search-args-simplify.c	Thu Apr 13 13:57:41 2017 +0300
@@ -39,11 +39,11 @@
 	{ "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" },