bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "lib.h"
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen#include "ioloop.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "dict.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen#include "index-storage.h"
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenstruct index_storage_attribute_iter {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct mailbox_attribute_iter iter;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct dict_iterate_context *diter;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen char *prefix;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t prefix_len;
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen bool dict_disabled;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen};
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenstatic struct mail_namespace *
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenmail_user_find_attribute_namespace(struct mail_user *user)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen{
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_namespace *ns;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ns = mail_namespace_find_inbox(user->namespaces);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (ns != NULL)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return ns;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen for (ns = user->namespaces; ns != NULL; ns = ns->next) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (ns->type == MAIL_NAMESPACE_TYPE_PRIVATE)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return ns;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return NULL;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen}
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenstatic int
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenindex_storage_get_user_dict(struct mail_storage *err_storage,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_user *user, struct dict **dict_r)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen{
20e04227229970d148801c507946666e2a9bd838Timo Sirainen struct dict_settings dict_set;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_namespace *ns;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_storage *attr_storage;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen const char *error;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (user->_attr_dict != NULL) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen *dict_r = user->_attr_dict;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return 0;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (user->attr_dict_failed) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen mail_storage_set_internal_error(err_storage);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return -1;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ns = mail_user_find_attribute_namespace(user);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (ns == NULL) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen /* probably never happens? */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen mail_storage_set_error(err_storage, MAIL_ERROR_NOTPOSSIBLE,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen "Mailbox attributes not available for this mailbox");
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return -1;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen attr_storage = mail_namespace_get_default_storage(ns);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (*attr_storage->set->mail_attribute_dict == '\0') {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen mail_storage_set_error(err_storage, MAIL_ERROR_NOTPOSSIBLE,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen "Mailbox attributes not enabled");
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return -1;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&dict_set);
20e04227229970d148801c507946666e2a9bd838Timo Sirainen dict_set.username = user->username;
20e04227229970d148801c507946666e2a9bd838Timo Sirainen dict_set.base_dir = user->set->base_dir;
20e04227229970d148801c507946666e2a9bd838Timo Sirainen if (dict_init(attr_storage->set->mail_attribute_dict, &dict_set,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen &user->_attr_dict, &error) < 0) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen mail_storage_set_critical(err_storage,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen "mail_attribute_dict: dict_init(%s) failed: %s",
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen attr_storage->set->mail_attribute_dict, error);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen user->attr_dict_failed = TRUE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return -1;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen *dict_r = user->_attr_dict;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return 0;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen}
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenstatic int
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenindex_storage_get_dict(struct mailbox *box, enum mail_attribute_type type,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct dict **dict_r, const char **mailbox_prefix_r)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen struct mail_storage *storage = box->storage;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen struct mail_namespace *ns;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct mailbox_metadata metadata;
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen struct dict_settings set;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *error;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (mailbox_get_metadata(box, MAILBOX_METADATA_GUID, &metadata) < 0)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return -1;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen *mailbox_prefix_r = guid_128_to_string(metadata.guid);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen ns = mailbox_get_namespace(box);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (type == MAIL_ATTRIBUTE_TYPE_PRIVATE) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen /* private attributes are stored in user's own dict */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return index_storage_get_user_dict(storage, storage->user, dict_r);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen } else if (ns->user == ns->owner) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen /* user owns the mailbox. shared attributes are stored in
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen the same dict. */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return index_storage_get_user_dict(storage, storage->user, dict_r);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen } else if (ns->owner != NULL) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen /* accessing shared attribute of a shared mailbox.
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen use the owner's dict. */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen return index_storage_get_user_dict(storage, ns->owner, dict_r);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen /* accessing shared attributes of a public mailbox. no user owns it,
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen so use the storage's dict. */
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (storage->_shared_attr_dict != NULL) {
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen *dict_r = storage->_shared_attr_dict;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return 0;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen if (*storage->set->mail_attribute_dict == '\0') {
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen mail_storage_set_error(storage, MAIL_ERROR_NOTPOSSIBLE,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen "Mailbox attributes not enabled");
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return -1;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (storage->shared_attr_dict_failed) {
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen mail_storage_set_internal_error(storage);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return -1;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&set);
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen set.username = storage->user->username;
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen set.base_dir = storage->user->set->base_dir;
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen if (mail_user_get_home(storage->user, &set.home_dir) <= 0)
9346506a9f4dd9a6285fe8595588e73161849235Timo Sirainen set.home_dir = NULL;
20e04227229970d148801c507946666e2a9bd838Timo Sirainen if (dict_init(storage->set->mail_attribute_dict, &set,
20e04227229970d148801c507946666e2a9bd838Timo Sirainen &storage->_shared_attr_dict, &error) < 0) {
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen mail_storage_set_critical(storage,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen "mail_attribute_dict: dict_init(%s) failed: %s",
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen storage->set->mail_attribute_dict, error);
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen storage->shared_attr_dict_failed = TRUE;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return -1;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen *dict_r = storage->_shared_attr_dict;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return 0;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenstatic const char *
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenkey_get_prefixed(enum mail_attribute_type type, const char *mailbox_prefix,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *key)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen switch (type) {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen case MAIL_ATTRIBUTE_TYPE_PRIVATE:
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen return t_strconcat(DICT_PATH_PRIVATE, mailbox_prefix, "/",
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen key, NULL);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen case MAIL_ATTRIBUTE_TYPE_SHARED:
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen return t_strconcat(DICT_PATH_SHARED, mailbox_prefix, "/",
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen key, NULL);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen i_unreached();
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenstatic int
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenindex_storage_attribute_get_dict_trans(struct mailbox_transaction_context *t,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen enum mail_attribute_type type,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen struct dict_transaction_context **dtrans_r,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen const char **mailbox_prefix_r)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen{
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen struct dict_transaction_context **dtransp = NULL;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen struct dict *dict;
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen struct mailbox_metadata metadata;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen switch (type) {
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen case MAIL_ATTRIBUTE_TYPE_PRIVATE:
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen dtransp = &t->attr_pvt_trans;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen break;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen case MAIL_ATTRIBUTE_TYPE_SHARED:
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen dtransp = &t->attr_shared_trans;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen break;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen }
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen i_assert(dtransp != NULL);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen if (*dtransp != NULL) {
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen /* transaction already created */
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen if (mailbox_get_metadata(t->box, MAILBOX_METADATA_GUID,
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen &metadata) < 0)
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen return -1;
668f92ab0ef7aa42445716d653c5673ed874ab65Timo Sirainen *mailbox_prefix_r = guid_128_to_string(metadata.guid);
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen *dtrans_r = *dtransp;
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen return 0;
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen }
4a9bbf81af2eba25653bbc4f744cc35e7bc9bb34Timo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (index_storage_get_dict(t->box, type, &dict, mailbox_prefix_r) < 0)
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return -1;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen *dtransp = *dtrans_r = dict_transaction_begin(dict);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen return 0;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen}
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenint index_storage_attribute_set(struct mailbox_transaction_context *t,
6cc4cce2078aca138fbce19305e69e77edcee614Timo Sirainen enum mail_attribute_type type, const char *key,
bd6a8056771b6150685dea319ab5a94e021d17f1Josef 'Jeff' Sipek const struct mail_attribute_value *value)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct dict_transaction_context *dtrans;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *mailbox_prefix;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen bool pvt = type == MAIL_ATTRIBUTE_TYPE_PRIVATE;
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen time_t ts = value->last_change != 0 ? value->last_change : ioloop_time;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen int ret = 0;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen if (index_storage_attribute_get_dict_trans(t, type, &dtrans,
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen &mailbox_prefix) < 0)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return -1;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen T_BEGIN {
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen const char *prefixed_key =
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen key_get_prefixed(type, mailbox_prefix, key);
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen const char *value_str;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen if (mailbox_attribute_value_to_string(t->box->storage, value,
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen &value_str) < 0) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen ret = -1;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen } else if (value_str != NULL) {
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen dict_set(dtrans, prefixed_key, value_str);
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen mail_index_attribute_set(t->itrans, pvt, key,
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen ts, strlen(value_str));
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen } else {
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen dict_unset(dtrans, prefixed_key);
238812433b4f7965fd662dce0f4efccb092630a8Timo Sirainen mail_index_attribute_unset(t->itrans, pvt, key, ts);
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen } T_END;
41e51b972f02e8b16c19fab9160294ea0a07c343Timo Sirainen return ret;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomiint index_storage_attribute_get(struct mailbox *box,
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen enum mail_attribute_type type, const char *key,
bd6a8056771b6150685dea319ab5a94e021d17f1Josef 'Jeff' Sipek struct mail_attribute_value *value_r)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct dict *dict;
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen const char *mailbox_prefix, *error;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen int ret;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(value_r);
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi if (index_storage_get_dict(box, type, &dict, &mailbox_prefix) < 0)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return -1;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen ret = dict_lookup(dict, pool_datastack_create(),
9c32eb25e7b90e753e0cd7b30f7a70e8ca9121d9Timo Sirainen key_get_prefixed(type, mailbox_prefix, key),
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen &value_r->value, &error);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (ret < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(box,
b5052fbfdbc2678cc8f12899afe55c998f43b740Timo Sirainen "Failed to set attribute %s: %s", key, error);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return -1;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return ret;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenstruct mailbox_attribute_iter *
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenindex_storage_attribute_iter_init(struct mailbox *box,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen enum mail_attribute_type type,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *prefix)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct index_storage_attribute_iter *iter;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct dict *dict;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *mailbox_prefix;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen iter = i_new(struct index_storage_attribute_iter, 1);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen iter->iter.box = box;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen if (index_storage_get_dict(box, type, &dict, &mailbox_prefix) < 0) {
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen if (mailbox_get_last_mail_error(box) == MAIL_ERROR_NOTPOSSIBLE)
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen iter->dict_disabled = TRUE;
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen } else {
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen iter->prefix = i_strdup(key_get_prefixed(type, mailbox_prefix,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen prefix));
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen iter->prefix_len = strlen(iter->prefix);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen iter->diter = dict_iterate_init(dict, iter->prefix,
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen DICT_ITERATE_FLAG_RECURSE |
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen DICT_ITERATE_FLAG_NO_VALUE);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return &iter->iter;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenconst char *
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenindex_storage_attribute_iter_next(struct mailbox_attribute_iter *_iter)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct index_storage_attribute_iter *iter =
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen (struct index_storage_attribute_iter *)_iter;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen const char *key, *value;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen if (iter->diter == NULL || !dict_iterate(iter->diter, &key, &value))
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return NULL;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen i_assert(strncmp(key, iter->prefix, iter->prefix_len) == 0);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen key += iter->prefix_len;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return key;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainenint index_storage_attribute_iter_deinit(struct mailbox_attribute_iter *_iter)
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen{
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen struct index_storage_attribute_iter *iter =
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen (struct index_storage_attribute_iter *)_iter;
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen const char *error;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen int ret;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen if (iter->diter == NULL) {
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen ret = iter->dict_disabled ? 0 : -1;
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen } else {
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen if ((ret = dict_iterate_deinit(&iter->diter, &error)) < 0) {
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi mailbox_set_critical(_iter->box,
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen "dict_iterate(%s) failed: %s",
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen iter->prefix, error);
055389c58fa3915e12fb4e72ec86782ce77c5c72Timo Sirainen }
ed157532dafb9dc25f98fda89bc1e324c3926898Timo Sirainen }
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen i_free(iter->prefix);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen i_free(iter);
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen return ret;
8bad545017a5c2b69cf6fa06a50763b3b68fb161Timo Sirainen}