changeset 6010:ed6c07975ccb HEAD

Fixes to returning mailboxes
author Timo Sirainen <tss@iki.fi>
date Sun, 15 Jul 2007 06:46:00 +0300
parents 62f92a68fc72
children 91c229e00772
files src/lib-storage/list/mailbox-list-maildir-iter.c src/lib-storage/list/mailbox-list-subscriptions.c
diffstat 2 files changed, 126 insertions(+), 117 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c	Sun Jul 15 06:45:36 2007 +0300
+++ b/src/lib-storage/list/mailbox-list-maildir-iter.c	Sun Jul 15 06:46:00 2007 +0300
@@ -22,13 +22,66 @@
 	struct mailbox_info info;
 };
 
+static void node_fix_parents(struct mailbox_node *node)
+{
+	/* Fix parent nodes' children states. also 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;
+
+		node->flags |= MAILBOX_CHILDREN;
+		node->flags &= ~MAILBOX_NOCHILDREN;
+	}
+}
+
+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)
+{
+	struct mailbox_node *node;
+	const char *p;
+	char hierarchy_sep;
+	bool created;
+
+	hierarchy_sep = ctx->ctx.list->hierarchy_sep;
+
+	t_push();
+	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) {
+			created = FALSE;
+			node = update_only ?
+				mailbox_tree_lookup(ctx->tree_ctx, mailbox_c) :
+				mailbox_tree_get(ctx->tree_ctx,
+						 mailbox_c, &created);
+			if (node != NULL) {
+				if (created) {
+					/* we haven't yet seen this mailbox,
+					   but we might see it later */
+					node->flags = MAILBOX_NONEXISTENT;
+				}
+				if (!update_only)
+					node->flags |= MAILBOX_MATCHED;
+				node->flags |= MAILBOX_CHILDREN | flags;
+				node->flags &= ~MAILBOX_NOCHILDREN;
+				node_fix_parents(node);
+			}
+		}
+	}
+	t_pop();
+}
+
 static int
 maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
 		     struct imap_match_glob *glob, bool update_only)
 {
 	DIR *dirp;
 	struct dirent *d;
-	const char *p, *mailbox_c;
+	const char *mailbox_c;
 	string_t *mailbox;
 	enum mailbox_info_flags flags;
 	enum imap_match_result match;
@@ -84,37 +137,14 @@
 		if (ret == 0)
 			continue;
 
-		if ((match & IMAP_MATCH_PARENT) != 0) {
-			/* get the name of the parent mailbox that matches */
-			t_push();
-			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)
-					break;
-			}
-			i_assert(p != NULL);
+		/* we know the children flags ourself, so ignore if any of
+		   them were set. */
+		flags &= ~(MAILBOX_NOINFERIORS |
+			   MAILBOX_CHILDREN | MAILBOX_NOCHILDREN);
 
-			created = FALSE;
-			node = update_only ?
-				mailbox_tree_lookup(ctx->tree_ctx, mailbox_c) :
-				mailbox_tree_get(ctx->tree_ctx,
-						 mailbox_c, &created);
-			if (node != NULL) {
-				if (created) {
-					/* we haven't yet seen this mailbox,
-					   but we might see it later */
-					node->flags = MAILBOX_NONEXISTENT;
-				}
-				if (!update_only)
-					node->flags |= MAILBOX_MATCHED;
-				node->flags |= MAILBOX_CHILDREN;
-				node->flags &= ~MAILBOX_NOCHILDREN;
-			}
-
-			t_pop();
+		if ((match & IMAP_MATCH_PARENT) != 0) {
+			maildir_fill_parents(ctx, glob, update_only,
+					     mailbox, mailbox_c, flags);
 		} else {
 			created = FALSE;
 			node = update_only ?
@@ -129,25 +159,8 @@
 					node->flags &= ~MAILBOX_NONEXISTENT;
 				if (!update_only)
 					node->flags |= MAILBOX_MATCHED;
-			}
-		}
-		if (node != NULL) {
-			/* apply flags given by storage. we know the children
-			   flags ourself, so ignore if any of them were set. */
-			node->flags |= flags & ~(MAILBOX_NOINFERIORS |
-						 MAILBOX_CHILDREN |
-						 MAILBOX_NOCHILDREN);
-
-			/* Fix parent nodes' children states. also 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;
-
-				node->flags |= MAILBOX_CHILDREN;
-				node->flags &= ~MAILBOX_NOCHILDREN;
+				node->flags |= flags;
+				node_fix_parents(node);
 			}
 		}
 	}
--- a/src/lib-storage/list/mailbox-list-subscriptions.c	Sun Jul 15 06:45:36 2007 +0300
+++ b/src/lib-storage/list/mailbox-list-subscriptions.c	Sun Jul 15 06:46:00 2007 +0300
@@ -7,15 +7,68 @@
 #include "mailbox-list-private.h"
 #include "mailbox-list-subscriptions.h"
 
-static void nodes_add_child_subscribed(struct mailbox_node *node)
+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_subscription_add(struct mailbox_list_iterate_context *ctx,
+			      struct mailbox_tree_context *tree_ctx,
+			      struct imap_match_glob *glob,
+			      bool update_only, const char *name)
 {
-	while (node != NULL) {
-		if (node->children != NULL) {
-			node->flags |= MAILBOX_MATCHED |
-				MAILBOX_CHILD_SUBSCRIBED;
-		}
-		node = node->next;
+	struct mailbox_node *node;
+	enum mailbox_info_flags create_flags, always_flags;
+	enum imap_match_result match;
+	const char *p;
+	bool created;
+
+	create_flags = (update_only ||
+			(ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) ?
+		(MAILBOX_NONEXISTENT | MAILBOX_NOCHILDREN) : 0;
+	always_flags = MAILBOX_SUBSCRIBED;
+
+	t_push();
+	for (;;) {
+		created = FALSE;
+		match = imap_match(glob, name);
+		if (match == IMAP_MATCH_YES) {
+			node = update_only ?
+				mailbox_tree_lookup(tree_ctx, name) :
+				mailbox_tree_get(tree_ctx, name, &created);
+			if (created) {
+				node->flags = create_flags;
+				if (create_flags != 0)
+					node_fix_parents(node);
+			}
+			if (node != NULL) {
+				if (!update_only)
+					node->flags |= MAILBOX_MATCHED;
+				node->flags |= always_flags;
+			}
+		} else if ((match & IMAP_MATCH_PARENT) == 0)
+			break;
+
+		if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) == 0)
+			break;
+
+		/* see if parent matches */
+		p = strrchr(name, ctx->list->hierarchy_sep);
+		if (p == NULL)
+			break;
+
+		name = t_strdup_until(name, p);
+		create_flags &= ~MAILBOX_NOCHILDREN;
+		always_flags = MAILBOX_CHILDREN | MAILBOX_CHILD_SUBSCRIBED;
 	}
+	t_pop();
 }
 
 int mailbox_list_subscriptions_fill(struct mailbox_list_iterate_context *ctx,
@@ -24,13 +77,7 @@
 				    bool update_only)
 {
 	struct subsfile_list_context *subsfile_ctx;
-	const char *path, *name, *p;
-	struct mailbox_node *node;
-	char hierarchy_sep;
-	bool created, add_flags;
-
-	add_flags = update_only ||
-		(ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0;
+	const char *path, *name;
 
 	path = t_strconcat(ctx->list->set.control_dir != NULL ?
 			   ctx->list->set.control_dir :
@@ -38,61 +85,10 @@
 			   "/", ctx->list->set.subscription_fname, NULL);
 	subsfile_ctx = subsfile_list_init(ctx->list, path);
 
-	hierarchy_sep = ctx->list->hierarchy_sep;
 	while ((name = subsfile_list_next(subsfile_ctx)) != NULL) {
-		created = FALSE;
-		switch (imap_match(glob, name)) {
-		case IMAP_MATCH_YES:
-			node = update_only ?
-				mailbox_tree_lookup(tree_ctx, name) :
-				mailbox_tree_get(tree_ctx, name, &created);
-			if (created && add_flags) {
-				node->flags = MAILBOX_NONEXISTENT |
-					MAILBOX_NOCHILDREN;
-			}
-			if (node != NULL) {
-				if (!update_only)
-					node->flags |= MAILBOX_MATCHED;
-				node->flags |= MAILBOX_SUBSCRIBED;
-			}
-			break;
-		case IMAP_MATCH_PARENT:
-			/* child matched */
-			if ((ctx->flags &
-			     MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) == 0)
-				break;
-
-			while ((p = strrchr(name, hierarchy_sep)) != NULL) {
-				name = t_strdup_until(name, p);
-				if (imap_match(glob, name) == IMAP_MATCH_YES)
-					break;
-			}
-			i_assert(p != NULL);
-
-			node = update_only ?
-				mailbox_tree_lookup(tree_ctx, name) :
-				mailbox_tree_get(tree_ctx, name, &created);
-			if (created && add_flags)
-				node->flags = MAILBOX_NONEXISTENT;
-			if (node != NULL) {
-				if (!update_only)
-					node->flags |= MAILBOX_MATCHED;
-				node->flags |= MAILBOX_CHILDREN |
-					MAILBOX_CHILD_SUBSCRIBED;
-				node->flags &= ~MAILBOX_NOCHILDREN;
-			}
-			break;
-		default:
-			break;
-		}
+		mailbox_list_subscription_add(ctx, tree_ctx, glob, update_only,
+					      name);
 	}
 
-	if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0 &&
-	    (ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) != 0) {
-		struct mailbox_node *nodes =
-			mailbox_tree_get(tree_ctx, NULL, NULL);
-
-		nodes_add_child_subscribed(nodes);
-	}
 	return subsfile_list_deinit(subsfile_ctx);
 }