Mercurial > dovecot > core-2.2
changeset 12586:a2780b694b2d
lib-storage: mailbox_alloc() now takes a virtual mailbox name and other related API changes.
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
line wrap: on
line diff
--- a/TODO Thu Jan 20 19:21:20 2011 +0200 +++ b/TODO Thu Jan 20 20:59:07 2011 +0200 @@ -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
--- a/src/doveadm/doveadm-mail-import.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/doveadm/doveadm-mail-import.c Thu Jan 20 20:59:07 2011 +0200 @@ -24,29 +24,27 @@ 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);
--- a/src/doveadm/doveadm-mail-iter.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/doveadm/doveadm-mail-iter.c Thu Jan 20 20:59:07 2011 +0200 @@ -20,12 +20,9 @@ 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;
--- a/src/doveadm/doveadm-mail-list-iter.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/doveadm/doveadm-mail-list-iter.c Thu Jan 20 20:59:07 2011 +0200 @@ -119,19 +119,22 @@ 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;
--- a/src/doveadm/doveadm-mail-mailbox.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/doveadm/doveadm-mail-mailbox.c Thu Jan 20 20:59:07 2011 +0200 @@ -184,33 +184,34 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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); }
--- a/src/doveadm/doveadm-mail.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/doveadm/doveadm-mail.c Thu Jan 20 20:59:07 2011 +0200 @@ -82,7 +82,7 @@ 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);
--- a/src/dsync/dsync-worker-local.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/dsync/dsync-worker-local.c Thu Jan 20 20:59:07 2011 +0200 @@ -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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ &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 @@ 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 @@ 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 @@ 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);
--- a/src/imap/cmd-create.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/cmd-create.c Thu Jan 20 20:59:07 2011 +0200 @@ -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 @@ 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
--- a/src/imap/cmd-delete.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/cmd-delete.c Thu Jan 20 20:59:07 2011 +0200 @@ -8,7 +8,7 @@ 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 @@ 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 */
--- a/src/imap/cmd-list.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/cmd-list.c Thu Jan 20 20:59:07 2011 +0200 @@ -225,10 +225,10 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ { 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 @@ /* 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 @@ 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 @@ -> 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ (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 @@ /* 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);
--- a/src/imap/cmd-namespace.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/cmd-namespace.c Thu Jan 20 20:59:07 2011 +0200 @@ -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 @@ 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, "\")"); }
--- a/src/imap/cmd-rename.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/cmd-rename.c Thu Jan 20 20:59:07 2011 +0200 @@ -8,17 +8,17 @@ { 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 @@ /* 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
--- a/src/imap/cmd-select.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/cmd-select.c Thu Jan 20 20:59:07 2011 +0200 @@ -373,7 +373,7 @@ 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 @@ 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 @@ (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);
--- a/src/imap/cmd-status.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/cmd-status.c Thu Jan 20 20:59:07 2011 +0200 @@ -13,7 +13,7 @@ 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 @@ 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;
--- a/src/imap/cmd-subscribe.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/cmd-subscribe.c Thu Jan 20 20:59:07 2011 +0200 @@ -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) +static bool +subscribe_is_valid_name(struct client_command_context *cmd, struct mailbox *box) { - 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) -{ - 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 @@ 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; - - 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"); - return TRUE; - } + orig_mailbox = mailbox; - /* 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."); + ns = client_find_namespace(cmd, &mailbox); + if (ns == NULL) 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; }
--- a/src/imap/imap-commands-util.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/imap-commands-util.c Thu Jan 20 20:59:07 2011 +0200 @@ -14,16 +14,13 @@ #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 @@ 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 @@ { 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 @@ if (ns1 != ns2) return FALSE; - name1 = mailbox_get_name(box1); + name1 = mailbox_get_vname(box1); if (strcmp(name1, name2) == 0) return TRUE;
--- a/src/imap/imap-commands-util.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/imap/imap-commands-util.h Thu Jan 20 20:59:07 2011 +0200 @@ -12,8 +12,7 @@ /* 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. */
--- a/src/lib-lda/mail-deliver.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-lda/mail-deliver.c Thu Jan 20 20:59:07 2011 +0200 @@ -141,14 +141,15 @@ *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 @@ } 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 */
--- a/src/lib-storage/index/cydir/cydir-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/cydir/cydir-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -36,7 +36,7 @@ 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 @@ 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);
--- a/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/dbox-multi/mdbox-storage-rebuild.c Thu Jan 20 20:59:07 2011 +0200 @@ -495,11 +495,9 @@ 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);
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/dbox-multi/mdbox-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -81,9 +81,9 @@ 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 @@ 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;
--- a/src/lib-storage/index/dbox-multi/mdbox-storage.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/dbox-multi/mdbox-storage.h Thu Jan 20 20:59:07 2011 +0200 @@ -61,10 +61,6 @@ 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);
--- a/src/lib-storage/index/dbox-single/sdbox-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/dbox-single/sdbox-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -30,7 +30,7 @@ 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 @@ 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;
--- a/src/lib-storage/index/imapc/imapc-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/imapc/imapc-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -305,7 +305,7 @@ 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 @@ 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;
--- a/src/lib-storage/index/index-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/index-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -250,20 +250,17 @@ 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); + i_assert(vname != 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)); - + 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 @@ 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; }
--- a/src/lib-storage/index/index-storage.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/index-storage.h Thu Jan 20 20:59:07 2011 +0200 @@ -60,7 +60,7 @@ 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);
--- a/src/lib-storage/index/maildir/maildir-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/maildir/maildir-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -263,7 +263,7 @@ 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 @@ 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);
--- a/src/lib-storage/index/mbox/mbox-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/mbox/mbox-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -345,7 +345,7 @@ 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->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;
--- a/src/lib-storage/index/raw/raw-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/raw/raw-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -36,7 +36,7 @@ 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 @@ 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;
--- a/src/lib-storage/index/shared/shared-list.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/shared/shared-list.c Thu Jan 20 20:59:07 2011 +0200 @@ -43,12 +43,13 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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,
--- a/src/lib-storage/index/shared/shared-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/index/shared/shared-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -130,6 +130,7 @@ 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 @@ } 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 @@ } 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 @@ *_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 @@ 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 @@ 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 @@ 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);
--- a/src/lib-storage/list/index-mailbox-list.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/list/index-mailbox-list.c Thu Jan 20 20:59:07 2011 +0200 @@ -100,7 +100,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } 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 */
--- a/src/lib-storage/list/mailbox-list-fs-iter.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Thu Jan 20 20:59:07 2011 +0200 @@ -223,7 +223,7 @@ 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 @@ 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 @@ 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 @@ } /* 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;
--- a/src/lib-storage/list/mailbox-list-fs.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/list/mailbox-list-fs.c Thu Jan 20 20:59:07 2011 +0200 @@ -135,6 +135,11 @@ 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_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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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,
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/list/mailbox-list-maildir-iter.c Thu Jan 20 20:59:07 2011 +0200 @@ -43,31 +43,30 @@ 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 @@ } 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,6 +260,81 @@ } static int +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; + const char *fname, *storage_name, *vname; + enum mailbox_info_flags flags; + enum imap_match_result match; + struct mailbox_node *node; + bool created; + 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) { @@ -270,14 +342,7 @@ struct mail_namespace *ns = list->ns; DIR *dirp; struct dirent *d; - const char *mailbox_name; - string_t *mailbox; - enum mailbox_info_flags flags; - enum imap_match_result match; - struct mailbox_node *node; - bool created; - struct stat st; - int ret; + int ret = 0; dirp = opendir(ctx->dir); if (dirp == NULL) { @@ -292,77 +357,13 @@ 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 @@ 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 @@ 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 @@ 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;
--- a/src/lib-storage/list/mailbox-list-maildir.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/list/mailbox-list-maildir.c Thu Jan 20 20:59:07 2011 +0200 @@ -29,6 +29,7 @@ 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 @@ 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 @@ } 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 @@ } 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 @@ 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_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 @@ 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 @@ 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 @@ /* 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 @@ } 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 @@ 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 @@ 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 @@ 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 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 @@ 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,
--- a/src/lib-storage/list/mailbox-list-maildir.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/list/mailbox-list-maildir.h Thu Jan 20 20:59:07 2011 +0200 @@ -15,6 +15,7 @@ struct mailbox_list list; const char *global_temp_prefix, *temp_prefix; + char sep; }; struct mailbox_list_iterate_context *
--- a/src/lib-storage/list/mailbox-list-none.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/list/mailbox-list-none.c Thu Jan 20 20:59:07 2011 +0200 @@ -47,6 +47,11 @@ 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 @@ 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 @@ 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,
--- a/src/lib-storage/list/mailbox-list-subscriptions.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/list/mailbox-list-subscriptions.c Thu Jan 20 20:59:07 2011 +0200 @@ -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 @@ (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); }
--- a/src/lib-storage/mail-namespace.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mail-namespace.c Thu Jan 20 20:59:07 2011 +0200 @@ -27,22 +27,7 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 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 @@ 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 @@ } 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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;
--- a/src/lib-storage/mail-namespace.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mail-namespace.h Thu Jan 20 20:59:07 2011 +0200 @@ -46,7 +46,6 @@ int refcount; enum namespace_type type; - char sep, real_sep, sep_str[3]; enum namespace_flags flags; char *prefix; @@ -93,48 +92,35 @@ /* 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,
--- a/src/lib-storage/mail-search.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mail-search.c Thu Jan 20 20:59:07 2011 +0200 @@ -99,7 +99,7 @@ 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:
--- a/src/lib-storage/mail-storage-private.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mail-storage-private.h Thu Jan 20 20:59:07 2011 +0200 @@ -38,7 +38,7 @@ 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); };
--- a/src/lib-storage/mail-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mail-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -560,20 +560,20 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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;
--- a/src/lib-storage/mail-storage.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mail-storage.h Thu Jan 20 20:59:07 2011 +0200 @@ -341,7 +341,7 @@ /* 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 @@ 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);
--- a/src/lib-storage/mailbox-list-private.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mailbox-list-private.h Thu Jan 20 20:59:07 2011 +0200 @@ -34,7 +34,7 @@ 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 @@ 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 @@ struct mailbox_list { const char *name; - char hierarchy_sep; enum mailbox_list_properties props; size_t mailbox_name_max_length; @@ -147,8 +151,15 @@ 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);
--- a/src/lib-storage/mailbox-list.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mailbox-list.c Thu Jan 20 20:59:07 2011 +0200 @@ -345,6 +345,98 @@ 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 @@ 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 @@ *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 @@ 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 @@ 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 @@ 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 @@ break; /* see if parent matches */ - p = strrchr(name, ns->sep); + p = strrchr(name, mail_namespace_get_sep(ns)); if (p == NULL) break;
--- a/src/lib-storage/mailbox-list.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/mailbox-list.h Thu Jan 20 20:59:07 2011 +0200 @@ -159,10 +159,11 @@ 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
--- a/src/lib-storage/test-mail-storage.h Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/test-mail-storage.h Thu Jan 20 20:59:07 2011 +0200 @@ -5,7 +5,7 @@ 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,
--- a/src/lib-storage/test-mailbox.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/lib-storage/test-mailbox.c Thu Jan 20 20:59:07 2011 +0200 @@ -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_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 @@ 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;
--- a/src/plugins/acl/acl-backend-vfile-acllist.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/acl/acl-backend-vfile-acllist.c Thu Jan 20 20:59:07 2011 +0200 @@ -165,8 +165,7 @@ 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);
--- a/src/plugins/acl/acl-backend-vfile.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/acl/acl-backend-vfile.c Thu Jan 20 20:59:07 2011 +0200 @@ -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 @@ 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 @@ 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); }
--- a/src/plugins/acl/acl-mailbox-list.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/acl/acl-mailbox-list.c Thu Jan 20 20:59:07 2011 +0200 @@ -90,7 +90,6 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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);
--- a/src/plugins/autocreate/autocreate-plugin.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/autocreate/autocreate-plugin.c Thu Jan 20 20:59:07 2011 +0200 @@ -18,7 +18,7 @@ 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 @@ 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)
--- a/src/plugins/fts-solr/fts-backend-solr.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/fts-solr/fts-backend-solr.c Thu Jan 20 20:59:07 2011 +0200 @@ -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_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 @@ 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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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,
--- a/src/plugins/fts/fts-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/fts/fts-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -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 @@ 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 @@ 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 @@ 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,
--- a/src/plugins/imap-acl/imap-acl-plugin.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/imap-acl/imap-acl-plugin.c Thu Jan 20 20:59:07 2011 +0200 @@ -57,7 +57,6 @@ { 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 @@ 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 @@ { 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 @@ 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) {
--- a/src/plugins/imap-quota/imap-quota-plugin.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/imap-quota/imap-quota-plugin.c Thu Jan 20 20:59:07 2011 +0200 @@ -74,14 +74,14 @@ 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 @@ 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 */
--- a/src/plugins/listescape/listescape-plugin.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/listescape/listescape-plugin.c Thu Jan 20 20:59:07 2011 +0200 @@ -13,38 +13,25 @@ #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 @@ 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 @@ 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 @@ 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 @@ 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); } -} - -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) -{ - struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list); - struct mail_namespace *orig_ns; - const char **escaped_patterns; - unsigned int i; - - 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; -} - -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) -{ - 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; + return str_c(dest); } -static const struct mailbox_info * -listescape_mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx) +static const char *listescape_list_get_vname(struct mailbox_list *list, + const char *storage_name) { - 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); + struct listescape_mailbox_list *mlist = LIST_ESCAPE_LIST_CONTEXT(list); + const char *vname; - 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; + vname = mlist->module_ctx.super.get_vname(list, storage_name); + return list_unescape(mlist, list->ns, vname); } -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) +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); - 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 @@ 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 struct mail_storage_hooks listescape_mail_storage_hooks = { - .mail_storage_created = listescape_mail_storage_created, .mailbox_list_created = listescape_mailbox_list_created };
--- a/src/plugins/quota/quota-count.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/quota/quota-count.c Thu Jan 20 20:59:07 2011 +0200 @@ -17,20 +17,17 @@ 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);
--- a/src/plugins/quota/quota-maildir.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/quota/quota-maildir.c Thu Jan 20 20:59:07 2011 +0200 @@ -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 @@ 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 @@ { struct mailbox_list *list; struct mail_storage *storage; - const char *name = ""; if (root->limits_initialized) return root->maildirsize_path != NULL; @@ -632,7 +632,7 @@ 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 &
--- a/src/plugins/quota/quota-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/quota/quota-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -561,7 +561,7 @@ 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); } }
--- a/src/plugins/quota/quota.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/quota/quota.c Thu Jan 20 20:59:07 2011 +0200 @@ -761,10 +761,9 @@ { 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;
--- a/src/plugins/snarf/snarf-plugin.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/snarf/snarf-plugin.c Thu Jan 20 20:59:07 2011 +0200 @@ -125,7 +125,7 @@ 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 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 @@ 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 @@ 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;
--- a/src/plugins/trash/trash-plugin.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/trash/trash-plugin.c Thu Jan 20 20:59:07 2011 +0200 @@ -225,16 +225,11 @@ 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; }
--- a/src/plugins/virtual/virtual-config.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/virtual/virtual-config.c Thu Jan 20 20:59:07 2011 +0200 @@ -135,7 +135,7 @@ 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);
--- a/src/plugins/virtual/virtual-storage.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/plugins/virtual/virtual-storage.c Thu Jan 20 20:59:07 2011 +0200 @@ -49,7 +49,8 @@ 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 @@ 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 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 @@ 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;
--- a/src/pop3/pop3-client.c Thu Jan 20 19:21:20 2011 +0200 +++ b/src/pop3/pop3-client.c Thu Jan 20 20:59:07 2011 +0200 @@ -236,7 +236,7 @@ { 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 @@ 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.");