Mercurial > dovecot > original-hg > dovecot-1.2
diff src/lib-storage/list/mailbox-list-maildir-iter.c @ 5829:1d73153584d2 HEAD
Mailbox listing API changed to support more features. Used to implement
support for half of LIST-EXTENDED.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Fri, 29 Jun 2007 03:39:27 +0300 |
parents | 45735dd11f17 |
children | 978722ad6184 |
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c Thu Jun 28 22:34:59 2007 +0300 +++ b/src/lib-storage/list/mailbox-list-maildir-iter.c Fri Jun 29 03:39:27 2007 +0300 @@ -4,14 +4,12 @@ #include "str.h" #include "home-expand.h" #include "imap-match.h" -#include "subscription-file.h" #include "mailbox-tree.h" +#include "mailbox-list-subscriptions.h" #include "mailbox-list-maildir.h" #include <dirent.h> -#define MAILBOX_FLAG_MATCHED 0x40000000 - struct maildir_list_iterate_context { struct mailbox_list_iterate_context ctx; pool_t pool; @@ -24,24 +22,6 @@ struct mailbox_info info; }; -static void maildir_nodes_fix(struct mailbox_node *node, bool is_subs) -{ - while (node != NULL) { - if (node->children != NULL) { - node->flags |= MAILBOX_CHILDREN; - node->flags &= ~MAILBOX_NOCHILDREN; - maildir_nodes_fix(node->children, is_subs); - } else if ((node->flags & MAILBOX_NONEXISTENT) != 0) { - if (!is_subs) { - node->flags &= ~MAILBOX_NONEXISTENT; - node->flags |= MAILBOX_NOSELECT; - } - node->flags |= MAILBOX_CHILDREN; - } - node = node->next; - } -} - static int maildir_fill_readdir(struct maildir_list_iterate_context *ctx, struct imap_match_glob *glob, bool update_only) @@ -107,6 +87,7 @@ continue; if (match == IMAP_MATCH_PARENT) { + /* get the name of the parent mailbox that matches */ t_push(); while ((p = strrchr(mailbox_c, hierarchy_sep)) != NULL) { @@ -119,15 +100,18 @@ created = FALSE; node = update_only ? - mailbox_tree_update(ctx->tree_ctx, mailbox_c) : + mailbox_tree_lookup(ctx->tree_ctx, mailbox_c) : mailbox_tree_get(ctx->tree_ctx, mailbox_c, &created); if (node != NULL) { - if (created) + if (created) { + /* we haven't yet seen this mailbox, + but we might see it later */ node->flags = MAILBOX_NONEXISTENT; - - node->flags |= MAILBOX_CHILDREN | - MAILBOX_FLAG_MATCHED; + } + if (!update_only) + node->flags |= MAILBOX_MATCHED; + node->flags |= MAILBOX_CHILDREN; node->flags &= ~MAILBOX_NOCHILDREN; } @@ -135,21 +119,37 @@ } else { created = FALSE; node = update_only ? - mailbox_tree_update(ctx->tree_ctx, mailbox_c) : + mailbox_tree_lookup(ctx->tree_ctx, mailbox_c) : mailbox_tree_get(ctx->tree_ctx, mailbox_c, &created); if (node != NULL) { if (created) node->flags = MAILBOX_NOCHILDREN; - node->flags &= ~MAILBOX_NONEXISTENT; - node->flags |= MAILBOX_FLAG_MATCHED; + else + 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; + } } } t_pop(); @@ -160,10 +160,12 @@ return -1; } - if ((ctx->ctx.list->ns->flags & NAMESPACE_FLAG_INBOX) != 0 && - (ctx->ctx.flags & MAILBOX_LIST_ITER_SUBSCRIBED) == 0) { + if ((ctx->ctx.list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) { /* make sure INBOX is there */ - node = mailbox_tree_get(ctx->tree_ctx, "INBOX", &created); + created = FALSE; + node = update_only ? + mailbox_tree_lookup(ctx->tree_ctx, "INBOX") : + mailbox_tree_get(ctx->tree_ctx, "INBOX", &created); if (created) node->flags = MAILBOX_NOCHILDREN; else @@ -172,66 +174,16 @@ switch (imap_match(glob, "INBOX")) { case IMAP_MATCH_YES: case IMAP_MATCH_PARENT: - node->flags |= MAILBOX_FLAG_MATCHED; + if (!update_only) + node->flags |= MAILBOX_MATCHED; break; default: break; } } - maildir_nodes_fix(mailbox_tree_get(ctx->tree_ctx, NULL, NULL), - (ctx->ctx.flags & MAILBOX_LIST_ITER_SUBSCRIBED) != 0); return 0; } -static int maildir_fill_subscribed(struct maildir_list_iterate_context *ctx, - struct imap_match_glob *glob) -{ - struct subsfile_list_context *subsfile_ctx; - const char *path, *name, *p; - struct mailbox_node *node; - char hierarchy_sep; - bool created; - - path = t_strconcat(ctx->ctx.list->set.control_dir != NULL ? - ctx->ctx.list->set.control_dir : - ctx->ctx.list->set.root_dir, - "/", ctx->ctx.list->set.subscription_fname, NULL); - subsfile_ctx = subsfile_list_init(ctx->ctx.list, path); - - hierarchy_sep = ctx->ctx.list->hierarchy_sep; - while ((name = subsfile_list_next(subsfile_ctx)) != NULL) { - switch (imap_match(glob, name)) { - case IMAP_MATCH_YES: - node = mailbox_tree_get(ctx->tree_ctx, name, NULL); - node->flags = MAILBOX_FLAG_MATCHED; - if ((ctx->ctx.flags & - MAILBOX_LIST_ITER_FAST_FLAGS) == 0) { - node->flags |= MAILBOX_NONEXISTENT | - MAILBOX_NOCHILDREN; - } - break; - case IMAP_MATCH_PARENT: - /* placeholder */ - while ((p = strrchr(name, hierarchy_sep)) != NULL) { - name = t_strdup_until(name, p); - if (imap_match(glob, name) > 0) - break; - } - i_assert(p != NULL); - - node = mailbox_tree_get(ctx->tree_ctx, name, &created); - if (created) node->flags = MAILBOX_NONEXISTENT; - node->flags |= MAILBOX_FLAG_MATCHED | MAILBOX_CHILDREN; - node->flags &= ~MAILBOX_NOCHILDREN; - break; - default: - break; - } - } - - return subsfile_list_deinit(subsfile_ctx); -} - struct mailbox_list_iterate_context * maildir_list_iter_init(struct mailbox_list *_list, const char *mask, enum mailbox_list_iter_flags flags) @@ -253,13 +205,17 @@ ctx->dir = _list->set.root_dir; ctx->prefix = ""; - if ((flags & MAILBOX_LIST_ITER_SUBSCRIBED) != 0) { - if (maildir_fill_subscribed(ctx, glob) < 0) { + if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) { + /* Listing only subscribed mailboxes. + Flags are set later if needed. */ + if (mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree_ctx, + glob, FALSE) < 0) { ctx->ctx.failed = TRUE; return &ctx->ctx; } } else if ((_list->flags & MAILBOX_LIST_FLAG_FULL_FS_ACCESS) != 0 && (p = strrchr(mask, '/')) != NULL) { + /* Listing non-default maildir */ dir = t_strdup_until(mask, p); ctx->prefix = p_strdup_until(pool, mask, p+1); @@ -268,17 +224,31 @@ ctx->dir = p_strdup(pool, home_expand(dir)); } - if ((flags & MAILBOX_LIST_ITER_SUBSCRIBED) == 0 || - (ctx->ctx.flags & MAILBOX_LIST_ITER_FAST_FLAGS) == 0) { - bool update_only = (flags & MAILBOX_LIST_ITER_SUBSCRIBED) != 0; + if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0 || + (flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) { + /* Add/update mailbox list with flags */ + bool update_only = + (flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0; + if (maildir_fill_readdir(ctx, glob, update_only) < 0) { ctx->ctx.failed = TRUE; return &ctx->ctx; } } + if ((flags & MAILBOX_LIST_ITER_RETURN_SUBSCRIBED) != 0 && + (flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0) { + /* we're listing all mailboxes but we want to know + \Subscribed flags */ + if (mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree_ctx, + glob, TRUE) < 0) { + ctx->ctx.failed = TRUE; + return &ctx->ctx; + } + } + ctx->tree_iter = mailbox_tree_iterate_init(ctx->tree_ctx, NULL, - MAILBOX_FLAG_MATCHED); + MAILBOX_MATCHED); return &ctx->ctx; }