dovecot-1.2: Added list=children option for namespaces.

dovecot at dovecot.org dovecot at dovecot.org
Fri Nov 21 17:03:31 EET 2008


details:   http://hg.dovecot.org/dovecot-1.2/rev/659667d89f69
changeset: 8461:659667d89f69
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Nov 21 17:03:27 2008 +0200
description:
Added list=children option for namespaces.

diffstat:

9 files changed, 97 insertions(+), 27 deletions(-)
src/imap/cmd-list.c                           |   26 +++++++++++++---
src/imap/cmd-subscribe.c                      |    3 +
src/lib-storage/index/shared/shared-list.c    |   40 +++++++++++++++++++++++--
src/lib-storage/index/shared/shared-storage.c |    3 +
src/lib-storage/mail-namespace.c              |   27 ++++++++++------
src/lib-storage/mail-namespace.h              |    6 ++-
src/master/mail-process.c                     |    6 ++-
src/master/master-settings.c                  |   11 +++++-
src/master/master-settings.h                  |    2 -

diffs (truncated from 348 to 300 lines):

diff -r 8dfb193bb30c -r 659667d89f69 src/imap/cmd-list.c
--- 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 @@ list_namespace_send_prefix(struct cmd_li
 	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
@@ -255,6 +255,19 @@ list_namespace_send_prefix(struct cmd_li
 		} else {
 			flags |= MAILBOX_NOCHILDREN;
 		}
+	}
+
+	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 ?
@@ -504,8 +517,10 @@ list_want_send_prefix(struct cmd_list_co
 	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 @@ list_namespace_match_pattern(struct cmd_
 	}
 
 	/* 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 @@ static void list_namespace_init(struct c
 			/* 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 */
diff -r 8dfb193bb30c -r 659667d89f69 src/imap/cmd-subscribe.c
--- 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 @@ static bool have_listable_namespace_pref
 	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)
diff -r 8dfb193bb30c -r 659667d89f69 src/lib-storage/index/shared/shared-list.c
--- 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 @@ shared_list_iter_init(struct mailbox_lis
 	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 @@ shared_list_iter_next(struct mailbox_lis
 {
 	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;
 }
 
diff -r 8dfb193bb30c -r 659667d89f69 src/lib-storage/index/shared/shared-storage.c
--- 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 @@ int shared_storage_get_namespace(struct 
 	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 @@ int shared_storage_get_namespace(struct 
 		return -1;
 	}
 	mail_user_add_namespace(user, ns);
+	_storage->ns->flags |= NAMESPACE_FLAG_USABLE;
 
 	*_name = mail_namespace_fix_sep(ns, name);
 	*ns_r = ns;
diff -r 8dfb193bb30c -r 659667d89f69 src/lib-storage/mail-namespace.c
--- 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 @@ namespace_add_env(const char *data, unsi
 		  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 @@ namespace_add_env(const char *data, unsi
 		       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 @@ namespace_add_env(const char *data, unsi
 
 	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 @@ static bool namespaces_check(struct mail
 			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 @@ static bool namespaces_check(struct mail
 			}
 		}
 		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 @@ int mail_namespaces_init(struct mail_use
 
 	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 @@ mail_namespaces_init_empty(struct mail_u
 	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 @@ const char *mail_namespace_get_vname(str
 
 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;
 }
diff -r 8dfb193bb30c -r 659667d89f69 src/lib-storage/mail-namespace.h
--- 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 @@ enum namespace_flags {
 	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,
 
diff -r 8dfb193bb30c -r 659667d89f69 src/master/mail-process.c
--- 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_namespace(struct namespace_setti
 			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",


More information about the dovecot-cvs mailing list