Mercurial > dovecot > original-hg > dovecot-1.2
changeset 5277:be3d55491b37 HEAD
When using MULTIAPPEND and LITERAL+ and message saving failed, we stopped
parsing client input too early (for subsequent appends after the failure)
which caused BAD replies.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 11 Mar 2007 18:02:23 +0200 |
parents | 56535cb50a09 |
children | d569caa88a66 |
files | src/imap/cmd-append.c |
diffstat | 1 files changed, 27 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-append.c Sun Mar 11 01:47:05 2007 +0200 +++ b/src/imap/cmd-append.c Sun Mar 11 18:02:23 2007 +0200 @@ -27,10 +27,12 @@ struct mailbox_keywords old_keywords; unsigned int message_input:1; + unsigned int failed:1; }; static void cmd_append_finish(struct cmd_append_context *ctx); static bool cmd_append_continue_message(struct client_command_context *cmd); +static bool cmd_append_continue_parsing(struct client_command_context *cmd); static void client_input(struct client_command_context *cmd) { @@ -145,11 +147,23 @@ (void)i_stream_get_data(ctx->input, &size); i_stream_skip(ctx->input, size); - if (ctx->input->v_offset == ctx->msg_size || - cmd->client->input->closed) { + if (cmd->client->input->closed) { cmd_append_finish(ctx); return TRUE; } + + if (ctx->input->v_offset == ctx->msg_size) { + /* finished, but with MULTIAPPEND and LITERAL+ we may get + more messages. */ + i_stream_unref(&ctx->input); + ctx->input = NULL; + + ctx->message_input = FALSE; + imap_parser_reset(ctx->save_parser); + cmd->func = cmd_append_continue_parsing; + return cmd_append_continue_parsing(cmd); + } + return FALSE; } @@ -198,7 +212,7 @@ ret = imap_parser_read_args(ctx->save_parser, 0, IMAP_PARSE_FLAG_LITERAL_SIZE, &args); if (ret == -1) { - if (ctx->box != NULL) + if (!ctx->failed) client_send_command_error(cmd, NULL); cmd_append_finish(ctx); return TRUE; @@ -215,7 +229,7 @@ /* eat away the trailing CRLF */ client->input_skip_line = TRUE; - if (ctx->box == NULL) { + if (ctx->failed) { /* we failed earlier, error message is sent */ cmd_append_finish(ctx); return TRUE; @@ -241,7 +255,7 @@ return cmd_append_cancel(ctx, nonsync); } - if (ctx->box == NULL) { + if (ctx->failed) { /* we failed earlier, make sure we just eat nonsync-literal if it's given. */ return cmd_append_cancel(ctx, nonsync); @@ -311,7 +325,6 @@ struct client *client = cmd->client; struct cmd_append_context *ctx = cmd->context; size_t size; - bool failed; int ret; if (cmd->cancel) { @@ -349,21 +362,19 @@ if (ctx->save_ctx == NULL) { /* failed above */ client_send_storage_error(cmd, ctx->storage); - failed = TRUE; + ctx->failed = TRUE; } else if (!all_written) { /* client disconnected before it finished sending the whole message. */ - failed = TRUE; + ctx->failed = TRUE; mailbox_save_cancel(&ctx->save_ctx); } else if (mailbox_save_finish(&ctx->save_ctx) < 0) { - failed = TRUE; + ctx->failed = TRUE; client_send_storage_error(cmd, ctx->storage); - } else { - failed = client->input->closed; } ctx->save_ctx = NULL; - if (failed) { + if (client->input->closed) { cmd_append_finish(ctx); return TRUE; } @@ -445,12 +456,15 @@ ctx->cmd = cmd; ctx->client = client; ctx->box = get_mailbox(cmd, mailbox); - if (ctx->box != NULL) { + if (ctx->box == NULL) + ctx->failed = TRUE; + else { ctx->storage = mailbox_get_storage(ctx->box); if (get_keywords(ctx) < 0) { client_send_storage_error(cmd, ctx->storage); mailbox_close(&ctx->box); + ctx->failed = TRUE; } else { ctx->t = mailbox_transaction_begin(ctx->box, MAILBOX_TRANSACTION_FLAG_EXTERNAL);