mail-search-register-human.c revision d81bbb6948b4d758e87206acb8da4cc4366fd478
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher/* Copyright (c) 2010-2015 Dovecot authors, see the included COPYING file */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "lib.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "ioloop.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "array.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "str.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "unichar.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "settings-parser.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "mail-storage.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "mail-search-register.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "mail-search-parser.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include "mail-search-build.h"
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher#include <time.h>
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher#include <ctype.h>
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagherstruct mail_search_register *mail_search_register_human;
33396dc46ea52c18f47db1b5d590880806521005Sumit Bose
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherhuman_search_or(struct mail_search_build_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher struct mail_search_arg *sarg;
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher /* this changes the parent arg to be an OR block instead of AND block */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->parent->type = SEARCH_OR;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_search_build_key(ctx, ctx->parent, &sarg) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return sarg;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherarg_new_human_date(struct mail_search_build_context *ctx,
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher enum mail_search_arg_type type,
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher enum mail_search_date_type date_type)
ee359fe1384507fed6c2274e7bfe81d288de4542Stephen Gallagher{
cc98edd9479d4622634a1275c98058916c14059aStephen Gallagher struct mail_search_arg *sarg;
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher const char *value;
1183d29d87c5c7439cf2364b7d7324d4a13b6e35Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sarg = mail_search_build_new(ctx, type);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_search_parse_string(ctx->parser, &value) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_parse_human_timestamp(value, &sarg->value.time) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sarg->value.time = (time_t)-1;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sarg->value.search_flags = MAIL_SEARCH_ARG_FLAG_USE_TZ;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (sarg->value.time == (time_t)-1) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->_error = p_strconcat(ctx->pool,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher "Invalid search date parameter: ", value, NULL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce }
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce sarg->value.date_type = date_type;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce return sarg;
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce}
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce
c89589fa349f38214c9cb8d9389c0fd557e5dca2Simo Sorce#define CALLBACK_DATE(_func, _type, _date_type) \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *\
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherhuman_search_##_func(struct mail_search_build_context *ctx) \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{ \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return arg_new_human_date(ctx, _type, _date_type); \
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen GallagherCALLBACK_DATE(before, SEARCH_BEFORE, MAIL_SEARCH_DATE_TYPE_RECEIVED)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen GallagherCALLBACK_DATE(on, SEARCH_ON, MAIL_SEARCH_DATE_TYPE_RECEIVED)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen GallagherCALLBACK_DATE(since, SEARCH_SINCE, MAIL_SEARCH_DATE_TYPE_RECEIVED)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen GallagherCALLBACK_DATE(sentbefore, SEARCH_BEFORE, MAIL_SEARCH_DATE_TYPE_SENT)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen GallagherCALLBACK_DATE(senton, SEARCH_ON, MAIL_SEARCH_DATE_TYPE_SENT)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen GallagherCALLBACK_DATE(sentsince, SEARCH_SINCE, MAIL_SEARCH_DATE_TYPE_SENT)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
d921c1eba437662437847279f251a0a5d8f70127MaximCALLBACK_DATE(savedbefore, SEARCH_BEFORE, MAIL_SEARCH_DATE_TYPE_SAVED)
d921c1eba437662437847279f251a0a5d8f70127MaximCALLBACK_DATE(savedon, SEARCH_ON, MAIL_SEARCH_DATE_TYPE_SAVED)
d921c1eba437662437847279f251a0a5d8f70127MaximCALLBACK_DATE(savedsince, SEARCH_SINCE, MAIL_SEARCH_DATE_TYPE_SAVED)
d921c1eba437662437847279f251a0a5d8f70127Maxim
d921c1eba437662437847279f251a0a5d8f70127Maximstatic struct mail_search_arg *
d921c1eba437662437847279f251a0a5d8f70127Maximarg_new_human_size(struct mail_search_build_context *ctx,
d921c1eba437662437847279f251a0a5d8f70127Maxim enum mail_search_arg_type type)
327127bb7fcc07f882209f029e14026de1b23c94Maxim{
327127bb7fcc07f882209f029e14026de1b23c94Maxim struct mail_search_arg *sarg;
327127bb7fcc07f882209f029e14026de1b23c94Maxim const char *value, *error;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sarg = mail_search_build_new(ctx, type);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_search_parse_string(ctx->parser, &value) < 0)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (settings_get_size(value, &sarg->value.size, &error) < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->_error = p_strdup(ctx->pool, error);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return sarg;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherhuman_search_larger(struct mail_search_build_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return arg_new_human_size(ctx, SEARCH_LARGER);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherhuman_search_smaller(struct mail_search_build_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return arg_new_human_size(ctx, SEARCH_SMALLER);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherhuman_search_guid(struct mail_search_build_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mail_search_build_str(ctx, SEARCH_GUID);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherhuman_search_mailbox(struct mail_search_build_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher struct mail_search_arg *sarg;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sarg = mail_search_build_str(ctx, SEARCH_MAILBOX);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (sarg == NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return NULL;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (strchr(sarg->value.str, '*') != NULL ||
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher strchr(sarg->value.str, '%') != NULL)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher sarg->type = SEARCH_MAILBOX_GLOB;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (!uni_utf8_str_is_valid(sarg->value.str)) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->_error = p_strconcat(ctx->pool,
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek "Mailbox name not valid UTF-8: ",
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek sarg->value.str, NULL);
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek return NULL;
e6e26182d58c05d896f72f2925426658a6dc70b5Jakub Hrozek }
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek return sarg;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherhuman_search_mailbox_guid(struct mail_search_build_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mail_search_build_str(ctx, SEARCH_MAILBOX_GUID);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_arg *
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherhuman_search_oldestonly(struct mail_search_build_context *ctx)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher{
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ctx->args->stop_on_nonmatch = TRUE;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher return mail_search_build_new(ctx, SEARCH_ALL);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher}
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic const struct mail_search_register_arg human_register_args[] = {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "OR", human_search_or },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* dates */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "BEFORE", human_search_before },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "ON", human_search_on },
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek { "SINCE", human_search_since },
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek { "SENTBEFORE", human_search_sentbefore },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "SENTON", human_search_senton },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "SENTSINCE", human_search_sentsince },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "SAVEDBEFORE", human_search_savedbefore },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "SAVEDON", human_search_savedon },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "SAVEDSINCE", human_search_savedsince },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "X-SAVEDBEFORE", human_search_savedbefore },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "X-SAVEDON", human_search_savedon },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "X-SAVEDSINCE", human_search_savedsince },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* sizes */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "LARGER", human_search_larger },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "SMALLER", human_search_smaller },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* Other Dovecot extensions: */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "GUID", human_search_guid },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "MAILBOX", human_search_mailbox },
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher { "MAILBOX-GUID", human_search_mailbox_guid },
5352c9b3609bca63814f9f6f03dbbbadf6c6333aStephen Gallagher { "OLDESTONLY", human_search_oldestonly }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher};
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagherstatic struct mail_search_register *
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozekmail_search_register_init_human(struct mail_search_register *imap_register)
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek{
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek struct mail_search_register *reg;
2a5790216f57e9bdfb2930d52860bb5300366536Jakub Hrozek mail_search_register_fallback_t *fallback;
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek ARRAY(struct mail_search_register_arg) copy_args;
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek const struct mail_search_register_arg *human_args, *imap_args;
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek unsigned int i, j, human_count, imap_count;
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek int ret;
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek reg = mail_search_register_init();
172c07013d1ea99447a780fd36f49d5c3a76981bJakub Hrozek mail_search_register_add(reg, human_register_args,
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher N_ELEMENTS(human_register_args));
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher /* find and register args in imap that don't exist in human */
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher imap_args = mail_search_register_get(imap_register, &imap_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher human_args = mail_search_register_get(reg, &human_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher t_array_init(&copy_args, imap_count);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (i = j = 0; i < imap_count && j < human_count; ) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher ret = strcmp(imap_args[i].key, human_args[j].key);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (ret < 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append(&copy_args, &imap_args[i], 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else if (ret > 0) {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher j++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher } else {
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher i++; j++;
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher }
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher for (; i < imap_count; i++)
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher array_append(&copy_args, &imap_args[i], 1);
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher
96c73559adfbdac96720008fc022cb1d540b53c3Jakub Hrozek imap_args = array_get(&copy_args, &imap_count);
6f51c802311fd81a409a26763ed45b28a3234d0dJakub Hrozek mail_search_register_add(reg, imap_args, imap_count);
84ae5edab16ad6be5e3be956cb6fa031c1428eb5Stephen Gallagher
551aa6c36797ed720487f5974dcadabf19e6ff9fStephen Gallagher if (mail_search_register_get_fallback(imap_register, &fallback))
mail_search_register_fallback(reg, fallback);
return reg;
}
struct mail_search_register *mail_search_register_get_human(void)
{
if (mail_search_register_human == NULL) {
struct mail_search_register *imap_reg =
mail_search_register_get_imap();
mail_search_register_human =
mail_search_register_init_human(imap_reg);
}
return mail_search_register_human;
}