bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen#include "lib.h"
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen#include "imap-arg.h"
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen#include "mail-search-parser-private.h"
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstruct imap_arg_stack {
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen struct imap_arg_stack *prev;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen const struct imap_arg *args;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen};
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstruct imap_mail_search_parser {
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen struct mail_search_parser parser;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen struct imap_arg_stack root, *cur;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen};
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstatic int imap_search_parse_key(struct mail_search_parser *_parser,
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen const char **key_r)
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen{
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen struct imap_mail_search_parser *parser =
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen (struct imap_mail_search_parser *)_parser;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen const struct imap_arg *arg = parser->cur->args;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen struct imap_arg_stack *stack;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen switch (arg->type) {
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_NIL:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_ATOM:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen *key_r = imap_arg_as_astring(arg);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen break;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_STRING:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_LITERAL:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen _parser->error = t_strconcat(
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen "Unexpected string as search key: ",
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen imap_arg_as_astring(arg), NULL);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return -1;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_LIST:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen stack = p_new(_parser->pool, struct imap_arg_stack, 1);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen stack->prev = parser->cur;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen stack->args = imap_arg_as_list(arg);
2ed75e0243a9845eb4f92436ff6016906a3189e4Timo Sirainen
2ed75e0243a9845eb4f92436ff6016906a3189e4Timo Sirainen parser->cur->args++;
2ed75e0243a9845eb4f92436ff6016906a3189e4Timo Sirainen parser->cur = stack;
2ed75e0243a9845eb4f92436ff6016906a3189e4Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen *key_r = MAIL_SEARCH_PARSER_KEY_LIST;
2ed75e0243a9845eb4f92436ff6016906a3189e4Timo Sirainen return 1;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_EOL:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser->cur = parser->cur->prev;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return 0;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_LITERAL_SIZE:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_LITERAL_SIZE_NONSYNC:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen i_unreached();
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen }
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser->cur->args++;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return 1;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen}
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstatic int imap_search_parse_string(struct mail_search_parser *_parser,
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen const char **value_r)
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen{
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen struct imap_mail_search_parser *parser =
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen (struct imap_mail_search_parser *)_parser;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen const struct imap_arg *arg = parser->cur->args;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen switch (arg->type) {
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_NIL:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_ATOM:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_STRING:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_LITERAL:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen *value_r = imap_arg_as_astring(arg);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen break;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_LIST:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen _parser->error = "Unexpected (";
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return -1;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_EOL:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen _parser->error = "Missing parameter for search key";
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return -1;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_LITERAL_SIZE:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen case IMAP_ARG_LITERAL_SIZE_NONSYNC:
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen i_unreached();
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen }
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser->cur->args++;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return 1;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen}
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstatic bool
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenimap_search_parse_skip_next(struct mail_search_parser *_parser, const char *str)
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen{
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen struct imap_mail_search_parser *parser =
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen (struct imap_mail_search_parser *)_parser;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen const char *arg;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen if (!imap_arg_get_astring(parser->cur->args, &arg))
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return FALSE;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen if (strcasecmp(arg, str) != 0)
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return FALSE;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser->cur->args++;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return TRUE;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen}
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstatic const struct mail_search_parser_vfuncs mail_search_parser_imap_vfuncs = {
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen imap_search_parse_key,
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen imap_search_parse_string,
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen imap_search_parse_skip_next
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen};
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenstruct mail_search_parser *
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainenmail_search_parser_init_imap(const struct imap_arg *args)
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen{
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen struct imap_mail_search_parser *parser;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen pool_t pool;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen pool = pool_alloconly_create("imap search parser", 1024);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser = p_new(pool, struct imap_mail_search_parser, 1);
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser->parser.pool = pool;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser->parser.v = mail_search_parser_imap_vfuncs;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser->root.args = args;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen parser->cur = &parser->root;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen return &parser->parser;
5c2d695acf9f95ae0dcdda89c4d2391ceda4d672Timo Sirainen}