From: Timo Sirainen Date: Tue, 11 Oct 2022 08:17:11 +0000 (+0300) Subject: lib-storage: Store mailbox names unescaped in box-name header X-Git-Tag: 2.3.20~42 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=efafbfaad680dcfe52a5ece7b6ca58696700a51e;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: Store mailbox names unescaped in box-name header 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. --- diff --git a/src/lib-storage/list/mailbox-list-index-backend.c b/src/lib-storage/list/mailbox-list-index-backend.c index 15dac411a5..e088f3ba0b 100644 --- a/src/lib-storage/list/mailbox-list-index-backend.c +++ b/src/lib-storage/list/mailbox-list-index-backend.c @@ -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; diff --git a/src/lib-storage/list/mailbox-list-index.c b/src/lib-storage/list/mailbox-list-index.c index 2ba8861d1c..5a38ca78bd 100644 --- a/src/lib-storage/list/mailbox-list-index.c +++ b/src/lib-storage/list/mailbox-list-index.c @@ -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) { diff --git a/src/lib-storage/list/mailbox-list-index.h b/src/lib-storage/list/mailbox-list-index.h index a2ca620c11..0109f5dcf6 100644 --- a/src/lib-storage/list/mailbox-list-index.h +++ b/src/lib-storage/list/mailbox-list-index.h @@ -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);