mailbox-attribute.c revision 3858a7a5da361c35f1e6e50c8e3214dc0cf379d6
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina/* Copyright (c) 2003-2016 Dovecot authors, see the included COPYING file */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinastatic ARRAY(struct mailbox_attribute_internal) mailbox_internal_attributes;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina pool_alloconly_create("mailbox attributes", 2048);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina i_array_init(&mailbox_internal_attributes, 32);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* internal mailbox attributes */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina * Internal attributes
769347ad4d35d43488eb98f980143495b0db415dStef Walter (void)array_bsearch_insert_pos(&mailbox_internal_attributes,
769347ad4d35d43488eb98f980143495b0db415dStef Walter iattr, mailbox_attribute_internal_cmp, &insert_idx);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ireg.key = p_strdup(mailbox_attribute_pool, iattr->key);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina array_insert(&mailbox_internal_attributes, insert_idx, &ireg, 1);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const struct mailbox_attribute_internal *iattrs, unsigned int count)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina unsigned int i;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina for (i = 0; i < count; i++)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina mailbox_attribute_register_internal(&iattrs[i]);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinastatic const struct mailbox_attribute_internal *
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinamailbox_internal_attribute_get(enum mail_attribute_type type,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const char *key)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const struct mailbox_attribute_internal *iattr;
65976ea5e9767bfaced81dfb97dc87d59f50b57eSimo Sorce unsigned int insert_idx;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (array_bsearch_insert_pos(&mailbox_internal_attributes,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* exact match */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return array_idx(&mailbox_internal_attributes, insert_idx);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* not found at all */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina iattr = array_idx(&mailbox_internal_attributes, insert_idx-1);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (strncmp(iattr->key, key, strlen(iattr->key)) != 0) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* iattr isn't a prefix of key */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina } else if ((iattr->flags & MAIL_ATTRIBUTE_INTERNAL_FLAG_CHILDREN) != 0) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* iattr is a prefix of key and it wants to handle the key */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinamailbox_internal_attributes_get(enum mail_attribute_type type,
07e941c1bbdc752142bbd3b838c540bc7ecd0ed7Stef Walter const char *prefix, bool have_dict, ARRAY_TYPE(const_string) *attrs)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const struct mailbox_attribute_internal *regs;
7c9fe57ad82747a32721ca0a08c5569282f3e0c4Pavel Březina unsigned int count, i;
2a25713afc6beefb11a799903a43f695c5d7a4f9Adam Tkac (void)array_bsearch_insert_pos(&mailbox_internal_attributes,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina regs = array_get(&mailbox_internal_attributes, &count);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina for (; i < count; i++) {
2a25713afc6beefb11a799903a43f695c5d7a4f9Adam Tkac /* remove prefix */
2a25713afc6beefb11a799903a43f695c5d7a4f9Adam Tkac /* list the key itself, so this becomes an
2a25713afc6beefb11a799903a43f695c5d7a4f9Adam Tkac empty key string. it's the same as how the
2a25713afc6beefb11a799903a43f695c5d7a4f9Adam Tkac dict backend works too. */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (have_dict || regs[i].rank == MAIL_ATTRIBUTE_INTERNAL_RANK_AUTHORITY)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina * Attribute API
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinamailbox_attribute_set_common(struct mailbox_transaction_context *t,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina enum mail_attribute_type type, const char *key,
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina iattr = mailbox_internal_attribute_get(type, key);
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* allow internal server attribute only for inbox */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov if (iattr != NULL && !t->box->inbox_any &&
6f8ae17869f4f8a1496e3f171ae6b5c11af1845cPavel Březina strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER,
c9aab1c04c399ca2d1abef74f6df22ced34983dcPavel Březina strlen(MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER)) == 0)
909a86af4eb99f5d311d7136cab78dca535ae304Sumit Bose /* handle internal attribute */
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov /* notify about assignment */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina if (iattr->set != NULL && iattr->set(t, key, value) < 0)
6f8ae17869f4f8a1496e3f171ae6b5c11af1845cPavel Březina mail_storage_set_error(t->box->storage, MAIL_ERROR_NOTPOSSIBLE, t_strdup_printf(
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina "The /%s/%s attribute cannot be changed",
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina (type == MAIL_ATTRIBUTE_TYPE_SHARED ? "shared" : "private"), key));
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* assign internal attribute */
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina /* FIXME: v2.3 should move the internal_attribute to attribute_set()
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina parameter (as flag). not done yet for API backwards compatibility */
ac40d2f2b2b2fc35c95389f5e28febd580bd2b7aJakub Hrozek iattr->rank != MAIL_ATTRIBUTE_INTERNAL_RANK_AUTHORITY;
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina ret = t->box->v.attribute_set(t, type, key, value);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinaint mailbox_attribute_set(struct mailbox_transaction_context *t,
458f5245dd5130d12666cce6faf8ef1ec7f80169Pavel Reichl enum mail_attribute_type type, const char *key,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return mailbox_attribute_set_common(t, type, key, value);
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březinaint mailbox_attribute_unset(struct mailbox_transaction_context *t,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina enum mail_attribute_type type, const char *key)
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina return mailbox_attribute_set_common(t, type, key, &value);
9e2c64c6d4f5560e27207193efea6536a566865eMichal Zidekint mailbox_attribute_value_to_string(struct mail_storage *storage,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina const char **str_r)
3f9e2c24dbc14b2eafbe4f5a5ee16fe9af3c3f75Jakub Hrozek const unsigned char *data;
a3c8390d19593b1e5277d95bfb4ab206d4785150Nikolai Kondrashov while (i_stream_read_more(value->value_stream, &data, &size) > 0) {
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina mail_storage_set_error(storage, MAIL_ERROR_PARAMS,
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina "Attribute string value has NULs");
2827b0d03f7b6bafa504d22a5d7ca39cbda048b3Pavel Březina mail_storage_set_critical(storage, "read(%s) failed: %s",
int ret;
if (ret < 0)
return ret;
i_unreached();
if (ret != 0)
return ret;
ret = 0;
return ret;
if (ret > 0) {
i_unreached();
int ret;
return ret;
int ret;
return ret;
struct mailbox_attribute_internal_iter {
unsigned int extra_attr_idx;
struct mailbox_attribute_iter *
const char *const *attr;
bool have_dict;
return iter;
const char *const *attrs;
unsigned int count, i;
const char *result;
for (i = 0; i < count; i++) {
if (i == count) {
return result;
return NULL;
int ret;
return ret;