/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "ioloop.h"
#include "str.h"
#include "imap-arg.h"
#include "imap-match.h"
#include "imap-utf7.h"
#include "mailbox-tree.h"
#include "mailbox-list-subscriptions.h"
#include "imapc-storage.h"
#include "imapc-list.h"
struct imapc_mailbox_list_iterate_context {
};
static struct {
const char *str;
} imap_list_flags[] = {
{ "\\NoSelect", MAILBOX_NOSELECT },
{ "\\NonExistent", MAILBOX_NONEXISTENT },
{ "\\NoInferiors", MAILBOX_NOINFERIORS },
{ "\\Subscribed", MAILBOX_SUBSCRIBED },
{ "\\All", MAILBOX_SPECIALUSE_ALL },
{ "\\Archive", MAILBOX_SPECIALUSE_ARCHIVE },
{ "\\Drafts", MAILBOX_SPECIALUSE_DRAFTS },
{ "\\Flagged", MAILBOX_SPECIALUSE_FLAGGED },
{ "\\Junk", MAILBOX_SPECIALUSE_JUNK },
{ "\\Sent", MAILBOX_SPECIALUSE_SENT },
{ "\\Trash", MAILBOX_SPECIALUSE_TRASH },
{ "\\Important", MAILBOX_SPECIALUSE_IMPORTANT }
};
extern struct mailbox_list imapc_mailbox_list;
struct imapc_storage_client *client);
struct imapc_storage_client *client);
{
/* separator is set lazily */
}
{
return -1;
return 0;
}
{
/* make sure all pending commands are aborted before anything is
deinitialized */
}
}
static void
enum mail_error default_error,
const struct imapc_command_reply *reply)
{
} else {
}
}
void *context)
{
} else {
}
}
static bool
{
unsigned int i;
for (i = 0; i < N_ELEMENTS(imap_list_flags); i++) {
return TRUE;
}
}
return FALSE;
}
static const char *
{
const char *list_name;
/* typically mailbox_list_escape_name() is used to escape vname into
a list name. but we want to convert remote IMAP name to a list name,
so we need to use the remote IMAP separator. */
/* list_name is now valid, so we can convert it to vname */
}
{
}
static struct mailbox_node *
struct mailbox_tree_context *tree,
{
bool created;
return NULL;
info_flags |= info_flag;
flags++;
}
T_BEGIN {
if ((info_flags & MAILBOX_NONEXISTENT) != 0)
else
} T_END;
return node;
}
struct imapc_storage_client *client)
{
/* we haven't asked for the separator yet.
lets see if this is the reply for its request. */
return;
/* we can't handle NIL separator yet */
} else {
}
}
struct imapc_storage_client *client)
{
/* we haven't asked for the separator yet */
return;
}
else {
/* LSUB \Noselect means that the mailbox isn't
subscribed, but it has children that are */
}
}
}
{
"imapc: LIST didn't return hierarchy separator");
} else if (imapc_list_prefix[0] != '\0' &&
"imapc_list_prefix must not end with hierarchy separator");
}
}
void *context)
{
;
}
}
{
if (list->root_sep_pending)
return;
}
{
return -1;
while (list->root_sep_pending)
return -1;
}
return 0;
}
{
char sep;
/* we can't really return a failure here. just return a common
separator and fail all the future list operations. */
return '/';
}
return sep;
}
static const char *
{
const char *storage_name;
}
return storage_name;
}
static const char *
{
if (*storage_name == '\0') {
/* ACL plugin does these lookups */
if (storage_name[0] == '\0') {
/* we're looking up the prefix itself */
} else {
i_assert(storage_name[0] ==
storage_name++;
}
}
}
{
/* indexes disabled */
i_error("imapc: Couldn't create %s mailbox list: %s",
}
}
return list->index_list;
}
static const char *
{
const char *vname;
return NULL;
/* put back the prefix, so it gets included in the filesystem. */
if (ns->prefix_len > 0) {
/* skip over the namespace prefix */
vname = "";
else {
}
}
if (vname[0] == '\0') {
} else {
}
}
}
static int
{
const char *fs_name;
} else {
return 0;
}
}
static const char *
{
return global ?
} else {
i_panic("imapc: Can't return a temp prefix for '%s'",
}
}
static const char *
{
}
static struct imapc_command *
struct imapc_mailbox_list *list)
{
}
{
return;
if (imapc_list_prefix_len > 0 &&
/* skip over the namespace prefix */
/* skip over the imapc list prefix */
imapc_list_prefix_len) == 0);
if (vname[0] != '\0') {
vname++;
}
/* put back the namespace prefix */
}
}
}
} T_END;
(void)mailbox_list_iter_deinit(&iter);
}
{
const char *pattern;
char sep;
return -1;
if (list->refreshed_mailboxes)
return 0;
pattern = "*";
else {
/* list "prefix*" instead of "prefix.*". this may return a bit
more than we want, but we're also interested in the flags
of the prefix itself. */
}
/* INBOX always exists in IMAP server. since this namespace is
marked with inbox=yes, show the INBOX even if
imapc_list_prefix doesn't match it */
bool created;
/* this listing didn't include the INBOX itself, but
might have included its children. make sure there
aren't any extra flags in it (especially
\NonExistent) */
}
}
}
}
static void
{
const char *name;
i_zero(&update_ctx);
}
}
static struct mailbox_list_iterate_context *
enum mailbox_list_iter_flags flags)
{
const char *ns_root_name;
char ns_sep;
int ret = 0;
if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) == 0 ||
(flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0)
list->iter_count++;
if ((flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0) {
/* we're listing only subscriptions. just use the cached
subscriptions list. */
flags);
if (ret < 0)
return _ctx;
}
/* if we've already failed, make sure we don't call
mailbox_list_get_hierarchy_sep(), since it clears the error */
if (ret == 0)
}
if (ret < 0)
}
static void
struct mailbox_node *node)
{
unsigned int i;
for (i = 0; i < N_ELEMENTS(imap_list_flags); i++) {
}
}
} else {
}
}
static const struct mailbox_info *
{
(struct imapc_mailbox_list_iterate_context *)_ctx;
const char *vname;
return NULL;
return mailbox_list_subscriptions_iter_next(_ctx);
do {
return mailbox_list_iter_default_next(_ctx);
/* don't return "" name */
return imapc_list_iter_next(_ctx);
}
/* we're iterating the INBOX namespace. pass through the
SPECIAL-USE flags if they exist. */
} else {
}
}
{
(struct imapc_mailbox_list_iterate_context *)_ctx;
if (--list->iter_count == 0) {
}
return ret;
}
static int
struct mailbox_list *dest_list)
{
(struct imapc_mailbox_list *)_src_list;
const char *pattern;
return -1;
if (src_list->refreshed_subscriptions) {
return 0;
}
pattern = "*";
else
return -1;
/* replace subscriptions tree in destination */
return 0;
}
{
}
static int
{
return -1;
return -1;
else {
if ((capa & IMAPC_CAPABILITY_UNSELECT) != 0)
else
}
}
}
static int
{
}
return 0;
}
static int
const char *name ATTR_UNUSED)
{
return -1;
}
static int
{
"Can't rename mailboxes across storages.");
return -1;
}
}
}
enum mailbox_info_flags *flags_r)
{
const char *vname;
if (!list->refreshed_mailboxes_recently) {
if (imapc_list_refresh(list) < 0)
return -1;
}
/* imapc list isn't used, but e.g. LAYOUT=none */
*flags_r = 0;
return 0;
}
else
return 0;
}
.v = {
.init = imapc_list_init,
}
};