mail-search-mime-build.c revision 74bc7e646663255703e10e0c0b7242ad7ad52f94
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch/* Copyright (c) 2016-2017 Dovecot authors, see the included COPYING file */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "lib.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "str.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "charset-utf8.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "mail-storage-private.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "mail-search-parser.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "mail-search-mime-register.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch#include "mail-search-mime-build.h"
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int mail_search_mime_build_list(struct mail_search_mime_build_context *ctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg **arg_r);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstruct mail_search_mime_arg *
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschmail_search_mime_build_new(struct mail_search_mime_build_context *ctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch enum mail_search_mime_arg_type type)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *arg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg = p_new(ctx->ctx->pool, struct mail_search_mime_arg, 1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->type = type;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return arg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstruct mail_search_mime_arg *
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschmail_search_mime_build_str(struct mail_search_mime_build_context *ctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch enum mail_search_mime_arg_type type)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *sarg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *value;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sarg = mail_search_mime_build_new(ctx, type);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (mail_search_parse_string(ctx->ctx->parser, &value) < 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return NULL;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sarg->value.str = p_strdup(ctx->ctx->pool, value);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return sarg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschmail_search_mime_build_key_int(struct mail_search_mime_build_context *ctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *parent,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg **arg_r)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *sarg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *old_parent = ctx->parent;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const char *key;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch const struct mail_search_mime_register_arg *reg_arg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx->parent = parent;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if ((ret = mail_search_parse_key(ctx->ctx->parser, &key)) <= 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (strcmp(key, MAIL_SEARCH_PARSER_KEY_LIST) == 0) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (mail_search_mime_build_list(ctx, &sarg) < 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (sarg->value.subargs == NULL) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx->ctx->_error = "No MIMEPART keys inside list";
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx->parent = old_parent;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch *arg_r = sarg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch key = t_str_ucase(key);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch reg_arg = mail_search_mime_register_find(key);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (reg_arg != NULL)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sarg = reg_arg->build(ctx);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch else {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sarg = NULL;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx->ctx->_error = p_strconcat
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch (ctx->ctx->pool, "Unknown MIMEPART key ", key, NULL);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx->parent = old_parent;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch *arg_r = sarg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return sarg == NULL ? -1 : 1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschint mail_search_mime_build_key(struct mail_search_mime_build_context *ctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *parent,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg **arg_r)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ret = mail_search_mime_build_key_int(ctx, parent, arg_r);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (ret <= 0) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (ret == 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx->ctx->_error = "Missing MIMEPART key";
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstatic int mail_search_mime_build_list(struct mail_search_mime_build_context *ctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg **arg_r)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *sarg, **subargs;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch enum mail_search_mime_arg_type cur_type = SEARCH_MIME_SUB;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sarg = p_new(ctx->ctx->pool, struct mail_search_mime_arg, 1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sarg->type = cur_type;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch subargs = &sarg->value.subargs;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch while ((ret = mail_search_mime_build_key_int(ctx, sarg, subargs)) > 0) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (cur_type == sarg->type) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* expected type */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch } else if (cur_type == SEARCH_MIME_SUB) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* type changed. everything in this list must now
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch belong to this type. */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch cur_type = sarg->type;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch } else {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx->ctx->_error =
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch "Use parenthesis when mixing ANDs and ORs";
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch subargs = &(*subargs)->next;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sarg->type = SEARCH_MIME_SUB;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (ret < 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return -1;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch sarg->type = cur_type;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch *arg_r = sarg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschint mail_search_mime_build(struct mail_search_build_context *bctx,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_part **mpart_r)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_build_context ctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_part *mpart;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *root;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch int ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch *mpart_r = NULL;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch i_zero(&ctx);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx.ctx = bctx;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch ctx.mime_part = mpart =
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch p_new(bctx->pool, struct mail_search_mime_part, 1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if ((ret=mail_search_mime_build_key(&ctx, NULL, &root)) < 0)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return ret;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch if (root->type == SEARCH_MIME_SUB && !root->match_not) {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch /* simple SUB root */
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpart->args = root->value.subargs;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch } else {
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpart->args = root;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch }
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch *mpart_r = mpart;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return 0;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschstruct mail_search_mime_arg *
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Boschmail_search_mime_build_add(pool_t pool,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_part *mpart,
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch enum mail_search_mime_arg_type type)
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch{
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch struct mail_search_mime_arg *arg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg = p_new(pool, struct mail_search_mime_arg, 1);
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->type = type;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch arg->next = mpart->args;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch mpart->args = arg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch return arg;
74bc7e646663255703e10e0c0b7242ad7ad52f94Stephan Bosch}