mailbox-list-iter.c revision 402e999a878e0cc41a0afb830fea0a93afc75f0d
/* Copyright (c) 2006-2012 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "imap-match.h"
#include "mail-storage.h"
#include "mailbox-tree.h"
#include "mailbox-list-private.h"
enum autocreate_match_result {
/* list contains the mailbox */
AUTOCREATE_MATCH_RESULT_YES = 0x01,
/* list contains children of the mailbox */
AUTOCREATE_MATCH_RESULT_CHILDREN = 0x02,
/* list contains parents of the mailbox */
};
struct autocreate_box {
const char *name;
const struct mailbox_settings *set;
enum mailbox_info_flags flags;
bool child_listed;
};
unsigned int idx;
struct mailbox_info new_info;
};
struct ns_list_iterate_context {
struct mailbox_list_iterate_context ctx;
struct mailbox_list_iterate_context *backend_ctx;
struct mail_namespace *namespaces;
const char **patterns, **patterns_ns_match;
enum namespace_type type_mask;
struct mail_namespace *iter_namespaces;
struct mailbox_info ns_info;
};
struct mailbox_list_iterate_context *
enum mailbox_list_iter_flags flags)
{
const char *patterns[2];
}
{
/* no subscriptions in this namespace. find where they are. */
/* no subscriptions. avoid crashes by initializing
a subscriptions tree. */
}
return 0;
}
}
}
static struct mailbox_settings *
struct mailbox_settings *in_set)
{
struct mailbox_settings *out_set;
return in_set;
/* namespace prefix itself */
} else {
}
return out_set;
}
static void
{
struct autocreate_box *autobox;
unsigned int i, count;
return;
if (count == 0)
return;
/* build the list of mailboxes we need to consider as existing */
for (i = 0; i < count; i++) {
continue;
/* autocreate mailbox belongs to listed namespace */
}
}
}
struct mailbox_list_iterate_context *
const char *const *patterns,
enum mailbox_list_iter_flags flags)
{
struct mailbox_list_iterate_context *ctx;
int ret = 0;
if ((flags & (MAILBOX_LIST_ITER_SELECT_SUBSCRIBED |
if (ret < 0)
else if ((flags & MAILBOX_LIST_ITER_NO_AUTO_BOXES) == 0)
return ctx;
}
static bool
{
return FALSE;
return FALSE;
}
return TRUE;
}
static bool
{
struct imap_match_glob *glob;
return FALSE;
}
static bool
{
switch (result) {
case IMAP_MATCH_YES:
/* allow matching prefix only when it's done without
wildcards */
return TRUE;
break;
case IMAP_MATCH_CHILDREN: {
/* allow this only if there isn't another namespace
with longer prefix that matches this pattern
(namespaces are sorted by prefix length) */
struct mail_namespace *tmp;
T_BEGIN {
break;
}
} T_END;
return TRUE;
break;
}
case IMAP_MATCH_NO:
case IMAP_MATCH_PARENT:
break;
}
return FALSE;
}
{
struct imap_match_glob *glob;
enum imap_match_result result;
const char *prefix_without_sep;
unsigned int len;
len--;
NAMESPACE_FLAG_LIST_CHILDREN)) == 0) {
/* non-listable namespace matches only with exact prefix */
return FALSE;
}
if (*prefix_without_sep == '\0')
else {
}
} else {
switch (result) {
case IMAP_MATCH_YES:
case IMAP_MATCH_CHILDREN:
return TRUE;
case IMAP_MATCH_NO:
case IMAP_MATCH_PARENT:
break;
}
return FALSE;
}
}
static bool
{
unsigned int i;
return FALSE;
/* filter out namespaces whose prefix doesn't match. this same code
handles both with and without STAR_WITHIN_NS, so the "without" case
is slower than necessary, but this shouldn't matter much */
T_BEGIN {
break;
break;
}
} T_END;
}
static struct mail_namespace *
{
break;
}
return ns;
}
static bool
{
struct imap_match_glob *glob;
enum imap_match_result result;
const char *prefix_without_sep;
NAMESPACE_FLAG_LIST_CHILDREN)) == 0) {
/* non-listable namespace matches only with exact prefix */
return FALSE;
}
return result == IMAP_MATCH_YES &&
}
struct mail_namespace *ns)
{
unsigned int i;
/* INBOX is going to be listed in any case,
don't duplicate it */
return FALSE;
}
T_BEGIN {
ctx->patterns_ns_match[i]);
} T_END;
if (ret)
break;
}
return ret;
}
static const struct mailbox_info *
{
struct ns_list_iterate_context *ctx =
(struct ns_list_iterate_context *)_ctx;
const struct mailbox_info *info;
}
}
/* go to the next namespace */
ctx->backend_ctx =
return mailbox_list_ns_iter_next(_ctx);
}
return info;
}
static int
{
struct ns_list_iterate_context *ctx =
(struct ns_list_iterate_context *)_ctx;
int ret;
}
return ret;
}
static const char **
unsigned int count)
{
const char **dup;
unsigned int i;
for (i = 0; i < count; i++) {
dup[i] = p;
for (; *p != '\0'; p++) {
if (*p == '*')
*p = '%';
}
}
return dup;
}
struct mailbox_list_iterate_context *
const char *const *patterns,
enum namespace_type type_mask,
enum mailbox_list_iter_flags flags)
{
struct ns_list_iterate_context *ctx;
unsigned int i, count;
for (i = 0; i < count; i++)
if ((flags & MAILBOX_LIST_ITER_STAR_WITHIN_NS) != 0) {
/* create copies of patterns with '*' wildcard changed to '%' */
} else {
}
if (namespaces != NULL) {
ctx->backend_ctx =
}
}
static enum autocreate_match_result
bool only_subscribed, unsigned int *idx_r)
{
struct mailbox_settings *const *sets;
enum autocreate_match_result result = 0;
*idx_r = -1U;
for (i = 0; i < count; i++) {
if (only_subscribed &&
continue;
continue;
*idx_r = i;
}
return result;
}
static const struct mailbox_info *
{
struct mailbox_list_autocreate_iterate_context *actx =
unsigned int idx;
if ((match & AUTOCREATE_MATCH_RESULT_YES) != 0) {
/* we have an exact match in the list.
don't list it at the end. */
}
if ((match & AUTOCREATE_MATCH_RESULT_CHILDREN) != 0) {
else {
}
}
/* make sure the mailbox existence flags are correct. */
else {
}
if ((match2 & AUTOCREATE_MATCH_RESULT_YES) != 0)
if ((match2 & AUTOCREATE_MATCH_RESULT_CHILDREN) != 0) {
}
/* we're listing all mailboxes and want \Subscribed flag */
if ((match2 & AUTOCREATE_MATCH_RESULT_YES) != 0) {
/* mailbox is also marked as autosubscribe */
}
if ((match2 & AUTOCREATE_MATCH_RESULT_CHILDREN) != 0) {
/* mailbox also has a children marked as
autosubscribe */
}
}
if ((match & AUTOCREATE_MATCH_RESULT_PARENT) != 0) {
/* there are autocreate parent boxes.
set their children flag states. */
struct autocreate_box *autobox;
unsigned int name_len;
continue;
}
}
return info;
}
const struct autocreate_box *autobox)
{
struct mailbox_list_autocreate_iterate_context *actx =
enum imap_match_result match;
if (match == IMAP_MATCH_YES) {
return TRUE;
}
const char *p;
(old_flags & (MAILBOX_CHILDREN |
if ((old_flags & MAILBOX_NONEXISTENT) == 0) {
}
if ((old_flags & MAILBOX_SUBSCRIBED) != 0)
do {
} while (match != IMAP_MATCH_YES);
return TRUE;
}
return FALSE;
}
static const struct mailbox_info *
{
const struct mailbox_info *info;
const struct mailbox_settings *set;
return NULL;
}
}
return info;
}
static const struct mailbox_info *
{
struct mailbox_list_autocreate_iterate_context *actx =
const struct mailbox_info *info;
unsigned int count;
return autocreate_iter_existing(ctx);
}
}
/* list missing mailboxes */
}
return NULL;
}
static bool
const struct mailbox_info *info)
{
}
const struct mailbox_info *
{
const struct mailbox_info *info;
do {
T_BEGIN {
else
} T_END;
return info;
}
{
}
{
/* If we happened to create any of the parents, we need to mark them
nonexistent. */
}
}
static void
const char *name)
{
struct mailbox_node *node;
enum imap_match_result match;
const char *p;
bool created, add_matched;
add_matched = TRUE;
for (;;) {
if (match == IMAP_MATCH_YES) {
if (created) {
if (create_flags != 0)
}
if ((always_flags & MAILBOX_CHILDREN) != 0)
}
/* We don't want to show the parent mailboxes unless
something else matches them, but if they are matched
we want to show them having child subscriptions */
add_matched = FALSE;
} else {
if ((match & IMAP_MATCH_PARENT) == 0)
break;
/* We've a (possibly) non-subscribed parent mailbox
which has a subscribed child mailbox. Make sure we
return the parent mailbox. */
}
if (!ctx->match_parents)
break;
/* see if parent matches */
if (p == NULL)
break;
}
}
const char *name)
{
T_BEGIN {
} T_END;
}