dovecot-2.2: mail-storage: Added registration API for builtin ma...

dovecot at dovecot.org dovecot at dovecot.org
Mon Sep 7 13:40:38 UTC 2015


details:   http://hg.dovecot.org/dovecot-2.2/rev/a2e28ee1a673
changeset: 19101:a2e28ee1a673
user:      Stephan Bosch <stephan at rename-it.nl>
date:      Sat Apr 25 11:42:06 2015 +0200
description:
mail-storage: Added registration API for builtin mailbox attributes.

diffstat:

 src/lib-storage/mail-storage.c              |    2 +
 src/lib-storage/mailbox-attribute-private.h |    3 +
 src/lib-storage/mailbox-attribute.c         |  312 +++++++++++++++++++++++++++-
 src/lib-storage/mailbox-attribute.h         |   44 +++
 4 files changed, 350 insertions(+), 11 deletions(-)

diffs (truncated from 463 to 300 lines):

diff -r ae159e69cb6f -r a2e28ee1a673 src/lib-storage/mail-storage.c
--- a/src/lib-storage/mail-storage.c	Mon Sep 07 15:07:55 2015 +0300
+++ b/src/lib-storage/mail-storage.c	Sat Apr 25 11:42:06 2015 +0200
@@ -45,6 +45,7 @@
 void mail_storage_init(void)
 {
 	dsasl_clients_init();
+	mailbox_attributes_init();
 	mailbox_lists_init();
 	mail_storage_hooks_init();
 	i_array_init(&mail_storage_classes, 8);
@@ -60,6 +61,7 @@
 		array_free(&mail_storage_classes);
 	mail_storage_hooks_deinit();
 	mailbox_lists_deinit();
+	mailbox_attributes_deinit();
 	dsasl_clients_deinit();
 }
 
diff -r ae159e69cb6f -r a2e28ee1a673 src/lib-storage/mailbox-attribute-private.h
--- a/src/lib-storage/mailbox-attribute-private.h	Mon Sep 07 15:07:55 2015 +0300
+++ b/src/lib-storage/mailbox-attribute-private.h	Sat Apr 25 11:42:06 2015 +0200
@@ -5,6 +5,9 @@
 	struct mailbox *box;
 };
 
+void mailbox_attributes_init(void);
+void mailbox_attributes_deinit(void);
+
 int mailbox_attribute_value_to_string(struct mail_storage *storage,
 				      const struct mail_attribute_value *value,
 				      const char **str_r);
diff -r ae159e69cb6f -r a2e28ee1a673 src/lib-storage/mailbox-attribute.c
--- a/src/lib-storage/mailbox-attribute.c	Mon Sep 07 15:07:55 2015 +0300
+++ b/src/lib-storage/mailbox-attribute.c	Sat Apr 25 11:42:06 2015 +0200
@@ -1,19 +1,168 @@
 /* Copyright (c) 2003-2015 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"
+
+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);
+}
+
+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);
+}
+
+static const struct mailbox_attribute_internal *
+mailbox_internal_attribute_get(enum mail_attribute_type type,
+			       const char *key)
+{
+	struct mailbox_attribute_internal dreg;
+	unsigned int insert_idx;
+
+	memset(&dreg, 0, sizeof(dreg));
+	dreg.type = type;	
+	dreg.key = key;
+
+	if (!array_bsearch_insert_pos(&mailbox_internal_attributes,
+				      &dreg, mailbox_attribute_internal_cmp,
+				      &insert_idx))
+		return NULL;
+
+	return array_idx(&mailbox_internal_attributes, insert_idx);
+}
+
+static void
+mailbox_internal_attributes_get(enum mail_attribute_type type,
+	const char *prefix, 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--;
+	}
+
+	memset(&dreg, 0, sizeof(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] != '/' && strlen(key) != plen)
+				return;
+			/* remove prefix */
+			key += plen + 1;
+		}
+
+		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;
+	
+	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, value) < 0)
+				return -1;
+			break;
+		case MAIL_ATTRIBUTE_INTERNAL_RANK_AUTHORITY:
+			if (iattr->set == NULL) {
+				mail_storage_set_error(t->box->storage, MAIL_ERROR_PARAMS, 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, value);
+		default:
+			i_unreached();
+		}
+	}
+	
+	return t->box->v.attribute_set(t, type, key, value);
+}
+
 int mailbox_attribute_set(struct mailbox_transaction_context *t,
 			  enum mail_attribute_type type, const char *key,
 			  const struct mail_attribute_value *value)
 {
-	return t->box->v.attribute_set(t, type, key, value);
+	return mailbox_attribute_set_common(t, type, key, value);
 }
 
 int mailbox_attribute_unset(struct mailbox_transaction_context *t,
@@ -22,7 +171,7 @@
 	struct mail_attribute_value value;
 
 	memset(&value, 0, sizeof(value));
-	return t->box->v.attribute_set(t, type, key, &value);
+	return mailbox_attribute_set_common(t, type, key, &value);
 }
 
 int mailbox_attribute_value_to_string(struct mail_storage *storage,
@@ -59,14 +208,74 @@
 	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, 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, value_r)) <= 0)
+				return ret;
+			value_r->flags |= MAIL_ATTRIBUTE_VALUE_FLAG_READONLY;
+			return 1;
+		default:
+			i_unreached();
+		}
+	}
+
+	/* user entries */
+	if ((ret = t->box->v.attribute_get(t, type, key, value_r)) != 0)
+		return ret;
+
+	/* default entries */
+	if (iattr != NULL) {
+		switch (iattr->rank) {
+		case MAIL_ATTRIBUTE_INTERNAL_RANK_DEFAULT:		
+			if ((ret = iattr->get(t, 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;
-
 	memset(value_r, 0, sizeof(*value_r));
-	if ((ret = t->box->v.attribute_get(t, type, key, value_r)) <= 0)
+	if ((ret = mailbox_attribute_get_common(t, type, key, value_r)) <= 0)
 		return ret;
 	i_assert(value_r->value != NULL);
 	return 1;
@@ -80,29 +289,110 @@
 
 	memset(value_r, 0, sizeof(*value_r));
 	value_r->flags |= MAIL_ATTRIBUTE_VALUE_FLAG_INT_STREAMS;
-	if ((ret = t->box->v.attribute_get(t, type, key, value_r)) <= 0)
+	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;


More information about the dovecot-cvs mailing list