Mercurial > dovecot > original-hg > dovecot-1.2
changeset 8461:659667d89f69 HEAD
Added list=children option for namespaces.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 21 Nov 2008 17:03:27 +0200 |
parents | 8dfb193bb30c |
children | 449634ed81b6 |
files | src/imap/cmd-list.c src/imap/cmd-subscribe.c src/lib-storage/index/shared/shared-list.c src/lib-storage/index/shared/shared-storage.c src/lib-storage/mail-namespace.c src/lib-storage/mail-namespace.h src/master/mail-process.c src/master/master-settings.c src/master/master-settings.h |
diffstat | 9 files changed, 96 insertions(+), 26 deletions(-) [+] |
line wrap: on
line diff
--- a/src/imap/cmd-list.c Fri Nov 21 17:03:02 2008 +0200 +++ b/src/imap/cmd-list.c Fri Nov 21 17:03:27 2008 +0200 @@ -222,7 +222,7 @@ enum mailbox_info_flags flags; const char *name; string_t *str; - + ctx->cur_ns_send_prefix = FALSE; /* see if we already listed this as a valid mailbox in another @@ -257,6 +257,19 @@ } } + if ((ctx->ns->flags & NAMESPACE_FLAG_LIST_CHILDREN) != 0) { + if (have_children) { + /* children are going to be listed. */ + return; + } + if ((flags & MAILBOX_CHILDREN) == 0) { + /* namespace has no children. don't show it. */ + return; + } + /* namespace has children but they don't match the list + pattern. the prefix itself matches though, so show it. */ + } + name = ctx->cur_ns_skip_trailing_sep ? t_strndup(ctx->ns->prefix, len-1) : ctx->ns->prefix; @@ -504,8 +517,10 @@ if ((ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) return FALSE; - /* send the prefix if namespace is listable.. */ - if ((ctx->ns->flags & NAMESPACE_FLAG_LIST) != 0) + /* send the prefix if namespace is listable. if children are listable + we may or may not need to send it. */ + if ((ctx->ns->flags & (NAMESPACE_FLAG_LIST_PREFIX | + NAMESPACE_FLAG_LIST_CHILDREN)) != 0) return TRUE; /* ..or if pattern is exactly the same as namespace prefix. @@ -550,7 +565,8 @@ } /* hidden and non-listable namespaces are invisible to wildcards */ - if ((ns->flags & NAMESPACE_FLAG_LIST) == 0 && + if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX | + NAMESPACE_FLAG_LIST_CHILDREN)) == 0 && list_pattern_has_wildcards(cur_pattern)) return FALSE; @@ -623,7 +639,7 @@ /* it's possible that the namespace prefix matched, even though its children didn't */ if (ctx->cur_ns_send_prefix) - list_namespace_send_prefix(ctx, TRUE); + list_namespace_send_prefix(ctx, FALSE); return; } /* we should still list INBOX */
--- a/src/imap/cmd-subscribe.c Fri Nov 21 17:03:02 2008 +0200 +++ b/src/imap/cmd-subscribe.c Fri Nov 21 17:03:27 2008 +0200 @@ -10,7 +10,8 @@ unsigned int name_len = strlen(name); for (; ns != NULL; ns = ns->next) { - if ((ns->flags & NAMESPACE_FLAG_LIST) == 0) + if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX | + NAMESPACE_FLAG_LIST_CHILDREN)) == 0) continue; if (ns->prefix_len <= name_len)
--- a/src/lib-storage/index/shared/shared-list.c Fri Nov 21 17:03:02 2008 +0200 +++ b/src/lib-storage/index/shared/shared-list.c Fri Nov 21 17:03:27 2008 +0200 @@ -1,12 +1,16 @@ /* Copyright (c) 2008 Dovecot authors, see the included COPYING file */ #include "lib.h" +#include "imap-match.h" #include "mailbox-list-private.h" #include "index-storage.h" #include "shared-storage.h" struct shared_mailbox_list_iterate_context { struct mailbox_list_iterate_context ctx; + struct mail_namespace *cur_ns; + struct imap_match_glob *glob; + struct mailbox_info info; }; extern struct mailbox_list shared_mailbox_list; @@ -149,8 +153,11 @@ ctx = i_new(struct shared_mailbox_list_iterate_context, 1); ctx->ctx.list = list; ctx->ctx.flags = flags; - - /* FIXME */ + ctx->cur_ns = list->ns->user->namespaces; + ctx->info.ns = list->ns; + ctx->info.flags = MAILBOX_NONEXISTENT; + ctx->glob = imap_match_init_multiple(default_pool, patterns, + FALSE, list->ns->sep); return &ctx->ctx; } @@ -159,7 +166,34 @@ { struct shared_mailbox_list_iterate_context *ctx = (struct shared_mailbox_list_iterate_context *)_ctx; + struct mail_namespace *ns = ctx->cur_ns; + for (; ns != NULL; ns = ns->next) { + if (ns->type != NAMESPACE_SHARED || + (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) + continue; + if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX | + NAMESPACE_FLAG_LIST_CHILDREN)) == 0) + continue; + + if (ns->prefix_len < ctx->info.ns->prefix_len || + strncmp(ns->prefix, ctx->info.ns->prefix, + ctx->info.ns->prefix_len) != 0) + continue; + + /* visible and listable namespace under ourself, see if the + prefix matches without the trailing separator */ + i_assert(ns->prefix_len > 0); + ctx->info.name = t_strndup(ns->prefix, ns->prefix_len - 1); + if ((_ctx->flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) == 0) + ctx->info.name += ctx->info.ns->prefix_len; + if (imap_match(ctx->glob, ctx->info.name) == IMAP_MATCH_YES) { + ctx->cur_ns = ns->next; + return &ctx->info; + } + } + + ctx->cur_ns = NULL; return NULL; }
--- a/src/lib-storage/index/shared/shared-storage.c Fri Nov 21 17:03:02 2008 +0200 +++ b/src/lib-storage/index/shared/shared-storage.c Fri Nov 21 17:03:27 2008 +0200 @@ -269,7 +269,7 @@ ns->type = NAMESPACE_SHARED; ns->user = user; ns->prefix = i_strdup(str_c(prefix)); - ns->flags = NAMESPACE_FLAG_LIST | NAMESPACE_FLAG_HIDDEN | + ns->flags = NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN | NAMESPACE_FLAG_AUTOCREATED; ns->sep = _storage->ns->sep; @@ -285,6 +285,7 @@ return -1; } mail_user_add_namespace(user, ns); + _storage->ns->flags |= NAMESPACE_FLAG_USABLE; *_name = mail_namespace_fix_sep(ns, name); *ns_r = ns;
--- a/src/lib-storage/mail-namespace.c Fri Nov 21 17:03:02 2008 +0200 +++ b/src/lib-storage/mail-namespace.c Fri Nov 21 17:03:27 2008 +0200 @@ -39,19 +39,24 @@ enum file_lock_method lock_method) { struct mail_namespace *ns; - const char *sep, *type, *prefix, *driver, *error; + const char *sep, *type, *prefix, *driver, *error, *list; ns = i_new(struct mail_namespace, 1); sep = getenv(t_strdup_printf("NAMESPACE_%u_SEP", num)); type = getenv(t_strdup_printf("NAMESPACE_%u_TYPE", num)); prefix = getenv(t_strdup_printf("NAMESPACE_%u_PREFIX", num)); + list = getenv(t_strdup_printf("NAMESPACE_%u_LIST", num)); if (getenv(t_strdup_printf("NAMESPACE_%u_INBOX", num)) != NULL) ns->flags |= NAMESPACE_FLAG_INBOX; if (getenv(t_strdup_printf("NAMESPACE_%u_HIDDEN", num)) != NULL) ns->flags |= NAMESPACE_FLAG_HIDDEN; - if (getenv(t_strdup_printf("NAMESPACE_%u_LIST", num)) != NULL) - ns->flags |= NAMESPACE_FLAG_LIST; + if (list != NULL) { + if (strcmp(list, "children") == 0) + ns->flags |= NAMESPACE_FLAG_LIST_CHILDREN; + else + ns->flags |= NAMESPACE_FLAG_LIST_PREFIX; + } if (getenv(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS", num)) != NULL) ns->flags |= NAMESPACE_FLAG_SUBSCRIPTIONS; @@ -76,7 +81,7 @@ type == NULL ? "" : type, prefix, sep == NULL ? "" : sep, (ns->flags & NAMESPACE_FLAG_INBOX) ? "yes" : "no", (ns->flags & NAMESPACE_FLAG_HIDDEN) ? "yes" : "no", - (ns->flags & NAMESPACE_FLAG_LIST) ? "yes" : "no", + list, (ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) ? "yes" : "no"); } @@ -88,6 +93,7 @@ if (ns->type == NAMESPACE_SHARED && strchr(ns->prefix, '%') != NULL) { /* dynamic shared namespace */ + ns->flags |= NAMESPACE_FLAG_INTERNAL; driver = "shared"; } else { driver = NULL; @@ -124,14 +130,15 @@ private_ns_count++; } if (*ns->prefix != '\0' && - (ns->flags & NAMESPACE_FLAG_LIST) != 0 && + (ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0 && ns->prefix[strlen(ns->prefix)-1] != ns->sep) { i_error("namespace configuration error: " "list=yes requires prefix=%s " "to end with separator", ns->prefix); return FALSE; } - if ((ns->flags & NAMESPACE_FLAG_LIST) != 0) { + 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) { @@ -142,7 +149,7 @@ } } if (*ns->prefix == '\0' && - (ns->flags & NAMESPACE_FLAG_LIST) == 0) { + (ns->flags & NAMESPACE_FLAG_LIST_PREFIX) == 0) { i_error("namespace configuration error: " "Empty prefix requires list=yes"); return FALSE; @@ -236,7 +243,7 @@ ns = i_new(struct mail_namespace, 1); ns->type = NAMESPACE_PRIVATE; - ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST | + ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_SUBSCRIPTIONS; ns->prefix = i_strdup(""); ns->user = user; @@ -270,7 +277,7 @@ ns = i_new(struct mail_namespace, 1); ns->user = user; ns->prefix = i_strdup(""); - ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST | + ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_SUBSCRIPTIONS; user->namespaces = ns; return ns; @@ -342,7 +349,7 @@ char mail_namespace_get_root_sep(const struct mail_namespace *namespaces) { - while ((namespaces->flags & NAMESPACE_FLAG_LIST) == 0) + while ((namespaces->flags & NAMESPACE_FLAG_LIST_PREFIX) == 0) namespaces = namespaces->next; return namespaces->sep; }
--- a/src/lib-storage/mail-namespace.h Fri Nov 21 17:03:02 2008 +0200 +++ b/src/lib-storage/mail-namespace.h Fri Nov 21 17:03:27 2008 +0200 @@ -14,8 +14,10 @@ NAMESPACE_FLAG_INBOX = 0x01, /* Namespace is visible only by explicitly using its full prefix */ NAMESPACE_FLAG_HIDDEN = 0x02, - /* Namespace is visible with LIST */ - NAMESPACE_FLAG_LIST = 0x04, + /* Namespace prefix is visible with LIST */ + NAMESPACE_FLAG_LIST_PREFIX = 0x04, + /* Namespace prefix isn't visible with LIST, but child mailboxes are */ + NAMESPACE_FLAG_LIST_CHILDREN = 0x08, /* Namespace uses its own subscriptions. */ NAMESPACE_FLAG_SUBSCRIPTIONS = 0x10,
--- a/src/master/mail-process.c Fri Nov 21 17:03:02 2008 +0200 +++ b/src/master/mail-process.c Fri Nov 21 17:03:27 2008 +0200 @@ -279,8 +279,10 @@ env_put(t_strdup_printf("NAMESPACE_%u_INBOX=1", i)); if (ns->hidden) env_put(t_strdup_printf("NAMESPACE_%u_HIDDEN=1", i)); - if (ns->list) - env_put(t_strdup_printf("NAMESPACE_%u_LIST=1", i)); + if (strcmp(ns->list, "no") != 0) { + env_put(t_strdup_printf("NAMESPACE_%u_LIST=%s", + i, ns->list)); + } if (ns->subscriptions) env_put(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS=1", i));
--- a/src/master/master-settings.c Fri Nov 21 17:03:02 2008 +0200 +++ b/src/master/master-settings.c Fri Nov 21 17:03:27 2008 +0200 @@ -160,7 +160,7 @@ DEF_STR(location), DEF_BOOL(inbox), DEF_BOOL(hidden), - DEF_BOOL(list), + DEF_STR(list), DEF_BOOL(subscriptions), { 0, NULL, 0 } @@ -362,7 +362,7 @@ MEMBER(inbox) FALSE, MEMBER(hidden) FALSE, - MEMBER(list) TRUE, + MEMBER(list) "yes", MEMBER(subscriptions) TRUE }; @@ -502,6 +502,13 @@ name); return FALSE; } + if (strcmp(ns->list, "yes") != 0 && + strcmp(ns->list, "no") != 0 && + strcmp(ns->list, "children") != 0) { + i_error("Namespace '%s': Invalid list value: %s", + name, ns->list); + return FALSE; + } return TRUE; }