dovecot-2.2: lib-storage: Added MAILBOX_METADATA_BACKEND_NAMESPACE

dovecot at dovecot.org dovecot at dovecot.org
Sun Sep 2 19:53:03 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/5f313144c481
changeset: 15014:5f313144c481
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Sep 02 19:52:31 2012 +0300
description:
lib-storage: Added MAILBOX_METADATA_BACKEND_NAMESPACE

diffstat:

 src/lib-storage/index/imapc/imapc-storage.c |  97 +++++++++++++++++++++++++++++
 src/lib-storage/index/imapc/imapc-storage.h |   9 ++
 src/lib-storage/index/index-status.c        |   7 +-
 src/lib-storage/mail-storage.h              |   9 ++-
 4 files changed, 120 insertions(+), 2 deletions(-)

diffs (229 lines):

diff -r fba15565c360 -r 5f313144c481 src/lib-storage/index/imapc/imapc-storage.c
--- a/src/lib-storage/index/imapc/imapc-storage.c	Sun Sep 02 19:32:55 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.c	Sun Sep 02 19:52:31 2012 +0300
@@ -52,6 +52,8 @@
 
 static void imapc_untagged_status(const struct imapc_untagged_reply *reply,
 				  struct imapc_storage *storage);
+static void imapc_untagged_namespace(const struct imapc_untagged_reply *reply,
+				     struct imapc_storage *storage);
 
 static bool
 imap_resp_text_code_parse(const char *str, enum mail_error *error_r)
@@ -255,12 +257,15 @@
 	storage->list->storage = storage;
 	storage->client = imapc_client_init(&set);
 
+	p_array_init(&storage->remote_namespaces, _storage->pool, 4);
 	p_array_init(&storage->untagged_callbacks, _storage->pool, 16);
 	imapc_client_register_untagged(storage->client,
 				       imapc_storage_untagged_cb, storage);
 	imapc_list_register_callbacks(storage->list);
 	imapc_storage_register_untagged(storage, "STATUS",
 					imapc_untagged_status);
+	imapc_storage_register_untagged(storage, "NAMESPACE",
+					imapc_untagged_namespace);
 	/* connect to imap server and get the hierarchy separator. */
 	if (imapc_storage_get_hierarchy_sep(storage, error_r) < 0) {
 		imapc_client_deinit(&storage->client);
@@ -600,6 +605,40 @@
 	}
 }
 
+static void imapc_untagged_namespace(const struct imapc_untagged_reply *reply,
+				     struct imapc_storage *storage)
+{
+	static enum mail_namespace_type ns_types[] = {
+		MAIL_NAMESPACE_TYPE_PRIVATE,
+		MAIL_NAMESPACE_TYPE_SHARED,
+		MAIL_NAMESPACE_TYPE_PUBLIC
+	};
+	struct imapc_namespace *ns;
+	const struct imap_arg *list, *list2;
+	const char *prefix, *sep;
+	unsigned int i;
+
+	array_clear(&storage->remote_namespaces);
+	for (i = 0; i < N_ELEMENTS(ns_types); i++) {
+		if (reply->args[i].type == IMAP_ARG_NIL)
+			continue;
+		if (!imap_arg_get_list(&reply->args[i], &list))
+			break;
+
+		for (; list->type != IMAP_ARG_EOL; list++) {
+			if (!imap_arg_get_list(list, &list2) ||
+			    !imap_arg_get_astring(&list2[0], &prefix) ||
+			    !imap_arg_get_nstring(&list2[1], &sep))
+				break;
+
+			ns = array_append_space(&storage->remote_namespaces);
+			ns->prefix = p_strdup(storage->storage.pool, prefix);
+			ns->separator = sep == NULL ? '\0' : sep[0];
+			ns->type = ns_types[i];
+		}
+	}
+}
+
 static void imapc_mailbox_get_selected_status(struct imapc_mailbox *mbox,
 					      enum mailbox_status_items items,
 					      struct mailbox_status *status_r)
@@ -664,10 +703,58 @@
 	return sctx.ret;
 }
 
+static int imapc_mailbox_get_namespaces(struct imapc_storage *storage)
+{
+	enum imapc_capability capa;
+	struct imapc_command *cmd;
+	struct imapc_simple_context sctx;
+
+	if (storage->namespaces_requested)
+		return 0;
+
+	capa = imapc_client_get_capabilities(storage->client);
+	if ((capa & IMAPC_CAPABILITY_NAMESPACE) == 0) {
+		/* NAMESPACE capability not supported */
+		return 0;
+	}
+
+	imapc_simple_context_init(&sctx, storage);
+	cmd = imapc_client_cmd(storage->client,
+			       imapc_simple_callback, &sctx);
+	imapc_command_send(cmd, "NAMESPACE");
+	imapc_simple_run(&sctx);
+
+	if (sctx.ret < 0)
+		return -1;
+	storage->namespaces_requested = TRUE;
+	return 0;
+}
+
+static const struct imapc_namespace *
+imapc_namespace_find_mailbox(struct imapc_storage *storage, const char *name)
+{
+	const struct imapc_namespace *ns, *best_ns = NULL;
+	unsigned int best_len = -1U, len;
+
+	array_foreach(&storage->remote_namespaces, ns) {
+		len = strlen(ns->prefix);
+		if (strncmp(ns->prefix, name, len) == 0) {
+			if (best_len > len) {
+				best_ns = ns;
+				best_len = len;
+			}
+		}
+	}
+	return best_ns;
+}
+
 static int imapc_mailbox_get_metadata(struct mailbox *box,
 				      enum mailbox_metadata_items items,
 				      struct mailbox_metadata *metadata_r)
 {
+	struct imapc_mailbox *mbox = (struct imapc_mailbox *)box;
+	const struct imapc_namespace *ns;
+
 	if (index_mailbox_get_metadata(box, items, metadata_r) < 0)
 		return -1;
 	if ((items & MAILBOX_METADATA_GUID) != 0) {
@@ -675,6 +762,16 @@
 		   FIXME: if indexes are enabled, keep this there. */
 		mail_generate_guid_128_hash(box->name, metadata_r->guid);
 	}
+	if ((items & MAILBOX_METADATA_BACKEND_NAMESPACE) != 0) {
+		if (imapc_mailbox_get_namespaces(mbox->storage) < 0)
+			return -1;
+
+		ns = imapc_namespace_find_mailbox(mbox->storage, box->name);
+		if (ns != NULL) {
+			metadata_r->backend_ns_prefix = ns->prefix;
+			metadata_r->backend_ns_type = ns->type;
+		}
+	}
 	return 0;
 }
 
diff -r fba15565c360 -r 5f313144c481 src/lib-storage/index/imapc/imapc-storage.h
--- a/src/lib-storage/index/imapc/imapc-storage.h	Sun Sep 02 19:32:55 2012 +0300
+++ b/src/lib-storage/index/imapc/imapc-storage.h	Sun Sep 02 19:52:31 2012 +0300
@@ -34,6 +34,12 @@
 #define IMAPC_BOX_HAS_FEATURE(mbox, feature) \
 	(((mbox)->storage->set->parsed_features & feature) != 0)
 
+struct imapc_namespace {
+	const char *prefix;
+	char separator;
+	enum mail_namespace_type type;
+};
+
 struct imapc_storage {
 	struct mail_storage storage;
 	const struct imapc_settings *set;
@@ -46,7 +52,10 @@
 	struct mailbox_status *cur_status;
 	unsigned int reopen_count;
 
+	ARRAY(struct imapc_namespace) remote_namespaces;
 	ARRAY(struct imapc_storage_event_callback) untagged_callbacks;
+
+	unsigned int namespaces_requested:1;
 };
 
 struct imapc_mail_cache {
diff -r fba15565c360 -r 5f313144c481 src/lib-storage/index/index-status.c
--- a/src/lib-storage/index/index-status.c	Sun Sep 02 19:32:55 2012 +0300
+++ b/src/lib-storage/index/index-status.c	Sun Sep 02 19:52:31 2012 +0300
@@ -4,8 +4,8 @@
 #include "array.h"
 #include "mail-cache.h"
 #include "mail-search-build.h"
+#include "mail-index-modseq.h"
 #include "index-storage.h"
-#include "mail-index-modseq.h"
 
 static void
 get_last_cached_seq(struct mailbox *box, uint32_t *last_cached_seq_r)
@@ -365,5 +365,10 @@
 		get_metadata_cache_fields(box, metadata_r);
 	if ((items & MAILBOX_METADATA_PRECACHE_FIELDS) != 0)
 		get_metadata_precache_fields(box, metadata_r);
+	if ((items & MAILBOX_METADATA_BACKEND_NAMESPACE) != 0) {
+		metadata_r->backend_ns_prefix = "";
+		metadata_r->backend_ns_type =
+			mailbox_list_get_namespace(box->list)->type;
+	}
 	return 0;
 }
diff -r fba15565c360 -r 5f313144c481 src/lib-storage/mail-storage.h
--- a/src/lib-storage/mail-storage.h	Sun Sep 02 19:32:55 2012 +0300
+++ b/src/lib-storage/mail-storage.h	Sun Sep 02 19:52:31 2012 +0300
@@ -8,6 +8,7 @@
 #include "guid.h"
 #include "mail-types.h"
 #include "mail-error.h"
+#include "mail-namespace.h"
 #include "mailbox-list.h"
 
 /* If some operation is taking long, call notify_ok every n seconds. */
@@ -81,7 +82,8 @@
 	MAILBOX_METADATA_GUID			= 0x01,
 	MAILBOX_METADATA_VIRTUAL_SIZE		= 0x02,
 	MAILBOX_METADATA_CACHE_FIELDS		= 0x04,
-	MAILBOX_METADATA_PRECACHE_FIELDS	= 0x08
+	MAILBOX_METADATA_PRECACHE_FIELDS	= 0x08,
+	MAILBOX_METADATA_BACKEND_NAMESPACE	= 0x10
 };
 
 enum mailbox_search_result_flags {
@@ -245,6 +247,11 @@
 	const ARRAY_TYPE(mailbox_cache_field) *cache_fields;
 	/* Fields that should be precached */
 	enum mail_fetch_field precache_fields;
+	/* imapc backend returns this based on the remote NAMESPACE reply,
+	   while currently other backends return "" and type the same as the
+	   mailbox's real namespace type */
+	const char *backend_ns_prefix;
+	enum mail_namespace_type backend_ns_type;
 };
 
 struct mailbox_update {


More information about the dovecot-cvs mailing list