dovecot: Fixes for listing namespaces with prefixes and real != ...
dovecot at dovecot.org
dovecot at dovecot.org
Sat Oct 20 22:58:58 EEST 2007
details: http://hg.dovecot.org/dovecot/rev/c901bdf0db75
changeset: 6573:c901bdf0db75
user: Timo Sirainen <tss at iki.fi>
date: Sat Oct 20 22:58:54 2007 +0300
description:
Fixes for listing namespaces with prefixes and real != virtual separator.
diffstat:
3 files changed, 101 insertions(+), 63 deletions(-)
src/imap/cmd-list.c | 35 ++++++---
src/lib-storage/list/mailbox-list-fs-iter.c | 49 +++++++------
src/lib-storage/list/mailbox-list-maildir-iter.c | 80 +++++++++++++---------
diffs (truncated from 368 to 300 lines):
diff -r 79836b3474f4 -r c901bdf0db75 src/imap/cmd-list.c
--- a/src/imap/cmd-list.c Sat Oct 20 22:23:14 2007 +0300
+++ b/src/imap/cmd-list.c Sat Oct 20 22:58:54 2007 +0300
@@ -516,6 +516,7 @@ list_namespace_match_pattern(struct cmd_
struct mail_namespace *ns = ctx->ns;
struct imap_match_glob *pat_glob;
enum imap_match_result match;
+ const char *p;
size_t len;
skip_namespace_prefix_pattern(ctx, &cur_ns_prefix,
@@ -547,15 +548,22 @@ list_namespace_match_pattern(struct cmd_
pat_glob = imap_match_init(pool_datastack_create(), orig_cur_pattern,
inboxcase, ns->sep);
match = imap_match(pat_glob, cur_ns_prefix);
- if ((match & (IMAP_MATCH_YES | IMAP_MATCH_CHILDREN)) == 0)
- return FALSE;
-
- if (match == IMAP_MATCH_YES && (ns->flags & NAMESPACE_FLAG_LIST) != 0 &&
- (ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0) {
- /* the namespace prefix itself matches too. send it. */
- ctx->cur_ns_send_prefix = TRUE;
- }
- return TRUE;
+ if (match == IMAP_MATCH_YES) {
+ if ((ns->flags & NAMESPACE_FLAG_LIST) != 0 &&
+ (ctx->list_flags &
+ MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0) {
+ /* the namespace prefix itself matches too. send it. */
+ ctx->cur_ns_send_prefix = TRUE;
+ }
+ /* if the pattern contains '*' characters, we'll need to
+ check our children too */
+ for (p = orig_cur_pattern; *p != '\0'; p++) {
+ if (*p == '*')
+ return TRUE;
+ }
+ }
+
+ return (match & IMAP_MATCH_CHILDREN) != 0;
}
static void list_namespace_init(struct cmd_list_context *ctx)
@@ -598,13 +606,18 @@ static void list_namespace_init(struct c
if (list_namespace_match_pattern(ctx, inboxcase, cur_ref,
cur_ns_prefix, pattern)) {
pattern = mailbox_list_join_refpattern(ns->list,
- ctx->ref, mail_namespace_fix_sep(ns, pattern));
+ ctx->ref, pattern);
array_append(&used_patterns, &pattern, 1);
}
}
- if (array_count(&used_patterns) == 0)
+ if (array_count(&used_patterns) == 0) {
+ /* it's possible that the namespace prefix matched,
+ even though its children didn't */
+ if (ctx->cur_ns_send_prefix)
+ list_namespace_send_prefix(ctx, TRUE);
return;
+ }
(void)array_append_space(&used_patterns); /* NULL-terminate */
pat = array_idx(&used_patterns, 0);
diff -r 79836b3474f4 -r c901bdf0db75 src/lib-storage/list/mailbox-list-fs-iter.c
--- a/src/lib-storage/list/mailbox-list-fs-iter.c Sat Oct 20 22:23:14 2007 +0300
+++ b/src/lib-storage/list/mailbox-list-fs-iter.c Sat Oct 20 22:58:54 2007 +0300
@@ -49,19 +49,20 @@ static const struct mailbox_info *
static const struct mailbox_info *
fs_list_next(struct fs_list_iterate_context *ctx);
-static int pattern_get_path_pos(const char *pattern, const char *path,
- unsigned int *pos_r)
+static int
+pattern_get_path_pos(struct mail_namespace *ns, const char *pattern,
+ const char *path, unsigned int *pos_r)
{
unsigned int i, j;
- if (strncasecmp(path, "INBOX/", 6) == 0) {
+ if (strncasecmp(path, "INBOX", 5) == 0 && path[5] == ns->sep) {
/* make sure INBOX prefix is matched case-insensitively */
char *tmp = t_strdup_noconst(pattern);
- if (strncmp(path, "INBOX/", 6) != 0)
- path = t_strconcat("INBOX/", path + 6, NULL);
-
- for (i = 0; tmp[i] != '/' && tmp[i] != '\0'; i++)
+ if (strncmp(path, "INBOX", 5) != 0)
+ path = t_strdup_printf("INBOX%c%s", ns->sep, path + 6);
+
+ for (i = 0; tmp[i] != ns->sep && tmp[i] != '\0'; i++)
tmp[i] = i_toupper(tmp[i]);
pattern = tmp;
}
@@ -72,13 +73,13 @@ static int pattern_get_path_pos(const ch
if (pattern[j] == '%') {
/* skip until we're at the next hierarchy separator */
- if (path[i] == '/') {
+ if (path[i] == ns->sep) {
/* assume that pattern matches. we can't be
sure, but it'll be checked later. */
for (j++; pattern[j] != '\0'; j++) {
if (pattern[j] == '*')
return -1;
- if (pattern[j] == '/') {
+ if (pattern[j] == ns->sep) {
j++;
break;
}
@@ -96,17 +97,19 @@ static int pattern_get_path_pos(const ch
return 1;
}
-static bool pattern_has_wildcard_at(const char *pattern, const char *path)
+static bool
+pattern_has_wildcard_at(struct mail_namespace *ns, const char *pattern,
+ const char *path)
{
unsigned int pos;
int ret;
- if ((ret = pattern_get_path_pos(pattern, path, &pos)) < 0)
+ if ((ret = pattern_get_path_pos(ns, pattern, path, &pos)) < 0)
return TRUE;
if (ret == 0)
return FALSE;
- for (; pattern[pos] != '\0' && pattern[pos] != '/'; pos++) {
+ for (; pattern[pos] != '\0' && pattern[pos] != ns->sep; pos++) {
if (pattern[pos] == '%' || pattern[pos] == '*')
return TRUE;
}
@@ -125,7 +128,8 @@ static int list_opendir(struct fs_list_i
t_push();
patterns = array_idx(&ctx->valid_patterns, 0);
for (i = 0; patterns[i] != NULL; i++) {
- if (pattern_has_wildcard_at(patterns[i], list_path))
+ if (pattern_has_wildcard_at(ctx->ctx.list->ns,
+ patterns[i], list_path))
break;
}
t_pop();
@@ -190,13 +194,14 @@ fs_list_iter_init(struct mailbox_list *_
return &ctx->ctx;
}
patterns = (const void *)array_idx(&ctx->valid_patterns, 0);
- ctx->glob = imap_match_init_multiple(default_pool, patterns, TRUE, '/');
+ ctx->glob = imap_match_init_multiple(default_pool, patterns, TRUE,
+ _list->ns->sep);
if ((flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
MAILBOX_LIST_ITER_RETURN_SUBSCRIBED)) != 0) {
/* we want to return MAILBOX_SUBSCRIBED flags, possibly for all
mailboxes. Build a mailbox tree of all the subscriptions. */
- ctx->subs_tree = mailbox_tree_init('/');
+ ctx->subs_tree = mailbox_tree_init(_list->ns->sep);
if (mailbox_list_subscriptions_fill(&ctx->ctx,
ctx->subs_tree,
ctx->glob, FALSE) < 0) {
@@ -334,6 +339,7 @@ static int
static int
list_file(struct fs_list_iterate_context *ctx, const struct dirent *d)
{
+ struct mail_namespace *ns = ctx->ctx.list->ns;
const char *fname = d->d_name;
struct list_dir_context *dir;
const char *list_path, *real_path, *vpath, *inbox_path;
@@ -366,7 +372,7 @@ list_file(struct fs_list_iterate_context
/* make sure we give only one correct INBOX */
real_path = t_strconcat(ctx->dir->real_path, "/", fname, NULL);
- if ((ctx->ctx.list->ns->flags & NAMESPACE_FLAG_INBOX) != 0 &&
+ if ((ns->flags & NAMESPACE_FLAG_INBOX) != 0 &&
strcasecmp(list_path, "INBOX") == 0) {
if (ctx->inbox_listed) {
/* already listed the INBOX */
@@ -405,7 +411,7 @@ list_file(struct fs_list_iterate_context
if ((ctx->info.flags & MAILBOX_NOINFERIORS) == 0) {
/* subdirectory. scan inside it. */
- vpath = t_strconcat(list_path, "/", NULL);
+ vpath = t_strdup_printf("%s%c", list_path, ns->sep);
match2 = imap_match(ctx->glob, vpath);
if (match == IMAP_MATCH_YES)
@@ -421,7 +427,8 @@ list_file(struct fs_list_iterate_context
dir = i_new(struct list_dir_context, 1);
dir->dirp = dirp;
dir->real_path = i_strdup(real_path);
- dir->virtual_path = i_strconcat(list_path, "/", NULL);
+ dir->virtual_path =
+ i_strdup_printf("%s%c", list_path, ns->sep);
dir->prev = ctx->dir;
ctx->dir = dir;
@@ -473,6 +480,7 @@ static struct dirent *fs_list_dir_next(s
static struct dirent *fs_list_dir_next(struct fs_list_iterate_context *ctx)
{
struct list_dir_context *dir = ctx->dir;
+ struct mail_namespace *ns = ctx->ctx.list->ns;
char *const *patterns;
const char *fname, *path, *p;
unsigned int pos;
@@ -493,13 +501,14 @@ static struct dirent *fs_list_dir_next(s
patterns += dir->pattern_pos;
dir->pattern_pos++;
- ret = pattern_get_path_pos(*patterns, dir->virtual_path, &pos);
+ ret = pattern_get_path_pos(ns, *patterns, dir->virtual_path,
+ &pos);
if (ret == 0)
continue;
i_assert(ret > 0);
/* get the filename from the pattern */
- p = strchr(*patterns + pos, '/');
+ p = strchr(*patterns + pos, ns->sep);
fname = p == NULL ? *patterns + pos :
t_strdup_until(*patterns + pos, p);
diff -r 79836b3474f4 -r c901bdf0db75 src/lib-storage/list/mailbox-list-maildir-iter.c
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c Sat Oct 20 22:23:14 2007 +0300
+++ b/src/lib-storage/list/mailbox-list-maildir-iter.c Sat Oct 20 22:58:54 2007 +0300
@@ -45,31 +45,39 @@ static void maildir_fill_parents(struct
const char *p;
char hierarchy_sep;
bool created;
-
- hierarchy_sep = ctx->ctx.list->hierarchy_sep;
+ const char *ns_prefix = ctx->ctx.list->ns->prefix;
+ unsigned int ns_prefix_len = strlen(ns_prefix);
+
+ hierarchy_sep = ctx->ctx.list->ns->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);
+ if (imap_match(glob, mailbox_c) != IMAP_MATCH_YES)
+ continue;
+
+ if (*ns_prefix != '\0' &&
+ strncmp(mailbox_c, ns_prefix, ns_prefix_len - 1) == 0) {
+ /* don't return matches to namespace prefix itself */
+ continue;
+ }
+
+ 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();
@@ -79,15 +87,18 @@ maildir_fill_readdir(struct maildir_list
maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
struct imap_match_glob *glob, bool update_only)
{
+ struct mail_namespace *ns = ctx->ctx.list->ns;
DIR *dirp;
struct dirent *d;
- const char *mailbox_name, *mailbox_c;
+ const char *mailbox_name;
+ char *mailbox_c;
string_t *mailbox;
enum mailbox_info_flags flags;
enum imap_match_result match;
struct mailbox_node *node;
bool created;
char prefix_char;
More information about the dovecot-cvs
mailing list