]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Quota works now properly with shared mailboxes.
authorTimo Sirainen <tss@iki.fi>
Fri, 21 Nov 2008 17:45:57 +0000 (19:45 +0200)
committerTimo Sirainen <tss@iki.fi>
Fri, 21 Nov 2008 17:45:57 +0000 (19:45 +0200)
--HG--
branch : HEAD

src/lib-storage/mail-user.c
src/lib-storage/mail-user.h
src/plugins/imap-quota/imap-quota-plugin.c
src/plugins/quota/quota-storage.c
src/plugins/quota/quota.c

index d8735e9b3e18ff618bc697650342fec827fed1bb..5f340cc7d82b6dc4b31270c1e085838c185cae60 100644 (file)
@@ -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);
index bb9edf51253e2b4180a8b712286497e138984319..d4379e560367a07a151287afd11193454098a74e 100644 (file)
@@ -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. */
index 287a15932a101dbaeca0a7f1f430cd4285aa4e8c..29fe3793c78ad19887badc26807b38261dc2eb5b 100644 (file)
@@ -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"
 
 #include <stdlib.h>
 
+#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;
 
        /* <mailbox> */
@@ -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;
 
        /* <quota root> */
        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;
 }
index db4ae82d0904aec634a9ec4dff0afbb34f4948cf..382a5bb362fd9a16035f0ff9bbf7fe04c8305861 100644 (file)
@@ -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);
        }
 
index 8a2604afd2bad79502e3d5d0c63ed340b197a5e7..42a360e49444c8d83d360d21a8eaaec27e22b9d1 100644 (file)
@@ -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);