# HG changeset patch # User Timo Sirainen # Date 1193525612 -10800 # Node ID e1fde9940f7e85ebd4ed99c91720dfbd4f061734 # Parent e2a4722f1b9b514c28a3bdd4813a2c286b9cafc9 Fixes to handling namespace prefixes and real!=virtual separator. Added a new MAILBOX_LIST_ITER_VIRTUAL_NAMES which specifies if mailbox listing should be using virtual or real mailbox names. diff -r e2a4722f1b9b -r e1fde9940f7e src/imap/cmd-list.c --- a/src/imap/cmd-list.c Sun Oct 28 01:52:00 2007 +0300 +++ b/src/imap/cmd-list.c Sun Oct 28 01:53:32 2007 +0300 @@ -819,14 +819,15 @@ args += 2; } + ctx->list_flags = MAILBOX_LIST_ITER_VIRTUAL_NAMES; if (lsub) { /* LSUB - we don't care about flags */ - ctx->list_flags = MAILBOX_LIST_ITER_SELECT_SUBSCRIBED | + ctx->list_flags |= MAILBOX_LIST_ITER_SELECT_SUBSCRIBED | MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH | MAILBOX_LIST_ITER_RETURN_NO_FLAGS; } else if (!ctx->used_listext) { /* non-extended LIST - return children flags always */ - ctx->list_flags = MAILBOX_LIST_ITER_RETURN_CHILDREN; + ctx->list_flags |= MAILBOX_LIST_ITER_RETURN_CHILDREN; } if (args[0].type != IMAP_ARG_EOL) { diff -r e2a4722f1b9b -r e1fde9940f7e src/lib-storage/list/mailbox-list-fs-iter.c --- a/src/lib-storage/list/mailbox-list-fs-iter.c Sun Oct 28 01:52:00 2007 +0300 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Sun Oct 28 01:53:32 2007 +0300 @@ -30,6 +30,7 @@ struct imap_match_glob *glob; struct mailbox_tree_context *subs_tree; struct mailbox_tree_iterate_context *tree_iter; + char sep; enum mailbox_info_flags inbox_flags; @@ -50,19 +51,19 @@ fs_list_next(struct fs_list_iterate_context *ctx); static int -pattern_get_path_pos(struct mail_namespace *ns, const char *pattern, +pattern_get_path_pos(struct fs_list_iterate_context *ctx, const char *pattern, const char *path, unsigned int *pos_r) { unsigned int i, j; - if (strncasecmp(path, "INBOX", 5) == 0 && path[5] == ns->sep) { + if (strncasecmp(path, "INBOX", 5) == 0 && path[5] == ctx->sep) { /* make sure INBOX prefix is matched case-insensitively */ char *tmp = t_strdup_noconst(pattern); if (strncmp(path, "INBOX", 5) != 0) - path = t_strdup_printf("INBOX%c%s", ns->sep, path + 6); + path = t_strdup_printf("INBOX%c%s", ctx->sep, path + 6); - for (i = 0; tmp[i] != ns->sep && tmp[i] != '\0'; i++) + for (i = 0; tmp[i] != ctx->sep && tmp[i] != '\0'; i++) tmp[i] = i_toupper(tmp[i]); pattern = tmp; } @@ -73,13 +74,13 @@ if (pattern[j] == '%') { /* skip until we're at the next hierarchy separator */ - if (path[i] == ns->sep) { + if (path[i] == ctx->sep) { /* assume that pattern matches. we can't be sure, but it'll be checked later. */ for (j++; pattern[j] != '\0'; j++) { if (pattern[j] == '*') return -1; - if (pattern[j] == ns->sep) { + if (pattern[j] == ctx->sep) { j++; break; } @@ -98,18 +99,18 @@ } static bool -pattern_has_wildcard_at(struct mail_namespace *ns, const char *pattern, - const char *path) +pattern_has_wildcard_at(struct fs_list_iterate_context *ctx, + const char *pattern, const char *path) { unsigned int pos; int ret; - if ((ret = pattern_get_path_pos(ns, pattern, path, &pos)) < 0) + if ((ret = pattern_get_path_pos(ctx, pattern, path, &pos)) < 0) return TRUE; if (ret == 0) return FALSE; - for (; pattern[pos] != '\0' && pattern[pos] != ns->sep; pos++) { + for (; pattern[pos] != '\0' && pattern[pos] != ctx->sep; pos++) { if (pattern[pos] == '%' || pattern[pos] == '*') return TRUE; } @@ -128,8 +129,7 @@ t_push(); patterns = array_idx(&ctx->valid_patterns, 0); for (i = 0; patterns[i] != NULL; i++) { - if (pattern_has_wildcard_at(ctx->ctx.list->ns, - patterns[i], list_path)) + if (pattern_has_wildcard_at(ctx, patterns[i], list_path)) break; } t_pop(); @@ -164,7 +164,7 @@ enum mailbox_list_iter_flags flags) { struct fs_list_iterate_context *ctx; - const char *path; + const char *path, *vpath; char *pattern; DIR *dirp; int ret; @@ -174,6 +174,8 @@ ctx->ctx.flags = flags; ctx->info_pool = pool_alloconly_create("fs list", 1024); ctx->next = fs_list_next; + ctx->sep = (flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0 ? + _list->ns->sep : _list->ns->real_sep; i_array_init(&ctx->valid_patterns, 8); for (; *patterns != NULL; patterns++) { @@ -195,15 +197,14 @@ } patterns = (const void *)array_idx(&ctx->valid_patterns, 0); ctx->glob = imap_match_init_multiple(default_pool, patterns, TRUE, - _list->ns->sep); + ctx->sep); if ((flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED | MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) { /* we want to return MAILBOX_SUBSCRIBED flags, possibly for all mailboxes. Build a mailbox tree of all the subscriptions. */ - ctx->subs_tree = mailbox_tree_init(_list->ns->sep); - if (mailbox_list_subscriptions_fill(&ctx->ctx, - ctx->subs_tree, + ctx->subs_tree = mailbox_tree_init(ctx->sep); + if (mailbox_list_subscriptions_fill(&ctx->ctx, ctx->subs_tree, ctx->glob, FALSE) < 0) { ctx->ctx.failed = TRUE; return &ctx->ctx; @@ -217,15 +218,17 @@ return &ctx->ctx; } + vpath = (flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0 ? + _list->ns->prefix : ""; path = mailbox_list_get_path(_list, NULL, MAILBOX_LIST_PATH_TYPE_DIR); - if ((ret = list_opendir(ctx, path, _list->ns->prefix, &dirp)) < 0) + if ((ret = list_opendir(ctx, path, vpath, &dirp)) < 0) return &ctx->ctx; if (ret > 0) { ctx->dir = i_new(struct list_dir_context, 1); ctx->dir->dirp = dirp; ctx->dir->real_path = i_strdup(path); - ctx->dir->virtual_path = i_strdup(_list->ns->prefix); + ctx->dir->virtual_path = i_strdup(vpath); } return &ctx->ctx; } @@ -411,7 +414,7 @@ if ((ctx->info.flags & MAILBOX_NOINFERIORS) == 0) { /* subdirectory. scan inside it. */ - vpath = t_strdup_printf("%s%c", list_path, ns->sep); + vpath = t_strdup_printf("%s%c", list_path, ctx->sep); match2 = imap_match(ctx->glob, vpath); if (match == IMAP_MATCH_YES) @@ -428,7 +431,7 @@ dir->dirp = dirp; dir->real_path = i_strdup(real_path); dir->virtual_path = - i_strdup_printf("%s%c", list_path, ns->sep); + i_strdup_printf("%s%c", list_path, ctx->sep); dir->prev = ctx->dir; ctx->dir = dir; @@ -480,7 +483,6 @@ static struct dirent *fs_list_dir_next(struct fs_list_iterate_context *ctx) { struct list_dir_context *dir = ctx->dir; - struct mail_namespace *ns = ctx->ctx.list->ns; char *const *patterns; const char *fname, *path, *p; unsigned int pos; @@ -501,14 +503,14 @@ patterns += dir->pattern_pos; dir->pattern_pos++; - ret = pattern_get_path_pos(ns, *patterns, dir->virtual_path, + ret = pattern_get_path_pos(ctx, *patterns, dir->virtual_path, &pos); if (ret == 0) continue; i_assert(ret > 0); /* get the filename from the pattern */ - p = strchr(*patterns + pos, ns->sep); + p = strchr(*patterns + pos, ctx->sep); fname = p == NULL ? *patterns + pos : t_strdup_until(*patterns + pos, p); diff -r e2a4722f1b9b -r e1fde9940f7e src/lib-storage/list/mailbox-list-maildir-iter.c --- a/src/lib-storage/list/mailbox-list-maildir-iter.c Sun Oct 28 01:52:00 2007 +0300 +++ b/src/lib-storage/list/mailbox-list-maildir-iter.c Sun Oct 28 01:53:32 2007 +0300 @@ -36,30 +36,37 @@ } } -static void maildir_fill_parents(struct maildir_list_iterate_context *ctx, - struct imap_match_glob *glob, bool update_only, - string_t *mailbox, const char *mailbox_c, - enum mailbox_info_flags flags) +static void +maildir_fill_parents(struct maildir_list_iterate_context *ctx, + struct imap_match_glob *glob, bool update_only, + string_t *mailbox, enum mailbox_info_flags flags) { + struct mail_namespace *ns = ctx->ctx.list->ns; struct mailbox_node *node; - const char *p; + const char *p, *mailbox_c; char hierarchy_sep; bool created; - const char *ns_prefix = ctx->ctx.list->ns->prefix; - unsigned int ns_prefix_len = strlen(ns_prefix); + unsigned int prefix_len; - hierarchy_sep = ctx->ctx.list->ns->sep; + if ((ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0) { + hierarchy_sep = ns->sep; + prefix_len = ns->prefix_len; + } else { + hierarchy_sep = ns->real_sep; + prefix_len = 0; + } t_push(); + 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); if (imap_match(glob, mailbox_c) != IMAP_MATCH_YES) continue; - if (*ns_prefix != '\0' && str_len(mailbox) == ns_prefix_len-1 && - strncmp(mailbox_c, ns_prefix, ns_prefix_len - 1) == 0 && - mailbox_c[ns_prefix_len-1] == hierarchy_sep) { + if (prefix_len > 0 && str_len(mailbox) == prefix_len-1 && + strncmp(mailbox_c, ns->prefix, prefix_len - 1) == 0 && + mailbox_c[prefix_len-1] == hierarchy_sep) { /* don't return matches to namespace prefix itself */ continue; } @@ -92,14 +99,12 @@ DIR *dirp; struct dirent *d; const char *mailbox_name; - char *mailbox_c; string_t *mailbox; enum mailbox_info_flags flags; enum imap_match_result match; struct mailbox_node *node; - bool created; + bool created, virtual_names; char prefix_char; - unsigned int pos; int ret; dirp = opendir(ctx->dir); @@ -112,6 +117,7 @@ return 0; } + virtual_names = (ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0; prefix_char = strcmp(ctx->ctx.list->name, MAILBOX_LIST_NAME_IMAPDIR) != 0 ? ctx->ctx.list->hierarchy_sep : '\0'; @@ -134,22 +140,17 @@ (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0'))) continue; - /* make sure the pattern matches */ - str_truncate(mailbox, 0); - if ((ns->flags & NAMESPACE_FLAG_INBOX) == 0 || - strcasecmp(mailbox_name, "INBOX") != 0) - str_append(mailbox, ns->prefix); - - pos = str_len(mailbox); - str_append(mailbox, mailbox_name); - mailbox_c = str_c_modifiable(mailbox); - while (mailbox_c[pos] != '\0') { - if (mailbox_c[pos] == ns->real_sep) - mailbox_c[pos] = ns->sep; - pos++; + if (!virtual_names) { + str_truncate(mailbox, 0); + str_append(mailbox, mailbox_name); + mailbox_name = str_c(mailbox); + } else { + mailbox_name = mail_namespace_get_vname(ns, mailbox, + mailbox_name); } - match = imap_match(glob, mailbox_c); + /* make sure the pattern matches */ + match = imap_match(glob, mailbox_name); if ((match & (IMAP_MATCH_YES | IMAP_MATCH_PARENT)) == 0) continue; @@ -172,13 +173,14 @@ if ((match & IMAP_MATCH_PARENT) != 0) { maildir_fill_parents(ctx, glob, update_only, - mailbox, mailbox_c, flags); + mailbox, flags); } else { created = FALSE; node = update_only ? - mailbox_tree_lookup(ctx->tree_ctx, mailbox_c) : + mailbox_tree_lookup(ctx->tree_ctx, + mailbox_name) : mailbox_tree_get(ctx->tree_ctx, - mailbox_c, &created); + mailbox_name, &created); if (node != NULL) { if (created) @@ -237,16 +239,20 @@ { struct maildir_list_iterate_context *ctx; struct imap_match_glob *glob; + char sep; pool_t pool; + sep = (flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0 ? + _list->ns->sep : _list->ns->real_sep; + pool = pool_alloconly_create("maildir_list", 1024); ctx = p_new(pool, struct maildir_list_iterate_context, 1); 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(sep); - glob = imap_match_init_multiple(pool, patterns, TRUE, _list->ns->sep); + glob = imap_match_init_multiple(pool, patterns, TRUE, sep); ctx->dir = _list->set.root_dir; diff -r e2a4722f1b9b -r e1fde9940f7e src/lib-storage/list/mailbox-list-subscriptions.c --- a/src/lib-storage/list/mailbox-list-subscriptions.c Sun Oct 28 01:52:00 2007 +0300 +++ b/src/lib-storage/list/mailbox-list-subscriptions.c Sun Oct 28 01:53:32 2007 +0300 @@ -1,93 +1,11 @@ /* Copyright (c) 2002-2007 Dovecot authors, see the included COPYING file */ #include "lib.h" -#include "imap-match.h" -#include "mailbox-tree.h" +#include "str.h" #include "subscription-file.h" #include "mailbox-list-private.h" #include "mailbox-list-subscriptions.h" -static void node_fix_parents(struct mailbox_node *node) -{ - /* If we happened to create any of the parents, we need to mark them - nonexistent. */ - node = node->parent; - for (; node != NULL; node = node->parent) { - if ((node->flags & MAILBOX_MATCHED) == 0) - node->flags |= MAILBOX_NONEXISTENT; - } -} - -static void -mailbox_list_subscription_add(struct mailbox_list_iterate_context *ctx, - struct mailbox_tree_context *tree_ctx, - struct imap_match_glob *glob, - bool update_only, const char *name) -{ - struct mail_namespace *ns = ctx->list->ns; - struct mailbox_node *node; - enum mailbox_info_flags create_flags, always_flags; - enum imap_match_result match; - const char *p; - bool created, add_matched; - - if ((ns->flags & NAMESPACE_FLAG_INBOX) == 0 || - strcasecmp(name, "INBOX") != 0) { - /* add namespace prefix to all but INBOX */ - name = t_strconcat(ns->prefix, name, NULL); - } - - create_flags = (update_only || - (ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) ? - (MAILBOX_NONEXISTENT | MAILBOX_NOCHILDREN) : 0; - always_flags = MAILBOX_SUBSCRIBED; - add_matched = TRUE; - - t_push(); - for (;;) { - created = FALSE; - match = imap_match(glob, name); - if (match == IMAP_MATCH_YES) { - node = update_only ? - mailbox_tree_lookup(tree_ctx, name) : - mailbox_tree_get(tree_ctx, name, &created); - if (created) { - node->flags = create_flags; - if (create_flags != 0) - node_fix_parents(node); - } - if (node != NULL) { - if (!update_only && add_matched) - node->flags |= MAILBOX_MATCHED; - node->flags |= always_flags; - } - /* We don't want to show the parent mailboxes unless - something else matches them, but if they are matched - we want to show them having child subscriptions */ - add_matched = FALSE; - } else { - if ((match & IMAP_MATCH_PARENT) == 0) - break; - /* We've a (possibly) non-subscribed parent mailbox - which has a subscribed child mailbox. Make sure we - return the parent mailbox. */ - } - - if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) == 0) - break; - - /* see if parent matches */ - p = strrchr(name, ns->sep); - if (p == NULL) - break; - - name = t_strdup_until(name, p); - create_flags &= ~MAILBOX_NOCHILDREN; - always_flags = MAILBOX_CHILDREN | MAILBOX_CHILD_SUBSCRIBED; - } - t_pop(); -} - int mailbox_list_subscriptions_fill(struct mailbox_list_iterate_context *ctx, struct mailbox_tree_context *tree_ctx, struct imap_match_glob *glob, @@ -96,27 +14,26 @@ struct mail_namespace *ns = ctx->list->ns; struct subsfile_list_context *subsfile_ctx; const char *path, *name; - char *p; + string_t *vname; + bool match_parents; + t_push(); + vname = t_str_new(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); + match_parents = + (ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) != 0; + while ((name = subsfile_list_next(subsfile_ctx)) != NULL) { - t_push(); - if (ns->real_sep != ns->sep) { - name = p = t_strdup_noconst(name); - for (; *p != '\0'; p++) { - if (*p == ns->real_sep) - *p = ns->sep; - } - } - mailbox_list_subscription_add(ctx, tree_ctx, glob, update_only, - name); - t_pop(); + name = mail_namespace_get_vname(ns, vname, name); + mailbox_list_iter_update(ctx, tree_ctx, glob, update_only, + match_parents, name); } + t_pop(); return subsfile_list_deinit(subsfile_ctx); } diff -r e2a4722f1b9b -r e1fde9940f7e src/lib-storage/mail-namespace.c --- a/src/lib-storage/mail-namespace.c Sun Oct 28 01:52:00 2007 +0300 +++ b/src/lib-storage/mail-namespace.c Sun Oct 28 01:53:32 2007 +0300 @@ -1,6 +1,7 @@ /* Copyright (c) 2005-2007 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "str.h" #include "file-lock.h" #include "mail-storage.h" #include "mail-namespace.h" @@ -292,6 +293,23 @@ return ret; } +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) == 0 || + strcasecmp(name, "INBOX") != 0) + 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); +} + char mail_namespace_get_root_sep(struct mail_namespace *namespaces) { while ((namespaces->flags & NAMESPACE_FLAG_LIST) == 0) diff -r e2a4722f1b9b -r e1fde9940f7e src/lib-storage/mail-namespace.h --- a/src/lib-storage/mail-namespace.h Sun Oct 28 01:52:00 2007 +0300 +++ b/src/lib-storage/mail-namespace.h Sun Oct 28 01:53:32 2007 +0300 @@ -47,6 +47,11 @@ /* Update hierarchy separators in given name to real_sep characters. */ const char *mail_namespace_fix_sep(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 hierarchy separator for mailboxes that are listed at root. */ char mail_namespace_get_root_sep(struct mail_namespace *namespaces); diff -r e2a4722f1b9b -r e1fde9940f7e src/lib-storage/mailbox-list-private.h --- a/src/lib-storage/mailbox-list-private.h Sun Oct 28 01:52:00 2007 +0300 +++ b/src/lib-storage/mailbox-list-private.h Sun Oct 28 01:53:32 2007 +0300 @@ -5,6 +5,8 @@ #include "mailbox-list.h" struct dirent; +struct imap_match_glob; +struct mailbox_tree_context; struct mailbox_list_vfuncs { struct mailbox_list *(*alloc)(void); @@ -101,6 +103,11 @@ int mailbox_list_delete_index_control(struct mailbox_list *list, const char *name); +void mailbox_list_iter_update(struct mailbox_list_iterate_context *ctx, + struct mailbox_tree_context *tree_ctx, + struct imap_match_glob *glob, bool update_only, + bool match_parents, const char *name); + bool mailbox_list_name_is_too_large(const char *name, char sep); enum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d); diff -r e2a4722f1b9b -r e1fde9940f7e src/lib-storage/mailbox-list.c --- a/src/lib-storage/mailbox-list.c Sun Oct 28 01:52:00 2007 +0300 +++ b/src/lib-storage/mailbox-list.c Sun Oct 28 01:53:32 2007 +0300 @@ -6,6 +6,8 @@ #include "home-expand.h" #include "mkdir-parents.h" #include "unlink-directory.h" +#include "imap-match.h" +#include "mailbox-tree.h" #include "mailbox-list-private.h" #include @@ -441,6 +443,80 @@ return 0; } +static void node_fix_parents(struct mailbox_node *node) +{ + /* If we happened to create any of the parents, we need to mark them + nonexistent. */ + node = node->parent; + for (; node != NULL; node = node->parent) { + if ((node->flags & MAILBOX_MATCHED) == 0) + node->flags |= MAILBOX_NONEXISTENT; + } +} + +void mailbox_list_iter_update(struct mailbox_list_iterate_context *ctx, + struct mailbox_tree_context *tree_ctx, + struct imap_match_glob *glob, bool update_only, + bool match_parents, const char *name) +{ + struct mail_namespace *ns = ctx->list->ns; + struct mailbox_node *node; + enum mailbox_info_flags create_flags, always_flags; + enum imap_match_result match; + const char *p; + bool created, add_matched; + + create_flags = (update_only || + (ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) ? + (MAILBOX_NONEXISTENT | MAILBOX_NOCHILDREN) : 0; + always_flags = MAILBOX_SUBSCRIBED; + add_matched = TRUE; + + t_push(); + for (;;) { + created = FALSE; + match = imap_match(glob, name); + if (match == IMAP_MATCH_YES) { + node = update_only ? + mailbox_tree_lookup(tree_ctx, name) : + mailbox_tree_get(tree_ctx, name, &created); + if (created) { + node->flags = create_flags; + if (create_flags != 0) + node_fix_parents(node); + } + if (node != NULL) { + if (!update_only && add_matched) + node->flags |= MAILBOX_MATCHED; + node->flags |= always_flags; + } + /* We don't want to show the parent mailboxes unless + something else matches them, but if they are matched + we want to show them having child subscriptions */ + add_matched = FALSE; + } else { + if ((match & IMAP_MATCH_PARENT) == 0) + break; + /* We've a (possibly) non-subscribed parent mailbox + which has a subscribed child mailbox. Make sure we + return the parent mailbox. */ + } + + if (!match_parents) + break; + + /* see if parent matches */ + p = strrchr(name, ns->sep); + if (p == NULL) + break; + + name = t_strdup_until(name, p); + create_flags &= ~MAILBOX_NOCHILDREN; + always_flags = MAILBOX_CHILDREN | MAILBOX_CHILD_SUBSCRIBED; + } + t_pop(); +} + bool mailbox_list_name_is_too_large(const char *name, char sep) { unsigned int levels = 1, level_len = 0; diff -r e2a4722f1b9b -r e1fde9940f7e src/lib-storage/mailbox-list.h --- a/src/lib-storage/mailbox-list.h Sun Oct 28 01:52:00 2007 +0300 +++ b/src/lib-storage/mailbox-list.h Sun Oct 28 01:53:32 2007 +0300 @@ -45,6 +45,9 @@ enum mailbox_list_iter_flags { /* Ignore index file and ACLs (used by ACL plugin internally) */ MAILBOX_LIST_ITER_RAW_LIST = 0x000001, + /* Use virtual mailbox names (virtual separators and namespace + prefixes) for patterns and for returned mailbox names. */ + MAILBOX_LIST_ITER_VIRTUAL_NAMES = 0x000002, /* List only subscribed mailboxes */ MAILBOX_LIST_ITER_SELECT_SUBSCRIBED = 0x000010, diff -r e2a4722f1b9b -r e1fde9940f7e src/plugins/acl/acl-mailbox-list.c --- a/src/plugins/acl/acl-mailbox-list.c Sun Oct 28 01:52:00 2007 +0300 +++ b/src/plugins/acl/acl-mailbox-list.c Sun Oct 28 01:53:32 2007 +0300 @@ -2,6 +2,7 @@ #include "lib.h" #include "array.h" +#include "str.h" #include "imap-match.h" #include "mailbox-tree.h" #include "mail-namespace.h" @@ -73,12 +74,11 @@ const struct acl_mask *acl_mask; struct acl_mailbox_list_context *nonowner_list_ctx; struct imap_match_glob *glob; - enum imap_match_result match; - struct mailbox_node *node; + struct mail_namespace *ns = ctx->ctx.list->ns; const char *name; + string_t *vname; char sep; int try, ret; - bool created; if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RAW_LIST) != 0) return FALSE; @@ -89,7 +89,13 @@ /* default is to not list mailboxes. we can optimize this. */ t_push(); - sep = mailbox_list_get_hierarchy_sep(ctx->ctx.list); + if ((ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0) { + sep = ns->sep; + vname = t_str_new(256); + } else { + sep = ns->real_sep; + vname = NULL; + } glob = imap_match_init_multiple(pool_datastack_create(), patterns, TRUE, sep); @@ -100,23 +106,12 @@ while ((ret = acl_backend_nonowner_lookups_iter_next( nonowner_list_ctx, &name)) > 0) { - match = imap_match(glob, name); - if (match == IMAP_MATCH_YES) { - node = mailbox_tree_get(ctx->tree, name, - &created); - if (created) - node->flags |= MAILBOX_NOCHILDREN; - node->flags |= MAILBOX_FLAG_MATCHED; - node->flags &= ~MAILBOX_NONEXISTENT; - } else if ((match & IMAP_MATCH_PARENT) != 0) { - node = mailbox_tree_get(ctx->tree, name, - &created); - if (created) - node->flags |= MAILBOX_NONEXISTENT; - node->flags |= MAILBOX_FLAG_MATCHED | - MAILBOX_CHILDREN; - node->flags &= ~MAILBOX_NOCHILDREN; + if (vname != NULL) { + name = mail_namespace_get_vname(ns, vname, + name); } + mailbox_list_iter_update(&ctx->ctx, ctx->tree, + glob, FALSE, TRUE, name); } if (ret == 0) break; @@ -159,15 +154,12 @@ struct acl_mailbox_list_iterate_context *ctx = (struct acl_mailbox_list_iterate_context *)_ctx; struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(_ctx->list); + struct mail_namespace *ns = _ctx->list->ns; const struct mailbox_info *info; struct mailbox_node *node; - const char *ns_prefix, *acl_name; - unsigned int ns_prefix_len; + const char *acl_name; int ret; - ns_prefix = _ctx->list->ns->prefix; - ns_prefix_len = strlen(ns_prefix); - for (;;) { if (ctx->tree_iter != NULL) { node = mailbox_tree_iterate_next(ctx->tree_iter, @@ -188,15 +180,20 @@ return info; } - /* Mailbox names contain namespace prefix, except when listing - INBOX. */ + t_push(); acl_name = info->name; - if (strncmp(acl_name, ns_prefix, ns_prefix_len) == 0) - acl_name += ns_prefix_len; + if ((ctx->ctx.flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) != 0) { + /* Mailbox names contain namespace prefix, + except when listing INBOX. */ + if (strncmp(acl_name, ns->prefix, ns->prefix_len) == 0) + acl_name += ns->prefix_len; + acl_name = mail_namespace_fix_sep(ns, acl_name); + } ret = acl_mailbox_list_have_right(alist, acl_name, ACL_STORAGE_RIGHT_LOOKUP, NULL); + t_pop(); if (ret > 0) return info; if (ret < 0) {