[dovecot-cvs] dovecot/src/lib-storage Makefile.am, 1.14, 1.15 mail-storage-private.h, 1.35, 1.36 mail-storage.c, 1.61, 1.62 mail-storage.h, 1.117, 1.118 mailbox-list-private.h, NONE, 1.1 mailbox-list.c, NONE, 1.1 mailbox-list.h, NONE, 1.1 mailbox-tree.h, 1.2, 1.3

tss at dovecot.org tss at dovecot.org
Thu Nov 16 00:16:35 UTC 2006


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

Modified Files:
	Makefile.am mail-storage-private.h mail-storage.c 
	mail-storage.h mailbox-tree.h 
Added Files:
	mailbox-list-private.h mailbox-list.c mailbox-list.h 
Log Message:
Initial code for separation of mailbox accessing and directory layout
handling. It's not yet possible to change the default layouts though.



Index: Makefile.am
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/Makefile.am,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- Makefile.am	28 Jun 2006 16:31:06 -0000	1.14
+++ Makefile.am	16 Nov 2006 00:16:32 -0000	1.15
@@ -1,4 +1,4 @@
-SUBDIRS = index subscription-file register
+SUBDIRS = list index register
 
 noinst_LIBRARIES = libstorage.a
 
@@ -13,6 +13,7 @@
 	mail-copy.c \
 	mail-search.c \
 	mail-storage.c \
+	mailbox-list.c \
 	mailbox-tree.c
 
 noinst_HEADERS = \
@@ -20,4 +21,6 @@
 	mail-search.h \
 	mail-storage.h \
 	mail-storage-private.h \
+	mailbox-list.h \
+	mailbox-list-private.h \
 	mailbox-tree.h

Index: mail-storage-private.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/mail-storage-private.h,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- mail-storage-private.h	17 Sep 2006 16:22:31 -0000	1.35
+++ mail-storage-private.h	16 Nov 2006 00:16:32 -0000	1.36
@@ -27,8 +27,6 @@
 			      struct mail_storage_callbacks *callbacks,
 			      void *context);
 
-	const char *(*get_mailbox_path)(struct mail_storage *storage,
-					const char *name, bool *is_file_r);
 	const char *(*get_mailbox_control_dir)(struct mail_storage *storage,
 					       const char *name);
 	const char *(*get_mailbox_index_dir)(struct mail_storage *storage,
@@ -45,20 +43,11 @@
 	int (*mailbox_rename)(struct mail_storage *storage, const char *oldname,
 			      const char *newname);
 
-	struct mailbox_list_context *
-		(*mailbox_list_init)(struct mail_storage *storage,
-				     const char *ref, const char *mask,
-				     enum mailbox_list_flags flags);
-	struct mailbox_list *
-		(*mailbox_list_next)(struct mailbox_list_context *ctx);
-	int (*mailbox_list_deinit)(struct mailbox_list_context *ctx);
-
-	int (*set_subscribed)(struct mail_storage *storage,
-			      const char *name, bool set);
-
-	int (*get_mailbox_name_status)(struct mail_storage *storage,
-				       const char *name,
-				       enum mailbox_name_status *status);
+	int (*is_mailbox)(struct mail_storage *storage,
+			  const char *dir, const char *fname,
+			  enum mailbox_list_iter_flags iter_flags,
+			  enum mailbox_info_flags *flags,
+			  enum mailbox_list_file_type type);
 
 	const char *(*get_last_error)(struct mail_storage *storage,
 				      bool *syntax_error_r,
@@ -67,7 +56,7 @@
 
 struct mail_storage {
 	char *name;
-	char hierarchy_sep;
+	bool mailbox_is_file;
 
         struct mail_storage_vfuncs v;
 
@@ -75,6 +64,7 @@
 	pool_t pool;
 
 	char *error;
+	struct mailbox_list *list;
 	enum mail_storage_flags flags;
         enum mail_storage_lock_method lock_method;
 
@@ -287,6 +277,13 @@
 
 const char *mail_storage_class_get_last_error(struct mail_storage *storage,
 					      bool *syntax_error_r);
-bool mailbox_name_is_too_large(const char *name, char sep);
+
+enum mailbox_list_flags
+mail_storage_get_list_flags(enum mail_storage_flags storage_flags);
+int mailbox_storage_list_is_mailbox(const char *dir, const char *fname,
+				    enum mailbox_list_file_type type,
+				    enum mailbox_list_iter_flags iter_flags,
+				    enum mailbox_info_flags *flags,
+				    void *context);
 
 #endif

Index: mail-storage.c
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/mail-storage.c,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -d -r1.61 -r1.62
--- mail-storage.c	9 Oct 2006 17:08:05 -0000	1.61
+++ mail-storage.c	16 Nov 2006 00:16:32 -0000	1.62
@@ -16,14 +16,6 @@
 	"Internal error occurred. Refer to server log for more information."
 #define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"
 
-/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
-   prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
-   then start renaming them to larger names from end to beginning, which
-   eventually would start causing the failures when trying to use too
-   long mailbox names. */
-#define MAILBOX_MAX_HIERARCHY_LEVELS 20
-#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200
-
 unsigned int mail_storage_module_id = 0;
 unsigned int mail_storage_mail_index_module_id = 0;
 
@@ -120,20 +112,20 @@
 }
 
 struct mail_storage *
-mail_storage_create(const char *name, const char *data, const char *user,
+mail_storage_create(const char *driver, const char *data, const char *user,
 		    enum mail_storage_flags flags,
 		    enum mail_storage_lock_method lock_method)
 {
 	struct mail_storage *storage;
 
-	storage = mail_storage_find(name);
+	storage = mail_storage_find(driver);
 	if (storage != NULL)
 		return storage->v.create(data, user, flags, lock_method);
 	else
 		return NULL;
 }
 
-struct mail_storage *
+static struct mail_storage *
 mail_storage_create_default(const char *user, enum mail_storage_flags flags,
 			    enum mail_storage_lock_method lock_method)
 {
@@ -265,6 +257,18 @@
 	storage->temporary_error = TRUE;
 }
 
+void mail_storage_set_list_error(struct mail_storage *storage)
+{
+	bool temp;
+
+	i_free(storage->error);
+	storage->error =
+		i_strdup(mailbox_list_get_last_error(storage->list, &temp));
+
+	storage->syntax_error = FALSE;
+	storage->temporary_error = temp;
+}
+
 void mail_storage_set_critical(struct mail_storage *storage,
 			       const char *fmt, ...)
 {
@@ -285,7 +289,12 @@
 
 char mail_storage_get_hierarchy_sep(struct mail_storage *storage)
 {
-	return storage->hierarchy_sep;
+	return mailbox_list_get_hierarchy_sep(storage->list);
+}
+
+struct mailbox_list *mail_storage_get_list(struct mail_storage *storage)
+{
+	return storage->list;
 }
 
 void mail_storage_set_callbacks(struct mail_storage *storage,
@@ -312,41 +321,6 @@
 	return storage->v.mailbox_rename(storage, oldname, newname);
 }
 
-struct mailbox_list_context *
-mail_storage_mailbox_list_init(struct mail_storage *storage,
-			       const char *ref, const char *mask,
-			       enum mailbox_list_flags flags)
-{
-	return storage->v.mailbox_list_init(storage, ref, mask, flags);
-}
-
-struct mailbox_list *
-mail_storage_mailbox_list_next(struct mailbox_list_context *ctx)
-{
-	return ctx->storage->v.mailbox_list_next(ctx);
-}
-
-int mail_storage_mailbox_list_deinit(struct mailbox_list_context **_ctx)
-{
-	struct mailbox_list_context *ctx = *_ctx;
-
-	*_ctx = NULL;
-	return ctx->storage->v.mailbox_list_deinit(ctx);
-}
-
-int mail_storage_set_subscribed(struct mail_storage *storage,
-				const char *name, bool set)
-{
-	return storage->v.set_subscribed(storage, name, set);
-}
-
-int mail_storage_get_mailbox_name_status(struct mail_storage *storage,
-					 const char *name,
-					 enum mailbox_name_status *status)
-{
-	return storage->v.get_mailbox_name_status(storage, name, status);
-}
-
 const char *mail_storage_get_last_error(struct mail_storage *storage,
 					bool *syntax_error_r,
 					bool *temporary_error_r)
@@ -358,19 +332,61 @@
 const char *mail_storage_get_mailbox_path(struct mail_storage *storage,
 					  const char *name, bool *is_file_r)
 {
-	return storage->v.get_mailbox_path(storage, name, is_file_r);
+	*is_file_r = storage->mailbox_is_file;
+
+	return mailbox_list_get_path(storage->list, name,
+				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
 }
 
 const char *mail_storage_get_mailbox_control_dir(struct mail_storage *storage,
 						 const char *name)
 {
-	return storage->v.get_mailbox_control_dir(storage, name);
+	return mailbox_list_get_path(storage->list, name,
+				     MAILBOX_LIST_PATH_TYPE_CONTROL);
 }
 
 const char *mail_storage_get_mailbox_index_dir(struct mail_storage *storage,
 					       const char *name)
 {
-	return storage->v.get_mailbox_index_dir(storage, name);
+	return mailbox_list_get_path(storage->list, name,
+				     MAILBOX_LIST_PATH_TYPE_INDEX);
+}
+
+enum mailbox_list_flags
+mail_storage_get_list_flags(enum mail_storage_flags storage_flags)
+{
+	enum mailbox_list_flags list_flags = 0;
+
+	if ((storage_flags & MAIL_STORAGE_FLAG_DEBUG) != 0)
+		list_flags |= MAILBOX_LIST_FLAG_DEBUG;
+	if ((storage_flags & MAIL_STORAGE_FLAG_HAS_INBOX) != 0)
+		list_flags |= MAILBOX_LIST_FLAG_INBOX;
+	if ((storage_flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0)
+		list_flags |= MAILBOX_LIST_FLAG_FULL_FS_ACCESS;
+	return list_flags;
+}
+
+int mailbox_storage_list_is_mailbox(const char *dir, const char *fname,
+				    enum mailbox_list_file_type type,
+				    enum mailbox_list_iter_flags iter_flags,
+				    enum mailbox_info_flags *flags,
+				    void *context)
+{
+	struct mail_storage *storage = context;
+
+	return mail_storage_is_mailbox(storage, dir, fname, iter_flags,
+				       flags, type);
+}
+
+
+int mail_storage_is_mailbox(struct mail_storage *storage,
+			    const char *dir, const char *fname,
+			    enum mailbox_list_iter_flags iter_flags,
+			    enum mailbox_info_flags *flags,
+			    enum mailbox_list_file_type type)
+{
+	return storage->v.is_mailbox(storage, dir, fname, iter_flags,
+				     flags, type);
 }
 
 struct mailbox *mailbox_open(struct mail_storage *storage, const char *name,
@@ -575,25 +591,3 @@
 {
 	return box->v.is_inconsistent(box);
 }
-
-bool mailbox_name_is_too_large(const char *name, char sep)
-{
-	unsigned int levels = 1, level_len = 0;
-
-	for (; *name != '\0'; name++) {
-		if (*name == sep) {
-			if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
-				return TRUE;
-			levels++;
-			level_len = 0;
-		} else {
-			level_len++;
-		}
-	}
-
-	if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
-		return TRUE;
-	if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
-		return TRUE;
-	return FALSE;
-}

Index: mail-storage.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/mail-storage.h,v
retrieving revision 1.117
retrieving revision 1.118
diff -u -d -r1.117 -r1.118
--- mail-storage.h	9 Oct 2006 17:08:05 -0000	1.117
+++ mail-storage.h	16 Nov 2006 00:16:32 -0000	1.118
@@ -4,6 +4,7 @@
 struct message_size;
 
 #include "mail-types.h"
+#include "mailbox-list.h"
 
 enum mail_storage_flags {
 	/* Print debugging information while initializing the storage */
@@ -26,7 +27,9 @@
 	MAIL_STORAGE_FLAG_SHARED_NAMESPACE	= 0x80,
 	/* Don't try to autodetect anything, require that the given data 
 	   contains all the necessary information. */
-	MAIL_STORAGE_FLAG_NO_AUTODETECTION	= 0x100
+	MAIL_STORAGE_FLAG_NO_AUTODETECTION	= 0x100,
+	/* Ths storage contains INBOX */
+	MAIL_STORAGE_FLAG_HAS_INBOX		= 0x200
 };
 
 enum mail_storage_lock_method {
@@ -53,26 +56,6 @@
 	MAILBOX_OPEN_MBOX_ONE_MSG_ONLY	= 0x40
 };
 
-enum mailbox_list_flags {
-	MAILBOX_LIST_SUBSCRIBED	= 0x01,
-	MAILBOX_LIST_FAST_FLAGS	= 0x02,
-	MAILBOX_LIST_CHILDREN	= 0x04,
-	MAILBOX_LIST_INBOX	= 0x08
-};
-
-enum mailbox_flags {
-	MAILBOX_NOSELECT	= 0x001,
-	MAILBOX_NONEXISTENT	= 0x002,
-	MAILBOX_PLACEHOLDER	= 0x004,
-	MAILBOX_CHILDREN	= 0x008,
-	MAILBOX_NOCHILDREN	= 0x010,
-	MAILBOX_NOINFERIORS	= 0x020,
-	MAILBOX_MARKED		= 0x040,
-	MAILBOX_UNMARKED	= 0x080,
-
-	MAILBOX_READONLY	= 0x100
-};
-
 enum mailbox_status_items {
 	STATUS_MESSAGES		= 0x01,
 	STATUS_RECENT		= 0x02,
@@ -83,13 +66,6 @@
 	STATUS_KEYWORDS		= 0x40
 };
 
-enum mailbox_name_status {
-	MAILBOX_NAME_EXISTS,
-	MAILBOX_NAME_VALID,
-	MAILBOX_NAME_INVALID,
-	MAILBOX_NAME_NOINFERIORS
-};
-
 enum mail_sort_type {
 /* Maximum size for sort program (each one separately + END) */
 #define MAX_SORT_PROGRAM_SIZE (7 + 1)
@@ -165,14 +141,8 @@
 struct mail_keywords;
 struct mail_save_context;
 struct mailbox;
-struct mailbox_list_context;
 struct mailbox_transaction_context;
 
-struct mailbox_list {
-	const char *name;
-        enum mailbox_flags flags;
-};
-
 struct mailbox_status {
 	uint32_t messages;
 	uint32_t recent;
@@ -232,23 +202,21 @@
 			    enum mail_storage_lock_method *lock_method_r);
 
 /* Create a new instance of registered mail storage class with given
-   storage-specific data. If data is NULL, it tries to use defaults.
+   storage-specific data. If data is NULL, it tries to autodetect defaults.
    May return NULL if anything fails. */
 struct mail_storage *
-mail_storage_create(const char *name, const char *data, const char *user,
+mail_storage_create(const char *driver, const char *data, const char *user,
 		    enum mail_storage_flags flags,
 		    enum mail_storage_lock_method lock_method);
-void mail_storage_destroy(struct mail_storage **storage);
-
-struct mail_storage *
-mail_storage_create_default(const char *user, enum mail_storage_flags flags,
-			    enum mail_storage_lock_method lock_method);
 struct mail_storage *
 mail_storage_create_with_data(const char *data, const char *user,
 			      enum mail_storage_flags flags,
 			      enum mail_storage_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);
+void mail_storage_set_list_error(struct mail_storage *storage);
 
 /* Set storage callback functions to use. */
 void mail_storage_set_callbacks(struct mail_storage *storage,
@@ -274,31 +242,6 @@
 int mail_storage_mailbox_rename(struct mail_storage *storage,
 				const char *oldname, const char *newname);
 
-/* Initialize new mailbox list request. mask may contain '%' and '*'
-   wildcards as defined in RFC3501. Matching against "INBOX" is
-   case-insensitive, but anything else is not. */
-struct mailbox_list_context *
-mail_storage_mailbox_list_init(struct mail_storage *storage,
-			       const char *ref, const char *mask,
-			       enum mailbox_list_flags flags);
-/* Get next mailbox. Returns the mailbox name */
-struct mailbox_list *
-mail_storage_mailbox_list_next(struct mailbox_list_context *ctx);
-/* Deinitialize mailbox list request. Returns FALSE if some error
-   occurred while listing. */
-int mail_storage_mailbox_list_deinit(struct mailbox_list_context **ctx);
-
-/* Subscribe/unsubscribe mailbox. There should be no error when
-   subscribing to already subscribed mailbox. Subscribing to
-   unexisting mailboxes is optional. */
-int mail_storage_set_subscribed(struct mail_storage *storage,
-				const char *name, bool set);
-
-/* Returns mailbox name status */
-int mail_storage_get_mailbox_name_status(struct mail_storage *storage,
-					 const char *name,
-					 enum mailbox_name_status *status);
-
 /* Returns the error message of last occurred error. */
 const char *mail_storage_get_last_error(struct mail_storage *storage,
 					bool *syntax_error_r,
@@ -319,6 +262,12 @@
 const char *mail_storage_get_mailbox_index_dir(struct mail_storage *storage,
 					       const char *name);
 
+int mail_storage_is_mailbox(struct mail_storage *storage,
+			    const char *dir, const char *fname,
+			    enum mailbox_list_iter_flags iter_flags,
+			    enum mailbox_info_flags *flags,
+			    enum mailbox_list_file_type type);
+
 /* Open a mailbox. If input stream is given, mailbox is opened read-only
    using it as a backend. If storage doesn't support stream backends and its
    tried to be used, NULL is returned.

--- NEW FILE: mailbox-list-private.h ---
#ifndef __MAILBOX_LIST_PRIVATE_H
#define __MAILBOX_LIST_PRIVATE_H

#include "mailbox-list.h"

struct dirent;

struct mailbox_list_vfuncs {
	struct mailbox_list *(*alloc)(void);
	void (*deinit)(struct mailbox_list *list);

	bool (*is_valid_mask)(struct mailbox_list *list, const char *mask);
	bool (*is_valid_existing_name)(struct mailbox_list *list,
				       const char *name);
	bool (*is_valid_create_name)(struct mailbox_list *list,
				     const char *name);

	const char *(*get_path)(struct mailbox_list *list, const char *name,
				enum mailbox_list_path_type type);
	int (*get_mailbox_name_status)(struct mailbox_list *list,
				       const char *name,
				       enum mailbox_name_status *status);

	const char *(*get_temp_prefix)(struct mailbox_list *list);

	struct mailbox_list_iterate_context *
		(*iter_init)(struct mailbox_list *list,
			     const char *ref, const char *mask,
			     enum mailbox_list_iter_flags flags);
	struct mailbox_info *
		(*iter_next)(struct mailbox_list_iterate_context *ctx);
	int (*iter_deinit)(struct mailbox_list_iterate_context *ctx);

	int (*set_subscribed)(struct mailbox_list *list,
			      const char *name, bool set);
};

struct mailbox_list {
	const char *name;
	char hierarchy_sep;
	size_t mailbox_name_max_length;

	struct mailbox_list_vfuncs v;

/* private: */
	pool_t pool;
	struct mailbox_list_settings set;
	enum mailbox_list_flags flags;

	char *error;
	bool temporary_error;

	mailbox_list_is_mailbox_t *callback;
	void *context;

	ARRAY_DEFINE(module_contexts, void);
};

struct mailbox_list_iterate_context {
	struct mailbox_list *list;
	enum mailbox_list_iter_flags flags;
	bool failed;
};

/* Modules should use do "my_id = mailbox_list_module_id++" and
   use objects' module_contexts[id] for their own purposes. */
extern unsigned int mailbox_list_module_id;

extern void (*hook_mailbox_list_created)(struct mailbox_list *list);

bool mailbox_list_name_is_too_large(const char *name, char sep);
enum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d);

void mailbox_list_clear_error(struct mailbox_list *list);
void mailbox_list_set_error(struct mailbox_list *list, const char *error);
void mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
	__attr_format__(2, 3);

#endif

--- NEW FILE: mailbox-list.c ---
/* Copyright (C) 2006 Timo Sirainen */

#include "lib.h"
#include "array.h"
#include "ioloop.h"
#include "mailbox-list-private.h"

#include <time.h>
#include <dirent.h>

/* 20 * (200+1) < 4096 which is the standard PATH_MAX. Having these settings
   prevents malicious user from creating eg. "a/a/a/.../a" mailbox name and
   then start renaming them to larger names from end to beginning, which
   eventually would start causing the failures when trying to use too
   long mailbox names. */
#define MAILBOX_MAX_HIERARCHY_LEVELS 20
#define MAILBOX_MAX_HIERARCHY_NAME_LENGTH 200

/* Message to show to users when critical error occurs */
#define CRITICAL_MSG \
	"Internal error occurred. Refer to server log for more information."
#define CRITICAL_MSG_STAMP CRITICAL_MSG " [%Y-%m-%d %H:%M:%S]"

void (*hook_mailbox_list_created)(struct mailbox_list *list);

static ARRAY_DEFINE(mailbox_list_drivers, const struct mailbox_list *);

static bool mailbox_list_driver_find(const char *name, unsigned int *idx_r)
{
	const struct mailbox_list *const *drivers;
	unsigned int i, count;

	drivers = array_get(&mailbox_list_drivers, &count);
	for (i = 0; i < count; i++) {
		if (strcasecmp(drivers[i]->name, name) == 0) {
			*idx_r = i;
			return TRUE;
		}
	}
	return FALSE;
}

void mailbox_list_register(const struct mailbox_list *list)
{
	if (!array_is_created(&mailbox_list_drivers))
		i_array_init(&mailbox_list_drivers, 4);
	else {
		unsigned int idx;

		if (mailbox_list_driver_find(list->name, &idx)) {
			i_fatal("mailbox_list_register(%s): duplicate driver",
				list->name);
		}
	}

	array_append(&mailbox_list_drivers, &list, 1);
}

void mailbox_list_unregister(const struct mailbox_list *list)
{
	unsigned int idx;

	if (!mailbox_list_driver_find(list->name, &idx)) {
		i_fatal("mailbox_list_unregister(%s): unknown driver",
			list->name);
	}
	array_delete(&mailbox_list_drivers, idx, 1);

	if (array_count(&mailbox_list_drivers) == 0)
		array_free(&mailbox_list_drivers);
}

int mailbox_list_init(const char *driver,
		      const struct mailbox_list_settings *set,
		      enum mailbox_list_flags flags,
		      mailbox_list_is_mailbox_t *callback, void *context,
		      struct mailbox_list **list_r, const char **error_r)
{
	const struct mailbox_list *const *class_p;
	struct mailbox_list *list;
	unsigned int idx;

	if (!mailbox_list_driver_find(driver, &idx)) {
		*error_r = "Unknown mailbox list driver";
		return -1;
	}

	i_assert(*set->root_dir != '\0');
	i_assert(*set->subscription_fname != '\0');

	class_p = array_idx(&mailbox_list_drivers, idx);
	list = (*class_p)->v.alloc();

	list->flags = flags;
	list->callback = callback;
	list->context = context;

	/* copy settings */
	list->set.root_dir = p_strdup(list->pool, set->root_dir);
	list->set.index_dir = set->index_dir == NULL ||
		strcmp(set->index_dir, set->root_dir) == 0 ? NULL :
		p_strdup(list->pool, set->index_dir);
	list->set.control_dir = set->control_dir == NULL ||
		strcmp(set->control_dir, set->root_dir) == 0 ? NULL :
		p_strdup(list->pool, set->control_dir);

	list->set.inbox_path = p_strdup(list->pool, set->inbox_path);
	list->set.subscription_fname =
		p_strdup(list->pool, set->subscription_fname);
	list->set.maildir_name = p_strdup(list->pool, set->maildir_name);

	if ((flags & MAILBOX_LIST_FLAG_DEBUG) != 0) {
		i_info("%s: root=%s, index=%s, control=%s, inbox=%s",
		       driver, list->set.root_dir,
		       list->set.index_dir == NULL ? "" : list->set.index_dir,
		       list->set.control_dir == NULL ?
		       "" : list->set.control_dir,
		       list->set.inbox_path == NULL ?
		       "" : list->set.inbox_path);
	}

	array_create(&list->module_contexts, list->pool, sizeof(void *), 5);

	if (hook_mailbox_list_created != NULL)
		hook_mailbox_list_created(list);

	*list_r = list;
	return 0;
}

void mailbox_list_deinit(struct mailbox_list *list)
{
	i_free_and_null(list->error);

	list->v.deinit(list);
}

const char *mailbox_list_get_driver_name(struct mailbox_list *list)
{
	return list->name;
}

char mailbox_list_get_hierarchy_sep(struct mailbox_list *list)
{
	return list->hierarchy_sep;
}

bool mailbox_list_is_valid_mask(struct mailbox_list *list, const char *mask)
{
	return list->v.is_valid_mask(list, mask);
}

bool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
					 const char *name)
{
	return list->v.is_valid_existing_name(list, name);
}

bool mailbox_list_is_valid_create_name(struct mailbox_list *list,
				       const char *name)
{
	return list->v.is_valid_create_name(list, name);
}

const char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
				  enum mailbox_list_path_type type)
{
	return list->v.get_path(list, name, type);
}

const char *mailbox_list_get_temp_prefix(struct mailbox_list *list)
{
	return list->v.get_temp_prefix(list);
}

int mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
					 const char *name,
					 enum mailbox_name_status *status)
{
	return list->v.get_mailbox_name_status(list, name, status);
}

struct mailbox_list_iterate_context *
mailbox_list_iter_init(struct mailbox_list *list,
		       const char *ref, const char *mask,
		       enum mailbox_list_iter_flags flags)
{
	return list->v.iter_init(list, ref, mask, flags);
}

struct mailbox_info *
mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx)
{
	return ctx->list->v.iter_next(ctx);
}

int mailbox_list_iter_deinit(struct mailbox_list_iterate_context **_ctx)
{
	struct mailbox_list_iterate_context *ctx = *_ctx;

	*_ctx = NULL;

	return ctx->list->v.iter_deinit(ctx);
}

int mailbox_list_set_subscribed(struct mailbox_list *list,
				const char *name, bool set)
{
	return list->v.set_subscribed(list, name, set);
}

bool mailbox_list_name_is_too_large(const char *name, char sep)
{
	unsigned int levels = 1, level_len = 0;

	for (; *name != '\0'; name++) {
		if (*name == sep) {
			if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
				return TRUE;
			levels++;
			level_len = 0;
		} else {
			level_len++;
		}
	}

	if (level_len > MAILBOX_MAX_HIERARCHY_NAME_LENGTH)
		return TRUE;
	if (levels > MAILBOX_MAX_HIERARCHY_LEVELS)
		return TRUE;
	return FALSE;
}

enum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d)
{
	enum mailbox_list_file_type type;

#ifdef HAVE_DIRENT_D_TYPE
	switch (d->d_type) {
	case DT_UNKNOWN:
		type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
		break;
	case DT_REG:
		type = MAILBOX_LIST_FILE_TYPE_FILE;
		break;
	case DT_DIR:
		type = MAILBOX_LIST_FILE_TYPE_DIR;
		break;
	case DT_LNK:
		type = MAILBOX_LIST_FILE_TYPE_SYMLINK;
		break;
	default:
		type = MAILBOX_LIST_FILE_TYPE_OTHER;
		break;
	}
#else
	type = MAILBOX_LIST_FILE_TYPE_UNKNOWN;
#endif
	return type;
}

const char *mailbox_list_get_last_error(struct mailbox_list *list,
					bool *temporary_error_r)
{
	*temporary_error_r = list->temporary_error;

	return list->error;
}

void mailbox_list_clear_error(struct mailbox_list *list)
{
	i_free_and_null(list->error);

	list->temporary_error = FALSE;
}

void mailbox_list_set_error(struct mailbox_list *list, const char *error)
{
	i_free(list->error);
	list->error = i_strdup(error);

	list->temporary_error = FALSE;
}

static void mailbox_list_set_internal_error(struct mailbox_list *list)
{
	struct tm *tm;
	char str[256];

	tm = localtime(&ioloop_time);

	i_free(list->error);
	list->error =
		strftime(str, sizeof(str), CRITICAL_MSG_STAMP, tm) > 0 ?
		i_strdup(str) : i_strdup(CRITICAL_MSG);
	list->temporary_error = TRUE;
}

void mailbox_list_set_critical(struct mailbox_list *list, const char *fmt, ...)
{
	va_list va;

	va_start(va, fmt);
	i_error("%s", t_strdup_vprintf(fmt, va));
	va_end(va);

	/* critical errors may contain sensitive data, so let user
	   see only "Internal error" with a timestamp to make it
	   easier to look from log files the actual error message. */
	mailbox_list_set_internal_error(list);
}

--- NEW FILE: mailbox-list.h ---
#ifndef __MAILBOX_LIST_H
#define __MAILBOX_LIST_H

struct mailbox_list;
struct mailbox_list_iterate_context;

enum mailbox_list_flags {
	/* Print debugging information while initializing the driver */
	MAILBOX_LIST_FLAG_DEBUG			= 0x01,
	/* This mailbox list contains INBOX. Match case-insensitively for it. */
	MAILBOX_LIST_FLAG_INBOX			= 0x02,
	/* Allow full filesystem access with absolute or relative paths. */
	MAILBOX_LIST_FLAG_FULL_FS_ACCESS	= 0x04
};

enum mailbox_info_flags {
	MAILBOX_NOSELECT	= 0x001,
	MAILBOX_NONEXISTENT	= 0x002,
	MAILBOX_PLACEHOLDER	= 0x004,
	MAILBOX_CHILDREN	= 0x008,
	MAILBOX_NOCHILDREN	= 0x010,
	MAILBOX_NOINFERIORS	= 0x020,
	MAILBOX_MARKED		= 0x040,
	MAILBOX_UNMARKED	= 0x080,

	MAILBOX_READONLY	= 0x100
};

enum mailbox_name_status {
	MAILBOX_NAME_EXISTS,
	MAILBOX_NAME_VALID,
	MAILBOX_NAME_INVALID,
	MAILBOX_NAME_NOINFERIORS
};

enum mailbox_list_iter_flags {
	/* List only subscribed mailboxes */
	MAILBOX_LIST_ITER_SUBSCRIBED	= 0x01,
	/* Don't return any flags unless it can be done without cost */
	MAILBOX_LIST_ITER_FAST_FLAGS	= 0x02,
	/* Return children flags */
	MAILBOX_LIST_ITER_CHILDREN	= 0x04
};

enum mailbox_list_path_type {
	/* Return directory's path (eg. /home/user/mail) */
	MAILBOX_LIST_PATH_TYPE_DIR,
	/* Return mailbox path (dir + maildir_name) */
	MAILBOX_LIST_PATH_TYPE_MAILBOX,
	/* Return control directory */
	MAILBOX_LIST_PATH_TYPE_CONTROL,
	/* Return index file directory */
	MAILBOX_LIST_PATH_TYPE_INDEX
};

enum mailbox_list_file_type {
	MAILBOX_LIST_FILE_TYPE_UNKNOWN = 0,
	MAILBOX_LIST_FILE_TYPE_FILE,
	MAILBOX_LIST_FILE_TYPE_DIR,
	MAILBOX_LIST_FILE_TYPE_SYMLINK,
	MAILBOX_LIST_FILE_TYPE_OTHER
};

struct mailbox_list_settings {
	const char *root_dir;
	const char *index_dir;
	const char *control_dir;

	const char *inbox_path;
	const char *subscription_fname;
	/* If non-empty, it means that mails exist in a maildir_name
	   subdirectory. eg. if you have a directory containing directories:

	   mail/
	   mail/foo/
	   mail/foo/Maildir

	   If mailbox_name is empty, you have mailboxes "mail", "mail/foo" and
	   "mail/foo/Maildir".

	   If mailbox_name is "Maildir", you have a non-selectable mailbox
	   "mail" and a selectable mailbox "mail/foo". */
	const char *maildir_name;
};

struct mailbox_info {
	const char *name;
        enum mailbox_info_flags flags;
};

/* Returns -1 if error, 0 if it's not a valid mailbox, 1 if it is.
   flags may be updated (especially the children flags). */
typedef int mailbox_list_is_mailbox_t(const char *dir, const char *fname,
				      enum mailbox_list_file_type type,
				      enum mailbox_list_iter_flags iter_flags,
				      enum mailbox_info_flags *flags_r,
				      void *context);

/* register all drivers */
void mailbox_list_register_all(void);

void mailbox_list_register(const struct mailbox_list *list);
void mailbox_list_unregister(const struct mailbox_list *list);

/* Returns 0 if ok, -1 if initialization failed. */
int mailbox_list_init(const char *driver,
		      const struct mailbox_list_settings *set,
		      enum mailbox_list_flags flags,
		      mailbox_list_is_mailbox_t *callback, void *context,
		      struct mailbox_list **list_r, const char **error_r);
void mailbox_list_deinit(struct mailbox_list *list);

const char *mailbox_list_get_driver_name(struct mailbox_list *list);
char mailbox_list_get_hierarchy_sep(struct mailbox_list *list);

/* Returns TRUE if the name doesn't contain any invalid characters.
   The create name check can be more strict. */
bool mailbox_list_is_valid_mask(struct mailbox_list *list, const char *mask);
bool mailbox_list_is_valid_existing_name(struct mailbox_list *list,
					 const char *name);
bool mailbox_list_is_valid_create_name(struct mailbox_list *list,
				       const char *name);

/* Return full path for the given mailbox name. The name must be a valid
   existing mailbox name, or NULL to get the root directory.
   For INDEX=MEMORY it returns "" as the path. */
const char *mailbox_list_get_path(struct mailbox_list *list, const char *name,
				  enum mailbox_list_path_type type);
/* Returns mailbox name status */
int mailbox_list_get_mailbox_name_status(struct mailbox_list *list,
					 const char *name,
					 enum mailbox_name_status *status);

/* Returns a prefix that temporary files should use without conflicting
   with the namespace. */
const char *mailbox_list_get_temp_prefix(struct mailbox_list *list);

/* Initialize new mailbox list request. mask may contain '%' and '*'
   wildcards as defined by RFC-3501. */
struct mailbox_list_iterate_context *
mailbox_list_iter_init(struct mailbox_list *list,
		       const char *ref, const char *mask,
		       enum mailbox_list_iter_flags flags);
/* Get next mailbox. Returns the mailbox name */
struct mailbox_info *
mailbox_list_iter_next(struct mailbox_list_iterate_context *ctx);
/* Deinitialize mailbox list request. Returns FALSE if some error
   occurred while listing. */
int mailbox_list_iter_deinit(struct mailbox_list_iterate_context **ctx);

/* Subscribe/unsubscribe mailbox. There should be no error when
   subscribing to already subscribed mailbox. Subscribing to
   unexisting mailboxes is optional. */
int mailbox_list_set_subscribed(struct mailbox_list *list,
				const char *name, bool set);

/* Returns the error message of last occurred error. */
const char *mailbox_list_get_last_error(struct mailbox_list *list,
					bool *temporary_error_r);

#endif

Index: mailbox-tree.h
===================================================================
RCS file: /var/lib/cvs/dovecot/src/lib-storage/mailbox-tree.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- mailbox-tree.h	13 Jan 2006 20:26:24 -0000	1.2
+++ mailbox-tree.h	16 Nov 2006 00:16:32 -0000	1.3
@@ -1,14 +1,14 @@
 #ifndef __MAILBOX_TREE_H
 #define __MAILBOX_TREE_H
 
-#include "mail-storage.h"
+#include "mailbox-list.h"
 
 struct mailbox_node {
 	struct mailbox_node *next;
 	struct mailbox_node *children;
 
 	char *name;
-	enum mailbox_flags flags;
+	enum mailbox_info_flags flags;
 };
 
 struct mailbox_tree_context *mailbox_tree_init(char separator);



More information about the dovecot-cvs mailing list