From: Timo Sirainen Date: Fri, 21 Nov 2008 17:45:57 +0000 (+0200) Subject: Quota works now properly with shared mailboxes. X-Git-Tag: 1.2.alpha4~19 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a443e5aaf632257bfd1e7aa9b3c42c09512bbe43;p=thirdparty%2Fdovecot%2Fcore.git Quota works now properly with shared mailboxes. --HG-- branch : HEAD --- diff --git a/src/lib-storage/mail-user.c b/src/lib-storage/mail-user.c index d8735e9b3e..5f340cc7d8 100644 --- a/src/lib-storage/mail-user.c +++ b/src/lib-storage/mail-user.c @@ -57,6 +57,17 @@ void mail_user_unref(struct mail_user **_user) user->v.deinit(user); } +struct mail_user *mail_user_find(struct mail_user *user, const char *name) +{ + struct mail_namespace *ns; + + for (ns = user->namespaces; ns != NULL; ns = ns->next) { + if (ns->owner != NULL && strcmp(ns->owner->username, name) == 0) + return ns->owner; + } + return NULL; +} + void mail_user_set_home(struct mail_user *user, const char *home) { user->_home = p_strdup(user->pool, home); diff --git a/src/lib-storage/mail-user.h b/src/lib-storage/mail-user.h index bb9edf5125..d4379e5603 100644 --- a/src/lib-storage/mail-user.h +++ b/src/lib-storage/mail-user.h @@ -23,6 +23,9 @@ struct mail_user { /* Either home is set or there is no home for the user. */ unsigned int home_looked_up:1; + /* User is an administrator. Allow operations not normally allowed + for other people. */ + unsigned int admin:1; }; struct mail_user_module_register { @@ -45,6 +48,9 @@ struct mail_user *mail_user_init(const char *username); void mail_user_ref(struct mail_user *user); void mail_user_unref(struct mail_user **user); +/* Find another user from the given user's namespaces. */ +struct mail_user *mail_user_find(struct mail_user *user, const char *name); + /* Specify the user's home directory. This should be called also when it's known that the user doesn't have a home directory to avoid the internal lookup. */ diff --git a/src/plugins/imap-quota/imap-quota-plugin.c b/src/plugins/imap-quota/imap-quota-plugin.c index 287a15932a..29fe3793c7 100644 --- a/src/plugins/imap-quota/imap-quota-plugin.c +++ b/src/plugins/imap-quota/imap-quota-plugin.c @@ -3,6 +3,7 @@ #include "common.h" #include "str.h" #include "imap-quote.h" +#include "mail-namespace.h" #include "commands.h" #include "quota.h" #include "quota-plugin.h" @@ -10,12 +11,28 @@ #include +#define QUOTA_USER_SEPARATOR ':' + const char *imap_quota_plugin_version = PACKAGE_VERSION; +static const char * +imap_quota_root_get_name(struct mail_user *user, struct mail_user *owner, + struct quota_root *root) +{ + const char *name; + + name = quota_root_get_name(root); + if (user == owner) + return name; + return t_strdup_printf("%s%c%s", owner->username, + QUOTA_USER_SEPARATOR, name); +} + static void -quota_send(struct client_command_context *cmd, struct quota_root *root) +quota_send(struct client_command_context *cmd, struct mail_user *owner, + struct quota_root *root) { - const char *const *list; + const char *name, *const *list; string_t *str; unsigned int i; uint64_t value, limit; @@ -23,7 +40,8 @@ quota_send(struct client_command_context *cmd, struct quota_root *root) str = t_str_new(128); str_append(str, "* QUOTA "); - imap_quote_append_string(str, quota_root_get_name(root), FALSE); + name = imap_quota_root_get_name(cmd->client->user, owner, root); + imap_quote_append_string(str, name, FALSE); str_append(str, " ("); list = quota_root_get_resources(root); @@ -47,11 +65,13 @@ quota_send(struct client_command_context *cmd, struct quota_root *root) static bool cmd_getquotaroot(struct client_command_context *cmd) { + struct client *client = cmd->client; struct mail_storage *storage; + struct mail_namespace *ns; struct mailbox *box; struct quota_root_iter *iter; struct quota_root *root; - const char *orig_mailbox, *mailbox; + const char *orig_mailbox, *mailbox, *name; string_t *str; /* */ @@ -71,11 +91,17 @@ static bool cmd_getquotaroot(struct client_command_context *cmd) return TRUE; } - if (quota_set == NULL) { + ns = mail_storage_get_namespace(storage); + if (quota_set == NULL || ns->owner == NULL) { mailbox_close(&box); client_send_tagline(cmd, "OK No quota."); return TRUE; } + if (ns->owner != client->user && !client->user->admin) { + mailbox_close(&box); + client_send_tagline(cmd, "NO Not showing other users' quota."); + return TRUE; + } /* send QUOTAROOT reply */ str = t_str_new(128); @@ -85,15 +111,16 @@ static bool cmd_getquotaroot(struct client_command_context *cmd) iter = quota_root_iter_init(box); while ((root = quota_root_iter_next(iter)) != NULL) { str_append_c(str, ' '); - imap_quote_append_string(str, quota_root_get_name(root), FALSE); + name = imap_quota_root_get_name(client->user, ns->owner, root); + imap_quote_append_string(str, name, FALSE); } quota_root_iter_deinit(&iter); - client_send_line(cmd->client, str_c(str)); + client_send_line(client, str_c(str)); /* send QUOTA reply for each quotaroot */ iter = quota_root_iter_init(box); while ((root = quota_root_iter_next(iter)) != NULL) - quota_send(cmd, root); + quota_send(cmd, ns->owner, root); quota_root_iter_deinit(&iter); mailbox_close(&box); @@ -103,8 +130,9 @@ static bool cmd_getquotaroot(struct client_command_context *cmd) static bool cmd_getquota(struct client_command_context *cmd) { - const char *root_name; + struct mail_user *owner = cmd->client->user; struct quota_root *root; + const char *root_name, *p; /* */ if (!client_read_string_args(cmd, 1, &root_name)) @@ -116,12 +144,23 @@ static bool cmd_getquota(struct client_command_context *cmd) } root = quota_root_lookup(cmd->client->user, root_name); + if (root == NULL && cmd->client->user->admin) { + /* we're an admin. see if there's a quota root for another + user. */ + p = strchr(root_name, QUOTA_USER_SEPARATOR); + if (p != NULL) { + owner = mail_user_find(cmd->client->user, + t_strdup_until(root_name, p)); + root = owner == NULL ? NULL : + quota_root_lookup(owner, p + 1); + } + } if (root == NULL) { client_send_tagline(cmd, "NO Quota root doesn't exist."); return TRUE; } - quota_send(cmd, root); + quota_send(cmd, owner, root); client_send_tagline(cmd, "OK Getquota completed."); return TRUE; } diff --git a/src/plugins/quota/quota-storage.c b/src/plugins/quota/quota-storage.c index db4ae82d09..382a5bb362 100644 --- a/src/plugins/quota/quota-storage.c +++ b/src/plugins/quota/quota-storage.c @@ -524,10 +524,10 @@ void quota_mail_storage_created(struct mail_storage *storage) MODULE_CONTEXT_SET_SELF(storage, quota_storage_module, qstorage); - if (storage->ns->type == NAMESPACE_PRIVATE && + if (storage->ns->owner != NULL && (storage->ns->flags & NAMESPACE_FLAG_INTERNAL) == 0) { - /* register to user's quota roots */ - quota = quota_get_mail_user_quota(storage->ns->user); + /* register to owner's quota roots */ + quota = quota_get_mail_user_quota(storage->ns->owner); quota_add_user_storage(quota, storage); } diff --git a/src/plugins/quota/quota.c b/src/plugins/quota/quota.c index 8a2604afd2..42a360e494 100644 --- a/src/plugins/quota/quota.c +++ b/src/plugins/quota/quota.c @@ -524,7 +524,8 @@ void quota_remove_user_storage(struct mail_storage *storage) struct mail_storage *const *storages; unsigned int i, count; - quota = quota_get_mail_user_quota(storage->ns->user); + quota = storage->ns->owner == NULL ? NULL : + quota_get_mail_user_quota(storage->ns->owner); if (quota == NULL) { /* no quota for this storage */ return; @@ -579,7 +580,7 @@ int quota_root_add_warning_rule(struct quota_root_settings *root_set, struct quota_root_iter * quota_root_iter_init(struct mailbox *box) { - struct mail_user *user = box->storage->ns->user; + struct mail_user *user = box->storage->ns->owner; struct quota_root_iter *iter; iter = i_new(struct quota_root_iter, 1); @@ -717,7 +718,7 @@ int quota_set_resource(struct quota_root *root ATTR_UNUSED, struct quota_transaction_context *quota_transaction_begin(struct mailbox *box) { - struct mail_user *user = box->storage->ns->user; + struct mail_user *user = box->storage->ns->owner; struct quota_transaction_context *ctx; ctx = i_new(struct quota_transaction_context, 1);