dovecot-2.2: quota: Added support for SETQUOTA IMAP command.
dovecot at dovecot.org
dovecot at dovecot.org
Sun Dec 8 21:26:49 EET 2013
details: http://hg.dovecot.org/dovecot-2.2/rev/fa84a2cd1dce
changeset: 17046:fa84a2cd1dce
user: Timo Sirainen <tss at iki.fi>
date: Sun Dec 08 21:26:29 2013 +0200
description:
quota: Added support for SETQUOTA IMAP command.
The configuration is done via quota_set setting. Currently only dict backend
is supported. For example:
plugin {
quota_set = dict:file:/var/lib/dovecot/quota/%u
}
The SETQUOTA command is available only for the "admin" user (userdb lookup
must return admin=y).
diffstat:
src/plugins/imap-quota/imap-quota-plugin.c | 5 ++
src/plugins/quota/quota-private.h | 2 +
src/plugins/quota/quota.c | 70 ++++++++++++++++++++++++++---
3 files changed, 69 insertions(+), 8 deletions(-)
diffs (150 lines):
diff -r 51edc7daf7f0 -r fa84a2cd1dce src/plugins/imap-quota/imap-quota-plugin.c
--- a/src/plugins/imap-quota/imap-quota-plugin.c Sun Dec 08 21:24:10 2013 +0200
+++ b/src/plugins/imap-quota/imap-quota-plugin.c Sun Dec 08 21:26:29 2013 +0200
@@ -186,6 +186,11 @@
return TRUE;
}
+ if (!cmd->client->user->admin) {
+ client_send_tagline(cmd, "NO Quota can be changed only by admin.");
+ return TRUE;
+ }
+
for (; !IMAP_ARG_IS_EOL(list_args); list_args += 2) {
if (!imap_arg_get_atom(&list_args[0], &name) ||
!imap_arg_get_atom(&list_args[1], &value_str) ||
diff -r 51edc7daf7f0 -r fa84a2cd1dce src/plugins/quota/quota-private.h
--- a/src/plugins/quota/quota-private.h Sun Dec 08 21:24:10 2013 +0200
+++ b/src/plugins/quota/quota-private.h Sun Dec 08 21:26:29 2013 +0200
@@ -88,6 +88,7 @@
struct quota_rule default_rule;
ARRAY(struct quota_rule) rules;
ARRAY(struct quota_warning_rule) warning_rules;
+ const char *limit_set;
/* If user is under quota before saving a mail, allow the last mail to
bring the user over quota by this many bytes. */
@@ -104,6 +105,7 @@
struct quota_root_settings *set;
struct quota *quota;
struct quota_backend backend;
+ struct dict *limit_set_dict;
/* this quota root applies only to this namespace. it may also be
a public namespace without an owner. */
diff -r 51edc7daf7f0 -r fa84a2cd1dce src/plugins/quota/quota.c
--- a/src/plugins/quota/quota.c Sun Dec 08 21:24:10 2013 +0200
+++ b/src/plugins/quota/quota.c Sun Dec 08 21:26:29 2013 +0200
@@ -7,6 +7,7 @@
#include "net.h"
#include "write-full.h"
#include "eacces-error.h"
+#include "dict.h"
#include "mailbox-list-private.h"
#include "quota-private.h"
#include "quota-fs.h"
@@ -20,6 +21,7 @@
"Quota exceeded (mailbox for user is full)"
#define RULE_NAME_DEFAULT_FORCE "*"
#define RULE_NAME_DEFAULT_NONFORCE "?"
+#define QUOTA_LIMIT_SET_PATH DICT_PATH_PRIVATE"quota/limit/"
struct quota_root_iter {
struct quota *quota;
@@ -111,6 +113,26 @@
}
static int
+quota_root_parse_set(struct mail_user *user, const char *root_name,
+ struct quota_root_settings *root_set,
+ const char **error_r)
+{
+ const char *name, *value;
+
+ name = t_strconcat(root_name, "_set", NULL);
+ value = mail_user_plugin_getenv(user, name);
+ if (value == NULL)
+ return 0;
+
+ if (strncmp(value, "dict:", 5) != 0) {
+ *error_r = t_strdup_printf("%s supports only dict backend", name);
+ return -1;
+ }
+ root_set->limit_set = p_strdup(root_set->set->pool, value+5);
+ return 0;
+}
+
+static int
quota_root_settings_init(struct quota_settings *quota_set, const char *root_def,
struct quota_root_settings **set_r,
const char **error_r)
@@ -182,6 +204,8 @@
return -1;
if (quota_root_parse_grace(user, root_name, root_set, error_r) < 0)
return -1;
+ if (quota_root_parse_set(user, root_name, root_set, error_r) < 0)
+ return -1;
return 0;
}
@@ -246,6 +270,8 @@
{
pool_t pool = root->pool;
+ if (root->limit_set_dict != NULL)
+ dict_deinit(&root->limit_set_dict);
root->backend.v.deinit(root);
pool_unref(&pool);
}
@@ -972,15 +998,43 @@
return *limit_r == 0 ? 0 : 1;
}
-int quota_set_resource(struct quota_root *root ATTR_UNUSED,
- const char *name ATTR_UNUSED,
- uint64_t value ATTR_UNUSED, const char **error_r)
+int quota_set_resource(struct quota_root *root, const char *name,
+ uint64_t value, const char **error_r)
{
- /* the quota information comes from userdb (or even config file),
- so there's really no way to support this until some major changes
- are done */
- *error_r = MAIL_ERRSTR_NO_PERMISSION;
- return -1;
+ struct dict_transaction_context *trans;
+ const char *key;
+
+ if (root->set->limit_set == NULL) {
+ *error_r = MAIL_ERRSTR_NO_PERMISSION;
+ return -1;
+ }
+ if (strcasecmp(name, QUOTA_NAME_STORAGE_KILOBYTES) == 0)
+ key = "storage";
+ else if (strcasecmp(name, QUOTA_NAME_STORAGE_BYTES) == 0)
+ key = "bytes";
+ else if (strcasecmp(name, QUOTA_NAME_MESSAGES) == 0)
+ key = "messages";
+ else {
+ *error_r = t_strdup_printf("Unsupported resource name: %s", name);
+ return -1;
+ }
+
+ if (root->limit_set_dict == NULL) {
+ if (dict_init(root->set->limit_set, DICT_DATA_TYPE_STRING,
+ root->quota->user->username,
+ root->quota->user->set->base_dir,
+ &root->limit_set_dict, error_r) < 0)
+ return -1;
+ }
+
+ trans = dict_transaction_begin(root->limit_set_dict);
+ key = t_strdup_printf(QUOTA_LIMIT_SET_PATH"%s", key);
+ dict_set(trans, key, dec2str(value));
+ if (dict_transaction_commit(&trans) < 0) {
+ *error_r = "Internal quota limit update error";
+ return -1;
+ }
+ return 0;
}
struct quota_transaction_context *quota_transaction_begin(struct mailbox *box)
More information about the dovecot-cvs
mailing list