Mercurial > dovecot > core-2.2
view src/lib-storage/mail-search-build.c @ 18137:3009a1a6f6d5
global: freshen copyright
Robomatically:
git ls-files | xargs perl -p -i -e 's/(\d+)-201[0-4]/$1-2015/g;s/ (201[0-4]) Dovecot/ $1-2015 Dovecot/'
Happy 2015 everyone!
Signed-off-by: Phil Carmody <phil@dovecot.fi>
author | Phil Carmody <phil@dovecot.fi> |
---|---|
date | Mon, 05 Jan 2015 22:20:10 +0200 |
parents | 36c2611e053e |
children | 14bf136959bc |
line wrap: on
line source
/* Copyright (c) 2002-2015 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-register.h" #include "mail-search-parser.h" #include "mail-search-build.h" #include <stdlib.h> static int mail_search_build_list(struct mail_search_build_context *ctx, struct mail_search_arg **arg_r); struct mail_search_arg * mail_search_build_new(struct mail_search_build_context *ctx, enum mail_search_arg_type type) { struct mail_search_arg *arg; arg = p_new(ctx->pool, struct mail_search_arg, 1); arg->type = type; return arg; } struct mail_search_arg * mail_search_build_str(struct mail_search_build_context *ctx, enum mail_search_arg_type type) { struct mail_search_arg *sarg; const char *value; sarg = mail_search_build_new(ctx, type); if (mail_search_parse_string(ctx->parser, &value) < 0) return NULL; sarg->value.str = p_strdup(ctx->pool, value); return sarg; } static int mail_search_build_key_int(struct mail_search_build_context *ctx, struct mail_search_arg *parent, struct mail_search_arg **arg_r) { struct mail_search_arg *sarg; struct mail_search_arg *old_parent = ctx->parent; const char *key; const struct mail_search_register_arg *reg_arg; mail_search_register_fallback_t *fallback; int ret; ctx->parent = parent; if ((ret = mail_search_parse_key(ctx->parser, &key)) <= 0) return ret; if (strcmp(key, MAIL_SEARCH_PARSER_KEY_LIST) == 0) { if (mail_search_build_list(ctx, &sarg) < 0) return -1; if (sarg->value.subargs == NULL) { ctx->_error = "No search parameters inside list"; return -1; } ctx->parent = old_parent; *arg_r = sarg; return 1; } key = t_str_ucase(key); reg_arg = mail_search_register_find(ctx->reg, key); if (reg_arg != NULL) sarg = reg_arg->build(ctx); else if (mail_search_register_get_fallback(ctx->reg, &fallback)) sarg = fallback(ctx, key); else { sarg = NULL; ctx->_error = p_strconcat(ctx->pool, "Unknown argument ", key, NULL); } ctx->parent = old_parent; *arg_r = sarg; return sarg == NULL ? -1 : 1; } int mail_search_build_key(struct mail_search_build_context *ctx, struct mail_search_arg *parent, struct mail_search_arg **arg_r) { int ret; ret = mail_search_build_key_int(ctx, parent, arg_r); if (ret <= 0) { if (ret == 0) ctx->_error = "Missing argument"; return -1; } return 0; } static int mail_search_build_list(struct mail_search_build_context *ctx, struct mail_search_arg **arg_r) { struct mail_search_arg *sarg, **subargs; enum mail_search_arg_type cur_type = SEARCH_SUB; int ret; sarg = p_new(ctx->pool, struct mail_search_arg, 1); sarg->type = cur_type; subargs = &sarg->value.subargs; while ((ret = mail_search_build_key_int(ctx, sarg, subargs)) > 0) { if (cur_type == sarg->type) { /* expected type */ } else if (cur_type == SEARCH_SUB) { /* type changed. everything in this list must now belong to this type. */ cur_type = sarg->type; } else { ctx->_error = "Use parenthesis when mixing ANDs and ORs"; return -1; } subargs = &(*subargs)->next; sarg->type = SEARCH_SUB; } if (ret < 0) return -1; sarg->type = cur_type; *arg_r = sarg; return 0; } int mail_search_build(struct mail_search_register *reg, struct mail_search_parser *parser, const char **charset, struct mail_search_args **args_r, const char **error_r) { struct mail_search_build_context ctx; struct mail_search_args *args; struct mail_search_arg *root; const char *str; int ret; *args_r = NULL; *error_r = NULL; args = mail_search_build_init(); memset(&ctx, 0, sizeof(ctx)); ctx.pool = args->pool; ctx.reg = reg; ctx.parser = parser; ctx.charset = p_strdup(ctx.pool, *charset); ret = mail_search_build_list(&ctx, &root); if (!ctx.charset_checked && ret == 0) { /* make sure we give an error message if charset is invalid */ ret = mail_search_build_get_utf8(&ctx, "", &str); } if (ret < 0) { *error_r = ctx._error != NULL ? t_strdup(ctx._error) : t_strdup(mail_search_parser_get_error(parser)); if (ctx.unknown_charset) *charset = NULL; pool_unref(&args->pool); return -1; } if (root->type == SEARCH_SUB && !root->match_not) { /* simple SUB root */ args->args = root->value.subargs; } else { args->args = root; } *args_r = args; return 0; } struct mail_search_args *mail_search_build_init(void) { struct mail_search_args *args; pool_t pool; pool = pool_alloconly_create("mail search args", 4096); args = p_new(pool, struct mail_search_args, 1); args->pool = pool; args->refcount = 1; return args; } struct mail_search_arg * mail_search_build_add(struct mail_search_args *args, enum mail_search_arg_type type) { struct mail_search_arg *arg; arg = p_new(args->pool, struct mail_search_arg, 1); arg->type = type; arg->next = args->args; args->args = arg; return arg; } void mail_search_build_add_all(struct mail_search_args *args) { (void)mail_search_build_add(args, SEARCH_ALL); } void mail_search_build_add_seqset(struct mail_search_args *args, uint32_t seq1, uint32_t seq2) { struct mail_search_arg *arg; arg = mail_search_build_add(args, SEARCH_SEQSET); p_array_init(&arg->value.seqset, args->pool, 1); seq_range_array_add_range(&arg->value.seqset, seq1, seq2); } int mail_search_build_get_utf8(struct mail_search_build_context *ctx, const char *input, const char **output_r) { int ret; T_BEGIN { string_t *utf8 = t_str_new(128); enum charset_result result; if (charset_to_utf8_str(ctx->charset, NULL, input, utf8, &result) < 0) { /* unknown charset */ ctx->_error = "Unknown charset"; ctx->unknown_charset = TRUE; ret = -1; } else if (result != CHARSET_RET_OK) { /* invalid key */ ctx->_error = "Invalid search key"; ret = -1; } else { *output_r = p_strdup(ctx->pool, str_c(utf8)); ret = 0; } } T_END; ctx->charset_checked = TRUE; return ret; }