diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 09:51:24 +0000 |
commit | f7548d6d28c313cf80e6f3ef89aed16a19815df1 (patch) | |
tree | a3f6f2a3f247293bee59ecd28e8cd8ceb6ca064a /src/lib-storage/mail-search-mime-build.c | |
parent | Initial commit. (diff) | |
download | dovecot-upstream.tar.xz dovecot-upstream.zip |
Adding upstream version 1:2.3.19.1+dfsg1.upstream/1%2.3.19.1+dfsg1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib-storage/mail-search-mime-build.c')
-rw-r--r-- | src/lib-storage/mail-search-mime-build.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/lib-storage/mail-search-mime-build.c b/src/lib-storage/mail-search-mime-build.c new file mode 100644 index 0000000..cdec68f --- /dev/null +++ b/src/lib-storage/mail-search-mime-build.c @@ -0,0 +1,173 @@ +/* Copyright (c) 2016-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "str.h" +#include "charset-utf8.h" +#include "mail-storage-private.h" +#include "mail-search-parser.h" +#include "mail-search-mime-register.h" +#include "mail-search-mime-build.h" + +static int mail_search_mime_build_list(struct mail_search_mime_build_context *ctx, + struct mail_search_mime_arg **arg_r); + +struct mail_search_mime_arg * +mail_search_mime_build_new(struct mail_search_mime_build_context *ctx, + enum mail_search_mime_arg_type type) +{ + struct mail_search_mime_arg *arg; + + arg = p_new(ctx->ctx->pool, struct mail_search_mime_arg, 1); + arg->type = type; + return arg; +} + +struct mail_search_mime_arg * +mail_search_mime_build_str(struct mail_search_mime_build_context *ctx, + enum mail_search_mime_arg_type type) +{ + struct mail_search_mime_arg *sarg; + const char *value; + + sarg = mail_search_mime_build_new(ctx, type); + if (mail_search_parse_string(ctx->ctx->parser, &value) < 0) + return NULL; + sarg->value.str = p_strdup(ctx->ctx->pool, value); + return sarg; +} + +static int +mail_search_mime_build_key_int(struct mail_search_mime_build_context *ctx, + struct mail_search_mime_arg *parent, + struct mail_search_mime_arg **arg_r) +{ + struct mail_search_mime_arg *sarg; + struct mail_search_mime_arg *old_parent = ctx->parent; + const char *key; + const struct mail_search_mime_register_arg *reg_arg; + int ret; + + ctx->parent = parent; + + if ((ret = mail_search_parse_key(ctx->ctx->parser, &key)) <= 0) + return ret; + + if (strcmp(key, MAIL_SEARCH_PARSER_KEY_LIST) == 0) { + if (mail_search_mime_build_list(ctx, &sarg) < 0) + return -1; + if (sarg->value.subargs == NULL) { + ctx->ctx->_error = "No MIMEPART keys inside list"; + return -1; + } + + ctx->parent = old_parent; + *arg_r = sarg; + return 1; + } + key = t_str_ucase(key); + + reg_arg = mail_search_mime_register_find(key); + if (reg_arg != NULL) + sarg = reg_arg->build(ctx); + else { + sarg = NULL; + ctx->ctx->_error = p_strconcat + (ctx->ctx->pool, "Unknown MIMEPART key ", key, NULL); + } + + ctx->parent = old_parent; + *arg_r = sarg; + return sarg == NULL ? -1 : 1; +} + +int mail_search_mime_build_key(struct mail_search_mime_build_context *ctx, + struct mail_search_mime_arg *parent, + struct mail_search_mime_arg **arg_r) +{ + int ret; + + ret = mail_search_mime_build_key_int(ctx, parent, arg_r); + if (ret <= 0) { + if (ret == 0) + ctx->ctx->_error = "Missing MIMEPART key"; + return -1; + } + return 0; +} + +static int mail_search_mime_build_list(struct mail_search_mime_build_context *ctx, + struct mail_search_mime_arg **arg_r) +{ + struct mail_search_mime_arg *sarg, **subargs; + enum mail_search_mime_arg_type cur_type = SEARCH_MIME_SUB; + int ret; + + sarg = p_new(ctx->ctx->pool, struct mail_search_mime_arg, 1); + sarg->type = cur_type; + + subargs = &sarg->value.subargs; + while ((ret = mail_search_mime_build_key_int(ctx, sarg, subargs)) > 0) { + if (cur_type == sarg->type) { + /* expected type */ + } else if (cur_type == SEARCH_MIME_SUB) { + /* type changed. everything in this list must now + belong to this type. */ + cur_type = sarg->type; + } else { + ctx->ctx->_error = + "Use parenthesis when mixing ANDs and ORs"; + return -1; + } + subargs = &(*subargs)->next; + sarg->type = SEARCH_MIME_SUB; + } + if (ret < 0) + return -1; + sarg->type = cur_type; + *arg_r = sarg; + return 0; +} + +int mail_search_mime_build(struct mail_search_build_context *bctx, + struct mail_search_mime_part **mpart_r) +{ + struct mail_search_mime_build_context ctx; + struct mail_search_mime_part *mpart; + struct mail_search_mime_arg *root; + int ret; + + *mpart_r = NULL; + + i_zero(&ctx); + ctx.ctx = bctx; + ctx.mime_part = mpart = + p_new(bctx->pool, struct mail_search_mime_part, 1); + + if ((ret=mail_search_mime_build_key(&ctx, NULL, &root)) < 0) + return ret; + + if (root->type == SEARCH_MIME_SUB && !root->match_not) { + /* simple SUB root */ + mpart->args = root->value.subargs; + } else { + mpart->args = root; + } + + *mpart_r = mpart; + return 0; +} + +struct mail_search_mime_arg * +mail_search_mime_build_add(pool_t pool, + struct mail_search_mime_part *mpart, + enum mail_search_mime_arg_type type) +{ + struct mail_search_mime_arg *arg; + + arg = p_new(pool, struct mail_search_mime_arg, 1); + arg->type = type; + + arg->next = mpart->args; + mpart->args = arg; + return arg; +} |