]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-storage: mailbox-list: index_list_delete_mailbox() - Support NO-NOSELECT
authorMarkus Valentin <markus.valentin@open-xchange.com>
Fri, 14 Jan 2022 07:04:09 +0000 (08:04 +0100)
committermartti.rannanjarvi <martti.rannanjarvi@open-xchange.com>
Wed, 26 Jan 2022 07:38:02 +0000 (07:38 +0000)
When NO-NOSELECT is configured delete parent mailboxes which are not
selectable or not existant when deleting child mailboxes.

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

index f8eefc5340a04f2ed95b881f182a214eb825a70b..fecad1db8e9b1ff9d56e6a7be8efa109e04a0c5d 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "hostpid.h"
+#include "str.h"
 #include "mail-index.h"
 #include "subscription-file.h"
 #include "mailbox-list-delete.h"
@@ -690,6 +691,50 @@ index_list_delete_entry(struct index_mailbox_list *list, const char *name,
        return ret;
 }
 
+static int
+index_list_try_delete_nonexistent_parent(struct mailbox_list *_list,
+                                        const char *name)
+{
+       struct index_mailbox_list *list =
+               container_of(_list, struct index_mailbox_list, list);
+       struct mailbox_list_index_node *node, *parent = NULL;
+       string_t *full_name;
+       const char *p;
+       char sep = mailbox_list_get_hierarchy_sep(_list);
+
+       if ((p = strrchr(name, sep)) == NULL) {
+               /* No occurrences of the hierarchy separator could be found
+                  in the name, so the mailbox has no parents. */
+               return 0;
+       }
+
+       /* Lookup parent node of of given "name" */
+       node = mailbox_list_index_lookup(_list, t_strdup_until(name, p));
+       full_name = t_str_new(32);
+
+       while (node != NULL) {
+               /* Attempt to delete all parent nodes that are NOSELECT or
+                  NONEXISTENT */
+               if (node->children != NULL)
+                       break;
+               if ((node->flags & MAILBOX_LIST_INDEX_FLAG_NOSELECT) != 0 ||
+                   (node->flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0) {
+                       /* The parent mailbox has no other children and is not
+                          existant or not selectable, delete it */
+                       str_truncate(full_name, 0);
+                       mailbox_list_index_node_get_path(node, sep, full_name);
+                       parent = node->parent;
+                       if (index_list_delete_entry(list, str_c(full_name), FALSE) < 0)
+                               return -1;
+               } else
+                       break;
+
+               /* If there is another parent attempt to delete it as well */
+               node = parent;
+       }
+       return 0;
+}
+
 static int
 index_list_delete_mailbox(struct mailbox_list *_list, const char *name)
 {
@@ -720,6 +765,9 @@ index_list_delete_mailbox(struct mailbox_list *_list, const char *name)
                if (index_list_delete_entry(list, name, TRUE) < 0)
                        return -1;
        }
+       if (_list->set.no_noselect && ret == 0)
+               (void)index_list_try_delete_nonexistent_parent(_list, name);
+
        return ret;
 }