now shows non-hidden namespaces in the LIST reply.
--HG--
branch : HEAD
if (!client_verify_mailbox_name(client, mailbox, TRUE, FALSE))
return TRUE;
- storage = client_find_storage(client, mailbox);
+ storage = client_find_storage(client, &mailbox);
if (storage == NULL)
return TRUE;
if (search_arg == NULL)
return TRUE;
- storage = client_find_storage(client, mailbox);
+ storage = client_find_storage(client, &mailbox);
if (storage == NULL)
return TRUE;
if (!client_read_string_args(client, 1, &mailbox))
return FALSE;
- storage = client_find_storage(client, mailbox);
+ storage = client_find_storage(client, &mailbox);
if (storage == NULL)
return TRUE;
if (mailbox_close(mailbox) < 0)
client_send_untagged_storage_error(client, storage);
} else {
- storage = client_find_storage(client, name);
+ storage = client_find_storage(client, &name);
if (storage == NULL)
return TRUE;
}
return *str == '\0' ? "" : str+1;
}
-static int mailbox_list(struct client *client, struct mail_storage *storage,
- const char *mask, const char *sep, const char *reply,
- enum mailbox_list_flags list_flags)
-{
- struct mailbox_list_context *ctx;
- struct mailbox_list *list;
- string_t *str;
-
- ctx = mail_storage_mailbox_list_init(storage, mask, list_flags);
- if (ctx == NULL)
- return FALSE;
-
- str = t_str_new(256);
- while ((list = mail_storage_mailbox_list_next(ctx)) != NULL) {
- str_truncate(str, 0);
- str_printfa(str, "* %s (%s) \"%s\" ", reply,
- mailbox_flags2str(list->flags, list_flags),
- sep);
- if (strcasecmp(list->name, "INBOX") == 0)
- str_append(str, "INBOX");
- else
- imap_quote_append_string(str, list->name, FALSE);
- client_send_line(client, str_c(str));
- }
-
- return mail_storage_mailbox_list_deinit(ctx);
-}
-
static int parse_list_flags(struct client *client, struct imap_arg *args,
enum mailbox_list_flags *list_flags)
{
return TRUE;
}
+static int
+list_namespace_mailboxes(struct client *client, struct imap_match_glob *glob,
+ struct namespace *ns, struct mailbox_list_context *ctx,
+ enum mailbox_list_flags list_flags)
+{
+ struct mailbox_list *list;
+ const char *name;
+ string_t *str, *name_str;
+ int inbox_found = FALSE;
+
+ t_push();
+ str = t_str_new(256);
+ name_str = t_str_new(256);
+ while ((list = mail_storage_mailbox_list_next(ctx)) != NULL) {
+ str_truncate(name_str, 0);
+ str_append(name_str, ns->prefix);
+ str_append(name_str, list->name);
+
+ if (ns->sep != ns->real_sep) {
+ char *p = str_c_modifyable(name_str);
+ for (; *p != '\0'; p++) {
+ if (*p == ns->real_sep)
+ *p = ns->sep;
+ }
+ }
+ name = str_c(name_str);
+
+ if (*ns->prefix != '\0') {
+ /* With masks containing '*' we do the checks here
+ so prefix is included in matching */
+ if (glob != NULL &&
+ imap_match(glob, name) != IMAP_MATCH_YES)
+ continue;
+ } else if (strcasecmp(list->name, "INBOX") == 0) {
+ if (!ns->inbox)
+ continue;
+
+ name = "INBOX";
+ inbox_found = TRUE;
+ }
+
+ str_truncate(str, 0);
+ str_printfa(str, "* LIST (%s) \"%s\" ",
+ mailbox_flags2str(list->flags, list_flags),
+ ns->sep_str);
+ imap_quote_append_string(str, name, FALSE);
+ client_send_line(client, str_c(str));
+ }
+ t_pop();
+
+ if (!inbox_found && ns->inbox) {
+ /* INBOX always exists */
+ str_printfa(str, "* LIST () \"%s\" \"INBOX\"", ns->sep_str);
+ client_send_line(client, str_c(str));
+ }
+
+ return mail_storage_mailbox_list_deinit(ctx);
+}
+
+static void skip_prefix(const char **prefix, const char **mask, int inbox)
+{
+ size_t mask_len, prefix_len, len;
+
+ prefix_len = strlen(*prefix);
+ mask_len = strlen(*mask);
+ len = I_MIN(prefix_len, mask_len);
+
+ if (strncmp(*prefix, *mask, len) == 0 ||
+ (inbox && len >= 6 &&
+ strncasecmp(*prefix, *mask, 6) == 0)) {
+ *prefix += len;
+ *mask += len;
+ }
+}
+
+static int list_mailboxes(struct client *client,
+ const char *ref, const char *mask,
+ enum mailbox_list_flags list_flags)
+{
+ struct namespace *ns;
+ struct mailbox_list_context *ctx;
+ struct imap_match_glob *glob;
+ enum imap_match_result match;
+ const char *cur_prefix, *cur_ref, *cur_mask;
+ size_t len;
+ int inbox;
+
+ inbox = strncasecmp(ref, "INBOX", 5) == 0 ||
+ (*ref == '\0' && strncasecmp(mask, "INBOX", 5) == 0);
+
+ for (ns = client->namespaces; ns != NULL; ns = ns->next) {
+ t_push();
+ cur_prefix = ns->prefix;
+ cur_ref = ref;
+ cur_mask = mask;
+ if (*ref != '\0') {
+ skip_prefix(&cur_prefix, &cur_ref, inbox);
+
+ if (*cur_ref != '\0' && *cur_prefix != '\0') {
+ /* reference parameter didn't match with
+ namespace prefix. skip this. */
+ t_pop();
+ continue;
+ }
+ }
+
+ if (*cur_ref == '\0' && *cur_prefix != '\0') {
+ skip_prefix(&cur_prefix, &cur_mask,
+ inbox && cur_ref == ref);
+ }
+
+ glob = imap_match_init(pool_datastack_create(), mask,
+ inbox && cur_ref == ref, ns->sep);
+
+ if (*cur_ref != '\0' || *cur_prefix == '\0')
+ match = IMAP_MATCH_CHILDREN;
+ else {
+ len = strlen(cur_prefix);
+ if (cur_prefix[len-1] == ns->sep)
+ cur_prefix = t_strndup(cur_prefix, len-1);
+ match = ns->hidden ? IMAP_MATCH_NO :
+ imap_match(glob, cur_prefix);
+
+ if (match == IMAP_MATCH_YES) {
+ /* The prefix itself matches */
+ string_t *str = t_str_new(128);
+ str_printfa(str, "* LIST (%s) \"%s\" ",
+ mailbox_flags2str(MAILBOX_PLACEHOLDER,
+ list_flags),
+ ns->sep_str);
+ len = strlen(ns->prefix);
+ imap_quote_append_string(str,
+ t_strndup(ns->prefix, len-1), FALSE);
+ client_send_line(client, str_c(str));
+ }
+ }
+
+ if (match >= 0) {
+ unsigned int count = 0;
+ if (*cur_prefix != '\0') {
+ /* we'll have to fix mask */
+ for (; *cur_prefix != '\0'; cur_prefix++) {
+ if (*cur_prefix == ns->sep)
+ count++;
+ }
+ if (count == 0)
+ count = 1;
+
+ while (count > 0) {
+ if (*cur_ref != '\0') {
+ while (*cur_ref != '\0' &&
+ *cur_ref++ != ns->sep)
+ ;
+ } else {
+ while (*cur_mask != '\0' &&
+ *cur_mask != '*' &&
+ *cur_mask != ns->sep)
+ cur_mask++;
+ if (*cur_mask == '*') {
+ cur_mask = "*";
+ break;
+ }
+ if (*cur_mask == '\0')
+ break;
+ cur_mask++;
+ }
+ count--;
+ }
+ }
+
+ if (*cur_mask != '*' || strcmp(mask, "*") == 0)
+ glob = NULL;
+
+ cur_ref = namespace_fix_sep(ns, cur_ref);
+ cur_mask = namespace_fix_sep(ns, cur_mask);
+
+ ctx = mail_storage_mailbox_list_init(ns->storage,
+ cur_ref, cur_mask,
+ list_flags);
+ if (list_namespace_mailboxes(client, glob, ns, ctx,
+ list_flags) < 0) {
+ client_send_storage_error(client, ns->storage);
+ t_pop();
+ return -1;
+ }
+ }
+ t_pop();
+ }
+
+ return 0;
+}
+
int _cmd_list_full(struct client *client, int lsub)
{
struct namespace *ns;
- struct mail_storage *storage;
struct imap_arg *args;
enum mailbox_list_flags list_flags;
const char *ref, *mask;
- char sep_chr, sep[3];
- int failed;
/* [(<options>)] <reference> <mailbox wildcards> */
if (!client_read_args(client, 0, 0, &args))
return TRUE;
}
- /* FIXME: really needs some work.. */
- ns = namespace_find(client->namespaces, *ref != '\0' ? ref : mask);
- if (ns != NULL)
- storage = ns->storage;
- else
- storage = client->namespaces->storage;
-
- sep_chr = mail_storage_get_hierarchy_sep(storage);
- if (sep_chr == '"' || sep_chr == '\\') {
- sep[0] = '\\';
- sep[1] = sep_chr;
- sep[2] = '\0';
- } else {
- sep[0] = sep_chr;
- sep[1] = '\0';
- }
-
if (*mask == '\0' && !lsub) {
/* special request to return the hierarchy delimiter */
- client_send_line(client, t_strconcat(
- "* LIST (\\Noselect) \"", sep, "\" \"\"", NULL));
- failed = FALSE;
- } else {
- if (*ref != '\0') {
- /* join reference + mask */
- if (*mask == sep_chr &&
- ref[strlen(ref)-1] == sep_chr) {
- /* LIST A. .B -> A.B */
- mask++;
- }
- if (*mask != sep_chr &&
- ref[strlen(ref)-1] != sep_chr) {
- /* LIST A B -> A.B */
- mask = t_strconcat(ref, sep, mask, NULL);
- } else {
- mask = t_strconcat(ref, mask, NULL);
- }
+ ns = namespace_find(client->namespaces, &ref);
+ if (ns == NULL) {
+ const char *empty = "";
+ ns = namespace_find(client->namespaces, &empty);
}
- failed = mailbox_list(client, storage, mask, sep,
- lsub ? "LSUB" : "LIST", list_flags) < 0;
+ if (ns != NULL) {
+ client_send_line(client, t_strconcat(
+ "* LIST (\\Noselect) \"", ns->sep_str,
+ "\" \"\"", NULL));
+ }
+ } else {
+ if (list_mailboxes(client, ref, mask, list_flags) < 0)
+ return TRUE;
}
- if (failed)
- client_send_storage_error(client, storage);
- else {
- client_send_tagline(client, lsub ?
- "OK Lsub completed." :
- "OK List completed.");
- }
+ client_send_tagline(client, !lsub ?
+ "OK List completed." :
+ "OK Lsub completed.");
return TRUE;
}
str_append_c(str, '(');
imap_quote_append_string(str, ns->prefix, FALSE);
str_append(str, " \"");
- if (ns->hierarchy_sep == '"' ||
- ns->hierarchy_sep == '\\')
- str_append_c(str, '\\');
- str_append_c(str, ns->hierarchy_sep);
+ str_append(str, ns->sep_str);
str_append(str, "\")");
}
if (!client_verify_mailbox_name(client, newname, FALSE, TRUE))
return TRUE;
- old_storage = client_find_storage(client, oldname);
+ old_storage = client_find_storage(client, &oldname);
if (old_storage == NULL)
return TRUE;
- new_storage = client_find_storage(client, newname);
+ new_storage = client_find_storage(client, &newname);
if (new_storage == NULL)
return TRUE;
}
}
- storage = client_find_storage(client, mailbox);
+ storage = client_find_storage(client, &mailbox);
if (storage == NULL)
return TRUE;
return TRUE;
}
- storage = client_find_storage(client, mailbox);
+ storage = client_find_storage(client, &mailbox);
if (storage == NULL)
return FALSE;
if (!client_verify_mailbox_name(client, mailbox, subscribe, FALSE))
return TRUE;
- storage = client_find_storage(client, mailbox);
+ storage = client_find_storage(client, &mailbox);
if (storage == NULL)
return TRUE;
#define MAILBOX_MAX_NAME_LEN 512
struct mail_storage *
-client_find_storage(struct client *client, const char *mailbox)
+client_find_storage(struct client *client, const char **mailbox)
{
struct namespace *ns;
const char *p;
char sep;
- storage = client_find_storage(client, mailbox);
+ storage = client_find_storage(client, &mailbox);
if (storage == NULL)
return FALSE;
/* Finds mail storage for given mailbox from namespaces. If not found,
sends "Unknown namespace" error message to client. */
struct mail_storage *
-client_find_storage(struct client *client, const char *mailbox);
+client_find_storage(struct client *client, const char **mailbox);
/* If should_exist is TRUE, this function returns TRUE if the mailbox
exists. If it doesn't exist but would be a valid mailbox name, the
#include <stdlib.h>
+static void namespace_init_storage(struct namespace *ns)
+{
+ ns->prefix_len = strlen(ns->prefix);
+ ns->real_sep = mail_storage_get_hierarchy_sep(ns->storage);
+
+ if (ns->sep == '\0')
+ ns->sep = ns->real_sep;
+
+ if (ns->sep == '"' || ns->sep == '\\') {
+ ns->sep_str[0] = '\\';
+ ns->sep_str[1] = ns->sep;
+ } else {
+ ns->sep_str[0] = ns->sep;
+ }
+
+ if (hook_mail_storage_created != NULL)
+ hook_mail_storage_created(&ns->storage);
+}
+
static struct namespace *
namespace_add_env(pool_t pool, const char *data, unsigned int num,
const char *user)
{
struct namespace *ns;
const char *sep, *type, *prefix;
- int inbox, hidden;
+ int inbox, hidden, subscriptions;
ns = p_new(pool, struct namespace, 1);
prefix = getenv(t_strdup_printf("NAMESPACE_%u_PREFIX", num));
inbox = getenv(t_strdup_printf("NAMESPACE_%u_INBOX", num)) != NULL;
hidden = getenv(t_strdup_printf("NAMESPACE_%u_HIDDEN", num)) != NULL;
+ subscriptions = getenv(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS",
+ num)) != NULL;
if (type == NULL || *type == '\0' || strncmp(type, "private", 7) == 0)
ns->type = NAMESPACE_PRIVATE;
ns->prefix = p_strdup(pool, prefix);
ns->inbox = inbox;
ns->hidden = hidden;
- ns->storage = mail_storage_create_with_data(data, user, ns->prefix,
- sep != NULL ? *sep : '\0');
+ ns->subscriptions = subscriptions;
+ ns->storage = mail_storage_create_with_data(data, user);
if (ns->storage == NULL) {
i_fatal("Failed to create storage for '%s' with data: %s",
ns->prefix, data);
}
- if (hook_mail_storage_created != NULL)
- hook_mail_storage_created(&ns->storage);
-
- ns->hierarchy_sep = mail_storage_get_hierarchy_sep(ns->storage);
+ if (sep != NULL)
+ ns->sep = *sep;
+ namespace_init_storage(ns);
return ns;
}
}
ns = p_new(pool, struct namespace, 1);
- ns->storage = mail_storage_create_with_data(mail, user, NULL, '\0');
+ ns->storage = mail_storage_create_with_data(mail, user);
if (ns->storage == NULL) {
if (mail != NULL && *mail != '\0')
i_fatal("Failed to create storage with data: %s", mail);
ns->type = NAMESPACE_PRIVATE;
ns->inbox = TRUE;
- ns->prefix = p_strdup(pool, "");
- ns->hierarchy_sep = mail_storage_get_hierarchy_sep(ns->storage);
- if (hook_mail_storage_created != NULL)
- hook_mail_storage_created(&ns->storage);
-
+ ns->subscriptions = TRUE;
+ ns->prefix = "";
+ namespace_init_storage(ns);
return ns;
}
}
}
+const char *namespace_fix_sep(struct namespace *ns, const char *name)
+{
+ char *ret, *p;
+
+ if (ns->sep == ns->real_sep)
+ return name;
+
+ ret = p_strdup(unsafe_data_stack_pool, name);
+ for (p = ret; *p != '\0'; p++) {
+ if (*p == ns->sep)
+ *p = ns->real_sep;
+ }
+ return ret;
+}
+
struct namespace *
-namespace_find(struct namespace *namespaces, const char *mailbox)
+namespace_find(struct namespace *namespaces, const char **mailbox)
{
+ struct namespace *ns = namespaces;
+ const char *box = *mailbox;
struct namespace *best = NULL;
- size_t len, best_len = 0;
+ size_t best_len = 0;
int inbox;
- inbox = strncasecmp(mailbox, "INBOX", 5) == 0;
- if (inbox && mailbox[5] == '\0') {
+ inbox = strncasecmp(box, "INBOX", 5) == 0;
+ if (inbox && box[5] == '\0') {
/* find the INBOX namespace */
- while (namespaces != NULL) {
- if (namespaces->inbox)
- return namespaces;
- if (namespaces->prefix == NULL)
- best = namespaces;
- namespaces = namespaces->next;
+ *mailbox = "INBOX";
+ while (ns != NULL) {
+ if (ns->inbox)
+ return ns;
+ if (*ns->prefix == '\0')
+ best = ns;
+ ns = ns->next;
}
return best;
}
- while (namespaces != NULL) {
- len = namespaces->prefix == NULL ? 0 :
- strlen(namespaces->prefix);
- if (len >= best_len &&
- (strncmp(namespaces->prefix, mailbox, len) == 0 ||
- (inbox && strncmp(namespaces->prefix, "INBOX", 5) == 0 &&
- mailbox[5] == namespaces->hierarchy_sep &&
- namespaces->prefix[5] == namespaces->hierarchy_sep &&
- strncmp(namespaces->prefix+6, mailbox+6, len-6) == 0))) {
- best = namespaces;
- best_len = len;
+ for (; ns != NULL; ns = ns->next) {
+ if (ns->prefix_len >= best_len &&
+ (strncmp(ns->prefix, box, ns->prefix_len) == 0 ||
+ (inbox && strncmp(ns->prefix, "INBOX", 5) == 0 &&
+ strncmp(ns->prefix+5, box+5, ns->prefix_len-5) == 0))) {
+ best = ns;
+ best_len = ns->prefix_len;
}
- namespaces = namespaces->next;
+ }
+
+ if (best != NULL) {
+ if (best_len > 0)
+ *mailbox += best_len;
+ else if (inbox && (box[5] == best->sep || box[5] == '\0'))
+ *mailbox = t_strconcat("INBOX", box+5, NULL);
+
+ *mailbox = namespace_fix_sep(best, *mailbox);
}
return best;
struct namespace *next;
enum namespace_type type;
- char hierarchy_sep;
+ char sep, real_sep, sep_str[3];
+
char *prefix;
- int inbox, hidden;
+ size_t prefix_len;
+
+ int inbox, hidden, subscriptions;
struct mail_storage *storage;
};
struct namespace *namespace_init(pool_t pool, const char *user);
void namespace_deinit(struct namespace *namespaces);
+const char *namespace_fix_sep(struct namespace *ns, const char *name);
+
struct namespace *
-namespace_find(struct namespace *namespaces, const char *mailbox);
+namespace_find(struct namespace *namespaces, const char **mailbox);
#endif
void index_storage_deinit(struct index_storage *storage)
{
- i_free(storage->storage.namespace);
i_free(storage->storage.error);
if (--index_storage_refcount > 0)
return FALSE;
}
- /* INBOX exists always */
- if (imap_match(glob, "INBOX") > 0 && !update_only) {
- node = mailbox_tree_get(ctx->tree_ctx, "INBOX", NULL);
- node->flags |= MAILBOX_FLAG_MATCHED | MAILBOX_NOCHILDREN;
- node->flags &= ~(MAILBOX_PLACEHOLDER | MAILBOX_NONEXISTENT);
- }
-
stat_dirs = getenv("MAILDIR_STAT_DIRS") != NULL;
mailbox = t_str_new(PATH_MAX);
match != IMAP_MATCH_PARENT)
continue;
- if (strcasecmp(fname, "INBOX") == 0)
- continue; /* ignore inboxes */
-
if (match == IMAP_MATCH_PARENT) {
t_push();
while ((p = strrchr(mailbox_c,
node = mailbox_tree_get(ctx->tree_ctx, name, NULL);
node->flags = MAILBOX_FLAG_MATCHED;
if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0) {
- if (strcasecmp(name, "INBOX") != 0)
- node->flags |= MAILBOX_NONEXISTENT;
- node->flags |= MAILBOX_NOCHILDREN;
+ node->flags |= MAILBOX_NONEXISTENT |
+ MAILBOX_NOCHILDREN;
}
break;
case IMAP_MATCH_PARENT:
struct mailbox_list_context *
maildir_mailbox_list_init(struct mail_storage *storage,
- const char *mask, enum mailbox_list_flags flags)
+ const char *ref, const char *mask,
+ enum mailbox_list_flags flags)
{
struct index_storage *istorage = (struct index_storage *)storage;
struct maildir_list_context *ctx;
ctx->flags = flags;
ctx->tree_ctx = mailbox_tree_init(MAILDIR_FS_SEP);
- if (storage->hierarchy_sep != MAILDIR_FS_SEP &&
- strchr(mask, MAILDIR_FS_SEP) != NULL) {
- /* this will never match, return nothing */
- return &ctx->mailbox_ctx;
+ if (*ref != '\0') {
+ /* join reference + mask */
+ if (*mask == MAILDIR_FS_SEP &&
+ ref[strlen(ref)-1] == MAILDIR_FS_SEP) {
+ /* A. .B -> A.B */
+ mask++;
+ } else if (*mask != MAILDIR_FS_SEP &&
+ ref[strlen(ref)-1] != MAILDIR_FS_SEP) {
+ /* A B -> A.B */
+ mask = t_strconcat(ref, MAILDIR_FS_SEP_S, mask, NULL);
+ } else {
+ mask = t_strconcat(ref, mask, NULL);
+ }
}
- mask = maildir_fix_mailbox_name(istorage, mask, FALSE);
glob = imap_match_init(pool, mask, TRUE, MAILDIR_FS_SEP);
ctx->dir = istorage->dir;
- ctx->prefix = storage->namespace == NULL ? "" :
- maildir_fix_mailbox_name(istorage, storage->namespace, FALSE);
+ ctx->prefix = "";
if ((flags & MAILBOX_LIST_SUBSCRIBED) != 0) {
- if (!maildir_fill_subscribed(ctx, glob)) {
- mailbox_tree_deinit(ctx->tree_ctx);
- pool_unref(pool);
- return NULL;
- }
+ if (!maildir_fill_subscribed(ctx, glob))
+ return &ctx->mailbox_ctx;
} else if (full_filesystem_access && (p = strrchr(mask, '/')) != NULL) {
dir = t_strdup_until(mask, p);
- ctx->prefix = t_strconcat(ctx->prefix,
- t_strdup_until(mask, p+1), NULL);
+ ctx->prefix = p_strdup_until(pool, mask, p+1);
if (*mask != '/' && *mask != '~')
dir = t_strconcat(istorage->dir, "/", dir, NULL);
if ((flags & MAILBOX_LIST_SUBSCRIBED) == 0 ||
(ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0) {
int update_only = (flags & MAILBOX_LIST_SUBSCRIBED) != 0;
- if (!maildir_fill_readdir(ctx, glob, update_only)) {
- mailbox_tree_deinit(ctx->tree_ctx);
- pool_unref(pool);
- return NULL;
- }
+ if (!maildir_fill_readdir(ctx, glob, update_only))
+ return &ctx->mailbox_ctx;
}
- ctx->prefix = p_strdup(pool, ctx->prefix);
ctx->node_path = str_new(pool, 256);
ctx->root = mailbox_tree_get(ctx->tree_ctx, NULL, NULL);
ctx->mailbox_ctx.storage = storage;
static int verify_inbox(struct index_storage *storage);
static struct mail_storage *
-maildir_create(const char *data, const char *user,
- const char *namespace, char hierarchy_sep)
+maildir_create(const char *data, const char *user)
{
struct index_storage *storage;
const char *root_dir, *inbox_dir, *index_dir, *control_dir;
storage = i_new(struct index_storage, 1);
storage->storage = maildir_storage;
- if (hierarchy_sep != '\0')
- storage->storage.hierarchy_sep = hierarchy_sep;
- storage->storage.namespace = i_strdup(namespace);
-
/* the default ".temp.xxx" prefix would be treated as directory */
storage->temp_prefix =
i_strconcat("temp.", my_hostname, ".", my_pid, ".", NULL);
MAILDIR_FS_SEP_S, p+1, NULL);
}
-const char *maildir_fix_mailbox_name(struct index_storage *storage,
- const char *name, int remove_namespace)
-{
- char *dup, *p, sep;
- size_t len;
-
- if (strncasecmp(name, "INBOX", 5) == 0 &&
- (name[5] == '\0' || name[5] == storage->storage.hierarchy_sep)) {
- /* use same case with all INBOX folders or we'll get
- into trouble */
- name = t_strconcat("INBOX", name+5, NULL);
- if (name[5] == '\0') {
- /* don't check namespace with INBOX */
- return name;
- }
- }
-
- if (storage->storage.namespace != NULL && remove_namespace) {
- len = strlen(storage->storage.namespace);
- if (strncmp(storage->storage.namespace, name, len) != 0) {
- i_panic("maildir: expecting namespace '%s' in name "
- "'%s'", storage->storage.namespace, name);
- }
- name += len;
- }
-
- if (full_filesystem_access && (*name == '/' || *name == '~'))
- return name;
-
- sep = storage->storage.hierarchy_sep;
- if (sep == MAILDIR_FS_SEP)
- return name;
-
- dup = t_strdup_noconst(name);
- for (p = dup; *p != '\0'; p++) {
- if (*p == sep)
- *p = MAILDIR_FS_SEP;
- }
-
- return dup;
-}
-
const char *maildir_get_path(struct index_storage *storage, const char *name)
{
if (full_filesystem_access && (*name == '/' || *name == '~'))
mail_storage_clear_error(_storage);
- name = maildir_fix_mailbox_name(storage, name, TRUE);
if (strcmp(name, "INBOX") == 0) {
if (verify_inbox(storage) < 0)
return NULL;
mail_storage_clear_error(_storage);
- name = maildir_fix_mailbox_name(storage, name, TRUE);
if (!maildir_is_valid_create_name(name)) {
mail_storage_set_error(_storage, "Invalid mailbox name");
return -1;
mail_storage_clear_error(_storage);
- name = maildir_fix_mailbox_name(storage, name, TRUE);
if (strcmp(name, "INBOX") == 0) {
mail_storage_set_error(_storage, "INBOX can't be deleted.");
return -1;
{
struct mailbox_list_context *ctx;
struct mailbox_list *list;
- const char *oldpath, *newpath, *new_listname, *mask;
+ const char *oldpath, *newpath, *new_listname;
size_t oldnamelen;
int ret;
ret = 0;
oldnamelen = strlen(oldname);
- mask = t_strdup_printf("%s%s%c*", storage->storage.namespace != NULL ?
- storage->storage.namespace : "", oldname,
- storage->storage.hierarchy_sep);
- ctx = maildir_mailbox_list_init(&storage->storage, mask,
+ ctx = maildir_mailbox_list_init(&storage->storage, oldname, "*",
MAILBOX_LIST_FAST_FLAGS);
while ((list = maildir_mailbox_list_next(ctx)) != NULL) {
- const char *list_name;
-
t_push();
- list_name = maildir_fix_mailbox_name(storage, list->name, TRUE);
- i_assert(oldnamelen <= strlen(list_name));
+ i_assert(oldnamelen <= strlen(list->name));
new_listname = t_strconcat(newname,
- list_name + oldnamelen, NULL);
- oldpath = maildir_get_path(storage, list_name);
+ list->name + oldnamelen, NULL);
+ oldpath = maildir_get_path(storage, list->name);
newpath = maildir_get_path(storage, new_listname);
/* FIXME: it's possible to merge two folders if either one of
break;
}
- (void)rename_indexes(storage, list_name, new_listname);
+ (void)rename_indexes(storage, list->name, new_listname);
t_pop();
}
mail_storage_clear_error(_storage);
- oldname = maildir_fix_mailbox_name(storage, oldname, TRUE);
- newname = maildir_fix_mailbox_name(storage, newname, TRUE);
-
if (!maildir_is_valid_existing_name(oldname) ||
!maildir_is_valid_create_name(newname)) {
mail_storage_set_error(_storage, "Invalid mailbox name");
storage->control_dir : storage->dir,
"/" SUBSCRIPTION_FILE_NAME, NULL);
- name = maildir_fix_mailbox_name(storage, name, FALSE);
return subsfile_set_subscribed(_storage, path, storage->temp_prefix,
name, set);
}
mail_storage_clear_error(_storage);
- name = maildir_fix_mailbox_name(storage, name, TRUE);
if (!maildir_is_valid_existing_name(name)) {
*status = MAILBOX_NAME_INVALID;
return 0;
struct mail_storage maildir_storage = {
"maildir", /* name */
- NULL, /* namespace */
- '.', /* default hierarchy separator */
+ '.', /* hierarchy separator */
maildir_create,
maildir_free,
struct mailbox_list_context *
maildir_mailbox_list_init(struct mail_storage *storage,
- const char *mask, enum mailbox_list_flags flags);
+ const char *ref, const char *mask,
+ enum mailbox_list_flags flags);
int maildir_mailbox_list_deinit(struct mailbox_list_context *ctx);
struct mailbox_list *
maildir_mailbox_list_next(struct mailbox_list_context *ctx);
int maildir_copy_commit(struct maildir_copy_context *ctx);
void maildir_copy_rollback(struct maildir_copy_context *ctx);
-const char *maildir_fix_mailbox_name(struct index_storage *storage,
- const char *name, int remove_namespace);
const char *maildir_get_path(struct index_storage *storage, const char *name);
int maildir_sync_last_commit(struct index_mailbox *ibox);
enum mailbox_list_flags flags;
- const char *prefix;
struct imap_match_glob *glob;
struct subsfile_list_context *subsfile_ctx;
};
static struct mailbox_list *mbox_list_subs(struct mbox_list_context *ctx);
-static struct mailbox_list *mbox_list_inbox(struct mbox_list_context *ctx);
static struct mailbox_list *mbox_list_path(struct mbox_list_context *ctx);
static struct mailbox_list *mbox_list_next(struct mbox_list_context *ctx);
-static struct mailbox_list *mbox_list_none(struct mbox_list_context *ctx);
-static const char *mask_get_dir(struct mail_storage *storage, const char *mask)
+static const char *mask_get_dir(const char *mask)
{
const char *p, *last_dir;
- size_t len;
-
- if (storage->namespace != NULL) {
- len = strlen(storage->namespace);
- if (strncmp(mask, storage->namespace, len) != 0)
- return NULL;
-
- mask += len;
- }
last_dir = NULL;
for (p = mask; *p != '\0' && *p != '%' && *p != '*'; p++) {
}
struct mailbox_list_context *
-mbox_mailbox_list_init(struct mail_storage *storage, const char *mask,
+mbox_mailbox_list_init(struct mail_storage *storage,
+ const char *ref, const char *mask,
enum mailbox_list_flags flags)
{
struct index_storage *istorage = (struct index_storage *)storage;
const char *path, *virtual_path;
DIR *dirp;
+ ctx = i_new(struct mbox_list_context, 1);
+ ctx->mailbox_ctx.storage = storage;
+ ctx->istorage = istorage;
+ ctx->list_pool = pool_alloconly_create("mbox_list", 1024);
+ ctx->next = mbox_list_next;
+
mail_storage_clear_error(storage);
- if (storage->hierarchy_sep != '/' && strchr(mask, '/') != NULL) {
- /* this will never match, return nothing */
- ctx = i_new(struct mbox_list_context, 1);
- ctx->mailbox_ctx.storage = storage;
- ctx->next = mbox_list_none;
+ /* check that we're not trying to do any "../../" lists */
+ if (!mbox_is_valid_mask(ref) ||
+ !mbox_is_valid_mask(mask)) {
+ mail_storage_set_error(storage, "Invalid mask");
return &ctx->mailbox_ctx;
}
- mask = mbox_fix_mailbox_name(istorage, mask, FALSE);
-
- /* check that we're not trying to do any "../../" lists */
- if (!mbox_is_valid_mask(mask)) {
- mail_storage_set_error(storage, "Invalid mask");
- return NULL;
+ if (*mask == '/' || *mask == '~') {
+ /* mask overrides reference */
+ } else if (*ref != '\0') {
+ /* merge reference and mask */
+ if (ref[strlen(ref)-1] == '/')
+ mask = t_strconcat(ref, mask, NULL);
+ else
+ mask = t_strconcat(ref, "/", mask, NULL);
}
if ((flags & MAILBOX_LIST_SUBSCRIBED) != 0) {
- ctx = i_new(struct mbox_list_context, 1);
ctx->mailbox_ctx.storage = storage;
ctx->istorage = istorage;
ctx->flags = flags;
ctx->subsfile_ctx =
subsfile_list_init(storage, path);
if (ctx->subsfile_ctx == NULL) {
- i_free(ctx);
- return NULL;
+ ctx->next = mbox_list_next;
+ return &ctx->mailbox_ctx;
}
ctx->glob = imap_match_init(default_pool, mask, TRUE, '/');
- ctx->list_pool = pool_alloconly_create("mbox_list", 1024);
return &ctx->mailbox_ctx;
}
/* if we're matching only subdirectories, don't bother scanning the
parent directories */
- virtual_path = mask_get_dir(storage, mask);
+ virtual_path = mask_get_dir(mask);
path = mbox_get_path(istorage, virtual_path);
if (list_opendir(storage, path, TRUE, &dirp) < 0)
- return NULL;
+ return &ctx->mailbox_ctx;
/* if user gave invalid directory, we just don't show any results. */
- ctx = i_new(struct mbox_list_context, 1);
- ctx->mailbox_ctx.storage = storage;
- ctx->istorage = istorage;
ctx->flags = flags;
ctx->glob = imap_match_init(default_pool, mask, TRUE, '/');
- ctx->list_pool = pool_alloconly_create("mbox_list", 1024);
- ctx->prefix = storage->namespace == NULL ? "" :
- mbox_fix_mailbox_name(istorage, storage->namespace, FALSE);
- if (virtual_path == NULL && imap_match(ctx->glob, "INBOX") > 0)
- ctx->next = mbox_list_inbox;
- else if (virtual_path != NULL && dirp != NULL)
+ if (virtual_path != NULL && dirp != NULL)
ctx->next = mbox_list_path;
- else
- ctx->next = mbox_list_next;
if (dirp != NULL) {
ctx->dir = i_new(struct list_dir_context, 1);
ctx->dir->dirp = dirp;
ctx->dir->real_path = i_strdup(path);
- ctx->dir->virtual_path = virtual_path == NULL ? NULL :
- i_strconcat(ctx->prefix, virtual_path, NULL);
+ ctx->dir->virtual_path = i_strdup(virtual_path);
}
return &ctx->mailbox_ctx;
}
/* check the mask */
if (ctx->dir->virtual_path == NULL)
- list_path = t_strconcat(ctx->prefix, fname, NULL);
+ list_path = fname;
else {
list_path = t_strconcat(ctx->dir->virtual_path,
"/", fname, NULL);
} else if (ret < 0)
return -1;
return match > 0 || match2 > 0;
- } else if (match > 0 &&
- strcmp(real_path, ctx->istorage->inbox_path) != 0 &&
- strcasecmp(list_path, "INBOX") != 0) {
- /* don't match any INBOX here, it's added separately.
- we might also have ~/mail/inbox, ~/mail/Inbox etc.
- Just ignore them for now. */
+ } else if (match > 0) {
ctx->list.flags = noselect ? MAILBOX_NOSELECT :
(MAILBOX_NOINFERIORS | STAT_GET_MARKED(st));
ctx->list.name = p_strdup(ctx->list_pool, list_path);
return 0;
}
-static struct mailbox_list *list_fix_name(struct mbox_list_context *ctx)
-{
- char *p, *str, sep;
-
- if (strchr(ctx->list.name, '/') != NULL) {
- str = p_strdup(ctx->list_pool, ctx->list.name);
- ctx->list.name = str;
-
- sep = ctx->mailbox_ctx.storage->hierarchy_sep;
- for (p = str; *p != '\0'; p++) {
- if (*p == '/')
- *p = sep;
- }
- }
-
- return &ctx->list;
-}
-
static struct mailbox_list *mbox_list_subs(struct mbox_list_context *ctx)
{
struct stat st;
if (imap_match(ctx->glob, name) > 0) {
p_clear(ctx->list_pool);
ctx->list.name = p_strdup(ctx->list_pool, name);
- return list_fix_name(ctx);
+ return &ctx->list;
}
}
i_unreached();
}
- (void)list_fix_name(ctx);
if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) != 0)
return &ctx->list;
t_push();
- name = mbox_fix_mailbox_name(ctx->istorage, ctx->list.name, TRUE);
- path = mbox_get_path(ctx->istorage, name);
+ path = mbox_get_path(ctx->istorage, ctx->list.name);
if (stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode))
ctx->list.flags = MAILBOX_NOSELECT | MAILBOX_CHILDREN;
STAT_GET_MARKED(st);
}
} else {
- if (strcasecmp(ctx->list.name, "INBOX") == 0)
- ctx->list.flags = MAILBOX_UNMARKED;
- else
- ctx->list.flags = MAILBOX_NONEXISTENT;
+ ctx->list.flags = MAILBOX_NONEXISTENT;
}
t_pop();
return &ctx->list;
}
-static struct mailbox_list *mbox_list_inbox(struct mbox_list_context *ctx)
-{
- struct stat st;
-
- if (ctx->dir != NULL && ctx->dir->virtual_path != NULL)
- ctx->next = mbox_list_path;
- else
- ctx->next = mbox_list_next;
-
- /* INBOX exists always, even if the file doesn't. */
- ctx->list.flags = strncmp(ctx->prefix, "INBOX/", 6) == 0 ?
- MAILBOX_CHILDREN : MAILBOX_NOINFERIORS;
- if ((ctx->flags & MAILBOX_LIST_FAST_FLAGS) == 0) {
- if (stat(ctx->istorage->inbox_path, &st) < 0)
- ctx->list.flags |= MAILBOX_UNMARKED;
- else
- ctx->list.flags |= STAT_GET_MARKED(st);
- }
-
- ctx->list.name = "INBOX";
- return &ctx->list;
-}
-
static struct mailbox_list *mbox_list_path(struct mbox_list_context *ctx)
{
ctx->next = mbox_list_next;
ctx->list.flags = MAILBOX_NOSELECT | MAILBOX_CHILDREN;
- ctx->list.name = p_strconcat(ctx->list_pool, ctx->prefix,
- ctx->dir->virtual_path, "/", NULL);
+ ctx->list.name =
+ p_strconcat(ctx->list_pool, ctx->dir->virtual_path, "/", NULL);
if (imap_match(ctx->glob, ctx->list.name) > 0)
- return list_fix_name(ctx);
+ return &ctx->list;
else
return ctx->next(ctx);
}
t_pop();
if (ret > 0)
- return list_fix_name(ctx);
+ return &ctx->list;
if (ret < 0) {
ctx->failed = TRUE;
return NULL;
/* finished */
return NULL;
}
-
-static struct mailbox_list *
-mbox_list_none(struct mbox_list_context *ctx __attr_unused__)
-{
- return NULL;
-}
return path;
}
-static struct mail_storage *
-mbox_create(const char *data, const char *user,
- const char *namespace, char hierarchy_sep)
+static struct mail_storage *mbox_create(const char *data, const char *user)
{
struct index_storage *storage;
const char *root_dir, *inbox_file, *index_dir, *p;
storage = i_new(struct index_storage, 1);
storage->storage = mbox_storage;
- if (hierarchy_sep != '\0')
- storage->storage.hierarchy_sep = hierarchy_sep;
- storage->storage.namespace = i_strdup(namespace);
-
storage->dir = i_strdup(home_expand(root_dir));
storage->inbox_path = i_strdup(home_expand(inbox_file));
storage->index_dir = i_strdup(home_expand(index_dir));
i_free(storage);
}
-const char *mbox_fix_mailbox_name(struct index_storage *istorage,
- const char *name, int remove_namespace)
-{
- struct mail_storage *storage = &istorage->storage;
- char *dup, *p, sep;
- size_t len;
-
- if (strncasecmp(name, "INBOX", 5) == 0 &&
- (name[5] == '\0' || name[5] == storage->hierarchy_sep)) {
- name = t_strconcat("INBOX", name+5, NULL);
- if (name[5] == '\0') {
- /* don't check namespace with INBOX */
- return name;
- }
- }
-
- if (storage->namespace != NULL && remove_namespace) {
- len = strlen(storage->namespace);
- if (strncmp(storage->namespace, name, len) != 0) {
- i_panic("mbox: expecting namespace '%s' in name '%s'",
- storage->namespace, name);
- }
- name += len;
- }
-
- if (*name == '/' && full_filesystem_access)
- return name;
-
- sep = storage->hierarchy_sep;
- if (sep == '/')
- return name;
-
- dup = t_strdup_noconst(name);
- for (p = dup; *p != '\0'; p++) {
- if (*p == sep)
- *p = '/';
- }
-
- return dup;
-}
-
int mbox_is_valid_mask(const char *mask)
{
const char *p;
if (fd != -1)
(void)close(fd);
else if (errno != EEXIST) {
- mail_storage_set_critical(storage,
- "open(%s, O_CREAT) failed: %m", storage->inbox_file);
+ mail_storage_set_critical(&storage->storage,
+ "open(%s, O_CREAT) failed: %m", storage->inbox_path);
}
/* make sure the index directories exist */
static const char *
mbox_get_path(struct index_storage *storage, const char *name)
{
- if (strcasecmp(name, "INBOX") == 0)
+ if (strcmp(name, "INBOX") == 0)
return storage->inbox_path;
if (full_filesystem_access && (*name == '/' || *name == '~'))
return home_expand(name);
const char *path, *index_dir;
uint32_t mbox_extra_idx;
- if (strcasecmp(name, "INBOX") == 0) {
+ if (strcmp(name, "INBOX") == 0) {
/* name = "INBOX"
path = "<inbox_file>/INBOX"
index_dir = "/mail/.imap/INBOX" */
mail_storage_clear_error(_storage);
- name = mbox_fix_mailbox_name(storage, name, TRUE);
-
- /* INBOX is always case-insensitive */
- if (strcasecmp(name, "INBOX") == 0) {
- /* make sure inbox exists */
+ if (strcmp(name, "INBOX") == 0) {
+ /* make sure INBOX exists */
if (verify_inbox(storage) < 0)
return NULL;
return mbox_open(storage, "INBOX", flags);
mail_storage_clear_error(_storage);
- name = mbox_fix_mailbox_name(storage, name, TRUE);
-
if (!mbox_is_valid_create_name(name)) {
mail_storage_set_error(_storage, "Invalid mailbox name");
return -1;
mail_storage_clear_error(_storage);
- name = mbox_fix_mailbox_name(storage, name, TRUE);
-
- if (strcasecmp(name, "INBOX") == 0) {
+ if (strcmp(name, "INBOX") == 0) {
mail_storage_set_error(_storage, "INBOX can't be deleted.");
return -1;
}
mail_storage_clear_error(_storage);
- oldname = mbox_fix_mailbox_name(storage, oldname, TRUE);
- newname = mbox_fix_mailbox_name(storage, newname, TRUE);
-
if (!mbox_is_valid_existing_name(oldname) ||
!mbox_is_valid_create_name(newname)) {
mail_storage_set_error(_storage, "Invalid mailbox name");
const char *path;
path = t_strconcat(storage->dir, "/" SUBSCRIPTION_FILE_NAME, NULL);
- name = mbox_fix_mailbox_name(storage, name, FALSE);
return subsfile_set_subscribed(_storage, path, storage->temp_prefix,
name, set);
}
mail_storage_clear_error(_storage);
- name = mbox_fix_mailbox_name(storage, name, TRUE);
-
if (!mbox_is_valid_existing_name(name)) {
*status = MAILBOX_NAME_INVALID;
return 0;
struct mail_storage mbox_storage = {
"mbox", /* name */
- NULL, /* namespace */
- '/', /* default hierarchy separator */
+ '/', /* hierarchy separator */
mbox_create,
mbox_free,
int mbox_set_syscall_error(struct index_mailbox *ibox, const char *function);
struct mailbox_list_context *
-mbox_mailbox_list_init(struct mail_storage *storage, const char *mask,
+mbox_mailbox_list_init(struct mail_storage *storage,
+ const char *ref, const char *mask,
enum mailbox_list_flags flags);
int mbox_mailbox_list_deinit(struct mailbox_list_context *ctx);
struct mailbox_list *mbox_mailbox_list_next(struct mailbox_list_context *ctx);
int mbox_save_commit(struct mbox_save_context *ctx);
void mbox_save_rollback(struct mbox_save_context *ctx);
-const char *mbox_fix_mailbox_name(struct index_storage *istorage,
- const char *name, int remove_namespace);
int mbox_is_valid_mask(const char *mask);
#endif
struct mail_storage {
char *name;
- char *namespace;
char hierarchy_sep;
- struct mail_storage *(*create)(const char *data, const char *user,
- const char *namespace,
- char hierarchy_sep);
+ struct mail_storage *(*create)(const char *data, const char *user);
void (*destroy)(struct mail_storage *storage);
int (*autodetect)(const char *data);
struct mailbox_list_context *
(*mailbox_list_init)(struct mail_storage *storage,
- const char *mask,
+ const char *ref, const char *mask,
enum mailbox_list_flags flags);
struct mailbox_list *
(*mailbox_list_next)(struct mailbox_list_context *ctx);
}
struct mail_storage *
-mail_storage_create(const char *name, const char *data, const char *user,
- const char *namespace, char hierarchy_sep)
+mail_storage_create(const char *name, const char *data, const char *user)
{
struct mail_storage_list *list;
i_assert(name != NULL);
for (list = storages; list != NULL; list = list->next) {
- if (strcasecmp(list->storage->name, name) == 0) {
- return list->storage->create(data, user,
- namespace, hierarchy_sep);
- }
+ if (strcasecmp(list->storage->name, name) == 0)
+ return list->storage->create(data, user);
}
return NULL;
}
struct mail_storage *
-mail_storage_create_default(const char *user,
- const char *namespace, char hierarchy_sep)
+mail_storage_create_default(const char *user)
{
struct mail_storage_list *list;
struct mail_storage *storage;
for (list = storages; list != NULL; list = list->next) {
- storage = list->storage->create(NULL, user, namespace,
- hierarchy_sep);
+ storage = list->storage->create(NULL, user);
if (storage != NULL)
return storage;
}
}
struct mail_storage *
-mail_storage_create_with_data(const char *data, const char *user,
- const char *namespace, char hierarchy_sep)
+mail_storage_create_with_data(const char *data, const char *user)
{
struct mail_storage *storage;
const char *p, *name;
- if (data == NULL || *data == '\0') {
- return mail_storage_create_default(user, namespace,
- hierarchy_sep);
- }
+ if (data == NULL || *data == '\0')
+ return mail_storage_create_default(user);
/* check if we're in the form of mailformat:data
(eg. maildir:Maildir) */
if (*p == ':') {
name = t_strdup_until(data, p);
- storage = mail_storage_create(name, p+1, user,
- namespace, hierarchy_sep);
+ storage = mail_storage_create(name, p+1, user);
} else {
storage = mail_storage_autodetect(data);
- if (storage != NULL) {
- storage = storage->create(data, user,
- namespace, hierarchy_sep);
- }
+ if (storage != NULL)
+ storage = storage->create(data, user);
}
return storage;
struct mailbox_list_context *
mail_storage_mailbox_list_init(struct mail_storage *storage,
- const char *mask,
+ const char *ref, const char *mask,
enum mailbox_list_flags flags)
{
- return storage->mailbox_list_init(storage, mask, flags);
+ return storage->mailbox_list_init(storage, ref, mask, flags);
}
struct mailbox_list *
If namespace is non-NULL, all mailbox names are expected to begin with it.
hierarchy_sep overrides the default separator if it's not '\0'. */
struct mail_storage *
-mail_storage_create(const char *name, const char *data, const char *user,
- const char *namespace, char hierarchy_sep);
+mail_storage_create(const char *name, const char *data, const char *user);
void mail_storage_destroy(struct mail_storage *storage);
+struct mail_storage *mail_storage_create_default(const char *user);
struct mail_storage *
-mail_storage_create_default(const char *user,
- const char *namespace, char hierarchy_sep);
-struct mail_storage *
-mail_storage_create_with_data(const char *data, const char *user,
- const char *namespace, char hierarchy_sep);
+mail_storage_create_with_data(const char *data, const char *user);
char mail_storage_get_hierarchy_sep(struct mail_storage *storage);
const char *oldname, const char *newname);
/* Initialize new mailbox list request. mask may contain '%' and '*'
- wildcards as defined in RFC2060. Matching against "INBOX" is
+ wildcards as defined in RFC3501. Matching against "INBOX" is
case-insensitive, but anything else is not. */
struct mailbox_list_context *
mail_storage_mailbox_list_init(struct mail_storage *storage,
- const char *mask,
+ const char *ref, const char *mask,
enum mailbox_list_flags flags);
/* Get next mailbox. Returns the mailbox name */
struct mailbox_list *
int mailbox_allow_new_keywords(struct mailbox *box);
/* Gets the mailbox status information. */
-int mailbox_get_status(struct mailbox *box,
- enum mailbox_status_items items,
+int mailbox_get_status(struct mailbox *box, enum mailbox_status_items items,
struct mailbox_status *status);
/* Synchronize the mailbox. */
}
static struct mailbox_list_context *
-_mailbox_list_init(struct mail_storage *storage, const char *mask,
+_mailbox_list_init(struct mail_storage *storage,
+ const char *ref, const char *mask,
enum mailbox_list_flags flags)
{
struct proxy_mail_storage *s = (struct proxy_mail_storage *) storage;
- return s->storage->mailbox_list_init(s->storage, mask, flags);
+ return s->storage->mailbox_list_init(s->storage, ref, mask, flags);
}
static int _set_subscribed(struct mail_storage *storage,
}
parse_workarounds();
- storage = mail_storage_create_with_data(mail, getenv("USER"),
- NULL, '\0');
+ storage = mail_storage_create_with_data(mail, getenv("USER"));
if (storage == NULL) {
/* failed */
if (mail != NULL && *mail != '\0')