Mercurial > dovecot > core-2.2
changeset 22709:86939499f531
LAYOUT=fs: Fix listing prefix/INBOX
Removed some confusing special case code that didn't seem to work very well.
Implemented this now properly so that prefix/INBOX is listed as \NoSelect
mailbox whenever it has children.
It's not actually possible to differentiate between INBOX and prefix/INBOX
in the storage for a inbox=yes namespace, because they both are converted
into the same storage_name=INBOX.
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Thu, 14 Dec 2017 01:36:50 +0200 |
parents | fe21125a7ba8 |
children | 3214091454e6 |
files | src/lib-storage/list/mailbox-list-fs-iter.c |
diffstat | 1 files changed, 25 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/list/mailbox-list-fs-iter.c Thu Dec 14 01:34:25 2017 +0200 +++ b/src/lib-storage/list/mailbox-list-fs-iter.c Thu Dec 14 01:36:50 2017 +0200 @@ -51,7 +51,7 @@ unsigned int inbox_found:1; unsigned int inbox_has_children:1; - unsigned int list_inbox_inbox:1; + unsigned int listed_prefix_inbox:1; }; static int @@ -181,6 +181,14 @@ } match = imap_match(ctx->ctx.glob, vname); + if (strcmp(d->d_name, "INBOX") == 0 && strcmp(vname, "INBOX") == 0 && + ctx->ctx.list->ns->prefix_len > 0) { + /* The glob was matched only against "INBOX", but this + directory may hold also prefix/INBOX. Just assume here + that it matches and verify later whether it was needed + or not. */ + match = IMAP_MATCH_YES; + } if ((dir->info_flags & (MAILBOX_CHILDREN | MAILBOX_NOCHILDREN | MAILBOX_NOINFERIORS)) == 0 && @@ -559,11 +567,8 @@ return ret; } -static void inbox_flags_set(struct fs_list_iterate_context *ctx, - enum imap_match_result child_dir_match) +static void inbox_flags_set(struct fs_list_iterate_context *ctx) { - struct mail_namespace *ns = ctx->ctx.list->ns; - /* INBOX is always selectable */ ctx->info.flags &= ~(MAILBOX_NOSELECT | MAILBOX_NONEXISTENT); @@ -571,25 +576,6 @@ ctx->info.flags &= ~(MAILBOX_CHILDREN|MAILBOX_NOCHILDREN); ctx->info.flags |= MAILBOX_NOINFERIORS; } - if (*ns->prefix != '\0' && - (ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) { - /* we're listing INBOX for a namespace with a prefix. - if there are children for the INBOX, they're returned under - the mailbox prefix, not under the INBOX itself. For example - with INBOX = /var/inbox/%u/Maildir, root = ~/Maildir: - ~/Maildir/INBOX/foo/ shows up as <prefix>/INBOX/foo and - INBOX can't directly have any children. */ - if (ns->prefix_len == 6 && - strncasecmp(ns->prefix, "INBOX", ns->prefix_len-1) == 0 && - (ctx->info.flags & MAILBOX_CHILDREN) != 0 && - (child_dir_match & IMAP_MATCH_CHILDREN) != 0) { - /* except, INBOX/ prefix is once again a special case. - we're now listing both the namespace prefix and the - INBOX. we're now doing a LIST INBOX/%, so we'll need - to create a fake \NoSelect INBOX/INBOX */ - ctx->list_inbox_inbox = TRUE; - } - } } static const char * @@ -616,7 +602,7 @@ (ctx->info.flags & MAILBOX_NONEXISTENT) != 0) return FALSE; - inbox_flags_set(ctx, 0); + inbox_flags_set(ctx); if (ctx->inbox_has_children) ctx->info.flags |= MAILBOX_CHILDREN; else { @@ -660,7 +646,14 @@ match = imap_match(ctx->ctx.glob, ctx->info.vname); - child_dir_name = t_strdup_printf("%s%c", ctx->info.vname, ctx->sep); + if (strcmp(ctx->info.vname, "INBOX") == 0 && + ctx->ctx.list->ns->prefix_len > 0) { + /* INBOX's children are matched as prefix/INBOX */ + child_dir_name = t_strdup_printf("%sINBOX", ns->prefix); + } else { + child_dir_name = + t_strdup_printf("%s%c", ctx->info.vname, ctx->sep); + } child_dir_match = imap_match(ctx->ctx.glob, child_dir_name); if (child_dir_match == IMAP_MATCH_YES) child_dir_match |= IMAP_MATCH_CHILDREN; @@ -711,7 +704,9 @@ } return 0; } - inbox_flags_set(ctx, child_dir_match); + if (subdir != NULL) + ctx->inbox_has_children = TRUE; + inbox_flags_set(ctx); ctx->info.vname = "INBOX"; /* always return uppercased */ ctx->inbox_found = TRUE; } else if (strcmp(storage_name, "INBOX") == 0 && @@ -777,12 +772,13 @@ fs_list_next_root(ctx); } - if (ctx->list_inbox_inbox) { + if (ctx->inbox_has_children && ctx->ctx.list->ns->prefix_len > 0 && + !ctx->listed_prefix_inbox) { ctx->info.flags = MAILBOX_CHILDREN | MAILBOX_NOSELECT; ctx->info.vname = p_strconcat(ctx->info_pool, ctx->ctx.list->ns->prefix, "INBOX", NULL); - ctx->list_inbox_inbox = FALSE; + ctx->listed_prefix_inbox = TRUE; if (imap_match(ctx->ctx.glob, ctx->info.vname) == IMAP_MATCH_YES) return 1; }