bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "imap-common.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "str.h"
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen#include "ostream.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "imap-quote.h"
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen#include "mail-namespace.h"
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "imap-commands.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "quota.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "quota-plugin.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "imap-quota-plugin.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen#define QUOTA_USER_SEPARATOR ':'
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
bd63b5b860658b01b1f46f26d406e1e4a9dc019aTimo Sirainenconst char *imap_quota_plugin_version = DOVECOT_ABI_VERSION;
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainenstatic struct module *imap_quota_module;
c1faff067b29fb48426cb84260adba563e93189aTimo Sirainenstatic imap_client_created_func_t *next_hook_client_created;
f6c1297c26b355c4aec2a08978f51ec3efecb351Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenstatic const char *
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainenimap_quota_root_get_name(struct mail_user *user, struct mail_user *owner,
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct quota_root *root)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen{
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen const char *name;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen name = quota_root_get_name(root);
ef2b2ef2e6a6eb5e4667f2e63faae8a3b646e8baTimo Sirainen if (user == owner || owner == NULL)
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen return name;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen return t_strdup_printf("%s%c%s", owner->username,
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen QUOTA_USER_SEPARATOR, name);
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen}
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainenstatic int
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainenquota_reply_write(string_t *str, struct mail_user *user,
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen struct mail_user *owner, struct quota_root *root)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi const char *name, *const *list, *error;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen unsigned int i;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen uint64_t value, limit;
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen size_t prefix_len, orig_len = str_len(str);
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen enum quota_get_result ret = QUOTA_GET_RESULT_UNLIMITED;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append(str, "* QUOTA ");
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen name = imap_quota_root_get_name(user, owner, root);
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen imap_append_astring(str, name);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append(str, " (");
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen prefix_len = str_len(str);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen list = quota_root_get_resources(root);
4ea6c43a08b37f270bd54b5809142246fd118263Timo Sirainen for (i = 0; *list != NULL; list++) {
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi ret = quota_get_resource(root, "", *list, &value, &limit, &error);
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi if (ret == QUOTA_GET_RESULT_INTERNAL_ERROR) {
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi i_error("Failed to get quota resource %s: %s",
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi *list, error);
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen break;
cf41318871bd42358df3420e50614f5310b08c77Martti Rannanjärvi }
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen if (ret == QUOTA_GET_RESULT_LIMITED) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (i > 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append_c(str, ' ');
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi str_printfa(str, "%s %"PRIu64" %"PRIu64, *list,
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi value, limit);
4ea6c43a08b37f270bd54b5809142246fd118263Timo Sirainen i++;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
bffaca7da2825c2a77aa46022358e2f8400a0f94Timo Sirainen if (str_len(str) == prefix_len) {
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen /* this quota root doesn't have any quota actually enabled. */
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen str_truncate(str, orig_len);
bffaca7da2825c2a77aa46022358e2f8400a0f94Timo Sirainen } else {
bffaca7da2825c2a77aa46022358e2f8400a0f94Timo Sirainen str_append(str, ")\r\n");
f162f350e1eacce12288a565657e769d7976dd7fTimo Sirainen }
2e07e3182f355cf04a1461dd7f893d0ebc818764Timo Sirainen return ret == QUOTA_GET_RESULT_INTERNAL_ERROR ? -1 : 0;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool cmd_getquotaroot(struct client_command_context *cmd)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct client *client = cmd->client;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen struct quota_user *quser = QUOTA_USER_CONTEXT(client->user);
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen struct mail_namespace *ns;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mailbox *box;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct quota_root_iter *iter;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct quota_root *root;
7d87a87b360ecac47fe10e7ca5c7e1433dd63004Timo Sirainen const char *mailbox, *orig_mailbox, *name;
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen string_t *quotaroot_reply, *quota_reply;
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen int ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* <mailbox> */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return FALSE;
7d87a87b360ecac47fe10e7ca5c7e1433dd63004Timo Sirainen orig_mailbox = mailbox;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ns = client_find_namespace(cmd, &mailbox);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ns == NULL)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
ef2b2ef2e6a6eb5e4667f2e63faae8a3b646e8baTimo Sirainen if (quser == NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "OK No quota.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
10ccd0e45768923d69be459e87ef6cd2574cec60Timo Sirainen if (ns->owner != NULL && ns->owner != client->user) {
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen client_send_tagline(cmd, "NO Not showing other users' quota.");
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen return TRUE;
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen /* build QUOTAROOT reply and QUOTA reply for all quota roots */
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen quotaroot_reply = t_str_new(128);
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen quota_reply = t_str_new(256);
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen str_append(quotaroot_reply, "* QUOTAROOT ");
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen imap_append_astring(quotaroot_reply, orig_mailbox);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen ret = 0;
d23c747de9d33966483fbdd41f08ad7766da7c5cTimo Sirainen iter = quota_root_iter_init(box);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen while ((root = quota_root_iter_next(iter)) != NULL) {
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen if (quota_root_is_hidden(root))
3f7583189249a28892cd5bd69e15681c7a8a619bTimo Sirainen continue;
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen str_append_c(quotaroot_reply, ' ');
a443e5aaf632257bfd1e7aa9b3c42c09512bbe43Timo Sirainen name = imap_quota_root_get_name(client->user, ns->owner, root);
44f93baa7b8dca7d00bf187cd3db1c15eed384d2Timo Sirainen imap_append_astring(quotaroot_reply, name);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen if (quota_reply_write(quota_reply, client->user, ns->owner, root) < 0)
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen ret = -1;
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen }
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen quota_root_iter_deinit(&iter);
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen mailbox_free(&box);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen /* send replies */
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen if (ret < 0)
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen client_send_tagline(cmd, "NO Internal quota calculation error.");
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen else if (str_len(quota_reply) == 0)
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen client_send_tagline(cmd, "OK No quota.");
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen else {
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen client_send_line(client, str_c(quotaroot_reply));
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen o_stream_nsend(client->output, str_data(quota_reply),
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen str_len(quota_reply));
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen client_send_tagline(cmd, "OK Getquotaroot completed.");
d337f4291d9ea9cd1adee0f468bc0c3baeabb4feTimo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainenstatic bool
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainenparse_quota_root(struct mail_user *user, const char *root_name,
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen struct mail_user **owner_r, struct quota_root **root_r)
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen{
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen const char *p;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen *owner_r = user;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen *root_r = quota_root_lookup(user, root_name);
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen if (*root_r != NULL || !user->admin)
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen return *root_r != NULL;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen /* we're an admin. see if there's a quota root for another user. */
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen p = strchr(root_name, QUOTA_USER_SEPARATOR);
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen if (p != NULL) {
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen *owner_r = mail_user_find(user, t_strdup_until(root_name, p));
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen *root_r = *owner_r == NULL ? NULL :
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen quota_root_lookup(*owner_r, p + 1);
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen }
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen return *root_r != NULL;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen}
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool cmd_getquota(struct client_command_context *cmd)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen struct mail_user *owner;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct quota_root *root;
10ccd0e45768923d69be459e87ef6cd2574cec60Timo Sirainen const char *root_name;
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen string_t *quota_reply;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* <quota root> */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (!client_read_string_args(cmd, 1, &root_name))
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return FALSE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen if (!parse_quota_root(cmd->client->user, root_name, &owner, &root)) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "NO Quota root doesn't exist.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
5a37e34b1b5acf453372cd112c70bb4e46b4bee2Timo Sirainen quota_reply = t_str_new(128);
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen if (quota_reply_write(quota_reply, cmd->client->user, owner, root) < 0)
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen client_send_tagline(cmd, "NO Internal quota calculation error.");
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen else {
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen o_stream_nsend(cmd->client->output, str_data(quota_reply),
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen str_len(quota_reply));
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen client_send_tagline(cmd, "OK Getquota completed.");
f4e66312c54f8f21df984e3b17c0cc752e019ec5Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool cmd_setquota(struct client_command_context *cmd)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct quota_root *root;
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen struct mail_user *owner;
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen const struct imap_arg *args, *list_args;
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen const char *root_name, *name, *value_str, *error;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen uint64_t value;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* <quota root> <resource limits> */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (!client_read_args(cmd, 2, 0, &args))
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return FALSE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen if (!imap_arg_get_astring(&args[0], &root_name) ||
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen !imap_arg_get_list(&args[1], &list_args)) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen if (!cmd->client->user->admin) {
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen client_send_tagline(cmd, "NO Quota can be changed only by admin.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen if (!parse_quota_root(cmd->client->user, root_name, &owner, &root)) {
e5dca7edde333c2759b0e6b1d0d00b94ea303322Timo Sirainen client_send_tagline(cmd, "NO Quota root doesn't exist.");
2521fd0986302cdabc8b0711eef63ac188f32cd6Timo Sirainen return TRUE;
2521fd0986302cdabc8b0711eef63ac188f32cd6Timo Sirainen }
2521fd0986302cdabc8b0711eef63ac188f32cd6Timo Sirainen
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen for (; !IMAP_ARG_IS_EOL(list_args); list_args += 2) {
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen if (!imap_arg_get_atom(&list_args[0], &name) ||
c2fbbf7515aa419dc8b2d62a3c2bb0471d51a391Timo Sirainen !imap_arg_get_atom(&list_args[1], &value_str) ||
9261dbf0675204898c6557591c7aa376e23a52b2Timo Sirainen str_to_uint64(value_str, &value) < 0) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen if (quota_set_resource(root, name, value, &error) < 0) {
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen client_send_command_error(cmd, error);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "OK Setquota completed.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void imap_quota_client_created(struct client **client)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen if (mail_user_is_plugin_loaded((*client)->user, imap_quota_module))
2c719bcb92302f45df4badb71d1d97f57235d0ccTimo Sirainen client_add_capability(*client, "QUOTA");
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (next_hook_client_created != NULL)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen next_hook_client_created(client);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainenvoid imap_quota_plugin_init(struct module *module)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
66a872b4569c048e804f0731680d89c6042d8890Timo Sirainen command_register("GETQUOTAROOT", cmd_getquotaroot, 0);
66a872b4569c048e804f0731680d89c6042d8890Timo Sirainen command_register("GETQUOTA", cmd_getquota, 0);
66a872b4569c048e804f0731680d89c6042d8890Timo Sirainen command_register("SETQUOTA", cmd_setquota, 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
cd2cd224d3216a243d55c71c298a5b7684de0ac4Timo Sirainen imap_quota_module = module;
ac0fed903142d28ae3a1d5d00d2097fdf161b138Timo Sirainen next_hook_client_created =
ac0fed903142d28ae3a1d5d00d2097fdf161b138Timo Sirainen imap_client_created_hook_set(imap_quota_client_created);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
f8da06de93e28b5d3e039a427cdde7e1e15daec8Timo Sirainenvoid imap_quota_plugin_deinit(void)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen command_unregister("GETQUOTAROOT");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen command_unregister("GETQUOTA");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen command_unregister("SETQUOTA");
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen imap_client_created_hook_set(next_hook_client_created);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
23fdad6c7e2581921f511e24cd9371c9eaebcef9Timo Sirainen
23fdad6c7e2581921f511e24cd9371c9eaebcef9Timo Sirainenconst char *imap_quota_plugin_dependencies[] = { "quota", NULL };
8552b0cad8ffe9ccb8270577ba28b8010c89af11Timo Sirainenconst char imap_quota_plugin_binary_dependency[] = "imap";