Mercurial > dovecot > core-2.2
view src/lib-storage/mailbox-attribute.c @ 21389:59437f8764c6
global: Replaced all instances of memset(p, 0, sizeof(*p)) with the new i_zero() macro.
Used the following script:
C_FILES=`git ls-files *.c`
H_FILES=`git ls-files *.h`
for F in "$C_FILES $H_FILES"; do
echo "$F"
perl -p -i -e 's/safe_memset\(&\(?([^,]*)\)?,\s*0,\s*sizeof\(\g1\)\)/i_zero_safe(&$1)/g' $F
perl -p -i -e 's/safe_memset\(([^,]*),\s*0,\s*sizeof\(\*\g1\)\)/i_zero_safe($1)/g' $F
perl -p -i -e 's/memset\(&\(?([^,]*)\)?,\s*0,\s*sizeof\(\g1\)\)/i_zero(&$1)/g' $F
perl -p -i -e 's/memset\(([^,]*),\s*0,\s*sizeof\(\*\g1\)\)/i_zero($1)/g' $F
done
author | Stephan Bosch <stephan.bosch@dovecot.fi> |
---|---|
date | Wed, 11 Jan 2017 01:57:46 +0100 |
parents | ed5df0ed7aa1 |
children | 2e2563132d5f |
line wrap: on
line source
/* Copyright (c) 2003-2016 Dovecot authors, see the included COPYING file */ #include "lib.h" #include "array.h" #include "str.h" #include "istream.h" #include "mail-storage-private.h" #include "bsearch-insert-pos.h" #include "mailbox-attribute-internal.h" static ARRAY(struct mailbox_attribute_internal) mailbox_internal_attributes; static pool_t mailbox_attribute_pool; void mailbox_attributes_init(void) { mailbox_attribute_pool = pool_alloconly_create("mailbox attributes", 2048); i_array_init(&mailbox_internal_attributes, 32); /* internal mailbox attributes */ mailbox_attributes_internal_init(); } void mailbox_attributes_deinit(void) { pool_unref(&mailbox_attribute_pool); array_free(&mailbox_internal_attributes); } /* * Internal attributes */ static int mailbox_attribute_internal_cmp( const struct mailbox_attribute_internal *reg1, const struct mailbox_attribute_internal *reg2) { if (reg1->type != reg2->type) return (int)reg1->type - (int)reg2->type; return strcmp(reg1->key, reg2->key); } void mailbox_attribute_register_internal( const struct mailbox_attribute_internal *iattr) { struct mailbox_attribute_internal ireg; unsigned int insert_idx; (void)array_bsearch_insert_pos(&mailbox_internal_attributes, iattr, mailbox_attribute_internal_cmp, &insert_idx); ireg = *iattr; ireg.key = p_strdup(mailbox_attribute_pool, iattr->key); array_insert(&mailbox_internal_attributes, insert_idx, &ireg, 1); } void mailbox_attribute_register_internals( const struct mailbox_attribute_internal *iattrs, unsigned int count) { unsigned int i; for (i = 0; i < count; i++) mailbox_attribute_register_internal(&iattrs[i]); } static const struct mailbox_attribute_internal * mailbox_internal_attribute_get(enum mail_attribute_type type, const char *key) { const struct mailbox_attribute_internal *iattr; struct mailbox_attribute_internal dreg; unsigned int insert_idx; i_zero(&dreg); dreg.type = type; dreg.key = key; if (array_bsearch_insert_pos(&mailbox_internal_attributes, &dreg, mailbox_attribute_internal_cmp, &insert_idx)) { /* exact match */ return array_idx(&mailbox_internal_attributes, insert_idx); } if (insert_idx == 0) { /* not found at all */ return NULL; } iattr = array_idx(&mailbox_internal_attributes, insert_idx-1); if (strncmp(iattr->key, key, strlen(iattr->key)) != 0) { /* iattr isn't a prefix of key */ return NULL; } else if ((iattr->flags & MAIL_ATTRIBUTE_INTERNAL_FLAG_CHILDREN) != 0) { /* iattr is a prefix of key and it wants to handle the key */ return iattr; } else { return NULL; } } static void mailbox_internal_attributes_get(enum mail_attribute_type type, const char *prefix, bool have_dict, ARRAY_TYPE(const_string) *attrs) { const struct mailbox_attribute_internal *regs; struct mailbox_attribute_internal dreg; char *bare_prefix; size_t plen; unsigned int count, i; bare_prefix = t_strdup_noconst(prefix); plen = strlen(bare_prefix); if (plen > 0 && bare_prefix[plen-1] == '/') { bare_prefix[plen-1] = '\0'; plen--; } i_zero(&dreg); dreg.type = type; dreg.key = bare_prefix; (void)array_bsearch_insert_pos(&mailbox_internal_attributes, &dreg, mailbox_attribute_internal_cmp, &i); regs = array_get(&mailbox_internal_attributes, &count); for (; i < count; i++) { const char *key = regs[i].key; if (regs[i].type != type) return; if (plen > 0) { if (strncmp(key, bare_prefix, plen) != 0) return; if (key[plen] == '/') { /* remove prefix */ key += plen + 1; } else if (key[plen] == '\0') { /* list the key itself, so this becomes an empty key string. it's the same as how the dict backend works too. */ key += plen; } else { return; } } if (have_dict || regs[i].rank == MAIL_ATTRIBUTE_INTERNAL_RANK_AUTHORITY) array_append(attrs, &key, 1); } } /* * Attribute API */ static int mailbox_attribute_set_common(struct mailbox_transaction_context *t, enum mail_attribute_type type, const char *key, const struct mail_attribute_value *value) { const struct mailbox_attribute_internal *iattr; int ret; iattr = mailbox_internal_attribute_get(type, key); /* allow internal server attribute only for inbox */ if (iattr != NULL && !t->box->inbox_any && strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER, strlen(MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER)) == 0) iattr = NULL; /* handle internal attribute */ if (iattr != NULL) { switch (iattr->rank) { case MAIL_ATTRIBUTE_INTERNAL_RANK_DEFAULT: case MAIL_ATTRIBUTE_INTERNAL_RANK_OVERRIDE: /* notify about assignment */ if (iattr->set != NULL && iattr->set(t, key, value) < 0) return -1; break; case MAIL_ATTRIBUTE_INTERNAL_RANK_AUTHORITY: if (iattr->set == NULL) { mail_storage_set_error(t->box->storage, MAIL_ERROR_NOTPOSSIBLE, t_strdup_printf( "The /%s/%s attribute cannot be changed", (type == MAIL_ATTRIBUTE_TYPE_SHARED ? "shared" : "private"), key)); return -1; } /* assign internal attribute */ return iattr->set(t, key, value); default: i_unreached(); } } /* FIXME: v2.3 should move the internal_attribute to attribute_set() parameter (as flag). not done yet for API backwards compatibility */ t->internal_attribute = iattr != NULL && iattr->rank != MAIL_ATTRIBUTE_INTERNAL_RANK_AUTHORITY; ret = t->box->v.attribute_set(t, type, key, value); t->internal_attribute = FALSE; return ret; } int mailbox_attribute_set(struct mailbox_transaction_context *t, enum mail_attribute_type type, const char *key, const struct mail_attribute_value *value) { return mailbox_attribute_set_common(t, type, key, value); } int mailbox_attribute_unset(struct mailbox_transaction_context *t, enum mail_attribute_type type, const char *key) { struct mail_attribute_value value; i_zero(&value); return mailbox_attribute_set_common(t, type, key, &value); } int mailbox_attribute_value_to_string(struct mail_storage *storage, const struct mail_attribute_value *value, const char **str_r) { string_t *str; const unsigned char *data; size_t size; if (value->value_stream == NULL) { *str_r = value->value; return 0; } str = t_str_new(128); i_stream_seek(value->value_stream, 0); while (i_stream_read_data(value->value_stream, &data, &size, 0) > 0) { if (memchr(data, '\0', size) != NULL) { mail_storage_set_error(storage, MAIL_ERROR_PARAMS, "Attribute string value has NULs"); return -1; } str_append_n(str, data, size); i_stream_skip(value->value_stream, size); } if (value->value_stream->stream_errno != 0) { mail_storage_set_critical(storage, "read(%s) failed: %s", i_stream_get_name(value->value_stream), i_stream_get_error(value->value_stream)); return -1; } i_assert(value->value_stream->eof); *str_r = str_c(str); return 0; } static int mailbox_attribute_get_common(struct mailbox_transaction_context *t, enum mail_attribute_type type, const char *key, struct mail_attribute_value *value_r) { const struct mailbox_attribute_internal *iattr; int ret; iattr = mailbox_internal_attribute_get(type, key); /* allow internal server attributes only for the inbox */ if (iattr != NULL && !t->box->inbox_user && strncmp(key, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER, strlen(MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER)) == 0) iattr = NULL; /* internal attribute */ if (iattr != NULL) { switch (iattr->rank) { case MAIL_ATTRIBUTE_INTERNAL_RANK_OVERRIDE: if ((ret = iattr->get(t, key, value_r)) != 0) { if (ret < 0) return -1; value_r->flags |= MAIL_ATTRIBUTE_VALUE_FLAG_READONLY; return 1; } case MAIL_ATTRIBUTE_INTERNAL_RANK_DEFAULT: break; case MAIL_ATTRIBUTE_INTERNAL_RANK_AUTHORITY: if ((ret = iattr->get(t, key, value_r)) <= 0) return ret; value_r->flags |= MAIL_ATTRIBUTE_VALUE_FLAG_READONLY; return 1; default: i_unreached(); } } /* user entries - FIXME: v2.3 should move the internal_attribute to attribute_get() parameter (as flag). not done yet for API backwards compatibility */ t->internal_attribute = iattr != NULL && iattr->rank != MAIL_ATTRIBUTE_INTERNAL_RANK_AUTHORITY; ret = t->box->v.attribute_get(t, type, key, value_r); t->internal_attribute = FALSE; if (ret != 0) return ret; /* default entries */ if (iattr != NULL) { switch (iattr->rank) { case MAIL_ATTRIBUTE_INTERNAL_RANK_DEFAULT: if (iattr->get == NULL) ret = 0; else { if ((ret = iattr->get(t, key, value_r)) < 0) return ret; } if (ret > 0) { value_r->flags |= MAIL_ATTRIBUTE_VALUE_FLAG_READONLY; return 1; } case MAIL_ATTRIBUTE_INTERNAL_RANK_OVERRIDE: break; default: i_unreached(); } } return 0; } int mailbox_attribute_get(struct mailbox_transaction_context *t, enum mail_attribute_type type, const char *key, struct mail_attribute_value *value_r) { int ret; i_zero(value_r); if ((ret = mailbox_attribute_get_common(t, type, key, value_r)) <= 0) return ret; i_assert(value_r->value != NULL); return 1; } int mailbox_attribute_get_stream(struct mailbox_transaction_context *t, enum mail_attribute_type type, const char *key, struct mail_attribute_value *value_r) { int ret; i_zero(value_r); value_r->flags |= MAIL_ATTRIBUTE_VALUE_FLAG_INT_STREAMS; if ((ret = mailbox_attribute_get_common(t, type, key, value_r)) <= 0) return ret; i_assert(value_r->value != NULL || value_r->value_stream != NULL); return 1; } struct mailbox_attribute_internal_iter { struct mailbox_attribute_iter iter; ARRAY_TYPE(const_string) extra_attrs; unsigned int extra_attr_idx; struct mailbox_attribute_iter *real_iter; }; struct mailbox_attribute_iter * mailbox_attribute_iter_init(struct mailbox *box, enum mail_attribute_type type, const char *prefix) { struct mailbox_attribute_internal_iter *intiter; struct mailbox_attribute_iter *iter; ARRAY_TYPE(const_string) extra_attrs; const char *const *attr; bool have_dict; iter = box->v.attribute_iter_init(box, type, prefix); i_assert(iter->box != NULL); /* check which internal attributes may apply */ t_array_init(&extra_attrs, 4); have_dict = box->storage->set->mail_attribute_dict[0] != '\0'; mailbox_internal_attributes_get(type, prefix, have_dict, &extra_attrs); /* any extra internal attributes to add? */ if (array_count(&extra_attrs) == 0) { /* no */ return iter; } /* yes */ intiter = i_new(struct mailbox_attribute_internal_iter, 1); intiter->real_iter = iter; i_array_init(&intiter->extra_attrs, 4); /* copy relevant attributes */ array_foreach(&extra_attrs, attr) { /* skip internal server attributes unless we're interating inbox */ if (!box->inbox_any && strncmp(*attr, MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER, strlen(MAILBOX_ATTRIBUTE_PREFIX_DOVECOT_PVT_SERVER)) == 0) continue; array_append(&intiter->extra_attrs, attr, 1); } return &intiter->iter; } const char *mailbox_attribute_iter_next(struct mailbox_attribute_iter *iter) { struct mailbox_attribute_internal_iter *intiter; const char *const *attrs; unsigned int count, i; const char *result; if (iter->box != NULL) { /* no internal attributes to add */ return iter->box->v.attribute_iter_next(iter); } /* filter out duplicate results */ intiter = (struct mailbox_attribute_internal_iter *)iter; attrs = array_get(&intiter->extra_attrs, &count); while ((result = intiter->real_iter->box-> v.attribute_iter_next(intiter->real_iter)) != NULL) { for (i = 0; i < count; i++) { if (strcasecmp(attrs[i], result) == 0) break; } if (i == count) { /* return normally */ return result; } /* this attribute name is also to be returned as extra; skip now */ } /* return extra attributes at the end */ if (intiter->extra_attr_idx < count) return attrs[intiter->extra_attr_idx++]; return NULL; } int mailbox_attribute_iter_deinit(struct mailbox_attribute_iter **_iter) { struct mailbox_attribute_iter *iter = *_iter; struct mailbox_attribute_internal_iter *intiter; int ret; *_iter = NULL; if (iter->box != NULL) { /* not wrapped */ return iter->box->v.attribute_iter_deinit(iter); } /* wrapped */ intiter = (struct mailbox_attribute_internal_iter *)iter; ret = intiter->real_iter->box->v.attribute_iter_deinit(intiter->real_iter); array_free(&intiter->extra_attrs); i_free(intiter); return ret; }