summaryrefslogtreecommitdiffstats
path: root/src/lib-storage/list/mailbox-list-notify-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-storage/list/mailbox-list-notify-tree.c')
-rw-r--r--src/lib-storage/list/mailbox-list-notify-tree.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/src/lib-storage/list/mailbox-list-notify-tree.c b/src/lib-storage/list/mailbox-list-notify-tree.c
new file mode 100644
index 0000000..6152dbb
--- /dev/null
+++ b/src/lib-storage/list/mailbox-list-notify-tree.c
@@ -0,0 +1,131 @@
+/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "str.h"
+#include "mail-index.h"
+#include "mail-storage.h"
+#include "mailbox-list-private.h"
+#include "mailbox-list-index.h"
+#include "mailbox-list-notify-tree.h"
+
+struct mailbox_list_notify_tree {
+ struct mailbox_list *list;
+ struct mailbox_tree_context *mailboxes;
+
+ struct mail_index_view *view;
+ bool failed;
+};
+
+static void
+mailbox_list_notify_node_get_status(struct mailbox_list_notify_tree *tree,
+ struct mailbox_notify_node *nnode)
+{
+ struct mailbox_status status;
+ const char *reason;
+ uint32_t seq;
+
+ if (!mail_index_lookup_seq(tree->view, nnode->index_uid, &seq))
+ return;
+
+ i_zero(&status);
+ (void)mailbox_list_index_status(tree->list, tree->view, seq,
+ STATUS_UIDVALIDITY | STATUS_UIDNEXT | STATUS_MESSAGES |
+ STATUS_UNSEEN | STATUS_HIGHESTMODSEQ, &status, nnode->guid,
+ NULL, &reason);
+ nnode->uidvalidity = status.uidvalidity;
+ nnode->uidnext = status.uidnext;
+ nnode->messages = status.messages;
+ nnode->unseen = status.unseen;
+ nnode->highest_modseq = status.highest_modseq;
+}
+
+static void
+mailbox_list_notify_node_build(struct mailbox_list_notify_tree *tree,
+ struct mailbox_list_index_node *index_node,
+ string_t *path)
+{
+ struct mailbox_node *node;
+ struct mailbox_notify_node *nnode;
+ size_t prefix_len;
+ bool created;
+
+ str_append(path, index_node->raw_name);
+
+ node = mailbox_tree_get(tree->mailboxes, str_c(path), &created);
+ nnode = (struct mailbox_notify_node *)node;
+ nnode->index_uid = index_node->uid;
+
+ if ((index_node->flags & MAILBOX_LIST_INDEX_FLAG_NONEXISTENT) != 0)
+ node->flags = MAILBOX_NONEXISTENT;
+ else if ((index_node->flags & MAILBOX_LIST_INDEX_FLAG_NOSELECT) != 0)
+ node->flags = MAILBOX_NOSELECT;
+ else {
+ node->flags = 0;
+ mailbox_list_notify_node_get_status(tree, nnode);
+ }
+ if ((index_node->flags & MAILBOX_LIST_INDEX_FLAG_NOINFERIORS) != 0)
+ node->flags |= MAILBOX_NOINFERIORS;
+
+ if (index_node->children != NULL) {
+ str_append_c(path, mailbox_list_get_hierarchy_sep(tree->list));
+ prefix_len = str_len(path);
+ index_node = index_node->children;
+ for (; index_node != NULL; index_node = index_node->next) {
+ str_truncate(path, prefix_len);
+ mailbox_list_notify_node_build(tree, index_node, path);
+ }
+ }
+}
+
+static void
+mailbox_list_notify_tree_build(struct mailbox_list_notify_tree *tree)
+{
+ struct mailbox_list_index *ilist = INDEX_LIST_CONTEXT_REQUIRE(tree->list);
+ struct mailbox_list_index_node *index_node;
+ string_t *path = t_str_new(128);
+
+ if (mailbox_list_index_refresh(tree->list) < 0)
+ tree->failed = TRUE;
+
+ tree->view = mail_index_view_open(ilist->index);
+ index_node = ilist->mailbox_tree;
+ for (; index_node != NULL; index_node = index_node->next) {
+ str_truncate(path, 0);
+ mailbox_list_notify_node_build(tree, index_node, path);
+ }
+ mail_index_view_close(&tree->view);
+}
+
+struct mailbox_list_notify_tree *
+mailbox_list_notify_tree_init(struct mailbox_list *list)
+{
+ struct mailbox_list_notify_tree *tree;
+
+ tree = i_new(struct mailbox_list_notify_tree, 1);
+ tree->list = list;
+ tree->mailboxes =
+ mailbox_tree_init_size(mailbox_list_get_hierarchy_sep(list),
+ sizeof(struct mailbox_notify_node));
+ mailbox_list_notify_tree_build(tree);
+ return tree;
+}
+
+void mailbox_list_notify_tree_deinit(struct mailbox_list_notify_tree **_tree)
+{
+ struct mailbox_list_notify_tree *tree = *_tree;
+
+ *_tree = NULL;
+
+ mailbox_tree_deinit(&tree->mailboxes);
+ i_free(tree);
+}
+
+struct mailbox_notify_node *
+mailbox_list_notify_tree_lookup(struct mailbox_list_notify_tree *tree,
+ const char *storage_name)
+{
+ struct mailbox_node *node;
+
+ node = mailbox_tree_lookup(tree->mailboxes, storage_name);
+ return (struct mailbox_notify_node *)node;
+}