mail-search-args-simplify.c revision c89ceadf661bde22e1cd9dc2eac09c19202e65ec
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "lib.h"
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen#include "hash.h"
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen#include "mail-search.h"
a020eb653b2620a989e4795adceb6136037327b2Timo Sirainen
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainenstruct mail_search_simplify_prev_arg {
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen struct {
57f5683fd9dc9bc79816c418bb30fdbc33b68a8cTimo Sirainen enum mail_search_arg_type type;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen enum mail_search_arg_flag search_flags;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen enum mail_search_date_type date_type;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen bool match_not;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen bool fuzzy;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } bin_mask;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen const char *hdr_field_name_mask;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen const char *str_mask;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct mail_search_arg *prev_arg;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen};
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstruct mail_search_simplify_ctx {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen pool_t pool;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen /* arg mask => prev_arg */
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen HASH_TABLE(struct mail_search_simplify_prev_arg *,
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen struct mail_search_simplify_prev_arg *) prev_args;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen bool parent_and;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen bool removals;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen};
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainenstatic int
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainenmail_search_simplify_prev_arg_cmp(const struct mail_search_simplify_prev_arg *arg1,
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen const struct mail_search_simplify_prev_arg *arg2)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen{
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen int ret;
c4478af52de63804efef2055580adf1dfc8679c6Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ret = memcmp(&arg1->bin_mask, &arg2->bin_mask, sizeof(arg1->bin_mask));
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (ret == 0)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen ret = null_strcmp(arg1->hdr_field_name_mask, arg2->hdr_field_name_mask);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (ret == 0)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen ret = null_strcmp(arg1->str_mask, arg2->str_mask);
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen return ret;
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen}
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen
379175cfba8150d481d9898b78330b719d128d84Timo Sirainenstatic unsigned int
379175cfba8150d481d9898b78330b719d128d84Timo Sirainenmail_search_simplify_prev_arg_hash(const struct mail_search_simplify_prev_arg *arg)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen unsigned int hash;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen hash = mem_hash(&arg->bin_mask, sizeof(arg->bin_mask));
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (arg->hdr_field_name_mask != NULL)
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen hash ^= str_hash(arg->hdr_field_name_mask);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (arg->str_mask != NULL)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen hash ^= str_hash(arg->str_mask);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen return hash;
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainen}
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen
33bd898e7756b289e65f43133312d9637afc1371Timo Sirainenstatic void mail_search_arg_get_base_mask(const struct mail_search_arg *arg,
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen struct mail_search_simplify_prev_arg *mask_r)
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen{
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen memset(mask_r, 0, sizeof(*mask_r));
4c892b0d94c5b1d6853dbe8e0b38059ea5b08ecaTimo Sirainen mask_r->bin_mask.type = arg->type;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mask_r->bin_mask.match_not = arg->match_not;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mask_r->bin_mask.fuzzy = arg->fuzzy;
2fb9ae42f9e36388ec6db24188b9108434043fd0Timo Sirainen mask_r->bin_mask.search_flags = arg->value.search_flags;
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen}
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen
a020eb653b2620a989e4795adceb6136037327b2Timo Sirainenstatic struct mail_search_arg **
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainenmail_search_args_simplify_get_prev_argp(struct mail_search_simplify_ctx *ctx,
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen const struct mail_search_simplify_prev_arg *mask)
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen{
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen struct mail_search_simplify_prev_arg *prev_arg;
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen
a8d47e2427558d5011dfc75694b704760c1ef8baTimo Sirainen prev_arg = hash_table_lookup(ctx->prev_args, mask);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (prev_arg == NULL) {
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen prev_arg = p_new(ctx->pool, struct mail_search_simplify_prev_arg, 1);
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen prev_arg->bin_mask = mask->bin_mask;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen prev_arg->hdr_field_name_mask =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen p_strdup(ctx->pool, mask->hdr_field_name_mask);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen prev_arg->str_mask =
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen p_strdup(ctx->pool, mask->str_mask);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen hash_table_insert(ctx->prev_args, prev_arg, prev_arg);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return &prev_arg->prev_arg;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx,
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct mail_search_arg *args)
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct mail_search_simplify_prev_arg mask;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct mail_search_arg **prev_argp;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (!((!args->match_not && ctx->parent_and) ||
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen (args->match_not && !ctx->parent_and)))
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return FALSE;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (*prev_argp == NULL) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen *prev_argp = args;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen return FALSE;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen } else {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen (*prev_argp)->value.flags |= args->value.flags;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return TRUE;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen}
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenstatic bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx,
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen struct mail_search_arg *args)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen{
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen struct mail_search_simplify_prev_arg mask;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen struct mail_search_arg **prev_argp;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (!((!args->match_not && ctx->parent_and) ||
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen (args->match_not && !ctx->parent_and)))
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen return FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen if (*prev_argp == NULL) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *prev_argp = args;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen return FALSE;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen } else {
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen seq_range_array_merge(&(*prev_argp)->value.seqset,
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen &args->value.seqset);
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen return TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainenstatic bool mail_search_args_merge_time(struct mail_search_simplify_ctx *ctx,
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen struct mail_search_arg *args)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen{
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen struct mail_search_simplify_prev_arg mask;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen mask.bin_mask.date_type = args->value.date_type;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen if (*prev_argp == NULL) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *prev_argp = args;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen return FALSE;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen }
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen prev_arg = *prev_argp;
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen switch (args->type) {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen case SEARCH_BEFORE:
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen if (ctx->parent_and) {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen if (prev_arg->value.time < args->value.time) {
7b64db32b95286235612eebb5d37d296a49306f7Timo Sirainen /* prev_arg < 5 AND arg < 10 */
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen } else {
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen /* prev_arg < 10 AND arg < 5 */
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen prev_arg->value.time = args->value.time;
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen }
a26b7e87b4157cfa800f9bcd8c4c044462d21268Timo Sirainen } else {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (prev_arg->value.time < args->value.time) {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen /* prev_arg < 5 OR arg < 10 */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen prev_arg->value.time = args->value.time;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen } else {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen /* prev_arg < 10 OR arg < 5 */
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen case SEARCH_ON:
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (prev_arg->value.time == args->value.time)
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return TRUE;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen return FALSE;
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen case SEARCH_SINCE:
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen if (ctx->parent_and) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (prev_arg->value.time < args->value.time) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen /* prev_arg >= 5 AND arg >= 10 */
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen prev_arg->value.time = args->value.time;
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen } else {
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen /* prev_arg >= 10 AND arg >= 5 */
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen }
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen } else {
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen if (prev_arg->value.time < args->value.time) {
8cca3b43b28365cfee4dc733c00caaeab8ecd2adTimo Sirainen /* prev_arg >= 5 OR arg >= 10 */
8cca3b43b28365cfee4dc733c00caaeab8ecd2adTimo Sirainen } else {
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen /* prev_arg >= 10 OR arg >= 5 */
4f2fa2e5f5a27e1d59dd38fbbf38e420e006596dTimo Sirainen prev_arg->value.time = args->value.time;
4f2fa2e5f5a27e1d59dd38fbbf38e420e006596dTimo Sirainen }
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen }
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen return TRUE;
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen default:
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen break;
e51cfb5506de764499cb5b81a098b23cf46f90f1Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen return FALSE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen}
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenstatic bool mail_search_args_merge_size(struct mail_search_simplify_ctx *ctx,
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct mail_search_arg *args)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen{
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct mail_search_simplify_prev_arg mask;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen if (*prev_argp == NULL) {
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen *prev_argp = args;
13b063ba3ea51256fd97d7fa883f14cb08842b0dTimo Sirainen return FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen prev_arg = *prev_argp;
013a8a91c83c6ea24bc75322b81235f19e26fa8fTimo Sirainen switch (args->type) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen case SEARCH_SMALLER:
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen if (ctx->parent_and) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (prev_arg->value.size < args->value.size) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* prev_arg < 5 AND arg < 10 */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else {
d1fff80640050631b06bfab904a34b2ad24601e8Timo Sirainen /* prev_arg < 10 AND arg < 5 */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen prev_arg->value.size = args->value.size;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (prev_arg->value.size < args->value.size) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* prev_arg < 5 OR arg < 10 */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen prev_arg->value.size = args->value.size;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* prev_arg < 10 OR arg < 5 */
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen }
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen }
f9142439f2b5e86065af7420e80fe52835227dc8Timo Sirainen return TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen case SEARCH_LARGER:
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ctx->parent_and) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (prev_arg->value.size < args->value.size) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen /* prev_arg >= 5 AND arg >= 10 */
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen prev_arg->value.size = args->value.size;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen } else {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* prev_arg >= 10 AND arg >= 5 */
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (prev_arg->value.size < args->value.size) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen /* prev_arg >= 5 OR arg >= 10 */
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen } else {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen /* prev_arg >= 10 OR arg >= 5 */
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen prev_arg->value.size = args->value.size;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen }
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return TRUE;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen default:
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen break;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
2f90189c6ee66a17f7bf838a8eb8a69868630fb8Timo Sirainen return FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenstatic bool mail_search_args_merge_text(struct mail_search_simplify_ctx *ctx,
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen struct mail_search_arg *args)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen struct mail_search_simplify_prev_arg mask;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen struct mail_search_arg **prev_argp;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen mail_search_arg_get_base_mask(args, &mask);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen mask.hdr_field_name_mask = args->hdr_field_name;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen mask.str_mask = args->value.str;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen if (*prev_argp == NULL) {
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen *prev_argp = args;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return FALSE;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen }
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen /* duplicate search word. */
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen return TRUE;
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen}
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenstatic bool
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainenmail_search_args_have_equal(const struct mail_search_arg *args,
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen const struct mail_search_arg *wanted_arg)
acfda38b75d0f0e899ef692fef01593bd56ed85eTimo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const struct mail_search_arg *arg;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (arg = args; arg != NULL; arg = arg->next) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (mail_search_arg_one_equals(arg, wanted_arg))
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen return TRUE;
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen }
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen return FALSE;
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen}
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainenstatic bool
d23dfc385f22d7a2c466d29501c9e0ce5a243deeTimo Sirainenmail_search_args_remove_equal(struct mail_search_arg *parent_arg,
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen const struct mail_search_arg *wanted_arg,
bcf1cf2afb9692b0db555e6ecf662a2fbd19793dTimo Sirainen bool check_subs)
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen{
23152672e3ad7f3512c11df43e8dabba4fe6407dTimo Sirainen struct mail_search_arg **argp;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen bool found = FALSE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen for (argp = &parent_arg->value.subargs; (*argp) != NULL; ) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (mail_search_arg_one_equals(*argp, wanted_arg)) {
d80f37f025593d959bdfa9c378915e4322f4f504Timo Sirainen *argp = (*argp)->next;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen found = TRUE;
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen } else if (check_subs) {
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen i_assert((*argp)->type == SEARCH_SUB);
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if (!mail_search_args_remove_equal(*argp, wanted_arg, FALSE)) {
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen /* we already verified that this should have
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen existed. */
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen i_unreached();
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen if ((*argp)->value.subargs == NULL)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen *argp = (*argp)->next;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen else
fc4e528886f47bf4d2dd0276fb8705c085c3b9aeTimo Sirainen argp = &(*argp)->next;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen found = TRUE;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen } else {
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen argp = &(*argp)->next;
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen }
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen return found;
94ce7e7700cda14a8342cb08e7285507b4b531daTimo Sirainen}
311d3dd2078c1b711a0cef013ba43a94078c115cTimo Sirainen
311d3dd2078c1b711a0cef013ba43a94078c115cTimo Sirainenstatic bool
311d3dd2078c1b711a0cef013ba43a94078c115cTimo Sirainenmail_search_args_have_all_equal(struct mail_search_arg *parent_arg,
311d3dd2078c1b711a0cef013ba43a94078c115cTimo Sirainen const struct mail_search_arg *wanted_args)
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen{
4654f788834c9d7920a351306b89cf5d1c21772eTimo Sirainen const struct mail_search_arg *arg;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen i_assert(parent_arg->type == SEARCH_SUB);
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen for (arg = wanted_args; arg != NULL; arg = arg->next) {
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen if (!mail_search_args_have_equal(parent_arg->value.subargs, arg))
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen return FALSE;
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen }
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen return TRUE;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen}
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainenstatic unsigned int
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainenmail_search_args_count(const struct mail_search_arg *args)
b06633c63fde22b6c8837ae70b2f95fe60075b0aTimo Sirainen{
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen unsigned int count;
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen for (count = 0; args != NULL; count++)
3398d5e2b883812de5d569721c8294b581e1d9e6Timo Sirainen args = args->next;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen return count;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen}
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenstatic bool
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenmail_search_args_simplify_or_drop_redundent_args(struct mail_search_arg *parent_arg)
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen{
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen struct mail_search_arg *arg, **argp, one_arg, *lowest_arg = NULL;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen unsigned int count, lowest_count = UINT_MAX;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen bool ret = FALSE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen /* find the arg which has the lowest number of child args */
9f10cc61ec303351b43e54155c86699ef53cb8beTimo Sirainen for (arg = parent_arg->value.subargs; arg != NULL; arg = arg->next) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (arg->type != SEARCH_SUB) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen one_arg = *arg;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen one_arg.next = NULL;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen lowest_arg = &one_arg;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen break;
5736aef6d0abe6796e57c2eda68f5c25db677918Timo Sirainen }
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen count = mail_search_args_count(arg->value.subargs);
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen if (count < lowest_count) {
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen lowest_arg = arg->value.subargs;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen lowest_count = count;
fc464e5b2b2ab4d415a5d5b90ce4475d34620a75Timo Sirainen }
5e751dbaecf7c337abc149f328c4a13ee5c15134Timo Sirainen }
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen i_assert(lowest_arg != NULL);
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen
4da8c6cdefabd31262318c32da3c13de1d9ea953Timo Sirainen /* if there are any args that include lowest_arg, drop the arg since
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen it's redundant. (non-SUB duplicates are dropped elsewhere.) */
9f10cc61ec303351b43e54155c86699ef53cb8beTimo Sirainen for (argp = &parent_arg->value.subargs; *argp != NULL; ) {
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen if (*argp != lowest_arg && (*argp)->type == SEARCH_SUB &&
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen (*argp)->value.subargs != lowest_arg &&
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen mail_search_args_have_all_equal(*argp, lowest_arg)) {
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen *argp = (*argp)->next;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen ret = TRUE;
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen } else {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen argp = &(*argp)->next;
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen return ret;
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen}
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainenstatic bool
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainenmail_search_args_simplify_extract_common_and(struct mail_search_arg *parent_arg,
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen pool_t pool)
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen{
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen struct mail_search_arg *arg, *sub_arg, *sub_next;
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen struct mail_search_arg *or_arg, *common_args = NULL;
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen i_assert(parent_arg->type == SEARCH_OR);
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen i_assert(!parent_arg->match_not);
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen /* find the first SEARCH_SUB */
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen for (arg = parent_arg->value.subargs; arg != NULL; arg = arg->next) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (arg->type == SEARCH_SUB)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen break;
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (arg == NULL)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen return FALSE;
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen for (sub_arg = arg->value.subargs; sub_arg != NULL; sub_arg = sub_next) {
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen sub_next = sub_arg->next;
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen /* check if sub_arg is found from all the args */
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen for (arg = parent_arg->value.subargs; arg != NULL; arg = arg->next) {
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen if (mail_search_arg_one_equals(arg, sub_arg)) {
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen /* the whole arg matches */
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen } else if (arg->type == SEARCH_SUB &&
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen mail_search_args_have_equal(arg->value.subargs, sub_arg)) {
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen /* exists as subarg */
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen } else {
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen break;
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen }
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen }
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (arg != NULL)
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen continue;
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen /* extract the arg and put it to common_args */
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen mail_search_args_remove_equal(parent_arg, sub_arg, TRUE);
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen sub_arg->next = common_args;
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen common_args = sub_arg;
117a55d4260651770705ecb96f68be2dab03b99bTimo Sirainen }
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen if (common_args == NULL)
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen return FALSE;
326c86b1cdb555957b236958e17142e82e34074eTimo Sirainen
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen if (parent_arg->value.subargs == NULL) {
0f5dc4da3982053036be65190e44bf28a67b1ca2Timo Sirainen /* there are only common args */
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen parent_arg->type = SEARCH_SUB;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen parent_arg->value.subargs = common_args;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen } else {
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen /* replace OR arg with AND(common_args, OR(non_common_args)) */
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen or_arg = p_new(pool, struct mail_search_arg, 1);
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen *or_arg = *parent_arg;
39993536eaef0a23954105e41040dcf88afd2e7eTimo Sirainen or_arg->next = common_args;
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen parent_arg->type = SEARCH_SUB;
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen parent_arg->value.subargs = or_arg;
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen }
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen return TRUE;
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen}
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainenstatic bool
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainenmail_search_args_simplify_sub(struct mailbox *box, pool_t pool,
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen struct mail_search_arg *args, bool parent_and)
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen{
dd7cbb32412c2f4d2d223af66672535bc1237246Timo Sirainen struct mail_search_simplify_ctx ctx;
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang struct mail_search_arg *sub, *prev_arg = NULL;
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang bool merged;
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen memset(&ctx, 0, sizeof(ctx));
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen ctx.parent_and = parent_and;
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen ctx.pool = pool_alloconly_create("mail search args simplify", 1024);
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen hash_table_create(&ctx.prev_args, ctx.pool, 0,
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen mail_search_simplify_prev_arg_hash,
287b5ba23f182fd98e7a6ba3a63669c1572f2ca4Timo Sirainen mail_search_simplify_prev_arg_cmp);
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang while (args != NULL) {
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang if (args->match_not && (args->type == SEARCH_SUB ||
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang args->type == SEARCH_OR)) {
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang /* neg(p and q and ..) == neg(p) or neg(q) or ..
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang neg(p or q or ..) == neg(p) and neg(q) and .. */
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang args->type = args->type == SEARCH_SUB ?
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang SEARCH_OR : SEARCH_SUB;
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang args->match_not = FALSE;
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang sub = args->value.subargs;
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang do {
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang sub->match_not = !sub->match_not;
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang sub = sub->next;
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang } while (sub != NULL);
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang }
527c2b071dca35b91648344e867ab1af9c988281Baofeng Wang
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if ((args->type == SEARCH_SUB && parent_and) ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (args->type == SEARCH_OR && !parent_and) ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ((args->type == SEARCH_SUB || args->type == SEARCH_OR) &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen args->value.subargs->next == NULL)) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* p and (q and ..) == p and q and ..
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen p or (q or ..) == p or q or ..
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen (p) = p */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen sub = args->value.subargs;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen for (; sub->next != NULL; sub = sub->next) ;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen sub->next = args->next;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen *args = *args->value.subargs;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen ctx.removals = TRUE;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen continue;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen }
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (args->type == SEARCH_SUB ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen args->type == SEARCH_OR ||
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen args->type == SEARCH_INTHREAD) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (args->type == SEARCH_OR) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (mail_search_args_simplify_or_drop_redundent_args(args))
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen ctx.removals = TRUE;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (mail_search_args_simplify_extract_common_and(args, pool))
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen ctx.removals = TRUE;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen }
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen if (mail_search_args_simplify_sub(box, pool, args->value.subargs,
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen args->type != SEARCH_OR))
08a33e7c0cf5ab2c4a0c96a55056cc3251d14c5eTimo Sirainen ctx.removals = TRUE;
cb17980a661554ebb3fd099c77e92a5be4d304ecTimo Sirainen }
cb17980a661554ebb3fd099c77e92a5be4d304ecTimo Sirainen
cb17980a661554ebb3fd099c77e92a5be4d304ecTimo Sirainen /* try to merge arguments */
cb17980a661554ebb3fd099c77e92a5be4d304ecTimo Sirainen switch (args->type) {
d2d5871fa9e7226df694ff7a4be511167b35b305Timo Sirainen case SEARCH_FLAGS:
d2c853636ec2d99c9f96da877ff520a3b86a18baTimo Sirainen merged = mail_search_args_merge_flags(&ctx, args);
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen break;
57f5683fd9dc9bc79816c418bb30fdbc33b68a8cTimo Sirainen case SEARCH_SEQSET:
57f5683fd9dc9bc79816c418bb30fdbc33b68a8cTimo Sirainen case SEARCH_UIDSET:
57f5683fd9dc9bc79816c418bb30fdbc33b68a8cTimo Sirainen merged = mail_search_args_merge_set(&ctx, args);
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen break;
57f5683fd9dc9bc79816c418bb30fdbc33b68a8cTimo Sirainen case SEARCH_BEFORE:
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen case SEARCH_ON:
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen case SEARCH_SINCE:
67c47dbb3fde79218320fd38a45c33f61bbf3012Timo Sirainen merged = mail_search_args_merge_time(&ctx, args);
55a14bce15b9f44441b5f56616d73651a294d770Timo Sirainen break;
55a14bce15b9f44441b5f56616d73651a294d770Timo Sirainen case SEARCH_SMALLER:
b16ee3cbbcd18cb86f2f73b5cc163ebfb995ffafTimo Sirainen case SEARCH_LARGER:
55a14bce15b9f44441b5f56616d73651a294d770Timo Sirainen merged = mail_search_args_merge_size(&ctx, args);
55a14bce15b9f44441b5f56616d73651a294d770Timo Sirainen break;
55a14bce15b9f44441b5f56616d73651a294d770Timo Sirainen case SEARCH_HEADER:
55a14bce15b9f44441b5f56616d73651a294d770Timo Sirainen case SEARCH_HEADER_ADDRESS:
b16ee3cbbcd18cb86f2f73b5cc163ebfb995ffafTimo Sirainen case SEARCH_HEADER_COMPRESS_LWSP:
b16ee3cbbcd18cb86f2f73b5cc163ebfb995ffafTimo Sirainen case SEARCH_BODY:
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen case SEARCH_TEXT:
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen merged = mail_search_args_merge_text(&ctx, args);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen break;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen default:
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen merged = FALSE;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen break;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
318ef3683d67683173f1b552cf5f9af4375b3017Timo Sirainen if (merged) {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen i_assert(prev_arg != NULL);
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen prev_arg->next = args->next;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen args = args->next;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen ctx.removals = TRUE;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen continue;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen }
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen prev_arg = args;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen args = args->next;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen }
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen hash_table_destroy(&ctx.prev_args);
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen pool_unref(&ctx.pool);
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen return ctx.removals;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen}
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainenstatic bool
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainenmail_search_args_unnest_inthreads(struct mail_search_args *args,
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen struct mail_search_arg **argp,
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen bool parent_inthreads, bool parent_and)
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen{
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen struct mail_search_arg *arg, *thread_arg, *or_arg;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen bool child_inthreads = FALSE, non_inthreads = FALSE;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen for (arg = *argp; arg != NULL; arg = arg->next) {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen switch (arg->type) {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen case SEARCH_SUB:
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen case SEARCH_OR:
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen if (!mail_search_args_unnest_inthreads(args,
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen &arg->value.subargs, parent_inthreads,
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen arg->type != SEARCH_OR)) {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen arg->result = 1;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen child_inthreads = TRUE;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen } else {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen arg->result = 0;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen non_inthreads = TRUE;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen }
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen break;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen case SEARCH_INTHREAD:
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen if (mail_search_args_unnest_inthreads(args,
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen &arg->value.subargs, TRUE, TRUE)) {
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen /* children converted to SEARCH_INTHREADs */
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen arg->type = SEARCH_SUB;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen }
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen args->have_inthreads = TRUE;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen arg->result = 1;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen child_inthreads = TRUE;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen break;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen default:
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen arg->result = 0;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen non_inthreads = TRUE;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen break;
87ca4b209c10954826b878da165d303d9b4dc5a2Timo Sirainen }
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen }
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen if (!parent_inthreads || !child_inthreads || !non_inthreads)
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen return FALSE;
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen /* put all non-INTHREADs under a single INTHREAD */
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen thread_arg = p_new(args->pool, struct mail_search_arg, 1);
691f802ef6ec2105079d420ba26b21088402c6daTimo Sirainen thread_arg->type = SEARCH_INTHREAD;
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen while (*argp != NULL) {
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen arg = *argp;
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen argp = &(*argp)->next;
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen if (arg->result == 0) {
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen /* not an INTHREAD or a SUB/OR with only INTHREADs */
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen arg->next = thread_arg->value.subargs;
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen thread_arg->value.subargs = arg;
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen }
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen }
a020eb653b2620a989e4795adceb6136037327b2Timo Sirainen if (!parent_and) {
9f7441a47863d44ec303c7980b499b46b3d1671bTimo Sirainen /* We want to OR the args */
9f7441a47863d44ec303c7980b499b46b3d1671bTimo Sirainen or_arg = p_new(args->pool, struct mail_search_arg, 1);
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen or_arg->type = SEARCH_OR;
1e40531c1de45bc87e72a9d5866ff2af79b63cebTimo Sirainen or_arg->value.subargs = thread_arg->value.subargs;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen thread_arg->value.subargs = or_arg;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen }
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen return TRUE;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen}
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainenvoid mail_search_args_simplify(struct mail_search_args *args)
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen{
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen bool removals;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen args->simplified = TRUE;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen removals = mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE);
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen if (mail_search_args_unnest_inthreads(args, &args->args,
c981098a515c62fdfb3261e532b5d6163a0f8946Timo Sirainen FALSE, TRUE)) {
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen /* we may have added some extra SUBs that could be dropped */
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen if (mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE))
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen removals = TRUE;
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen }
1701b354e81ff1dfd0b6c7bb4412b8d9c2b9f986Timo Sirainen while (removals)
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen removals = mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE);
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen}
379175cfba8150d481d9898b78330b719d128d84Timo Sirainen