dovecot: Fixes to handling namespace prefixes and real!=virtual ...

dovecot at dovecot.org dovecot at dovecot.org
Sun Oct 28 01:53:36 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/e1fde9940f7e
changeset: 6639:e1fde9940f7e
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Oct 28 01:53:32 2007 +0300
description:
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.

diffstat:

10 files changed, 220 insertions(+), 188 deletions(-)
src/imap/cmd-list.c                               |    5 
src/lib-storage/list/mailbox-list-fs-iter.c       |   52 +++++-----
src/lib-storage/list/mailbox-list-maildir-iter.c  |   80 ++++++++-------
src/lib-storage/list/mailbox-list-subscriptions.c |  107 ++-------------------
src/lib-storage/mail-namespace.c                  |   18 +++
src/lib-storage/mail-namespace.h                  |    5 
src/lib-storage/mailbox-list-private.h            |    7 +
src/lib-storage/mailbox-list.c                    |   76 ++++++++++++++
src/lib-storage/mailbox-list.h                    |    3 
src/plugins/acl/acl-mailbox-list.c                |   55 +++++-----

diffs (truncated from 787 to 300 lines):

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 @@ bool cmd_list_full(struct client_command
 		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 fs_list_iterate_context {
 	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_cont
 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);
-
-		for (i = 0; tmp[i] != ns->sep && tmp[i] != '\0'; i++)
+			path = t_strdup_printf("INBOX%c%s", ctx->sep, path + 6);
+
+		for (i = 0; tmp[i] != ctx->sep && tmp[i] != '\0'; i++)
 			tmp[i] = i_toupper(tmp[i]);
 		pattern = tmp;
 	}
@@ -73,13 +74,13 @@ pattern_get_path_pos(struct mail_namespa
 
 		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 @@ pattern_get_path_pos(struct mail_namespa
 }
 
 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 @@ static int list_opendir(struct fs_list_i
 	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 @@ fs_list_iter_init(struct mailbox_list *_
 		  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 @@ fs_list_iter_init(struct mailbox_list *_
 	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 @@ fs_list_iter_init(struct mailbox_list *_
 	}
 	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 @@ fs_list_iter_init(struct mailbox_list *_
 		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 @@ list_file(struct fs_list_iterate_context
 
 	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 @@ list_file(struct fs_list_iterate_context
 			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(s
 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 @@ static struct dirent *fs_list_dir_next(s
 		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 node_fix_parents(struct mail
 	}
 }
 
-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);
-
-	hierarchy_sep = ctx->ctx.list->ns->sep;
+	unsigned int prefix_len;
+
+	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 @@ maildir_fill_readdir(struct maildir_list
 	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 @@ maildir_fill_readdir(struct maildir_list
 		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 @@ maildir_fill_readdir(struct maildir_list
 		    (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0')))
 			continue;
 
+		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);
+		}
+
 		/* make sure the pattern matches */
-		str_truncate(mailbox, 0);
-		if ((ns->flags & NAMESPACE_FLAG_INBOX) == 0 ||


More information about the dovecot-cvs mailing list