]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: mailbox_list_default_get_storage_name() - Escape ns_prefix/INBOX if...
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Thu, 14 Jan 2021 15:45:07 +0000 (17:45 +0200)
committeraki.tuomi <aki.tuomi@open-xchange.com>
Wed, 3 Feb 2021 09:04:22 +0000 (09:04 +0000)
If storage_name_escape_char is set, escape the "I" letter in the
storage_name if the namespace also has inbox=yes. This way it's possible to
distinguish between the actual INBOX and ns_prefix/INBOX.

src/lib-storage/mailbox-list.c
src/lib-storage/test-mailbox-list.c

index c6ec9587ce9b227e0a05722a91859e53eff2b44e..d846ccede869b2be7d8f4bbd3b46f0ee6d661f0e 100644 (file)
@@ -538,7 +538,7 @@ mailbox_list_name_unescape(const char **_name, char escape_char)
        *_name = str_c(str);
 }
 
-static void
+static bool
 mailbox_list_vname_prepare(struct mailbox_list *list, const char **_vname)
 {
        struct mail_namespace *ns = list->ns;
@@ -550,9 +550,20 @@ mailbox_list_vname_prepare(struct mailbox_list *list, const char **_vname)
                vname = "INBOX";
        } else if (ns->prefix_len > 0) {
                /* skip namespace prefix, except if this is INBOX */
-               if (strncmp(ns->prefix, vname, ns->prefix_len) == 0)
+               if (strncmp(ns->prefix, vname, ns->prefix_len) == 0) {
                        vname += ns->prefix_len;
-               else if (strncmp(ns->prefix, vname, ns->prefix_len-1) == 0 &&
+                       if (strcmp(vname, "INBOX") == 0 &&
+                           (list->ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0 &&
+                           list->set.storage_name_escape_char != '\0') {
+                               /* prefix/INBOX - this is troublesome, because
+                                  it ends up conflicting with the INBOX name.
+                                  Handle this in a bit kludgy way by escaping
+                                  the initial "I" character. */
+                               *_vname = t_strdup_printf("%c49NBOX",
+                                       list->set.storage_name_escape_char);
+                               return TRUE;
+                       }
+               } else if (strncmp(ns->prefix, vname, ns->prefix_len-1) == 0 &&
                         strlen(vname) == ns->prefix_len-1 &&
                         ns->prefix[ns->prefix_len-1] == mail_namespace_get_sep(ns)) {
                        /* trying to access the namespace prefix itself */
@@ -569,6 +580,7 @@ mailbox_list_vname_prepare(struct mailbox_list *list, const char **_vname)
                vname = "INBOX";
        }
        *_vname = vname;
+       return FALSE;
 }
 
 static const char *
@@ -606,7 +618,8 @@ const char *mailbox_list_default_get_storage_name(struct mailbox_list *list,
 {
        const char *prepared_name = vname;
 
-       mailbox_list_vname_prepare(list, &prepared_name);
+       if (mailbox_list_vname_prepare(list, &prepared_name))
+               return prepared_name;
        if (list->ns->type == MAIL_NAMESPACE_TYPE_SHARED &&
            (list->ns->flags & NAMESPACE_FLAG_AUTOCREATED) == 0) {
                /* Accessing shared namespace root. This is just the initial
index 32169faf5b1f644c20a3d4200032b9c10fddf2aa..e0d1401da889cb65c66e5cc94cfefcf832bcb0e4 100644 (file)
@@ -434,6 +434,11 @@ static void test_mailbox_list_get_names(void)
                  .storage_name = "inBox",
                  .ns_flags = NAMESPACE_FLAG_INBOX_USER,
                  .ns_prefix = "prefix/", .ns_sep = '/', .list_sep = '.' },
+               { .vname = "prefix/INBOX",
+                 .storage_name = "+49NBOX",
+                 .ns_flags = NAMESPACE_FLAG_INBOX_USER,
+                 .ns_prefix = "prefix/", .ns_sep = '/', .list_sep = '.',
+                 .storage_name_escape_char = '+' },
 
                /* Problematic cases - not reversible: */
                { .vname = "parent.child",