Mercurial > dovecot > core-2.2
changeset 22110:786b4dcee7e5
lib-storage: Don't list duplicate autocreated mailboxes' parents
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Mon, 29 May 2017 15:30:36 +0300 |
parents | 7e438ab023c1 |
children | 973a978ed497 |
files | src/lib-storage/list/mailbox-list-iter-private.h src/lib-storage/list/mailbox-list-iter.c |
diffstat | 2 files changed, 32 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-iter-private.h Mon May 29 13:53:17 2017 +0300 +++ b/src/lib-storage/list/mailbox-list-iter-private.h Mon May 29 15:30:36 2017 +0300 @@ -17,6 +17,7 @@ ARRAY(struct autocreate_box) boxes; ARRAY_TYPE(mailbox_settings) box_sets; ARRAY_TYPE(mailbox_settings) all_ns_box_sets; + HASH_TABLE(char *, char *) duplicate_vnames; bool listing_autoboxes:1; };
--- a/src/lib-storage/list/mailbox-list-iter.c Mon May 29 13:53:17 2017 +0300 +++ b/src/lib-storage/list/mailbox-list-iter.c Mon May 29 15:30:36 2017 +0300 @@ -2,6 +2,7 @@ #include "lib.h" #include "array.h" +#include "hash.h" #include "imap-match.h" #include "mail-storage.h" #include "mailbox-tree.h" @@ -114,6 +115,8 @@ actx = p_new(ctx->pool, struct mailbox_list_autocreate_iterate_context, 1); ctx->autocreate_ctx = actx; + hash_table_create(&actx->duplicate_vnames, ctx->pool, 0, + str_hash, strcmp); /* build the list of mailboxes we need to consider as existing */ p_array_init(&actx->boxes, ctx->pool, 16); @@ -817,12 +820,25 @@ match = autocreate_box_match(&actx->box_sets, ctx->list->ns, info->vname, FALSE, &idx); - if (!actx->listing_autoboxes && - (match & AUTOCREATE_MATCH_RESULT_YES) != 0) { - /* we have an exact match in the list. - don't list it at the end. */ - array_delete(&actx->boxes, idx, 1); - array_delete(&actx->box_sets, idx, 1); + if (!actx->listing_autoboxes) { + if ((match & AUTOCREATE_MATCH_RESULT_YES) != 0) { + /* we have an exact match in the list. + don't list it at the end. */ + array_delete(&actx->boxes, idx, 1); + array_delete(&actx->box_sets, idx, 1); + } + if ((match & AUTOCREATE_MATCH_RESULT_CHILDREN) != 0 && + hash_table_lookup(actx->duplicate_vnames, info->vname) == NULL) { + /* Prevent autocreate-iteration from adding this + mailbox as a duplicate. For example we're listing % + and we're here because "foo" was found. However, + there's also "foo/bar" with auto=create. We're + telling here to the autocreate iteration code that + "foo" was already found and it doesn't need to add + it again. */ + char *vname = p_strdup(ctx->pool, info->vname); + hash_table_insert(actx->duplicate_vnames, vname, vname); + } } if ((match & AUTOCREATE_MATCH_RESULT_CHILDREN) != 0) { @@ -918,6 +934,7 @@ enum mailbox_info_flags old_flags = actx->new_info.flags; char sep = mail_namespace_get_sep(ctx->list->ns); const char *p; + char *vname; /* e.g. autocreate=foo/bar and we're listing % */ actx->new_info.flags = MAILBOX_NONEXISTENT | @@ -932,12 +949,16 @@ do { p = strrchr(actx->new_info.vname, sep); i_assert(p != NULL); - actx->new_info.vname = + actx->new_info.vname = vname = p_strdup_until(ctx->pool, actx->new_info.vname, p); match = imap_match(ctx->glob, actx->new_info.vname); } while (match != IMAP_MATCH_YES); - return TRUE; + + if (hash_table_lookup(actx->duplicate_vnames, vname) == NULL) { + hash_table_insert(actx->duplicate_vnames, vname, vname); + return TRUE; + } } return FALSE; } @@ -1030,6 +1051,8 @@ if (ctx == &mailbox_list_iter_failed) return -1; + if (ctx->autocreate_ctx != NULL) + hash_table_destroy(&ctx->autocreate_ctx->duplicate_vnames); return ctx->list->v.iter_deinit(ctx); }