dovecot-2.2: imap: Code cleanup and error handling fixes for CAT...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Jun 2 19:39:43 EEST 2012
details: http://hg.dovecot.org/dovecot-2.2/rev/848be27099c8
changeset: 14595:848be27099c8
user: Timo Sirainen <tss at iki.fi>
date: Sat Jun 02 19:39:27 2012 +0300
description:
imap: Code cleanup and error handling fixes for CATENATE
diffstat:
src/imap/cmd-append.c | 238 ++++++++++++++++++++++++++-----------------------
1 files changed, 125 insertions(+), 113 deletions(-)
diffs (truncated from 303 to 300 lines):
diff -r 27c8a6c9088d -r 848be27099c8 src/imap/cmd-append.c
--- a/src/imap/cmd-append.c Sat Jun 02 19:01:25 2012 +0300
+++ b/src/imap/cmd-append.c Sat Jun 02 19:39:27 2012 +0300
@@ -6,6 +6,7 @@
#include "istream-chain.h"
#include "ostream.h"
#include "str.h"
+#include "mail-storage-private.h"
#include "imap-parser.h"
#include "imap-date.h"
#include "imap-util.h"
@@ -196,18 +197,116 @@
}
static int
+cmd_append_catenate_url(struct client_command_context *cmd, const char *caturl)
+{
+ struct cmd_append_context *ctx = cmd->context;
+ struct imap_msgpart_url *mpurl;
+ struct istream *input;
+ uoff_t size, newsize;
+ const char *error;
+ int ret;
+
+ ret = imap_msgpart_url_parse(cmd->client->user, cmd->client->mailbox,
+ caturl, &mpurl, &error);
+ if (ret < 0) {
+ client_send_storage_error(cmd, ctx->storage);
+ return -1;
+ }
+ if (ret == 0) {
+ /* invalid url, abort */
+ client_send_tagline(cmd,
+ t_strdup_printf("NO [BADURL %s] %s.", caturl, error));
+ return -1;
+ }
+
+ /* catenate URL */
+ ret = imap_msgpart_url_read_part(mpurl, &input, &size, &error);
+ if (ret < 0) {
+ client_send_storage_error(cmd, ctx->storage);
+ return -1;
+ }
+ if (ret == 0) {
+ /* invalid url, abort */
+ client_send_tagline(cmd,
+ t_strdup_printf("NO [BADURL %s] %s.", caturl, error));
+ return -1;
+ }
+ if (size == 0) {
+ /* empty input */
+ imap_msgpart_url_free(&mpurl);
+ return 0;
+ }
+
+ newsize = ctx->cat_msg_size + size;
+ if (newsize < ctx->cat_msg_size) {
+ client_send_tagline(cmd,
+ "NO [TOOBIG] Composed message grows too big.");
+ imap_msgpart_url_free(&mpurl);
+ return -1;
+ }
+
+ ctx->cat_msg_size = newsize;
+ /* add this input stream to chain */
+ i_stream_chain_append(ctx->catchain, input);
+ input = NULL;
+ /* save by reading the chain stream */
+ while (!i_stream_is_eof(ctx->input)) {
+ ret = i_stream_read(ctx->input);
+ i_assert(ret != 0); /* we can handle only blocking input here */
+ if (mailbox_save_continue(ctx->save_ctx) < 0 || ret == -1)
+ break;
+ }
+
+ if (ctx->input->stream_errno != 0) {
+ errno = ctx->input->stream_errno;
+ mail_storage_set_critical(ctx->box->storage,
+ "read(%s) failed: %m (for CATENATE URL %s)",
+ i_stream_get_name(input), caturl);
+ client_send_storage_error(cmd, ctx->storage);
+ ret = -1;
+ } else if (!input->eof) {
+ /* save failed */
+ client_send_storage_error(cmd, ctx->storage);
+ ret = -1;
+ } else {
+ ret = 0;
+ }
+ imap_msgpart_url_free(&mpurl);
+ return 0;
+}
+
+static int cmd_append_catenate_text(struct client_command_context *cmd)
+{
+ struct cmd_append_context *ctx = cmd->context;
+ uoff_t newsize;
+
+ newsize = ctx->cat_msg_size + ctx->literal_size;
+ if (newsize < ctx->cat_msg_size) {
+ client_send_tagline(cmd,
+ "NO [TOOBIG] Composed message grows too big.");
+ return -1;
+ }
+
+ /* save the mail */
+ ctx->cat_msg_size = newsize;
+ ctx->litinput = i_stream_create_limit(cmd->client->input,
+ ctx->literal_size);
+ i_stream_chain_append(ctx->catchain, ctx->litinput);
+ return 0;
+}
+
+static int
cmd_append_catenate(struct client_command_context *cmd,
const struct imap_arg *args, bool *nonsync_r)
{
- struct client *client = cmd->client;
struct cmd_append_context *ctx = cmd->context;
- struct imap_msgpart_url *mpurl;
- const char *catpart, *error;
- uoff_t newsize;
- int ret;
+ const char *catpart;
*nonsync_r = FALSE;
+ if (ctx->failed)
+ return -1;
+
/* Handle URLs until a TEXT literal is encountered */
while (imap_arg_get_atom(args, &catpart)) {
const char *caturl;
@@ -217,103 +316,15 @@
args++;
if (!imap_arg_get_astring(args, &caturl))
break;
- if (ctx->failed)
+ if (cmd_append_catenate_url(cmd, caturl) < 0)
return -1;
-
- ret = imap_msgpart_url_parse(client->user, client->mailbox,
- caturl, &mpurl, &error);
- if (ret < 0) {
- client_send_storage_error(cmd, ctx->storage);
- return -1;
- }
- if (ret == 0) {
- /* invalid url, abort */
- client_send_tagline(cmd,
- t_strdup_printf("NO [BADURL %s] %s.", caturl, error));
- return -1;
- }
-
- if (cmd->cancel) {
- imap_msgpart_url_free(&mpurl);
- cmd_append_finish(ctx);
- return 1;
- }
-
- /* catenate URL */
- if (ctx->save_ctx != NULL) {
- struct istream *input = NULL;
- uoff_t size;
-
- ret = imap_msgpart_url_read_part(mpurl, &input, &size, &error);
- if (ret < 0) {
- client_send_storage_error(cmd, ctx->storage);
- return -1;
- }
- if (ret == 0) {
- /* invalid url, abort */
- client_send_tagline(cmd,
- t_strdup_printf("NO [BADURL %s] %s.", caturl, error));
- return -1;
- }
-
- newsize = ctx->cat_msg_size + size;
- if (newsize < ctx->cat_msg_size) {
- client_send_tagline(cmd,
- "NO [TOOBIG] Composed message grows too big.");
- imap_msgpart_url_free(&mpurl);
- return -1;
- }
-
- if (input != NULL) {
- ctx->cat_msg_size = newsize;
- i_stream_chain_append(ctx->catchain, input);
-
- while (!input->eof) {
- ret = i_stream_read(ctx->input);
- if (mailbox_save_continue(ctx->save_ctx) < 0) {
- /* we still have to finish reading the message
- from client */
- mailbox_save_cancel(&ctx->save_ctx);
- break;
- }
- if (ret == -1 || ret == 0)
- break;
- }
-
- if (!input->eof) {
- client_send_tagline(cmd, t_strdup_printf(
- "NO [BADURL %s] Failed to read all data.", caturl));
- imap_msgpart_url_free(&mpurl);
- return -1;
- }
- }
- }
- imap_msgpart_url_free(&mpurl);
} else if (strcasecmp(catpart, "TEXT") == 0) {
/* TEXT <literal> */
args++;
if (!imap_arg_get_literal_size(args, &ctx->literal_size))
break;
-
*nonsync_r = args->type == IMAP_ARG_LITERAL_SIZE_NONSYNC;
- if (ctx->failed) {
- /* we failed earlier, make sure we just eat
- nonsync-literal if it's given. */
- return -1;
- }
-
- newsize = ctx->cat_msg_size + ctx->literal_size;
- if (newsize < ctx->cat_msg_size) {
- client_send_tagline(cmd,
- "NO [TOOBIG] Composed message grows too big.");
- return -1;
- }
-
- /* save the mail */
- ctx->cat_msg_size = newsize;
- ctx->litinput = i_stream_create_limit(client->input, ctx->literal_size);
- i_stream_chain_append(ctx->catchain, ctx->litinput);
- return 1;
+ return cmd_append_catenate_text(cmd) < 0 ? -1 : 1;
} else {
break;
}
@@ -334,7 +345,6 @@
i_stream_chain_append(ctx->catchain, NULL);
i_stream_unref(&ctx->input);
- ctx->input = NULL;
ctx->catenate = FALSE;
if (mailbox_save_finish(&ctx->save_ctx) < 0) {
@@ -515,27 +525,30 @@
/* save the mail */
ctx->save_ctx = mailbox_save_alloc(ctx->t);
mailbox_save_set_flags(ctx->save_ctx, flags, keywords);
+ if (keywords != NULL)
+ mailbox_keywords_unref(&keywords);
mailbox_save_set_received_date(ctx->save_ctx,
internal_date, timezone_offset);
- ret = mailbox_save_begin(&ctx->save_ctx, ctx->input);
- ctx->count++;
-
- if (cat_list != NULL &&
- (ret = cmd_append_catenate(cmd, cat_list, nonsync_r)) <= 0) {
- if (ret < 0)
- client->input_skip_line = TRUE;
- return ret;
- }
-
- if (keywords != NULL)
- mailbox_keywords_unref(&keywords);
-
- if (ret < 0) {
+ if (mailbox_save_begin(&ctx->save_ctx, ctx->input) < 0) {
/* save initialization failed */
client_send_storage_error(cmd, ctx->storage);
return -1;
}
- return 1;
+ ctx->count++;
+
+ if (cat_list == NULL) {
+ /* normal APPEND */
+ return 1;
+ } else if ((ret = cmd_append_catenate(cmd, cat_list, nonsync_r)) < 0) {
+ client->input_skip_line = TRUE;
+ return -1;
+ } else if (ret == 0) {
+ /* CATENATE consisted only of URLs */
+ return 0;
+ } else {
+ /* TEXT part found from CATENATE */
+ return 1;
+ }
}
static bool cmd_append_finish_parsing(struct client_command_context *cmd)
@@ -637,8 +650,7 @@
return cmd_append_finish_parsing(cmd);
}
- /* Handle multiple messages (IMAP URLs) while no literals are
- encountered) */
+ /* Handle MULTIAPPEND messages while CATENATE contains only URLs */
More information about the dovecot-cvs
mailing list