From: Timo Sirainen Date: Mon, 23 Nov 2009 20:01:45 +0000 (-0500) Subject: imap: Don't send NONEXISTENT resp code to non-delete operations. X-Git-Tag: 2.0.beta1~88 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dcd4d96ba85264382f2f928f139607db87975f03;p=thirdparty%2Fdovecot%2Fcore.git imap: Don't send NONEXISTENT resp code to non-delete operations. --HG-- branch : HEAD --- diff --git a/src/imap/cmd-list.c b/src/imap/cmd-list.c index 883b2ad563..393388577c 100644 --- a/src/imap/cmd-list.c +++ b/src/imap/cmd-list.c @@ -320,7 +320,7 @@ static void list_send_status(struct cmd_list_context *ctx, const char *name) const char *storage_name, *error; storage_name = mail_namespace_get_storage_name(ctx->ns, name); - if (imap_status_get(ctx->cmd->client, ctx->ns, storage_name, + if (imap_status_get(ctx->cmd, ctx->ns, storage_name, ctx->status_items, &status, &error) < 0) { client_send_line(ctx->cmd->client, t_strconcat("* ", error, NULL)); diff --git a/src/imap/cmd-status.c b/src/imap/cmd-status.c index 817a14eb34..cf59180c30 100644 --- a/src/imap/cmd-status.c +++ b/src/imap/cmd-status.c @@ -38,7 +38,7 @@ bool cmd_status(struct client_command_context *cmd) selected_mailbox = client->mailbox != NULL && mailbox_equals(client->mailbox, ns, real_mailbox); - if (imap_status_get(client, ns, real_mailbox, items, + if (imap_status_get(cmd, ns, real_mailbox, items, &status, &error) < 0) { client_send_tagline(cmd, error); return TRUE; diff --git a/src/imap/imap-commands-util.c b/src/imap/imap-commands-util.c index 6fdaffb7a6..ff6bea47ac 100644 --- a/src/imap/imap-commands-util.c +++ b/src/imap/imap-commands-util.c @@ -111,23 +111,26 @@ client_find_namespace(struct client_command_context *cmd, const char **mailboxp, break; case MAILBOX_NAME_VALID: + resp_code = ""; switch (mode) { case CLIENT_VERIFY_MAILBOX_NAME: case CLIENT_VERIFY_MAILBOX_SHOULD_NOT_EXIST: return ns; case CLIENT_VERIFY_MAILBOX_SHOULD_EXIST: - resp_code = IMAP_RESP_CODE_NONEXISTENT; + if ((cmd->cmd_flags & COMMAND_FLAG_USE_NONEXISTENT) != 0) + resp_code = IMAP_RESP_CODE_NONEXISTENT; break; case CLIENT_VERIFY_MAILBOX_SHOULD_EXIST_TRYCREATE: resp_code = "TRYCREATE"; break; default: - resp_code = NULL; i_unreached(); } + if (*resp_code != '\0') + resp_code = t_strconcat("[", resp_code, "] ", NULL); client_send_tagline(cmd, t_strconcat( - "NO [", resp_code, "] Mailbox doesn't exist: ", + "NO ", resp_code, "Mailbox doesn't exist: ", str_sanitize(orig_mailbox, MAILBOX_MAX_NAME_LEN), NULL)); break; @@ -161,7 +164,8 @@ bool client_verify_open_mailbox(struct client_command_context *cmd) } const char * -imap_get_error_string(const char *error_string, enum mail_error error) +imap_get_error_string(struct client_command_context *cmd, + const char *error_string, enum mail_error error) { const char *resp_code = NULL; @@ -182,7 +186,8 @@ imap_get_error_string(const char *error_string, enum mail_error error) resp_code = IMAP_RESP_CODE_OVERQUOTA; break; case MAIL_ERROR_NOTFOUND: - resp_code = IMAP_RESP_CODE_NONEXISTENT; + if ((cmd->cmd_flags & COMMAND_FLAG_USE_NONEXISTENT) != 0) + resp_code = IMAP_RESP_CODE_NONEXISTENT; break; case MAIL_ERROR_EXISTS: resp_code = IMAP_RESP_CODE_ALREADYEXISTS; @@ -207,7 +212,8 @@ void client_send_list_error(struct client_command_context *cmd, enum mail_error error; error_string = mailbox_list_get_last_error(list, &error); - client_send_tagline(cmd, imap_get_error_string(error_string, error)); + client_send_tagline(cmd, imap_get_error_string(cmd, error_string, + error)); } void client_send_storage_error(struct client_command_context *cmd, @@ -225,7 +231,8 @@ void client_send_storage_error(struct client_command_context *cmd, } error_string = mail_storage_get_last_error(storage, &error); - client_send_tagline(cmd, imap_get_error_string(error_string, error)); + client_send_tagline(cmd, imap_get_error_string(cmd, error_string, + error)); } void client_send_untagged_storage_error(struct client *client, diff --git a/src/imap/imap-commands-util.h b/src/imap/imap-commands-util.h index c1964c56df..f738d116d0 100644 --- a/src/imap/imap-commands-util.h +++ b/src/imap/imap-commands-util.h @@ -33,7 +33,8 @@ client_find_namespace(struct client_command_context *cmd, const char **mailbox, bool client_verify_open_mailbox(struct client_command_context *cmd); const char * -imap_get_error_string(const char *error_string, enum mail_error error); +imap_get_error_string(struct client_command_context *cmd, + const char *error_string, enum mail_error error); /* Send last mailbox list error message to client. */ void client_send_list_error(struct client_command_context *cmd, diff --git a/src/imap/imap-commands.c b/src/imap/imap-commands.c index 6a2661dfe8..ea7c50ac20 100644 --- a/src/imap/imap-commands.c +++ b/src/imap/imap-commands.c @@ -15,14 +15,14 @@ static const struct command imap4rev1_commands[] = { { "APPEND", cmd_append, COMMAND_FLAG_BREAKS_SEQS }, { "EXAMINE", cmd_examine, COMMAND_FLAG_BREAKS_MAILBOX }, { "CREATE", cmd_create, 0 }, - { "DELETE", cmd_delete, 0 }, - { "RENAME", cmd_rename, 0 }, + { "DELETE", cmd_delete, COMMAND_FLAG_USE_NONEXISTENT }, + { "RENAME", cmd_rename, COMMAND_FLAG_USE_NONEXISTENT }, { "LIST", cmd_list, 0 }, { "LSUB", cmd_lsub, 0 }, { "SELECT", cmd_select, COMMAND_FLAG_BREAKS_MAILBOX }, { "STATUS", cmd_status, 0 }, { "SUBSCRIBE", cmd_subscribe, 0 }, - { "UNSUBSCRIBE", cmd_unsubscribe, 0 }, + { "UNSUBSCRIBE", cmd_unsubscribe, COMMAND_FLAG_USE_NONEXISTENT }, { "CHECK", cmd_check, COMMAND_FLAG_BREAKS_SEQS }, { "CLOSE", cmd_close, COMMAND_FLAG_BREAKS_MAILBOX }, diff --git a/src/imap/imap-commands.h b/src/imap/imap-commands.h index c385f401cf..dc6391c819 100644 --- a/src/imap/imap-commands.h +++ b/src/imap/imap-commands.h @@ -24,7 +24,12 @@ enum command_flags { COMMAND_FLAG_USES_SEQS, /* Command requires mailbox syncing before it can do its job. */ - COMMAND_FLAG_REQUIRES_SYNC = 0x08 + COMMAND_FLAG_REQUIRES_SYNC = 0x08, + /* Command allows replying with [NONEXISTENT] imap resp code. + Dovecot internally returns it for all kinds of commands, + but unfortunately RFC 5530 specifies it only for "delete something" + operations. */ + COMMAND_FLAG_USE_NONEXISTENT = 0x10 }; struct command { diff --git a/src/imap/imap-status.c b/src/imap/imap-status.c index 9aa8e63d04..285c20d70c 100644 --- a/src/imap/imap-status.c +++ b/src/imap/imap-status.c @@ -49,10 +49,12 @@ int imap_status_parse_items(struct client_command_context *cmd, return 0; } -int imap_status_get(struct client *client, struct mail_namespace *ns, +int imap_status_get(struct client_command_context *cmd, + struct mail_namespace *ns, const char *mailbox, enum mailbox_status_items items, struct mailbox_status *status_r, const char **error_r) { + struct client *client = cmd->client; struct mailbox *box; enum mail_error error; int ret; @@ -77,7 +79,7 @@ int imap_status_get(struct client *client, struct mail_namespace *ns, if (ret < 0) { struct mail_storage *storage = mailbox_get_storage(box); *error_r = mail_storage_get_last_error(storage, &error); - *error_r = imap_get_error_string(*error_r, error); + *error_r = imap_get_error_string(cmd, *error_r, error); } mailbox_close(&box); return ret; diff --git a/src/imap/imap-status.h b/src/imap/imap-status.h index dcb7b0b594..cfccaff899 100644 --- a/src/imap/imap-status.h +++ b/src/imap/imap-status.h @@ -4,7 +4,8 @@ int imap_status_parse_items(struct client_command_context *cmd, const struct imap_arg *args, enum mailbox_status_items *items_r); -int imap_status_get(struct client *client, struct mail_namespace *ns, +int imap_status_get(struct client_command_context *cmd, + struct mail_namespace *ns, const char *mailbox, enum mailbox_status_items items, struct mailbox_status *status_r, const char **error_r); void imap_status_send(struct client *client, const char *mailbox,