dovecot-2.2: Various fixes to listing mailboxes.

dovecot at dovecot.org dovecot at dovecot.org
Wed Sep 26 18:01:29 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/d079d72abb79
changeset: 15122:d079d72abb79
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Sep 02 16:06:45 2012 +0300
description:
Various fixes to listing mailboxes.
Some of these are a bit kludgy, v2.2 has a larger rewrite of the code to
implement them more nicely.

diffstat:

 src/imap/cmd-list.c                         |  89 +++++++++++++++++++++++-----
 src/lib-storage/list/mailbox-list-fs-iter.c |   7 ++
 2 files changed, 79 insertions(+), 17 deletions(-)

diffs (209 lines):

diff -r 5625ab0a3eed -r d079d72abb79 src/imap/cmd-list.c
--- a/src/imap/cmd-list.c	Fri Aug 31 16:19:21 2012 +0300
+++ b/src/imap/cmd-list.c	Sun Sep 02 16:06:45 2012 +0300
@@ -35,6 +35,9 @@
 	unsigned int used_status:1;
 };
 
+static bool mailbox_list_match_anything(struct cmd_list_context *ctx,
+					struct mail_namespace *ns);
+
 static void
 mailbox_flags2str(struct cmd_list_context *ctx, string_t *str,
 		  const char *special_use, enum mailbox_info_flags flags)
@@ -207,7 +210,58 @@
 	return flags;
 }
 
-static bool list_namespace_has_children(struct cmd_list_context *ctx)
+static bool
+ns_prefix_is_visible(struct cmd_list_context *ctx,
+		     struct mail_namespace *ns)
+{
+	if ((ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0)
+		return TRUE;
+	if ((ns->flags & NAMESPACE_FLAG_LIST_CHILDREN) != 0) {
+		if (mailbox_list_match_anything(ctx, ns))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static bool
+ns_prefix_has_visible_child_namespace(struct cmd_list_context *ctx,
+				      const char *prefix)
+{
+	struct mail_namespace *ns;
+	unsigned int prefix_len = strlen(prefix);
+
+	for (ns = ctx->ns->user->namespaces; ns != NULL; ns = ns->next) {
+		if (ns->prefix_len > prefix_len &&
+		    strncmp(ns->prefix, prefix, prefix_len) == 0 &&
+		    ns_prefix_is_visible(ctx, ns))
+			return TRUE;
+	}
+	return FALSE;
+}
+
+static bool
+mailbox_ns_prefix_is_shared_inbox(struct mail_namespace *ns)
+{
+	const struct mail_storage_settings *set;
+	struct mail_storage *storage;
+
+	mailbox_list_get_closest_storage(ns->list, &storage);
+	set = mail_storage_get_settings(storage);
+	return ns->type == NAMESPACE_SHARED &&
+		(ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0 &&
+		!set->mail_shared_explicit_inbox;
+}
+
+static bool
+mailbox_is_shared_inbox(struct mail_namespace *ns, const char *vname)
+{
+	return mailbox_ns_prefix_is_shared_inbox(ns) &&
+		strncmp(ns->prefix, vname, ns->prefix_len-1) == 0 &&
+		vname[ns->prefix_len-1] == '\0';
+}
+
+static bool mailbox_list_match_anything(struct cmd_list_context *ctx,
+					struct mail_namespace *ns)
 {
 	enum mailbox_list_iter_flags list_flags =
 		MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
@@ -215,18 +269,22 @@
 	const struct mailbox_info *info;
 	bool ret = FALSE;
 
-	if ((ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0)
-		list_flags |= MAILBOX_LIST_ITER_SELECT_SUBSCRIBED;
-
-	list_iter = mailbox_list_iter_init(ctx->ns->list,
-		t_strconcat(ctx->ns->prefix, "%", NULL), list_flags);
+	list_iter = mailbox_list_iter_init(ns->list,
+		t_strconcat(ns->prefix, "%", NULL), list_flags);
 	info = mailbox_list_iter_next(list_iter);
+	if (info != NULL && mailbox_ns_prefix_is_shared_inbox(ns) &&
+	    mailbox_is_shared_inbox(ns, info->name)) {
+		/* we don't want to see this, try the next one */
+		info = mailbox_list_iter_next(list_iter);
+	}
 	if (info != NULL)
 		ret = TRUE;
 	if (mailbox_list_iter_deinit(&list_iter) < 0) {
 		/* safer to answer TRUE in error conditions */
 		ret = TRUE;
 	}
+	if (!ret && ns_prefix_has_visible_child_namespace(ctx, ns->prefix))
+		ret = TRUE;
 	return ret;
 }
 
@@ -248,17 +306,14 @@
 	struct imap_match_glob *glob;
 	enum imap_match_result match;
 	const char *ns_prefix, *p;
-	bool inboxcase;
 	unsigned int skip_len;
 
 	skip_len = strlen(ctx->ref);
 	if (strncmp(ctx->ns->prefix, ctx->ref, skip_len) != 0)
 		skip_len = 0;
 
-	inboxcase = strncasecmp(ctx->ns->prefix, "INBOX", 5) == 0 &&
-		ctx->ns->prefix[5] == mail_namespace_get_sep(ctx->ns);
 	glob = imap_match_init_multiple(pool_datastack_create(),
-					ctx->patterns, inboxcase,
+					ctx->patterns, TRUE,
 					mail_namespace_get_sep(ctx->ns));
 	ns_prefix = ctx->ns->prefix + skip_len;
 	match = imap_match(glob, ns_prefix);
@@ -344,7 +399,7 @@
 	}
 
 	if ((flags & MAILBOX_CHILDREN) == 0) {
-		if (have_children || list_namespace_has_children(ctx)) {
+		if (have_children || mailbox_list_match_anything(ctx, ctx->ns)) {
 			flags |= MAILBOX_CHILDREN;
 			flags &= ~MAILBOX_NOCHILDREN;
 		} else {
@@ -471,7 +526,7 @@
 			ctx->inbox_found = TRUE;
 		}
 		if (ctx->cur_ns_send_prefix)
-			list_namespace_send_prefix(ctx, TRUE);
+			list_namespace_send_prefix(ctx, FALSE);
 
 		/* if there's a list=yes namespace with this name, list it as
 		   having children */
@@ -673,10 +728,11 @@
 }
 
 static bool
-list_namespace_match_pattern(struct cmd_list_context *ctx, bool inboxcase,
+list_namespace_match_pattern(struct cmd_list_context *ctx,
 			     const char *cur_ref, const char *cur_ns_prefix,
 			     const char *cur_pattern)
 {
+	const char *orig_cur_ns_prefix = cur_ns_prefix;
 	const char *orig_cur_pattern = cur_pattern;
 	struct mail_namespace *ns = ctx->ns;
 	struct imap_match_glob *pat_glob;
@@ -698,6 +754,7 @@
 		}
 		return TRUE;
 	}
+	cur_ns_prefix = orig_cur_ns_prefix;
 
 	/* namespace prefix still wasn't completely skipped over.
 	   for example cur_ns_prefix=INBOX/, pattern=%/% or pattern=IN%.
@@ -722,7 +779,7 @@
 
 	/* check if this namespace prefix matches the current pattern */
 	pat_glob = imap_match_init(pool_datastack_create(), orig_cur_pattern,
-				   inboxcase, mail_namespace_get_sep(ns));
+				   TRUE, 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))
@@ -764,7 +821,6 @@
 	const char *cur_ns_prefix, *cur_ref, *const *pat, *pattern;
 	enum imap_match_result inbox_match;
 	ARRAY_DEFINE(used_patterns, const char *);
-	bool inboxcase;
 
 	cur_ns_prefix = ns->prefix;
 	cur_ref = ctx->ref;
@@ -782,14 +838,13 @@
 
 	inbox_match = list_use_inboxcase(ctx);
 	ctx->cur_ns_match_inbox = inbox_match == IMAP_MATCH_YES;
-	inboxcase = (inbox_match & (IMAP_MATCH_YES | IMAP_MATCH_PARENT)) != 0;
 
 	t_array_init(&used_patterns, 16);
 	for (pat = ctx->patterns; *pat != NULL; pat++) {
 		pattern = *pat;
 		/* see if pattern even has a chance of matching the
 		   namespace prefix */
-		if (list_namespace_match_pattern(ctx, inboxcase, cur_ref,
+		if (list_namespace_match_pattern(ctx, cur_ref,
 						 cur_ns_prefix, pattern)) {
 			pattern = mailbox_list_join_refpattern(ns->list,
 							ctx->ref, pattern);
diff -r 5625ab0a3eed -r d079d72abb79 src/lib-storage/list/mailbox-list-fs-iter.c
--- a/src/lib-storage/list/mailbox-list-fs-iter.c	Fri Aug 31 16:19:21 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs-iter.c	Sun Sep 02 16:06:45 2012 +0300
@@ -771,6 +771,13 @@
 	if (ret <= 0)
 		return NULL;
 
+	if (_ctx->list->ns->type == NAMESPACE_SHARED &&
+	    !_ctx->list->ns->list->mail_set->mail_shared_explicit_inbox &&
+	    strlen(ctx->info.name) < _ctx->list->ns->prefix_len) {
+		/* shared/user INBOX, IMAP code already lists it */
+		return fs_list_iter_next(_ctx);
+	}
+
 	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_SUBSCRIBED) != 0) {
 		mailbox_list_set_subscription_flags(ctx->ctx.list,
 						    ctx->info.name,


More information about the dovecot-cvs mailing list