ARRAY_TYPE(imap_arg_list) * test_parse_imap_args(pool_t pool, const char *line, unsigned int linelen, const char **error_r) { struct imap_parser *imap_parser; struct istream *input; const struct imap_arg *args; ARRAY_TYPE(imap_arg_list) *dup_args; enum imap_parser_error fatal; int ret; input = i_stream_create_from_data(line, linelen); imap_parser = imap_parser_create(input, NULL, (size_t)-1); ret = imap_parser_finish_line(imap_parser, 0, IMAP_PARSE_FLAG_LITERAL8 | IMAP_PARSE_FLAG_LITERAL_TYPE | IMAP_PARSE_FLAG_ATOM_ALLCHARS | IMAP_PARSE_FLAG_MULTILINE_STR, &args); if (ret < 0) { dup_args = NULL; if (ret == -2) *error_r = "Missing data"; else { *error_r = t_strdup(imap_parser_get_error(imap_parser, &fatal)); } } else { dup_args = test_parse_imap_args_dup(pool, args); } imap_parser_unref(&imap_parser); i_stream_unref(&input); return dup_args; }
static int cmd_id(struct imap_client *client) { struct imap_client_cmd_id *id; enum imap_parser_flags parser_flags; const struct imap_arg *args; int ret; if (client->cmd_id == NULL) { client->cmd_id = id = i_new(struct imap_client_cmd_id, 1); id->parser = imap_parser_create(client->common.input, client->common.output, MAX_IMAP_LINE); parser_flags = IMAP_PARSE_FLAG_STOP_AT_LIST; } else {
static struct client_command_context * client_command_new(struct client *client) { struct client_command_context *cmd; cmd = client_command_alloc(client); if (client->free_parser != NULL) { cmd->parser = client->free_parser; client->free_parser = NULL; } else { cmd->parser = imap_parser_create(client->input, client->output, client->set->imap_max_line_length); } return cmd; }
bool cmd_append(struct client_command_context *cmd) { struct client *client = cmd->client; struct cmd_append_context *ctx; const char *mailbox; if (client->syncing) { /* if transaction is created while its view is synced, appends aren't allowed for it. */ cmd->state = CLIENT_COMMAND_STATE_WAIT_UNAMBIGUITY; return FALSE; } /* <mailbox> */ if (!client_read_string_args(cmd, 1, &mailbox)) return FALSE; /* we keep the input locked all the time */ client->input_lock = cmd; ctx = p_new(cmd->pool, struct cmd_append_context, 1); ctx->cmd = cmd; ctx->client = client; ctx->started = ioloop_time; if (client_open_save_dest_box(cmd, mailbox, &ctx->box) < 0) ctx->failed = TRUE; else { ctx->t = mailbox_transaction_begin(ctx->box, MAILBOX_TRANSACTION_FLAG_EXTERNAL | MAILBOX_TRANSACTION_FLAG_ASSIGN_UIDS); } io_remove(&client->io); client->io = io_add(i_stream_get_fd(client->input), IO_READ, client_input_append, cmd); /* append is special because we're only waiting on client input, not client output, so disable the standard output handler until we're finished */ o_stream_unset_flush_callback(client->output); ctx->save_parser = imap_parser_create(client->input, client->output, client->set->imap_max_line_length); cmd->func = cmd_append_parse_new_msg; cmd->context = ctx; return cmd_append_parse_new_msg(cmd); }
static bool cmd_setmetadata_start(struct imap_setmetadata_context *ctx) { struct client_command_context *cmd = ctx->cmd; struct client *client = cmd->client; /* we support large literals, so read the values from client asynchronously the same way as APPEND does. */ client->input_lock = cmd; ctx->parser = imap_parser_create(client->input, client->output, client->set->imap_max_line_length); o_stream_unset_flush_callback(client->output); cmd->func = cmd_setmetadata_continue; cmd->context = ctx; return cmd_setmetadata_continue(cmd); }
static void test_imap_parser_crlf(void) { static const char *test_input = "foo\r\nx\ry\n"; struct istream *input; struct imap_parser *parser; const struct imap_arg *args; unsigned int i; bool fatal; test_begin("imap parser crlf handling"); input = test_istream_create(test_input); parser = imap_parser_create(input, NULL, 1024); /* must return -2 until LF is read */ for (i = 0; test_input[i] != '\n'; i++) { test_istream_set_size(input, i+1); (void)i_stream_read(input); test_assert(imap_parser_read_args(parser, 0, 0, &args) == -2); } test_istream_set_size(input, i+1); (void)i_stream_read(input); test_assert(imap_parser_read_args(parser, 0, 0, &args) == 1); test_assert(args[0].type == IMAP_ARG_ATOM); test_assert(args[1].type == IMAP_ARG_EOL); /* CR without LF should fail with error */ imap_parser_reset(parser); i_stream_seek(input, ++i); test_istream_set_size(input, ++i); (void)i_stream_read(input); test_assert(imap_parser_read_args(parser, 0, 0, &args) == -2); test_istream_set_size(input, ++i); (void)i_stream_read(input); test_assert(imap_parser_read_args(parser, 0, 0, &args) == -2); test_istream_set_size(input, ++i); (void)i_stream_read(input); test_assert(imap_parser_read_args(parser, 0, 0, &args) == -1); test_assert(strcmp(imap_parser_get_error(parser, &fatal), "CR sent without LF") == 0 && !fatal); imap_parser_destroy(&parser); i_stream_destroy(&input); test_end(); }
static struct mail_search_args * virtual_search_args_parse(const string_t *rule, const char **error_r) { struct istream *input; struct imap_parser *imap_parser; const struct imap_arg *args; struct mail_search_parser *parser; struct mail_search_args *sargs; const char *charset = "UTF-8"; bool fatal; int ret; if (str_len(rule) == 0) { sargs = mail_search_build_init(); mail_search_build_add_all(sargs); return sargs; } input = i_stream_create_from_data(str_data(rule), str_len(rule)); (void)i_stream_read(input); imap_parser = imap_parser_create(input, NULL, (size_t)-1); ret = imap_parser_finish_line(imap_parser, 0, 0, &args); if (ret < 0) { sargs = NULL; *error_r = t_strdup(imap_parser_get_error(imap_parser, &fatal)); } else { parser = mail_search_parser_init_imap(args); if (mail_search_build(mail_search_register_get_imap(), parser, &charset, &sargs, error_r) < 0) sargs = NULL; mail_search_parser_deinit(&parser); } imap_parser_unref(&imap_parser); i_stream_destroy(&input); return sargs; }
const char *imap_id_reply_generate(const char *settings) { struct istream *input; struct imap_parser *parser; const struct imap_arg *args; const char *ret; if (settings == NULL) return "NIL"; input = i_stream_create_from_data(settings, strlen(settings)); (void)i_stream_read(input); parser = imap_parser_create(input, NULL, (size_t)-1); if (imap_parser_finish_line(parser, 0, 0, &args) <= 0) ret = "NIL"; else ret = imap_id_reply_generate_from_imap_args(args); imap_parser_unref(&parser); i_stream_destroy(&input); return ret; }
bool cmd_setmetadata(struct client_command_context *cmd) { struct imap_setmetadata_context *ctx; const struct imap_arg *args; const char *mailbox; struct mail_namespace *ns; int ret; ret = imap_parser_read_args(cmd->parser, 2, IMAP_PARSE_FLAG_STOP_AT_LIST, &args); if (ret == -1) { client_send_command_error(cmd, NULL); return TRUE; } if (ret == -2) return FALSE; if (!imap_arg_get_astring(&args[0], &mailbox) || args[1].type != IMAP_ARG_LIST) { client_send_command_error(cmd, "Invalid arguments."); return TRUE; } if (!cmd->client->imap_metadata_enabled) { client_send_command_error(cmd, "METADATA disabled."); return TRUE; } ctx = p_new(cmd->pool, struct imap_setmetadata_context, 1); ctx->cmd = cmd; ctx->cmd->context = ctx; if (mailbox[0] == '\0') { /* server attribute */ ctx->key_prefix = MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER; ns = mail_namespace_find_inbox(cmd->client->user->namespaces); mailbox = "INBOX"; } else { ns = client_find_namespace(cmd, &mailbox); if (ns == NULL) return TRUE; } if (cmd->client->mailbox != NULL && !cmd->client->mailbox_examined && mailbox_equals(cmd->client->mailbox, ns, mailbox)) ctx->box = cmd->client->mailbox; else { ctx->box = mailbox_alloc(ns->list, mailbox, 0); if (mailbox_open(ctx->box) < 0) { client_send_box_error(cmd, ctx->box); mailbox_free(&ctx->box); return TRUE; } } ctx->trans = mailbox_transaction_begin(ctx->box, 0); /* we support large literals, so read the values from client asynchronously the same way as APPEND does. */ cmd->client->input_lock = cmd; ctx->parser = imap_parser_create(cmd->client->input, cmd->client->output, cmd->client->set->imap_max_line_length); o_stream_unset_flush_callback(cmd->client->output); cmd->func = cmd_setmetadata_continue; cmd->context = ctx; return cmd_setmetadata_continue(cmd); }