mail-search.c revision 38537f71055adbbf214ba2a682f13d5947957298
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool mail_search_arg_equals(const struct mail_search_arg *arg1,
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainenmailbox_uidset_change(struct mail_search_arg *arg, struct mailbox *box,
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainen const ARRAY_TYPE(seq_range) *search_saved_uidset)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen unsigned int i, count;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (arg->value.str != NULL && strcmp(arg->value.str, "$") == 0) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* SEARCHRES: Replace with saved uidset */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen array_append_array(&arg->value.seqset, search_saved_uidset);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* make a copy of the UIDs */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* empty set, keep it */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen memcpy(uids, array_idx(&arg->value.seqset, 0), sizeof(*uids) * count);
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen /* put them back to the range as sequences */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (i = 0; i < count; i++) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mailbox_get_seq_range(box, uids[i].seq1, uids[i].seq2,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen /* make sure the last message is in the range */
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen seq_range_array_add(&arg->value.seqset, 0, seq2);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenmail_search_args_init_sub(struct mail_search_args *args,
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen const ARRAY_TYPE(seq_range) *search_saved_uidset)
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen /* modseq with keyword */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* simplification should have unnested all
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen inthreads, so we'll assume that
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen have_inthreads=FALSE */
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen /* fall through */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen mail_search_args_init_sub(args, arg->value.subargs,
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainenvoid mail_search_args_init(struct mail_search_args *args,
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen const ARRAY_TYPE(seq_range) *search_saved_uidset)
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen mail_search_args_init_sub(args, args->args, change_uidsets,
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenstatic void mail_search_args_deinit_sub(struct mail_search_args *args,
4b41116563110d00330896a568eff1078c382827Timo Sirainen mailbox_keywords_free(args->box, &arg->value.keywords);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen i_assert(arg->value.search_args->refcount > 0);
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainen /* fall through */
8a13b020f90e080570658b18c042e7e352c8b14fTimo Sirainen mail_search_args_deinit_sub(args, arg->value.subargs);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenvoid mail_search_args_deinit(struct mail_search_args *args)
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen mail_search_args_deinit_sub(args, args->args);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainenstatic void mail_search_args_seq2uid_sub(struct mail_search_args *args,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* replace sequences with UIDs in the existing array.
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen this way it's possible to switch between uidsets and
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen seqsets constantly without leaking memory */
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen mail_search_args_seq2uid_sub(args, arg->value.subargs,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenvoid mail_search_args_seq2uid(struct mail_search_args *args)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen mail_search_args_seq2uid_sub(args, args->args, &uids);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainenvoid mail_search_args_ref(struct mail_search_args *args)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainenvoid mail_search_args_unref(struct mail_search_args **_args)
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen i_assert(args->init_refcount <= args->refcount);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenvoid mail_search_args_reset(struct mail_search_arg *args, bool full_reset)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen if (args->type == SEARCH_OR || args->type == SEARCH_SUB)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen mail_search_args_reset(args->value.subargs, full_reset);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic void search_arg_foreach(struct mail_search_arg *arg,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen /* sublist of conditions */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen search_arg_foreach(subarg, callback, context);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen /* didn't match */
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen /* OR-list of conditions */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen search_arg_foreach(subarg, callback, context);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* matched */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* just a single condition */
310767ca33e7636d40ec45dee68a2c319a5fa3c0Timo Sirainenint mail_search_args_foreach(struct mail_search_arg *args,
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainen /* didn't match */
b0a901f1dbe9e05ac1c92a0974af6bce0274f31aTimo Sirainensearch_arg_analyze(struct mail_search_arg *arg, buffer_t *headers,
cd83124e5d070a016c590bb0b1096d7828c7b6adTimo Sirainen buffer_append(headers, &date_hdr, sizeof(const char *));
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen sizeof(const char *));
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenconst char *const *
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainenmail_search_args_analyze(struct mail_search_arg *args,
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen *have_headers = *have_body = have_text = FALSE;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen headers = buffer_create_dynamic(pool_datastack_create(), 128);
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen search_arg_analyze(args, headers, have_body, &have_text);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *have_headers = have_text || headers->used != 0;
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen buffer_append(headers, &null, sizeof(const char *));
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainenmail_search_keywords_merge(struct mail_keywords **_kw1,
0cce885512b836ce021260a58e7b4f099b36d0f1Timo Sirainen struct mail_keywords *kw1 = *_kw1, *kw2 = *_kw2;
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen unsigned int i, j;
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen t_array_init(&new_indexes, kw1->count + kw2->count + 1);
b62140c5849297a800fee942026d9c3cb8c60206Timo Sirainen array_append(&new_indexes, kw1->idx, kw1->count);
4d527c363482be2b65dd0573d878ecda86cbb0bbTimo Sirainen /* don't add duplicates */
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen new_kw = mail_index_keywords_create_from_indexes(kw1->index,
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainenmail_search_args_simplify_sub(struct mail_search_arg *args, bool parent_and)
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct mail_search_arg *prev_flags_arg, *prev_not_flags_arg;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen struct mail_search_arg *prev_kw_arg, *prev_not_kw_arg;
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen /* neg(p and q and ..) == neg(p) or neg(q) or ..
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen neg(p or q or ..) == neg(p) and neg(q) and .. */
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen if ((args->type == SEARCH_SUB && parent_and) ||
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen ((args->type == SEARCH_SUB || args->type == SEARCH_OR) &&
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* p and (q and ..) == p and q and ..
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen p or (q or ..) == p or q or ..
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen mail_search_args_simplify_sub(args->value.subargs,
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen /* merge all flags arguments */
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen if (args->type == SEARCH_FLAGS && !args->not && parent_and) {
!parent_and) {
!parent_and) {
case SEARCH_SUB:
case SEARCH_OR:
case SEARCH_INTHREAD:
return FALSE;
if (!parent_and) {
return TRUE;
return FALSE;
case SEARCH_OR:
case SEARCH_SUB:
case SEARCH_ALL:
return TRUE;
case SEARCH_SEQSET:
return FALSE;
case SEARCH_UIDSET:
case SEARCH_FLAGS:
case SEARCH_KEYWORDS:
case SEARCH_BEFORE:
case SEARCH_ON:
case SEARCH_SINCE:
case SEARCH_SENTBEFORE:
case SEARCH_SENTON:
case SEARCH_SENTSINCE:
case SEARCH_SMALLER:
case SEARCH_LARGER:
case SEARCH_HEADER:
case SEARCH_HEADER_ADDRESS:
return FALSE;
case SEARCH_BODY:
case SEARCH_TEXT:
case SEARCH_BODY_FAST:
case SEARCH_TEXT_FAST:
case SEARCH_GUID:
case SEARCH_MAILBOX:
case SEARCH_MODSEQ: {
case SEARCH_INTHREAD:
i_unreached();
return FALSE;
return FALSE;
return FALSE;