diff options
Diffstat (limited to 'src/lib-storage/list/mailbox-list-notify-tree.c')
-rw-r--r-- | src/lib-storage/list/mailbox-list-notify-tree.c | 131 |
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; +} |