[dovecot-cvs] dovecot/src/imap cmd-append.c,1.46,1.47
cras at dovecot.org
cras at dovecot.org
Sun Sep 26 13:37:05 EEST 2004
Update of /var/lib/cvs/dovecot/src/imap
In directory talvi:/tmp/cvs-serv26131
Modified Files:
cmd-append.c
Log Message:
If message was APPENDed with LITERALPLUS and it failed for some reason (eg.
mailbox didn't exist), we didn't consume the following message but instead
treated it as commands.
Index: cmd-append.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/imap/cmd-append.c,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- cmd-append.c 29 Aug 2004 07:52:02 -0000 1.46
+++ cmd-append.c 26 Sep 2004 10:37:03 -0000 1.47
@@ -115,13 +115,48 @@
if (ctx->t != NULL)
mailbox_transaction_rollback(ctx->t);
- if (ctx->box != ctx->client->mailbox)
+ if (ctx->box != ctx->client->mailbox && ctx->box != NULL)
mailbox_close(ctx->box);
(void)i_stream_get_data(ctx->client->input, &size);
ctx->client->input_pending = size != 0;
}
+static int cmd_append_continue_cancel(struct client *client)
+{
+ struct cmd_append_context *ctx = client->cmd_context;
+ size_t size;
+
+ (void)i_stream_read(ctx->input);
+ (void)i_stream_get_data(ctx->input, &size);
+ i_stream_skip(ctx->input, size);
+
+ if (ctx->input->v_offset == ctx->msg_size || ctx->input->closed) {
+ cmd_append_finish(ctx);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int cmd_append_cancel(struct cmd_append_context *ctx, int nonsync)
+{
+ if (!nonsync) {
+ cmd_append_finish(ctx);
+ return TRUE;
+ }
+
+ /* we have to read the nonsynced literal so we don't treat the message
+ data as commands. */
+ ctx->input = i_stream_create_limit(default_pool, ctx->client->input,
+ ctx->client->input->v_offset,
+ ctx->msg_size);
+
+ ctx->client->command_pending = TRUE;
+ ctx->client->cmd_func = cmd_append_continue_cancel;
+ ctx->client->cmd_context = ctx;
+ return cmd_append_continue_cancel(ctx->client);
+}
+
static int cmd_append_continue_parsing(struct client *client)
{
struct cmd_append_context *ctx = client->cmd_context;
@@ -139,7 +174,8 @@
ret = imap_parser_read_args(ctx->save_parser, 0,
IMAP_PARSE_FLAG_LITERAL_SIZE, &args);
if (ret == -1) {
- client_send_command_error(client, NULL);
+ if (ctx->box != NULL)
+ client_send_command_error(client, NULL);
cmd_append_finish(ctx);
return TRUE;
}
@@ -152,6 +188,12 @@
/* last message */
enum mailbox_sync_flags sync_flags;
+ if (ctx->box == NULL) {
+ /* we failed earlier, error message is sent */
+ cmd_append_finish(ctx);
+ return TRUE;
+ }
+
ret = mailbox_transaction_commit(ctx->t, 0);
ctx->t = NULL;
if (ret < 0) {
@@ -171,16 +213,19 @@
if (!validate_args(args, &flags_list, &internal_date_str,
&ctx->msg_size, &nonsync)) {
client_send_command_error(client, "Invalid arguments.");
- cmd_append_finish(ctx);
- return TRUE;
+ return cmd_append_cancel(ctx, nonsync);
+ }
+
+ if (ctx->box == NULL) {
+ /* we failed earlier, make sure we just eat nonsync-literal
+ if it's given. */
+ return cmd_append_cancel(ctx, nonsync);
}
if (flags_list != NULL) {
if (!client_parse_mail_flags(client, flags_list->args,
- &client->keywords, &flags)) {
- cmd_append_finish(ctx);
- return TRUE;
- }
+ &client->keywords, &flags))
+ return cmd_append_cancel(ctx, nonsync);
} else {
memset(&flags, 0, sizeof(flags));
}
@@ -192,8 +237,7 @@
} else if (!imap_parse_datetime(internal_date_str,
&internal_date, &timezone_offset)) {
client_send_tagline(client, "BAD Invalid internal date.");
- cmd_append_finish(ctx);
- return TRUE;
+ return cmd_append_cancel(ctx, nonsync);
}
if (ctx->msg_size == 0) {
@@ -246,7 +290,7 @@
i_stream_skip(ctx->input, size);
}
- if (ctx->input->v_offset == ctx->msg_size) {
+ if (ctx->input->v_offset == ctx->msg_size || ctx->input->closed) {
/* finished */
i_stream_unref(ctx->input);
ctx->input = NULL;
@@ -282,51 +326,59 @@
return FALSE;
}
-int cmd_append(struct client *client)
+static struct mailbox *get_mailbox(struct client *client, const char *name)
{
- struct cmd_append_context *ctx;
struct mail_storage *storage;
struct mailbox *box;
- struct mailbox_status status;
- const char *mailbox;
- /* <mailbox> */
- if (!client_read_string_args(client, 1, &mailbox))
- return FALSE;
-
- if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE))
- return TRUE;
+ if (!client_verify_mailbox_name(client, name, TRUE, FALSE))
+ return NULL;
- storage = client_find_storage(client, &mailbox);
+ storage = client_find_storage(client, &name);
if (storage == NULL)
- return TRUE;
+ return NULL;
if (client->mailbox != NULL &&
- mailbox_name_equals(mailbox_get_name(client->mailbox), mailbox))
- box = client->mailbox;
- else {
- box = mailbox_open(storage, mailbox, MAILBOX_OPEN_FAST |
- MAILBOX_OPEN_KEEP_RECENT);
- if (box == NULL) {
- client_send_storage_error(client, storage);
- return TRUE;
- }
- }
+ mailbox_name_equals(mailbox_get_name(client->mailbox), name))
+ return client->mailbox;
- if (mailbox_get_status(box, STATUS_KEYWORDS, &status) < 0) {
+ box = mailbox_open(storage, name, MAILBOX_OPEN_FAST |
+ MAILBOX_OPEN_KEEP_RECENT);
+ if (box == NULL) {
client_send_storage_error(client, storage);
- mailbox_close(box);
- return TRUE;
+ return NULL;
}
+ return box;
+}
+
+int cmd_append(struct client *client)
+{
+ struct cmd_append_context *ctx;
+ struct mailbox_status status;
+ const char *mailbox;
+
+ /* <mailbox> */
+ if (!client_read_string_args(client, 1, &mailbox))
+ return FALSE;
ctx = p_new(client->cmd_pool, struct cmd_append_context, 1);
ctx->client = client;
- ctx->storage = storage;
- ctx->box = box;
- ctx->t = mailbox_transaction_begin(box, FALSE);
+ ctx->box = get_mailbox(client, mailbox);
+ if (ctx->box != NULL) {
+ ctx->storage = mailbox_get_storage(ctx->box);
- client_save_keywords(&client->keywords, status.keywords,
- status.keywords_count);
+ if (mailbox_get_status(ctx->box, STATUS_KEYWORDS,
+ &status) < 0) {
+ client_send_storage_error(client, ctx->storage);
+ mailbox_close(ctx->box);
+ ctx->box = NULL;
+ } else {
+ client_save_keywords(&client->keywords, status.keywords,
+ status.keywords_count);
+ }
+ ctx->t = ctx->box == NULL ? NULL :
+ mailbox_transaction_begin(ctx->box, FALSE);
+ }
io_remove(client->io);
client->io = io_add(i_stream_get_fd(client->input), IO_READ,
More information about the dovecot-cvs
mailing list