[dovecot-cvs] dovecot/src/imap cmd-append.c,1.91,1.92

tss at dovecot.org tss at dovecot.org
Sun Mar 11 18:02:25 EET 2007


Update of /var/lib/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv4384

Modified Files:
	cmd-append.c 
Log Message:
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.



Index: cmd-append.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/cmd-append.c,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- cmd-append.c	1 Mar 2007 11:15:26 -0000	1.91
+++ cmd-append.c	11 Mar 2007 16:02:23 -0000	1.92
@@ -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);



More information about the dovecot-cvs mailing list