struct mailbox_list_iterate_context *
mailbox_list_subscriptions_iter_init(struct mailbox_list *list,
				     const char *const *patterns,
				     enum mailbox_list_iter_flags flags)
{
	struct subscriptions_mailbox_list_iterate_context *ctx;
	pool_t pool;
	char sep = mail_namespace_get_sep(list->ns);

	pool = pool_alloconly_create("mailbox list subscriptions iter", 1024);
	ctx = p_new(pool, struct subscriptions_mailbox_list_iterate_context, 1);
	ctx->ctx.pool = pool;
	ctx->ctx.list = list;
	ctx->ctx.flags = flags;
	ctx->ctx.glob = imap_match_init_multiple(pool, patterns, TRUE, sep);
	array_create(&ctx->ctx.module_contexts, pool, sizeof(void *), 5);

	ctx->tree = mailbox_tree_init(sep);
	mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree, FALSE);

	ctx->info.ns = list->ns;
	/* the tree usually has only those entries we want to iterate through,
	   but there are also non-matching root entries (e.g. "LSUB foo/%" will
	   include the "foo"), which we'll drop with MAILBOX_MATCHED. */
	ctx->iter = mailbox_tree_iterate_init(ctx->tree, NULL, MAILBOX_MATCHED);
	return &ctx->ctx;
}
struct mailbox_list_iterate_context *
mailbox_list_index_iter_init(struct mailbox_list *list,
			     const char *const *patterns,
			     enum mailbox_list_iter_flags flags)
{
	struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT(list);
	struct mailbox_list_index_iterate_context *ctx;
	pool_t pool;
	char ns_sep = mail_namespace_get_sep(list->ns);

	pool = pool_alloconly_create("mailbox list index iter", 2048);
	ctx = p_new(pool, struct mailbox_list_index_iterate_context, 1);
	ctx->ctx.pool = pool;
	ctx->ctx.list = list;
	ctx->ctx.flags = flags;
	ctx->ctx.glob = imap_match_init_multiple(pool, patterns, TRUE, ns_sep);
	array_create(&ctx->ctx.module_contexts, pool, sizeof(void *), 5);
	ctx->info_pool = pool_alloconly_create("mailbox list index iter info", 128);

	if (!iter_use_index(ctx)) {
		/* no indexing */
		ctx->backend_ctx = ilist->module_ctx.super.
			iter_init(list, patterns, flags);
	} else {
		/* listing mailboxes from index */
		ctx->info.ns = list->ns;
		ctx->path = str_new(pool, 128);
		ctx->next_node = ilist->mailbox_tree;
		ctx->mailbox_pool = ilist->mailbox_pool;
		pool_ref(ctx->mailbox_pool);
	}
	return &ctx->ctx;
}
Beispiel #3
0
struct imap_match_glob *
imap_match_init(pool_t pool, const char *pattern,
		bool inboxcase, char separator)
{
	const char *patterns[2];

	patterns[0] = pattern;
	patterns[1] = NULL;
	return imap_match_init_multiple(pool, patterns, inboxcase, separator);
}
Beispiel #4
0
static struct mailbox_list_iterate_context *
acl_mailbox_list_iter_init(struct mailbox_list *list,
			   const char *const *patterns,
			   enum mailbox_list_iter_flags flags)
{
	struct acl_mailbox_list *alist = ACL_LIST_CONTEXT(list);
	struct acl_mailbox_list_iterate_context *ctx;
	pool_t pool;
	const char *p;
	unsigned int i;
	bool inboxcase;

	pool = pool_alloconly_create("mailbox list acl iter", 1024);
	ctx = p_new(pool, struct acl_mailbox_list_iterate_context, 1);
	ctx->ctx.pool = pool;
	ctx->ctx.list = list;
	ctx->ctx.flags = flags;

	if (list->ns->type != MAIL_NAMESPACE_TYPE_PRIVATE &&
	    (list->ns->flags & NAMESPACE_FLAG_SUBSCRIPTIONS) != 0) {
		/* non-private namespace with subscriptions=yes. this could be
		   a site-global subscriptions file, so hide subscriptions for
		   mailboxes the user doesn't see. */
		ctx->hide_nonlistable_subscriptions = TRUE;
	}

	inboxcase = (list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0;
	ctx->sep = mail_namespace_get_sep(list->ns);
	ctx->ctx.glob = imap_match_init_multiple(pool, patterns,
						 inboxcase, ctx->sep);
	/* see if all patterns have only a single '*' and it's at the end.
	   we can use it to do some optimizations. */
	ctx->simple_star_glob = TRUE;
	for (i = 0; patterns[i] != NULL; i++) {
		p = strchr(patterns[i], '*');
		if (p == NULL || p[1] != '\0') {
			ctx->simple_star_glob = FALSE;
			break;
		}
	}

	/* Try to avoid reading ACLs from all mailboxes by getting a smaller
	   list of mailboxes that have even potential to be visible. If we
	   couldn't get such a list, we'll go through all mailboxes. */
	T_BEGIN {
		acl_mailbox_try_list_fast(ctx);
	} T_END;
	ctx->super_ctx = alist->module_ctx.super.
		iter_init(list, patterns, flags);
	return &ctx->ctx;
}
struct mailbox_list_iterate_context *
maildir_list_iter_init(struct mailbox_list *_list, const char *const *patterns,
		       enum mailbox_list_iter_flags flags)
{
	struct maildir_mailbox_list *list =
		(struct maildir_mailbox_list *)_list;
	struct maildir_list_iterate_context *ctx;
	pool_t pool;
	char ns_sep = mail_namespace_get_sep(_list->ns);
	int ret;

	pool = pool_alloconly_create("mailbox list maildir iter", 1024);
	ctx = p_new(pool, struct maildir_list_iterate_context, 1);
	ctx->ctx.pool = pool;
	ctx->ctx.list = _list;
	ctx->ctx.flags = flags;
	ctx->ctx.glob = imap_match_init_multiple(pool, patterns, TRUE, ns_sep);
	array_create(&ctx->ctx.module_contexts, pool, sizeof(void *), 5);

	ctx->tree_ctx = mailbox_tree_init(ns_sep);
	ctx->info.ns = _list->ns;
	ctx->prefix_char = strcmp(_list->name, MAILBOX_LIST_NAME_IMAPDIR) == 0 ?
		'\0' : list->sep;

	ctx->dir = _list->set.root_dir;

	if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
		/* Listing only subscribed mailboxes.
		   Flags are set later if needed. */
		bool default_nonexistent =
			(flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0;

		mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree_ctx,
						default_nonexistent);
	}

	if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0 ||
	    (flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) {
		/* Add/update mailbox list with flags */
		bool update_only =
			(flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0;

		T_BEGIN {
			ret = maildir_fill_readdir(ctx, ctx->ctx.glob,
						   update_only);
		} T_END;
		if (ret < 0) {
			ctx->ctx.failed = TRUE;
			return &ctx->ctx;
		}
	}