changeset 16198:249305f71c73

Merged changes from v2.1 tree.
author Timo Sirainen <tss@iki.fi>
date Fri, 05 Apr 2013 00:13:16 +0300
parents c67d787164fa (current diff) c42846219939 (diff)
children 92c88eca562d
files .hgsigs .hgtags NEWS configure.ac src/auth/auth-request.c src/doveadm/Makefile.am src/doveadm/doveadm-dump-log.c src/doveadm/doveadm-mail-batch.c src/doveadm/doveadm-mail-index.c src/doveadm/doveadm-mail.c src/doveadm/doveadm-mail.h src/indexer/master-connection.c src/lib-index/mail-index-modseq.c src/lib-index/mail-index-sync-update.c src/lib-index/mail-index-transaction-update.c src/lib-index/mail-transaction-log.h src/lib-master/mountpoint-list.c src/lib-storage/index/cydir/cydir-storage.c src/lib-storage/index/dbox-common/dbox-storage.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/mbox/mbox-storage.c src/lib-storage/index/pop3c/pop3c-storage.c src/lib-storage/index/raw/raw-storage.c src/lib-storage/list/mailbox-list-delete.c src/lib-storage/list/mailbox-list-fs.c src/lib-storage/list/mailbox-list-maildir.c src/lib-storage/mailbox-list-private.h src/lib/macros.h src/plugins/acl/acl-mailbox.c src/plugins/virtual/virtual-config.c
diffstat 24 files changed, 309 insertions(+), 46 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsigs	Thu Apr 04 23:35:27 2013 +0300
+++ b/.hgsigs	Fri Apr 05 00:13:16 2013 +0300
@@ -58,6 +58,7 @@
 b314c97d4bbffd01b20f8492592aa422c13e3d55 0 iEYEABECAAYFAlEJlGMACgkQyUhSUUBVismNdQCgggPP/dt1duU1CMYfkpE4Kyc9Ju0An0kphokRqrtppkeqg7pF1JR01Mgq
 fc75811f3c08d80ed339cbb4d37c66f549542ba7 0 iEYEABECAAYFAlEU+CEACgkQyUhSUUBViskh9QCgnqPHUkNvtOioWxo4W7fXjCFLVAwAnR9Z26jgBpoejXDkgwT07wdfYiL3
 018de2aa893a040256cb8cd92b1fc9f3f2bbd09f 0 iEYEABECAAYFAlEmOJEACgkQyUhSUUBVismawgCfbfY6KuH+/AauPkRZs4ish20YeV8Ani5DMLh02DUyJvDIpVPJMmTn2Mu/
+582108c190f88597c5215279cb66f74673144c9b 0 iEUEABECAAYFAlFd69UACgkQyUhSUUBVisk/aQCYyYU9JcDM3SrTZu1oJuS26IAnZACeM400zLRROTaM6QYBVKTqTnfpuBY=
 508d46f858153c85ae777e87e1c5143a534a51fe 0 iEYEABECAAYFAlErhDkACgkQyUhSUUBViskRdwCeJ61F0qLZ/3xxIQruTujzo0AEWK0An3PH7nkTY7ouyBdUr0QCra5KLXEZ
 e62fa121f4a2db3348fd79bb176dd363cc1224bf 0 iEYEABECAAYFAlErsAwACgkQyUhSUUBVismarACbBffm3XY21sfkTsbmF8o8udtRZk4An0ofYy2VminZ3S8EFApHymk/UpNv
 11bd79bf4866b0d728b25717134a6ba972505746 0 iEYEABECAAYFAlFKFqsACgkQyUhSUUBVismbSwCdHgMYWjcwcTM7fD4v6wTd/8/8ZEsAn2THId1zYspMTEMtDg0rlrvjlht4
--- a/.hgtags	Thu Apr 04 23:35:27 2013 +0300
+++ b/.hgtags	Fri Apr 05 00:13:16 2013 +0300
@@ -95,6 +95,7 @@
 b314c97d4bbffd01b20f8492592aa422c13e3d55 2.1.14
 fc75811f3c08d80ed339cbb4d37c66f549542ba7 2.1.15
 018de2aa893a040256cb8cd92b1fc9f3f2bbd09f 2.2.beta2
+582108c190f88597c5215279cb66f74673144c9b 2.1.16
 508d46f858153c85ae777e87e1c5143a534a51fe 2.2.rc1
 e62fa121f4a2db3348fd79bb176dd363cc1224bf 2.2.rc2
 11bd79bf4866b0d728b25717134a6ba972505746 2.2.rc3
--- a/configure.ac	Thu Apr 04 23:35:27 2013 +0300
+++ b/configure.ac	Fri Apr 05 00:13:16 2013 +0300
@@ -297,6 +297,9 @@
 AC_DEFINE_UNQUOTED(DOVECOT_STRING, "$PACKAGE_STRING", Dovecot string)
 AC_DEFINE_UNQUOTED(DOVECOT_VERSION, "$PACKAGE_VERSION", Dovecot version)
 
+AC_DEFINE([DOVECOT_VERSION_MAJOR], regexp(AC_PACKAGE_VERSION, [^\([0-9]+\)\.\([0-9]+\)], [\1]), [Dovecot major version])
+AC_DEFINE([DOVECOT_VERSION_MINOR], regexp(AC_PACKAGE_VERSION, [^\([0-9]+\)\.\([0-9]+\)], [\2]), [Dovecot minor version])
+
 AC_CHECK_HEADERS(strings.h stdint.h unistd.h dirent.h malloc.h inttypes.h \
   sys/uio.h sys/sysmacros.h sys/resource.h sys/select.h libgen.h \
   sys/quota.h sys/fs/ufs_quota.h ufs/ufs/quota.h jfs/quota.h \
--- a/src/auth/auth-request.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/auth/auth-request.c	Fri Apr 05 00:13:16 2013 +0300
@@ -1304,6 +1304,18 @@
 	return TRUE;
 }
 
+static void
+auth_request_passdb_import(struct auth_request *request, const char *args,
+			   const char *key_prefix, const char *default_scheme)
+{
+	const char *const *arg, *field;
+
+	for (arg = t_strsplit(args, "\t"); *arg != NULL; arg++) {
+		field = t_strconcat(key_prefix, *arg, NULL);
+		auth_request_set_field_keyvalue(request, field, default_scheme);
+	}
+}
+
 void auth_request_set_field(struct auth_request *request,
 			    const char *name, const char *value,
 			    const char *default_scheme)
@@ -1350,6 +1362,17 @@
 		request->passdb_password = NULL;
 		auth_fields_add(request->extra_fields, name, value, 0);
 		return;
+	} else if (strcmp(name, "passdb_import") == 0) {
+		auth_request_passdb_import(request, value, "", default_scheme);
+		return;
+		if (strcmp(name, "userdb_userdb_import") == 0) {
+			/* we need can't put the whole userdb_userdb_import
+			   value to extra_cache_fields or it doesn't work
+			   properly. so handle this explicitly. */
+			auth_request_passdb_import(request, value,
+						   "userdb_", default_scheme);
+			return;
+		}
 	} else {
 		/* these fields are returned to client */
 		auth_fields_add(request->extra_fields, name, value, 0);
@@ -1422,6 +1445,24 @@
 	}
 }
 
+static void
+auth_request_userdb_import(struct auth_request *request, const char *args)
+{
+	const char *key, *value, *const *arg;
+
+	for (arg = t_strsplit(args, "\t"); *arg != NULL; arg++) {
+		value = strchr(*arg, '=');
+		if (value == NULL) {
+			key = *arg;
+			value = "";
+		} else {
+			key = t_strdup_until(*arg, value);
+			value++;
+		}
+		auth_request_set_userdb_field(request, key, value);
+	}
+}
+
 void auth_request_set_userdb_field(struct auth_request *request,
 				   const char *name, const char *value)
 {
@@ -1451,7 +1492,7 @@
 		auth_request_set_uidgid_file(request, value);
 		return;
 	} else if (strcmp(name, "userdb_import") == 0) {
-		auth_fields_import(request->userdb_reply, value, 0);
+		auth_request_userdb_import(request, value);
 		return;
 	} else if (strcmp(name, "system_user") == 0) {
 		/* FIXME: the system_user is for backwards compatibility */
--- a/src/doveadm/Makefile.am	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/doveadm/Makefile.am	Fri Apr 05 00:13:16 2013 +0300
@@ -61,6 +61,7 @@
 common = \
 	doveadm-mail.c \
 	doveadm-mail-altmove.c \
+	doveadm-mail-batch.c \
 	doveadm-mail-expunge.c \
 	doveadm-mail-fetch.c \
 	doveadm-mail-import.c \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-mail-batch.c	Fri Apr 05 00:13:16 2013 +0300
@@ -0,0 +1,162 @@
+/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "doveadm-mail.h"
+
+#include <unistd.h>
+
+struct batch_cmd_context {
+	struct doveadm_mail_cmd_context ctx;
+	ARRAY(struct doveadm_mail_cmd_context *) commands;
+};
+
+static int cmd_batch_prerun(struct doveadm_mail_cmd_context *_ctx,
+			    struct mail_storage_service_user *service_user,
+			    const char **error_r)
+{
+	struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx;
+	struct doveadm_mail_cmd_context *const *cmdp;
+	int ret = 0;
+
+	array_foreach(&ctx->commands, cmdp) {
+		if ((*cmdp)->v.prerun != NULL &&
+		    (*cmdp)->v.prerun(*cmdp, service_user, error_r) < 0) {
+			ret = -1;
+			break;
+		}
+	}
+	return ret;
+}
+
+static int cmd_batch_run(struct doveadm_mail_cmd_context *_ctx,
+			 struct mail_user *user)
+{
+	struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx;
+	struct doveadm_mail_cmd_context *const *cmdp;
+	int ret = 0;
+
+	array_foreach(&ctx->commands, cmdp) {
+		if ((*cmdp)->v.run(*cmdp, user) < 0) {
+			ret = -1;
+			break;
+		}
+	}
+	return ret;
+}
+
+static void
+cmd_batch_add(struct batch_cmd_context *batchctx,
+	      int argc, const char *const *argv)
+{
+	struct doveadm_mail_cmd_context *subctx;
+	const struct doveadm_mail_cmd *cmd;
+	const char *getopt_args;
+	int c;
+
+	cmd = doveadm_mail_cmd_find_from_argv(argv[0], &argc, &argv);
+	if (cmd == NULL) {
+		i_fatal_status(EX_USAGE, "doveadm batch: Unknown subcommand %s",
+			       argv[1]);
+	}
+
+	subctx = doveadm_mail_cmd_init(cmd, doveadm_settings);
+	subctx->full_args = argv + 1;
+	subctx->service_flags |= batchctx->ctx.service_flags;
+
+	optind = 1;
+	getopt_args = subctx->getopt_args != NULL ? subctx->getopt_args : "";
+	while ((c = getopt(argc, (void *)argv, getopt_args)) > 0) {
+		if (subctx->v.parse_arg == NULL ||
+		    !subctx->v.parse_arg(subctx, c))
+			doveadm_mail_help(cmd);
+	}
+	argv += optind;
+	if (argv[0] != NULL && cmd->usage_args == NULL) {
+		i_fatal_status(EX_USAGE, "doveadm %s: Unknown parameter: %s",
+			       cmd->name, argv[0]);
+	}
+	subctx->args = argv;
+	if (subctx->v.preinit != NULL)
+		subctx->v.preinit(subctx);
+	array_append(&batchctx->commands, &subctx, 1);
+}
+
+static void
+cmd_batch_preinit(struct doveadm_mail_cmd_context *_ctx)
+{
+	const char *const *args = _ctx->args;
+	struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx;
+	ARRAY_TYPE(const_string) sep_args;
+	const char *sep = args[0];
+	unsigned int i, start;
+	int argc;
+	const char *const *argv;
+
+	if (sep == NULL || args[1] == NULL)
+		doveadm_mail_help_name("batch");
+	args++;
+
+	p_array_init(&ctx->commands, _ctx->pool, 8);
+	p_array_init(&sep_args, _ctx->pool, 16);
+	for (i = start = 0;; i++) {
+		if (args[i] != NULL && strcmp(args[i], sep) != 0) {
+			array_append(&sep_args, &args[i], 1);
+			continue;
+		}
+		if (i > start) {
+			(void)array_append_space(&sep_args);
+			argc = i - start;
+			argv = array_idx(&sep_args, start);
+			cmd_batch_add(ctx, argc, argv);
+			start = i+1;
+		}
+		if (args[i] == NULL)
+			break;
+	}
+	(void)array_append_space(&sep_args);
+}
+
+static void
+cmd_batch_init(struct doveadm_mail_cmd_context *_ctx,
+	       const char *const args[] ATTR_UNUSED)
+{
+	struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx;
+	struct doveadm_mail_cmd_context *const *cmdp;
+	struct batch_cmd_context *subctx;
+
+	array_foreach(&ctx->commands, cmdp) {
+		subctx = (struct batch_cmd_context *)*cmdp;
+		subctx->ctx.storage_service = _ctx->storage_service;
+		if (subctx->ctx.v.init != NULL)
+			subctx->ctx.v.init(&subctx->ctx, subctx->ctx.args);
+	}
+}
+
+static void cmd_batch_deinit(struct doveadm_mail_cmd_context *_ctx)
+{
+	struct batch_cmd_context *ctx = (struct batch_cmd_context *)_ctx;
+	struct doveadm_mail_cmd_context *const *cmdp;
+
+	array_foreach(&ctx->commands, cmdp) {
+		if ((*cmdp)->v.deinit != NULL)
+			(*cmdp)->v.deinit(*cmdp);
+	}
+}
+
+static struct doveadm_mail_cmd_context *cmd_batch_alloc(void)
+{
+	struct batch_cmd_context *ctx;
+
+	ctx = doveadm_mail_cmd_alloc(struct batch_cmd_context);
+	ctx->ctx.v.preinit = cmd_batch_preinit;
+	ctx->ctx.v.init = cmd_batch_init;
+	ctx->ctx.v.prerun = cmd_batch_prerun;
+	ctx->ctx.v.run = cmd_batch_run;
+	ctx->ctx.v.deinit = cmd_batch_deinit;
+	return &ctx->ctx;
+}
+
+struct doveadm_mail_cmd cmd_batch = {
+	cmd_batch_alloc, "batch", "<sep> <cmd1> [<sep> <cmd2> [..]]"
+};
--- a/src/doveadm/doveadm-mail.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/doveadm/doveadm-mail.c	Fri Apr 05 00:13:16 2013 +0300
@@ -539,59 +539,78 @@
 }
 
 static bool
-doveadm_mail_try_run_multi_word(const struct doveadm_mail_cmd *cmd,
-				const char *cmdname, int argc, char *argv[])
+doveadm_mail_cmd_try_find_multi_word(const struct doveadm_mail_cmd *cmd,
+				     const char *cmdname, int *argc,
+				     const char *const **argv)
 {
 	unsigned int len;
 
-	if (argc < 2)
+	if (*argc < 2)
 		return FALSE;
+	*argc -= 1;
+	*argv += 1;
 
-	len = strlen(argv[1]);
-	if (strncmp(cmdname, argv[1], len) != 0)
+	len = strlen((*argv)[0]);
+	if (strncmp(cmdname, (*argv)[0], len) != 0)
 		return FALSE;
 
 	if (cmdname[len] == ' ') {
 		/* more args */
-		return doveadm_mail_try_run_multi_word(cmd, cmdname + len + 1,
-						       argc - 1, argv + 1);
+		return doveadm_mail_cmd_try_find_multi_word(cmd, cmdname + len + 1,
+							    argc, argv);
 	}
 	if (cmdname[len] != '\0')
 		return FALSE;
 
 	/* match */
-	doveadm_mail_cmd(cmd, argc - 1, argv + 1);
 	return TRUE;
 }
 
-bool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
+const struct doveadm_mail_cmd *
+doveadm_mail_cmd_find_from_argv(const char *cmd_name, int *argc,
+				const char *const **argv)
 {
 	const struct doveadm_mail_cmd *cmd;
 	unsigned int cmd_name_len;
+	const char *const *orig_argv;
+	int orig_argc;
 
-	i_assert(argc > 0);
+	i_assert(*argc > 0);
 
 	cmd_name_len = strlen(cmd_name);
 	array_foreach(&doveadm_mail_cmds, cmd) {
-		if (strcmp(cmd->name, cmd_name) == 0) {
-			doveadm_mail_cmd(cmd, argc, argv);
-			return TRUE;
-		}
+		if (strcmp(cmd->name, cmd_name) == 0)
+			return cmd;
 
 		/* see if it matches a multi-word command */
 		if (strncmp(cmd->name, cmd_name, cmd_name_len) == 0 &&
 		    cmd->name[cmd_name_len] == ' ') {
 			const char *subcmd = cmd->name + cmd_name_len + 1;
 
-			if (doveadm_mail_try_run_multi_word(cmd, subcmd,
-							    argc, argv))
-				return TRUE;
+			orig_argc = *argc;
+			orig_argv = *argv;
+			if (doveadm_mail_cmd_try_find_multi_word(cmd, subcmd,
+								 argc, argv))
+				return cmd;
+			*argc = orig_argc;
+			*argv = orig_argv;
 		}
 	}
 
 	return FALSE;
 }
 
+bool doveadm_mail_try_run(const char *cmd_name, int argc, char *argv[])
+{
+	const struct doveadm_mail_cmd *cmd;
+
+	cmd = doveadm_mail_cmd_find_from_argv(cmd_name, &argc, (void *)&argv);
+	if (cmd == NULL)
+		return FALSE;
+	doveadm_mail_cmd(cmd, argc, argv);
+	return TRUE;
+}
+
 void doveadm_mail_register_cmd(const struct doveadm_mail_cmd *cmd)
 {
 	/* for now we'll just assume that cmd will be permanently in memory */
@@ -684,6 +703,7 @@
 	&cmd_mailbox_subscribe,
 	&cmd_mailbox_unsubscribe,
 	&cmd_mailbox_status,
+	&cmd_batch,
 	&cmd_dsync_backup,
 	&cmd_dsync_mirror,
 	&cmd_dsync_server
--- a/src/doveadm/doveadm-mail.h	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/doveadm/doveadm-mail.h	Fri Apr 05 00:13:16 2013 +0300
@@ -97,6 +97,9 @@
 void doveadm_mail_init(void);
 void doveadm_mail_deinit(void);
 
+const struct doveadm_mail_cmd *
+doveadm_mail_cmd_find_from_argv(const char *cmd_name, int *argc,
+				const char *const **argv);
 struct doveadm_mail_cmd_context *
 doveadm_mail_cmd_init(const struct doveadm_mail_cmd *cmd,
 		      const struct doveadm_settings *set);
@@ -147,5 +150,6 @@
 extern struct doveadm_mail_cmd cmd_mailbox_subscribe;
 extern struct doveadm_mail_cmd cmd_mailbox_unsubscribe;
 extern struct doveadm_mail_cmd cmd_mailbox_status;
+struct doveadm_mail_cmd cmd_batch;
 
 #endif
--- a/src/lib-index/mail-index-transaction-update.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-index/mail-index-transaction-update.c	Fri Apr 05 00:13:16 2013 +0300
@@ -896,8 +896,8 @@
 	struct mail_index_transaction_ext_hdr_update *hdr;
 	size_t new_size;
 
-	i_assert(offset <= (uint16_t)-1 && size <= (uint16_t)-1 &&
-		 offset + size <= (uint16_t)-1);
+	i_assert(offset <= (uint32_t)-1 && size <= (uint32_t)-1 &&
+		 offset + size <= (uint32_t)-1);
 
 	if (!array_is_created(&t->ext_hdr_updates))
 		i_array_init(&t->ext_hdr_updates, ext_id + 2);
--- a/src/lib-master/mountpoint-list.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-master/mountpoint-list.c	Fri Apr 05 00:13:16 2013 +0300
@@ -56,6 +56,8 @@
 	"/sys",
 	"/proc",
 	"/var/run",
+	"/var/tmp",
+	"/tmp",
 	"/run",
 #ifdef __APPLE__
 	"/Volumes",
--- a/src/lib-storage/index/cydir/cydir-storage.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Fri Apr 05 00:13:16 2013 +0300
@@ -67,7 +67,7 @@
 		/* exists, open it */
 	} else if (errno == ENOENT) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
 		return -1;
 	} else if (errno == EACCES) {
 		mail_storage_set_critical(box->storage, "%s",
--- a/src/lib-storage/index/dbox-common/dbox-storage.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/index/dbox-common/dbox-storage.c	Fri Apr 05 00:13:16 2013 +0300
@@ -202,7 +202,7 @@
 		;
 	else if (errno == ENOENT || errno == ENAMETOOLONG) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
 		return -1;
 	} else if (errno == EACCES) {
 		mail_storage_set_critical(box->storage, "%s",
--- a/src/lib-storage/index/maildir/maildir-storage.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Fri Apr 05 00:13:16 2013 +0300
@@ -367,7 +367,7 @@
 
 	if (errno == ENOENT || errno == ENAMETOOLONG) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
 		return -1;
 	} else {
 		mail_storage_set_critical(box->storage,
--- a/src/lib-storage/index/mbox/mbox-storage.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/index/mbox/mbox-storage.c	Fri Apr 05 00:13:16 2013 +0300
@@ -484,7 +484,7 @@
 		return -1;
 	} else if (ENOTFOUND(errno)) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+			T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
 		return -1;
 	} else if (mail_storage_set_error_from_errno(box->storage)) {
 		return -1;
--- a/src/lib-storage/index/pop3c/pop3c-storage.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/index/pop3c/pop3c-storage.c	Fri Apr 05 00:13:16 2013 +0300
@@ -164,7 +164,7 @@
 
 	if (strcmp(box->name, "INBOX") != 0) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
-				       T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+				       T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
 		return -1;
 	}
 
--- a/src/lib-storage/index/raw/raw-storage.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/index/raw/raw-storage.c	Fri Apr 05 00:13:16 2013 +0300
@@ -161,7 +161,7 @@
 		if (ENOTFOUND(errno)) {
 			mail_storage_set_error(box->storage,
 				MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
 		} else if (!mail_storage_set_error_from_errno(box->storage)) {
 			mail_storage_set_critical(box->storage,
 				"open(%s) failed: %m", path);
--- a/src/lib-storage/list/mailbox-list-delete.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/list/mailbox-list-delete.c	Fri Apr 05 00:13:16 2013 +0300
@@ -69,7 +69,7 @@
 				continue;
 			}
 			mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+				T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
 			return -1;
 		}
 		if (errno == EXDEV) {
@@ -126,7 +126,7 @@
 		return 0;
 	else if (ENOTFOUND(errno)) {
 		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-				       T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+				       T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
 		return -1;
 	} else {
 		if (!mailbox_list_set_error_from_errno(list)) {
@@ -154,7 +154,7 @@
 	if (dir == NULL) {
 		if (errno == ENOENT) {
 			mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+				T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
 		} else {
 			if (!mailbox_list_set_error_from_errno(list)) {
 				mailbox_list_set_critical(list,
@@ -342,7 +342,7 @@
 
 	if (errno == ENOENT) {
 		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+			T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
 	} else if (errno == EISDIR ||
 		   errno == EPERM) { /* Solaris */
 		mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
--- a/src/lib-storage/list/mailbox-list-fs.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/list/mailbox-list-fs.c	Fri Apr 05 00:13:16 2013 +0300
@@ -275,7 +275,7 @@
 
 	if (errno == ENOENT || errno == ENOTDIR) {
 		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+			T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
 	} else if (errno == ENOTEMPTY || errno == EEXIST) {
 		/* mbox workaround: if only .imap/ directory is preventing the
 		   deletion, remove it */
@@ -458,7 +458,7 @@
 	if (rename(oldpath, newpath) < 0) {
 		if (ENOTFOUND(errno)) {
 			mailbox_list_set_error(oldlist, MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(oldname));
+				T_MAILBOX_LIST_ERR_NOT_FOUND(oldlist, oldname));
 		} else if (!mailbox_list_set_error_from_errno(oldlist)) {
 			mailbox_list_set_critical(oldlist,
 				"rename(%s, %s) failed: %m", oldpath, newpath);
--- a/src/lib-storage/list/mailbox-list-maildir.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/list/mailbox-list-maildir.c	Fri Apr 05 00:13:16 2013 +0300
@@ -263,7 +263,7 @@
 				       "Mailbox exists");
 	} else if (errno == ENOENT || errno == ENOTDIR) {
 		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
+			T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
 	} else {
 		mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
 	}
@@ -450,7 +450,7 @@
 			return -1;
 		if (!found && ret == 0) {
 			mailbox_list_set_error(oldlist, MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(oldname));
+				T_MAILBOX_LIST_ERR_NOT_FOUND(oldlist, oldname));
 			return -1;
 		}
 
--- a/src/lib-storage/mailbox-list-private.h	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib-storage/mailbox-list-private.h	Fri Apr 05 00:13:16 2013 +0300
@@ -16,6 +16,10 @@
 
 #define MAILBOX_LOG_FILE_NAME "dovecot.mailbox.log"
 
+#define T_MAILBOX_LIST_ERR_NOT_FOUND(list, name) \
+	t_strdup_printf(MAIL_ERRSTR_MAILBOX_NOT_FOUND, \
+			mailbox_list_get_vname(list, name))
+
 struct stat;
 struct dirent;
 struct imap_match_glob;
--- a/src/lib/macros.h	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/lib/macros.h	Fri Apr 05 00:13:16 2013 +0300
@@ -207,4 +207,12 @@
 #define i_unreached() \
 	i_panic("file %s: line %d: unreached", __FILE__, __LINE__)
 
+/* Convenience macros to test the versions of dovecot. */
+#if defined DOVECOT_VERSION_MAJOR && defined DOVECOT_VERSION_MINOR
+#  define DOVECOT_PREREQ(maj, min) \
+          ((DOVECOT_VERSION_MAJOR << 16) + DOVECOT_VERSION_MINOR >= ((maj) << 16) + (min))
+#else
+#  define DOVECOT_PREREQ(maj, min) 0
 #endif
+
+#endif
--- a/src/plugins/acl/acl-mailbox.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/plugins/acl/acl-mailbox.c	Fri Apr 05 00:13:16 2013 +0300
@@ -151,7 +151,7 @@
 				       MAIL_ERRSTR_NO_PERMISSION);
 	} else if (ret == 0) {
 		mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
+				T_MAIL_ERR_MAILBOX_NOT_FOUND(box->vname));
 	}
 }
 
--- a/src/plugins/quota/quota-status.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/plugins/quota/quota-status.c	Fri Apr 05 00:13:16 2013 +0300
@@ -21,6 +21,7 @@
 	struct connection conn;
 
 	char *recipient;
+	uoff_t size;
 };
 
 static enum quota_protocol protocol;
@@ -42,7 +43,8 @@
 	i_free_and_null(client->recipient);
 }
 
-static int quota_check(struct mail_user *user, const char **error_r)
+static int
+quota_check(struct mail_user *user, uoff_t mail_size, const char **error_r)
 {
 	struct quota_user *quser = QUOTA_USER_CONTEXT(user);
 	struct mail_namespace *ns;
@@ -60,7 +62,7 @@
 	box = mailbox_alloc(ns->list, "INBOX", 0);
 
 	ctx = quota_transaction_begin(box);
-	ret = quota_test_alloc(ctx, 1, &too_large);
+	ret = quota_test_alloc(ctx, I_MAX(1, mail_size), &too_large);
 	quota_transaction_rollback(&ctx);
 
 	mailbox_free(&box);
@@ -77,7 +79,7 @@
 	struct mail_storage_service_input input;
 	struct mail_storage_service_user *service_user;
 	struct mail_user *user;
-	const char *error;
+	const char *value = NULL, *error;
 	int ret;
 
 	if (client->recipient == NULL) {
@@ -92,21 +94,31 @@
 					       &service_user, &user, &error);
 	restrict_access_allow_coredumps(TRUE);
 	if (ret == 0) {
-		o_stream_send_str(client->conn.output,
-				  "action=REJECT Unknown user\n\n");
+		value = mail_user_plugin_getenv(user, "quota_status_nouser");
+		if (value == NULL)
+			value = "REJECT Unknown user";
 	} else if (ret > 0) {
-		if ((ret = quota_check(user, &error)) > 0)
-			o_stream_send_str(client->conn.output, "action=OK\n\n");
-		else if (ret == 0) {
-			o_stream_send_str(client->conn.output, t_strdup_printf(
-					  "action=552 5.2.2 %s\n\n", error));
+		if ((ret = quota_check(user, client->size, &error)) > 0) {
+			/* under quota */
+			value = mail_user_plugin_getenv(user, "quota_status_success");
+			if (value == NULL)
+				value = "OK";
+		} else if (ret == 0) {
+			/* over quota */
+			value = mail_user_plugin_getenv(user, "quota_status_overquota");
+			if (value == NULL)
+				value = t_strdup_printf("552 5.2.2 %s\n\n", error);
 		}
 		mail_user_unref(&user);
 		mail_storage_service_user_free(&service_user);
 	}
 	if (ret < 0) {
+		/* temporary failure */
 		o_stream_send_str(client->conn.output, t_strdup_printf(
 			"action=DEFER_IF_PERMIT %s\n\n", error));
+	} else {
+		o_stream_send_str(client->conn.output,
+				  t_strdup_printf("action=%s\n\n", value));
 	}
 }
 
@@ -124,6 +136,10 @@
 	if (client->recipient == NULL &&
 	    strncmp(line, "recipient=", 10) == 0)
 		client->recipient = i_strdup(line + 10);
+	else if (strncmp(line, "size=", 5) == 0) {
+		if (str_to_uoff(line+5, &client->size) < 0)
+			client->size = 0;
+	}
 	return 1;
 }
 
--- a/src/plugins/virtual/virtual-config.c	Thu Apr 04 23:35:27 2013 +0300
+++ b/src/plugins/virtual/virtual-config.c	Fri Apr 05 00:13:16 2013 +0300
@@ -379,7 +379,7 @@
 				"Virtual mailbox missing configuration file");
 		} else if (errno == ENOENT) {
 			mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
-				T_MAIL_ERR_MAILBOX_NOT_FOUND(mbox->box.name));
+				T_MAIL_ERR_MAILBOX_NOT_FOUND(mbox->box.vname));
 		} else {
 			mail_storage_set_critical(storage,
 				"stat(%s) failed: %m", box_path);