changeset 13791:37c2348b67f5

lib-storage: Moved mailbox list iteration functions to a separate file.
author Timo Sirainen <tss@iki.fi>
date Fri, 02 Dec 2011 14:23:47 +0200
parents 6591f7783d55
children b48fb6a08389
files src/lib-storage/Makefile.am src/lib-storage/mailbox-list-iter.c src/lib-storage/mailbox-list.c
diffstat 3 files changed, 399 insertions(+), 398 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/Makefile.am	Fri Dec 02 13:12:16 2011 +0200
+++ b/src/lib-storage/Makefile.am	Fri Dec 02 14:23:47 2011 +0200
@@ -40,6 +40,7 @@
 	mailbox-header.c \
 	mailbox-keywords.c \
 	mailbox-list.c \
+	mailbox-list-iter.c \
 	mailbox-search-result.c \
 	mailbox-tree.c \
 	mailbox-uidvalidity.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-storage/mailbox-list-iter.c	Fri Dec 02 14:23:47 2011 +0200
@@ -0,0 +1,396 @@
+/* Copyright (c) 2006-2011 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "imap-match.h"
+#include "mailbox-tree.h"
+#include "mailbox-list-private.h"
+
+struct ns_list_iterate_context {
+	struct mailbox_list_iterate_context ctx;
+	struct mailbox_list_iterate_context *backend_ctx;
+	struct mail_namespace *namespaces;
+	pool_t pool;
+	const char **patterns, **patterns_ns_match;
+	enum namespace_type type_mask;
+};
+
+struct mailbox_list_iterate_context *
+mailbox_list_iter_init(struct mailbox_list *list, const char *pattern,
+		       enum mailbox_list_iter_flags flags)
+{
+	const char *patterns[2];
+
+	patterns[0] = pattern;
+	patterns[1] = NULL;
+	return mailbox_list_iter_init_multiple(list, patterns, flags);
+}
+
+static int mailbox_list_subscriptions_refresh(struct mailbox_list *list)
+{
+	struct mail_namespace *ns = list->ns;
+
+	if ((ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) == 0) {
+		/* no subscriptions in this namespace. find where they are. */
+		ns = mail_namespace_find_subscribable(ns->user->namespaces,
+						      ns->prefix);
+		if (ns == NULL) {
+			/* no subscriptions */
+			return 0;
+		}
+	}
+	return ns->list->v.subscriptions_refresh(ns->list, list);
+}
+
+struct mailbox_list_iterate_context *
+mailbox_list_iter_init_multiple(struct mailbox_list *list,
+				const char *const *patterns,
+				enum mailbox_list_iter_flags flags)
+{
+	struct mailbox_list_iterate_context *ctx;
+	int ret = 0;
+
+	i_assert(*patterns != NULL);
+
+	if ((flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
+		      MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0)
+		ret = mailbox_list_subscriptions_refresh(list);
+
+	ctx = list->v.iter_init(list, patterns, flags);
+	if (ret < 0)
+		ctx->failed = TRUE;
+	return ctx;
+}
+
+static bool
+ns_match_simple(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
+{
+	if ((ctx->type_mask & ns->type) == 0)
+		return FALSE;
+
+	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SKIP_ALIASES) != 0) {
+		if (ns->alias_for != NULL)
+			return FALSE;
+	}
+	return TRUE;
+}
+
+static bool
+ns_match_inbox(struct mail_namespace *ns, const char *pattern)
+{
+	struct imap_match_glob *glob;
+
+	if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) == 0)
+		return FALSE;
+
+	glob = imap_match_init(pool_datastack_create(), pattern,
+			       TRUE, mail_namespace_get_sep(ns));
+	return imap_match(glob, "INBOX") == IMAP_MATCH_YES;
+}
+
+static bool
+ns_match_next(struct ns_list_iterate_context *ctx, struct mail_namespace *ns,
+	      const char *pattern)
+{
+	struct imap_match_glob *glob;
+	enum imap_match_result result;
+	const char *prefix_without_sep;
+	unsigned int len;
+
+	len = ns->prefix_len;
+	if (len > 0 && ns->prefix[len-1] == mail_namespace_get_sep(ns))
+		len--;
+
+	if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
+			  NAMESPACE_FLAG_LIST_CHILDREN)) == 0) {
+		/* non-listable namespace matches only with exact prefix */
+		if (strncmp(ns->prefix, pattern, ns->prefix_len) != 0)
+			return FALSE;
+	}
+
+	prefix_without_sep = t_strndup(ns->prefix, len);
+	if (*prefix_without_sep == '\0')
+		result = IMAP_MATCH_CHILDREN;
+	else {
+		glob = imap_match_init(pool_datastack_create(), pattern,
+				       TRUE, mail_namespace_get_sep(ns));
+		result = imap_match(glob, prefix_without_sep);
+	}
+
+	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_STAR_WITHIN_NS) == 0) {
+		switch (result) {
+		case IMAP_MATCH_YES:
+		case IMAP_MATCH_CHILDREN:
+			return TRUE;
+		case IMAP_MATCH_NO:
+		case IMAP_MATCH_PARENT:
+			break;
+		}
+		return FALSE;
+	}
+
+	switch (result) {
+	case IMAP_MATCH_YES:
+		/* allow matching prefix only when it's done without
+		   wildcards */
+		if (strcmp(prefix_without_sep, pattern) == 0)
+			return TRUE;
+		break;
+	case IMAP_MATCH_CHILDREN: {
+		/* allow this only if there isn't another namespace
+		   with longer prefix that matches this pattern
+		   (namespaces are sorted by prefix length) */
+		struct mail_namespace *tmp;
+
+		T_BEGIN {
+			for (tmp = ns->next; tmp != NULL; tmp = tmp->next) {
+				if (ns_match_simple(ctx, tmp) &&
+				    ns_match_next(ctx, tmp, pattern))
+					break;
+			}
+		} T_END;
+		if (tmp == NULL)
+			return TRUE;
+		break;
+	}
+	case IMAP_MATCH_NO:
+	case IMAP_MATCH_PARENT:
+		break;
+	}
+	return FALSE;
+}
+
+static bool
+ns_match(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
+{
+	unsigned int i;
+
+	if (!ns_match_simple(ctx, ns))
+		return FALSE;
+
+	/* filter out namespaces whose prefix doesn't match. this same code
+	   handles both with and without STAR_WITHIN_NS, so the "without" case
+	   is slower than necessary, but this shouldn't matter much */
+	T_BEGIN {
+		for (i = 0; ctx->patterns_ns_match[i] != NULL; i++) {
+			if (ns_match_inbox(ns, ctx->patterns_ns_match[i]))
+				break;
+			if (ns_match_next(ctx, ns, ctx->patterns_ns_match[i]))
+				break;
+		}
+	} T_END;
+
+	return ctx->patterns_ns_match[i] != NULL;
+}
+
+static struct mail_namespace *
+ns_next(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
+{
+	for (; ns != NULL; ns = ns->next) {
+		if (ns_match(ctx, ns))
+			break;
+	}
+	return ns;
+}
+
+static const struct mailbox_info *
+mailbox_list_ns_iter_next(struct mailbox_list_iterate_context *_ctx)
+{
+	struct ns_list_iterate_context *ctx =
+		(struct ns_list_iterate_context *)_ctx;
+	const struct mailbox_info *info;
+
+	info = ctx->backend_ctx == NULL ? NULL :
+		mailbox_list_iter_next(ctx->backend_ctx);
+	if (info == NULL && ctx->namespaces != NULL) {
+		/* go to the next namespace */
+		if (mailbox_list_iter_deinit(&ctx->backend_ctx) < 0)
+			_ctx->failed = TRUE;
+		ctx->ctx.list->ns = ctx->namespaces;
+		ctx->backend_ctx =
+			mailbox_list_iter_init_multiple(ctx->namespaces->list,
+							ctx->patterns,
+							_ctx->flags);
+		ctx->namespaces = ns_next(ctx, ctx->namespaces->next);
+		return mailbox_list_ns_iter_next(_ctx);
+	}
+	return info;
+}
+
+static int
+mailbox_list_ns_iter_deinit(struct mailbox_list_iterate_context *_ctx)
+{
+	struct ns_list_iterate_context *ctx =
+		(struct ns_list_iterate_context *)_ctx;
+	int ret;
+
+	if (ctx->backend_ctx != NULL) {
+		if (mailbox_list_iter_deinit(&ctx->backend_ctx) < 0)
+			_ctx->failed = TRUE;
+	}
+	ret = _ctx->failed ? -1 : 0;
+	pool_unref(&ctx->pool);
+	return ret;
+}
+
+static const char **
+dup_patterns_without_stars(pool_t pool, const char *const *patterns,
+			   unsigned int count)
+{
+	const char **dup;
+	unsigned int i;
+
+	dup = p_new(pool, const char *, count + 1);
+	for (i = 0; i < count; i++) {
+		char *p = p_strdup(pool, patterns[i]);
+		dup[i] = p;
+
+		for (; *p != '\0'; p++) {
+			if (*p == '*')
+				*p = '%';
+		}
+	}
+	return dup;
+}
+
+struct mailbox_list_iterate_context *
+mailbox_list_iter_init_namespaces(struct mail_namespace *namespaces,
+				  const char *const *patterns,
+				  enum namespace_type type_mask,
+				  enum mailbox_list_iter_flags flags)
+{
+	struct ns_list_iterate_context *ctx;
+	unsigned int i, count;
+	pool_t pool;
+
+	i_assert(namespaces != NULL);
+
+	pool = pool_alloconly_create("mailbox list namespaces", 1024);
+	ctx = p_new(pool, struct ns_list_iterate_context, 1);
+	ctx->pool = pool;
+	ctx->type_mask = type_mask;
+	ctx->ctx.flags = flags;
+	ctx->ctx.list = p_new(pool, struct mailbox_list, 1);
+	ctx->ctx.list->v.iter_next = mailbox_list_ns_iter_next;
+	ctx->ctx.list->v.iter_deinit = mailbox_list_ns_iter_deinit;
+
+	count = str_array_length(patterns);
+	ctx->patterns = p_new(pool, const char *, count + 1);
+	for (i = 0; i < count; i++)
+		ctx->patterns[i] = p_strdup(pool, patterns[i]);
+
+	if ((flags & MAILBOX_LIST_ITER_STAR_WITHIN_NS) != 0) {
+		/* create copies of patterns with '*' wildcard changed to '%' */
+		ctx->patterns_ns_match =
+			dup_patterns_without_stars(pool, ctx->patterns, count);
+	} else {
+		ctx->patterns_ns_match = ctx->patterns;
+	}
+
+	namespaces = ns_next(ctx, namespaces);
+	ctx->ctx.list->ns = namespaces;
+	if (namespaces != NULL) {
+		ctx->backend_ctx =
+			mailbox_list_iter_init_multiple(namespaces->list,
+							patterns, flags);
+		ctx->namespaces = ns_next(ctx, namespaces->next);
+	}
+	return &ctx->ctx;
+}
+
+const struct mailbox_info *
+mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
+{
+	const struct mailbox_info *info;
+
+	info = ctx->list->v.iter_next(ctx);
+	if (info != NULL)
+		ctx->list->ns->flags |= NAMESPACE_FLAG_USABLE;
+	return info;
+}
+
+int mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
+{
+	struct mailbox_list_iterate_context *ctx = *_ctx;
+
+	*_ctx = NULL;
+
+	return ctx->list->v.iter_deinit(ctx);
+}
+
+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_iter_update_real(struct mailbox_list_iter_update_context *ctx,
+			      const char *name)
+{
+	struct mail_namespace *ns = ctx->iter_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 = MAILBOX_NOCHILDREN;
+	always_flags = ctx->leaf_flags;
+	add_matched = TRUE;
+
+	for (;;) {
+		created = FALSE;
+		match = imap_match(ctx->glob, name);
+		if (match == IMAP_MATCH_YES) {
+			node = ctx->update_only ?
+				mailbox_tree_lookup(ctx->tree_ctx, name) :
+				mailbox_tree_get(ctx->tree_ctx, name, &created);
+			if (created) {
+				node->flags = create_flags;
+				if (create_flags != 0)
+					node_fix_parents(node);
+			}
+			if (node != NULL) {
+				if (!ctx->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->match_parents)
+			break;
+
+		/* see if parent matches */
+		p = strrchr(name, mail_namespace_get_sep(ns));
+		if (p == NULL)
+			break;
+
+		name = t_strdup_until(name, p);
+		create_flags |= MAILBOX_NONEXISTENT;
+		create_flags &= ~MAILBOX_NOCHILDREN;
+		always_flags = MAILBOX_CHILDREN | ctx->parent_flags;
+	}
+}
+
+void mailbox_list_iter_update(struct mailbox_list_iter_update_context *ctx,
+			      const char *name)
+{
+	T_BEGIN {
+		mailbox_list_iter_update_real(ctx, name);
+	} T_END;
+}
--- a/src/lib-storage/mailbox-list.c	Fri Dec 02 13:12:16 2011 +0200
+++ b/src/lib-storage/mailbox-list.c	Fri Dec 02 14:23:47 2011 +0200
@@ -8,19 +8,13 @@
 #include "sha1.h"
 #include "hash.h"
 #include "home-expand.h"
-#include "close-keep-errno.h"
-#include "eacces-error.h"
-#include "read-full.h"
-#include "write-full.h"
-#include "safe-mkstemp.h"
-#include "unlink-directory.h"
 #include "unichar.h"
 #include "settings-parser.h"
-#include "imap-match.h"
 #include "imap-utf7.h"
 #include "mailbox-log.h"
 #include "mailbox-tree.h"
-#include "mail-storage-private.h"
+#include "mail-storage.h"
+#include "mail-storage-hooks.h"
 #include "mailbox-list-private.h"
 
 #include <time.h>
@@ -37,15 +31,6 @@
 #define MAILBOX_MAX_HIERARCHY_LEVELS 20
 #define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200
 
-struct ns_list_iterate_context {
-	struct mailbox_list_iterate_context ctx;
-	struct mailbox_list_iterate_context *backend_ctx;
-	struct mail_namespace *namespaces;
-	pool_t pool;
-	const char **patterns, **patterns_ns_match;
-	enum namespace_type type_mask;
-};
-
 struct mailbox_list_module_register mailbox_list_module_register = { 0 };
 
 static ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);
@@ -971,309 +956,6 @@
 	return pattern;
 }
 
-struct mailbox_list_iterate_context *
-mailbox_list_iter_init(struct mailbox_list *list, const char *pattern,
-		       enum mailbox_list_iter_flags flags)
-{
-	const char *patterns[2];
-
-	patterns[0] = pattern;
-	patterns[1] = NULL;
-	return mailbox_list_iter_init_multiple(list, patterns, flags);
-}
-
-static int mailbox_list_subscriptions_refresh(struct mailbox_list *list)
-{
-	struct mail_namespace *ns = list->ns;
-
-	if ((ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) == 0) {
-		/* no subscriptions in this namespace. find where they are. */
-		ns = mail_namespace_find_subscribable(ns->user->namespaces,
-						      ns->prefix);
-		if (ns == NULL) {
-			/* no subscriptions */
-			return 0;
-		}
-	}
-	return ns->list->v.subscriptions_refresh(ns->list, list);
-}
-
-struct mailbox_list_iterate_context *
-mailbox_list_iter_init_multiple(struct mailbox_list *list,
-				const char *const *patterns,
-				enum mailbox_list_iter_flags flags)
-{
-	struct mailbox_list_iterate_context *ctx;
-	int ret = 0;
-
-	i_assert(*patterns != NULL);
-
-	if ((flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
-		      MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0)
-		ret = mailbox_list_subscriptions_refresh(list);
-
-	ctx = list->v.iter_init(list, patterns, flags);
-	if (ret < 0)
-		ctx->failed = TRUE;
-	return ctx;
-}
-
-static bool
-ns_match_simple(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
-{
-	if ((ctx->type_mask & ns->type) == 0)
-		return FALSE;
-
-	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SKIP_ALIASES) != 0) {
-		if (ns->alias_for != NULL)
-			return FALSE;
-	}
-	return TRUE;
-}
-
-static bool
-ns_match_inbox(struct mail_namespace *ns, const char *pattern)
-{
-	struct imap_match_glob *glob;
-
-	if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) == 0)
-		return FALSE;
-
-	glob = imap_match_init(pool_datastack_create(), pattern,
-			       TRUE, mail_namespace_get_sep(ns));
-	return imap_match(glob, "INBOX") == IMAP_MATCH_YES;
-}
-
-static bool
-ns_match_next(struct ns_list_iterate_context *ctx, struct mail_namespace *ns,
-	      const char *pattern)
-{
-	struct imap_match_glob *glob;
-	enum imap_match_result result;
-	const char *prefix_without_sep;
-	unsigned int len;
-
-	len = ns->prefix_len;
-	if (len > 0 && ns->prefix[len-1] == mail_namespace_get_sep(ns))
-		len--;
-
-	if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
-			  NAMESPACE_FLAG_LIST_CHILDREN)) == 0) {
-		/* non-listable namespace matches only with exact prefix */
-		if (strncmp(ns->prefix, pattern, ns->prefix_len) != 0)
-			return FALSE;
-	}
-
-	prefix_without_sep = t_strndup(ns->prefix, len);
-	if (*prefix_without_sep == '\0')
-		result = IMAP_MATCH_CHILDREN;
-	else {
-		glob = imap_match_init(pool_datastack_create(), pattern,
-				       TRUE, mail_namespace_get_sep(ns));
-		result = imap_match(glob, prefix_without_sep);
-	}
-
-	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_STAR_WITHIN_NS) == 0) {
-		switch (result) {
-		case IMAP_MATCH_YES:
-		case IMAP_MATCH_CHILDREN:
-			return TRUE;
-		case IMAP_MATCH_NO:
-		case IMAP_MATCH_PARENT:
-			break;
-		}
-		return FALSE;
-	}
-
-	switch (result) {
-	case IMAP_MATCH_YES:
-		/* allow matching prefix only when it's done without
-		   wildcards */
-		if (strcmp(prefix_without_sep, pattern) == 0)
-			return TRUE;
-		break;
-	case IMAP_MATCH_CHILDREN: {
-		/* allow this only if there isn't another namespace
-		   with longer prefix that matches this pattern
-		   (namespaces are sorted by prefix length) */
-		struct mail_namespace *tmp;
-
-		T_BEGIN {
-			for (tmp = ns->next; tmp != NULL; tmp = tmp->next) {
-				if (ns_match_simple(ctx, tmp) &&
-				    ns_match_next(ctx, tmp, pattern))
-					break;
-			}
-		} T_END;
-		if (tmp == NULL)
-			return TRUE;
-		break;
-	}
-	case IMAP_MATCH_NO:
-	case IMAP_MATCH_PARENT:
-		break;
-	}
-	return FALSE;
-}
-
-static bool
-ns_match(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
-{
-	unsigned int i;
-
-	if (!ns_match_simple(ctx, ns))
-		return FALSE;
-
-	/* filter out namespaces whose prefix doesn't match. this same code
-	   handles both with and without STAR_WITHIN_NS, so the "without" case
-	   is slower than necessary, but this shouldn't matter much */
-	T_BEGIN {
-		for (i = 0; ctx->patterns_ns_match[i] != NULL; i++) {
-			if (ns_match_inbox(ns, ctx->patterns_ns_match[i]))
-				break;
-			if (ns_match_next(ctx, ns, ctx->patterns_ns_match[i]))
-				break;
-		}
-	} T_END;
-
-	return ctx->patterns_ns_match[i] != NULL;
-}
-
-static struct mail_namespace *
-ns_next(struct ns_list_iterate_context *ctx, struct mail_namespace *ns)
-{
-	for (; ns != NULL; ns = ns->next) {
-		if (ns_match(ctx, ns))
-			break;
-	}
-	return ns;
-}
-
-static const struct mailbox_info *
-mailbox_list_ns_iter_next(struct mailbox_list_iterate_context *_ctx)
-{
-	struct ns_list_iterate_context *ctx =
-		(struct ns_list_iterate_context *)_ctx;
-	const struct mailbox_info *info;
-
-	info = ctx->backend_ctx == NULL ? NULL :
-		mailbox_list_iter_next(ctx->backend_ctx);
-	if (info == NULL && ctx->namespaces != NULL) {
-		/* go to the next namespace */
-		if (mailbox_list_iter_deinit(&ctx->backend_ctx) < 0)
-			_ctx->failed = TRUE;
-		ctx->ctx.list->ns = ctx->namespaces;
-		ctx->backend_ctx =
-			mailbox_list_iter_init_multiple(ctx->namespaces->list,
-							ctx->patterns,
-							_ctx->flags);
-		ctx->namespaces = ns_next(ctx, ctx->namespaces->next);
-		return mailbox_list_ns_iter_next(_ctx);
-	}
-	return info;
-}
-
-static int
-mailbox_list_ns_iter_deinit(struct mailbox_list_iterate_context *_ctx)
-{
-	struct ns_list_iterate_context *ctx =
-		(struct ns_list_iterate_context *)_ctx;
-	int ret;
-
-	if (ctx->backend_ctx != NULL) {
-		if (mailbox_list_iter_deinit(&ctx->backend_ctx) < 0)
-			_ctx->failed = TRUE;
-	}
-	ret = _ctx->failed ? -1 : 0;
-	pool_unref(&ctx->pool);
-	return ret;
-}
-
-static const char **
-dup_patterns_without_stars(pool_t pool, const char *const *patterns,
-			   unsigned int count)
-{
-	const char **dup;
-	unsigned int i;
-
-	dup = p_new(pool, const char *, count + 1);
-	for (i = 0; i < count; i++) {
-		char *p = p_strdup(pool, patterns[i]);
-		dup[i] = p;
-
-		for (; *p != '\0'; p++) {
-			if (*p == '*')
-				*p = '%';
-		}
-	}
-	return dup;
-}
-
-struct mailbox_list_iterate_context *
-mailbox_list_iter_init_namespaces(struct mail_namespace *namespaces,
-				  const char *const *patterns,
-				  enum namespace_type type_mask,
-				  enum mailbox_list_iter_flags flags)
-{
-	struct ns_list_iterate_context *ctx;
-	unsigned int i, count;
-	pool_t pool;
-
-	i_assert(namespaces != NULL);
-
-	pool = pool_alloconly_create("mailbox list namespaces", 1024);
-	ctx = p_new(pool, struct ns_list_iterate_context, 1);
-	ctx->pool = pool;
-	ctx->type_mask = type_mask;
-	ctx->ctx.flags = flags;
-	ctx->ctx.list = p_new(pool, struct mailbox_list, 1);
-	ctx->ctx.list->v.iter_next = mailbox_list_ns_iter_next;
-	ctx->ctx.list->v.iter_deinit = mailbox_list_ns_iter_deinit;
-
-	count = str_array_length(patterns);
-	ctx->patterns = p_new(pool, const char *, count + 1);
-	for (i = 0; i < count; i++)
-		ctx->patterns[i] = p_strdup(pool, patterns[i]);
-
-	if ((flags & MAILBOX_LIST_ITER_STAR_WITHIN_NS) != 0) {
-		/* create copies of patterns with '*' wildcard changed to '%' */
-		ctx->patterns_ns_match =
-			dup_patterns_without_stars(pool, ctx->patterns, count);
-	} else {
-		ctx->patterns_ns_match = ctx->patterns;
-	}
-
-	namespaces = ns_next(ctx, namespaces);
-	ctx->ctx.list->ns = namespaces;
-	if (namespaces != NULL) {
-		ctx->backend_ctx =
-			mailbox_list_iter_init_multiple(namespaces->list,
-							patterns, flags);
-		ctx->namespaces = ns_next(ctx, namespaces->next);
-	}
-	return &ctx->ctx;
-}
-
-const struct mailbox_info *
-mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
-{
-	const struct mailbox_info *info;
-
-	info = ctx->list->v.iter_next(ctx);
-	if (info != NULL)
-		ctx->list->ns->flags |= NAMESPACE_FLAG_USABLE;
-	return info;
-}
-
-int mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
-{
-	struct mailbox_list_iterate_context *ctx = *_ctx;
-
-	*_ctx = NULL;
-
-	return ctx->list->v.iter_deinit(ctx);
-}
-
 int mailbox_has_children(struct mailbox_list *list, const char *name)
 {
 	struct mailbox_list_iterate_context *iter;
@@ -1508,84 +1190,6 @@
 	list->changelog_timestamp = stamp;
 }
 
-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_iter_update_real(struct mailbox_list_iter_update_context *ctx,
-			      const char *name)
-{
-	struct mail_namespace *ns = ctx->iter_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 = MAILBOX_NOCHILDREN;
-	always_flags = ctx->leaf_flags;
-	add_matched = TRUE;
-
-	for (;;) {
-		created = FALSE;
-		match = imap_match(ctx->glob, name);
-		if (match == IMAP_MATCH_YES) {
-			node = ctx->update_only ?
-				mailbox_tree_lookup(ctx->tree_ctx, name) :
-				mailbox_tree_get(ctx->tree_ctx, name, &created);
-			if (created) {
-				node->flags = create_flags;
-				if (create_flags != 0)
-					node_fix_parents(node);
-			}
-			if (node != NULL) {
-				if (!ctx->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->match_parents)
-			break;
-
-		/* see if parent matches */
-		p = strrchr(name, mail_namespace_get_sep(ns));
-		if (p == NULL)
-			break;
-
-		name = t_strdup_until(name, p);
-		create_flags |= MAILBOX_NONEXISTENT;
-		create_flags &= ~MAILBOX_NOCHILDREN;
-		always_flags = MAILBOX_CHILDREN | ctx->parent_flags;
-	}
-}
-
-void mailbox_list_iter_update(struct mailbox_list_iter_update_context *ctx,
-			      const char *name)
-{
-	T_BEGIN {
-		mailbox_list_iter_update_real(ctx, name);
-	} T_END;
-}
-
 bool mailbox_list_name_is_too_large(const char *name, char sep)
 {
 	unsigned int levels = 1, level_len = 0;