dovecot-2.1: Various fixes to listing mailboxes.
dovecot at dovecot.org
dovecot at dovecot.org
Sun Sep 2 16:06:52 EEST 2012
details: http://hg.dovecot.org/dovecot-2.1/rev/d079d72abb79
changeset: 14694:d079d72abb79
user: Timo Sirainen <tss at iki.fi>
date: Sun Sep 02 16:06:45 2012 +0300
description:
Various fixes to listing mailboxes.
Some of these are a bit kludgy, v2.2 has a larger rewrite of the code to
implement them more nicely.
diffstat:
src/imap/cmd-list.c | 89 +++++++++++++++++++++++-----
src/lib-storage/list/mailbox-list-fs-iter.c | 7 ++
2 files changed, 79 insertions(+), 17 deletions(-)
diffs (209 lines):
diff -r 5625ab0a3eed -r d079d72abb79 src/imap/cmd-list.c
--- a/src/imap/cmd-list.c Fri Aug 31 16:19:21 2012 +0300
+++ b/src/imap/cmd-list.c Sun Sep 02 16:06:45 2012 +0300
@@ -35,6 +35,9 @@
unsigned int used_status:1;
};
+static bool mailbox_list_match_anything(struct cmd_list_context *ctx,
+ struct mail_namespace *ns);
+
static void
mailbox_flags2str(struct cmd_list_context *ctx, string_t *str,
const char *special_use, enum mailbox_info_flags flags)
@@ -207,7 +210,58 @@
return flags;
}
-static bool list_namespace_has_children(struct cmd_list_context *ctx)
+static bool
+ns_prefix_is_visible(struct cmd_list_context *ctx,
+ struct mail_namespace *ns)
+{
+ if ((ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0)
+ return TRUE;
+ if ((ns->flags & NAMESPACE_FLAG_LIST_CHILDREN) != 0) {
+ if (mailbox_list_match_anything(ctx, ns))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool
+ns_prefix_has_visible_child_namespace(struct cmd_list_context *ctx,
+ const char *prefix)
+{
+ struct mail_namespace *ns;
+ unsigned int prefix_len = strlen(prefix);
+
+ for (ns = ctx->ns->user->namespaces; ns != NULL; ns = ns->next) {
+ if (ns->prefix_len > prefix_len &&
+ strncmp(ns->prefix, prefix, prefix_len) == 0 &&
+ ns_prefix_is_visible(ctx, ns))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static bool
+mailbox_ns_prefix_is_shared_inbox(struct mail_namespace *ns)
+{
+ const struct mail_storage_settings *set;
+ struct mail_storage *storage;
+
+ mailbox_list_get_closest_storage(ns->list, &storage);
+ set = mail_storage_get_settings(storage);
+ return ns->type == NAMESPACE_SHARED &&
+ (ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0 &&
+ !set->mail_shared_explicit_inbox;
+}
+
+static bool
+mailbox_is_shared_inbox(struct mail_namespace *ns, const char *vname)
+{
+ return mailbox_ns_prefix_is_shared_inbox(ns) &&
+ strncmp(ns->prefix, vname, ns->prefix_len-1) == 0 &&
+ vname[ns->prefix_len-1] == '\0';
+}
+
+static bool mailbox_list_match_anything(struct cmd_list_context *ctx,
+ struct mail_namespace *ns)
{
enum mailbox_list_iter_flags list_flags =
MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
@@ -215,18 +269,22 @@
const struct mailbox_info *info;
bool ret = FALSE;
- if ((ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0)
- list_flags |= MAILBOX_LIST_ITER_SELECT_SUBSCRIBED;
-
- list_iter = mailbox_list_iter_init(ctx->ns->list,
- t_strconcat(ctx->ns->prefix, "%", NULL), list_flags);
+ list_iter = mailbox_list_iter_init(ns->list,
+ t_strconcat(ns->prefix, "%", NULL), list_flags);
info = mailbox_list_iter_next(list_iter);
+ if (info != NULL && mailbox_ns_prefix_is_shared_inbox(ns) &&
+ mailbox_is_shared_inbox(ns, info->name)) {
+ /* we don't want to see this, try the next one */
+ info = mailbox_list_iter_next(list_iter);
+ }
if (info != NULL)
ret = TRUE;
if (mailbox_list_iter_deinit(&list_iter) < 0) {
/* safer to answer TRUE in error conditions */
ret = TRUE;
}
+ if (!ret && ns_prefix_has_visible_child_namespace(ctx, ns->prefix))
+ ret = TRUE;
return ret;
}
@@ -248,17 +306,14 @@
struct imap_match_glob *glob;
enum imap_match_result match;
const char *ns_prefix, *p;
- bool inboxcase;
unsigned int skip_len;
skip_len = strlen(ctx->ref);
if (strncmp(ctx->ns->prefix, ctx->ref, skip_len) != 0)
skip_len = 0;
- inboxcase = strncasecmp(ctx->ns->prefix, "INBOX", 5) == 0 &&
- ctx->ns->prefix[5] == mail_namespace_get_sep(ctx->ns);
glob = imap_match_init_multiple(pool_datastack_create(),
- ctx->patterns, inboxcase,
+ ctx->patterns, TRUE,
mail_namespace_get_sep(ctx->ns));
ns_prefix = ctx->ns->prefix + skip_len;
match = imap_match(glob, ns_prefix);
@@ -344,7 +399,7 @@
}
if ((flags & MAILBOX_CHILDREN) == 0) {
- if (have_children || list_namespace_has_children(ctx)) {
+ if (have_children || mailbox_list_match_anything(ctx, ctx->ns)) {
flags |= MAILBOX_CHILDREN;
flags &= ~MAILBOX_NOCHILDREN;
} else {
@@ -471,7 +526,7 @@
ctx->inbox_found = TRUE;
}
if (ctx->cur_ns_send_prefix)
- list_namespace_send_prefix(ctx, TRUE);
+ list_namespace_send_prefix(ctx, FALSE);
/* if there's a list=yes namespace with this name, list it as
having children */
@@ -673,10 +728,11 @@
}
static bool
-list_namespace_match_pattern(struct cmd_list_context *ctx, bool inboxcase,
+list_namespace_match_pattern(struct cmd_list_context *ctx,
const char *cur_ref, const char *cur_ns_prefix,
const char *cur_pattern)
{
+ const char *orig_cur_ns_prefix = cur_ns_prefix;
const char *orig_cur_pattern = cur_pattern;
struct mail_namespace *ns = ctx->ns;
struct imap_match_glob *pat_glob;
@@ -698,6 +754,7 @@
}
return TRUE;
}
+ cur_ns_prefix = orig_cur_ns_prefix;
/* namespace prefix still wasn't completely skipped over.
for example cur_ns_prefix=INBOX/, pattern=%/% or pattern=IN%.
@@ -722,7 +779,7 @@
/* check if this namespace prefix matches the current pattern */
pat_glob = imap_match_init(pool_datastack_create(), orig_cur_pattern,
- inboxcase, mail_namespace_get_sep(ns));
+ TRUE, mail_namespace_get_sep(ns));
match = imap_match(pat_glob, cur_ns_prefix);
if (match == IMAP_MATCH_YES) {
if (list_want_send_prefix(ctx, orig_cur_pattern))
@@ -764,7 +821,6 @@
const char *cur_ns_prefix, *cur_ref, *const *pat, *pattern;
enum imap_match_result inbox_match;
ARRAY_DEFINE(used_patterns, const char *);
- bool inboxcase;
cur_ns_prefix = ns->prefix;
cur_ref = ctx->ref;
@@ -782,14 +838,13 @@
inbox_match = list_use_inboxcase(ctx);
ctx->cur_ns_match_inbox = inbox_match == IMAP_MATCH_YES;
- inboxcase = (inbox_match & (IMAP_MATCH_YES | IMAP_MATCH_PARENT)) != 0;
t_array_init(&used_patterns, 16);
for (pat = ctx->patterns; *pat != NULL; pat++) {
pattern = *pat;
/* see if pattern even has a chance of matching the
namespace prefix */
- if (list_namespace_match_pattern(ctx, inboxcase, cur_ref,
+ if (list_namespace_match_pattern(ctx, cur_ref,
cur_ns_prefix, pattern)) {
pattern = mailbox_list_join_refpattern(ns->list,
ctx->ref, pattern);
diff -r 5625ab0a3eed -r d079d72abb79 src/lib-storage/list/mailbox-list-fs-iter.c
--- a/src/lib-storage/list/mailbox-list-fs-iter.c Fri Aug 31 16:19:21 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs-iter.c Sun Sep 02 16:06:45 2012 +0300
@@ -771,6 +771,13 @@
if (ret <= 0)
return NULL;
+ if (_ctx->list->ns->type == NAMESPACE_SHARED &&
+ !_ctx->list->ns->list->mail_set->mail_shared_explicit_inbox &&
+ strlen(ctx->info.name) < _ctx->list->ns->prefix_len) {
+ /* shared/user INBOX, IMAP code already lists it */
+ return fs_list_iter_next(_ctx);
+ }
+
if ((ctx->ctx.flags & MAILBOX_LIST_ITER_RETURN_SUBSCRIBED) != 0) {
mailbox_list_set_subscription_flags(ctx->ctx.list,
ctx->info.name,
More information about the dovecot-cvs
mailing list