]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Moved namespace and hierarchy separator handling to imap-specific code. LIST
authorTimo Sirainen <tss@iki.fi>
Thu, 22 Jul 2004 21:20:00 +0000 (00:20 +0300)
committerTimo Sirainen <tss@iki.fi>
Thu, 22 Jul 2004 21:20:00 +0000 (00:20 +0300)
now shows non-hidden namespaces in the LIST reply.

--HG--
branch : HEAD

26 files changed:
src/imap/cmd-append.c
src/imap/cmd-copy.c
src/imap/cmd-create.c
src/imap/cmd-delete.c
src/imap/cmd-list.c
src/imap/cmd-namespace.c
src/imap/cmd-rename.c
src/imap/cmd-select.c
src/imap/cmd-status.c
src/imap/cmd-subscribe.c
src/imap/commands-util.c
src/imap/commands-util.h
src/imap/namespace.c
src/imap/namespace.h
src/lib-storage/index/index-storage.c
src/lib-storage/index/maildir/maildir-list.c
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/maildir/maildir-storage.h
src/lib-storage/index/mbox/mbox-list.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/index/mbox/mbox-storage.h
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/lib-storage/proxy-mail-storage.c
src/pop3/main.c

index aab5829471e2d41d64d3f0b1c94899db492fc7a9..2c671e21257e2e59e668e042db817efdf8656e6c 100644 (file)
@@ -69,7 +69,7 @@ int cmd_append(struct client *client)
        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;
 
index bff008b0ea5744469cd969f5a51615814ac2bfaf..b24d4966f13d9087940227f930ef840c56c225c7 100644 (file)
@@ -75,7 +75,7 @@ int cmd_copy(struct client *client)
        if (search_arg == NULL)
                return TRUE;
 
-       storage = client_find_storage(client, mailbox);
+       storage = client_find_storage(client, &mailbox);
        if (storage == NULL)
                return TRUE;
 
index e8d30a30f7bef9c4717789f8998c31ed5ee5d05c..3d079f394290a86822410a1c8ec6a2cf4d3587c9 100644 (file)
@@ -14,7 +14,7 @@ int cmd_create(struct client *client)
        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;
 
index 816bf54c3aae252195a9751016913f5ad988413d..3dedbe14c53bc32e66a7be2170d729735a96a223 100644 (file)
@@ -28,7 +28,7 @@ int cmd_delete(struct client *client)
                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;
        }
index 3296b167f30532f5d2d0e5ee30d1d1abe5bac39c..4cb8b61ebf9f37393521bf75e83598ed1cb2afd4 100644 (file)
@@ -48,34 +48,6 @@ mailbox_flags2str(enum mailbox_flags flags, enum mailbox_list_flags list_flags)
        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)
 {
@@ -104,15 +76,204 @@ static int parse_list_flags(struct client *client, struct imap_arg *args,
        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))
@@ -145,56 +306,27 @@ int _cmd_list_full(struct client *client, int lsub)
                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;
 }
 
index f0b8a077b1378b72d7ac9a5d5fe40a3dcfaf2b67..5e01439abce2c7fb655646fd15c1e7afe833fb7f 100644 (file)
@@ -20,10 +20,7 @@ static void list_namespaces(struct namespace *ns, enum namespace_type type,
                        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, "\")");
                }
 
index c2e279b7052c72f45c40c78edf486808bac312d0..abe5203ac3b82b86fd4219f6c489a1692abefe8f 100644 (file)
@@ -15,11 +15,11 @@ int cmd_rename(struct client *client)
        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;
 
index f9fc81e464c26686c78f068b28681a71a2d27d90..671a9aa565fc436a5d3ff4432fcc388ea638b38e 100644 (file)
@@ -24,7 +24,7 @@ int _cmd_select_full(struct client *client, int readonly)
                }
        }
 
-       storage = client_find_storage(client, mailbox);
+       storage = client_find_storage(client, &mailbox);
        if (storage == NULL)
                return TRUE;
 
index 2f90cf35b68ad26433de4911edb16938da4cee73..6b5e4288018d82342f80b0b823191ffc51509d2e 100644 (file)
@@ -102,7 +102,7 @@ int cmd_status(struct client *client)
                return TRUE;
        }
 
-       storage = client_find_storage(client, mailbox);
+       storage = client_find_storage(client, &mailbox);
        if (storage == NULL)
                return FALSE;
 
index a77452c6ac5fda69bef9cd88c0919e09c9c09a40..abef31ca8849adcb636cdd8ad263e83008ca8c86 100644 (file)
@@ -15,7 +15,7 @@ int _cmd_subscribe_full(struct client *client, int subscribe)
        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;
 
index 9ecfce8da0d2f4f54ad6da27b4b876afa5834eb1..4be03841f36d572c2ec37ee6ef5f4d5cd54d34e4 100644 (file)
@@ -17,7 +17,7 @@
 #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;
 
@@ -37,7 +37,7 @@ int client_verify_mailbox_name(struct client *client, const char *mailbox,
        const char *p;
        char sep;
 
-       storage = client_find_storage(client, mailbox);
+       storage = client_find_storage(client, &mailbox);
        if (storage == NULL)
                return FALSE;
 
index 4cb8f755716dfe76f4b73a7b94c1b5088fe08a42..cd5a3ef37e0c2413e4f59fab97ee548991e6a237 100644 (file)
@@ -11,7 +11,7 @@ struct mail_full_flags;
 /* 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
index 74a205a2b5debd4b94146581de198b095b91c786..f538e065df6b7ac561a9b02be686e73e4081b9ea 100644 (file)
@@ -6,13 +6,32 @@
 
 #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);
 
@@ -21,6 +40,8 @@ namespace_add_env(pool_t pool, const char *data, unsigned int num,
        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;
@@ -37,17 +58,16 @@ namespace_add_env(pool_t pool, const char *data, unsigned int num,
        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;
 }
 
@@ -88,7 +108,7 @@ struct namespace *namespace_init(pool_t pool, const char *user)
        }
 
        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);
@@ -105,11 +125,9 @@ struct namespace *namespace_init(pool_t pool, const char *user)
 
        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;
 }
 
@@ -121,39 +139,61 @@ void namespace_deinit(struct namespace *namespaces)
        }
 }
 
+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;
index fb5ecd8cf5de0ba29cc466c9519d3e538c9a7749..c341aff39591ea77912168230bd22a3eac50e65c 100644 (file)
@@ -11,16 +11,21 @@ struct namespace {
        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
index c709b34c15f6238e411108e3c3c056f5b0c63551..507c2194939e35a6d50f334c333a1a857fe1bdc6 100644 (file)
@@ -44,7 +44,6 @@ void index_storage_init(struct index_storage *storage __attr_unused__)
 
 void index_storage_deinit(struct index_storage *storage)
 {
-       i_free(storage->storage.namespace);
        i_free(storage->storage.error);
 
        if (--index_storage_refcount > 0)
index a5763ec4b3a4534ad86da5e7df4c6a6a745dbdb3..18606623ef4bfa161bb6f00ceffdcd7f84913e8e 100644 (file)
@@ -70,13 +70,6 @@ static int maildir_fill_readdir(struct maildir_list_context *ctx,
                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);
@@ -139,9 +132,6 @@ static int maildir_fill_readdir(struct maildir_list_context *ctx,
                    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,
@@ -219,9 +209,8 @@ static int maildir_fill_subscribed(struct maildir_list_context *ctx,
                        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:
@@ -249,7 +238,8 @@ static int maildir_fill_subscribed(struct maildir_list_context *ctx,
 
 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;
@@ -266,29 +256,32 @@ maildir_mailbox_list_init(struct mail_storage *storage,
        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);
@@ -298,14 +291,10 @@ maildir_mailbox_list_init(struct mail_storage *storage,
        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;
index b78e29f21775bc0c52084b1a58ea6c3c123c29bd..7dcd75313adae9c4b9be8574c5bc681fa64c5017 100644 (file)
@@ -30,8 +30,7 @@ static const char *maildirs[] = { "cur", "new", "tmp", NULL  };
 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;
@@ -91,10 +90,6 @@ maildir_create(const char *data, const char *user,
        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);
@@ -184,48 +179,6 @@ static const char *maildir_get_absolute_path(const char *name, int unlink)
                           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 == '~'))
@@ -455,7 +408,6 @@ maildir_mailbox_open(struct mail_storage *_storage,
 
        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;
@@ -496,7 +448,6 @@ static int maildir_mailbox_create(struct mail_storage *_storage,
 
        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;
@@ -524,7 +475,6 @@ static int maildir_mailbox_delete(struct mail_storage *_storage,
 
        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;
@@ -620,29 +570,23 @@ static int rename_subfolders(struct index_storage *storage,
 {
        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
@@ -665,7 +609,7 @@ static int rename_subfolders(struct index_storage *storage,
                        break;
                }
 
-               (void)rename_indexes(storage, list_name, new_listname);
+               (void)rename_indexes(storage, list->name, new_listname);
                t_pop();
        }
 
@@ -683,9 +627,6 @@ static int maildir_mailbox_rename(struct mail_storage *_storage,
 
        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");
@@ -741,7 +682,6 @@ static int maildir_set_subscribed(struct mail_storage *_storage,
                           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);
 }
@@ -756,7 +696,6 @@ static int maildir_get_mailbox_name_status(struct mail_storage *_storage,
 
        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;
@@ -821,9 +760,8 @@ maildir_notify_changes(struct mailbox *box, unsigned int min_interval,
 
 struct mail_storage maildir_storage = {
        "maildir", /* name */
-       NULL, /* namespace */
 
-       '.', /* default hierarchy separator */
+       '.', /* hierarchy separator */
 
        maildir_create,
        maildir_free,
index d756e79b4431f4c5df159fbaf39902332948997b..7a8941292c9960454db2bc048afac3b16f819cae 100644 (file)
@@ -33,7 +33,8 @@ int maildir_create_tmp(struct index_mailbox *ibox, const char *dir,
 
 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);
@@ -60,8 +61,6 @@ int maildir_copy(struct mailbox_transaction_context *t, struct mail *mail,
 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);
index 3180da42a3e1430ed59709ebdf377659d4f20629..7c2af279b9699fba2b654b5cccc70560b913834c 100644 (file)
@@ -31,7 +31,6 @@ struct mbox_list_context {
 
        enum mailbox_list_flags flags;
 
-       const char *prefix;
        struct imap_match_glob *glob;
        struct subsfile_list_context *subsfile_ctx;
 
@@ -45,23 +44,12 @@ struct mbox_list_context {
 };
 
 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++) {
@@ -110,7 +98,8 @@ static int list_opendir(struct mail_storage *storage,
 }
 
 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;
@@ -118,26 +107,32 @@ mbox_mailbox_list_init(struct mail_storage *storage, const char *mask,
        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;
@@ -148,45 +143,33 @@ mbox_mailbox_list_init(struct mail_storage *storage, const char *mask,
                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;
 }
@@ -253,7 +236,7 @@ static int list_file(struct mbox_list_context *ctx, const char *fname)
 
        /* 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);
@@ -303,12 +286,7 @@ static int list_file(struct mbox_list_context *ctx, const char *fname)
                } 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);
@@ -318,24 +296,6 @@ static int list_file(struct mbox_list_context *ctx, const char *fname)
        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;
@@ -362,19 +322,17 @@ static struct mailbox_list *mbox_list_subs(struct mbox_list_context *ctx)
                        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;
@@ -383,48 +341,22 @@ static struct mailbox_list *mbox_list_subs(struct mbox_list_context *ctx)
                                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);
 }
@@ -445,7 +377,7 @@ static struct mailbox_list *mbox_list_next(struct mbox_list_context *ctx)
                        t_pop();
 
                        if (ret > 0)
-                               return list_fix_name(ctx);
+                               return &ctx->list;
                        if (ret < 0) {
                                ctx->failed = TRUE;
                                return NULL;
@@ -460,9 +392,3 @@ static struct mailbox_list *mbox_list_next(struct mbox_list_context *ctx)
        /* finished */
        return NULL;
 }
-
-static struct mailbox_list *
-mbox_list_none(struct mbox_list_context *ctx __attr_unused__)
-{
-       return NULL;
-}
index f1b64e34349703045c8e49a18965b207e3fd3b9d..0b2de0f37496c705e75bd56117d7159922dc8756 100644 (file)
@@ -150,9 +150,7 @@ static const char *create_root_dir(void)
        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;
@@ -224,10 +222,6 @@ mbox_create(const char *data, const char *user,
        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));
@@ -251,47 +245,6 @@ static void mbox_free(struct mail_storage *_storage)
        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;
@@ -390,8 +343,8 @@ static int verify_inbox(struct index_storage *storage)
        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 */
@@ -404,7 +357,7 @@ static int verify_inbox(struct index_storage *storage)
 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);
@@ -434,7 +387,7 @@ mbox_open(struct index_storage *storage, const char *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" */
@@ -487,11 +440,8 @@ mbox_mailbox_open(struct mail_storage *_storage,
 
        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);
@@ -538,8 +488,6 @@ static int mbox_mailbox_create(struct mail_storage *_storage, const char *name,
 
        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;
@@ -607,9 +555,7 @@ static int mbox_mailbox_delete(struct mail_storage *_storage, const char *name)
 
        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;
        }
@@ -701,9 +647,6 @@ static int mbox_mailbox_rename(struct mail_storage *_storage,
 
        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");
@@ -780,7 +723,6 @@ static int mbox_set_subscribed(struct mail_storage *_storage,
        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);
 }
@@ -795,8 +737,6 @@ static int mbox_get_mailbox_name_status(struct mail_storage *_storage,
 
        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;
@@ -853,9 +793,8 @@ mbox_notify_changes(struct mailbox *box, unsigned int min_interval,
 
 struct mail_storage mbox_storage = {
        "mbox", /* name */
-       NULL, /* namespace */
 
-       '/', /* default hierarchy separator */
+       '/', /* hierarchy separator */
 
        mbox_create,
        mbox_free,
index c8ac722a252a497bf5f787ca30c0c6b429469184..e526613c03457c941522166f8bd828c409bab840 100644 (file)
@@ -24,7 +24,8 @@ extern size_t mbox_hide_headers_count;
 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);
@@ -45,8 +46,6 @@ int mbox_save(struct mailbox_transaction_context *t,
 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
index e237089588fee3344bf56d8ac7da7970b5bf0bf4..1e72ede3561a7c9ed237381b322ace42b2fbdd95 100644 (file)
@@ -5,12 +5,9 @@
 
 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);
@@ -31,7 +28,7 @@ struct mail_storage {
 
        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);
index 4990b1246945b43bafae43ca48affb4f3b6552da..57d70e0b7cebdc106b3bae7be85937584c1e9b2b 100644 (file)
@@ -69,33 +69,28 @@ void mail_storage_class_unregister(struct mail_storage *storage_class)
 }
 
 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;
        }
@@ -116,16 +111,13 @@ static struct mail_storage *mail_storage_autodetect(const char *data)
 }
 
 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) */
@@ -134,14 +126,11 @@ mail_storage_create_with_data(const char *data, const char *user,
 
        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;
@@ -260,10 +249,10 @@ int mail_storage_mailbox_rename(struct mail_storage *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 *
index d4ae1b90e18cbc63db4eac9dfc0a66eebe6f298a..2b50eac0c6e21494bf6d94a6c77637d4f9898207 100644 (file)
@@ -167,16 +167,12 @@ void mail_storage_class_unregister(struct mail_storage *storage_class);
    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);
 
@@ -205,11 +201,11 @@ int mail_storage_mailbox_rename(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 *
@@ -259,8 +255,7 @@ int mailbox_is_readonly(struct mailbox *box);
 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. */
index efe70f9221eb445d9efd17683b87bb9a175143c8..22d19dab58cd415a0f681a31e71431534efb2304 100644 (file)
@@ -52,12 +52,13 @@ static int _mailbox_rename(struct mail_storage *storage, const char *oldname,
 }
 
 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,
index 5ac6fef8115c19518c19acbc60c6a07bef519b8b..df8c0a20a0e0f91fc9518d62ddcd2d3d0efc1328 100644 (file)
@@ -130,8 +130,7 @@ static int main_init(void)
        }
         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')