]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: Store mailbox names unescaped in box-name header
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 11 Oct 2022 08:17:11 +0000 (11:17 +0300)
committerMarkus Valentin <markus.valentin@open-xchange.com>
Wed, 19 Oct 2022 06:34:45 +0000 (08:34 +0200)
This header is used when rebuilding mailbox list indexes with LAYOUT=index.
The escape character is currently hardcoded for LAYOUT=index, so this
couldn't have broken anything unless the hardcoded separator was changed.
Still, this was wrong/confusing behavior.

src/lib-storage/list/mailbox-list-index-backend.c
src/lib-storage/list/mailbox-list-index.c
src/lib-storage/list/mailbox-list-index.h

index 15dac411a57ae920d5b3e2c1e9fa34e6f52dacfa..e088f3ba0beb17ab3f6c4daf2dc8dad2cbdb1cf2 100644 (file)
@@ -554,14 +554,10 @@ static int index_list_mailbox_open(struct mailbox *box)
           we don't keep rewriting the name just in case some backend switches
           between separators when accessed different ways. */
 
-       /* Get the current mailbox name with \0 separators. */
-       char sep = mailbox_list_get_hierarchy_sep(box->list);
-       char *box_zerosep_name = t_strdup_noconst(box->name);
-       size_t box_name_len = strlen(box_zerosep_name);
-       for (size_t i = 0; i < box_name_len; i++) {
-               if (box_zerosep_name[i] == sep)
-                       box_zerosep_name[i] = '\0';
-       }
+       /* Get the current mailbox name with \0 separators and unesacped. */
+       size_t box_name_len;
+       const unsigned char *box_zerosep_name =
+               mailbox_name_hdr_encode(box->list, box->name, &box_name_len);
 
        /* Does it match what's in the header now? */
        mail_index_get_header_ext(box->view, box->box_name_hdr_ext_id,
@@ -585,14 +581,9 @@ static int index_list_mailbox_open(struct mailbox *box)
                (void)mail_index_transaction_commit(&trans);
        } else if (name_hdr_size > 0) {
                /* Mailbox name is corrupted. Rename it to the previous name. */
-               char sep = mailbox_list_get_hierarchy_sep(box->list);
-               char *newname = t_malloc0(name_hdr_size + 1);
-               memcpy(newname, name_hdr, name_hdr_size);
-               for (size_t i = 0; i < name_hdr_size; i++) {
-                       if (newname[i] == '\0')
-                               newname[i] = sep;
-               }
-
+               const char *newname =
+                       mailbox_name_hdr_decode_storage_name(
+                               box->list, name_hdr, name_hdr_size);
                index_list_rename_corrupted(box, newname);
        }
        return 0;
index 2ba8861d1c63c4ee1df12ebfba7bdd5d1fe1e4eb..5a38ca78bdd51594bd1bfccb46c903f7a4d6a874 100644 (file)
@@ -521,6 +521,70 @@ int mailbox_list_index_parse(struct mailbox_list *list,
        return 0;
 }
 
+const unsigned char *
+mailbox_name_hdr_encode(struct mailbox_list *list, const char *storage_name,
+                       size_t *name_len_r)
+{
+       const char sep[] = {
+               mailbox_list_get_hierarchy_sep(list),
+               '\0'
+       };
+       const char **name_parts =
+               (const char **)p_strsplit(unsafe_data_stack_pool, storage_name, sep);
+       if (list->set.storage_name_escape_char != '\0') {
+               for (unsigned int i = 0; name_parts[i] != NULL; i++) {
+                       mailbox_list_name_unescape(&name_parts[i],
+                               list->set.storage_name_escape_char);
+               }
+       }
+
+       string_t *str = t_str_new(64);
+       str_append(str, name_parts[0]);
+       for (unsigned int i = 1; name_parts[i] != NULL; i++) {
+               str_append_c(str, '\0');
+               str_append(str, name_parts[i]);
+       }
+       *name_len_r = str_len(str);
+       return str_data(str);
+}
+
+const char *
+mailbox_name_hdr_decode_storage_name(struct mailbox_list *list,
+                                    const unsigned char *name_hdr,
+                                    size_t name_hdr_size)
+{
+       const char list_sep = mailbox_list_get_hierarchy_sep(list);
+       const char escape_char = list->set.storage_name_escape_char;
+       string_t *storage_name = t_str_new(name_hdr_size);
+       while (name_hdr_size > 0) {
+               const unsigned char *p = memchr(name_hdr, '\0', name_hdr_size);
+               size_t name_part_len;
+               if (p == NULL) {
+                       name_part_len = name_hdr_size;
+                       name_hdr_size = 0;
+               } else {
+                       name_part_len = p - name_hdr;
+                       i_assert(name_hdr_size > name_part_len);
+                       name_hdr_size -= name_part_len + 1;
+               }
+
+               if (escape_char == '\0')
+                       str_append_data(storage_name, name_hdr, name_part_len);
+               else {
+                       const char *name_part =
+                               t_strndup(name_hdr, name_part_len);
+                       str_append(storage_name,
+                                  mailbox_list_escape_name_params(name_part,
+                                       "", '\0', list_sep, escape_char,
+                                       list->set.maildir_name));
+               }
+
+               if (p != NULL)
+                       name_hdr += name_part_len + 1;
+       }
+       return str_c(storage_name);
+}
+
 bool mailbox_list_index_need_refresh(struct mailbox_list_index *ilist,
                                     struct mail_index_view *view)
 {
index a2ca620c11f7498bf824a183c1159bcbd7bc2896..0109f5dcf619eae87d1c0c98990516e15fbcacb6 100644 (file)
@@ -162,6 +162,16 @@ void mailbox_list_index_node_get_path(const struct mailbox_list_index_node *node
 void mailbox_list_index_node_unlink(struct mailbox_list_index *ilist,
                                    struct mailbox_list_index_node *node);
 
+/* Return mailbox name encoded into box-name header. */
+const unsigned char *
+mailbox_name_hdr_encode(struct mailbox_list *list, const char *storage_name,
+                       size_t *name_len_r);
+/* Return mailbox name decoded from box-name header. */
+const char *
+mailbox_name_hdr_decode_storage_name(struct mailbox_list *list,
+                                    const unsigned char *name_hdr,
+                                    size_t name_hdr_size);
+
 int mailbox_list_index_index_open(struct mailbox_list *list);
 bool mailbox_list_index_need_refresh(struct mailbox_list_index *ilist,
                                     struct mail_index_view *view);