Mercurial > dovecot > original-hg > dovecot-2.2
changeset 17046:fa84a2cd1dce
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).
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Sun, 08 Dec 2013 21:26:29 +0200 |
parents | 51edc7daf7f0 |
children | 10ded3e11a8e |
files | src/plugins/imap-quota/imap-quota-plugin.c src/plugins/quota/quota-private.h src/plugins/quota/quota.c |
diffstat | 3 files changed, 69 insertions(+), 8 deletions(-) [+] |
line wrap: on
line diff
--- 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) ||
--- 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. */
--- 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)