]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
imap: Some mailbox accessing commands failed with wrong error message.
authorTimo Sirainen <tss@iki.fi>
Tue, 16 Mar 2010 14:15:03 +0000 (16:15 +0200)
committerTimo Sirainen <tss@iki.fi>
Tue, 16 Mar 2010 14:15:03 +0000 (16:15 +0200)
--HG--
branch : HEAD

src/imap/cmd-append.c
src/imap/cmd-copy.c
src/imap/cmd-create.c
src/imap/cmd-delete.c
src/imap/cmd-rename.c
src/imap/cmd-select.c
src/imap/cmd-status.c
src/imap/cmd-subscribe.c
src/imap/imap-commands-util.c
src/imap/imap-commands-util.h

index 075b675b4b8446c7bfd74d6ee2d6aaf95ecdaee1..a500fae7a46c363f7740daa5270e5dc87da9a775 100644 (file)
@@ -454,17 +454,31 @@ get_mailbox(struct client_command_context *cmd, const char *name)
 {
        struct mail_namespace *ns;
        struct mailbox *box;
+       enum mailbox_name_status status;
+       const char *storage_name;
 
-       ns = client_find_namespace(cmd, &name,
-                                  CLIENT_VERIFY_MAILBOX_SHOULD_EXIST_TRYCREATE);
+       ns = client_find_namespace(cmd, name, &storage_name, &status);
        if (ns == NULL)
                return NULL;
 
+       switch (status) {
+       case MAILBOX_NAME_EXISTS_MAILBOX:
+               break;
+       case MAILBOX_NAME_EXISTS_DIR:
+               status = MAILBOX_NAME_VALID;
+               /* fall through */
+       case MAILBOX_NAME_VALID:
+       case MAILBOX_NAME_INVALID:
+       case MAILBOX_NAME_NOINFERIORS:
+               client_fail_mailbox_name_status(cmd, name, "TRYCREATE", status);
+               return NULL;
+       }
+
        if (cmd->client->mailbox != NULL &&
-           mailbox_equals(cmd->client->mailbox, ns, name))
+           mailbox_equals(cmd->client->mailbox, ns, storage_name))
                return cmd->client->mailbox;
 
-       box = mailbox_alloc(ns->list, name, MAILBOX_FLAG_SAVEONLY |
+       box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_SAVEONLY |
                            MAILBOX_FLAG_KEEP_RECENT);
        if (mailbox_open(box) < 0) {
                client_send_storage_error(cmd, mailbox_get_storage(box));
index 34182878bbf5a17c636b4709c4b3e9b70e495eda..3cd415a9afe46010ecb8255218d24f5e9d3156ff 100644 (file)
@@ -90,7 +90,8 @@ bool cmd_copy(struct client_command_context *cmd)
        struct mailbox *destbox;
        struct mailbox_transaction_context *t;
         struct mail_search_args *search_args;
-       const char *messageset, *mailbox, *src_uidset;
+       const char *messageset, *mailbox, *storage_name, *src_uidset;
+       enum mailbox_name_status status;
        enum mailbox_sync_flags sync_flags = 0;
        enum imap_sync_flags imap_flags = 0;
        struct mail_transaction_commit_changes changes;
@@ -110,15 +111,28 @@ bool cmd_copy(struct client_command_context *cmd)
                return ret < 0;
 
        /* open the destination mailbox */
-       dest_ns = client_find_namespace(cmd, &mailbox,
-                               CLIENT_VERIFY_MAILBOX_SHOULD_EXIST_TRYCREATE);
+       dest_ns = client_find_namespace(cmd, mailbox, &storage_name, &status);
        if (dest_ns == NULL)
                return TRUE;
 
-       if (mailbox_equals(client->mailbox, dest_ns, mailbox))
+       switch (status) {
+       case MAILBOX_NAME_EXISTS_MAILBOX:
+               break;
+       case MAILBOX_NAME_EXISTS_DIR:
+               status = MAILBOX_NAME_VALID;
+               /* fall through */
+       case MAILBOX_NAME_VALID:
+       case MAILBOX_NAME_INVALID:
+       case MAILBOX_NAME_NOINFERIORS:
+               client_fail_mailbox_name_status(cmd, mailbox,
+                                               "TRYCREATE", status);
+               return NULL;
+       }
+
+       if (mailbox_equals(client->mailbox, dest_ns, storage_name))
                destbox = client->mailbox;
        else {
-               destbox = mailbox_alloc(dest_ns->list, mailbox,
+               destbox = mailbox_alloc(dest_ns->list, storage_name,
                                        MAILBOX_FLAG_SAVEONLY |
                                        MAILBOX_FLAG_KEEP_RECENT);
                if (mailbox_open(destbox) < 0) {
index 27602ad16aee5a77bb8e222484b9975bb3ea5d60..e0a8184f7ba10e5562e1287330122cb451a835f4 100644 (file)
@@ -7,8 +7,9 @@
 
 bool cmd_create(struct client_command_context *cmd)
 {
+       enum mailbox_name_status status;
        struct mail_namespace *ns;
-       const char *mailbox, *full_mailbox;
+       const char *mailbox, *storage_name;
        struct mailbox *box;
        bool directory;
        size_t len;
@@ -16,16 +17,15 @@ bool cmd_create(struct client_command_context *cmd)
        /* <mailbox> */
        if (!client_read_string_args(cmd, 1, &mailbox))
                return FALSE;
-       full_mailbox = mailbox;
 
-       ns = client_find_namespace(cmd, &mailbox, CLIENT_VERIFY_MAILBOX_NONE);
+       ns = client_find_namespace(cmd, mailbox, &storage_name, NULL);
        if (ns == NULL)
                return TRUE;
 
-       len = strlen(full_mailbox);
-       if (len == 0 || full_mailbox[len-1] != ns->sep)
+       len = strlen(mailbox);
+       if (len == 0 || mailbox[len-1] != ns->sep)
                directory = FALSE;
-       else if (*mailbox == '\0') {
+       else if (*storage_name == '\0') {
                client_send_tagline(cmd, "NO ["IMAP_RESP_CODE_ALREADYEXISTS
                                    "] Namespace already exists.");
                return TRUE;
@@ -34,17 +34,28 @@ bool cmd_create(struct client_command_context *cmd)
                   informing us that it wants to create children under this
                   mailbox. */
                 directory = TRUE;
-               mailbox = t_strndup(mailbox, strlen(mailbox)-1);
-               full_mailbox = t_strndup(full_mailbox, len-1);
+               storage_name = t_strndup(storage_name, strlen(storage_name)-1);
+               mailbox = t_strndup(mailbox, len-1);
        }
 
-       mailbox = full_mailbox;
-       ns = client_find_namespace(cmd, &mailbox,
-                                  CLIENT_VERIFY_MAILBOX_SHOULD_NOT_EXIST);
+       ns = client_find_namespace(cmd, mailbox, &storage_name, &status);
        if (ns == NULL)
                return TRUE;
+       switch (status) {
+       case MAILBOX_NAME_VALID:
+               break;
+       case MAILBOX_NAME_EXISTS_DIR:
+               if (!directory)
+                       break;
+               /* fall through */
+       case MAILBOX_NAME_EXISTS_MAILBOX:
+       case MAILBOX_NAME_INVALID:
+       case MAILBOX_NAME_NOINFERIORS:
+               client_fail_mailbox_name_status(cmd, mailbox, NULL, status);
+               return TRUE;
+       }
 
-       box = mailbox_alloc(ns->list, mailbox, 0);
+       box = mailbox_alloc(ns->list, storage_name, 0);
        if (mailbox_create(box, NULL, directory) < 0)
                client_send_storage_error(cmd, mailbox_get_storage(box));
        else
index 661538445c0414a8006201c0521e0d783b1cd356..098780c1f2c36181ea1fc985efe75207e2f08862 100644 (file)
@@ -6,9 +6,10 @@
 bool cmd_delete(struct client_command_context *cmd)
 {
        struct client *client = cmd->client;
+       enum mailbox_name_status status;
        struct mail_namespace *ns;
        struct mailbox *box;
-       const char *name;
+       const char *name, *storage_name;
 
        /* <mailbox> */
        if (!client_read_string_args(cmd, 1, &name))
@@ -20,12 +21,21 @@ bool cmd_delete(struct client_command_context *cmd)
                return TRUE;
        }
 
-       ns = client_find_namespace(cmd, &name,
-                                  CLIENT_VERIFY_MAILBOX_DIR_SHOULD_EXIST);
+       ns = client_find_namespace(cmd, name, &storage_name, &status);
        if (ns == NULL)
                return TRUE;
+       switch (status) {
+       case MAILBOX_NAME_EXISTS_MAILBOX:
+       case MAILBOX_NAME_EXISTS_DIR:
+               break;
+       case MAILBOX_NAME_VALID:
+       case MAILBOX_NAME_INVALID:
+       case MAILBOX_NAME_NOINFERIORS:
+               client_fail_mailbox_name_status(cmd, name, NULL, status);
+               return TRUE;
+       }
 
-       box = mailbox_alloc(ns->list, name, 0);
+       box = mailbox_alloc(ns->list, storage_name, 0);
        if (client->mailbox != NULL &&
            mailbox_backends_equal(box, client->mailbox)) {
                /* deleting selected mailbox. close it first */
index fddbf62dc2bf0b495142e6409b291503ae134c9b..b31563891ddc9115f3d514d956047cb74041af3e 100644 (file)
@@ -6,40 +6,59 @@
 
 bool cmd_rename(struct client_command_context *cmd)
 {
+       enum mailbox_name_status status;
        struct mail_namespace *old_ns, *new_ns;
        struct mailbox *old_box, *new_box;
-       const char *oldname, *newname;
+       const char *oldname, *newname, *storage_oldname, *storage_newname;
        unsigned int oldlen;
 
        /* <old name> <new name> */
        if (!client_read_string_args(cmd, 2, &oldname, &newname))
                return FALSE;
 
-       old_ns = client_find_namespace(cmd, &oldname,
-                                      CLIENT_VERIFY_MAILBOX_DIR_SHOULD_EXIST);
+       old_ns = client_find_namespace(cmd, oldname, &storage_oldname, &status);
        if (old_ns == NULL)
                return TRUE;
+       switch (status) {
+       case MAILBOX_NAME_EXISTS_MAILBOX:
+       case MAILBOX_NAME_EXISTS_DIR:
+               break;
+       case MAILBOX_NAME_VALID:
+       case MAILBOX_NAME_INVALID:
+       case MAILBOX_NAME_NOINFERIORS:
+               client_fail_mailbox_name_status(cmd, oldname, NULL, status);
+               return TRUE;
+       }
 
-       new_ns = client_find_namespace(cmd, &newname,
-                               CLIENT_VERIFY_MAILBOX_DIR_SHOULD_NOT_EXIST);
+       new_ns = client_find_namespace(cmd, newname, &storage_newname, &status);
        if (new_ns == NULL)
                return TRUE;
+       switch (status) {
+       case MAILBOX_NAME_VALID:
+               break;
+       case MAILBOX_NAME_EXISTS_MAILBOX:
+       case MAILBOX_NAME_EXISTS_DIR:
+       case MAILBOX_NAME_INVALID:
+       case MAILBOX_NAME_NOINFERIORS:
+               client_fail_mailbox_name_status(cmd, newname, NULL, status);
+               return TRUE;
+       }
 
        if (old_ns == new_ns) {
                /* disallow box -> box/child, because it may break clients and
                   there's really no point in doing it anyway. */
                old_ns = mailbox_list_get_namespace(old_ns->list);
-               oldlen = strlen(oldname);
-               if (strncmp(oldname, newname, oldlen) == 0 &&
-                   newname[oldlen] == old_ns->real_sep) {
+               oldlen = strlen(storage_oldname);
+               if (strncmp(storage_oldname, storage_newname, oldlen) == 0 &&
+                   storage_newname[oldlen] == old_ns->real_sep) {
                        client_send_tagline(cmd,
                                "NO Can't rename mailbox under its own child.");
                        return TRUE;
                }
        }
 
-       old_box = mailbox_alloc(old_ns->list, oldname, 0);
-       new_box = mailbox_alloc(new_ns->list, newname, 0);
+       old_box = mailbox_alloc(old_ns->list, storage_oldname, 0);
+       new_box = mailbox_alloc(new_ns->list, storage_newname, 0);
        if (mailbox_rename(old_box, new_box, TRUE) < 0)
                client_send_storage_error(cmd, mailbox_get_storage(old_box));
        else
index 583c4f1ac7f6b6151382e1a23a35ab93f25fe6f9..039cd69470608ffa8c2ecaef53347593650198b8 100644 (file)
@@ -342,7 +342,8 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
        struct mailbox *box;
        struct imap_select_context *ctx;
        const struct imap_arg *args;
-       const char *mailbox;
+       enum mailbox_name_status status;
+       const char *mailbox, *storage_name;
        int ret;
 
        /* <mailbox> [(optional parameters)] */
@@ -357,10 +358,21 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
 
        ctx = p_new(cmd->pool, struct imap_select_context, 1);
        ctx->cmd = cmd;
-       ctx->ns = client_find_namespace(cmd, &mailbox,
-                                       CLIENT_VERIFY_MAILBOX_SHOULD_EXIST);
+       ctx->ns = client_find_namespace(cmd, mailbox, &storage_name, &status);
        if (ctx->ns == NULL)
                return TRUE;
+       switch (status) {
+       case MAILBOX_NAME_EXISTS_MAILBOX:
+               break;
+       case MAILBOX_NAME_EXISTS_DIR:
+               status = MAILBOX_NAME_VALID;
+               /* fall through */
+       case MAILBOX_NAME_VALID:
+       case MAILBOX_NAME_INVALID:
+       case MAILBOX_NAME_NOINFERIORS:
+               client_fail_mailbox_name_status(cmd, mailbox, NULL, status);
+               return TRUE;
+       }
 
        if (args[1].type == IMAP_ARG_LIST) {
                if (!select_parse_options(ctx, IMAP_ARG_LIST_ARGS(&args[1]))) {
@@ -389,7 +401,7 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
                client_enable(client, MAILBOX_FEATURE_CONDSTORE);
        }
 
-       ret = select_open(ctx, mailbox, readonly);
+       ret = select_open(ctx, storage_name, readonly);
        cmd_select_finish(ctx, ret);
        return TRUE;
 }
index 61ee0dae0cb87b113e44b5d4985d744c774762de..43cc8ecf3657c1eb1c02603994d18a9ba28feab7 100644 (file)
@@ -9,18 +9,19 @@
 bool cmd_status(struct client_command_context *cmd)
 {
        struct client *client = cmd->client;
+       enum mailbox_name_status status;
        const struct imap_arg *args;
        struct imap_status_items items;
        struct imap_status_result result;
        struct mail_namespace *ns;
-       const char *mailbox, *real_mailbox, *error;
+       const char *mailbox, *storage_name, *error;
        bool selected_mailbox;
 
        /* <mailbox> <status items> */
        if (!client_read_args(cmd, 2, 0, &args))
                return FALSE;
 
-       mailbox = real_mailbox = imap_arg_string(&args[0]);
+       mailbox = imap_arg_string(&args[0]);
        if (mailbox == NULL || args[1].type != IMAP_ARG_LIST) {
                client_send_command_error(cmd, "Status items must be list.");
                return TRUE;
@@ -31,14 +32,25 @@ bool cmd_status(struct client_command_context *cmd)
                                    &items) < 0)
                return TRUE;
 
-       ns = client_find_namespace(cmd, &real_mailbox,
-                                  CLIENT_VERIFY_MAILBOX_SHOULD_EXIST);
+       ns = client_find_namespace(cmd, mailbox, &storage_name, &status);
        if (ns == NULL)
                return TRUE;
+       switch (status) {
+       case MAILBOX_NAME_EXISTS_MAILBOX:
+               break;
+       case MAILBOX_NAME_EXISTS_DIR:
+               status = MAILBOX_NAME_VALID;
+               /* fall through */
+       case MAILBOX_NAME_VALID:
+       case MAILBOX_NAME_INVALID:
+       case MAILBOX_NAME_NOINFERIORS:
+               client_fail_mailbox_name_status(cmd, mailbox, NULL, status);
+               return TRUE;
+       }
 
        selected_mailbox = client->mailbox != NULL &&
-               mailbox_equals(client->mailbox, ns, real_mailbox);
-       if (imap_status_get(cmd, ns, real_mailbox, &items,
+               mailbox_equals(client->mailbox, ns, storage_name);
+       if (imap_status_get(cmd, ns, storage_name, &items,
                            &result, &error) < 0) {
                client_send_tagline(cmd, error);
                return TRUE;
index 222bb7db318533fc1246245b22dd91d83985f54e..39615aac4b512d22bafac305b5a0b3aec473c8bb 100644 (file)
@@ -28,69 +28,91 @@ static bool have_listable_namespace_prefix(struct mail_namespace *ns,
 
 bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
 {
-       struct mail_namespace *ns, *real_ns;
-       const char *mailbox, *mailbox2 = NULL, *verify_name, *real_name;
+       enum mailbox_name_status status;
+       struct mail_namespace *ns, *box_ns;
+       const char *mailbox, *storage_name, *subs_name, *subs_name2 = NULL;
        bool unsubscribed_mailbox2;
 
        /* <mailbox> */
        if (!client_read_string_args(cmd, 1, &mailbox))
                return FALSE;
-       verify_name = mailbox;
 
-       real_name = mailbox;
-       real_ns = client_find_namespace(cmd, &real_name,
-                                       CLIENT_VERIFY_MAILBOX_NONE);
-       if (real_ns == NULL)
+       box_ns = client_find_namespace(cmd, mailbox, &storage_name, NULL);
+       if (box_ns == NULL)
                return TRUE;
 
        /* now find a namespace where the subscription can be added to */
+       subs_name = mailbox;
        ns = mail_namespace_find_subscribable(cmd->client->user->namespaces,
-                                             &mailbox);
+                                             &subs_name);
        if (ns == NULL) {
                client_send_tagline(cmd, "NO Unknown subscription namespace.");
                return TRUE;
        }
 
-       if (ns != real_ns) {
+       if (ns != box_ns) {
                /* subscription is being written to a different namespace
                   than where the mailbox exists. */
-               mailbox = t_strconcat(real_ns->prefix, real_name, NULL);
+               subs_name = t_strconcat(box_ns->prefix, storage_name, NULL);
                /* drop the common prefix */
-               i_assert(strncmp(ns->prefix, mailbox, strlen(ns->prefix)) == 0);
-               mailbox += strlen(ns->prefix);
+               i_assert(strncmp(ns->prefix, subs_name, strlen(ns->prefix)) == 0);
+               subs_name += strlen(ns->prefix);
        }
 
        if ((cmd->client->set->parsed_workarounds &
                        WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
-           *mailbox != '\0' && mailbox[strlen(mailbox)-1] ==
+           *subs_name != '\0' && subs_name[strlen(subs_name)-1] ==
            mailbox_list_get_hierarchy_sep(ns->list)) {
                /* verify the validity without the trailing '/' */
-               verify_name = t_strndup(verify_name, strlen(verify_name)-1);
-               mailbox2 = mailbox;
                mailbox = t_strndup(mailbox, strlen(mailbox)-1);
+               subs_name2 = subs_name;
+               subs_name = t_strndup(subs_name, strlen(subs_name)-1);
        }
 
        if (have_listable_namespace_prefix(cmd->client->user->namespaces,
-                                          verify_name)) {
+                                          mailbox)) {
                /* subscribing to a listable namespace prefix, allow it. */
        } else if (subscribe) {
-               if (client_find_namespace(cmd, &verify_name,
-                               CLIENT_VERIFY_MAILBOX_DIR_SHOULD_EXIST) == NULL)
+               if (client_find_namespace(cmd, mailbox,
+                                         &storage_name, &status) == NULL)
                        return TRUE;
+               switch (status) {
+               case MAILBOX_NAME_EXISTS_MAILBOX:
+               case MAILBOX_NAME_EXISTS_DIR:
+                       break;
+               case MAILBOX_NAME_VALID:
+               case MAILBOX_NAME_INVALID:
+               case MAILBOX_NAME_NOINFERIORS:
+                       client_fail_mailbox_name_status(cmd, mailbox,
+                                                       NULL, status);
+                       return TRUE;
+               }
        } else {
-               if (client_find_namespace(cmd, &verify_name,
-                               CLIENT_VERIFY_MAILBOX_NAME) == NULL)
+               if (client_find_namespace(cmd, mailbox,
+                                         &storage_name, &status) == NULL)
+                       return TRUE;
+               switch (status) {
+               case MAILBOX_NAME_EXISTS_MAILBOX:
+               case MAILBOX_NAME_EXISTS_DIR:
+               case MAILBOX_NAME_VALID:
+                       break;
+               case MAILBOX_NAME_INVALID:
+               case MAILBOX_NAME_NOINFERIORS:
+                       client_fail_mailbox_name_status(cmd, mailbox,
+                                                       NULL, status);
                        return TRUE;
+               }
        }
 
        unsubscribed_mailbox2 = FALSE;
-       if (!subscribe && mailbox2 != NULL) {
+       if (!subscribe && subs_name2 != NULL) {
                /* try to unsubscribe both "box" and "box/" */
-               if (mailbox_list_set_subscribed(ns->list, mailbox2, FALSE) == 0)
+               if (mailbox_list_set_subscribed(ns->list, subs_name2,
+                                               FALSE) == 0)
                        unsubscribed_mailbox2 = TRUE;
        }
 
-       if (mailbox_list_set_subscribed(ns->list, mailbox, subscribe) < 0 &&
+       if (mailbox_list_set_subscribed(ns->list, subs_name, subscribe) < 0 &&
            !unsubscribed_mailbox2) {
                client_send_list_error(cmd, ns->list);
        } else {
index 7bdc63c2a1b6257459ecfd3637157d71ed7bd98f..5a68867de59d428370a31a5ff220693514889b22 100644 (file)
 #define MAILBOX_MAX_NAME_LEN 512
 
 struct mail_namespace *
-client_find_namespace(struct client_command_context *cmd, const char **mailboxp,
-                     enum client_verify_mailbox_mode mode)
+client_find_namespace(struct client_command_context *cmd, const char *mailbox,
+                     const char **storage_name_r,
+                     enum mailbox_name_status *mailbox_status_r)
 {
        struct mail_namespace *ns;
-       enum mailbox_name_status mailbox_status;
-       const char *orig_mailbox, *mailbox, *p, *resp_code = NULL;
-       unsigned int mailbox_len;
+       const char *storage_name, *p;
+       unsigned int storage_name_len;
+       char sep;
 
-       orig_mailbox = *mailboxp;
-       ns = mail_namespace_find(cmd->client->user->namespaces, mailboxp);
+       storage_name = mailbox;
+       ns = mail_namespace_find(cmd->client->user->namespaces, &storage_name);
        if (ns == NULL) {
                client_send_tagline(cmd, "NO Unknown namespace.");
                return NULL;
        }
-       mailbox = *mailboxp;
 
-       if (mode == CLIENT_VERIFY_MAILBOX_NONE)
+       if (mailbox_status_r == NULL) {
+               *storage_name_r = storage_name;
                return ns;
+       }
 
        /* make sure it even looks valid */
-       if (*mailbox == '\0' && !(*orig_mailbox != '\0' && ns->list)) {
+       if (*storage_name == '\0' && !(*mailbox != '\0' && ns->list)) {
                client_send_tagline(cmd, "NO Empty mailbox name.");
                return NULL;
        }
 
-       mailbox_len = strlen(mailbox);
+       sep = mailbox_list_get_hierarchy_sep(ns->list);
+       storage_name_len = strlen(storage_name);
        if ((cmd->client->set->parsed_workarounds &
                        WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
-           mailbox[mailbox_len-1] == mailbox_list_get_hierarchy_sep(ns->list)) {
+           storage_name[storage_name_len-1] == sep) {
                /* drop the extra trailing hierarchy separator */
-               mailbox = t_strndup(mailbox, mailbox_len-1);
-               *mailboxp = mailbox;
+               storage_name = t_strndup(storage_name, storage_name_len-1);
        }
 
-       if (ns->real_sep != ns->sep && ns->prefix_len < strlen(orig_mailbox)) {
+       if (ns->real_sep != ns->sep && ns->prefix_len < strlen(mailbox)) {
                /* make sure there are no real separators used in the mailbox
                   name. */
-               orig_mailbox += ns->prefix_len;
-               for (p = orig_mailbox; *p != '\0'; p++) {
+               mailbox += ns->prefix_len;
+               for (p = mailbox; *p != '\0'; p++) {
                        if (*p == ns->real_sep) {
                                client_send_tagline(cmd, t_strdup_printf(
                                        "NO Character not allowed "
@@ -70,94 +72,63 @@ client_find_namespace(struct client_command_context *cmd, const char **mailboxp,
        }
 
        /* make sure two hierarchy separators aren't next to each others */
-       for (p = mailbox+1; *p != '\0'; p++) {
+       for (p = storage_name+1; *p != '\0'; p++) {
                if (p[0] == ns->real_sep && p[-1] == ns->real_sep) {
                        client_send_tagline(cmd, "NO Invalid mailbox name.");
                        return NULL;
                }
        }
 
-       if (mailbox_len > MAILBOX_MAX_NAME_LEN) {
+       if (storage_name_len > MAILBOX_MAX_NAME_LEN) {
                client_send_tagline(cmd, "NO Mailbox name too long.");
                return NULL;
        }
 
        /* check what our storage thinks of it */
-       if (mailbox_list_get_mailbox_name_status(ns->list, mailbox,
-                                                &mailbox_status) < 0) {
+       if (mailbox_list_get_mailbox_name_status(ns->list, storage_name,
+                                                mailbox_status_r) < 0) {
                client_send_list_error(cmd, ns->list);
                return NULL;
        }
+       *storage_name_r = storage_name;
+       return ns;
+}
 
-       switch (mailbox_status) {
+void client_fail_mailbox_name_status(struct client_command_context *cmd,
+                                    const char *mailbox_name,
+                                    const char *resp_code,
+                                    enum mailbox_name_status status)
+{
+       switch (status) {
        case MAILBOX_NAME_EXISTS_MAILBOX:
        case MAILBOX_NAME_EXISTS_DIR:
-               switch (mode) {
-               case CLIENT_VERIFY_MAILBOX_SHOULD_EXIST:
-               case CLIENT_VERIFY_MAILBOX_SHOULD_EXIST_TRYCREATE:
-                       if (mailbox_status == MAILBOX_NAME_EXISTS_DIR)
-                               break;
-                       return ns;
-               case CLIENT_VERIFY_MAILBOX_NONE:
-               case CLIENT_VERIFY_MAILBOX_NAME:
-               case CLIENT_VERIFY_MAILBOX_DIR_SHOULD_EXIST:
-                       return ns;
-               case CLIENT_VERIFY_MAILBOX_SHOULD_NOT_EXIST:
-                       if (mailbox_status == MAILBOX_NAME_EXISTS_DIR)
-                               return ns;
-                       break;
-               case CLIENT_VERIFY_MAILBOX_DIR_SHOULD_NOT_EXIST:
-                       break;
-               }
-
                client_send_tagline(cmd, t_strconcat(
                        "NO [", IMAP_RESP_CODE_ALREADYEXISTS,
-                       "] Mailbox exists.", NULL));
+                       "] Mailbox already exists: ",
+                       str_sanitize(mailbox_name, MAILBOX_MAX_NAME_LEN),
+                       NULL));
                break;
-
        case MAILBOX_NAME_VALID:
-               resp_code = "";
-               switch (mode) {
-               case CLIENT_VERIFY_MAILBOX_NAME:
-               case CLIENT_VERIFY_MAILBOX_SHOULD_NOT_EXIST:
-               case CLIENT_VERIFY_MAILBOX_DIR_SHOULD_NOT_EXIST:
-               case CLIENT_VERIFY_MAILBOX_DIR_SHOULD_EXIST:
-                       return ns;
-               case CLIENT_VERIFY_MAILBOX_SHOULD_EXIST:
-                       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:
-                       i_unreached();
-               }
-
-               if (*resp_code != '\0')
+               if (resp_code == NULL)
+                       resp_code = "";
+               else
                        resp_code = t_strconcat("[", resp_code, "] ", NULL);
                client_send_tagline(cmd, t_strconcat(
                        "NO ", resp_code, "Mailbox doesn't exist: ",
-                       str_sanitize(orig_mailbox, MAILBOX_MAX_NAME_LEN),
+                       str_sanitize(mailbox_name, MAILBOX_MAX_NAME_LEN),
                        NULL));
                break;
-
        case MAILBOX_NAME_INVALID:
                client_send_tagline(cmd, t_strconcat(
                        "NO Invalid mailbox name: ",
-                       str_sanitize(orig_mailbox, MAILBOX_MAX_NAME_LEN),
+                       str_sanitize(mailbox_name, MAILBOX_MAX_NAME_LEN),
                        NULL));
                break;
-
        case MAILBOX_NAME_NOINFERIORS:
                client_send_tagline(cmd,
-                       "NO Mailbox parent doesn't allow inferior mailboxes.");
+                       "NO Parent mailbox doesn't allow child mailboxes.");
                break;
-
-       default:
-                i_unreached();
        }
-       return NULL;
 }
 
 bool client_verify_open_mailbox(struct client_command_context *cmd)
index 078bea5d7c0add739222ad2cba61062fa7179cb9..8fe49269f5aec31c8eb49659ff18d1bc8f55e039 100644 (file)
@@ -1,23 +1,6 @@
 #ifndef IMAP_COMMANDS_UTIL_H
 #define IMAP_COMMANDS_UTIL_H
 
-enum client_verify_mailbox_mode {
-       /* Don't verify mailbox name validity */
-       CLIENT_VERIFY_MAILBOX_NONE,
-       /* Verify only that the mailbox name is valid */
-       CLIENT_VERIFY_MAILBOX_NAME,
-       /* If mailbox doesn't exist, fail with [NONEXISTENT] resp code */
-       CLIENT_VERIFY_MAILBOX_SHOULD_EXIST,
-       /* Like above, but allow also non-selectable mailboxes */
-       CLIENT_VERIFY_MAILBOX_DIR_SHOULD_EXIST,
-       /* If mailbox doesn't exist, fail with [TRYCREATE] resp code */
-       CLIENT_VERIFY_MAILBOX_SHOULD_EXIST_TRYCREATE,
-       /* If mailbox exists, fail with [ALREADYEXISTS] resp code */
-       CLIENT_VERIFY_MAILBOX_SHOULD_NOT_EXIST,
-       /* If dir/mailbox exists, fail with [ALREADYEXISTS] resp code */
-       CLIENT_VERIFY_MAILBOX_DIR_SHOULD_NOT_EXIST
-};
-
 struct msgset_generator_context {
        string_t *str;
        uint32_t first_uid, last_uid;
@@ -29,8 +12,15 @@ struct mailbox_keywords;
 /* Finds namespace for given mailbox from namespaces. If namespace isn't found
    or mailbox name is invalid, sends a tagged NO reply to client. */
 struct mail_namespace *
-client_find_namespace(struct client_command_context *cmd, const char **mailbox,
-                     enum client_verify_mailbox_mode mode);
+client_find_namespace(struct client_command_context *cmd, const char *mailbox,
+                     const char **storage_name_r,
+                     enum mailbox_name_status *mailbox_status_r);
+
+/* Send tagged NO reply based on mailbox name status. */
+void client_fail_mailbox_name_status(struct client_command_context *cmd,
+                                    const char *mailbox_name,
+                                    const char *resp_code,
+                                    enum mailbox_name_status status);
 
 /* Returns TRUE if mailbox is selected. If not, sends "No mailbox selected"
    error message to client. */