mail-search-args-simplify.c revision 1e167fbb281ccf41178a0b70495193c768f9ff75
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "lib.h"
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen#include "hash.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "mail-search.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstruct mail_search_simplify_prev_arg {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen enum mail_search_arg_type type;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen enum mail_search_arg_flag search_flags;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen enum mail_search_date_type date_type;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen bool match_not;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen bool fuzzy;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen } bin_mask;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen const char *hdr_field_name_mask;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen const char *str_mask;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_search_arg *prev_arg;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen};
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstruct mail_search_simplify_ctx {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen pool_t pool;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* arg mask => prev_arg */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen HASH_TABLE(struct mail_search_simplify_prev_arg *,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_search_simplify_prev_arg *) prev_args;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen bool parent_and;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen bool removals;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen};
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic int
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenmail_search_simplify_prev_arg_cmp(const struct mail_search_simplify_prev_arg *arg1,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen const struct mail_search_simplify_prev_arg *arg2)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen int ret;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = memcmp(&arg1->bin_mask, &arg2->bin_mask, sizeof(arg1->bin_mask));
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (ret == 0)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = null_strcmp(arg1->hdr_field_name_mask, arg2->hdr_field_name_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (ret == 0)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen ret = null_strcmp(arg1->str_mask, arg2->str_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return ret;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen}
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic unsigned int
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenmail_search_simplify_prev_arg_hash(const struct mail_search_simplify_prev_arg *arg)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen unsigned int hash;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen hash = mem_hash(&arg->bin_mask, sizeof(arg->bin_mask));
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (arg->hdr_field_name_mask != NULL)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen hash ^= str_hash(arg->hdr_field_name_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (arg->str_mask != NULL)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen hash ^= str_hash(arg->str_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return hash;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen}
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic void mail_search_arg_get_base_mask(const struct mail_search_arg *arg,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct mail_search_simplify_prev_arg *mask_r)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen{
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen memset(mask_r, 0, sizeof(*mask_r));
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask_r->bin_mask.type = arg->type;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask_r->bin_mask.match_not = arg->match_not;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask_r->bin_mask.fuzzy = arg->fuzzy;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask_r->bin_mask.search_flags = arg->value.search_flags;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen}
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic struct mail_search_arg **
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenmail_search_args_simplify_get_prev_argp(struct mail_search_simplify_ctx *ctx,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen const struct mail_search_simplify_prev_arg *mask)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen{
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_search_simplify_prev_arg *prev_arg;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg = hash_table_lookup(ctx->prev_args, mask);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg == NULL) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg = p_new(ctx->pool, struct mail_search_simplify_prev_arg, 1);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen prev_arg->bin_mask = mask->bin_mask;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen prev_arg->hdr_field_name_mask =
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen p_strdup(ctx->pool, mask->hdr_field_name_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen prev_arg->str_mask =
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen p_strdup(ctx->pool, mask->str_mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen hash_table_insert(ctx->prev_args, prev_arg, prev_arg);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return &prev_arg->prev_arg;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen}
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstatic bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct mail_search_arg *args)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct mail_search_simplify_prev_arg mask;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct mail_search_arg **prev_argp;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (!((!args->match_not && ctx->parent_and) ||
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen (args->match_not && !ctx->parent_and)))
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return FALSE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (*prev_argp == NULL) {
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen *prev_argp = args;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen return FALSE;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen } else {
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen (*prev_argp)->value.flags |= args->value.flags;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen return TRUE;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen }
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen}
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainenstatic bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct mail_search_arg *args)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct mail_search_simplify_prev_arg mask;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct mail_search_arg **prev_argp;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (!((!args->match_not && ctx->parent_and) ||
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen (args->match_not && !ctx->parent_and)))
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return FALSE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (*prev_argp == NULL) {
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen *prev_argp = args;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen return FALSE;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen } else {
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen seq_range_array_merge(&(*prev_argp)->value.seqset,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen &args->value.seqset);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen return TRUE;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen }
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen}
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic bool mail_search_args_merge_time(struct mail_search_simplify_ctx *ctx,
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_search_arg *args)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct mail_search_simplify_prev_arg mask;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask.bin_mask.date_type = args->value.date_type;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (*prev_argp == NULL) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen *prev_argp = args;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return FALSE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg = *prev_argp;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen switch (args->type) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_BEFORE:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (ctx->parent_and) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time < args->value.time) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg < 5 AND arg < 10 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen } else {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg < 10 AND arg < 5 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg->value.time = args->value.time;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen } else {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time < args->value.time) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg < 5 OR arg < 10 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg->value.time = args->value.time;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen } else {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg < 10 OR arg < 5 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return TRUE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_ON:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time == args->value.time)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return TRUE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return FALSE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_SINCE:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (ctx->parent_and) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time < args->value.time) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg >= 5 AND arg >= 10 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg->value.time = args->value.time;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen } else {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg >= 10 AND arg >= 5 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen } else {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (prev_arg->value.time < args->value.time) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg >= 5 OR arg >= 10 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen } else {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* prev_arg >= 10 OR arg >= 5 */
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg->value.time = args->value.time;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return TRUE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen default:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen break;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen return FALSE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen}
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainenstatic bool mail_search_args_merge_size(struct mail_search_simplify_ctx *ctx,
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen struct mail_search_arg *args)
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct mail_search_simplify_prev_arg mask;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen mail_search_arg_get_base_mask(args, &mask);
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (*prev_argp == NULL) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen *prev_argp = args;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen return FALSE;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen prev_arg = *prev_argp;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen switch (args->type) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen case SEARCH_SMALLER:
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (ctx->parent_and) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (prev_arg->value.size < args->value.size) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg < 5 AND arg < 10 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen } else {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg < 10 AND arg < 5 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen prev_arg->value.size = args->value.size;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen } else {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (prev_arg->value.size < args->value.size) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg < 5 OR arg < 10 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen prev_arg->value.size = args->value.size;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen } else {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg < 10 OR arg < 5 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen return TRUE;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen case SEARCH_LARGER:
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (ctx->parent_and) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (prev_arg->value.size < args->value.size) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg >= 5 AND arg >= 10 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen prev_arg->value.size = args->value.size;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen } else {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg >= 10 AND arg >= 5 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen } else {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (prev_arg->value.size < args->value.size) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg >= 5 OR arg >= 10 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen } else {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen /* prev_arg >= 10 OR arg >= 5 */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen prev_arg->value.size = args->value.size;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen return TRUE;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen default:
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen break;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen return FALSE;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen}
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainenstatic bool mail_search_args_merge_text(struct mail_search_simplify_ctx *ctx,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct mail_search_arg *args)
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen{
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct mail_search_simplify_prev_arg mask;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen struct mail_search_arg **prev_argp;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mail_search_arg_get_base_mask(args, &mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask.hdr_field_name_mask = args->hdr_field_name;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mask.str_mask = args->value.str;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (*prev_argp == NULL) {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen *prev_argp = args;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return FALSE;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen }
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* duplicate search word. */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return TRUE;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen}
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenstatic bool
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenmail_search_args_have_equal(const struct mail_search_arg *args,
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen const struct mail_search_arg *wanted_arg)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen{
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen const struct mail_search_arg *arg;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen for (arg = args; arg != NULL; arg = arg->next) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen if (mail_search_arg_one_equals(arg, wanted_arg))
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen return TRUE;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen return FALSE;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen}
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainenstatic bool
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainenmail_search_args_remove_equal(struct mail_search_arg **argsp,
632018810af689442569cbb0139c55868923ccfeTimo Sirainen const struct mail_search_arg *wanted_arg,
632018810af689442569cbb0139c55868923ccfeTimo Sirainen bool check_subs)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen{
632018810af689442569cbb0139c55868923ccfeTimo Sirainen struct mail_search_arg **argp;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen bool found = FALSE;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen for (argp = argsp; (*argp) != NULL; ) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (mail_search_arg_one_equals(*argp, wanted_arg)) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen *argp = (*argp)->next;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen found = TRUE;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen } else if (check_subs) {
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen i_assert((*argp)->type == SEARCH_SUB ||
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen (*argp)->type == SEARCH_OR);
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen if (!mail_search_args_remove_equal(&(*argp)->value.subargs, wanted_arg, FALSE)) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* we already verified that this should have
632018810af689442569cbb0139c55868923ccfeTimo Sirainen existed. */
632018810af689442569cbb0139c55868923ccfeTimo Sirainen i_unreached();
632018810af689442569cbb0139c55868923ccfeTimo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if ((*argp)->value.subargs == NULL)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen *argp = (*argp)->next;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen else
632018810af689442569cbb0139c55868923ccfeTimo Sirainen argp = &(*argp)->next;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen found = TRUE;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen } else {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen argp = &(*argp)->next;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen return found;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen}
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenstatic bool
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenmail_search_args_have_all_equal(struct mail_search_arg *parent_arg,
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen const struct mail_search_arg *wanted_args)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen{
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen const struct mail_search_arg *arg;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen i_assert(parent_arg->type == SEARCH_SUB ||
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen parent_arg->type == SEARCH_OR);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen for (arg = wanted_args; arg != NULL; arg = arg->next) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen if (!mail_search_args_have_equal(parent_arg->value.subargs, arg))
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen return FALSE;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen return TRUE;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen}
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenstatic unsigned int
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenmail_search_args_count(const struct mail_search_arg *args)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen{
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen unsigned int count;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen for (count = 0; args != NULL; count++)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen args = args->next;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen return count;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen}
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainenstatic bool
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainenmail_search_args_simplify_drop_redundent_args(struct mail_search_arg **argsp,
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen bool and_arg)
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen{
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen struct mail_search_arg *arg, **argp, one_arg, *lowest_arg = NULL;
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen enum mail_search_arg_type child_subargs_type;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen unsigned int count, lowest_count = UINT_MAX;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen bool ret = FALSE;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen child_subargs_type = and_arg ? SEARCH_OR : SEARCH_SUB;
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen /* find the arg which has the lowest number of child args */
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen for (arg = *argsp; arg != NULL; arg = arg->next) {
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen if (arg->type != child_subargs_type) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen one_arg = *arg;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen one_arg.next = NULL;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen lowest_arg = &one_arg;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen break;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen count = mail_search_args_count(arg->value.subargs);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen if (count < lowest_count) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen lowest_arg = arg->value.subargs;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen lowest_count = count;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen i_assert(lowest_arg != NULL);
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen /* if there are any args that include lowest_arg, drop the arg since
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen it's redundant. (non-SUB duplicates are dropped elsewhere.) */
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen for (argp = argsp; *argp != NULL; ) {
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen if (*argp != lowest_arg && (*argp)->type == child_subargs_type &&
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen (*argp)->value.subargs != lowest_arg &&
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen mail_search_args_have_all_equal(*argp, lowest_arg)) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen *argp = (*argp)->next;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen ret = TRUE;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen } else {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen argp = &(*argp)->next;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen return ret;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen}
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen
fb79b36eb34532dbe67caf99eefe3660b8c841e0Timo Sirainenstatic bool
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainenmail_search_args_simplify_extract_common(struct mail_search_arg **argsp,
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen pool_t pool, bool and_arg)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen{
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen /* Simple SUB example:
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen (a AND b) OR (a AND c) -> a AND (b OR c)
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen More complicated example:
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen (c1 AND c2 AND u1 AND u2) OR (c1 AND c2 AND u3 AND u4) ->
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen c1 AND c2 AND ((u1 AND u2) OR (u3 AND u4))
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen Similarly for ORs:
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen (a OR b) AND (a OR c) -> a OR (b AND c)
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen (c1 OR c2 OR u1 OR u2) AND (c1 OR c2 OR u3 OR u4) ->
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen c1 OR c2 OR ((u1 OR u2) AND (u3 OR u4))
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen */
632018810af689442569cbb0139c55868923ccfeTimo Sirainen struct mail_search_arg *arg, *sub_arg, *sub_next;
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen struct mail_search_arg *new_arg, *child_arg, *common_args = NULL;
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen enum mail_search_arg_type child_subargs_type;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen if ((*argsp)->next == NULL) {
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen /* single arg, nothing to extract */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen return FALSE;
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen child_subargs_type = and_arg ? SEARCH_OR : SEARCH_SUB;
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen /* find the first arg with child_subargs_type */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen for (arg = *argsp; arg != NULL; arg = arg->next) {
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen if (arg->type == child_subargs_type)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen break;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (arg == NULL)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen return FALSE;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainen for (sub_arg = arg->value.subargs; sub_arg != NULL; sub_arg = sub_next) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen sub_next = sub_arg->next;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* check if sub_arg is found from all the args */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen for (arg = *argsp; arg != NULL; arg = arg->next) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (mail_search_arg_one_equals(arg, sub_arg)) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* the whole arg matches */
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen } else if (arg->type == child_subargs_type &&
632018810af689442569cbb0139c55868923ccfeTimo Sirainen mail_search_args_have_equal(arg->value.subargs, sub_arg)) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* exists as subarg */
632018810af689442569cbb0139c55868923ccfeTimo Sirainen } else {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen break;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (arg != NULL)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen continue;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* extract the arg and put it to common_args */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen mail_search_args_remove_equal(argsp, sub_arg, TRUE);
632018810af689442569cbb0139c55868923ccfeTimo Sirainen sub_arg->next = common_args;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen common_args = sub_arg;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (common_args == NULL)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen return FALSE;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen /* replace all the original args with a single new SUB/OR arg */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen new_arg = p_new(pool, struct mail_search_arg, 1);
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen new_arg->type = child_subargs_type;
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen if (*argsp == NULL) {
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* there are only common args */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen new_arg->value.subargs = common_args;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen } else {
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen /* replace OR arg with AND(OR(non_common_args), common_args)
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen or
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen replace AND arg with OR(AND(non_common_args), common_args) */
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen child_arg = p_new(pool, struct mail_search_arg, 1);
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen child_arg->type = and_arg ? SEARCH_SUB : SEARCH_OR;
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen child_arg->value.subargs = *argsp;
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen child_arg->next = common_args;
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen new_arg->value.subargs = child_arg;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen }
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen *argsp = new_arg;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen return TRUE;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen}
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainenstatic bool
632018810af689442569cbb0139c55868923ccfeTimo Sirainenmail_search_args_simplify_sub(struct mailbox *box, pool_t pool,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct mail_search_arg *args, bool parent_and)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen{
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct mail_search_simplify_ctx ctx;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen struct mail_search_arg *sub, *prev_arg = NULL;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen bool merged;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen memset(&ctx, 0, sizeof(ctx));
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen ctx.parent_and = parent_and;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen ctx.pool = pool_alloconly_create("mail search args simplify", 1024);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen hash_table_create(&ctx.prev_args, ctx.pool, 0,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mail_search_simplify_prev_arg_hash,
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen mail_search_simplify_prev_arg_cmp);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen while (args != NULL) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (args->match_not && (args->type == SEARCH_SUB ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args->type == SEARCH_OR)) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* neg(p and q and ..) == neg(p) or neg(q) or ..
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen neg(p or q or ..) == neg(p) and neg(q) and .. */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args->type = args->type == SEARCH_SUB ?
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen SEARCH_OR : SEARCH_SUB;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args->match_not = FALSE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen sub = args->value.subargs;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen do {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen sub->match_not = !sub->match_not;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen sub = sub->next;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen } while (sub != NULL);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if ((args->type == SEARCH_SUB && parent_and) ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen (args->type == SEARCH_OR && !parent_and) ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen ((args->type == SEARCH_SUB || args->type == SEARCH_OR) &&
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args->value.subargs->next == NULL)) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* p and (q and ..) == p and q and ..
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen p or (q or ..) == p or q or ..
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen (p) = p */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen sub = args->value.subargs;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen for (; sub->next != NULL; sub = sub->next) ;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen sub->next = args->next;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen *args = *args->value.subargs;
c89ceadf661bde22e1cd9dc2eac09c19202e65ecTimo Sirainen ctx.removals = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen continue;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (args->type == SEARCH_SUB ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args->type == SEARCH_OR ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args->type == SEARCH_INTHREAD) {
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen i_assert(!args->match_not);
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen if (args->type != SEARCH_INTHREAD) {
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen bool and_arg = args->type == SEARCH_SUB;
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen if (mail_search_args_simplify_drop_redundent_args(&args->value.subargs, and_arg))
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen ctx.removals = TRUE;
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen if (mail_search_args_simplify_extract_common(&args->value.subargs, pool, and_arg))
632018810af689442569cbb0139c55868923ccfeTimo Sirainen ctx.removals = TRUE;
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (mail_search_args_simplify_sub(box, pool, args->value.subargs,
fb79b36eb34532dbe67caf99eefe3660b8c841e0Timo Sirainen args->type != SEARCH_OR))
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen ctx.removals = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* try to merge arguments */
1e167fbb281ccf41178a0b70495193c768f9ff75Timo Sirainen merged = FALSE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen switch (args->type) {
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_FLAGS:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen merged = mail_search_args_merge_flags(&ctx, args);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen break;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_SEQSET:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_UIDSET:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen merged = mail_search_args_merge_set(&ctx, args);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen break;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_BEFORE:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_ON:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen case SEARCH_SINCE:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen merged = mail_search_args_merge_time(&ctx, args);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen break;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen case SEARCH_SMALLER:
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen case SEARCH_LARGER:
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen merged = mail_search_args_merge_size(&ctx, args);
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen break;
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen case SEARCH_BODY:
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen case SEARCH_TEXT:
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen if (args->value.str[0] == '\0') {
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen /* BODY "" and TEXT "" matches everything */
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen args->type = SEARCH_ALL;
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen ctx.removals = TRUE;
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen break;
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen }
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen /* fall through */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen case SEARCH_HEADER:
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen case SEARCH_HEADER_ADDRESS:
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen case SEARCH_HEADER_COMPRESS_LWSP:
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen merged = mail_search_args_merge_text(&ctx, args);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen break;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen default:
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen break;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (merged) {
25f959d63f5379702f44f5ae125eb3b70a6a47d7Timo Sirainen i_assert(prev_arg != NULL);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen prev_arg->next = args->next;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen args = args->next;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen ctx.removals = TRUE;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen continue;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen prev_arg = args;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args = args->next;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen hash_table_destroy(&ctx.prev_args);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen pool_unref(&ctx.pool);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen return ctx.removals;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen}
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic bool
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenmail_search_args_unnest_inthreads(struct mail_search_args *args,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct mail_search_arg **argp,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen bool parent_inthreads, bool parent_and)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen{
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct mail_search_arg *arg, *thread_arg, *or_arg;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen bool child_inthreads = FALSE, non_inthreads = FALSE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen for (arg = *argp; arg != NULL; arg = arg->next) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen switch (arg->type) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen case SEARCH_SUB:
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen case SEARCH_OR:
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (!mail_search_args_unnest_inthreads(args,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen &arg->value.subargs, parent_inthreads,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen arg->type != SEARCH_OR)) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen arg->result = 1;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen child_inthreads = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen } else {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen arg->result = 0;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen non_inthreads = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen break;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen case SEARCH_INTHREAD:
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (mail_search_args_unnest_inthreads(args,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen &arg->value.subargs, TRUE, TRUE)) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* children converted to SEARCH_INTHREADs */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen arg->type = SEARCH_SUB;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args->have_inthreads = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen arg->result = 1;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen child_inthreads = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen break;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen default:
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen arg->result = 0;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen non_inthreads = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen break;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (!parent_inthreads || !child_inthreads || !non_inthreads)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return FALSE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* put all non-INTHREADs under a single INTHREAD */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen thread_arg = p_new(args->pool, struct mail_search_arg, 1);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen thread_arg->type = SEARCH_INTHREAD;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen while (*argp != NULL) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen arg = *argp;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen argp = &(*argp)->next;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (arg->result == 0) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* not an INTHREAD or a SUB/OR with only INTHREADs */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen arg->next = thread_arg->value.subargs;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen thread_arg->value.subargs = arg;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (!parent_and) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* We want to OR the args */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen or_arg = p_new(args->pool, struct mail_search_arg, 1);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen or_arg->type = SEARCH_OR;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen or_arg->value.subargs = thread_arg->value.subargs;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen thread_arg->value.subargs = or_arg;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen}
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenvoid mail_search_args_simplify(struct mail_search_args *args)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen{
fb79b36eb34532dbe67caf99eefe3660b8c841e0Timo Sirainen bool removals;
fb79b36eb34532dbe67caf99eefe3660b8c841e0Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen args->simplified = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainen removals = mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (mail_search_args_unnest_inthreads(args, &args->args,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen FALSE, TRUE)) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* we may have added some extra SUBs that could be dropped */
c89ceadf661bde22e1cd9dc2eac09c19202e65ecTimo Sirainen if (mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE))
c89ceadf661bde22e1cd9dc2eac09c19202e65ecTimo Sirainen removals = TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen for (;;) {
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen if (mail_search_args_simplify_drop_redundent_args(&args->args, TRUE))
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen removals = TRUE;
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen if (mail_search_args_simplify_extract_common(&args->args, args->pool, TRUE))
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen removals = TRUE;
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen if (!removals)
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen break;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen removals = mail_search_args_simplify_sub(args->box, args->pool, args->args, TRUE);
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen}