mail-search-args-simplify.c revision f5e8a76a128d4e92f0641135183c164fd5c5ce5e
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2002-2015 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "lib.h"
bca919b207e27d0d08b431bdb0f2ac099ef8b512Timo Sirainen#include "hash.h"
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen#include "mail-search.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainenstruct mail_search_simplify_prev_arg {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg mask;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg *prev_arg;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstruct mail_search_simplify_ctx {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen pool_t pool;
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* arg mask => prev_arg */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen HASH_TABLE(struct mail_search_arg *,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_simplify_prev_arg *) prev_args;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool parent_and;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool removals;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen};
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int mail_search_arg_cmp(const struct mail_search_arg *arg1,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mail_search_arg *arg2)
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return memcmp(arg1, arg2, sizeof(*arg1));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
afa201e7e1d2447e8dfa1aff43de0fdad564105fTimo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic unsigned int mail_search_arg_hash(const struct mail_search_arg *arg)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return mem_hash(arg, sizeof(*arg));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void mail_search_arg_get_base_mask(const struct mail_search_arg *arg,
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen struct mail_search_arg *mask_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memset(mask_r, 0, sizeof(*mask_r));
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mask_r->type = arg->type;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mask_r->match_not = arg->match_not;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mask_r->value.search_flags = arg->value.search_flags;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic struct mail_search_arg **
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainenmail_search_args_simplify_get_prev_argp(struct mail_search_simplify_ctx *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const struct mail_search_arg *mask)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen{
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mail_search_simplify_prev_arg *prev_arg;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen prev_arg = hash_table_lookup(ctx->prev_args, mask);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (prev_arg == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_arg = p_new(ctx->pool, struct mail_search_simplify_prev_arg, 1);
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen prev_arg->mask = *mask;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen hash_table_insert(ctx->prev_args, &prev_arg->mask, prev_arg);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen return &prev_arg->prev_arg;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen}
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainenstatic bool mail_search_args_merge_flags(struct mail_search_simplify_ctx *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg *args)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg mask;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen struct mail_search_arg **prev_argp;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!((!args->match_not && ctx->parent_and) ||
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (args->match_not && !ctx->parent_and)))
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen mail_search_arg_get_base_mask(args, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (*prev_argp == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *prev_argp = args;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen return FALSE;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen (*prev_argp)->value.flags |= args->value.flags;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainen}
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainen
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainenstatic bool mail_search_args_merge_set(struct mail_search_simplify_ctx *ctx,
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen struct mail_search_arg *args)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen{
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainen struct mail_search_arg mask;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen struct mail_search_arg **prev_argp;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (!((!args->match_not && ctx->parent_and) ||
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen (args->match_not && !ctx->parent_and)))
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen mail_search_arg_get_base_mask(args, &mask);
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (*prev_argp == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *prev_argp = args;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen seq_range_array_merge(&(*prev_argp)->value.seqset,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &args->value.seqset);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return TRUE;
4b2a4c8c762e3eaddf7fd2abfe7d4cca6e5e3fd8Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool mail_search_args_merge_time(struct mail_search_simplify_ctx *ctx,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg *args)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg mask;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mask.value.date_type = args->value.date_type;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (*prev_argp == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *prev_argp = args;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_arg = *prev_argp;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen switch (args->type) {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen case SEARCH_BEFORE:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ctx->parent_and) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (prev_arg->value.time < args->value.time) {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen /* prev_arg < 5 AND arg < 10 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg < 10 AND arg < 5 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_arg->value.time = args->value.time;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen }
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen } else {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (prev_arg->value.time < args->value.time) {
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen /* prev_arg < 5 OR arg < 10 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_arg->value.time = args->value.time;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg < 10 OR arg < 5 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
547e916f4e6f01af682f8b6e032c337f2a699364Timo Sirainen }
547e916f4e6f01af682f8b6e032c337f2a699364Timo Sirainen return TRUE;
547e916f4e6f01af682f8b6e032c337f2a699364Timo Sirainen case SEARCH_ON:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (prev_arg->value.time == args->value.time)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen case SEARCH_SINCE:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ctx->parent_and) {
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen if (prev_arg->value.time < args->value.time) {
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen /* prev_arg >= 5 AND arg >= 10 */
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen prev_arg->value.time = args->value.time;
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg >= 10 AND arg >= 5 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (prev_arg->value.time < args->value.time) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg >= 5 OR arg >= 10 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* prev_arg >= 10 OR arg >= 5 */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen prev_arg->value.time = args->value.time;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return TRUE;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen default:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen break;
fa7c76955c6bc62689fbdf39318194f85905e6e2Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic bool mail_search_args_merge_size(struct mail_search_simplify_ctx *ctx,
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen struct mail_search_arg *args)
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen{
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen struct mail_search_arg mask;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen struct mail_search_arg **prev_argp, *prev_arg;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen mail_search_arg_get_base_mask(args, &mask);
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen prev_argp = mail_search_args_simplify_get_prev_argp(ctx, &mask);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (*prev_argp == NULL) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen *prev_argp = args;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen prev_arg = *prev_argp;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen switch (args->type) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen case SEARCH_SMALLER:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (ctx->parent_and) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (prev_arg->value.size < args->value.size) {
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen /* prev_arg < 5 AND arg < 10 */
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen } else {
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen /* prev_arg < 10 AND arg < 5 */
888ab4e17f7441b4dcca4a01886d055b57f4586dTimo Sirainen prev_arg->value.size = args->value.size;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (prev_arg->value.size < args->value.size) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* prev_arg < 5 OR arg < 10 */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen prev_arg->value.size = args->value.size;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } else {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* prev_arg < 10 OR arg < 5 */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return TRUE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_LARGER:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ctx->parent_and) {
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (prev_arg->value.size < args->value.size) {
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen /* prev_arg >= 5 AND arg >= 10 */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen prev_arg->value.size = args->value.size;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen } else {
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen /* prev_arg >= 10 AND arg >= 5 */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen }
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen } else {
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (prev_arg->value.size < args->value.size) {
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen /* prev_arg >= 5 OR arg >= 10 */
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen } else {
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen /* prev_arg >= 10 OR arg >= 5 */
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen prev_arg->value.size = args->value.size;
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen }
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen }
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen return TRUE;
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen default:
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen break;
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return FALSE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic bool
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenmail_search_args_simplify_sub(struct mailbox *box,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct mail_search_arg *args, bool parent_and)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen struct mail_search_simplify_ctx ctx;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen struct mail_search_arg *sub, *prev_arg = NULL;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen bool merged;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen memset(&ctx, 0, sizeof(ctx));
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen ctx.parent_and = parent_and;
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen ctx.pool = pool_alloconly_create("mail search args simplify", 1024);
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen hash_table_create(&ctx.prev_args, ctx.pool, 0, mail_search_arg_hash,
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen mail_search_arg_cmp);
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen while (args != NULL) {
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen if (args->match_not && (args->type == SEARCH_SUB ||
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen args->type == SEARCH_OR)) {
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen /* neg(p and q and ..) == neg(p) or neg(q) or ..
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen neg(p or q or ..) == neg(p) and neg(q) and .. */
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen args->type = args->type == SEARCH_SUB ?
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen SEARCH_OR : SEARCH_SUB;
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen args->match_not = FALSE;
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen sub = args->value.subargs;
e22ac7474fb36e3e3dcfeb70ea5f54ea812aa2d0Timo Sirainen do {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen sub->match_not = !sub->match_not;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen sub = sub->next;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } while (sub != NULL);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if ((args->type == SEARCH_SUB && parent_and) ||
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen (args->type == SEARCH_OR && !parent_and) ||
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ((args->type == SEARCH_SUB || args->type == SEARCH_OR) &&
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen args->value.subargs->next == NULL)) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* p and (q and ..) == p and q and ..
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen p or (q or ..) == p or q or ..
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen (p) = p */
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen sub = args->value.subargs;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen for (; sub->next != NULL; sub = sub->next) ;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen sub->next = args->next;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen *args = *args->value.subargs;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen continue;
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen }
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen if (args->type == SEARCH_SUB ||
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen args->type == SEARCH_OR ||
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen args->type == SEARCH_INTHREAD) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (mail_search_args_simplify_sub(box, args->value.subargs,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen args->type != SEARCH_OR))
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ctx.removals = TRUE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* try to merge arguments */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen switch (args->type) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_FLAGS:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = mail_search_args_merge_flags(&ctx, args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen break;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_SEQSET:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_UIDSET:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = mail_search_args_merge_set(&ctx, args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen break;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_BEFORE:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_ON:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_SINCE:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = mail_search_args_merge_time(&ctx, args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen break;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_SMALLER:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen case SEARCH_LARGER:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = mail_search_args_merge_size(&ctx, args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen break;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen default:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen merged = FALSE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen break;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (merged) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen prev_arg->next = args->next;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen args = args->next;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ctx.removals = TRUE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen continue;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen prev_arg = args;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen args = args->next;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen hash_table_destroy(&ctx.prev_args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool_unref(&ctx.pool);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return ctx.removals;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainenstatic bool
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainenmail_search_args_unnest_inthreads(struct mail_search_args *args,
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen struct mail_search_arg **argp,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool parent_inthreads, bool parent_and)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mail_search_arg *arg, *thread_arg, *or_arg;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen bool child_inthreads = FALSE, non_inthreads = FALSE;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen for (arg = *argp; arg != NULL; arg = arg->next) {
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen switch (arg->type) {
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen case SEARCH_SUB:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen case SEARCH_OR:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!mail_search_args_unnest_inthreads(args,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &arg->value.subargs, parent_inthreads,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen arg->type != SEARCH_OR)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen arg->result = 1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen child_inthreads = TRUE;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen } else {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen arg->result = 0;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen non_inthreads = TRUE;
5539418f448cd9bb38fc085e654861479dd1130bTimo Sirainen }
5539418f448cd9bb38fc085e654861479dd1130bTimo Sirainen break;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen case SEARCH_INTHREAD:
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mail_search_args_unnest_inthreads(args,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen &arg->value.subargs, TRUE, TRUE)) {
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* children converted to SEARCH_INTHREADs */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen arg->type = SEARCH_SUB;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen args->have_inthreads = TRUE;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen arg->result = 1;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen child_inthreads = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen break;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen default:
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen arg->result = 0;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen non_inthreads = TRUE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen break;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (!parent_inthreads || !child_inthreads || !non_inthreads)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return FALSE;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* put all non-INTHREADs under a single INTHREAD */
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen thread_arg = p_new(args->pool, struct mail_search_arg, 1);
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen thread_arg->type = SEARCH_INTHREAD;
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen while (*argp != NULL) {
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen arg = *argp;
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen argp = &(*argp)->next;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (arg->result == 0) {
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* not an INTHREAD or a SUB/OR with only INTHREADs */
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen arg->next = thread_arg->value.subargs;
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen thread_arg->value.subargs = arg;
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen }
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen }
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen if (!parent_and) {
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen /* We want to OR the args */
2b9e49e4e65e3e2dca38f56971029a3051ccdb99Timo Sirainen or_arg = p_new(args->pool, struct mail_search_arg, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen or_arg->type = SEARCH_OR;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen or_arg->value.subargs = thread_arg->value.subargs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen thread_arg->value.subargs = or_arg;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen return TRUE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
e5fb952c6d49d3b6bff1746551566202e92947daTimo Sirainen
438f12d7a776da695019114884b48188d94613efTimo Sirainenvoid mail_search_args_simplify(struct mail_search_args *args)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen{
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen bool removals;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen args->simplified = TRUE;
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen removals = mail_search_args_simplify_sub(args->box, args->args, TRUE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mail_search_args_unnest_inthreads(args, &args->args,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen FALSE, TRUE)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* we may have added some extra SUBs that could be dropped */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_search_args_simplify_sub(args->box, args->args, TRUE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen }
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (removals)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_search_args_simplify_sub(args->box, args->args, TRUE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen}
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen