mail-search.c revision 78f8407de32c9a51f2db00f4edb466f4279fa456
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenmailbox_uidset_change(struct mail_search_arg *arg, struct mailbox *box,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const ARRAY_TYPE(seq_range) *search_saved_uidset)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen unsigned int i, count;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen if (arg->value.str != NULL && strcmp(arg->value.str, "$") == 0) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* SEARCHRES: Replace with saved uidset */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_append_array(&arg->value.seqset, search_saved_uidset);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* make a copy of the UIDs */
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* empty set, keep it */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen memcpy(uids, array_idx(&arg->value.seqset, 0), sizeof(*uids) * count);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* put them back to the range as sequences */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen for (i = 0; i < count; i++) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mailbox_get_seq_range(box, uids[i].seq1, uids[i].seq2,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* make sure the last message is in the range */
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen seq_range_array_add(&arg->value.seqset, seq2);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_search_arg_init(struct mail_search_args *args,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const ARRAY_TYPE(seq_range) *search_saved_uidset)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* modseq with keyword */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* simplification should have unnested all
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen inthreads, so we'll assume that
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen have_inthreads=FALSE */
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen /* fall through */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen mail_search_arg_init(args, arg->value.subargs,
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainenvoid mail_search_args_init(struct mail_search_args *args,
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen const ARRAY_TYPE(seq_range) *search_saved_uidset)
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen i_assert(args->init_refcount <= args->refcount);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_search_arg_init(args, args->args, change_uidsets,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_search_arg_deinit(struct mail_search_arg *arg)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_keywords_unref(&arg->initialized.keywords);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen imap_match_deinit(&arg->initialized.mailbox_glob);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen i_assert(arg->initialized.search_args->refcount > 0);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen /* fall through */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvoid mail_search_args_deinit(struct mail_search_args *args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void mail_search_args_seq2uid_sub(struct mail_search_args *args,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* replace sequences with UIDs in the existing array.
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen this way it's possible to switch between uidsets and
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen seqsets constantly without leaking memory */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_search_args_seq2uid_sub(args, arg->value.subargs,
f210ec6b25f80d06419921e9231465bb114ee971Timo Sirainenvoid mail_search_args_seq2uid(struct mail_search_args *args)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen mail_search_args_seq2uid_sub(args, args->args, &uids);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainenvoid mail_search_args_ref(struct mail_search_args *args)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainenvoid mail_search_args_unref(struct mail_search_args **_args)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_assert(args->init_refcount <= args->refcount);
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainenmail_search_arg_dup_one(pool_t pool, const struct mail_search_arg *arg)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen new_arg = p_new(pool, struct mail_search_arg, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen new_arg->nonmatch_always = arg->nonmatch_always;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen new_arg->value.search_flags = arg->value.search_flags;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen new_arg->value.thread_type = arg->value.thread_type;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* fall through */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_search_arg_dup(pool, arg->value.subargs);
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen array_append_array(&new_arg->value.seqset, &arg->value.seqset);
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen new_arg->value.date_type = arg->value.date_type;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen new_arg->hdr_field_name = p_strdup(pool, arg->hdr_field_name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* fall through */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen new_arg->value.str = p_strdup(pool, arg->value.str);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenmail_search_arg_dup(pool_t pool, const struct mail_search_arg *arg)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct mail_search_arg *new_arg = NULL, **dest = &new_arg;
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainenmail_search_args_dup(const struct mail_search_args *args)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen new_args->have_inthreads = args->have_inthreads;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen new_args->args = mail_search_arg_dup(new_args->pool, args->args);
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainenvoid mail_search_args_reset(struct mail_search_arg *args, bool full_reset)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen if (args->type == SEARCH_OR || args->type == SEARCH_SUB)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen mail_search_args_reset(args->value.subargs, full_reset);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic void search_arg_foreach(struct mail_search_arg *arg,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* sublist of conditions */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen search_arg_foreach(subarg, callback, context);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* didn't match */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* OR-list of conditions */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen search_arg_foreach(subarg, callback, context);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* matched */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* just a single condition */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenint mail_search_args_foreach(struct mail_search_arg *args,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* didn't match */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainensearch_arg_analyze(struct mail_search_arg *arg, buffer_t *headers,
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen if (arg->value.date_type == MAIL_SEARCH_DATE_TYPE_SENT)
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen buffer_append(headers, &date_hdr, sizeof(const char *));
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen sizeof(const char *));
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenconst char *const *
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainenmail_search_args_analyze(struct mail_search_arg *args,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *have_headers = *have_body = have_text = FALSE;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen headers = buffer_create_dynamic(pool_datastack_create(), 128);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen search_arg_analyze(args, headers, have_body, &have_text);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *have_headers = have_text || headers->used != 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen buffer_append(headers, &null, sizeof(const char *));
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenmail_search_args_match_mailbox_arg(const struct mail_search_arg *arg,
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen for (; subarg != NULL; subarg = subarg->next) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (mail_search_args_match_mailbox_arg(subarg,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen for (; subarg != NULL; subarg = subarg->next) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!mail_search_args_match_mailbox_arg(subarg,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen glob = imap_match_init(pool_datastack_create(),
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ret = imap_match(glob, vname) == IMAP_MATCH_YES;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool mail_search_args_match_mailbox(struct mail_search_args *args,
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen for (arg = args->args; arg != NULL; arg = arg->next) {
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen if (!mail_search_args_match_mailbox_arg(arg, vname, sep))
20eafc2a848865ce7bf5e8c609e3b0bbd9077ec2Timo Sirainenbool mail_search_arg_one_equals(const struct mail_search_arg *arg1,
20eafc2a848865ce7bf5e8c609e3b0bbd9077ec2Timo Sirainen arg1->value.search_flags != arg2->value.search_flags)
ceae1acc3e3022c6b5fe52a4a34890dffdbcb77fTimo Sirainen return mail_search_arg_equals(arg1->value.subargs,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen /* sequences may point to different messages at different times,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen never assume they match */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen return array_cmp(&arg1->value.seqset, &arg2->value.seqset);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return array_cmp(&arg1->value.seqset, &arg2->value.seqset);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen return arg1->value.flags == arg2->value.flags;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen return strcasecmp(arg1->value.str, arg2->value.str);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen return arg1->value.time == arg2->value.time &&
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen arg1->value.date_type == arg2->value.date_type;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (strcasecmp(arg1->hdr_field_name, arg2->hdr_field_name) != 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* fall through */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* don't bother doing case-insensitive comparison. it must not
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen be done for guid/mailbox, and for others we should support
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen full i18n case-insensitivity (or the active comparator
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen in future). */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return strcmp(arg1->value.str, arg2->value.str) == 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mail_search_modseq *m1 = arg1->value.modseq;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const struct mail_search_modseq *m2 = arg2->value.modseq;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (arg1->value.thread_type != arg2->value.thread_type)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return mail_search_args_equal(arg1->initialized.search_args,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool mail_search_arg_equals(const struct mail_search_arg *arg1,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenbool mail_search_args_equal(const struct mail_search_args *args1,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_assert(args1->simplified == args2->simplified);
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainen return mail_search_arg_equals(args1->args, args2->args);
e726bf74fcc8d24f4c9d0d83217b3db4314d9d1fTimo Sirainenmail_search_args_result_serialize_arg(const struct mail_search_arg *arg,
d3380f13cb3e398bb5e7acbd4d04582397f62ec2Timo Sirainen buffer_append_c(dest, arg->result < 0 ? 0xff : arg->result);
case SEARCH_OR:
case SEARCH_SUB:
case SEARCH_INTHREAD:
const unsigned char **data,
case SEARCH_OR:
case SEARCH_SUB:
case SEARCH_INTHREAD: