]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: mailbox_alloc() now takes a virtual mailbox name and other related API...
authorTimo Sirainen <tss@iki.fi>
Thu, 20 Jan 2011 18:59:07 +0000 (20:59 +0200)
committerTimo Sirainen <tss@iki.fi>
Thu, 20 Jan 2011 18:59:07 +0000 (20:59 +0200)
All storage_name <-> vname conversions now go through the same two
mailbox_list methods. This has many benefits, such as:

 * listescape plugin is now much simpler and bugfree
 * allows changing lib-storage API to use UTF-8 mailbox names in future
 * allows creation of "mailbox aliases" plugin

68 files changed:
TODO
src/doveadm/doveadm-mail-import.c
src/doveadm/doveadm-mail-iter.c
src/doveadm/doveadm-mail-list-iter.c
src/doveadm/doveadm-mail-mailbox.c
src/doveadm/doveadm-mail.c
src/dsync/dsync-worker-local.c
src/imap/cmd-create.c
src/imap/cmd-delete.c
src/imap/cmd-list.c
src/imap/cmd-namespace.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
src/lib-lda/mail-deliver.c
src/lib-storage/index/cydir/cydir-storage.c
src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c
src/lib-storage/index/dbox-multi/mdbox-storage.c
src/lib-storage/index/dbox-multi/mdbox-storage.h
src/lib-storage/index/dbox-single/sdbox-storage.c
src/lib-storage/index/imapc/imapc-storage.c
src/lib-storage/index/index-storage.c
src/lib-storage/index/index-storage.h
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/index/raw/raw-storage.c
src/lib-storage/index/shared/shared-list.c
src/lib-storage/index/shared/shared-storage.c
src/lib-storage/list/index-mailbox-list.c
src/lib-storage/list/mailbox-list-fs-iter.c
src/lib-storage/list/mailbox-list-fs.c
src/lib-storage/list/mailbox-list-maildir-iter.c
src/lib-storage/list/mailbox-list-maildir.c
src/lib-storage/list/mailbox-list-maildir.h
src/lib-storage/list/mailbox-list-none.c
src/lib-storage/list/mailbox-list-subscriptions.c
src/lib-storage/mail-namespace.c
src/lib-storage/mail-namespace.h
src/lib-storage/mail-search.c
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/lib-storage/mailbox-list-private.h
src/lib-storage/mailbox-list.c
src/lib-storage/mailbox-list.h
src/lib-storage/test-mail-storage.h
src/lib-storage/test-mailbox.c
src/plugins/acl/acl-backend-vfile-acllist.c
src/plugins/acl/acl-backend-vfile.c
src/plugins/acl/acl-mailbox-list.c
src/plugins/autocreate/autocreate-plugin.c
src/plugins/fts-solr/fts-backend-solr.c
src/plugins/fts/fts-storage.c
src/plugins/imap-acl/imap-acl-plugin.c
src/plugins/imap-quota/imap-quota-plugin.c
src/plugins/listescape/listescape-plugin.c
src/plugins/quota/quota-count.c
src/plugins/quota/quota-maildir.c
src/plugins/quota/quota-storage.c
src/plugins/quota/quota.c
src/plugins/snarf/snarf-plugin.c
src/plugins/trash/trash-plugin.c
src/plugins/virtual/virtual-config.c
src/plugins/virtual/virtual-storage.c
src/pop3/pop3-client.c

diff --git a/TODO b/TODO
index ae9166af8a11af8a058eb18645048425ebe04c79..e8cc4b05823637b57153daf4804d6508879c4a28 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,5 @@
+ - check:
+    - dsyncing between two namespace separators is probably broken..
  - remove mail_deliver_session after all, do all the stuff transparently
    by hooking into mailbox_copy().
      - use this hook also to do the mail deduplication: 1) sort all destination
index 3994279251fc2d74ffd8493fa5963dd64ab180f8..c7868beeb12dafb3b42baee8270b30421947569c 100644 (file)
@@ -24,29 +24,27 @@ dest_mailbox_open_or_create(struct import_cmd_context *ctx,
        struct mail_namespace *ns;
        struct mailbox *box;
        enum mail_error error;
-       const char *errstr, *storage_name;
+       const char *errstr;
 
        if (*ctx->dest_parent != '\0') {
                /* prefix destination mailbox name with given parent mailbox */
-               storage_name = ctx->dest_parent;
-               ns = mail_namespace_find(user->namespaces, &storage_name);
+               ns = mail_namespace_find(user->namespaces, ctx->dest_parent);
                if (ns == NULL) {
                        i_error("Can't find namespace for parent mailbox %s",
                                ctx->dest_parent);
                        return -1;
                }
                name = t_strdup_printf("%s%c%s", ctx->dest_parent,
-                                      ns->sep, name);
+                                      mail_namespace_get_sep(ns), name);
        }
 
-       storage_name = name;
-       ns = mail_namespace_find(user->namespaces, &storage_name);
+       ns = mail_namespace_find(user->namespaces, name);
        if (ns == NULL) {
                i_error("Can't find namespace for mailbox %s", name);
                return -1;
        }
 
-       box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_SAVEONLY |
+       box = mailbox_alloc(ns->list, name, MAILBOX_FLAG_SAVEONLY |
                            MAILBOX_FLAG_KEEP_RECENT);
        if (mailbox_create(box, NULL, FALSE) < 0) {
                errstr = mailbox_get_last_error(box, &error);
index 89e08c5ad4cad259bbec7bdb6c9f6549144deffb..a7b838622b6be9e57e78549130306296aa8ea0e6 100644 (file)
@@ -20,12 +20,9 @@ int doveadm_mail_iter_init(const struct mailbox_info *info,
                           struct doveadm_mail_iter **iter_r)
 {
        struct doveadm_mail_iter *iter;
-       const char *storage_name;
-
-       storage_name = mail_namespace_get_storage_name(info->ns, info->name);
 
        iter = i_new(struct doveadm_mail_iter, 1);
-       iter->box = mailbox_alloc(info->ns->list, storage_name,
+       iter->box = mailbox_alloc(info->ns->list, info->name,
                                  MAILBOX_FLAG_KEEP_RECENT |
                                  MAILBOX_FLAG_IGNORE_ACLS);
        iter->search_args = search_args;
index fd94291d377bdaa897fc37e9de60e9d0838e6125..e8d80bfb35a2aaccc28d29c836647ce497d86d9c 100644 (file)
@@ -119,19 +119,22 @@ doveadm_mail_list_iter_next(struct doveadm_mail_list_iter *iter)
        unsigned int len;
 
        while ((info = mailbox_list_iter_next(iter->iter)) != NULL) {
+               char sep = mail_namespace_get_sep(info->ns);
+
                if ((info->flags & (MAILBOX_NOSELECT |
                                    MAILBOX_NONEXISTENT)) != 0) {
                        if (iter->only_selectable)
                                continue;
                }
                len = strlen(info->name);
-               if (len > 0 && info->name[len-1] == info->ns->sep) {
+               if (len > 0 &&
+                   info->name[len-1] == sep) {
                        /* when listing "foo/%" it lists "foo/". skip it. */
                        continue;
                }
 
                if (mail_search_args_match_mailbox(iter->search_args,
-                                                  info->name, info->ns->sep))
+                                                  info->name, sep))
                        break;
        }
        return info;
index b0c4fc679ec6ca2e73af3071f9158deea271d77c..00a9f084e12e50a3157bb6b5cd28129647b47709 100644 (file)
@@ -184,33 +184,34 @@ cmd_mailbox_create_run(struct doveadm_mail_cmd_context *_ctx,
        struct mailbox_cmd_context *ctx = (struct mailbox_cmd_context *)_ctx;
        struct mail_namespace *ns;
        struct mailbox *box;
+       struct mail_storage *storage;
        const char *const *namep;
 
        array_foreach(&ctx->mailboxes, namep) {
-               const char *storage_name = *namep;
+               const char *name = *namep;
                unsigned int len;
                bool directory = FALSE;
 
-               ns = mail_namespace_find(user->namespaces, &storage_name);
+               ns = mail_namespace_find(user->namespaces, name);
                if (ns == NULL)
-                       i_fatal("Can't find namespace for: %s", *namep);
+                       i_fatal("Can't find namespace for: %s", name);
 
-               len = strlen(storage_name);
-               if (len > 0 && storage_name[len-1] == ns->real_sep) {
-                       storage_name = t_strndup(storage_name, len-1);
+               len = strlen(name);
+               if (len > 0 && name[len-1] == mail_namespace_get_sep(ns)) {
+                       name = t_strndup(name, len-1);
                        directory = TRUE;
                }
 
-               box = mailbox_alloc(ns->list, storage_name, 0);
+               box = mailbox_alloc(ns->list, name, 0);
+               storage = mailbox_get_storage(box);
                if (mailbox_create(box, NULL, directory) < 0) {
-                       i_error("Can't create mailbox %s: %s", *namep,
+                       i_error("Can't create mailbox %s: %s", name,
                                mailbox_get_last_error(box, NULL));
                }
                if (ctx->ctx.subscriptions) {
-                       if (mailbox_list_set_subscribed(ns->list, storage_name,
-                                                       TRUE) < 0) {
-                               i_error("Can't subscribe to mailbox %s: %s", *namep,
-                                       mailbox_list_get_last_error(ns->list, NULL));
+                       if (mailbox_set_subscribed(box, TRUE) < 0) {
+                               i_error("Can't subscribe to mailbox %s: %s", name,
+                                       mail_storage_get_last_error(storage, NULL));
                        }
                }
                mailbox_free(&box);
@@ -252,25 +253,26 @@ cmd_mailbox_delete_run(struct doveadm_mail_cmd_context *_ctx,
        struct mailbox_cmd_context *ctx = (struct mailbox_cmd_context *)_ctx;
        struct mail_namespace *ns;
        struct mailbox *box;
+       struct mail_storage *storage;
        const char *const *namep;
 
        array_foreach(&ctx->mailboxes, namep) {
-               const char *storage_name = *namep;
+               const char *name = *namep;
 
-               ns = mail_namespace_find(user->namespaces, &storage_name);
+               ns = mail_namespace_find(user->namespaces, name);
                if (ns == NULL)
-                       i_fatal("Can't find namespace for: %s", *namep);
+                       i_fatal("Can't find namespace for: %s", name);
 
-               box = mailbox_alloc(ns->list, storage_name, 0);
+               box = mailbox_alloc(ns->list, name, 0);
+               storage = mailbox_get_storage(box);
                if (mailbox_delete(box) < 0) {
-                       i_error("Can't delete mailbox %s: %s", *namep,
+                       i_error("Can't delete mailbox %s: %s", name,
                                mailbox_get_last_error(box, NULL));
                }
                if (ctx->ctx.subscriptions) {
-                       if (mailbox_list_set_subscribed(ns->list, storage_name,
-                                                       FALSE) < 0) {
-                               i_error("Can't unsubscribe mailbox %s: %s", *namep,
-                                       mailbox_list_get_last_error(ns->list, NULL));
+                       if (mailbox_set_subscribed(box, FALSE) < 0) {
+                               i_error("Can't unsubscribe mailbox %s: %s", name,
+                                       mail_storage_get_last_error(storage, NULL));
                        }
                }
                mailbox_free(&box);
@@ -315,10 +317,10 @@ cmd_mailbox_rename_run(struct doveadm_mail_cmd_context *_ctx,
        const char *oldname = ctx->oldname;
        const char *newname = ctx->newname;
 
-       oldns = mail_namespace_find(user->namespaces, &oldname);
+       oldns = mail_namespace_find(user->namespaces, oldname);
        if (oldns == NULL)
                i_fatal("Can't find namespace for: %s", oldname);
-       newns = mail_namespace_find(user->namespaces, &newname);
+       newns = mail_namespace_find(user->namespaces, newname);
        if (newns == NULL)
                i_fatal("Can't find namespace for: %s", newname);
 
@@ -329,13 +331,13 @@ cmd_mailbox_rename_run(struct doveadm_mail_cmd_context *_ctx,
                        mailbox_get_last_error(oldbox, NULL));
        }
        if (ctx->ctx.subscriptions) {
-               if (mailbox_list_set_subscribed(oldns->list, oldname, FALSE) < 0) {
+               if (mailbox_set_subscribed(oldbox, FALSE) < 0) {
                        i_error("Can't unsubscribe mailbox %s: %s", ctx->oldname,
-                               mailbox_list_get_last_error(oldns->list, NULL));
+                               mailbox_get_last_error(oldbox, NULL));
                }
-               if (mailbox_list_set_subscribed(newns->list, newname, TRUE) < 0) {
+               if (mailbox_set_subscribed(newbox, TRUE) < 0) {
                        i_error("Can't subscribe to mailbox %s: %s", ctx->newname,
-                               mailbox_list_get_last_error(newns->list, NULL));
+                               mailbox_get_last_error(newbox, NULL));
                }
        }
 
@@ -376,19 +378,18 @@ cmd_mailbox_subscribe_run(struct doveadm_mail_cmd_context *_ctx,
        const char *const *namep;
 
        array_foreach(&ctx->mailboxes, namep) {
-               const char *storage_name = *namep;
+               const char *name = *namep;
 
-               ns = mail_namespace_find(user->namespaces, &storage_name);
+               ns = mail_namespace_find(user->namespaces, name);
                if (ns == NULL)
-                       i_fatal("Can't find namespace for: %s", *namep);
+                       i_fatal("Can't find namespace for: %s", name);
 
-               box = mailbox_alloc(ns->list, storage_name, 0);
-               if (mailbox_list_set_subscribed(ns->list, storage_name,
-                                               ctx->ctx.subscriptions) < 0) {
-                       i_error("Can't %s mailbox %s: %s", *namep,
+               box = mailbox_alloc(ns->list, name, 0);
+               if (mailbox_set_subscribed(box, ctx->ctx.subscriptions) < 0) {
+                       i_error("Can't %s mailbox %s: %s", name,
                                ctx->ctx.subscriptions ? "subscribe to" :
                                "unsubscribe",
-                               mailbox_list_get_last_error(ns->list, NULL));
+                               mail_storage_get_last_error(mailbox_get_storage(box), NULL));
                }
                mailbox_free(&box);
        }
index 721cc6b0a3062f8cdde064aaa9dd7d6503d9021f..098d5f31db8d09f4a4e195fb93faf0a172df628d 100644 (file)
@@ -82,7 +82,7 @@ doveadm_mailbox_find(struct mail_user *user, const char *mailbox)
                i_fatal("Mailbox name not valid UTF-8: %s", mailbox);
        mailbox = str_c(str);
 
-       ns = mail_namespace_find(user->namespaces, &mailbox);
+       ns = mail_namespace_find(user->namespaces, mailbox);
        if (ns == NULL)
                i_fatal("Can't find namespace for mailbox %s", mailbox);
 
index 52ee4e6196ee34649c3137e8deb3e29164ebb78a..5a98fa9888654e265dcd688c046d66b44529b952 100644 (file)
@@ -13,6 +13,7 @@
 #include "mail-namespace.h"
 #include "mail-storage.h"
 #include "mail-search-build.h"
+#include "mailbox-list-private.h"
 #include "dsync-worker-private.h"
 
 #include <ctype.h>
@@ -48,7 +49,7 @@ struct local_dsync_worker_msg_iter {
 struct local_dsync_mailbox {
        struct mail_namespace *ns;
        mailbox_guid_t guid;
-       const char *storage_name;
+       const char *name;
 };
 
 struct local_dsync_mailbox_change {
@@ -442,8 +443,7 @@ local_worker_mailbox_iter_init(struct dsync_worker *_worker)
 
 static void
 local_dsync_worker_add_mailbox(struct local_dsync_worker *worker,
-                              struct mail_namespace *ns,
-                              const char *storage_name,
+                              struct mail_namespace *ns, const char *name,
                               const mailbox_guid_t *guid)
 {
        struct local_dsync_mailbox *lbox;
@@ -451,7 +451,7 @@ local_dsync_worker_add_mailbox(struct local_dsync_worker *worker,
        lbox = p_new(worker->pool, struct local_dsync_mailbox, 1);
        lbox->ns = ns;
        memcpy(lbox->guid.guid, guid->guid, sizeof(lbox->guid.guid));
-       lbox->storage_name = p_strdup(worker->pool, storage_name);
+       lbox->name = p_strdup(worker->pool, name);
 
        hash_table_insert(worker->mailbox_hash, &lbox->guid, lbox);
 }
@@ -535,9 +535,9 @@ local_worker_mailbox_iter_next(struct dsync_worker_mailbox_iter *_iter,
                return iter_next_deleted(iter, worker, dsync_box_r);
 
        dsync_box_r->name = info->name;
-       dsync_box_r->name_sep = info->ns->sep;
+       dsync_box_r->name_sep = mail_namespace_get_sep(info->ns);
 
-       storage_name = mail_namespace_get_storage_name(info->ns, info->name);
+       storage_name = mailbox_list_get_storage_name(info->ns->list, info->name);
        dsync_str_sha_to_guid(storage_name, &dsync_box_r->name_sha1);
 
        /* get last change timestamp */
@@ -553,12 +553,12 @@ local_worker_mailbox_iter_next(struct dsync_worker_mailbox_iter *_iter,
 
        if ((info->flags & MAILBOX_NOSELECT) != 0) {
                dsync_box_r->flags |= DSYNC_MAILBOX_FLAG_NOSELECT;
-               local_dsync_worker_add_mailbox(worker, info->ns, storage_name,
+               local_dsync_worker_add_mailbox(worker, info->ns, info->name,
                                               &dsync_box_r->name_sha1);
                return 1;
        }
 
-       box = mailbox_alloc(info->ns->list, storage_name, flags);
+       box = mailbox_alloc(info->ns->list, info->name, flags);
        if (mailbox_get_status(box, status_items, &status) < 0 ||
            mailbox_get_metadata(box, metadata_items, &metadata) < 0) {
                i_error("Failed to sync mailbox %s: %s", info->name,
@@ -596,12 +596,12 @@ local_worker_mailbox_iter_next(struct dsync_worker_mailbox_iter *_iter,
                i_error("Mailboxes don't have unique GUIDs: "
                        "%s is shared by %s and %s",
                        dsync_guid_to_str(&dsync_box_r->mailbox_guid),
-                       old_lbox->storage_name, storage_name);
+                       old_lbox->name, info->name);
                mailbox_free(&box);
                _iter->failed = TRUE;
                return -1;
        }
-       local_dsync_worker_add_mailbox(worker, info->ns, storage_name,
+       local_dsync_worker_add_mailbox(worker, info->ns, info->name,
                                       &dsync_box_r->mailbox_guid);
        mailbox_free(&box);
        return 1;
@@ -642,18 +642,6 @@ local_worker_subs_iter_init(struct dsync_worker *_worker)
        return &iter->iter;
 }
 
-static struct mail_namespace *
-find_subscription_ns(struct local_dsync_worker *worker, const char *vname)
-{
-       struct mail_namespace *const *nsp;
-
-       array_foreach(&worker->subs_namespaces, nsp) {
-               if (strncmp((*nsp)->prefix, vname, (*nsp)->prefix_len) == 0)
-                       return *nsp;
-       }
-       return NULL;
-}
-
 static int
 local_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter,
                            struct dsync_worker_subscription *rec_r)
@@ -664,7 +652,6 @@ local_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter,
                (struct local_dsync_worker *)_iter->worker;
        struct local_dsync_dir_change *change, change_lookup;
        const struct mailbox_info *info;
-       struct mail_namespace *subs_ns;
        const char *storage_name;
 
        memset(rec_r, 0, sizeof(*rec_r));
@@ -673,13 +660,7 @@ local_worker_subs_iter_next(struct dsync_worker_subs_iter *_iter,
        if (info == NULL)
                return -1;
 
-       subs_ns = find_subscription_ns(worker, info->name);
-       if (subs_ns == NULL)
-               subs_ns = info->ns;
-       storage_name = mail_namespace_get_storage_name(subs_ns, info->name);
-       if (subs_ns != info->ns)
-               storage_name = t_strconcat(subs_ns->prefix, storage_name, NULL);
-
+       storage_name = mailbox_list_get_storage_name(info->ns->list, info->name);
        dsync_str_sha_to_guid(storage_name, &change_lookup.name_sha1);
        change_lookup.list = info->ns->list;
 
@@ -748,36 +729,27 @@ local_worker_set_subscribed(struct dsync_worker *_worker,
 {
        struct local_dsync_worker *worker =
                (struct local_dsync_worker *)_worker;
-       struct mail_namespace *ns, *subs_ns;
-       const char *storage_name;
+       struct mail_namespace *ns;
+       struct mailbox *box;
 
-       storage_name = name;
-       ns = mail_namespace_find(worker->user->namespaces,
-                                &storage_name);
+       ns = mail_namespace_find(worker->user->namespaces, name);
        if (ns == NULL) {
                i_error("Can't find namespace for mailbox %s", name);
                return;
        }
 
-       subs_ns = find_subscription_ns(worker, name);
-       if (subs_ns != NULL) {
-               /* subscription is being written to a different namespace
-                  than where the mailbox exists. */
-               storage_name = mail_namespace_get_storage_name(subs_ns, name);
-               storage_name = t_strconcat(subs_ns->prefix, storage_name, NULL);
-               /* drop the common prefix */
-               i_assert(strncmp(ns->prefix, storage_name,
-                                strlen(ns->prefix)) == 0);
-               storage_name += strlen(ns->prefix);
-       }
+       box = mailbox_alloc(ns->list, name, 0);
+       ns = mailbox_get_namespace(box);
 
        mailbox_list_set_changelog_timestamp(ns->list, last_change);
-       if (mailbox_list_set_subscribed(ns->list, storage_name, set) < 0) {
+       if (mailbox_set_subscribed(box, set) < 0) {
                dsync_worker_set_failure(_worker);
                i_error("Can't update subscription %s: %s", name,
-                       mailbox_list_get_last_error(ns->list, NULL));
+                       mail_storage_get_last_error(mailbox_get_storage(box),
+                                                   NULL));
        }
        mailbox_list_set_changelog_timestamp(ns->list, (time_t)-1);
+       mailbox_free(&box);
 }
 
 static int local_mailbox_open(struct local_dsync_worker *worker,
@@ -796,10 +768,10 @@ static int local_mailbox_open(struct local_dsync_worker *worker,
                return -1;
        }
 
-       box = mailbox_alloc(lbox->ns->list, lbox->storage_name, flags);
+       box = mailbox_alloc(lbox->ns->list, lbox->name, flags);
        if (mailbox_sync(box, 0) < 0 ||
            mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0) {
-               i_error("Failed to sync mailbox %s: %s", lbox->storage_name,
+               i_error("Failed to sync mailbox %s: %s", lbox->name,
                        mailbox_get_last_error(box, NULL));
                mailbox_free(&box);
                return -1;
@@ -807,7 +779,7 @@ static int local_mailbox_open(struct local_dsync_worker *worker,
 
        if (memcmp(metadata.guid, guid->guid, sizeof(guid->guid)) != 0) {
                i_error("Mailbox %s changed its GUID (%s -> %s)",
-                       lbox->storage_name, dsync_guid_to_str(guid),
+                       lbox->name, dsync_guid_to_str(guid),
                        mail_guid_128_to_string(metadata.guid));
                mailbox_free(&box);
                return -1;
@@ -1071,16 +1043,19 @@ local_worker_convert_mailbox_name(struct local_dsync_worker *worker,
                                  const struct dsync_mailbox *dsync_box,
                                  bool creating)
 {
-       if (dsync_box->name_sep != ns->sep) {
+       char list_sep, ns_sep = mail_namespace_get_sep(ns);
+
+       if (dsync_box->name_sep != ns_sep) {
                /* mailbox names use different separators. convert them. */
                name = mailbox_name_convert(worker, name,
-                                           dsync_box->name_sep, ns->sep);
+                                           dsync_box->name_sep, ns_sep);
        }
        if (creating) {
+               list_sep = mailbox_list_get_hierarchy_sep(ns->list);
                if (!mailbox_list_is_valid_create_name(ns->list, name)) {
                        /* change any real separators to alt separators,
                           drop any potentially invalid characters */
-                       name = mailbox_name_cleanup(name, ns->real_sep,
+                       name = mailbox_name_cleanup(name, list_sep,
                                                    worker->alt_char);
                }
                if (!mailbox_list_is_valid_create_name(ns->list, name)) {
@@ -1119,17 +1094,16 @@ local_worker_mailbox_alloc(struct local_dsync_worker *worker,
                                  &dsync_box->mailbox_guid);
        if (lbox != NULL) {
                /* use the existing known mailbox name */
-               return mailbox_alloc(lbox->ns->list, lbox->storage_name, 0);
+               return mailbox_alloc(lbox->ns->list, lbox->name, 0);
        }
 
-       name = dsync_box->name;
-       ns = mail_namespace_find(worker->user->namespaces, &name);
+       ns = mail_namespace_find(worker->user->namespaces, dsync_box->name);
        if (ns == NULL) {
                i_error("Can't find namespace for mailbox %s", dsync_box->name);
                return NULL;
        }
 
-       name = local_worker_convert_mailbox_name(worker, name, ns,
+       name = local_worker_convert_mailbox_name(worker, dsync_box->name, ns,
                                                 dsync_box, creating);
        if (!dsync_mailbox_is_noselect(dsync_box)) {
                local_dsync_worker_add_mailbox(worker, ns, name,
@@ -1261,9 +1235,9 @@ local_worker_delete_mailbox(struct dsync_worker *_worker,
 
        mailbox_list_set_changelog_timestamp(lbox->ns->list,
                                             dsync_box->last_change);
-       box = mailbox_alloc(lbox->ns->list, lbox->storage_name, 0);
+       box = mailbox_alloc(lbox->ns->list, lbox->name, 0);
        if (mailbox_delete(box) < 0) {
-               i_error("Can't delete mailbox %s: %s", lbox->storage_name,
+               i_error("Can't delete mailbox %s: %s", lbox->name,
                        mailbox_get_last_error(box, NULL));
                dsync_worker_set_failure(_worker);
        }
@@ -1280,8 +1254,8 @@ local_worker_delete_dir(struct dsync_worker *_worker,
        struct mail_namespace *ns;
        const char *storage_name;
 
-       storage_name = dsync_box->name;
-       ns = mail_namespace_find(worker->user->namespaces, &storage_name);
+       ns = mail_namespace_find(worker->user->namespaces, dsync_box->name);
+       storage_name = mailbox_list_get_storage_name(ns->list, dsync_box->name);
 
        mailbox_list_set_changelog_timestamp(ns->list, dsync_box->last_change);
        if (mailbox_list_delete_dir(ns->list, storage_name) < 0) {
@@ -1315,21 +1289,21 @@ local_worker_rename_mailbox(struct dsync_worker *_worker,
        list = lbox->ns->list;
        newname = local_worker_convert_mailbox_name(worker, dsync_box->name,
                                                    lbox->ns, dsync_box, TRUE);
-       if (strcmp(lbox->storage_name, newname) == 0) {
+       if (strcmp(lbox->name, newname) == 0) {
                /* nothing changed after all. probably because some characters
                   in mailbox name weren't valid. */
                return;
        }
 
        mailbox_list_set_changelog_timestamp(list, dsync_box->last_change);
-       old_box = mailbox_alloc(list, lbox->storage_name, 0);
+       old_box = mailbox_alloc(list, lbox->name, 0);
        new_box = mailbox_alloc(list, newname, 0);
        if (mailbox_rename(old_box, new_box, FALSE) < 0) {
-               i_error("Can't rename mailbox %s to %s: %s", lbox->storage_name,
+               i_error("Can't rename mailbox %s to %s: %s", lbox->name,
                        newname, mailbox_get_last_error(old_box, NULL));
                dsync_worker_set_failure(_worker);
        } else {
-               lbox->storage_name = p_strdup(worker->pool, newname);
+               lbox->name = p_strdup(worker->pool, newname);
        }
        mailbox_free(&old_box);
        mailbox_free(&new_box);
index 941fcfd726f133798668cfecffcd7663d412c16c..b14e17a6d223538f52e1cce510c260f58c15a139 100644 (file)
@@ -8,7 +8,7 @@
 bool cmd_create(struct client_command_context *cmd)
 {
        struct mail_namespace *ns;
-       const char *mailbox, *storage_name;
+       const char *mailbox, *orig_mailbox;
        struct mailbox *box;
        bool directory;
        size_t len;
@@ -17,36 +17,27 @@ bool cmd_create(struct client_command_context *cmd)
        if (!client_read_string_args(cmd, 1, &mailbox))
                return FALSE;
 
-       ns = client_find_namespace(cmd, mailbox, &storage_name);
+       orig_mailbox = mailbox;
+       ns = client_find_namespace(cmd, &mailbox);
        if (ns == NULL)
                return TRUE;
 
-       len = strlen(mailbox);
-       if (len == 0 || mailbox[len-1] != ns->sep)
+       len = strlen(orig_mailbox);
+       if (len == 0 || orig_mailbox[len-1] != mail_namespace_get_sep(ns))
                directory = FALSE;
-       else if (*storage_name == '\0') {
-               client_send_tagline(cmd, "NO ["IMAP_RESP_CODE_ALREADYEXISTS
-                                   "] Namespace already exists.");
-               return TRUE;
-       } else {
+       else {
                /* name ends with hierarchy separator - client is just
                   informing us that it wants to create children under this
                   mailbox. */
                 directory = TRUE;
-               mailbox = t_strndup(mailbox, len-1);
 
-               /* drop also from storage_name. it's already dropped when
+               /* drop separator from mailbox. it's already dropped when
                   WORKAROUND_TB_EXTRA_MAILBOX_SEP is enabled */
-               len = strlen(storage_name);
-               if (storage_name[len-1] == ns->real_sep)
-                       storage_name = t_strndup(storage_name, len-1);
+               if (len == strlen(mailbox))
+                       mailbox = t_strndup(mailbox, len-1);
        }
 
-       ns = client_find_namespace(cmd, mailbox, &storage_name);
-       if (ns == NULL)
-               return TRUE;
-
-       box = mailbox_alloc(ns->list, storage_name, 0);
+       box = mailbox_alloc(ns->list, mailbox, 0);
        if (mailbox_create(box, NULL, directory) < 0)
                client_send_storage_error(cmd, mailbox_get_storage(box));
        else
index a65327a8ae2a88a3830347c5187dd02505498fba..1612f837cda1dfa0ac2f426d4bdc55545b1b7fc6 100644 (file)
@@ -8,7 +8,7 @@ bool cmd_delete(struct client_command_context *cmd)
        struct client *client = cmd->client;
        struct mail_namespace *ns;
        struct mailbox *box;
-       const char *name, *storage_name;
+       const char *name;
 
        /* <mailbox> */
        if (!client_read_string_args(cmd, 1, &name))
@@ -20,11 +20,11 @@ bool cmd_delete(struct client_command_context *cmd)
                return TRUE;
        }
 
-       ns = client_find_namespace(cmd, name, &storage_name);
+       ns = client_find_namespace(cmd, &name);
        if (ns == NULL)
                return TRUE;
 
-       box = mailbox_alloc(ns->list, storage_name, 0);
+       box = mailbox_alloc(ns->list, name, 0);
        if (client->mailbox != NULL &&
            mailbox_backends_equal(box, client->mailbox)) {
                /* deleting selected mailbox. close it first */
index 234e2ba003eb59c96fd8c3d35d55349c5f4e1d9b..7aca23d4f4d29ac97d824694d84138c1163b14a7 100644 (file)
@@ -225,10 +225,10 @@ static const char *ns_get_listed_prefix(struct cmd_list_context *ctx)
        bool inboxcase;
 
        inboxcase = strncasecmp(ctx->ns->prefix, "INBOX", 5) == 0 &&
-               ctx->ns->prefix[5] == ctx->ns->sep;
+               ctx->ns->prefix[5] == mail_namespace_get_sep(ctx->ns);
        glob = imap_match_init_multiple(pool_datastack_create(),
                                        ctx->patterns, inboxcase,
-                                       ctx->ns->sep);
+                                       mail_namespace_get_sep(ctx->ns));
        ns_prefix = ctx->ns->prefix;
        match = imap_match(glob, ns_prefix);
        if (match == IMAP_MATCH_YES) {
@@ -237,7 +237,7 @@ static const char *ns_get_listed_prefix(struct cmd_list_context *ctx)
        }
 
        while ((match & IMAP_MATCH_PARENT) != 0) {
-               p = strrchr(ns_prefix, ctx->ns->sep);
+               p = strrchr(ns_prefix, mail_namespace_get_sep(ctx->ns));
                i_assert(p != NULL);
                ns_prefix = t_strdup_until(ns_prefix, p);
                match = imap_match(glob, ns_prefix);
@@ -246,6 +246,16 @@ static const char *ns_get_listed_prefix(struct cmd_list_context *ctx)
        return ns_prefix;
 }
 
+static void list_reply_append_ns_sep_param(string_t *str, char sep)
+{
+       str_append_c(str, '"');
+       if (sep == '\\')
+               str_append(str, "\\\\");
+       else
+               str_append_c(str, sep);
+       str_append_c(str, '"');
+}
+
 static void
 list_namespace_send_prefix(struct cmd_list_context *ctx, bool have_children)
 {
@@ -255,6 +265,7 @@ list_namespace_send_prefix(struct cmd_list_context *ctx, bool have_children)
        const char *name;
        string_t *str;
        bool same_ns, ends_with_sep;
+       char ns_sep = mail_namespace_get_sep(ctx->ns);
 
        ctx->cur_ns_send_prefix = FALSE;
 
@@ -267,7 +278,7 @@ list_namespace_send_prefix(struct cmd_list_context *ctx, bool have_children)
 
        name = ns_get_listed_prefix(ctx);
        len = strlen(ctx->ns->prefix);
-       ends_with_sep = ctx->ns->prefix[len-1] == ctx->ns->sep;
+       ends_with_sep = ctx->ns->prefix[len-1] == ns_sep;
 
        /* we may be listing namespace's parent. in such case we always want to
           set the name as nonexistent. */
@@ -314,9 +325,13 @@ list_namespace_send_prefix(struct cmd_list_context *ctx, bool have_children)
        }
 
        str = t_str_new(128);
-       str_append(str, "* LIST (");
+       str_printfa(str, "* %s (", ctx->lsub ? "LSUB" : "LIST");
+       if (ctx->lsub)
+               flags |= MAILBOX_NONEXISTENT;
        mailbox_flags2str(ctx, str, flags);
-       str_printfa(str, ") \"%s\" ", ctx->ns->sep_str);
+       str_append(str, ") ");
+       list_reply_append_ns_sep_param(str, ns_sep);
+       str_append_c(str, ' ');
        imap_quote_append_string(str, name, FALSE);
        mailbox_childinfo2str(ctx, str, flags);
 
@@ -328,7 +343,7 @@ static void list_send_status(struct cmd_list_context *ctx, const char *name,
 {
        struct imap_status_result result;
        struct mail_namespace *ns;
-       const char *storage_name, *error;
+       const char *error;
 
        if ((flags & (MAILBOX_NONEXISTENT | MAILBOX_NOSELECT)) != 0) {
                /* doesn't exist, don't even try to get STATUS */
@@ -342,9 +357,8 @@ static void list_send_status(struct cmd_list_context *ctx, const char *name,
 
        /* if we're listing subscriptions and there are subscriptions=no
           namespaces, ctx->ns may not point to correct one */
-       storage_name = name;
-       ns = mail_namespace_find(ctx->ns->user->namespaces, &storage_name);
-       if (imap_status_get(ctx->cmd, ns, storage_name,
+       ns = mail_namespace_find(ctx->ns->user->namespaces, name);
+       if (imap_status_get(ctx->cmd, ns, name,
                            &ctx->status_items, &result, &error) < 0) {
                client_send_line(ctx->cmd->client,
                                 t_strconcat("* ", error, NULL));
@@ -427,7 +441,10 @@ list_namespace_mailboxes(struct cmd_list_context *ctx)
                str_truncate(str, 0);
                str_printfa(str, "* %s (", ctx->lsub ? "LSUB" : "LIST");
                mailbox_flags2str(ctx, str, flags);
-               str_printfa(str, ") \"%s\" ", ctx->ns->sep_str);
+               str_append(str, ") ");
+               list_reply_append_ns_sep_param(str,
+                       mail_namespace_get_sep(ctx->ns));
+               str_append_c(str, ' ');
                imap_quote_append_string(str, name, FALSE);
                mailbox_childinfo2str(ctx, str, flags);
 
@@ -506,7 +523,7 @@ skip_namespace_prefix_ref(struct cmd_list_context *ctx,
                     -> cur_ns_prefix="", cur_ref="baz"
                   */
                skip_namespace_prefix(&cur_ns_prefix, &cur_ref, TRUE,
-                                     ctx->ns->sep);
+                                     mail_namespace_get_sep(ctx->ns));
 
                if (*cur_ref != '\0' && *cur_ns_prefix != '\0') {
                        /* reference parameter didn't match with
@@ -537,7 +554,8 @@ skip_namespace_prefix_pattern(struct cmd_list_context *ctx,
        i_assert(*cur_ref == '\0');
 
        skip_namespace_prefix(&cur_ns_prefix, &cur_pattern,
-                             cur_ref == ctx->ref, ctx->ns->sep);
+                             cur_ref == ctx->ref,
+                             mail_namespace_get_sep(ctx->ns));
 
        if (*cur_pattern == '\0' && *cur_ns_prefix == '\0') {
                /* trying to list the namespace prefix itself. */
@@ -567,7 +585,7 @@ list_use_inboxcase(struct cmd_list_context *ctx)
                inbox_glob =
                        imap_match_init(pool_datastack_create(),
                                        t_strconcat(ctx->ref, *pat, NULL),
-                                       TRUE, ctx->ns->sep);
+                                       TRUE, mail_namespace_get_sep(ctx->ns));
                match = imap_match(inbox_glob, "INBOX");
 
                if (match == IMAP_MATCH_YES)
@@ -582,16 +600,8 @@ static bool
 list_want_send_prefix(struct cmd_list_context *ctx, const char *pattern)
 {
        /* don't send the prefix if we're listing subscribed mailboxes */
-       if ((ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
-               if ((ctx->ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) == 0) {
-                       /* using parent's subscriptions file. it'll handle
-                          this internally */
-                       return FALSE;
-               }
-               /* send prefix if namespace has at least some subscriptions,
-                  but pattern doesn't match any children (e.g. "%") */
-               return TRUE;
-       }
+       if ((ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0)
+               return FALSE;
 
        /* send the prefix if namespace is listable. if children are listable
           we may or may not need to send it. */
@@ -644,7 +654,7 @@ list_namespace_match_pattern(struct cmd_list_context *ctx, bool inboxcase,
           don't do it if we're listing only the prefix itself
           (LIST "" foo/ needs to return "foo/" entry) */
        len = strlen(cur_ns_prefix);
-       if (cur_ns_prefix[len-1] == ns->sep &&
+       if (cur_ns_prefix[len-1] == mail_namespace_get_sep(ns) &&
            strcmp(cur_pattern, cur_ns_prefix) != 0) {
                ctx->cur_ns_skip_trailing_sep = TRUE;
                cur_ns_prefix = t_strndup(cur_ns_prefix, len-1);
@@ -658,7 +668,7 @@ list_namespace_match_pattern(struct cmd_list_context *ctx, bool inboxcase,
 
        /* check if this namespace prefix matches the current pattern */
        pat_glob = imap_match_init(pool_datastack_create(), orig_cur_pattern,
-                                  inboxcase, ns->sep);
+                                  inboxcase, mail_namespace_get_sep(ns));
        match = imap_match(pat_glob, cur_ns_prefix);
        if (match == IMAP_MATCH_YES) {
                if (list_want_send_prefix(ctx, orig_cur_pattern))
@@ -670,9 +680,14 @@ list_namespace_match_pattern(struct cmd_list_context *ctx, bool inboxcase,
                        if (*p == '*')
                                return TRUE;
                }
+               if ((ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
+                       /* the namespace prefix itself may be subscribed. */
+                       return TRUE;
+               }
+               return FALSE;
        } else {
                while ((match & IMAP_MATCH_PARENT) != 0) {
-                       p = strrchr(cur_ns_prefix, ns->sep);
+                       p = strrchr(cur_ns_prefix, mail_namespace_get_sep(ns));
                        if (p == NULL)
                                break;
                        cur_ns_prefix = t_strdup_until(cur_ns_prefix, p);
@@ -685,9 +700,8 @@ list_namespace_match_pattern(struct cmd_list_context *ctx, bool inboxcase,
                        if (list_want_send_prefix(ctx, orig_cur_pattern))
                                ctx->cur_ns_send_prefix = TRUE;
                }
+               return (match & IMAP_MATCH_CHILDREN) != 0;
        }
-
-       return (match & IMAP_MATCH_CHILDREN) != 0;
 }
 
 static void list_namespace_init(struct cmd_list_context *ctx)
@@ -701,12 +715,6 @@ static void list_namespace_init(struct cmd_list_context *ctx)
        cur_ns_prefix = ns->prefix;
        cur_ref = ctx->ref;
 
-       if ((ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) == 0 &&
-           (ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
-               /* ignore namespaces which don't have subscriptions */
-               return;
-       }
-
        ctx->cur_ns_skip_trailing_sep = FALSE;
 
        if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0)
@@ -750,22 +758,24 @@ static void list_namespace_init(struct cmd_list_context *ctx)
        (void)array_append_space(&used_patterns); /* NULL-terminate */
        pat = array_idx(&used_patterns, 0);
 
-       cur_ref = mail_namespace_fix_sep(ns, cur_ref);
        ctx->list_iter = mailbox_list_iter_init_multiple(ns->list, pat,
                                                         ctx->list_flags);
 }
 
 static void list_inbox(struct cmd_list_context *ctx)
 {
-       const char *str;
+       string_t *str;
 
        /* INBOX always exists */
        if (!ctx->inbox_found && ctx->cur_ns_match_inbox &&
            (ctx->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
            (ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0) {
-               str = t_strdup_printf("* LIST (\\Unmarked) \"%s\" \"INBOX\"",
-                                     ctx->ns->sep_str);
-               client_send_line(ctx->cmd->client, str);
+               str = t_str_new(64);
+               str_append(str, "* LIST (\\Unmarked) ");
+               list_reply_append_ns_sep_param(str,
+                       mail_namespace_get_sep(ctx->ns));
+               str_append(str, " \"INBOX\"");
+               client_send_line(ctx->cmd->client, str_c(str));
        }
 }
 
@@ -821,10 +831,10 @@ static void cmd_list_ref_root(struct client *client, const char *ref)
        /* Special request to return the hierarchy delimiter and mailbox root
           name. If namespace has a prefix, it's returned as the mailbox root.
           Otherwise we'll emulate UW-IMAP behavior. */
-       ns = mail_namespace_find_visible(client->user->namespaces, &ref);
+       ns = mail_namespace_find_visible(client->user->namespaces, ref);
        if (ns != NULL) {
                ns_prefix = ns->prefix;
-               ns_sep = ns->sep;
+               ns_sep = mail_namespace_get_sep(ns);
        } else {
                ns_prefix = "";
                ns_sep = mail_namespaces_get_root_sep(client->user->namespaces);
index 1075047004412118787c30e41cce1fa7cd1228e4..6f1c0274447d9f64d01a6a3523fe0de1209cb1ab 100644 (file)
@@ -9,6 +9,7 @@
 static void list_namespaces(struct mail_namespace *ns,
                            enum namespace_type type, string_t *str)
 {
+       char ns_sep;
        bool found = FALSE;
 
        while (ns != NULL) {
@@ -18,10 +19,13 @@ static void list_namespaces(struct mail_namespace *ns,
                                str_append_c(str, '(');
                                found = TRUE;
                        }
+                       ns_sep = mail_namespace_get_sep(ns);
                        str_append_c(str, '(');
                        imap_quote_append_string(str, ns->prefix, FALSE);
                        str_append(str, " \"");
-                       str_append(str, ns->sep_str);
+                       if (ns_sep == '\\')
+                               str_append_c(str, '\\');
+                       str_append_c(str, ns_sep);
                        str_append(str, "\")");
                }
 
index 56a97fc2cac3418144ea9466032af03d8b198c33..3d44fd1c50e68f75a8fc80dbd3357b44a0945d12 100644 (file)
@@ -8,17 +8,17 @@ bool cmd_rename(struct client_command_context *cmd)
 {
        struct mail_namespace *old_ns, *new_ns;
        struct mailbox *old_box, *new_box;
-       const char *oldname, *newname, *storage_oldname, *storage_newname;
+       const char *oldname, *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, &storage_oldname);
+       old_ns = client_find_namespace(cmd, &oldname);
        if (old_ns == NULL)
                return TRUE;
-       new_ns = client_find_namespace(cmd, newname, &storage_newname);
+       new_ns = client_find_namespace(cmd, &newname);
        if (new_ns == NULL)
                return TRUE;
 
@@ -26,17 +26,17 @@ bool cmd_rename(struct client_command_context *cmd)
                /* 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(storage_oldname);
-               if (strncmp(storage_oldname, storage_newname, oldlen) == 0 &&
-                   storage_newname[oldlen] == old_ns->real_sep) {
+               oldlen = strlen(oldname);
+               if (strncmp(oldname, newname, oldlen) == 0 &&
+                   newname[oldlen] == mail_namespace_get_sep(old_ns)) {
                        client_send_tagline(cmd,
                                "NO Can't rename mailbox under its own child.");
                        return TRUE;
                }
        }
 
-       old_box = mailbox_alloc(old_ns->list, storage_oldname, 0);
-       new_box = mailbox_alloc(new_ns->list, storage_newname, 0);
+       old_box = mailbox_alloc(old_ns->list, oldname, 0);
+       new_box = mailbox_alloc(new_ns->list, newname, 0);
        if (mailbox_rename(old_box, new_box, TRUE) < 0)
                client_send_storage_error(cmd, mailbox_get_storage(old_box));
        else
index 6294b219384fef9e6d62c4876cbd35278b3f6d60..e986ed78ecbbcd04be2b8a6c28ca2ea88229777e 100644 (file)
@@ -373,7 +373,7 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
        struct client *client = cmd->client;
        struct imap_select_context *ctx;
        const struct imap_arg *args, *list_args;
-       const char *mailbox, *storage_name;
+       const char *mailbox;
        int ret;
 
        /* <mailbox> [(optional parameters)] */
@@ -388,7 +388,7 @@ 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, &storage_name);
+       ctx->ns = client_find_namespace(cmd, &mailbox);
        if (ctx->ns == NULL) {
                close_selected_mailbox(client);
                return TRUE;
@@ -413,7 +413,7 @@ bool cmd_select_full(struct client_command_context *cmd, bool readonly)
                (void)client_enable(client, MAILBOX_FEATURE_CONDSTORE);
        }
 
-       ret = select_open(ctx, storage_name, readonly);
+       ret = select_open(ctx, mailbox, readonly);
        if (ret == 0)
                return FALSE;
        cmd_select_finish(ctx, ret);
index 20fd2bf0864b1b75bba0308fffa0f0ea895e1490..53900d4aad81e2fc3fc4bbbdce8f5b00c6739fa9 100644 (file)
@@ -13,7 +13,7 @@ bool cmd_status(struct client_command_context *cmd)
        struct imap_status_items items;
        struct imap_status_result result;
        struct mail_namespace *ns;
-       const char *mailbox, *storage_name, *error;
+       const char *mailbox, *error;
        bool selected_mailbox;
 
        /* <mailbox> <status items> */
@@ -30,13 +30,13 @@ bool cmd_status(struct client_command_context *cmd)
        if (imap_status_parse_items(cmd, list_args, &items) < 0)
                return TRUE;
 
-       ns = client_find_namespace(cmd, mailbox, &storage_name);
+       ns = client_find_namespace(cmd, &mailbox);
        if (ns == NULL)
                return TRUE;
 
        selected_mailbox = client->mailbox != NULL &&
-               mailbox_equals(client->mailbox, ns, storage_name);
-       if (imap_status_get(cmd, ns, storage_name, &items,
+               mailbox_equals(client->mailbox, ns, mailbox);
+       if (imap_status_get(cmd, ns, mailbox, &items,
                            &result, &error) < 0) {
                client_send_tagline(cmd, error);
                return TRUE;
index 95dbaf18117e34adf53ac8c16d2823e8c0d85211..889c44deaf0456fbdf00f66e79287da807c270b2 100644 (file)
@@ -4,58 +4,19 @@
 #include "imap-commands.h"
 #include "mail-namespace.h"
 
-static bool have_listable_namespace_prefix(struct mail_namespace *ns,
-                                          const char *name)
-{
-       unsigned int name_len = strlen(name);
-
-       for (; ns != NULL; ns = ns->next) {
-               if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
-                                 NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
-                       continue;
-
-               if (ns->prefix_len <= name_len)
-                       continue;
-
-               /* if prefix has multiple hierarchies, allow subscribing to
-                  any of the hierarchies */
-               if (strncmp(ns->prefix, name, name_len) == 0 &&
-                   ns->prefix[name_len] == ns->sep)
-                       return TRUE;
-       }
-       return FALSE;
-}
-
 static bool
-subscribe_is_valid_name(struct client_command_context *cmd, const char *mailbox)
+subscribe_is_valid_name(struct client_command_context *cmd, struct mailbox *box)
 {
-       struct mail_namespace *ns;
-       struct mailbox *box;
-       const char *storage_name;
        int ret;
 
-       if (have_listable_namespace_prefix(cmd->client->user->namespaces,
-                                          mailbox)) {
-               /* subscribing to a listable namespace prefix, allow it. */
-               return TRUE;
-       }
-
-       /* see if the mailbox exists */
-       ns = client_find_namespace(cmd, mailbox, &storage_name);
-       if (ns == NULL)
-               return FALSE;
-
-       box = mailbox_alloc(ns->list, storage_name, 0);
        if ((ret = mailbox_exists(box)) < 0) {
                client_send_storage_error(cmd, mailbox_get_storage(box));
-               mailbox_free(&box);
                return FALSE;
        }
-       mailbox_free(&box);
-
        if (ret == 0) {
                client_send_tagline(cmd, t_strdup_printf(
-                       "NO "MAIL_ERRSTR_MAILBOX_NOT_FOUND, mailbox));
+                       "NO "MAIL_ERRSTR_MAILBOX_NOT_FOUND,
+                       mailbox_get_vname(box)));
                return FALSE;
        }
        return TRUE;
@@ -63,71 +24,46 @@ subscribe_is_valid_name(struct client_command_context *cmd, const char *mailbox)
 
 bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
 {
-       struct mail_namespace *ns, *box_ns;
-       const char *mailbox, *storage_name, *subs_name, *subs_name2 = NULL;
+       struct mail_namespace *ns;
+       struct mailbox *box, *box2;
+       const char *mailbox, *orig_mailbox;
        bool unsubscribed_mailbox2;
 
        /* <mailbox> */
        if (!client_read_string_args(cmd, 1, &mailbox))
                return FALSE;
+       orig_mailbox = mailbox;
 
-       box_ns = client_find_namespace(cmd, mailbox, &storage_name);
-       if (box_ns == NULL)
-               return TRUE;
-       if (!mailbox_list_is_valid_existing_name(box_ns->list, storage_name)) {
-               client_send_tagline(cmd, "NO [CANNOT] Invalid mailbox name");
+       ns = client_find_namespace(cmd, &mailbox);
+       if (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,
-                                             &subs_name);
-       if (ns == NULL) {
-               client_send_tagline(cmd, "NO Unknown subscription namespace.");
-               return TRUE;
-       }
-
-       if (ns != box_ns) {
-               /* subscription is being written to a different namespace
-                  than where the mailbox exists. */
-               subs_name = t_strconcat(box_ns->prefix, storage_name, NULL);
-               /* drop the common 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 &&
-           *subs_name != '\0' &&
-           subs_name[strlen(subs_name)-1] == ns->real_sep) {
-               /* verify the validity without the trailing '/' */
-               mailbox = t_strndup(mailbox, strlen(mailbox)-1);
-               subs_name2 = subs_name;
-               subs_name = t_strndup(subs_name, strlen(subs_name)-1);
-       }
 
+       box = mailbox_alloc(ns->list, mailbox, 0);
        if (subscribe) {
-               if (!subscribe_is_valid_name(cmd, mailbox))
+               if (!subscribe_is_valid_name(cmd, box)) {
+                       mailbox_free(&box);
                        return TRUE;
+               }
        }
 
        unsubscribed_mailbox2 = FALSE;
-       if (!subscribe && subs_name2 != NULL) {
+       if (!subscribe && mailbox != orig_mailbox) {
                /* try to unsubscribe both "box" and "box/" */
-               if (mailbox_list_set_subscribed(ns->list, subs_name2,
-                                               FALSE) == 0)
+               box2 = mailbox_alloc(ns->list, orig_mailbox, 0);
+               if (mailbox_set_subscribed(box2, FALSE) == 0)
                        unsubscribed_mailbox2 = TRUE;
+               mailbox_free(&box2);
        }
 
-       if (mailbox_list_set_subscribed(ns->list, subs_name, subscribe) < 0 &&
+       if (mailbox_set_subscribed(box, subscribe) < 0 &&
            !unsubscribed_mailbox2) {
-               client_send_list_error(cmd, ns->list);
+               client_send_storage_error(cmd, mailbox_get_storage(box));
        } else {
                client_send_tagline(cmd, subscribe ?
                                    "OK Subscribe completed." :
                                    "OK Unsubscribe completed.");
        }
+       mailbox_free(&box);
        return TRUE;
 }
 
index 0c2281696b722bbef49b15a23db4dbda47cc95e6..4dfe9aba739ff483c0f7edca2c62cf6cc787bc42 100644 (file)
 #include "imap-commands-util.h"
 
 struct mail_namespace *
-client_find_namespace(struct client_command_context *cmd, const char *mailbox,
-                     const char **storage_name_r)
+client_find_namespace(struct client_command_context *cmd, const char **mailbox)
 {
        struct mail_namespace *namespaces = cmd->client->user->namespaces;
        struct mail_namespace *ns;
-       const char *storage_name, *p;
-       unsigned int storage_name_len;
+       unsigned int name_len;
 
-       storage_name = mailbox;
-       ns = mail_namespace_find(namespaces, &storage_name);
+       ns = mail_namespace_find(namespaces, *mailbox);
        if (ns == NULL) {
                client_send_tagline(cmd, t_strdup_printf(
                        "NO Client tried to access nonexistent namespace. "
@@ -32,31 +29,14 @@ client_find_namespace(struct client_command_context *cmd, const char *mailbox,
                return NULL;
        }
 
-       storage_name_len = strlen(storage_name);
+       name_len = strlen(*mailbox);
        if ((cmd->client->set->parsed_workarounds &
                        WORKAROUND_TB_EXTRA_MAILBOX_SEP) != 0 &&
-           storage_name_len > 0 &&
-           storage_name[storage_name_len-1] == ns->real_sep) {
+           name_len > 0 &&
+           (*mailbox)[name_len-1] == mail_namespace_get_sep(ns)) {
                /* drop the extra trailing hierarchy separator */
-               storage_name = t_strndup(storage_name, storage_name_len-1);
+               *mailbox = t_strndup(*mailbox, name_len-1);
        }
-
-       if (ns->real_sep != ns->sep && ns->prefix_len < strlen(mailbox)) {
-               /* make sure there are no real separators used in the mailbox
-                  name. */
-               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 "
-                                       "in mailbox name: '%c'",
-                                       ns->real_sep));
-                               return NULL;
-                       }
-               }
-       }
-
-       *storage_name_r = storage_name;
        return ns;
 }
 
@@ -75,19 +55,19 @@ int client_open_save_dest_box(struct client_command_context *cmd,
 {
        struct mail_namespace *ns;
        struct mailbox *box;
-       const char *storage_name, *error_string;
+       const char *error_string;
        enum mail_error error;
 
-       ns = client_find_namespace(cmd, name, &storage_name);
+       ns = client_find_namespace(cmd, &name);
        if (ns == NULL)
                return -1;
 
        if (cmd->client->mailbox != NULL &&
-           mailbox_equals(cmd->client->mailbox, ns, storage_name)) {
+           mailbox_equals(cmd->client->mailbox, ns, name)) {
                *destbox_r = cmd->client->mailbox;
                return 0;
        }
-       box = mailbox_alloc(ns->list, storage_name,
+       box = mailbox_alloc(ns->list, name,
                            MAILBOX_FLAG_SAVEONLY | MAILBOX_FLAG_KEEP_RECENT);
        if (mailbox_open(box) < 0) {
                error_string = mailbox_get_last_error(box, &error);
@@ -335,7 +315,7 @@ bool mailbox_equals(const struct mailbox *box1,
        if (ns1 != ns2)
                return FALSE;
 
-        name1 = mailbox_get_name(box1);
+        name1 = mailbox_get_vname(box1);
        if (strcmp(name1, name2) == 0)
                return TRUE;
 
index 6eb6c50473ef9e342513c93346fe0f19c8efd6d0..9d1e9fa81c77db066f968be0d96c2e72c118fac8 100644 (file)
@@ -12,8 +12,7 @@ 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,
-                     const char **storage_name_r);
+client_find_namespace(struct client_command_context *cmd, const char **mailbox);
 
 /* Returns TRUE if mailbox is selected. If not, sends "No mailbox selected"
    error message to client. */
index ed3d398adedfbf668deea67746816204294de25b..686e70592ed35acc5e73c00908795ff87b51afc2 100644 (file)
@@ -141,14 +141,15 @@ int mail_deliver_save_open(struct mail_deliver_save_open_context *ctx,
        *error_str_r = NULL;
 
        name = mailbox_name_to_mutf7(name);
-       ns = mail_namespace_find(ctx->user->namespaces, &name);
+       ns = mail_namespace_find(ctx->user->namespaces, name);
        if (ns == NULL) {
                *error_str_r = "Unknown namespace";
                *error_r = MAIL_ERROR_PARAMS;
                return -1;
        }
 
-       if (*name == '\0' && (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
+       if (strcmp(name, ns->prefix) == 0 &&
+           (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
                /* delivering to a namespace prefix means we actually want to
                   deliver to the INBOX instead */
                name = "INBOX";
@@ -178,7 +179,7 @@ int mail_deliver_save_open(struct mail_deliver_save_open_context *ctx,
        }
        if (ctx->lda_mailbox_autosubscribe) {
                /* (try to) subscribe to it */
-               (void)mailbox_list_set_subscribed(ns->list, name, TRUE);
+               (void)mailbox_set_subscribed(box, TRUE);
        }
 
        /* and try opening again */
index 89998f14521a28b420e53a3d4ca062a410bd79f2..d526cf56d2b44d1491384b925e38fa1149e8b574 100644 (file)
@@ -36,7 +36,7 @@ cydir_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
 
 static struct mailbox *
 cydir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                   const char *name, enum mailbox_flags flags)
+                   const char *vname, enum mailbox_flags flags)
 {
        struct cydir_mailbox *mbox;
        struct index_mailbox_context *ibox;
@@ -53,7 +53,7 @@ cydir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.list = list;
        mbox->box.mail_vfuncs = &cydir_mail_vfuncs;
 
-       index_storage_mailbox_alloc(&mbox->box, name, flags,
+       index_storage_mailbox_alloc(&mbox->box, vname, flags,
                                    CYDIR_INDEX_PREFIX);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
index 2ea487d43f9baa812705b0820e3a4b97554963b0..24968b3f8dc7193cd74112be451e11de487386b3 100644 (file)
@@ -495,11 +495,9 @@ rebuild_mailbox(struct mdbox_storage_rebuild_context *ctx,
        struct mail_index_transaction *trans;
        struct dbox_sync_rebuild_context *rebuild_ctx;
        enum mail_error error;
-       const char *name;
        int ret;
 
-       name = mail_namespace_get_storage_name(ns, vname);
-       box = mailbox_alloc(ns->list, name, MAILBOX_FLAG_READONLY |
+       box = mailbox_alloc(ns->list, vname, MAILBOX_FLAG_READONLY |
                            MAILBOX_FLAG_KEEP_RECENT |
                            MAILBOX_FLAG_IGNORE_ACLS);
        i_assert(box->storage == &ctx->storage->storage.storage);
index fc4e5b65e0204fd382c6a3628485f845d4ccb468..7a755ac65d897bf4c68f8c8b2c62da3dbf4bdfe1 100644 (file)
@@ -81,9 +81,9 @@ static void mdbox_storage_destroy(struct mail_storage *_storage)
        dbox_storage_destroy(_storage);
 }
 
-struct mailbox *
+static struct mailbox *
 mdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                   const char *name, enum mailbox_flags flags)
+                   const char *vname, enum mailbox_flags flags)
 {
        struct mdbox_mailbox *mbox;
        struct index_mailbox_context *ibox;
@@ -100,7 +100,8 @@ mdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.list = list;
        mbox->box.mail_vfuncs = &mdbox_mail_vfuncs;
 
-       index_storage_mailbox_alloc(&mbox->box, name, flags, DBOX_INDEX_PREFIX);
+       index_storage_mailbox_alloc(&mbox->box, vname,
+                                   flags, DBOX_INDEX_PREFIX);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
        ibox->save_commit_pre = mdbox_transaction_save_commit_pre;
index c318a95ac60046ace2f0b7b696161f65be7b1260..787f39c37d9f7d7c3c8f7b8c9acd09dc550f0f15 100644 (file)
@@ -61,10 +61,6 @@ struct mdbox_mailbox {
 
 extern struct mail_vfuncs mdbox_mail_vfuncs;
 
-struct mailbox *
-mdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                   const char *name, enum mailbox_flags flags);
-
 int mdbox_mail_open(struct dbox_mail *mail, uoff_t *offset_r,
                    struct dbox_file **file_r);
 
index f97101890fe4f47e105b184cc5333e281c1ada37..5ae2829a61aaff791c65ef431f3a2c6546f1e5c5 100644 (file)
@@ -30,7 +30,7 @@ static struct mail_storage *sdbox_storage_alloc(void)
 
 static struct mailbox *
 sdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                   const char *name, enum mailbox_flags flags)
+                   const char *vname, enum mailbox_flags flags)
 {
        struct sdbox_mailbox *mbox;
        struct index_mailbox_context *ibox;
@@ -47,7 +47,8 @@ sdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.list = list;
        mbox->box.mail_vfuncs = &sdbox_mail_vfuncs;
 
-       index_storage_mailbox_alloc(&mbox->box, name, flags, DBOX_INDEX_PREFIX);
+       index_storage_mailbox_alloc(&mbox->box, vname,
+                                   flags, DBOX_INDEX_PREFIX);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
        ibox->save_commit_pre = sdbox_transaction_save_commit_pre;
index 70e2fe52d208f4561a03be8a8ba09a3fe16c39a8..54a144b2d9c5a183472cadfc67209b79f9ddf084 100644 (file)
@@ -305,7 +305,7 @@ imapc_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
 
 static struct mailbox *
 imapc_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                   const char *name, enum mailbox_flags flags)
+                   const char *vname, enum mailbox_flags flags)
 {
        struct imapc_mailbox *mbox;
        struct index_mailbox_context *ibox;
@@ -321,7 +321,7 @@ imapc_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.list = list;
        mbox->box.mail_vfuncs = &imapc_mail_vfuncs;
 
-       index_storage_mailbox_alloc(&mbox->box, name, flags, NULL);
+       index_storage_mailbox_alloc(&mbox->box, vname, flags, NULL);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
        ibox->save_commit_pre = imapc_transaction_save_commit_pre;
index 7289e618517d0535f9e63ca470bcf87d171918b5..74fbe083c23155e3d9c555332a8c435ef0cefa97 100644 (file)
@@ -250,20 +250,17 @@ int index_storage_mailbox_open(struct mailbox *box, bool move_to_memory)
        return 0;
 }
 
-void index_storage_mailbox_alloc(struct mailbox *box, const char *name,
+void index_storage_mailbox_alloc(struct mailbox *box, const char *vname,
                                 enum mailbox_flags flags,
                                 const char *index_prefix)
 {
        struct index_mailbox_context *ibox;
-       string_t *vname;
 
-       i_assert(name != NULL);
-
-       box->name = p_strdup(box->pool, name);
-       vname = t_str_new(128);
-       mail_namespace_get_vname(box->list->ns, vname, name);
-       box->vname = p_strdup(box->pool, str_c(vname));
+       i_assert(vname != NULL);
 
+       box->vname = p_strdup(box->pool, vname);
+       box->name = p_strdup(box->pool,
+                            mailbox_list_get_storage_name(box->list, vname));
        box->flags = flags;
        box->index_prefix = p_strdup(box->pool, index_prefix);
 
@@ -277,9 +274,9 @@ void index_storage_mailbox_alloc(struct mailbox *box, const char *name,
        ibox->next_lock_notify = time(NULL) + LOCK_NOTIFY_INTERVAL;
        MODULE_CONTEXT_SET(box, index_storage_module, ibox);
 
-       box->inbox_user = strcmp(name, "INBOX") == 0 &&
+       box->inbox_user = strcmp(box->name, "INBOX") == 0 &&
                (box->list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0;
-       box->inbox_any = strcmp(name, "INBOX") == 0 &&
+       box->inbox_any = strcmp(box->name, "INBOX") == 0 &&
                (box->list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0;
 }
 
index fd042c8fef6f002d6ecf22feff0e5ab8e6d55ce8..8d78b85a334c81b811393728fcef83427c85300a 100644 (file)
@@ -60,7 +60,7 @@ void index_storage_lock_notify(struct mailbox *box,
                               unsigned int secs_left);
 void index_storage_lock_notify_reset(struct mailbox *box);
 
-void index_storage_mailbox_alloc(struct mailbox *box, const char *name,
+void index_storage_mailbox_alloc(struct mailbox *box, const char *vname,
                                 enum mailbox_flags flags,
                                 const char *index_prefix);
 int index_storage_mailbox_exists(struct mailbox *box);
index 670b9e9a6edb035bfe2217d9d56a8b36ea0fb510..a2bac9fb8e38e5d85be3282e4487d42e8bcf706f 100644 (file)
@@ -263,7 +263,7 @@ static void maildir_lock_touch_timeout(struct maildir_mailbox *mbox)
 
 static struct mailbox *
 maildir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                     const char *name, enum mailbox_flags flags)
+                     const char *vname, enum mailbox_flags flags)
 {
        struct maildir_mailbox *mbox;
        struct index_mailbox_context *ibox;
@@ -277,7 +277,7 @@ maildir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.list = list;
        mbox->box.mail_vfuncs = &maildir_mail_vfuncs;
 
-       index_storage_mailbox_alloc(&mbox->box, name, flags,
+       index_storage_mailbox_alloc(&mbox->box, vname, flags,
                                    MAILDIR_INDEX_PREFIX);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
index e2620ae93160c3913c83aaed4b52bbe422fa2566..ed5249c3de0159a2e10d13dfddf495a9c87cf9b4 100644 (file)
@@ -345,7 +345,7 @@ static bool want_memory_indexes(struct mbox_storage *storage, const char *path)
 
 static struct mailbox *
 mbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                  const char *name, enum mailbox_flags flags)
+                  const char *vname, enum mailbox_flags flags)
 {
        struct mbox_mailbox *mbox;
        struct index_mailbox_context *ibox;
@@ -359,7 +359,8 @@ mbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.list = list;
        mbox->box.mail_vfuncs = &mbox_mail_vfuncs;
 
-       index_storage_mailbox_alloc(&mbox->box, name, flags, MBOX_INDEX_PREFIX);
+       index_storage_mailbox_alloc(&mbox->box, vname,
+                                   flags, MBOX_INDEX_PREFIX);
 
        ibox = INDEX_STORAGE_CONTEXT(&mbox->box);
        ibox->save_commit_pre = mbox_transaction_save_commit_pre;
index f5a9e5bf76d50091b5961902124ca05a061d6c49..30cd401098666f6d253f5f7676e787834a752937 100644 (file)
@@ -36,7 +36,7 @@ raw_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
 
 static struct mailbox *
 raw_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                 const char *name, enum mailbox_flags flags)
+                 const char *vname, enum mailbox_flags flags)
 {
        struct raw_mailbox *mbox;
        pool_t pool;
@@ -51,7 +51,7 @@ raw_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        mbox->box.list = list;
        mbox->box.mail_vfuncs = &raw_mail_vfuncs;
 
-       index_storage_mailbox_alloc(&mbox->box, name, flags, NULL);
+       index_storage_mailbox_alloc(&mbox->box, vname, flags, NULL);
 
        mbox->mtime = mbox->ctime = (time_t)-1;
        mbox->storage = (struct raw_storage *)storage;
index 52e97a335e2da73c4e348fbb271a88630a21ff49..0b3ceaefe4c0a244c3f89d09ea2fa3f050b5e747 100644 (file)
@@ -43,12 +43,13 @@ static void shared_list_copy_error(struct mailbox_list *shared_list,
 }
 
 static int
-shared_get_storage(struct mailbox_list **list, const char **name,
+shared_get_storage(struct mailbox_list **list, const char *vname,
                   struct mail_storage **storage_r)
 {
        struct mail_namespace *ns = (*list)->ns;
+       const char *name = vname;
 
-       if (shared_storage_get_namespace(&ns, name) < 0)
+       if (shared_storage_get_namespace(&ns, &name) < 0)
                return -1;
        *list = ns->list;
        *storage_r = ns->storage;
@@ -85,6 +86,11 @@ shared_is_valid_create_name(struct mailbox_list *list, const char *name)
        return mailbox_list_is_valid_create_name(ns->list, name);
 }
 
+static char shared_list_get_hierarchy_sep(struct mailbox_list *list ATTR_UNUSED)
+{
+       return '/';
+}
+
 static const char *
 shared_list_get_path(struct mailbox_list *list, const char *name,
                     enum mailbox_list_path_type type)
@@ -145,6 +151,7 @@ shared_list_iter_init(struct mailbox_list *list, const char *const *patterns,
                      enum mailbox_list_iter_flags flags)
 {
        struct shared_mailbox_list_iterate_context *ctx;
+       char sep = mail_namespace_get_sep(list->ns);
 
        ctx = i_new(struct shared_mailbox_list_iterate_context, 1);
        ctx->ctx.list = list;
@@ -153,7 +160,7 @@ shared_list_iter_init(struct mailbox_list *list, const char *const *patterns,
        ctx->info.ns = list->ns;
        ctx->info.flags = MAILBOX_NONEXISTENT;
        ctx->glob = imap_match_init_multiple(default_pool, patterns,
-                                            FALSE, list->ns->sep);
+                                            FALSE, sep);
        return &ctx->ctx;
 }
 
@@ -299,7 +306,6 @@ shared_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
 
 struct mailbox_list shared_mailbox_list = {
        .name = "shared",
-       .hierarchy_sep = '/',
        .props = 0,
        .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
 
@@ -310,6 +316,9 @@ struct mailbox_list shared_mailbox_list = {
                shared_is_valid_pattern,
                shared_is_valid_existing_name,
                shared_is_valid_create_name,
+               shared_list_get_hierarchy_sep,
+               mailbox_list_default_get_vname,
+               mailbox_list_default_get_storage_name,
                shared_list_get_path,
                shared_list_get_temp_prefix,
                shared_list_join_refpattern,
index e80f2a8a8145b4c64be8662b8aef0169ae47d486..6d0bdcbf367cea1f102d3c616d24c12565ebd299 100644 (file)
@@ -130,6 +130,7 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
        const char *domain = NULL, *username = NULL, *userdomain = NULL;
        const char *name, *p, *next, **dest, *error;
        string_t *prefix, *location;
+       char ns_sep = mail_namespace_get_sep(ns);
        int ret;
 
        p = storage->ns_prefix_pattern;
@@ -156,7 +157,7 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
                }
                p++;
 
-               next = strchr(name, *p != '\0' ? *p : ns->sep);
+               next = strchr(name, *p != '\0' ? *p : ns_sep);
                if (next == NULL) {
                        *dest = name;
                        name = "";
@@ -167,7 +168,7 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
        }
        if (*p != '\0') {
                if (*name == '\0' ||
-                   (name[1] == '\0' && *name == ns->sep)) {
+                   (name[1] == '\0' && *name == ns_sep)) {
                        /* trying to open <prefix>/<user> mailbox */
                        name = "INBOX";
                } else {
@@ -223,7 +224,8 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
 
        *_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
        if (*_ns != NULL) {
-               *_name = mail_namespace_fix_sep(ns, name);
+               *_name = mailbox_list_get_storage_name(ns->list,
+                               t_strconcat(ns->prefix, name, NULL));
                return 0;
        }
 
@@ -259,7 +261,6 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
        new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
                NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
                NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
-       new_ns->sep = ns->sep;
        new_ns->mail_set = _storage->set;
 
        location = t_str_new(256);
@@ -276,7 +277,7 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
 
        ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
        ns_set->type = "shared";
-       ns_set->separator = p_strdup_printf(user->pool, "%c", new_ns->sep);
+       ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
        ns_set->prefix = new_ns->prefix;
        ns_set->location = p_strdup(user->pool, str_c(location));
        ns_set->hidden = TRUE;
@@ -298,7 +299,8 @@ int shared_storage_get_namespace(struct mail_namespace **_ns,
                return -1;
        }
        ns->flags |= NAMESPACE_FLAG_USABLE;
-       *_name = mail_namespace_fix_sep(new_ns, name);
+       *_name = mailbox_list_get_storage_name(new_ns->list,
+                               t_strconcat(new_ns->prefix, name, NULL));
        *_ns = new_ns;
 
        mail_user_add_namespace(user, &new_ns);
index d069aa9fdbc0d37cafa4806645f757f409e294d9..73c88f8e30f482db91892e344fb0e8975bd57858 100644 (file)
@@ -100,7 +100,7 @@ index_mailbox_list_is_synced(struct index_mailbox_list_iterate_context *ctx)
 static void pattern_parse(struct mailbox_list *list, const char *pattern,
                          const char **prefix_r, int *recurse_level_r)
 {
-       char sep = list->hierarchy_sep;
+       char sep = mailbox_list_get_hierarchy_sep(list);
        const char *prefix_start, *prefix_end;
        bool seen_wildcards = FALSE;
        int recurse_level = 0;
@@ -188,6 +188,7 @@ index_mailbox_list_iter_init_try(struct index_mailbox_list_iterate_context *ctx,
        const char *prefix, *cur_prefix, *const *tmp;
        enum mailbox_list_iter_flags subs_flags;
        int cur_recurse_level;
+       char sep;
 
        subs_flags = MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
                MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
@@ -198,12 +199,12 @@ index_mailbox_list_iter_init_try(struct index_mailbox_list_iterate_context *ctx,
                return FALSE;
        }
 
-       ctx->glob = imap_match_init_multiple(default_pool, patterns, TRUE,
-                                            list->hierarchy_sep);
+       sep = mailbox_list_get_hierarchy_sep(list);
+       ctx->glob = imap_match_init_multiple(default_pool, patterns, TRUE, sep);
        if ((flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
                      MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) {
                /* we'll need to know the subscriptions */
-               ctx->subs_tree = mailbox_tree_init(list->hierarchy_sep);
+               ctx->subs_tree = mailbox_tree_init(sep);
                if (mailbox_list_subscriptions_fill(&ctx->ctx, ctx->subs_tree,
                                                    ctx->glob, FALSE) < 0) {
                        /* let the backend handle this failure */
@@ -261,8 +262,7 @@ index_mailbox_list_iter_init_try(struct index_mailbox_list_iterate_context *ctx,
                        mailbox_list_index_iterate_init(ctx->view, prefix,
                                                        ctx->recurse_level);
                ctx->prefix = *prefix == '\0' ? i_strdup(ctx->ns_prefix) :
-                       i_strdup_printf("%s%s%c", ctx->ns_prefix, prefix,
-                                       list->hierarchy_sep);
+                       i_strdup_printf("%s%s%c", ctx->ns_prefix, prefix, sep);
        }
        return TRUE;
 }
@@ -457,6 +457,7 @@ static int index_mailbox_list_open_indexes(struct mailbox_list *list,
        struct index_mailbox_list *ilist = INDEX_LIST_CONTEXT(list);
        const char *path;
        enum mail_index_open_flags index_flags = 0;
+       char sep;
        int ret;
 
        index_flags = mail_storage_settings_to_index_flags(list->mail_set);
@@ -479,7 +480,8 @@ static int index_mailbox_list_open_indexes(struct mailbox_list *list,
        }
 
        path = t_strconcat(dir, "/"MAILBOX_LIST_INDEX_NAME, NULL);
-       ilist->list_index = mailbox_list_index_alloc(path, list->hierarchy_sep,
+       sep = mailbox_list_get_hierarchy_sep(list);
+       ilist->list_index = mailbox_list_index_alloc(path, sep,
                                                     ilist->mail_index);
        if (mailbox_list_index_open_or_create(ilist->list_index) < 0) {
                /* skip indexing */
index cf0d57748bdbb076aa7894adda245d257ec8ef23..d27764345e7136e6de8ca3988a78761a0ef05d01 100644 (file)
@@ -223,7 +223,7 @@ fs_list_iter_init(struct mailbox_list *_list, const char *const *patterns,
        ctx->ctx.flags = flags;
        ctx->info_pool = pool_alloconly_create("fs list", 1024);
        ctx->next = fs_list_next;
-       ctx->sep = _list->ns->sep;
+       ctx->sep = mail_namespace_get_sep(_list->ns);
        ctx->info.ns = _list->ns;
 
        prefix_len = strlen(_list->ns->prefix);
@@ -238,7 +238,8 @@ fs_list_iter_init(struct mailbox_list *_list, const char *const *patterns,
                        test_pattern += prefix_len;
                /* check pattern also when it's converted to use real
                   separators. */
-               real_pattern = mail_namespace_fix_sep(_list->ns, test_pattern);
+               real_pattern =
+                       mailbox_list_get_storage_name(_list, test_pattern);
                if (mailbox_list_is_valid_pattern(_list, test_pattern) &&
                    mailbox_list_is_valid_pattern(_list, real_pattern)) {
                        if (strcasecmp(*patterns, "INBOX") == 0) {
@@ -649,7 +650,7 @@ fs_list_subs(struct fs_list_iterate_context *ctx)
        struct mailbox_node *node;
        enum mailbox_info_flags flags;
        struct mail_namespace *ns;
-       const char *path, *dir, *fname, *storage_name;
+       const char *path, *dir, *fname, *subs_name, *storage_name;
        unsigned int len;
        struct stat st;
 
@@ -667,19 +668,18 @@ fs_list_subs(struct fs_list_iterate_context *ctx)
        }
 
        /* see if this is for another subscriptions=no namespace */
-       storage_name = ctx->info.name;
+       subs_name = ctx->info.name;
        ns = mail_namespace_find_unsubscribable(ctx->info.ns->user->namespaces,
-                                               &storage_name);
-       if (ns == NULL) {
+                                               subs_name);
+       if (ns == NULL)
                ns = ctx->info.ns;
-               storage_name = mail_namespace_get_storage_name(ns, storage_name);
-       }
 
        /* if name ends with hierarchy separator, drop the separator */
-       len = strlen(storage_name);
-       if (len > 0 && storage_name[len-1] == ns->real_sep)
-               storage_name = t_strndup(storage_name, len-1);
+       len = strlen(subs_name);
+       if (len > 0 && subs_name[len-1] == mail_namespace_get_sep(ns))
+               subs_name = t_strndup(subs_name, len-1);
 
+       storage_name = mailbox_list_get_storage_name(ns->list, subs_name);
        if (!mailbox_list_is_valid_pattern(ns->list, storage_name)) {
                /* broken entry in subscriptions file */
                ctx->info.flags = MAILBOX_NONEXISTENT;
index b1fef29ca5ca2d844360b57fd2b6d4d74d852352..cc6d08375dda6d719a7f04ca528137eb7c649b9a 100644 (file)
@@ -135,6 +135,11 @@ fs_is_valid_create_name(struct mailbox_list *list, const char *name)
        return fs_list_is_valid_common_nonfs(list, name);
 }
 
+static char fs_list_get_hierarchy_sep(struct mailbox_list *list ATTR_UNUSED)
+{
+       return '/';
+}
+
 static const char *
 fs_list_get_path(struct mailbox_list *_list, const char *name,
                 enum mailbox_list_path_type type)
@@ -368,6 +373,7 @@ static int fs_list_rmdir(struct mailbox_list *list, const char *name,
 static int fs_list_delete_dir(struct mailbox_list *list, const char *name)
 {
        const char *path, *child_name, *child_path, *p;
+       char sep;
 
        path = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR);
        if (fs_list_rmdir(list, name, path) == 0)
@@ -379,8 +385,8 @@ static int fs_list_delete_dir(struct mailbox_list *list, const char *name)
        } else if (errno == ENOTEMPTY || errno == EEXIST) {
                /* mbox workaround: if only .imap/ directory is preventing the
                   deletion, remove it */
-               child_name = t_strdup_printf("%s%cchild", name,
-                                            list->ns->real_sep);
+               sep = mailbox_list_get_hierarchy_sep(list);
+               child_name = t_strdup_printf("%s%cchild", name, sep);
                child_path = mailbox_list_get_path(list, child_name,
                                                   MAILBOX_LIST_PATH_TYPE_INDEX);
                if (strncmp(path, child_path, strlen(path)) == 0) {
@@ -438,7 +444,7 @@ static int fs_list_rename_mailbox(struct mailbox_list *oldlist,
                                  const char *newname, bool rename_children)
 {
        struct mail_storage *oldstorage;
-       const char *oldpath, *newpath, *alt_newpath, *root_path;
+       const char *oldvname, *oldpath, *newpath, *alt_newpath, *root_path;
        const char *p, *origin;
        enum mailbox_list_path_type path_type, alt_path_type;
        struct stat st;
@@ -446,7 +452,8 @@ static int fs_list_rename_mailbox(struct mailbox_list *oldlist,
        gid_t gid;
        bool rmdir_parent = FALSE;
 
-       if (mailbox_list_get_storage(&oldlist, &oldname, &oldstorage) < 0)
+       oldvname = mailbox_list_get_vname(oldlist, oldname);
+       if (mailbox_list_get_storage(&oldlist, oldvname, &oldstorage) < 0)
                return -1;
 
        if (rename_children) {
@@ -564,7 +571,6 @@ static int fs_list_rename_mailbox(struct mailbox_list *oldlist,
 
 struct mailbox_list fs_mailbox_list = {
        .name = MAILBOX_LIST_NAME_FS,
-       .hierarchy_sep = '/',
        .props = 0,
        .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
 
@@ -575,6 +581,9 @@ struct mailbox_list fs_mailbox_list = {
                fs_is_valid_pattern,
                fs_is_valid_existing_name,
                fs_is_valid_create_name,
+               fs_list_get_hierarchy_sep,
+               mailbox_list_default_get_vname,
+               mailbox_list_default_get_storage_name,
                fs_list_get_path,
                fs_list_get_temp_prefix,
                fs_list_join_refpattern,
index a90113d866836f3d15a44784ddf8d468b725ecd4..d43b4d43e3eccd9439d1ec0019275ad77a05f7c3 100644 (file)
@@ -43,31 +43,30 @@ static void node_fix_parents(struct mailbox_node *node)
 static void
 maildir_fill_parents(struct maildir_list_iterate_context *ctx,
                     struct imap_match_glob *glob, bool update_only,
-                    string_t *mailbox)
+                    const char *vname)
 {
        struct mail_namespace *ns = ctx->ctx.list->ns;
        struct mailbox_node *node;
-       const char *p, *mailbox_c;
-       bool created;
+       const char *p;
+       unsigned int vname_len = strlen(vname);
+       bool created, ns_sep = mail_namespace_get_sep(ns);
 
-       mailbox_c = str_c(mailbox);
-       while ((p = strrchr(mailbox_c, ns->sep)) != NULL) {
-               str_truncate(mailbox, (size_t) (p-mailbox_c));
-               mailbox_c = str_c(mailbox);
-               if (imap_match(glob, mailbox_c) != IMAP_MATCH_YES)
+       while ((p = strrchr(vname, ns_sep)) != NULL) {
+               vname = t_strdup_until(vname, p);
+               if (imap_match(glob, vname) != IMAP_MATCH_YES)
                        continue;
 
-               if (ns->prefix_len > 0 && str_len(mailbox) == ns->prefix_len-1 &&
-                   strncmp(mailbox_c, ns->prefix, ns->prefix_len - 1) == 0 &&
-                   mailbox_c[ns->prefix_len-1] == ns->sep) {
+               if (ns->prefix_len > 0 && vname_len == ns->prefix_len-1 &&
+                   strncmp(vname, ns->prefix, ns->prefix_len - 1) == 0 &&
+                   vname[ns->prefix_len-1] == ns_sep) {
                        /* don't return matches to namespace prefix itself */
                        continue;
                }
 
                created = FALSE;
                node = update_only ?
-                       mailbox_tree_lookup(ctx->tree_ctx, mailbox_c) :
-                       mailbox_tree_get(ctx->tree_ctx, mailbox_c, &created);
+                       mailbox_tree_lookup(ctx->tree_ctx, vname) :
+                       mailbox_tree_get(ctx->tree_ctx, vname, &created);
                if (node != NULL) {
                        if (created) {
                                /* we haven't yet seen this mailbox,
@@ -84,21 +83,19 @@ maildir_fill_parents(struct maildir_list_iterate_context *ctx,
 }
 
 static void maildir_set_children(struct maildir_list_iterate_context *ctx,
-                                string_t *mailbox)
+                                const char *vname)
 {
        struct mailbox_node *node;
-       const char *p, *mailbox_c;
+       const char *p;
        char hierarchy_sep;
 
-       hierarchy_sep = ctx->ctx.list->ns->sep;
+       hierarchy_sep = mail_namespace_get_sep(ctx->ctx.list->ns);
 
        /* mark the first existing parent as containing children */
-       mailbox_c = str_c(mailbox);
-       while ((p = strrchr(mailbox_c, hierarchy_sep)) != NULL) {
-               str_truncate(mailbox, (size_t) (p-mailbox_c));
-               mailbox_c = str_c(mailbox);
+       while ((p = strrchr(vname, hierarchy_sep)) != NULL) {
+               vname = t_strdup_until(vname, p);
 
-               node = mailbox_tree_lookup(ctx->tree_ctx, mailbox_c);
+               node = mailbox_tree_lookup(ctx->tree_ctx, vname);
                if (node != NULL) {
                        node->flags &= ~MAILBOX_NOCHILDREN;
                        node->flags |= MAILBOX_CHILDREN;
@@ -263,15 +260,12 @@ static bool maildir_delete_trash_dir(struct maildir_list_iterate_context *ctx,
 }
 
 static int
-maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
-                    struct imap_match_glob *glob, bool update_only)
+maildir_fill_readdir_entry(struct maildir_list_iterate_context *ctx,
+                          struct imap_match_glob *glob, const struct dirent *d,
+                          bool update_only)
 {
        struct mailbox_list *list = ctx->ctx.list;
-       struct mail_namespace *ns = list->ns;
-       DIR *dirp;
-       struct dirent *d;
-       const char *mailbox_name;
-       string_t *mailbox;
+       const char *fname, *storage_name, *vname;
        enum mailbox_info_flags flags;
        enum imap_match_result match;
        struct mailbox_node *node;
@@ -279,6 +273,77 @@ maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
        struct stat st;
        int ret;
 
+       fname = d->d_name;
+       if (fname[0] == ctx->prefix_char)
+               storage_name = fname + 1;
+       else {
+               if (ctx->prefix_char != '\0' || fname[0] == '.')
+                       return 0;
+               storage_name = fname;
+       }
+
+       /* skip . and .. */
+       if (fname[0] == '.' &&
+           (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0')))
+               return 0;
+
+       vname = mailbox_list_get_vname(list, storage_name);
+
+       /* make sure the pattern matches */
+       match = imap_match(glob, vname);
+       if ((match & (IMAP_MATCH_YES | IMAP_MATCH_PARENT)) == 0)
+               return 0;
+
+       /* check if this is an actual mailbox */
+       if (maildir_delete_trash_dir(ctx, fname))
+               return 0;
+
+       T_BEGIN {
+               ret = list->v.get_mailbox_flags(list, ctx->dir, fname,
+                               mailbox_list_get_file_type(d), &st, &flags);
+       } T_END;
+       if (ret <= 0)
+               return ret;
+
+       /* we know the children flags ourself, so ignore if any of
+          them were set. */
+       flags &= ~(MAILBOX_NOINFERIORS | MAILBOX_CHILDREN | MAILBOX_NOCHILDREN);
+
+       if ((match & IMAP_MATCH_PARENT) != 0)
+               maildir_fill_parents(ctx, glob, update_only, vname);
+       else {
+               created = FALSE;
+               node = update_only ?
+                       mailbox_tree_lookup(ctx->tree_ctx, vname) :
+                       mailbox_tree_get(ctx->tree_ctx, vname, &created);
+
+               if (node != NULL) {
+                       if (created)
+                               node->flags = MAILBOX_NOCHILDREN;
+                       else
+                               node->flags &= ~MAILBOX_NONEXISTENT;
+                       if (!update_only)
+                               node->flags |= MAILBOX_MATCHED;
+                       node->flags |= flags;
+                       node_fix_parents(node);
+               } else {
+                       i_assert(update_only);
+                       maildir_set_children(ctx, vname);
+               }
+       }
+       return 0;
+}
+
+static int
+maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
+                    struct imap_match_glob *glob, bool update_only)
+{
+       struct mailbox_list *list = ctx->ctx.list;
+       struct mail_namespace *ns = list->ns;
+       DIR *dirp;
+       struct dirent *d;
+       int ret = 0;
+
        dirp = opendir(ctx->dir);
        if (dirp == NULL) {
                if (errno == EACCES) {
@@ -292,77 +357,13 @@ maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
                return 0;
        }
 
-       mailbox = t_str_new(MAILBOX_LIST_NAME_MAX_LENGTH);
        while ((d = readdir(dirp)) != NULL) {
-               const char *fname = d->d_name;
-
-               if (fname[0] == ctx->prefix_char)
-                       mailbox_name = fname + 1;
-               else {
-                       if (ctx->prefix_char != '\0' || fname[0] == '.')
-                               continue;
-                       mailbox_name = fname;
-               }
-
-               /* skip . and .. */
-               if (fname[0] == '.' &&
-                   (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0')))
-                       continue;
-
-               mailbox_name = mail_namespace_get_vname(ns, mailbox,
-                                                       mailbox_name);
-
-               /* make sure the pattern matches */
-               match = imap_match(glob, mailbox_name);
-               if ((match & (IMAP_MATCH_YES | IMAP_MATCH_PARENT)) == 0)
-                       continue;
-
-               /* check if this is an actual mailbox */
-               if (maildir_delete_trash_dir(ctx, fname))
-                       continue;
-
                T_BEGIN {
-                       ret = list->v.get_mailbox_flags(list, ctx->dir, fname,
-                               mailbox_list_get_file_type(d), &st, &flags);
+                       ret = maildir_fill_readdir_entry(ctx, glob, d,
+                                                        update_only);
                } T_END;
-               if (ret <= 0) {
-                       if (ret < 0)
-                               return -1;
-                       continue;
-               }
-
-               /* we know the children flags ourself, so ignore if any of
-                  them were set. */
-               flags &= ~(MAILBOX_NOINFERIORS |
-                          MAILBOX_CHILDREN | MAILBOX_NOCHILDREN);
-
-               if ((match & IMAP_MATCH_PARENT) != 0) {
-                       T_BEGIN {
-                               maildir_fill_parents(ctx, glob, update_only,
-                                                    mailbox);
-                       } T_END;
-               } else {
-                       created = FALSE;
-                       node = update_only ?
-                               mailbox_tree_lookup(ctx->tree_ctx,
-                                                   mailbox_name) :
-                               mailbox_tree_get(ctx->tree_ctx,
-                                                mailbox_name, &created);
-
-                       if (node != NULL) {
-                               if (created)
-                                       node->flags = MAILBOX_NOCHILDREN;
-                               else
-                                       node->flags &= ~MAILBOX_NONEXISTENT;
-                               if (!update_only)
-                                       node->flags |= MAILBOX_MATCHED;
-                               node->flags |= flags;
-                               node_fix_parents(node);
-                       } else {
-                               i_assert(update_only);
-                               maildir_set_children(ctx, mailbox);
-                       }
-               }
+               if (ret < 0)
+                       break;
        }
 
        if (closedir(dirp) < 0) {
@@ -370,6 +371,8 @@ maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
                                          ctx->dir);
                return -1;
        }
+       if (ret < 0)
+               return -1;
 
        if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
                /* make sure INBOX is listed */
@@ -436,9 +439,12 @@ struct mailbox_list_iterate_context *
 maildir_list_iter_init(struct mailbox_list *_list, const char *const *patterns,
                       enum mailbox_list_iter_flags flags)
 {
+       struct maildir_mailbox_list *list =
+               (struct maildir_mailbox_list *)_list;
        struct maildir_list_iterate_context *ctx;
         struct imap_match_glob *glob;
        pool_t pool;
+       char ns_sep = mail_namespace_get_sep(_list->ns);
        int ret;
 
        pool = pool_alloconly_create("maildir_list", 1024);
@@ -446,12 +452,12 @@ maildir_list_iter_init(struct mailbox_list *_list, const char *const *patterns,
        ctx->ctx.list = _list;
        ctx->ctx.flags = flags;
        ctx->pool = pool;
-       ctx->tree_ctx = mailbox_tree_init(_list->ns->sep);
+       ctx->tree_ctx = mailbox_tree_init(ns_sep);
        ctx->info.ns = _list->ns;
        ctx->prefix_char = strcmp(_list->name, MAILBOX_LIST_NAME_IMAPDIR) == 0 ?
-               '\0' : _list->hierarchy_sep;
+               '\0' : list->sep;
 
-       glob = imap_match_init_multiple(pool, patterns, TRUE, _list->ns->sep);
+       glob = imap_match_init_multiple(pool, patterns, TRUE, ns_sep);
 
        ctx->dir = _list->set.root_dir;
 
index 7b5039cb2c6ddd5cc30207c8f2cd1bf4ec00c29a..bd3d74b3ef5c7ee58b94e331c42e387fcea14e69 100644 (file)
@@ -29,6 +29,7 @@ static struct mailbox_list *maildir_list_alloc(void)
        list = p_new(pool, struct maildir_mailbox_list, 1);
        list->list = maildir_mailbox_list;
        list->list.pool = pool;
+       list->sep = '.';
 
        list->global_temp_prefix = MAILDIR_GLOBAL_TEMP_PREFIX;
        list->temp_prefix = p_strconcat(pool, list->global_temp_prefix,
@@ -69,7 +70,8 @@ maildir_list_get_dirname_path(struct mailbox_list *list, const char *dir,
        else if (list->name == imapdir_mailbox_list.name)
                return t_strdup_printf("%s/%s", dir, name);
 
-       return t_strdup_printf("%s/%c%s", dir, list->hierarchy_sep, name);
+       return t_strdup_printf("%s/%c%s", dir,
+                              mailbox_list_get_hierarchy_sep(list), name);
 }
 
 static const char *
@@ -90,23 +92,23 @@ maildir_list_get_absolute_path(struct mailbox_list *list, const char *name)
 }
 
 static bool
-maildir_list_is_valid_common(struct mailbox_list *list, const char *name,
-                            size_t *len_r)
+maildir_list_is_valid_common(struct maildir_mailbox_list *list,
+                            const char *name, size_t *len_r)
 {
        size_t len;
 
        /* check that there are no adjacent hierarchy separators */
        for (len = 0; name[len] != '\0'; len++) {
-               if (name[len] == list->hierarchy_sep &&
-                   name[len+1] == list->hierarchy_sep)
+               if (name[len] == list->sep &&
+                   name[len+1] == list->sep)
                        return FALSE;
        }
 
        if (len == 0 || name[len-1] == '/')
                return FALSE;
 
-       if (name[0] == list->hierarchy_sep ||
-           name[len-1] == list->hierarchy_sep)
+       if (name[0] == list->sep ||
+           name[len-1] == list->sep)
                return FALSE;
 
        *len_r = len;
@@ -137,22 +139,26 @@ maildir_is_valid_pattern(struct mailbox_list *list ATTR_UNUSED,
 }
 
 static bool
-maildir_is_valid_existing_name(struct mailbox_list *list, const char *name)
+maildir_is_valid_existing_name(struct mailbox_list *_list, const char *name)
 {
+       struct maildir_mailbox_list *list =
+               (struct maildir_mailbox_list *)_list;
        size_t len;
 
        if (!maildir_list_is_valid_common(list, name, &len))
                return FALSE;
 
-       if (list->mail_set->mail_full_filesystem_access)
+       if (_list->mail_set->mail_full_filesystem_access)
                return TRUE;
 
        return maildir_list_is_valid_common_nonfs(name);
 }
 
 static bool
-maildir_is_valid_create_name(struct mailbox_list *list, const char *name)
+maildir_is_valid_create_name(struct mailbox_list *_list, const char *name)
 {
+       struct maildir_mailbox_list *list =
+               (struct maildir_mailbox_list *)_list;
        size_t len;
 
        if (!maildir_list_is_valid_common(list, name, &len))
@@ -160,17 +166,25 @@ maildir_is_valid_create_name(struct mailbox_list *list, const char *name)
        if (len > MAILDIR_MAX_CREATE_MAILBOX_NAME_LENGTH)
                return FALSE;
 
-       if (list->mail_set->mail_full_filesystem_access)
+       if (_list->mail_set->mail_full_filesystem_access)
                return TRUE;
 
        if (!maildir_list_is_valid_common_nonfs(name))
                return FALSE;
-       if (mailbox_list_name_is_too_large(name, list->hierarchy_sep))
+       if (mailbox_list_name_is_too_large(name, list->sep))
                return FALSE;
 
        return TRUE;
 }
 
+static char maildir_list_get_hierarchy_sep(struct mailbox_list *_list)
+{
+       struct maildir_mailbox_list *list =
+               (struct maildir_mailbox_list *)_list;
+
+       return list->sep;
+}
+
 static const char *
 maildir_list_get_path(struct mailbox_list *_list, const char *name,
                      enum mailbox_list_path_type type)
@@ -348,15 +362,17 @@ maildir_list_create_mailbox_dir(struct mailbox_list *list, const char *name,
                maildir_list_create_maildirfolder_file(list, path);
 }
 
-static const char *mailbox_list_maildir_get_trash_dir(struct mailbox_list *list)
+static const char *
+mailbox_list_maildir_get_trash_dir(struct mailbox_list *_list)
 {
+       struct maildir_mailbox_list *list =
+               (struct maildir_mailbox_list *)_list;
        const char *root_dir;
 
-       root_dir = mailbox_list_get_path(list, NULL,
+       root_dir = mailbox_list_get_path(_list, NULL,
                                         MAILBOX_LIST_PATH_TYPE_DIR);
        return t_strdup_printf("%s/%c%c"MAILBOX_LIST_MAILDIR_TRASH_DIR_NAME,
-                              root_dir, list->hierarchy_sep,
-                              list->hierarchy_sep);
+                              root_dir, list->sep, list->sep);
 }
 
 static int
@@ -448,7 +464,7 @@ maildir_rename_children(struct mailbox_list *oldlist, const char *oldname,
        const char *const *names, *old_vname, *new_vname;
        unsigned int i, count, old_vnamelen;
        pool_t pool;
-       string_t *str;
+       char old_ns_sep;
        int ret;
 
        ret = 0;
@@ -460,14 +476,13 @@ maildir_rename_children(struct mailbox_list *oldlist, const char *oldname,
        pool = pool_alloconly_create("Maildir++ children list", 1024);
        i_array_init(&names_arr, 64);
 
-       str = t_str_new(256);
-       old_vname = t_strdup(mail_namespace_get_vname(oldlist->ns, str, oldname));
+       old_vname = mailbox_list_get_vname(oldlist, oldname);
        old_vnamelen = strlen(oldname);
 
-       str_truncate(str, 0);
-       new_vname = t_strdup(mail_namespace_get_vname(newlist->ns, str, newname));
+       new_vname = mailbox_list_get_vname(newlist, newname);
 
-       pattern = t_strdup_printf("%s%c*", old_vname, oldlist->ns->sep);
+       old_ns_sep = mail_namespace_get_sep(oldlist->ns);
+       pattern = t_strdup_printf("%s%c*", old_vname, old_ns_sep);
        iter = mailbox_list_iter_init(oldlist, pattern,
                                      MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
                                      MAILBOX_LIST_ITER_RAW_LIST);
@@ -477,7 +492,7 @@ maildir_rename_children(struct mailbox_list *oldlist, const char *oldname,
                /* verify that the prefix matches, otherwise we could have
                   problems with mailbox names containing '%' and '*' chars */
                if (strncmp(info->name, old_vname, old_vnamelen) == 0 &&
-                   info->name[old_vnamelen] == oldlist->ns->sep) {
+                   info->name[old_vnamelen] == old_ns_sep) {
                        name = p_strdup(pool, info->name + old_vnamelen);
                        array_append(&names_arr, &name, 1);
                }
@@ -490,7 +505,7 @@ maildir_rename_children(struct mailbox_list *oldlist, const char *oldname,
        }
 
        for (i = 0; i < count; i++) {
-               old_childname = mail_namespace_get_storage_name(oldlist->ns,
+               old_childname = mailbox_list_get_storage_name(oldlist,
                                        t_strconcat(old_vname, names[i], NULL));
                if (strcmp(old_childname, new_vname) == 0) {
                        /* When doing RENAME "a" "a.b" we see "a.b" here.
@@ -498,7 +513,7 @@ maildir_rename_children(struct mailbox_list *oldlist, const char *oldname,
                        continue;
                }
 
-               new_childname = mail_namespace_get_storage_name(newlist->ns,
+               new_childname = mailbox_list_get_storage_name(newlist,
                                        t_strconcat(new_vname, names[i], NULL));
                oldpath = mailbox_list_get_path(oldlist, old_childname,
                                                MAILBOX_LIST_PATH_TYPE_MAILBOX);
@@ -596,7 +611,6 @@ maildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
 
 struct mailbox_list maildir_mailbox_list = {
        .name = MAILBOX_LIST_NAME_MAILDIRPLUSPLUS,
-       .hierarchy_sep = '.',
        .props = MAILBOX_LIST_PROP_NO_MAILDIR_NAME |
                MAILBOX_LIST_PROP_NO_ALT_DIR |
                MAILBOX_LIST_PROP_NO_NOSELECT,
@@ -609,6 +623,9 @@ struct mailbox_list maildir_mailbox_list = {
                maildir_is_valid_pattern,
                maildir_is_valid_existing_name,
                maildir_is_valid_create_name,
+               maildir_list_get_hierarchy_sep,
+               mailbox_list_default_get_vname,
+               mailbox_list_default_get_storage_name,
                maildir_list_get_path,
                maildir_list_get_temp_prefix,
                NULL,
@@ -627,7 +644,6 @@ struct mailbox_list maildir_mailbox_list = {
 
 struct mailbox_list imapdir_mailbox_list = {
        .name = MAILBOX_LIST_NAME_IMAPDIR,
-       .hierarchy_sep = '.',
        .props = MAILBOX_LIST_PROP_NO_MAILDIR_NAME |
                MAILBOX_LIST_PROP_NO_ALT_DIR |
                MAILBOX_LIST_PROP_NO_NOSELECT,
@@ -640,6 +656,9 @@ struct mailbox_list imapdir_mailbox_list = {
                maildir_is_valid_pattern,
                maildir_is_valid_existing_name,
                maildir_is_valid_create_name,
+               maildir_list_get_hierarchy_sep,
+               mailbox_list_default_get_vname,
+               mailbox_list_default_get_storage_name,
                maildir_list_get_path,
                maildir_list_get_temp_prefix,
                NULL,
index cefb48f1404997d650f21738991397ae8086c6d6..cc349a4068b59f191cd71d3b735df7e18e0c3086 100644 (file)
@@ -15,6 +15,7 @@ struct maildir_mailbox_list {
        struct mailbox_list list;
 
        const char *global_temp_prefix, *temp_prefix;
+       char sep;
 };
 
 struct mailbox_list_iterate_context *
index 240cf489e07e1650381e203d23013121f5dbbb50..ce9ce41945ad2c88caea52f6f0f7336e37a2e359 100644 (file)
@@ -47,6 +47,11 @@ none_is_valid_create_name(struct mailbox_list *list ATTR_UNUSED,
        return FALSE;
 }
 
+static char none_list_get_hierarchy_sep(struct mailbox_list *list ATTR_UNUSED)
+{
+       return '/';
+}
+
 static const char *
 none_list_get_path(struct mailbox_list *list ATTR_UNUSED,
                   const char *name ATTR_UNUSED,
@@ -147,7 +152,6 @@ none_list_get_mailbox_flags(struct mailbox_list *list ATTR_UNUSED,
 
 struct mailbox_list none_mailbox_list = {
        .name = MAILBOX_LIST_NAME_NONE,
-       .hierarchy_sep = '/',
        .props = MAILBOX_LIST_PROP_NO_ROOT,
        .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
 
@@ -158,6 +162,9 @@ struct mailbox_list none_mailbox_list = {
                none_is_valid_pattern,
                none_is_valid_existing_name,
                none_is_valid_create_name,
+               none_list_get_hierarchy_sep,
+               mailbox_list_default_get_vname,
+               mailbox_list_default_get_storage_name,
                none_list_get_path,
                none_list_get_temp_prefix,
                NULL,
index bfda4b4749cbb996c6e04dbc5f92265f7b116320..69d70c0fa1c6b26b7962e9e68766de46ce220852 100644 (file)
@@ -1,31 +1,95 @@
 /* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "str.h"
 #include "subscription-file.h"
 #include "mailbox-list-private.h"
 #include "mailbox-list-subscriptions.h"
 
+static int
+mailbox_list_subscription_fill_one(struct mailbox_list_iter_update_context *update_ctx,
+                                  struct mail_namespace *default_ns,
+                                  const char *name)
+{
+       struct mail_namespace *namespaces = default_ns->user->namespaces;
+       struct mail_namespace *ns;
+       const char *vname;
+
+       /* default_ns is whatever namespace we're currently listing.
+          if we have e.g. prefix="" and prefix=pub/ namespaces with
+          pub/ namespace having subscriptions=no, we want to:
+
+          1) when listing "" namespace we want to skip over any names
+          that begin with pub/. */
+       ns = mail_namespace_find_unsubscribable(namespaces, name);
+       if (ns != NULL && ns != default_ns)
+               return 0;
+
+       /* 2) when listing pub/ namespace, skip over entries that don't
+          begin with pub/. */
+       if (ns == NULL &&
+           (default_ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) == 0)
+               return 0;
+
+       /* When listing shared namespace's subscriptions, we need to
+          autocreate all the visible child namespaces and use the
+          child namespace. */
+       if (ns != NULL && ns->type == NAMESPACE_SHARED &&
+           (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
+               /* we'll need to get the namespace autocreated.
+                  one easy way is to just ask if a mailbox name under
+                  it is valid, and it gets created */
+               (void)mailbox_list_is_valid_existing_name(ns->list, name);
+               ns = mail_namespace_find_unsubscribable(namespaces, name);
+               i_assert(ns != NULL &&
+                        (ns->flags & NAMESPACE_FLAG_AUTOCREATED) != 0);
+       }
+
+       /* When listing pub/ namespace, skip over the namespace
+          prefix in the name. the rest of the name is storage_name. */
+       if (ns != NULL) {
+               i_assert(strncmp(name, ns->prefix, ns->prefix_len) == 0);
+               name += ns->prefix_len;
+       } else {
+               ns = default_ns;
+       }
+
+       if (!mailbox_list_is_valid_existing_name(ns->list, name)) {
+               /* we'll only get into trouble if we show this */
+               return -1;
+       } else {
+               vname = mailbox_list_get_vname(ns->list, name);
+               mailbox_list_iter_update(update_ctx, vname);
+       }
+       return 0;
+}
+
 static int
 mailbox_list_subscriptions_fill_real(struct mailbox_list_iterate_context *ctx,
                                     struct mailbox_tree_context *tree_ctx,
                                     struct imap_match_glob *glob,
                                     bool update_only)
 {
-       struct mail_namespace *default_ns = ctx->list->ns;
-       struct mail_namespace *namespaces = default_ns->user->namespaces;
+       struct mail_namespace *ns, *default_ns = ctx->list->ns;
+       struct mailbox_list *list = ctx->list;
        struct mailbox_list_iter_update_context update_ctx;
        struct subsfile_list_context *subsfile_ctx;
-       struct mail_namespace *ns;
-       const char *path, *name, *name2, *full_name, *orig_name;
-       string_t *vname;
+       const char *path, *name;
 
-       vname = str_new(default_pool, 256);
-       path = t_strconcat(ctx->list->set.control_dir != NULL ?
-                          ctx->list->set.control_dir :
-                          ctx->list->set.root_dir,
-                          "/", ctx->list->set.subscription_fname, NULL);
-       subsfile_ctx = subsfile_list_init(ctx->list, path);
+       if ((ctx->list->ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) == 0) {
+               /* need to list these using another namespace */
+               ns = mail_namespace_find_subscribable(default_ns->user->namespaces,
+                                                     default_ns->prefix);
+               if (ns == NULL) {
+                       /* no subscriptions */
+                       return 0;
+               }
+               list = ns->list;
+       }
+
+       path = t_strconcat(list->set.control_dir != NULL ?
+                          list->set.control_dir : list->set.root_dir,
+                          "/", list->set.subscription_fname, NULL);
+       subsfile_ctx = subsfile_list_init(list, path);
 
        memset(&update_ctx, 0, sizeof(update_ctx));
        update_ctx.iter_ctx = ctx;
@@ -38,37 +102,13 @@ mailbox_list_subscriptions_fill_real(struct mailbox_list_iterate_context *ctx,
                (ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) != 0;
 
        while ((name = subsfile_list_next(subsfile_ctx)) != NULL) T_BEGIN {
-               orig_name = name;
-               full_name = name2 =
-                       t_strconcat(default_ns->prefix, name, NULL);
-               ns = mail_namespace_find_unsubscribable(namespaces, &name2);
-               if (ns == NULL)
-                       ns = default_ns;
-               else if (ns->type == NAMESPACE_SHARED &&
-                        (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
-                       /* we'll need to get the namespace autocreated.
-                          one easy way is to just ask if a mailbox name under
-                          it is valid, and it gets created */
-                       (void)mailbox_list_is_valid_existing_name(ns->list,
-                                                                 name2);
-                       name = full_name;
-                       ns = mail_namespace_find_unsubscribable(namespaces,
-                                                               &name);
-               } else {
-                       name = name2;
-               }
-
-               if (!mailbox_list_is_valid_existing_name(ns->list, name)) {
-                       /* we'll only get into trouble if we show this */
+               if (mailbox_list_subscription_fill_one(&update_ctx, default_ns,
+                                                      name) < 0) {
                        i_warning("Subscriptions file %s: "
                                  "Ignoring invalid entry: %s",
-                                 path, orig_name);
-               } else {
-                       name = mail_namespace_get_vname(ns, vname, name);
-                       mailbox_list_iter_update(&update_ctx, name);
+                                 path, name);
                }
        } T_END;
-       str_free(&vname);
        return subsfile_list_deinit(subsfile_ctx);
 }
 
index 1ae8daee2e084fa6327f8aff8105f50a1dc1fab6..9bc2e5a664c8dac80a3d6b7effd357f5a31c6533 100644 (file)
@@ -27,22 +27,7 @@ void mail_namespace_finish_list_init(struct mail_namespace *ns,
                                     struct mailbox_list *list)
 {
        ns->list = list;
-
-       /* allow plugins to override real_sep */
-       if (ns->real_sep == '\0')
-               ns->real_sep = list->hierarchy_sep;
        ns->prefix_len = strlen(ns->prefix);
-
-       if (ns->set->separator != NULL)
-               ns->sep = *ns->set->separator;
-       if (ns->sep == '\0')
-                ns->sep = ns->real_sep;
-       if (ns->sep == '"' || ns->sep == '\\') {
-               ns->sep_str[0] = '\\';
-               ns->sep_str[1] = ns->sep;
-       } else {
-               ns->sep_str[0] = ns->sep;
-       }
 }
 
 static void mail_namespace_free(struct mail_namespace *ns)
@@ -203,9 +188,10 @@ namespaces_check(struct mail_namespace *namespaces, const char **error_r)
 {
        struct mail_namespace *ns, *inbox_ns = NULL;
        unsigned int subscriptions_count = 0;
-       char list_sep = '\0';
+       char ns_sep, list_sep = '\0';
 
        for (ns = namespaces; ns != NULL; ns = ns->next) {
+               ns_sep = mail_namespace_get_sep(ns);
                if (mail_namespace_find_prefix(ns->next, ns->prefix) != NULL) {
                        *error_r = t_strdup_printf(
                                "Duplicate namespace prefix: \"%s\"",
@@ -225,7 +211,7 @@ namespaces_check(struct mail_namespace *namespaces, const char **error_r)
                if (*ns->prefix != '\0' &&
                    (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
                                  NAMESPACE_FLAG_LIST_CHILDREN)) != 0 &&
-                   ns->prefix[strlen(ns->prefix)-1] != ns->sep) {
+                   ns->prefix[strlen(ns->prefix)-1] != ns_sep) {
                        *error_r = t_strdup_printf(
                                "list=yes requires prefix=%s "
                                "to end with separator", ns->prefix);
@@ -234,7 +220,7 @@ namespaces_check(struct mail_namespace *namespaces, const char **error_r)
                if (*ns->prefix != '\0' &&
                    (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
                                  NAMESPACE_FLAG_LIST_CHILDREN)) != 0 &&
-                   ns->prefix[0] == ns->sep) {
+                   ns->prefix[0] == ns_sep) {
                        *error_r = t_strdup_printf(
                                "list=yes requires prefix=%s "
                                "not to start with separator", ns->prefix);
@@ -243,8 +229,8 @@ namespaces_check(struct mail_namespace *namespaces, const char **error_r)
                if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
                                  NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
                        if (list_sep == '\0')
-                               list_sep = ns->sep;
-                       else if (list_sep != ns->sep) {
+                               list_sep = ns_sep;
+                       else if (list_sep != ns_sep) {
                                *error_r = "All list=yes namespaces must use "
                                        "the same separator";
                                return FALSE;
@@ -472,60 +458,6 @@ void mail_namespace_destroy(struct mail_namespace *ns)
        mail_namespace_unref(&ns);
 }
 
-const char *mail_namespace_fix_sep(struct mail_namespace *ns, const char *name)
-{
-       char *ret, *p;
-
-       if (ns->sep == ns->real_sep)
-               return name;
-       if (ns->type == NAMESPACE_SHARED &&
-           (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
-               /* shared namespace root. the backend storage's hierarchy
-                  separator isn't known yet, so do nothing. */
-               return name;
-       }
-
-       ret = p_strdup(unsafe_data_stack_pool, name);
-       for (p = ret; *p != '\0'; p++) {
-               if (*p == ns->sep)
-                       *p = ns->real_sep;
-       }
-       return ret;
-}
-
-const char *mail_namespace_get_storage_name(struct mail_namespace *ns,
-                                           const char *name)
-{
-       unsigned int len = strlen(ns->prefix);
-
-       if (len > 0) {
-               if (strncmp(ns->prefix, name, len) == 0)
-                       name += len;
-               else {
-                       i_assert(strcasecmp(name, "INBOX") == 0);
-               }
-       }
-       return mail_namespace_fix_sep(ns, name);
-}
-
-const char *mail_namespace_get_vname(struct mail_namespace *ns, string_t *dest,
-                                    const char *name)
-{
-       str_truncate(dest, 0);
-       if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) == 0 ||
-           strcasecmp(name, "INBOX") != 0 ||
-           ns->user != ns->owner)
-               str_append(dest, ns->prefix);
-
-       for (; *name != '\0'; name++) {
-               if (*name == ns->real_sep)
-                       str_append_c(dest, ns->sep);
-               else
-                       str_append_c(dest, *name);
-       }
-       return str_c(dest);
-}
-
 struct mail_storage *
 mail_namespace_get_default_storage(struct mail_namespace *ns)
 {
@@ -533,11 +465,17 @@ mail_namespace_get_default_storage(struct mail_namespace *ns)
        return ns->storage;
 }
 
-char mail_namespaces_get_root_sep(const struct mail_namespace *namespaces)
+char mail_namespace_get_sep(struct mail_namespace *ns)
+{
+       return *ns->set->separator != '\0' ? *ns->set->separator :
+               mailbox_list_get_hierarchy_sep(ns->list);
+}
+
+char mail_namespaces_get_root_sep(struct mail_namespace *namespaces)
 {
        while ((namespaces->flags & NAMESPACE_FLAG_LIST_PREFIX) == 0)
                namespaces = namespaces->next;
-       return namespaces->sep;
+       return mail_namespace_get_sep(namespaces);
 }
 
 static bool mail_namespace_is_usable_prefix(struct mail_namespace *ns,
@@ -558,7 +496,7 @@ static bool mail_namespace_is_usable_prefix(struct mail_namespace *ns,
 
        if (strncmp(ns->prefix, mailbox, ns->prefix_len-1) == 0 &&
            mailbox[ns->prefix_len-1] == '\0' &&
-           ns->prefix[ns->prefix_len-1] == ns->sep) {
+           ns->prefix[ns->prefix_len-1] == mail_namespace_get_sep(ns)) {
                /* we're trying to access the namespace prefix itself */
                return TRUE;
        }
@@ -566,21 +504,18 @@ static bool mail_namespace_is_usable_prefix(struct mail_namespace *ns,
 }
 
 static struct mail_namespace *
-mail_namespace_find_mask(struct mail_namespace *namespaces,
-                        const char **mailbox,
+mail_namespace_find_mask(struct mail_namespace *namespaces, const char *box,
                         enum namespace_flags flags,
                         enum namespace_flags mask)
 {
         struct mail_namespace *ns = namespaces;
-       const char *box = *mailbox;
        struct mail_namespace *best = NULL;
-       unsigned int len, best_len = 0;
+       unsigned int best_len = 0;
        bool inbox;
 
        inbox = strncasecmp(box, "INBOX", 5) == 0;
        if (inbox && box[5] == '\0') {
                /* find the INBOX namespace */
-               *mailbox = "INBOX";
                while (ns != NULL) {
                        if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
                            (ns->flags & mask) == flags)
@@ -599,21 +534,11 @@ mail_namespace_find_mask(struct mail_namespace *namespaces,
                        best_len = ns->prefix_len;
                }
        }
-
-       if (best != NULL) {
-               if (best_len > 0) {
-                       len = strlen(*mailbox);
-                       *mailbox += I_MIN(len, best_len);
-               } else if (inbox && (box[5] == best->sep || box[5] == '\0'))
-                       *mailbox = t_strconcat("INBOX", box+5, NULL);
-
-               *mailbox = mail_namespace_fix_sep(best, *mailbox);
-       }
        return best;
 }
 
 static struct mail_namespace *
-mail_namespace_find_shared(struct mail_namespace *ns, const char **mailbox)
+mail_namespace_find_shared(struct mail_namespace *ns, const char *mailbox)
 {
        struct mailbox_list *list = ns->list;
        struct mail_storage *storage;
@@ -625,7 +550,7 @@ mail_namespace_find_shared(struct mail_namespace *ns, const char **mailbox)
 }
 
 struct mail_namespace *
-mail_namespace_find(struct mail_namespace *namespaces, const char **mailbox)
+mail_namespace_find(struct mail_namespace *namespaces, const char *mailbox)
 {
        struct mail_namespace *ns;
 
@@ -633,7 +558,7 @@ mail_namespace_find(struct mail_namespace *namespaces, const char **mailbox)
        if (ns != NULL && ns->type == NAMESPACE_SHARED &&
            (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
                /* see if we need to autocreate a namespace for shared user */
-               if (strchr(*mailbox, ns->sep) != NULL)
+               if (strchr(mailbox, mail_namespace_get_sep(ns)) != NULL)
                        return mail_namespace_find_shared(ns, mailbox);
        }
        return ns;
@@ -641,7 +566,7 @@ mail_namespace_find(struct mail_namespace *namespaces, const char **mailbox)
 
 struct mail_namespace *
 mail_namespace_find_visible(struct mail_namespace *namespaces,
-                           const char **mailbox)
+                           const char *mailbox)
 {
        return mail_namespace_find_mask(namespaces, mailbox, 0,
                                        NAMESPACE_FLAG_HIDDEN);
@@ -649,7 +574,7 @@ mail_namespace_find_visible(struct mail_namespace *namespaces,
 
 struct mail_namespace *
 mail_namespace_find_subscribable(struct mail_namespace *namespaces,
-                                const char **mailbox)
+                                const char *mailbox)
 {
        return mail_namespace_find_mask(namespaces, mailbox,
                                        NAMESPACE_FLAG_SUBSCRIPTIONS,
@@ -658,7 +583,7 @@ mail_namespace_find_subscribable(struct mail_namespace *namespaces,
 
 struct mail_namespace *
 mail_namespace_find_unsubscribable(struct mail_namespace *namespaces,
-                                  const char **mailbox)
+                                  const char *mailbox)
 {
        return mail_namespace_find_mask(namespaces, mailbox,
                                        0, NAMESPACE_FLAG_SUBSCRIPTIONS);
@@ -672,16 +597,6 @@ mail_namespace_find_inbox(struct mail_namespace *namespaces)
        return namespaces;
 }
 
-bool mail_namespace_update_name(const struct mail_namespace *ns,
-                               const char **mailbox)
-{
-       struct mail_namespace tmp_ns = *ns;
-
-       /* FIXME: a bit kludgy.. */
-       tmp_ns.next = NULL;
-       return mail_namespace_find_mask(&tmp_ns, mailbox, 0, 0) != NULL;
-}
-
 struct mail_namespace *
 mail_namespace_find_prefix(struct mail_namespace *namespaces,
                           const char *prefix)
@@ -707,7 +622,7 @@ mail_namespace_find_prefix_nosep(struct mail_namespace *namespaces,
        for (ns = namespaces; ns != NULL; ns = ns->next) {
                if (ns->prefix_len == len + 1 &&
                    strncmp(ns->prefix, prefix, len) == 0 &&
-                   ns->prefix[len] == ns->sep)
+                   ns->prefix[len] == mail_namespace_get_sep(ns))
                        return ns;
        }
        return NULL;
index 5c87f131c5f69496ffd591f16f7f93c39429c1d8..9978396060ee9fab91ad2e1f5ea56a0d9c02807f 100644 (file)
@@ -46,7 +46,6 @@ struct mail_namespace {
        int refcount;
 
         enum namespace_type type;
-       char sep, real_sep, sep_str[3];
        enum namespace_flags flags;
 
        char *prefix;
@@ -93,48 +92,35 @@ void mail_namespace_add_storage(struct mail_namespace *ns,
 /* Destroy a single namespace and remove it from user's namespaces list. */
 void mail_namespace_destroy(struct mail_namespace *ns);
 
-/* Update hierarchy separators in given name to real_sep characters. */
-const char *mail_namespace_fix_sep(struct mail_namespace *ns, const char *name);
-/* Skip namespace prefix and change hierarchy separators. */
-const char *mail_namespace_get_storage_name(struct mail_namespace *ns,
-                                           const char *name);
-/* Write virtual mailbox name to dest and return it. Separators are changed to
-   virtual ones and namespace prefix is inserted except for INBOX. */
-const char *mail_namespace_get_vname(struct mail_namespace *ns, string_t *dest,
-                                    const char *name);
 /* Returns the default storage to use for newly created mailboxes. */
 struct mail_storage *
 mail_namespace_get_default_storage(struct mail_namespace *ns);
 
+/* Return namespace's hierarchy separator. */
+char mail_namespace_get_sep(struct mail_namespace *ns);
 /* Returns the hierarchy separator for mailboxes that are listed at root. */
-char mail_namespaces_get_root_sep(const struct mail_namespace *namespaces)
+char mail_namespaces_get_root_sep(struct mail_namespace *namespaces)
        ATTR_PURE;
 
-/* Returns namespace based on the mailbox name's prefix. Updates mailbox to
-   be a valid name inside the namespace (prefix is skipped, hierarchy separator
-   is changed to real_sep). If no namespaces were found, returns NULL. */
+/* Returns namespace based on the mailbox name's prefix, or NULL if no matching
+   namespace could be found. */
 struct mail_namespace *
-mail_namespace_find(struct mail_namespace *namespaces, const char **mailbox);
+mail_namespace_find(struct mail_namespace *namespaces, const char *mailbox);
 /* Like above, but ignore hidden namespaces. */
 struct mail_namespace *
 mail_namespace_find_visible(struct mail_namespace *namespaces,
-                           const char **mailbox);
+                           const char *mailbox);
 /* Like above, but find only from namespaces with subscriptions flag set. */
 struct mail_namespace *
 mail_namespace_find_subscribable(struct mail_namespace *namespaces,
-                                const char **mailbox);
+                                const char *mailbox);
 /* Like above, but find only from namespaces with subscriptions flag not set. */
 struct mail_namespace *
 mail_namespace_find_unsubscribable(struct mail_namespace *namespaces,
-                                  const char **mailbox);
+                                  const char *mailbox);
 /* Returns the INBOX namespace */
 struct mail_namespace *
 mail_namespace_find_inbox(struct mail_namespace *namespaces);
-/* Returns TRUE if the given namespace matches the mailbox's prefix.
-   Updates mailbox name to be a valid name inside the namespace. */
-bool mail_namespace_update_name(const struct mail_namespace *ns,
-                               const char **mailbox);
-
 /* Find a namespace with given prefix. */
 struct mail_namespace *
 mail_namespace_find_prefix(struct mail_namespace *namespaces,
index 307bcf93fd21096e5f431479722e3dca0bc07ad9..120e40a299ccf4c2ba74e4c993b6e09ab55a77cf 100644 (file)
@@ -99,7 +99,7 @@ mail_search_args_init_sub(struct mail_search_args *args,
 
                        arg->value.mailbox_glob =
                                imap_match_init(default_pool, arg->value.str,
-                                               TRUE, ns->sep);
+                                               TRUE, mail_namespace_get_sep(ns));
                        break;
                }
                case SEARCH_INTHREAD:
index e4e9926a9f0beb46c61c1feb529f66563fea867d..305dd649a8a7b6b97b2ee98a27ce7bed4d7871c9 100644 (file)
@@ -38,7 +38,7 @@ struct mail_storage_vfuncs {
 
        struct mailbox *(*mailbox_alloc)(struct mail_storage *storage,
                                         struct mailbox_list *list,
-                                        const char *name,
+                                        const char *vname,
                                         enum mailbox_flags flags);
        int (*purge)(struct mail_storage *storage);
 };
index ed96649370e76e4c43b6a5b242f90c81a42026b0..2cafdd8747425ce7c32b643cf27b939da1a72ade 100644 (file)
@@ -560,20 +560,20 @@ bool mail_storage_set_error_from_errno(struct mail_storage *storage)
        return TRUE;
 }
 
-struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
+struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
                              enum mailbox_flags flags)
 {
        struct mailbox_list *new_list = list;
        struct mail_storage *storage;
        struct mailbox *box;
 
-       if (mailbox_list_get_storage(&new_list, &name, &storage) < 0) {
+       if (mailbox_list_get_storage(&new_list, vname, &storage) < 0) {
                /* just use the first storage. FIXME: does this break? */
                storage = list->ns->storage;
        }
 
        T_BEGIN {
-               box = storage->v.mailbox_alloc(storage, new_list, name, flags);
+               box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
                hook_mailbox_allocated(box);
        } T_END;
 
@@ -581,6 +581,28 @@ struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
        return box;
 }
 
+static bool have_listable_namespace_prefix(struct mail_namespace *ns,
+                                          const char *name)
+{
+       unsigned int name_len = strlen(name);
+
+       for (; ns != NULL; ns = ns->next) {
+               if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
+                                 NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
+                       continue;
+
+               if (ns->prefix_len <= name_len)
+                       continue;
+
+               /* if prefix has multiple hierarchies, match
+                  any of the hierarchies */
+               if (strncmp(ns->prefix, name, name_len) == 0 &&
+                   ns->prefix[name_len] == mail_namespace_get_sep(ns))
+                       return TRUE;
+       }
+       return FALSE;
+}
+
 int mailbox_exists(struct mailbox *box)
 {
        if (!mailbox_list_is_valid_existing_name(box->list, box->name)) {
@@ -589,9 +611,49 @@ int mailbox_exists(struct mailbox *box)
                return -1;
        }
 
+       if (have_listable_namespace_prefix(box->storage->user->namespaces,
+                                          box->vname)) {
+               /* listable namespace prefix always exists */
+               return 1;
+       }
+
        return box->v.exists(box);
 }
 
+static int mailbox_check_mismatching_separators(struct mailbox *box)
+{
+       struct mail_namespace *ns = box->list->ns;
+       const char *p, *vname = box->vname;
+       char list_sep, ns_sep;
+
+       list_sep = mailbox_list_get_hierarchy_sep(box->list);
+       ns_sep = mail_namespace_get_sep(ns);
+
+       if (ns_sep == list_sep)
+               return 0;
+
+       if (ns->prefix_len > 0) {
+               /* vname is prefix with or without separator */
+               i_assert(strncmp(vname, ns->prefix, ns->prefix_len-1) == 0);
+               vname += ns->prefix_len - 1;
+               if (vname[0] != '\0') {
+                       i_assert(vname[0] == ns->prefix[ns->prefix_len-1]);
+                       vname++;
+               }
+       }
+
+       for (p = vname; *p != '\0'; p++) {
+               if (*p == list_sep) {
+                       mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
+                               t_strdup_printf("NO Character not allowed "
+                                               "in mailbox name: '%c'",
+                                               list_sep));
+                       return -1;
+               }
+       }
+       return 0;
+}
+
 static int mailbox_open_full(struct mailbox *box, struct istream *input)
 {
        int ret;
@@ -599,6 +661,8 @@ static int mailbox_open_full(struct mailbox *box, struct istream *input)
        if (box->opened)
                return 0;
 
+       if (mailbox_check_mismatching_separators(box) < 0)
+               return -1;
        if (!mailbox_list_is_valid_existing_name(box->list, box->name)) {
                mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
                                       "Invalid mailbox name");
@@ -876,6 +940,42 @@ int mailbox_rename(struct mailbox *src, struct mailbox *dest,
        return src->v.rename(src, dest, rename_children);
 }
 
+int mailbox_set_subscribed(struct mailbox *box, bool set)
+{
+       struct mail_namespace *ns;
+       struct mailbox_list *list = box->list;
+       const char *subs_name;
+
+       if (!mailbox_list_is_valid_existing_name(list, box->name)) {
+               mail_storage_set_error(box->storage, MAIL_ERROR_PARAMS,
+                                      "Invalid mailbox name");
+               return -1;
+       }
+
+       if ((list->ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) != 0)
+               subs_name = box->name;
+       else {
+               /* subscriptions=no namespace, find another one where we can
+                  add the subscription to */
+               ns = mail_namespace_find_subscribable(list->ns->user->namespaces,
+                                                     box->vname);
+               if (ns == NULL) {
+                       mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
+                               "This namespace has no subscriptions");
+                       return -1;
+               }
+               /* use <orig ns prefix><orig storage name> as the
+                  subscription name */
+               subs_name = t_strconcat(list->ns->prefix, box->name, NULL);
+               /* drop the common prefix (typically there isn't one) */
+               i_assert(strncmp(ns->prefix, subs_name, strlen(ns->prefix)) == 0);
+               subs_name += strlen(ns->prefix);
+
+               list = ns->list;
+       }
+       return mailbox_list_set_subscribed(list, subs_name, set);
+}
+
 struct mail_storage *mailbox_get_storage(const struct mailbox *box)
 {
        return box->storage;
index 9b9e0db225d6e581b6959435d45ec028e2b11b9c..1a9382463f8b38e44fa5843e51203b5d3f643ce4 100644 (file)
@@ -341,7 +341,7 @@ bool mail_storage_is_mailbox_file(struct mail_storage *storage) ATTR_PURE;
 /* Initialize mailbox without actually opening any files or verifying that
    it exists. Note that append and copy may open the selected mailbox again
    with possibly different readonly-state. */
-struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *name,
+struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
                              enum mailbox_flags flags);
 /* Returns 1 if mailbox exists (even if it's unselectable),
    0 if not and -1 if some error occurred. */
@@ -373,6 +373,9 @@ int mailbox_delete(struct mailbox *box);
    fails, the error is set to src's storage. */
 int mailbox_rename(struct mailbox *src, struct mailbox *dest,
                   bool rename_children);
+/* Subscribe/unsubscribe mailbox. Subscribing to
+   nonexistent mailboxes is optional. */
+int mailbox_set_subscribed(struct mailbox *box, bool set);
 
 /* Enable the given feature for the mailbox. */
 int mailbox_enable(struct mailbox *box, enum mailbox_feature features);
index 3fbf7570ddd403d77299ea4b672109b3f2880163..248d2795d8964fb6cfcdd3ac835bcdb4a2e70676 100644 (file)
@@ -34,7 +34,7 @@ struct mailbox_list_vfuncs {
        struct mailbox_list *(*alloc)(void);
        void (*deinit)(struct mailbox_list *list);
 
-       int (*get_storage)(struct mailbox_list **list, const char **name,
+       int (*get_storage)(struct mailbox_list **list, const char *vname,
                           struct mail_storage **storage_r);
        bool (*is_valid_pattern)(struct mailbox_list *list,
                                 const char *pattern);
@@ -43,6 +43,11 @@ struct mailbox_list_vfuncs {
        bool (*is_valid_create_name)(struct mailbox_list *list,
                                     const char *name);
 
+       char (*get_hierarchy_sep)(struct mailbox_list *list);
+       const char *(*get_vname)(struct mailbox_list *list,
+                                const char *storage_name);
+       const char *(*get_storage_name)(struct mailbox_list *list,
+                                       const char *vname);
        const char *(*get_path)(struct mailbox_list *list, const char *name,
                                enum mailbox_list_path_type type);
 
@@ -89,7 +94,6 @@ union mailbox_list_module_context {
 
 struct mailbox_list {
        const char *name;
-       char hierarchy_sep;
        enum mailbox_list_properties props;
        size_t mailbox_name_max_length;
 
@@ -147,8 +151,15 @@ void mailbox_lists_deinit(void);
 int mailbox_list_settings_parse(struct mail_user *user, const char *data,
                                struct mailbox_list_settings *set_r,
                                const char **error_r);
+const char *mailbox_list_default_get_storage_name(struct mailbox_list *list,
+                                                 const char *vname);
+const char *mailbox_list_default_get_vname(struct mailbox_list *list,
+                                          const char *storage_name);
 const char *mailbox_list_get_unexpanded_path(struct mailbox_list *list,
                                             enum mailbox_list_path_type type);
+const char *mailbox_list_get_storage_name(struct mailbox_list *list,
+                                         const char *vname);
+const char *mailbox_list_get_vname(struct mailbox_list *list, const char *name);
 const char *
 mailbox_list_get_root_path(const struct mailbox_list_settings *set,
                           enum mailbox_list_path_type type);
index 8456de866fc763c5498daddb579b35aa10eb744f..749d66fe70d82bfd398943e16a04fddeb5668bf7 100644 (file)
@@ -345,6 +345,98 @@ const char *mailbox_list_get_unexpanded_path(struct mailbox_list *list,
        return mailbox_list_get_root_path(&set, type);
 }
 
+const char *mailbox_list_default_get_storage_name(struct mailbox_list *list,
+                                                 const char *vname)
+{
+       struct mail_namespace *ns = list->ns;
+       unsigned int prefix_len = strlen(ns->prefix);
+       char list_sep, ns_sep, *ret, *p;
+
+       if (prefix_len > 0) {
+               /* skip namespace prefix, except if this is INBOX */
+               if (strncmp(ns->prefix, vname, prefix_len) == 0)
+                       vname += prefix_len;
+               else if (strncmp(ns->prefix, vname, prefix_len-1) == 0 &&
+                        ns->prefix[prefix_len-1] == mail_namespace_get_sep(ns)) {
+                       /* trying to access the namespace prefix itself */
+                       vname = "";
+               } else {
+                       i_assert(strcasecmp(vname, "INBOX") == 0);
+               }
+       }
+
+       list_sep = mailbox_list_get_hierarchy_sep(list);
+       ns_sep = mail_namespace_get_sep(ns);
+
+       if (list_sep == ns_sep)
+               return vname;
+       if (ns->type == NAMESPACE_SHARED &&
+           (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
+               /* shared namespace root. the backend storage's hierarchy
+                  separator isn't known yet, so do nothing. */
+               return vname;
+       }
+
+       ret = p_strdup(unsafe_data_stack_pool, vname);
+       for (p = ret; *p != '\0'; p++) {
+               if (*p == ns_sep)
+                       *p = list_sep;
+       }
+       return ret;
+}
+
+const char *mailbox_list_get_storage_name(struct mailbox_list *list,
+                                         const char *vname)
+{
+       return list->v.get_storage_name(list, vname);
+}
+
+const char *mailbox_list_default_get_vname(struct mailbox_list *list,
+                                          const char *storage_name)
+{
+       unsigned int i, prefix_len, name_len;
+       char list_sep, ns_sep, *ret;
+
+       if ((list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
+           strcasecmp(storage_name, "INBOX") == 0 &&
+           list->ns->user == list->ns->owner) {
+               /* user's INBOX - use as-is */
+               return "INBOX";
+       }
+       if (*storage_name == '\0') {
+               /* return namespace prefix without the separator */
+               if (list->ns->prefix_len == 0)
+                       return list->ns->prefix;
+               else {
+                       return t_strndup(list->ns->prefix,
+                                        list->ns->prefix_len - 1);
+               }
+       }
+
+       prefix_len = strlen(list->ns->prefix);
+       list_sep = mailbox_list_get_hierarchy_sep(list);
+       ns_sep = mail_namespace_get_sep(list->ns);
+
+       if (list_sep == ns_sep && prefix_len == 0)
+               return storage_name;
+
+       /* @UNSAFE */
+       name_len = strlen(storage_name);
+       ret = t_malloc(prefix_len + name_len + 1);
+       memcpy(ret, list->ns->prefix, prefix_len);
+       for (i = 0; i < name_len; i++) {
+               ret[i + prefix_len] = storage_name[i] == list_sep ? ns_sep :
+                       storage_name[i];
+       }
+       ret[i + prefix_len] = '\0';
+       return ret;
+}
+
+const char *mailbox_list_get_vname(struct mailbox_list *list, const char *name)
+{
+       return list->v.get_vname(list, name);
+}
+
 void mailbox_list_destroy(struct mailbox_list **_list)
 {
        struct mailbox_list *list = *_list;
@@ -388,11 +480,11 @@ mailbox_list_get_user(const struct mailbox_list *list)
        return list->ns->user;
 }
 
-int mailbox_list_get_storage(struct mailbox_list **list, const char **name,
+int mailbox_list_get_storage(struct mailbox_list **list, const char *vname,
                             struct mail_storage **storage_r)
 {
        if ((*list)->v.get_storage != NULL)
-               return (*list)->v.get_storage(list, name, storage_r);
+               return (*list)->v.get_storage(list, vname, storage_r);
        else {
                *storage_r = (*list)->ns->storage;
                return 0;
@@ -405,6 +497,11 @@ void mailbox_list_get_closest_storage(struct mailbox_list *list,
        *storage = list->ns->storage;
 }
 
+char mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
+{
+       return list->v.get_hierarchy_sep(list);
+}
+
 static void
 mailbox_list_get_permissions_full(struct mailbox_list *list, const char *name,
                                  mode_t *file_mode_r, mode_t *dir_mode_r,
@@ -818,7 +915,7 @@ ns_match_inbox(struct mail_namespace *ns, const char *pattern)
                return FALSE;
 
        glob = imap_match_init(pool_datastack_create(), pattern,
-                              TRUE, ns->sep);
+                              TRUE, mail_namespace_get_sep(ns));
        return imap_match(glob, "INBOX") == IMAP_MATCH_YES;
 }
 
@@ -832,7 +929,7 @@ ns_match_next(struct ns_list_iterate_context *ctx, struct mail_namespace *ns,
        unsigned int len;
 
        len = ns->prefix_len;
-       if (len > 0 && ns->prefix[len-1] == ns->sep)
+       if (len > 0 && ns->prefix[len-1] == mail_namespace_get_sep(ns))
                len--;
 
        if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
@@ -847,7 +944,7 @@ ns_match_next(struct ns_list_iterate_context *ctx, struct mail_namespace *ns,
                result = IMAP_MATCH_CHILDREN;
        else {
                glob = imap_match_init(pool_datastack_create(), pattern,
-                                      TRUE, ns->sep);
+                                      TRUE, mail_namespace_get_sep(ns));
                result = imap_match(glob, prefix_without_sep);
        }
 
@@ -1273,7 +1370,7 @@ mailbox_list_iter_update_real(struct mailbox_list_iter_update_context *ctx,
                        break;
 
                /* see if parent matches */
-               p = strrchr(name, ns->sep);
+               p = strrchr(name, mail_namespace_get_sep(ns));
                if (p == NULL)
                        break;
 
index 82b0ea14abc87d77f2f09bcf60e8b784331d0204..23090be3a587ddc2db54870774524006272d9f0d 100644 (file)
@@ -159,10 +159,11 @@ struct mail_namespace *
 mailbox_list_get_namespace(const struct mailbox_list *list) ATTR_PURE;
 struct mail_user *
 mailbox_list_get_user(const struct mailbox_list *list) ATTR_PURE;
-int mailbox_list_get_storage(struct mailbox_list **list, const char **name,
+int mailbox_list_get_storage(struct mailbox_list **list, const char *vname,
                             struct mail_storage **storage_r);
 void mailbox_list_get_closest_storage(struct mailbox_list *list,
                                      struct mail_storage **storage);
+char mailbox_list_get_hierarchy_sep(struct mailbox_list *list);
 
 /* Returns the mode and GID that should be used when creating new files to
    the specified mailbox or to mailbox list root. (gid_t)-1 is
index 22057c23796c9392f8d63f5d98a97af6d09e9a06..1a723964ef059be2ab81b2b4c209e48bc77365ee 100644 (file)
@@ -5,7 +5,7 @@ struct mail_storage *test_mail_storage_create(void);
 
 struct mailbox *
 test_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                  const char *name, enum mailbox_flags flags);
+                  const char *vname, enum mailbox_flags flags);
 
 struct mail *
 test_mailbox_mail_alloc(struct mailbox_transaction_context *t,
index c6fb9571526a219c991555f0251f89600f4bab19..3baf6be6277fd91c2f83fe4a0eaab4403cffc4f0 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "array.h"
 #include "mail-storage-private.h"
+#include "mailbox-list-private.h"
 #include "test-mail-storage.h"
 
 #define TEST_UID_VALIDITY 1
@@ -272,7 +273,7 @@ struct mailbox test_mailbox = {
 
 struct mailbox *
 test_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
-                  const char *name, enum mailbox_flags flags)
+                  const char *vname, enum mailbox_flags flags)
 {
        struct mailbox *box;
        pool_t pool;
@@ -280,7 +281,8 @@ test_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
        pool = pool_alloconly_create("test mailbox", 1024);
        box = p_new(pool, struct mailbox, 1);
        *box = test_mailbox;
-       box->name = p_strdup(pool, name);
+       box->vname = p_strdup(pool, vname);
+       box->name = p_strdup(pool, mailbox_list_get_storage_name(list, vname));
        box->storage = storage;
        box->list = list;
 
index 80dd46bc97f41a861c3fe4a3de9e506ce68b21d0..0e47b08918d403051f478b5d4ba641b4268d0465 100644 (file)
@@ -165,8 +165,7 @@ acllist_append(struct acl_backend_vfile *backend, struct ostream *output,
        const char *name;
        int ret;
 
-       name = mail_namespace_get_storage_name(backend->backend.list->ns,
-                                              vname);
+       name = mailbox_list_get_storage_name(backend->backend.list, vname);
        acl_cache_flush(backend->backend.cache, name);
        aclobj = acl_object_init_from_name(&backend->backend, name);
 
index 98800c89b7790cb0711e809cb57393b5d371192a..a96a3eac22e48f90b19a579cfb37b11d2c12af2e 100644 (file)
@@ -11,6 +11,7 @@
 #include "file-dotlock.h"
 #include "nfs-workarounds.h"
 #include "mail-storage-private.h"
+#include "mailbox-list-private.h"
 #include "mail-namespace.h"
 #include "acl-cache.h"
 #include "acl-backend-vfile.h"
@@ -161,21 +162,16 @@ acl_backend_vfile_object_init(struct acl_backend *_backend,
        struct acl_backend_vfile *backend =
                (struct acl_backend_vfile *)_backend;
        struct acl_object_vfile *aclobj;
-       const char *dir;
+       const char *dir, *vname;
 
        aclobj = i_new(struct acl_object_vfile, 1);
        aclobj->aclobj.backend = _backend;
        aclobj->aclobj.name = i_strdup(name);
 
        if (backend->global_dir != NULL) T_BEGIN {
-               struct mail_namespace *ns =
-                       mailbox_list_get_namespace(_backend->list);
-               string_t *vname;
-
-               vname = t_str_new(128);
-               mail_namespace_get_vname(ns, vname, name);
+               vname = mailbox_list_get_vname(backend->backend.list, name);
                aclobj->global_path = i_strconcat(backend->global_dir, "/",
-                                                 str_c(vname), NULL);
+                                                 vname, NULL);
        } T_END;
 
        dir = acl_backend_vfile_get_local_dir(_backend, name);
@@ -190,7 +186,7 @@ get_parent_mailbox(struct acl_backend *backend, const char *name)
        struct mail_namespace *ns = mailbox_list_get_namespace(backend->list);
        const char *p;
 
-       p = strrchr(name, ns->real_sep);
+       p = strrchr(name, mail_namespace_get_sep(ns));
        return p == NULL ? NULL : t_strdup_until(name, p);
 }
 
index 14549c00169ff60fb6869862c1934b35347cd5ed..7c549c8f7d740eba5f7bad9adf294071f6003fa1 100644 (file)
@@ -90,7 +90,6 @@ acl_mailbox_try_list_fast(struct acl_mailbox_list_iterate_context *ctx)
        struct mail_namespace *ns = ctx->ctx.list->ns;
        struct mailbox_list_iter_update_context update_ctx;
        const char *name;
-       string_t *vname = NULL;
        int ret;
 
        if ((ctx->ctx.flags & (MAILBOX_LIST_ITER_RAW_LIST |
@@ -111,7 +110,6 @@ acl_mailbox_try_list_fast(struct acl_mailbox_list_iterate_context *ctx)
                return;
 
        /* no LOOKUP right by default, we can optimize this */
-       vname = t_str_new(256);
        memset(&update_ctx, 0, sizeof(update_ctx));
        update_ctx.iter_ctx = &ctx->ctx;
        update_ctx.glob =
@@ -124,9 +122,11 @@ acl_mailbox_try_list_fast(struct acl_mailbox_list_iterate_context *ctx)
        nonowner_list_ctx = acl_backend_nonowner_lookups_iter_init(backend);
        while ((ret = acl_backend_nonowner_lookups_iter_next(nonowner_list_ctx,
                                                             &name)) > 0) {
-               if (vname != NULL)
-                       name = mail_namespace_get_vname(ns, vname, name);
-               mailbox_list_iter_update(&update_ctx, name);
+               T_BEGIN {
+                       const char *vname =
+                               mailbox_list_get_vname(ns->list, name);
+                       mailbox_list_iter_update(&update_ctx, vname);
+               } T_END;
        }
        acl_backend_nonowner_lookups_iter_deinit(&nonowner_list_ctx);
 
@@ -171,7 +171,7 @@ acl_mailbox_list_iter_init(struct mailbox_list *list,
        ctx->ctx.flags = flags;
 
        inboxcase = (list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0;
-       ctx->sep = list->ns->sep;
+       ctx->sep = mail_namespace_get_sep(list->ns);
        ctx->glob = imap_match_init_multiple(default_pool, patterns,
                                             inboxcase, ctx->sep);
        /* see if all patterns have only a single '*' and it's at the end.
@@ -220,14 +220,15 @@ acl_mailbox_list_iter_next_info(struct acl_mailbox_list_iterate_context *ctx)
 
 static const char *
 acl_mailbox_list_iter_get_name(struct mailbox_list_iterate_context *ctx,
-                              const char *name)
+                              const char *vname)
 {
        struct mail_namespace *ns = ctx->list->ns;
+       const char *name;
        unsigned int len;
 
-       name = mail_namespace_get_storage_name(ns, name);
+       name = mailbox_list_get_storage_name(ns->list, vname);
        len = strlen(name);
-       if (len > 0 && name[len-1] == ns->real_sep) {
+       if (len > 0 && name[len-1] == mailbox_list_get_hierarchy_sep(ns->list)) {
                /* name ends with separator. this can happen if doing e.g.
                   LIST "" foo/% and it lists "foo/". */
                name = t_strndup(name, len-1);
index 9ab143d6b13f9efd3ea199b2fbeac77df953e379..94bb9e62272d8ac5ab2222e89c69ad0179bb9f15 100644 (file)
@@ -18,7 +18,7 @@ autocreate_mailbox(struct mail_namespace *namespaces, const char *name)
        const char *str;
        enum mail_error error;
 
-       ns = mail_namespace_find(namespaces, &name);
+       ns = mail_namespace_find(namespaces, name);
        if (ns == NULL) {
                if (namespaces->mail_set->mail_debug)
                        i_debug("autocreate: No namespace found for %s", name);
@@ -57,24 +57,26 @@ static void
 autosubscribe_mailbox(struct mail_namespace *namespaces, const char *name)
 {
        struct mail_namespace *ns;
+       struct mailbox *box;
        const char *str;
        enum mail_error error;
 
-       ns = mail_namespace_find_subscribable(namespaces, &name);
+       ns = mail_namespace_find_subscribable(namespaces, name);
        if (ns == NULL) {
                if (namespaces->mail_set->mail_debug)
                        i_debug("autocreate: No namespace found for %s", name);
                return;
        }
 
-       if (mailbox_list_set_subscribed(ns->list, name, TRUE) < 0) {
-               str = mailbox_list_get_last_error(ns->list,
-                                                 &error);
+       box = mailbox_alloc(ns->list, name, 0);
+       if (mailbox_set_subscribed(box, TRUE) < 0) {
+               str = mailbox_get_last_error(box, &error);
                if (error != MAIL_ERROR_EXISTS && ns->mail_set->mail_debug) {
                        i_debug("autocreate: Failed to subscribe mailbox "
                                "%s: %s", name, str);
                }
        }
+       mailbox_free(&box);
 }
 
 static void autosubscribe_mailboxes(struct mail_namespace *namespaces)
index d975839a75c7cdbe156c3e6f75d82fe9dcd220b4..694f22234e0ee5dc886ddbc3bf7a337a47c8282b 100644 (file)
@@ -6,7 +6,7 @@
 #include "strescape.h"
 #include "unichar.h"
 #include "mail-storage-private.h"
-#include "mail-namespace.h"
+#include "mailbox-list-private.h"
 #include "fts-mailbox.h"
 #include "solr-connection.h"
 #include "fts-solr-plugin.h"
@@ -37,7 +37,6 @@ struct solr_fts_backend_build_context {
 struct solr_virtual_uid_map_context {
        struct fts_backend *backend;
        struct mailbox *box;
-       string_t *vname;
 };
 
 struct fts_backend_solr_get_last_uids_context {
@@ -46,7 +45,6 @@ struct fts_backend_solr_get_last_uids_context {
        ARRAY_TYPE(fts_backend_uid_map) *last_uids;
 
        struct mailbox *box;
-       string_t *vname;
 };
 
 static struct solr_connection *solr_conn = NULL;
@@ -387,16 +385,15 @@ solr_virtual_get_last_uids(const char *ns_prefix, const char *mailbox,
        struct fts_backend_solr_get_last_uids_context *ctx = context;
        struct fts_backend_uid_map *map;
        struct mail_namespace *ns;
-       const char *vname;
 
        ns = solr_get_namespaces(ctx->backend, ctx->box, ns_prefix);
-       for (; ns != NULL; ns = ns->alias_chain_next) {
-               vname = mail_namespace_get_vname(ns, ctx->vname, mailbox);
+       for (; ns != NULL; ns = ns->alias_chain_next) T_BEGIN {
+               const char *vname = mailbox_list_get_vname(ns->list, mailbox);
                map = array_append_space(ctx->last_uids);
                map->mailbox = p_strdup(ctx->pool, vname);
                map->uidvalidity = uidvalidity;
                map->uid = *uid;
-       }
+       } T_END;
        return FALSE;
 }
 
@@ -407,9 +404,6 @@ solr_add_pattern(string_t *str, const struct mailbox_virtual_pattern *pattern)
        const char *name, *p;
 
        name = pattern->pattern;
-       if (!mail_namespace_update_name(pattern->ns, &name))
-               name = mail_namespace_fix_sep(pattern->ns, name);
-
        fts_box_name_get_root(&ns, &name);
 
        if (strcmp(name, "*") == 0) {
@@ -513,7 +507,6 @@ fts_backend_solr_get_all_last_uids(struct fts_backend *backend, pool_t pool,
        ctx.pool = pool;
        ctx.last_uids = last_uids;
        ctx.box = backend->box;
-       ctx.vname = t_str_new(256);
 
        str = t_str_new(256);
        str_printfa(str, "fl=uid,box,uidv,ns&rows=%u&q=last_uid:TRUE+user:",
@@ -775,17 +768,20 @@ static bool solr_virtual_uid_map(const char *ns_prefix, const char *mailbox,
 {
        struct solr_virtual_uid_map_context *ctx = context;
        struct mail_namespace *ns;
-       const char *vname;
-       bool convert_inbox;
+       bool convert_inbox, ret;
 
        ns = solr_get_namespaces(ctx->backend, ctx->box, ns_prefix);
        convert_inbox = (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
                strcmp(mailbox, "INBOX") == 0;
        for (; ns != NULL; ns = ns->alias_chain_next) {
-               vname = convert_inbox ? ns->prefix :
-                       mail_namespace_get_vname(ns, ctx->vname, mailbox);
-               if (fts_mailbox_get_virtual_uid(ctx->box, vname, uidvalidity,
-                                               *uid, uid))
+               T_BEGIN {
+                       const char *vname = convert_inbox ? ns->prefix :
+                               mailbox_list_get_vname(ns->list, mailbox);
+                       ret = fts_mailbox_get_virtual_uid(ctx->box, vname,
+                                                         uidvalidity,
+                                                         *uid, uid);
+               } T_END;
+               if (ret)
                        return TRUE;
        }
        return FALSE;
@@ -868,7 +864,6 @@ static int fts_backend_solr_lookup(struct fts_backend_lookup_context *ctx,
                memset(&uid_map_ctx, 0, sizeof(uid_map_ctx));
                uid_map_ctx.backend = ctx->backend;
                uid_map_ctx.box = box;
-               uid_map_ctx.vname = t_str_new(256);
                return solr_connection_select(solr_conn, str_c(str),
                                              solr_virtual_uid_map,
                                              &uid_map_ctx,
index dc1a51f0410f47e69cb6a0b72ce0fee52754a6f5..88823e5dd00b12d4a4152fce95518ddf1baad5e7 100644 (file)
@@ -12,6 +12,7 @@
 #include "mail-namespace.h"
 #include "mail-search-build.h"
 #include "mail-storage-private.h"
+#include "mailbox-list-private.h"
 #include "fts-api-private.h"
 #include "fts-mailbox.h"
 #include "fts-storage.h"
@@ -348,13 +349,10 @@ static int mailbox_name_cmp(const struct fts_orig_mailboxes *box1,
        int ret;
 
        T_BEGIN {
-               string_t *tmp1, *tmp2;
                const char *vname1, *vname2;
 
-               tmp1 = t_str_new(128);
-               tmp2 = t_str_new(128);
-               vname1 = mail_namespace_get_vname(box1->ns, tmp1, box1->name);
-               vname2 = mail_namespace_get_vname(box2->ns, tmp2, box2->name);
+               vname1 = mailbox_list_get_vname(box1->ns->list, box1->name);
+               vname2 = mailbox_list_get_vname(box2->ns->list, box2->name);
                ret = strcmp(vname1, vname2);
        } T_END;
        return ret;
@@ -374,8 +372,6 @@ static int fts_build_init_virtual_next(struct fts_search_context *fctx)
        const struct fts_orig_mailboxes *boxes;
        const struct fts_backend_uid_map *last_uids;
        unsigned int boxi, uidi, box_count, last_uid_count;
-       const char *vname;
-       string_t *tmp;
        int ret, vret = 0;
 
        if (vctx->pool == NULL)
@@ -387,13 +383,16 @@ static int fts_build_init_virtual_next(struct fts_search_context *fctx)
        boxes = array_get(&vctx->orig_mailboxes, &box_count);
        last_uids = array_get(&vctx->last_uids, &last_uid_count);
 
-       tmp = t_str_new(256);
        boxi = vctx->boxi;
        uidi = vctx->uidi;
        while (vret == 0 && boxi < box_count && uidi < last_uid_count) {
-               vname = mail_namespace_get_vname(boxes[boxi].ns, tmp,
-                                                boxes[boxi].name);
-               ret = strcmp(vname, last_uids[uidi].mailbox);
+               T_BEGIN {
+                       const char *vname;
+
+                       vname = mailbox_list_get_vname(boxes[boxi].ns->list,
+                                                      boxes[boxi].name);
+                       ret = strcmp(vname, last_uids[uidi].mailbox);
+               } T_END;
                if (ret == 0) {
                        /* match. check also that uidvalidity matches. */
                        mailbox_get_open_status(boxes[boxi].box,
index ef3d64040def3bc540097c96fba85639d6acdb93..55bf722dc86a0e69f80dac368e86035479d181bc 100644 (file)
@@ -57,7 +57,6 @@ acl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
 {
        struct mail_namespace *ns;
        struct mailbox *box;
-       const char *storage_name;
        int ret;
 
        if (ACL_USER_CONTEXT(cmd->client->user) == NULL) {
@@ -65,13 +64,13 @@ acl_mailbox_open_as_admin(struct client_command_context *cmd, const char *name)
                return NULL;
        }
 
-       ns = client_find_namespace(cmd, name, &storage_name);
+       ns = client_find_namespace(cmd, &name);
        if (ns == NULL)
                return NULL;
 
        /* Force opening the mailbox so that we can give a nicer error message
           if mailbox isn't selectable but is listable. */
-       box = mailbox_alloc(ns->list, storage_name, ACL_MAILBOX_FLAGS |
+       box = mailbox_alloc(ns->list, name, ACL_MAILBOX_FLAGS |
                            MAILBOX_FLAG_IGNORE_ACLS);
        ret = acl_mailbox_right_lookup(box, ACL_STORAGE_RIGHT_ADMIN);
        if (ret > 0)
@@ -308,7 +307,7 @@ static bool cmd_myrights(struct client_command_context *cmd)
 {
        struct mail_namespace *ns;
        struct mailbox *box;
-       const char *mailbox, *storage_name;
+       const char *mailbox;
        const char *const *rights;
        string_t *str;
 
@@ -320,11 +319,11 @@ static bool cmd_myrights(struct client_command_context *cmd)
                return TRUE;
        }
 
-       ns = client_find_namespace(cmd, mailbox, &storage_name);
+       ns = client_find_namespace(cmd, &mailbox);
        if (ns == NULL)
                return TRUE;
 
-       box = mailbox_alloc(ns->list, storage_name,
+       box = mailbox_alloc(ns->list, mailbox,
                            ACL_MAILBOX_FLAGS | MAILBOX_FLAG_IGNORE_ACLS);
        if (acl_object_get_my_rights(acl_mailbox_get_aclobj(box),
                                     pool_datastack_create(), &rights) < 0) {
index 2817145b602b9fd408f27f6a7c29f1eb205afe4c..b7ddf73ddd10df2e751c0e2b1f7dd354e2aa62f2 100644 (file)
@@ -74,14 +74,14 @@ static bool cmd_getquotaroot(struct client_command_context *cmd)
        struct mailbox *box;
        struct quota_root_iter *iter;
         struct quota_root *root;
-       const char *mailbox, *storage_name, *name;
+       const char *mailbox, *name;
        string_t *quotaroot_reply, *quota_reply;
 
        /* <mailbox> */
        if (!client_read_string_args(cmd, 1, &mailbox))
                return FALSE;
 
-       ns = client_find_namespace(cmd, mailbox, &storage_name);
+       ns = client_find_namespace(cmd, &mailbox);
        if (ns == NULL)
                return TRUE;
 
@@ -95,7 +95,7 @@ static bool cmd_getquotaroot(struct client_command_context *cmd)
                return TRUE;
        }
 
-       box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_READONLY |
+       box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY |
                            MAILBOX_FLAG_KEEP_RECENT);
 
        /* build QUOTAROOT reply and QUOTA reply for all quota roots */
index e8b100f722c92f8618e9006b5f5bdb3f77aa5ea7..722628054072ddeb49c5f7352bc85bbbf56c52ea 100644 (file)
 
 #define DEFAULT_ESCAPE_CHAR '\\'
 
-#define LIST_ESCAPE_CONTEXT(obj) \
-       MODULE_CONTEXT(obj, listescape_storage_module)
 #define LIST_ESCAPE_LIST_CONTEXT(obj) \
        MODULE_CONTEXT(obj, listescape_list_module)
 
-struct listescape_mail_storage {
-       union mail_storage_module_context module_ctx;
-};
-
-struct listescape_mailbox_list_iter {
-       struct mailbox_list_iterate_context *ctx;
-       string_t *name;
-       struct mailbox_info info;
-};
-
 struct listescape_mailbox_list {
        union mailbox_list_module_context module_ctx;
-       ARRAY_DEFINE(iters, struct listescape_mailbox_list_iter);
        char escape_char;
 };
 
 const char *listescape_plugin_version = DOVECOT_VERSION;
 
-static MODULE_CONTEXT_DEFINE_INIT(listescape_storage_module,
-                                 &mail_storage_module_register);
 static MODULE_CONTEXT_DEFINE_INIT(listescape_list_module,
                                  &mailbox_list_module_register);
 
 static const char *
 list_escape(struct listescape_mailbox_list *mlist,
-           struct mail_namespace *ns, const char *str, bool vname)
+           struct mail_namespace *ns, const char *str)
 {
+       char ns_sep = mail_namespace_get_sep(ns);
+       char list_sep = mailbox_list_get_hierarchy_sep(ns->list);
        string_t *esc = t_str_new(64);
        unsigned int i;
 
@@ -55,7 +42,7 @@ list_escape(struct listescape_mailbox_list *mlist,
        if (i > ns->prefix_len)
                i = ns->prefix_len;
 
-       if (vname && i > 0 && strncmp(ns->prefix, str, i) == 0) {
+       if (i > 0 && strncmp(ns->prefix, str, i) == 0) {
                str_append_n(esc, str, i);
                str += i;
        }
@@ -65,13 +52,10 @@ list_escape(struct listescape_mailbox_list *mlist,
                str++;
        }
        for (; *str != '\0'; str++) {
-               if (*str == ns->sep) {
-                       if (!vname)
-                               str_append_c(esc, ns->list->hierarchy_sep);
-                       else
-                               str_append_c(esc, *str);
-               } else if (*str == ns->list->hierarchy_sep ||
-                          *str == mlist->escape_char || *str == '/')
+               if (*str == ns_sep)
+                       str_append_c(esc, *str);
+               else if (*str == list_sep ||
+                        *str == mlist->escape_char || *str == '/')
                        str_printfa(esc, "%c%02x", mlist->escape_char, *str);
                else
                        str_append_c(esc, *str);
@@ -79,10 +63,13 @@ list_escape(struct listescape_mailbox_list *mlist,
        return str_c(esc);
 }
 
-static void list_unescape_str(struct listescape_mailbox_list *mlist,
-                             struct mail_namespace *ns,
-                             const char *str, string_t *dest)
+static const char *
+list_unescape(struct listescape_mailbox_list *mlist,
+             struct mail_namespace *ns, const char *str)
 {
+       char ns_sep = mail_namespace_get_sep(ns);
+       char list_sep = mailbox_list_get_hierarchy_sep(ns->list);
+       string_t *dest = t_str_new(strlen(str));
        unsigned int num;
 
        for (; *str != '\0'; str++) {
@@ -100,220 +87,31 @@ static void list_unescape_str(struct listescape_mailbox_list *mlist,
 
                        str_append_c(dest, num);
                        str += 2;
-               } else if (*str == ns->list->hierarchy_sep)
-                       str_append_c(dest, ns->sep);
+               } else if (*str == list_sep)
+                       str_append_c(dest, ns_sep);
                else
                        str_append_c(dest, *str);
        }
+       return str_c(dest);
 }
 
-static struct mail_namespace *
-listescape_find_orig_ns(struct mail_namespace *parent_ns, const char *name)
-{
-       struct mail_namespace *ns, *best = NULL;
-
-       for (ns = parent_ns->user->namespaces; ns != NULL; ns = ns->next) {
-               if ((ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) != 0)
-                       continue;
-
-               if (strncmp(ns->prefix, parent_ns->prefix,
-                           parent_ns->prefix_len) == 0 &&
-                   strncmp(ns->prefix + parent_ns->prefix_len, name,
-                           ns->prefix_len) == 0) {
-                       if (best == NULL || ns->prefix_len > best->prefix_len)
-                               best = ns;
-               }
-       }
-       return best != NULL ? best : parent_ns;
-}
-
-static const char *const *
-iter_escape_patterns(struct mailbox_list *list,
-                    const char *const *patterns,
-                    enum mailbox_list_iter_flags flags)
+static const char *listescape_list_get_vname(struct mailbox_list *list,
+                                            const char *storage_name)
 {
        struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
-       struct mail_namespace *orig_ns;
-       const char **escaped_patterns;
-       unsigned int i;
+       const char *vname;
 
-       escaped_patterns = t_new(const char *, str_array_length(patterns) + 1);
-       for (i = 0; patterns[i] != NULL; i++) {
-               if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
-                       /* we may be listing subscriptions for other namespaces
-                          prefixes. don't escape characters in the namespace
-                          prefixes. */
-                       orig_ns = listescape_find_orig_ns(list->ns,
-                                                         patterns[i]);
-               } else {
-                       orig_ns = list->ns;
-               }
-               escaped_patterns[i] = list_escape(mlist, orig_ns,
-                                                 patterns[i], TRUE);
-       }
-       return escaped_patterns;
+       vname = mlist->module_ctx.super.get_vname(list, storage_name);
+       return list_unescape(mlist, list->ns, vname);
 }
 
-static struct mailbox_list_iterate_context *
-listescape_mailbox_list_iter_init(struct mailbox_list *list,
-                                 const char *const *patterns,
-                                 enum mailbox_list_iter_flags flags)
+static const char *listescape_list_get_storage_name(struct mailbox_list *list,
+                                                   const char *vname)
 {
        struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
-       struct mailbox_list_iterate_context *ctx;
-       struct listescape_mailbox_list_iter *liter;
-
-       /* this is kind of kludgy. In ACL code we want to convert patterns,
-          in maildir renaming code we don't. so for now just use the _RAW_LIST
-          flag.. */
-       if ((flags & MAILBOX_LIST_ITER_RAW_LIST) == 0)
-               patterns = iter_escape_patterns(list, patterns, flags);
 
-       /* Listing breaks if ns->real_sep isn't correct, but with everything
-          else we need real_sep == virtual_sep. maybe some day lib-storage
-          API gets changed so that it sees only virtual mailbox names and
-          convers them internally and we don't have this problem. */
-       list->ns->real_sep = list->hierarchy_sep;
-       ctx = mlist->module_ctx.super.iter_init(list, patterns, flags);
-       list->ns->real_sep = list->ns->sep;
-
-       liter = array_append_space(&mlist->iters);
-       liter->ctx = ctx;
-       liter->name = str_new(default_pool, 256);
-       return ctx;
-}
-
-static struct listescape_mailbox_list_iter *
-listescape_mailbox_list_iter_find(struct listescape_mailbox_list *mlist,
-                                struct mailbox_list_iterate_context *ctx)
-{
-       struct listescape_mailbox_list_iter *liter;
-
-       array_foreach_modifiable(&mlist->iters, liter) {
-               if (liter->ctx == ctx)
-                       return liter;
-       }
-       return NULL;
-}
-
-static const struct mailbox_info *
-listescape_mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
-{
-       struct listescape_mailbox_list *mlist =
-               LIST_ESCAPE_LIST_CONTEXT(ctx->list);
-       struct mail_namespace *ns;
-       struct listescape_mailbox_list_iter *liter;
-       const struct mailbox_info *info;
-
-       liter = listescape_mailbox_list_iter_find(mlist, ctx);
-       i_assert(liter != NULL);
-
-       ctx->list->ns->real_sep = ctx->list->hierarchy_sep;
-       info = mlist->module_ctx.super.iter_next(ctx);
-       ctx->list->ns->real_sep = ctx->list->ns->sep;
-       if (info == NULL)
-               return info;
-
-       ns = (ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0 ?
-               ctx->list->ns :
-               listescape_find_orig_ns(ctx->list->ns, info->name);
-
-       if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
-           strcasecmp(info->name, "INBOX") == 0)
-               return info;
-
-       str_truncate(liter->name, 0);
-       str_append(liter->name, ns->prefix);
-       list_unescape_str(mlist, ns, info->name + ns->prefix_len, liter->name);
-       liter->info = *info;
-       liter->info.name = str_c(liter->name);
-       return &liter->info;
-}
-
-static int
-listescape_mailbox_list_iter_deinit(struct mailbox_list_iterate_context *ctx)
-{
-       struct mailbox_list *list = ctx->list;
-       struct listescape_mailbox_list *mlist =
-               LIST_ESCAPE_LIST_CONTEXT(ctx->list);
-       struct listescape_mailbox_list_iter *liters;
-       unsigned int i, count;
-       int ret;
-
-       liters = array_get_modifiable(&mlist->iters, &count);
-       for (i = 0; i < count; i++) {
-               if (liters[i].ctx == ctx) {
-                       str_free(&liters[i].name);
-                       array_delete(&mlist->iters, i, 1);
-               }
-       }
-
-       list->ns->real_sep = list->hierarchy_sep;
-       ret = mlist->module_ctx.super.iter_deinit(ctx);
-       list->ns->real_sep = list->ns->sep;
-       return ret;
-}
-
-static struct mailbox *
-listescape_mailbox_alloc(struct mail_storage *storage,
-                        struct mailbox_list *list,
-                        const char *name, enum mailbox_flags flags)
-{
-       struct listescape_mail_storage *mstorage = LIST_ESCAPE_CONTEXT(storage);
-       struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
-
-       if (list->hierarchy_sep != list->ns->sep)
-               name = list_escape(mlist, list->ns, name, FALSE);
-       return mstorage->module_ctx.super.
-               mailbox_alloc(storage, list, name, flags);
-}
-
-static int listescape_set_subscribed(struct mailbox_list *list, 
-                                    const char *name, bool set)
-{
-       struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
-       struct mail_namespace *ns;
-       const char *esc_name;
-
-       ns = listescape_find_orig_ns(list->ns, name);
-       if (ns == list->ns || strncmp(ns->prefix, name, ns->prefix_len) != 0)
-               name = list_escape(mlist, ns, name, FALSE);
-       else {
-               esc_name = list_escape(mlist, ns, name + ns->prefix_len, FALSE);
-               name = t_strconcat(ns->prefix, esc_name, NULL);
-       }
-       return mlist->module_ctx.super.set_subscribed(list, name, set);
-}
-
-static bool listescape_is_valid_existing_name(struct mailbox_list *list,
-                                             const char *name)
-{
-       struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
-
-       name = list_escape(mlist, list->ns, name, FALSE);
-       return mlist->module_ctx.super.is_valid_existing_name(list, name);
-}
-
-static bool listescape_is_valid_create_name(struct mailbox_list *list,
-                                           const char *name)
-{
-       struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list);
-
-       name = list_escape(mlist, list->ns, name, FALSE);
-       return mlist->module_ctx.super.is_valid_create_name(list, name);
-}
-
-static void listescape_mail_storage_created(struct mail_storage *storage)
-{
-       struct listescape_mail_storage *mstorage;
-       struct mail_storage_vfuncs *v = storage->vlast;
-
-       mstorage = p_new(storage->pool, struct listescape_mail_storage, 1);
-       mstorage->module_ctx.super = *v;
-       storage->vlast = &mstorage->module_ctx.super;
-       v->mailbox_alloc = listescape_mailbox_alloc;
-
-       MODULE_CONTEXT_SET(storage, listescape_storage_module, mstorage);
+       return mlist->module_ctx.super.
+               get_storage_name(list, list_escape(mlist, list->ns, vname));
 }
 
 static void listescape_mailbox_list_created(struct mailbox_list *list)
@@ -321,22 +119,17 @@ static void listescape_mailbox_list_created(struct mailbox_list *list)
        struct mailbox_list_vfuncs *v = list->vlast;
        struct listescape_mailbox_list *mlist;
        const char *env;
+       char ns_sep = mail_namespace_get_sep(list->ns);
+       char list_sep = mailbox_list_get_hierarchy_sep(list);
 
-       if (list->hierarchy_sep == list->ns->sep)
+       if (list_sep == ns_sep)
                return;
 
-       list->ns->real_sep = list->ns->sep;
-
        mlist = p_new(list->pool, struct listescape_mailbox_list, 1);
        mlist->module_ctx.super = *v;
        list->vlast = &mlist->module_ctx.super;
-       p_array_init(&mlist->iters, list->pool, 4);
-       v->iter_init = listescape_mailbox_list_iter_init;
-       v->iter_next = listescape_mailbox_list_iter_next;
-       v->iter_deinit = listescape_mailbox_list_iter_deinit;
-       v->set_subscribed = listescape_set_subscribed;
-       v->is_valid_existing_name = listescape_is_valid_existing_name;
-       v->is_valid_create_name = listescape_is_valid_create_name;
+       v->get_vname = listescape_list_get_vname;
+       v->get_storage_name = listescape_list_get_storage_name;
 
        env = mail_user_plugin_getenv(list->ns->user, "listescape_char");
        mlist->escape_char = env != NULL && *env != '\0' ?
@@ -346,7 +139,6 @@ static void listescape_mailbox_list_created(struct mailbox_list *list)
 }
 
 static struct mail_storage_hooks listescape_mail_storage_hooks = {
-       .mail_storage_created = listescape_mail_storage_created,
        .mailbox_list_created = listescape_mailbox_list_created
 };
 
index aca2b406afa7f9f848ab89d956cfa4db69dc25f8..1f080cf98498adafbc3f30fb78f4698608835f3f 100644 (file)
@@ -17,20 +17,17 @@ quota_count_mailbox(struct quota_root *root, struct mail_namespace *ns,
        struct mail_search_context *ctx;
        struct mail *mail;
        struct mail_search_args *search_args;
-       const char *storage_name;
        enum mail_error error;
        uoff_t size;
        int ret = 0;
 
-       storage_name = mail_namespace_get_storage_name(ns, vname);
-
        rule = quota_root_rule_find(root->set, vname);
        if (rule != NULL && rule->ignore) {
                /* mailbox not included in quota */
                return 0;
        }
 
-       box = mailbox_alloc(ns->list, storage_name,
+       box = mailbox_alloc(ns->list, vname,
                            MAILBOX_FLAG_READONLY | MAILBOX_FLAG_KEEP_RECENT);
        if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
                error = mailbox_get_last_mail_error(box);
index 21dfd586214b135b50b9551b06e604c60aeff165..2eb6b0c2a6e7fde7fa1aa37a78c8b49faed18595 100644 (file)
@@ -10,6 +10,7 @@
 #include "write-full.h"
 #include "str.h"
 #include "maildir-storage.h"
+#include "mailbox-list-private.h"
 #include "quota-private.h"
 
 #include <stdio.h>
@@ -157,8 +158,8 @@ maildir_list_next(struct maildir_list_context *ctx, time_t *mtime_r)
                T_BEGIN {
                        const char *path, *storage_name;
 
-                       storage_name = mail_namespace_get_storage_name(
-                               ctx->info->ns, ctx->info->name);
+                       storage_name = mailbox_list_get_storage_name(
+                               ctx->info->ns->list, ctx->info->name);
                        path = mailbox_list_get_path(ctx->list, storage_name,
                                        MAILBOX_LIST_PATH_TYPE_MAILBOX);
                        str_truncate(ctx->path, 0);
@@ -619,7 +620,6 @@ static bool maildirquota_limits_init(struct maildir_quota_root *root)
 {
        struct mailbox_list *list;
        struct mail_storage *storage;
-       const char *name = "";
 
        if (root->limits_initialized)
                return root->maildirsize_path != NULL;
@@ -632,7 +632,7 @@ static bool maildirquota_limits_init(struct maildir_quota_root *root)
        i_assert(root->maildirsize_path != NULL);
 
        list = root->maildirsize_ns->list;
-       if (mailbox_list_get_storage(&list, &name, &storage) == 0 &&
+       if (mailbox_list_get_storage(&list, "", &storage) == 0 &&
            strcmp(storage->name, MAILDIR_STORAGE_NAME) != 0) {
                /* non-maildir namespace, skip */
                if ((storage->class_flags &
index 9aebd7ac5c917ec6e7b0e1f40e559507e1eb3262..7d489e41e8a52cd61f8678deb9abd7531b82d917 100644 (file)
@@ -561,7 +561,7 @@ static void quota_root_set_namespace(struct quota_root *root,
 
        array_foreach(&root->set->rules, rule) {
                name = rule->mailbox_name;
-               if (mail_namespace_find(namespaces, &name) == NULL)
+               if (mail_namespace_find(namespaces, name) == NULL)
                        i_error("quota: Unknown namespace: %s", name);
        }
 }
index 8140032848f27b0fa4e187acc1b5e299795a74f3..00b4ec8d7eee589d879c09fe85e499b59790f335 100644 (file)
@@ -761,10 +761,9 @@ bool quota_root_is_namespace_visible(struct quota_root *root,
 {
        struct mailbox_list *list = ns->list;
        struct mail_storage *storage;
-       const char *name = "";
 
        /* this check works as long as there is only one storage per list */
-       if (mailbox_list_get_storage(&list, &name, &storage) == 0 &&
+       if (mailbox_list_get_storage(&list, "", &storage) == 0 &&
            (storage->class_flags & MAIL_STORAGE_CLASS_FLAG_NOQUOTA) != 0)
                return FALSE;
 
index e576cfcec35d5bda388ba8b91aa482e53be613c7..44c0d01c839059609eaa9ea0a620ed6c85a6f978 100644 (file)
@@ -125,7 +125,7 @@ snarf_box_find(struct mail_user *user, struct mailbox_list **list_r,
        if (snarf_name == NULL)
                return FALSE;
 
-       snarf_ns = mail_namespace_find(user->namespaces, &snarf_name);
+       snarf_ns = mail_namespace_find(user->namespaces, snarf_name);
        if (snarf_ns == NULL) {
                i_error("snarf: Namespace not found for mailbox: %s",
                        snarf_name);
@@ -166,8 +166,8 @@ static void snarf_mailbox_allocated(struct mailbox *box)
 
 static struct mailbox *
 snarf_mailbox_alloc(struct mail_storage *storage,
-                   struct mailbox_list *list, const char *name,
-                   enum mailbox_flags flags)
+                   struct mailbox_list *list,
+                   const char *vname, enum mailbox_flags flags)
 {
        struct snarf_mail_storage *sstorage = SNARF_CONTEXT(storage);
        struct mail_namespace *ns = mailbox_list_get_namespace(list);
@@ -176,7 +176,7 @@ snarf_mailbox_alloc(struct mail_storage *storage,
        const char *snarf_name;
        struct stat st;
 
-       if (strcmp(name, "INBOX") == 0 &&
+       if (strcmp(vname, "INBOX") == 0 &&
            (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) {
                if (stat(sstorage->snarf_path, &st) == 0)
                        sstorage->snarfing_disabled = FALSE;
@@ -191,13 +191,13 @@ snarf_mailbox_alloc(struct mail_storage *storage,
                        if (snarf_box_find(storage->user, &snarf_list,
                                           &snarf_name)) {
                                list = snarf_list;
-                               name = snarf_name;
+                               vname = snarf_name;
                        }
                }
        }
 
        box = sstorage->module_ctx.super.
-               mailbox_alloc(storage, list, name, flags);
+               mailbox_alloc(storage, list, vname, flags);
        if (sstorage->snarfing_disabled) {
                box->inbox_user = TRUE;
                box->inbox_any = TRUE;
index d1d9f2a1dec0b3a45bee30b579554cf465707509..ee3f281bc3893ebacd42a7858743308cf5cc9891 100644 (file)
@@ -225,16 +225,11 @@ static bool trash_find_storage(struct mail_user *user,
                               struct trash_mailbox *trash)
 {
        struct mail_namespace *ns;
-       const char *name;
 
-       for (ns = user->namespaces; ns != NULL; ns = ns->next) {
-               name = trash->name;
-               if (mail_namespace_update_name(ns, &name)) {
-                       if (name != trash->name)
-                               trash->name = p_strdup(user->pool, name);
-                       trash->ns = ns;
-                       return TRUE;
-               }
+       ns = mail_namespace_find(user->namespaces, trash->name);
+       if (ns != NULL) {
+               trash->ns = ns;
+               return TRUE;
        }
        return FALSE;
 }
index fc46352f9d2c50f6324e019f2e0ded481d70ac1e..932958a0baeadd48f4b51fe2778978c903654e3f 100644 (file)
@@ -135,7 +135,7 @@ virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
        if (*line == '-' || *line == '!') line++;
        bbox->ns = strcasecmp(line, "INBOX") == 0 ?
                mail_namespace_find_inbox(user->namespaces) :
-               mail_namespace_find(user->namespaces, &line);
+               mail_namespace_find(user->namespaces, line);
        if (bbox->ns == NULL) {
                *error_r = t_strdup_printf("Namespace not found for %s",
                                           bbox->name);
index 3dab618094f6544abd4db23c248f6082332a44b3..6e500a3361ae0b8cf71634d0e9603b19ceb12a85 100644 (file)
@@ -49,7 +49,8 @@ static const char *get_user_visible_mailbox_name(struct mailbox *box)
                return box->vname;
        else {
                return t_strdup_printf("<hidden>%c%s",
-                                      box->list->hierarchy_sep, box->name);
+                                      mail_namespace_get_sep(box->list->ns),
+                                      box->vname);
        }
 }
 
@@ -176,7 +177,7 @@ static int virtual_backend_box_open(struct virtual_mailbox *mbox,
        flags |= MAILBOX_FLAG_KEEP_RECENT;
 
        mailbox = bbox->name;
-       ns = mail_namespace_find(user->namespaces, &mailbox);
+       ns = mail_namespace_find(user->namespaces, mailbox);
        bbox->box = mailbox_alloc(ns->list, mailbox, flags);
 
        if (mailbox_open(bbox->box) < 0)
@@ -221,7 +222,7 @@ static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
 
 static struct mailbox *
 virtual_mailbox_alloc(struct mail_storage *_storage, struct mailbox_list *list,
-                     const char *name, enum mailbox_flags flags)
+                     const char *vname, enum mailbox_flags flags)
 {
        struct virtual_storage *storage = (struct virtual_storage *)_storage;
        struct virtual_mailbox *mbox;
@@ -236,7 +237,7 @@ virtual_mailbox_alloc(struct mail_storage *_storage, struct mailbox_list *list,
        mbox->box.mail_vfuncs = &virtual_mail_vfuncs;
        mbox->vfuncs = virtual_mailbox_vfuncs;
 
-       index_storage_mailbox_alloc(&mbox->box, name, flags,
+       index_storage_mailbox_alloc(&mbox->box, vname, flags,
                                    VIRTUAL_INDEX_PREFIX);
 
        mbox->storage = storage;
index 09a6c7ffdac3d8f25be59e25911af061e6fd9a40..8b9a4d35bf462143a3d2f255f936424cd7ed5239 100644 (file)
@@ -236,7 +236,7 @@ struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
 {
        struct mail_namespace *ns;
        struct mail_storage *storage;
-       const char *inbox, *ident;
+       const char *ident;
        struct client *client;
         enum mailbox_flags flags;
        const char *errmsg;
@@ -269,8 +269,7 @@ struct client *client_create(int fd_in, int fd_out, struct mail_user *user,
        pop3_client_count++;
        DLLIST_PREPEND(&pop3_clients, client);
 
-       inbox = "INBOX";
-       ns = mail_namespace_find(user->namespaces, &inbox);
+       ns = mail_namespace_find(user->namespaces, "INBOX");
        if (ns == NULL) {
                client_send_line(client, "-ERR No INBOX namespace for user.");
                client_destroy(client, "No INBOX namespace for user.");