enum mailbox_info_flags flags;
const char *name;
string_t *str;
-
+
ctx->cur_ns_send_prefix = FALSE;
/* see if we already listed this as a valid mailbox in another
}
}
+ if ((ctx->ns->flags & NAMESPACE_FLAG_LIST_CHILDREN) != 0) {
+ if (have_children) {
+ /* children are going to be listed. */
+ return;
+ }
+ if ((flags & MAILBOX_CHILDREN) == 0) {
+ /* namespace has no children. don't show it. */
+ return;
+ }
+ /* namespace has children but they don't match the list
+ pattern. the prefix itself matches though, so show it. */
+ }
+
name = ctx->cur_ns_skip_trailing_sep ?
t_strndup(ctx->ns->prefix, len-1) : ctx->ns->prefix;
if ((ctx->list_flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0)
return FALSE;
- /* send the prefix if namespace is listable.. */
- if ((ctx->ns->flags & NAMESPACE_FLAG_LIST) != 0)
+ /* send the prefix if namespace is listable. if children are listable
+ we may or may not need to send it. */
+ if ((ctx->ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
+ NAMESPACE_FLAG_LIST_CHILDREN)) != 0)
return TRUE;
/* ..or if pattern is exactly the same as namespace prefix.
}
/* hidden and non-listable namespaces are invisible to wildcards */
- if ((ns->flags & NAMESPACE_FLAG_LIST) == 0 &&
+ if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
+ NAMESPACE_FLAG_LIST_CHILDREN)) == 0 &&
list_pattern_has_wildcards(cur_pattern))
return FALSE;
/* 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);
+ list_namespace_send_prefix(ctx, FALSE);
return;
}
/* we should still list INBOX */
unsigned int name_len = strlen(name);
for (; ns != NULL; ns = ns->next) {
- if ((ns->flags & NAMESPACE_FLAG_LIST) == 0)
+ if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
+ NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
continue;
if (ns->prefix_len <= name_len)
/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
#include "lib.h"
+#include "imap-match.h"
#include "mailbox-list-private.h"
#include "index-storage.h"
#include "shared-storage.h"
struct shared_mailbox_list_iterate_context {
struct mailbox_list_iterate_context ctx;
+ struct mail_namespace *cur_ns;
+ struct imap_match_glob *glob;
+ struct mailbox_info info;
};
extern struct mailbox_list shared_mailbox_list;
ctx = i_new(struct shared_mailbox_list_iterate_context, 1);
ctx->ctx.list = list;
ctx->ctx.flags = flags;
-
- /* FIXME */
+ ctx->cur_ns = list->ns->user->namespaces;
+ ctx->info.ns = list->ns;
+ ctx->info.flags = MAILBOX_NONEXISTENT;
+ ctx->glob = imap_match_init_multiple(default_pool, patterns,
+ FALSE, list->ns->sep);
return &ctx->ctx;
}
{
struct shared_mailbox_list_iterate_context *ctx =
(struct shared_mailbox_list_iterate_context *)_ctx;
+ struct mail_namespace *ns = ctx->cur_ns;
+
+ for (; ns != NULL; ns = ns->next) {
+ if (ns->type != NAMESPACE_SHARED ||
+ (ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0)
+ continue;
+ if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
+ NAMESPACE_FLAG_LIST_CHILDREN)) == 0)
+ continue;
+
+ if (ns->prefix_len < ctx->info.ns->prefix_len ||
+ strncmp(ns->prefix, ctx->info.ns->prefix,
+ ctx->info.ns->prefix_len) != 0)
+ continue;
+
+ /* visible and listable namespace under ourself, see if the
+ prefix matches without the trailing separator */
+ i_assert(ns->prefix_len > 0);
+ ctx->info.name = t_strndup(ns->prefix, ns->prefix_len - 1);
+ if ((_ctx->flags & MAILBOX_LIST_ITER_VIRTUAL_NAMES) == 0)
+ ctx->info.name += ctx->info.ns->prefix_len;
+ if (imap_match(ctx->glob, ctx->info.name) == IMAP_MATCH_YES) {
+ ctx->cur_ns = ns->next;
+ return &ctx->info;
+ }
+ }
+ ctx->cur_ns = NULL;
return NULL;
}
ns->type = NAMESPACE_SHARED;
ns->user = user;
ns->prefix = i_strdup(str_c(prefix));
- ns->flags = NAMESPACE_FLAG_LIST | NAMESPACE_FLAG_HIDDEN |
+ ns->flags = NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
NAMESPACE_FLAG_AUTOCREATED;
ns->sep = _storage->ns->sep;
return -1;
}
mail_user_add_namespace(user, ns);
+ _storage->ns->flags |= NAMESPACE_FLAG_USABLE;
*_name = mail_namespace_fix_sep(ns, name);
*ns_r = ns;
enum file_lock_method lock_method)
{
struct mail_namespace *ns;
- const char *sep, *type, *prefix, *driver, *error;
+ const char *sep, *type, *prefix, *driver, *error, *list;
ns = i_new(struct mail_namespace, 1);
sep = getenv(t_strdup_printf("NAMESPACE_%u_SEP", num));
type = getenv(t_strdup_printf("NAMESPACE_%u_TYPE", num));
prefix = getenv(t_strdup_printf("NAMESPACE_%u_PREFIX", num));
+ list = getenv(t_strdup_printf("NAMESPACE_%u_LIST", num));
if (getenv(t_strdup_printf("NAMESPACE_%u_INBOX", num)) != NULL)
ns->flags |= NAMESPACE_FLAG_INBOX;
if (getenv(t_strdup_printf("NAMESPACE_%u_HIDDEN", num)) != NULL)
ns->flags |= NAMESPACE_FLAG_HIDDEN;
- if (getenv(t_strdup_printf("NAMESPACE_%u_LIST", num)) != NULL)
- ns->flags |= NAMESPACE_FLAG_LIST;
+ if (list != NULL) {
+ if (strcmp(list, "children") == 0)
+ ns->flags |= NAMESPACE_FLAG_LIST_CHILDREN;
+ else
+ ns->flags |= NAMESPACE_FLAG_LIST_PREFIX;
+ }
if (getenv(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS", num)) != NULL)
ns->flags |= NAMESPACE_FLAG_SUBSCRIPTIONS;
type == NULL ? "" : type, prefix, sep == NULL ? "" : sep,
(ns->flags & NAMESPACE_FLAG_INBOX) ? "yes" : "no",
(ns->flags & NAMESPACE_FLAG_HIDDEN) ? "yes" : "no",
- (ns->flags & NAMESPACE_FLAG_LIST) ? "yes" : "no",
+ list,
(ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) ?
"yes" : "no");
}
if (ns->type == NAMESPACE_SHARED && strchr(ns->prefix, '%') != NULL) {
/* dynamic shared namespace */
+ ns->flags |= NAMESPACE_FLAG_INTERNAL;
driver = "shared";
} else {
driver = NULL;
private_ns_count++;
}
if (*ns->prefix != '\0' &&
- (ns->flags & NAMESPACE_FLAG_LIST) != 0 &&
+ (ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0 &&
ns->prefix[strlen(ns->prefix)-1] != ns->sep) {
i_error("namespace configuration error: "
"list=yes requires prefix=%s "
"to end with separator", ns->prefix);
return FALSE;
}
- if ((ns->flags & NAMESPACE_FLAG_LIST) != 0) {
+ if ((ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
+ NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
if (list_sep == '\0')
list_sep = ns->sep;
else if (list_sep != ns->sep) {
}
}
if (*ns->prefix == '\0' &&
- (ns->flags & NAMESPACE_FLAG_LIST) == 0) {
+ (ns->flags & NAMESPACE_FLAG_LIST_PREFIX) == 0) {
i_error("namespace configuration error: "
"Empty prefix requires list=yes");
return FALSE;
ns = i_new(struct mail_namespace, 1);
ns->type = NAMESPACE_PRIVATE;
- ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST |
+ ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST_PREFIX |
NAMESPACE_FLAG_SUBSCRIPTIONS;
ns->prefix = i_strdup("");
ns->user = user;
ns = i_new(struct mail_namespace, 1);
ns->user = user;
ns->prefix = i_strdup("");
- ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST |
+ ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST_PREFIX |
NAMESPACE_FLAG_SUBSCRIPTIONS;
user->namespaces = ns;
return ns;
char mail_namespace_get_root_sep(const struct mail_namespace *namespaces)
{
- while ((namespaces->flags & NAMESPACE_FLAG_LIST) == 0)
+ while ((namespaces->flags & NAMESPACE_FLAG_LIST_PREFIX) == 0)
namespaces = namespaces->next;
return namespaces->sep;
}
NAMESPACE_FLAG_INBOX = 0x01,
/* Namespace is visible only by explicitly using its full prefix */
NAMESPACE_FLAG_HIDDEN = 0x02,
- /* Namespace is visible with LIST */
- NAMESPACE_FLAG_LIST = 0x04,
+ /* Namespace prefix is visible with LIST */
+ NAMESPACE_FLAG_LIST_PREFIX = 0x04,
+ /* Namespace prefix isn't visible with LIST, but child mailboxes are */
+ NAMESPACE_FLAG_LIST_CHILDREN = 0x08,
/* Namespace uses its own subscriptions. */
NAMESPACE_FLAG_SUBSCRIPTIONS = 0x10,
env_put(t_strdup_printf("NAMESPACE_%u_INBOX=1", i));
if (ns->hidden)
env_put(t_strdup_printf("NAMESPACE_%u_HIDDEN=1", i));
- if (ns->list)
- env_put(t_strdup_printf("NAMESPACE_%u_LIST=1", i));
+ if (strcmp(ns->list, "no") != 0) {
+ env_put(t_strdup_printf("NAMESPACE_%u_LIST=%s",
+ i, ns->list));
+ }
if (ns->subscriptions)
env_put(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS=1",
i));
DEF_STR(location),
DEF_BOOL(inbox),
DEF_BOOL(hidden),
- DEF_BOOL(list),
+ DEF_STR(list),
DEF_BOOL(subscriptions),
{ 0, NULL, 0 }
MEMBER(inbox) FALSE,
MEMBER(hidden) FALSE,
- MEMBER(list) TRUE,
+ MEMBER(list) "yes",
MEMBER(subscriptions) TRUE
};
name);
return FALSE;
}
+ if (strcmp(ns->list, "yes") != 0 &&
+ strcmp(ns->list, "no") != 0 &&
+ strcmp(ns->list, "children") != 0) {
+ i_error("Namespace '%s': Invalid list value: %s",
+ name, ns->list);
+ return FALSE;
+ }
return TRUE;
}
bool inbox;
bool hidden;
- bool list;
+ const char *list;
bool subscriptions;
};