dovecot-2.1: Moved autocreate plugin functionality into lib-stor...

dovecot at dovecot.org dovecot at dovecot.org
Fri Dec 2 16:22:42 EET 2011


details:   http://hg.dovecot.org/dovecot-2.1/rev/ee783a878120
changeset: 13793:ee783a878120
user:      Timo Sirainen <tss at iki.fi>
date:      Fri Dec 02 16:22:31 2011 +0200
description:
Moved autocreate plugin functionality into lib-storage.
The autocreate plugin is still used for backwards compatibility.

Mailboxes can be configured like:

mailbox Sent {
  auto = subscribe
}
mailbox Spam {
  auto = create
}

diffstat:

 src/config/settings-get.pl                 |    1 +
 src/lib-storage/mail-storage-private.h     |    2 +
 src/lib-storage/mail-storage-settings.c    |   48 ++
 src/lib-storage/mail-storage-settings.h    |   12 +
 src/lib-storage/mail-storage.c             |   77 +++-
 src/lib-storage/mailbox-list-iter.c        |  270 ++++++++++++++++-
 src/lib-storage/mailbox-list-private.h     |    1 +
 src/plugins/autocreate/autocreate-plugin.c |  473 ++--------------------------
 8 files changed, 434 insertions(+), 450 deletions(-)

diffs (truncated from 1111 to 300 lines):

diff -r b48fb6a08389 -r ee783a878120 src/config/settings-get.pl
--- a/src/config/settings-get.pl	Fri Dec 02 14:49:08 2011 +0200
+++ b/src/config/settings-get.pl	Fri Dec 02 16:22:31 2011 +0200
@@ -8,6 +8,7 @@
 print '#include "file-lock.h"'."\n";
 print '#include "fsync-mode.h"'."\n";
 print '#include "hash-format.h"'."\n";
+print '#include "unichar.h"'."\n";
 print '#include "settings-parser.h"'."\n";
 print '#include "all-settings.h"'."\n";
 print '#include <stddef.h>'."\n";
diff -r b48fb6a08389 -r ee783a878120 src/lib-storage/mail-storage-private.h
--- a/src/lib-storage/mail-storage-private.h	Fri Dec 02 14:49:08 2011 +0200
+++ b/src/lib-storage/mail-storage-private.h	Fri Dec 02 16:22:31 2011 +0200
@@ -226,6 +226,8 @@
 
 	/* default vfuncs for new struct mails. */
 	const struct mail_vfuncs *mail_vfuncs;
+	/* Mailbox settings, or NULL if defaults */
+	const struct mailbox_settings *set;
 
 	/* If non-zero, fail mailbox_open() with this error. mailbox_alloc()
 	   can set this to force open to fail. */
diff -r b48fb6a08389 -r ee783a878120 src/lib-storage/mail-storage-settings.c
--- a/src/lib-storage/mail-storage-settings.c	Fri Dec 02 14:49:08 2011 +0200
+++ b/src/lib-storage/mail-storage-settings.c	Fri Dec 02 16:22:31 2011 +0200
@@ -4,6 +4,7 @@
 #include "array.h"
 #include "hash-format.h"
 #include "var-expand.h"
+#include "unichar.h"
 #include "settings-parser.h"
 #include "mail-index.h"
 #include "mail-user.h"
@@ -15,6 +16,7 @@
 
 static bool mail_storage_settings_check(void *_set, pool_t pool, const char **error_r);
 static bool namespace_settings_check(void *_set, pool_t pool, const char **error_r);
+static bool mailbox_settings_check(void *_set, pool_t pool, const char **error_r);
 static bool mail_user_settings_check(void *_set, pool_t pool, const char **error_r);
 
 #undef DEF
@@ -142,6 +144,37 @@
 };
 
 #undef DEF
+#define DEF(type, name) \
+	{ type, #name, offsetof(struct mailbox_settings, name), NULL }
+
+static const struct setting_define mailbox_setting_defines[] = {
+	DEF(SET_STR, name),
+	{ SET_ENUM, "auto", offsetof(struct mailbox_settings, autocreate), NULL } ,
+
+	SETTING_DEFINE_LIST_END
+};
+
+const struct mailbox_settings mailbox_default_settings = {
+	.name = "",
+	.autocreate = MAILBOX_SET_AUTO_NO":"
+		MAILBOX_SET_AUTO_CREATE":"
+		MAILBOX_SET_AUTO_SUBSCRIBE
+};
+
+const struct setting_parser_info mailbox_setting_parser_info = {
+	.defines = mailbox_setting_defines,
+	.defaults = &mailbox_default_settings,
+
+	.type_offset = offsetof(struct mailbox_settings, name),
+	.struct_size = sizeof(struct mailbox_settings),
+
+	.parent_offset = (size_t)-1,
+	.parent = &mail_user_setting_parser_info,
+
+	.check_func = mailbox_settings_check
+};
+
+#undef DEF
 #undef DEFLIST_UNIQUE
 #define DEF(type, name) \
 	{ type, #name, offsetof(struct mail_user_settings, name), NULL }
@@ -173,6 +206,7 @@
 	DEF(SET_STR, mail_log_prefix),
 
 	DEFLIST_UNIQUE(namespaces, "namespace", &mail_namespace_setting_parser_info),
+	DEFLIST_UNIQUE(mailboxes, "mailbox", &mailbox_setting_parser_info),
 	{ SET_STRLIST, "plugin", offsetof(struct mail_user_settings, plugin_envs), NULL },
 
 	SETTING_DEFINE_LIST_END
@@ -202,6 +236,7 @@
 	.mail_log_prefix = "%s(%u): ",
 
 	.namespaces = ARRAY_INIT,
+	.mailboxes = ARRAY_INIT,
 	.plugin_envs = ARRAY_INIT
 };
 
@@ -425,6 +460,19 @@
 	return TRUE;
 }
 
+static bool mailbox_settings_check(void *_set, pool_t pool ATTR_UNUSED,
+				   const char **error_r)
+{
+	struct mailbox_settings *set = _set;
+
+	if (!uni_utf8_str_is_valid(set->name)) {
+		*error_r = t_strdup_printf("mailbox %s: name isn't valid UTF-8",
+					   set->name);
+		return FALSE;
+	}
+	return TRUE;
+}
+
 static bool mail_user_settings_check(void *_set, pool_t pool ATTR_UNUSED,
 				     const char **error_r ATTR_UNUSED)
 {
diff -r b48fb6a08389 -r ee783a878120 src/lib-storage/mail-storage-settings.h
--- a/src/lib-storage/mail-storage-settings.h	Fri Dec 02 14:49:08 2011 +0200
+++ b/src/lib-storage/mail-storage-settings.h	Fri Dec 02 16:22:31 2011 +0200
@@ -55,6 +55,16 @@
 	struct mail_user_settings *user_set;
 };
 
+/* <settings checks> */
+#define MAILBOX_SET_AUTO_NO "no"
+#define MAILBOX_SET_AUTO_CREATE "create"
+#define MAILBOX_SET_AUTO_SUBSCRIBE "subscribe"
+/* </settings checks> */
+struct mailbox_settings {
+	const char *name;
+	const char *autocreate;
+};
+
 struct mail_user_settings {
 	const char *base_dir;
 	const char *auth_socket_path;
@@ -77,6 +87,7 @@
 	const char *mail_log_prefix;
 
 	ARRAY_DEFINE(namespaces, struct mail_namespace_settings *);
+	ARRAY_DEFINE(mailboxes, struct mailbox_settings *);
 	ARRAY_DEFINE(plugin_envs, const char *);
 };
 
@@ -84,6 +95,7 @@
 extern const struct setting_parser_info mail_namespace_setting_parser_info;
 extern const struct setting_parser_info mail_storage_setting_parser_info;
 extern const struct mail_namespace_settings mail_namespace_default_settings;
+extern const struct mailbox_settings mailbox_default_settings;
 
 const void *
 mail_user_set_get_driver_settings(const struct setting_parser_info *info,
diff -r b48fb6a08389 -r ee783a878120 src/lib-storage/mail-storage.c
--- a/src/lib-storage/mail-storage.c	Fri Dec 02 14:49:08 2011 +0200
+++ b/src/lib-storage/mail-storage.c	Fri Dec 02 16:22:31 2011 +0200
@@ -602,6 +602,18 @@
 	return TRUE;
 }
 
+static struct mailbox_settings *
+mailbox_settings_find(struct mail_user *user, const char *vname)
+{
+	struct mailbox_settings *const *box_set;
+
+	array_foreach(&user->set->mailboxes, box_set) {
+		if (strcmp((*box_set)->name, vname) == 0)
+			return *box_set;
+	}
+	return NULL;
+}
+
 struct mailbox *mailbox_alloc(struct mailbox_list *list, const char *vname,
 			      enum mailbox_flags flags)
 {
@@ -628,6 +640,7 @@
 
 	T_BEGIN {
 		box = storage->v.mailbox_alloc(storage, new_list, vname, flags);
+		box->set = mailbox_settings_find(storage->user, vname);
 		hook_mailbox_allocated(box);
 	} T_END;
 
@@ -704,6 +717,14 @@
 	return FALSE;
 }
 
+static bool mailbox_is_autocreated(struct mailbox *box)
+{
+	if (box->inbox_user)
+		return TRUE;
+	return box->set != NULL &&
+		strcmp(box->set->autocreate, MAILBOX_SET_AUTO_NO) != 0;
+}
+
 int mailbox_exists(struct mailbox *box, bool auto_boxes,
 		   enum mailbox_existence *existence_r)
 {
@@ -732,8 +753,7 @@
 		return 0;
 	}
 
-	if (strcmp(box->name, "INBOX") == 0 && box->inbox_user && auto_boxes) {
-		/* INBOX always exists */
+	if (auto_boxes && box->set != NULL && mailbox_is_autocreated(box)) {
 		*existence_r = MAILBOX_EXISTENCE_SELECT;
 		return 0;
 	}
@@ -788,6 +808,47 @@
 	return 0;
 }
 
+static void mailbox_autocreate(struct mailbox *box)
+{
+	const char *errstr;
+	enum mail_error error;
+
+	if (mailbox_create(box, NULL, FALSE) < 0) {
+		errstr = mailbox_get_last_error(box, &error);
+		if (error != MAIL_ERROR_NOTFOUND && !box->inbox_user) {
+			mail_storage_set_critical(box->storage,
+				"Failed to autocreate mailbox %s: %s",
+				box->vname, errstr);
+		}
+	} else if (box->set != NULL &&
+		   strcmp(box->set->autocreate,
+			  MAILBOX_SET_AUTO_SUBSCRIBE) == 0) {
+		if (mailbox_set_subscribed(box, TRUE) < 0) {
+			mail_storage_set_critical(box->storage,
+				"Failed to autosubscribe to mailbox %s: %s",
+				box->vname, mailbox_get_last_error(box, NULL));
+		}
+	}
+}
+
+static int mailbox_autocreate_and_reopen(struct mailbox *box)
+{
+	int ret;
+
+	mailbox_autocreate(box);
+	mailbox_close(box);
+
+	ret = box->v.open(box);
+	if (ret < 0 && box->inbox_user &&
+	    !box->storage->user->inbox_open_error_logged) {
+		box->storage->user->inbox_open_error_logged = TRUE;
+		mail_storage_set_critical(box->storage,
+			"Opening INBOX failed: %s",
+			mailbox_get_last_error(box, NULL));
+	}
+	return ret;
+}
+
 static int mailbox_open_full(struct mailbox *box, struct istream *input)
 {
 	int ret;
@@ -832,16 +893,8 @@
 	} T_END;
 
 	if (ret < 0 && box->storage->error == MAIL_ERROR_NOTFOUND &&
-	    box->input == NULL && box->inbox_user) T_BEGIN {
-		/* INBOX should always exist. try to create it and retry. */
-		(void)mailbox_create(box, NULL, FALSE);
-		mailbox_close(box);
-		ret = box->v.open(box);
-		if (ret < 0 && !box->storage->user->inbox_open_error_logged) {
-			box->storage->user->inbox_open_error_logged = TRUE;
-			i_error("Opening INBOX failed: %s",
-				mailbox_get_last_error(box, NULL));
-		}
+	    box->input == NULL && mailbox_is_autocreated(box)) T_BEGIN {
+		ret = mailbox_autocreate_and_reopen(box);
 	} T_END;
 
 	if (ret < 0) {
diff -r b48fb6a08389 -r ee783a878120 src/lib-storage/mailbox-list-iter.c
--- a/src/lib-storage/mailbox-list-iter.c	Fri Dec 02 14:49:08 2011 +0200
+++ b/src/lib-storage/mailbox-list-iter.c	Fri Dec 02 16:22:31 2011 +0200
@@ -1,10 +1,35 @@
 /* Copyright (c) 2006-2011 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
+#include "array.h"
 #include "imap-match.h"
 #include "mailbox-tree.h"
 #include "mailbox-list-private.h"
 
+enum autocreate_match_result {
+	/* list contains the mailbox */
+	AUTOCREATE_MATCH_RESULT_YES		= 0x01,
+	/* list contains children of the mailbox */
+	AUTOCREATE_MATCH_RESULT_CHILDREN	= 0x02,
+	/* list contains parents of the mailbox */
+	AUTOCREATE_MATCH_RESULT_PARENT		= 0x04
+};
+
+struct autocreate_box {
+	const char *name;
+	enum mailbox_info_flags flags;
+	bool child_listed;
+};


More information about the dovecot-cvs mailing list