[dovecot-cvs] dovecot/src/lib-storage Makefile.am, 1.16, 1.17 mail-namespace.c, NONE, 1.1 mail-namespace.h, NONE, 1.1 mail-storage-private.h, 1.50, 1.51 mail-storage.c, 1.78, 1.79 mail-storage.h, 1.128, 1.129

tss at dovecot.org tss at dovecot.org
Tue Apr 3 11:34:32 EEST 2007


Update of /var/lib/cvs/dovecot/src/lib-storage
In directory talvi:/tmp/cvs-serv21629/lib-storage

Modified Files:
	Makefile.am mail-storage-private.h mail-storage.c 
	mail-storage.h 
Added Files:
	mail-namespace.c mail-namespace.h 
Log Message:
Moved namespace handling to lib-storage. Beginnings of namespace support for
non-IMAP parts of Dovecot.



Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/Makefile.am,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- Makefile.am	22 Feb 2007 21:51:07 -0000	1.16
+++ Makefile.am	3 Apr 2007 08:34:29 -0000	1.17
@@ -11,6 +11,7 @@
 libstorage_a_SOURCES = \
 	mail.c \
 	mail-copy.c \
+	mail-namespace.c \
 	mail-search.c \
 	mail-storage.c \
 	mailbox-list.c \
@@ -18,6 +19,7 @@
 
 headers = \
 	mail-copy.h \
+	mail-namespace.h \
 	mail-search.h \
 	mail-storage.h \
 	mail-storage-private.h \

--- NEW FILE: mail-namespace.c ---
/* Copyright (C) 2005-2007 Timo Sirainen */

#include "lib.h"
#include "file-lock.h"
#include "mail-storage.h"
#include "mail-namespace.h"

#include <stdlib.h>

static void namespace_init_storage(struct mail_namespace *ns)
{
	ns->prefix_len = strlen(ns->prefix);
	ns->real_sep = mail_storage_get_hierarchy_sep(ns->storage);

	if (ns->sep == '\0')
                ns->sep = ns->real_sep;

	if (ns->sep == '"' || ns->sep == '\\') {
		ns->sep_str[0] = '\\';
		ns->sep_str[1] = ns->sep;
	} else {
		ns->sep_str[0] = ns->sep;
	}
}

static struct mail_namespace *
namespace_add_env(pool_t pool, const char *data, unsigned int num,
		  const char *user, enum mail_storage_flags flags,
		  enum file_lock_method lock_method)
{
        struct mail_namespace *ns;
        const char *sep, *type, *prefix;
	bool inbox, hidden, subscriptions;

	ns = p_new(pool, struct mail_namespace, 1);

	sep = getenv(t_strdup_printf("NAMESPACE_%u_SEP", num));
	type = getenv(t_strdup_printf("NAMESPACE_%u_TYPE", num));
	prefix = getenv(t_strdup_printf("NAMESPACE_%u_PREFIX", num));
	inbox = getenv(t_strdup_printf("NAMESPACE_%u_INBOX", num)) != NULL;
	hidden = getenv(t_strdup_printf("NAMESPACE_%u_HIDDEN", num)) != NULL;
	subscriptions = getenv(t_strdup_printf("NAMESPACE_%u_SUBSCRIPTIONS",
					       num)) != NULL;

	if (type == NULL || *type == '\0' || strncmp(type, "private", 7) == 0)
		ns->type = NAMESPACE_PRIVATE;
	else if (strncmp(type, "shared", 6) == 0)
		ns->type = NAMESPACE_SHARED;
	else if (strncmp(type, "public", 6) == 0)
		ns->type = NAMESPACE_PUBLIC;
	else {
		i_error("Unknown namespace type: %s", type);
		return NULL;
	}

	if (ns->type != NAMESPACE_PRIVATE)
		flags |= MAIL_STORAGE_FLAG_SHARED_NAMESPACE;
	if (ns->inbox)
		flags |= MAIL_STORAGE_FLAG_HAS_INBOX;

	if (prefix == NULL)
		prefix = "";

	if ((flags & MAIL_STORAGE_FLAG_DEBUG) != 0) {
		i_info("Namespace: type=%s, prefix=%s, sep=%s, "
		       "inbox=%s, hidden=%s, subscriptions=%s",
		       type == NULL ? "" : type, prefix, sep == NULL ? "" : sep,
		       inbox ? "yes" : "no",
		       hidden ? "yes" : "no",
		       subscriptions ? "yes" : "no");
	}

	ns->prefix = p_strdup(pool, prefix);
	ns->inbox = inbox;
	ns->hidden = hidden;
	ns->subscriptions = subscriptions;
	if (mail_storage_create(ns, NULL, data, user, flags, lock_method) < 0) {
		i_error("Failed to create storage for '%s' with data: %s",
			ns->prefix, data);
		return NULL;
	}

	if (sep != NULL)
		ns->sep = *sep;
        namespace_init_storage(ns);
	return ns;
}

int mail_namespaces_init(pool_t pool, const char *user,
			 struct mail_namespace **namespaces_r)
{
	struct mail_namespace *namespaces, *ns, **ns_p;
	enum mail_storage_flags flags;
        enum file_lock_method lock_method;
	const char *mail, *data;
	unsigned int i;

	mail_storage_parse_env(&flags, &lock_method);
        namespaces = NULL; ns_p = &namespaces;

	/* first try NAMESPACE_* environments */
	for (i = 1; ; i++) {
		t_push();
		data = getenv(t_strdup_printf("NAMESPACE_%u", i));
		t_pop();

		if (data == NULL)
			break;

		t_push();
		*ns_p = namespace_add_env(pool, data, i, user, flags,
					  lock_method);
		t_pop();

		if (*ns_p != NULL)
			return -1;

		ns_p = &(*ns_p)->next;
	}

	if (namespaces != NULL) {
		*namespaces_r = namespaces;
		return 0;
	}

	/* fallback to MAIL */
	mail = getenv("MAIL");
	if (mail == NULL) {
		/* support also maildir-specific environment */
		mail = getenv("MAILDIR");
		if (mail != NULL)
			mail = t_strconcat("maildir:", mail, NULL);
	}

	ns = p_new(pool, struct mail_namespace, 1);
	ns->type = NAMESPACE_PRIVATE;
	ns->inbox = TRUE;
	ns->subscriptions = TRUE;
	ns->prefix = "";

	flags |= MAIL_STORAGE_FLAG_HAS_INBOX;
	if (mail_storage_create(ns, NULL, mail, user, flags, lock_method) < 0) {
		if (mail != NULL && *mail != '\0')
			i_error("Failed to create storage with data: %s", mail);
		else {
			const char *home;

			home = getenv("HOME");
			if (home == NULL) home = "not set";

			i_error("MAIL environment missing and "
				"autodetection failed (home %s)", home);
		}
		return -1;
	}

	namespace_init_storage(ns);
	*namespaces_r = ns;
	return 0;
}

struct mail_namespace *mail_namespaces_init_empty(pool_t pool)
{
	struct mail_namespace *ns;

	ns = p_new(pool, struct mail_namespace, 1);
	ns->prefix = "";
	return ns;
}

void mail_namespaces_deinit(struct mail_namespace **_namespaces)
{
	struct mail_namespace *namespaces = *_namespaces;

	*_namespaces = NULL;
	while (namespaces != NULL) {
		if (namespaces->storage != NULL)
			mail_storage_destroy(&namespaces->storage);
		namespaces = namespaces->next;
	}
}

const char *mail_namespace_fix_sep(struct mail_namespace *ns, const char *name)
{
	char *ret, *p;

	if (ns->sep == ns->real_sep)
		return name;

	ret = p_strdup(unsafe_data_stack_pool, name);
	for (p = ret; *p != '\0'; p++) {
		if (*p == ns->sep)
			*p = ns->real_sep;
	}
	return ret;
}

static struct mail_namespace *
mail_namespace_find_int(struct mail_namespace *namespaces, const char **mailbox,
			bool show_hidden)
{
#define CHECK_VISIBILITY(ns, show_hidden) \
	((!(ns)->hidden) || (show_hidden))
        struct mail_namespace *ns = namespaces;
	const char *box = *mailbox;
	struct mail_namespace *best = NULL;
	size_t best_len = 0;
	bool inbox;

	inbox = strncasecmp(box, "INBOX", 5) == 0;
	if (inbox && box[5] == '\0') {
		/* find the INBOX namespace */
		*mailbox = "INBOX";
		while (ns != NULL) {
			if (ns->inbox && CHECK_VISIBILITY(ns, show_hidden))
				return ns;
			if (*ns->prefix == '\0')
				best = ns;
			ns = ns->next;
		}
		return best;
	}

	for (; ns != NULL; ns = ns->next) {
		if (ns->prefix_len >= best_len &&
		    (strncmp(ns->prefix, box, ns->prefix_len) == 0 ||
		     (inbox && strncmp(ns->prefix, "INBOX", 5) == 0 &&
		      strncmp(ns->prefix+5, box+5, ns->prefix_len-5) == 0)) &&
		    CHECK_VISIBILITY(ns, show_hidden)) {
			best = ns;
			best_len = ns->prefix_len;
		}
	}

	if (best != NULL) {
		if (best_len > 0)
			*mailbox += best_len;
		else if (inbox && (box[5] == best->sep || box[5] == '\0'))
			*mailbox = t_strconcat("INBOX", box+5, NULL);

		*mailbox = mail_namespace_fix_sep(best, *mailbox);
	}

	return best;
}

struct mail_namespace *
mail_namespace_find(struct mail_namespace *namespaces, const char **mailbox)
{
	return mail_namespace_find_int(namespaces, mailbox, TRUE);
}

struct mail_namespace *
mail_namespace_find_visible(struct mail_namespace *namespaces,
			    const char **mailbox)
{
	return mail_namespace_find_int(namespaces, mailbox, FALSE);
}

struct mail_namespace *
mail_namespace_find_prefix(struct mail_namespace *namespaces,
			   const char *prefix)
{
        struct mail_namespace *ns;
	unsigned int len = strlen(prefix);

	for (ns = namespaces; ns != NULL; ns = ns->next) {
		if (ns->prefix_len == len &&
		    strcmp(ns->prefix, prefix) == 0)
			return ns;
	}
	return NULL;
}

--- NEW FILE: mail-namespace.h ---
#ifndef __MAIL_NAMESPACE_H
#define __MAIL_NAMESPACE_H

enum namespace_type {
	NAMESPACE_PRIVATE,
	NAMESPACE_SHARED,
	NAMESPACE_PUBLIC
};

struct mail_namespace {
	struct mail_namespace *next;

        enum namespace_type type;
	char sep, real_sep, sep_str[3];

	const char *prefix;
	size_t prefix_len;

	bool inbox, hidden, subscriptions;
	struct mail_storage *storage;
};

int mail_namespaces_init(pool_t pool, const char *user,
			 struct mail_namespace **namespaces_r);
struct mail_namespace *mail_namespaces_init_empty(pool_t pool);
void mail_namespaces_deinit(struct mail_namespace **namespaces);

const char *mail_namespace_fix_sep(struct mail_namespace *ns, const char *name);

struct mail_namespace *
mail_namespace_find(struct mail_namespace *namespaces, const char **mailbox);
struct mail_namespace *
mail_namespace_find_visible(struct mail_namespace *namespaces,
			    const char **mailbox);
struct mail_namespace *
mail_namespace_find_prefix(struct mail_namespace *namespaces,
			   const char *prefix);

#endif

Index: mail-storage-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/mail-storage-private.h,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- mail-storage-private.h	30 Mar 2007 18:57:34 -0000	1.50
+++ mail-storage-private.h	3 Apr 2007 08:34:29 -0000	1.51
@@ -53,6 +53,7 @@
 	pool_t pool;
 
 	char *error;
+	struct mail_namespace *ns;
 	struct mailbox_list *list;
 
 	const char *user; /* name of user accessing the storage */

Index: mail-storage.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/mail-storage.c,v
retrieving revision 1.78
retrieving revision 1.79
diff -u -d -r1.78 -r1.79
--- mail-storage.c	30 Mar 2007 18:57:34 -0000	1.78
+++ mail-storage.c	3 Apr 2007 08:34:29 -0000	1.79
@@ -7,6 +7,7 @@
 #include "mail-index-private.h"
 #include "mailbox-list-private.h"
 #include "mail-storage-private.h"
+#include "mail-namespace.h"
 #include "index/index-storage.h"
 
 #include <stdlib.h>
@@ -149,10 +150,10 @@
 	}
 }
 
-struct mail_storage *
-mail_storage_create(const char *driver, const char *data, const char *user,
-		    enum mail_storage_flags flags,
-		    enum file_lock_method lock_method)
+int mail_storage_create(struct mail_namespace *ns, const char *driver,
+			const char *data, const char *user,
+			enum mail_storage_flags flags,
+			enum file_lock_method lock_method)
 {
 	struct mail_storage *storage_class, *storage;
 	struct mail_storage *const *classes;
@@ -173,14 +174,14 @@
 				"don't know what to do with it: %s "
 				"(try prefixing it with mbox: or maildir:)",
 				data);
-			return NULL;
+			return -1;
 		}
 		classes = &storage_class;
 		count = 1;
 	} else {
 		storage_class = mail_storage_find(driver);
 		if (storage_class == NULL)
-			return NULL;
+			return -1;
 		classes = &storage_class;
 		count = 1;
 	}
@@ -190,6 +191,7 @@
 		storage->flags = flags;
 		storage->lock_method = lock_method;
 		storage->user = p_strdup(storage->pool, user);
+		storage->ns = ns;
 
 		storage->callbacks =
 			p_new(storage->pool, struct mail_storage_callbacks, 1);
@@ -202,11 +204,13 @@
 		pool_unref(storage->pool);
 	}
 	if (i == count)
-		return NULL;
+		return -1;
 
 	if (hook_mail_storage_created != NULL)
 		hook_mail_storage_created(storage);
-	return storage;
+
+	ns->storage = storage;
+	return 0;
 }
 
 void mail_storage_destroy(struct mail_storage **_storage)
@@ -319,6 +323,11 @@
 	return storage->list;
 }
 
+struct mail_namespace *mail_storage_get_namespace(struct mail_storage *storage)
+{
+	return storage->ns;
+}
+
 void mail_storage_set_callbacks(struct mail_storage *storage,
 				struct mail_storage_callbacks *callbacks,
 				void *context)

Index: mail-storage.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/mail-storage.h,v
retrieving revision 1.128
retrieving revision 1.129
diff -u -d -r1.128 -r1.129
--- mail-storage.h	30 Mar 2007 13:40:12 -0000	1.128
+++ mail-storage.h	3 Apr 2007 08:34:29 -0000	1.129
@@ -136,6 +136,7 @@
 	MAILBOX_SYNC_TYPE_KEYWORDS	= 0x04
 };
 
+struct mail_namespace;
 struct mail_storage;
 struct mail_search_arg;
 struct mail_keywords;
@@ -204,15 +205,16 @@
 /* Create a new instance of registered mail storage class with given
    storage-specific data. If driver is NULL, it's tried to be autodetected
    from data. If data is NULL, it uses the first storage that exists.
-   May return NULL if anything fails. */
-struct mail_storage *
-mail_storage_create(const char *driver, const char *data, const char *user,
-		    enum mail_storage_flags flags,
-		    enum file_lock_method lock_method);
+   The storage is put into ns->storage. */
+int mail_storage_create(struct mail_namespace *ns, const char *driver,
+			const char *data, const char *user,
+			enum mail_storage_flags flags,
+			enum file_lock_method lock_method);
 void mail_storage_destroy(struct mail_storage **storage);
 
 char mail_storage_get_hierarchy_sep(struct mail_storage *storage);
 struct mailbox_list *mail_storage_get_list(struct mail_storage *storage);
+struct mail_namespace *mail_storage_get_namespace(struct mail_storage *storage);
 void mail_storage_set_list_error(struct mail_storage *storage);
 
 /* Set storage callback functions to use. */



More information about the dovecot-cvs mailing list