diff options
Diffstat (limited to 'src/lib-storage/mail-search-parser-imap.c')
-rw-r--r-- | src/lib-storage/mail-search-parser-imap.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/lib-storage/mail-search-parser-imap.c b/src/lib-storage/mail-search-parser-imap.c new file mode 100644 index 0000000..12f48b3 --- /dev/null +++ b/src/lib-storage/mail-search-parser-imap.c @@ -0,0 +1,122 @@ +/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "imap-arg.h" +#include "mail-search-parser-private.h" + +struct imap_arg_stack { + struct imap_arg_stack *prev; + + const struct imap_arg *args; +}; + +struct imap_mail_search_parser { + struct mail_search_parser parser; + + struct imap_arg_stack root, *cur; +}; + +static int imap_search_parse_key(struct mail_search_parser *_parser, + const char **key_r) +{ + struct imap_mail_search_parser *parser = + (struct imap_mail_search_parser *)_parser; + const struct imap_arg *arg = parser->cur->args; + struct imap_arg_stack *stack; + + switch (arg->type) { + case IMAP_ARG_NIL: + case IMAP_ARG_ATOM: + *key_r = imap_arg_as_astring(arg); + break; + case IMAP_ARG_STRING: + case IMAP_ARG_LITERAL: + _parser->error = t_strconcat( + "Unexpected string as search key: ", + imap_arg_as_astring(arg), NULL); + return -1; + case IMAP_ARG_LIST: + stack = p_new(_parser->pool, struct imap_arg_stack, 1); + stack->prev = parser->cur; + stack->args = imap_arg_as_list(arg); + + parser->cur->args++; + parser->cur = stack; + + *key_r = MAIL_SEARCH_PARSER_KEY_LIST; + return 1; + case IMAP_ARG_EOL: + parser->cur = parser->cur->prev; + return 0; + case IMAP_ARG_LITERAL_SIZE: + case IMAP_ARG_LITERAL_SIZE_NONSYNC: + i_unreached(); + } + parser->cur->args++; + return 1; +} + +static int imap_search_parse_string(struct mail_search_parser *_parser, + const char **value_r) +{ + struct imap_mail_search_parser *parser = + (struct imap_mail_search_parser *)_parser; + const struct imap_arg *arg = parser->cur->args; + + switch (arg->type) { + case IMAP_ARG_NIL: + case IMAP_ARG_ATOM: + case IMAP_ARG_STRING: + case IMAP_ARG_LITERAL: + *value_r = imap_arg_as_astring(arg); + break; + case IMAP_ARG_LIST: + _parser->error = "Unexpected ("; + return -1; + case IMAP_ARG_EOL: + _parser->error = "Missing parameter for search key"; + return -1; + case IMAP_ARG_LITERAL_SIZE: + case IMAP_ARG_LITERAL_SIZE_NONSYNC: + i_unreached(); + } + parser->cur->args++; + return 1; +} + +static bool +imap_search_parse_skip_next(struct mail_search_parser *_parser, const char *str) +{ + struct imap_mail_search_parser *parser = + (struct imap_mail_search_parser *)_parser; + const char *arg; + + if (!imap_arg_get_astring(parser->cur->args, &arg)) + return FALSE; + if (strcasecmp(arg, str) != 0) + return FALSE; + + parser->cur->args++; + return TRUE; +} + +static const struct mail_search_parser_vfuncs mail_search_parser_imap_vfuncs = { + imap_search_parse_key, + imap_search_parse_string, + imap_search_parse_skip_next +}; + +struct mail_search_parser * +mail_search_parser_init_imap(const struct imap_arg *args) +{ + struct imap_mail_search_parser *parser; + pool_t pool; + + pool = pool_alloconly_create("imap search parser", 1024); + parser = p_new(pool, struct imap_mail_search_parser, 1); + parser->parser.pool = pool; + parser->parser.v = mail_search_parser_imap_vfuncs; + parser->root.args = args; + parser->cur = &parser->root; + return &parser->parser; +} |