imap-quota-plugin.c revision bf9ea5404a0094a8fb8199b677d81f803512c44e
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen/* Copyright (C) 2005 Timo Sirainen */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "common.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "str.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "imap-quote.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "commands.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "quota.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "quota-plugin.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include "imap-quota-plugin.h"
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen#include <stdlib.h>
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic void
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenquota_send(struct client_command_context *cmd, struct quota_root *root)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen const char *const *list;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen string_t *str;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen unsigned int i;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen uint64_t value, limit;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen int ret;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen t_push();
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str = t_str_new(128);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append(str, "* QUOTA ");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen imap_quote_append_string(str, quota_root_get_name(root), FALSE);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append(str, " (");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen list = quota_root_get_resources(root);
4ea6c43a08b37f270bd54b5809142246fd118263Timo Sirainen for (i = 0; *list != NULL; list++) {
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen ret = quota_get_resource(root, "", *list, &value, &limit);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (ret > 0) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (i > 0)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append_c(str, ' ');
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_printfa(str, "%s %llu %llu", *list,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (unsigned long long)value,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen (unsigned long long)limit);
4ea6c43a08b37f270bd54b5809142246fd118263Timo Sirainen i++;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen } else if (ret < 0) {
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen client_send_line(cmd->client,
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen "* BAD Internal quota calculation error");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append_c(str, ')');
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_line(cmd->client, str_c(str));
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen t_pop();
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool cmd_getquotaroot(struct client_command_context *cmd)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mail_storage *storage;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct mailbox *box;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct quota_root_iter *iter;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct quota_root *root;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen const char *mailbox;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen string_t *str;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* <mailbox> */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return FALSE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen storage = client_find_storage(cmd, &mailbox);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (storage == NULL)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen box = mailbox_open(storage, mailbox, NULL, (MAILBOX_OPEN_READONLY |
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen MAILBOX_OPEN_FAST |
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen MAILBOX_OPEN_KEEP_RECENT));
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (box == NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_storage_error(cmd, storage);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (quota == NULL) {
e17d463c0d18233d1184f5b9237ff3f514f031ceTimo Sirainen mailbox_close(&box);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "OK No quota.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* send QUOTAROOT reply */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str = t_str_new(128);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append(str, "* QUOTAROOT ");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen imap_quote_append_string(str, mailbox, FALSE);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen iter = quota_root_iter_init(quota, box);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen while ((root = quota_root_iter_next(iter)) != NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen str_append_c(str, ' ');
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen imap_quote_append_string(str, quota_root_get_name(root), FALSE);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen quota_root_iter_deinit(iter);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_line(cmd->client, str_c(str));
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* send QUOTA reply for each quotaroot */
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen iter = quota_root_iter_init(quota, box);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen while ((root = quota_root_iter_next(iter)) != NULL)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen quota_send(cmd, root);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen quota_root_iter_deinit(iter);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen mailbox_close(&box);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "OK Getquotaroot completed.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic bool cmd_getquota(struct client_command_context *cmd)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen const char *root_name;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct quota_root *root;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen /* <quota root> */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (!client_read_string_args(cmd, 1, &root_name))
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return FALSE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (quota == NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "OK No quota.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen root = quota_root_lookup(quota, root_name);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (root == NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "NO Quota root doesn't exist.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen quota_send(cmd, root);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "OK Getquota completed.");
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;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct imap_arg *args, *arg;
bf9ea5404a0094a8fb8199b677d81f803512c44eTimo Sirainen const char *root_name, *name, *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
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen root_name = imap_arg_string(&args[0]);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (args[1].type != IMAP_ARG_LIST || root_name == NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (quota == NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "OK No quota.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen root = quota_root_lookup(quota, root_name);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (root == NULL) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_tagline(cmd, "NO Quota root doesn't exist.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen arg = IMAP_ARG_LIST(&args[1])->args;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen for (; arg->type != IMAP_ARG_EOL; arg += 2) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen name = imap_arg_string(arg);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen if (name == NULL || arg[1].type != IMAP_ARG_ATOM ||
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen !is_numeric(IMAP_ARG_STR(&arg[1]), '\0')) {
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen return TRUE;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen }
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen value = strtoull(IMAP_ARG_STR_NONULL(&arg[1]), NULL, 10);
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
f8da06de93e28b5d3e039a427cdde7e1e15daec8Timo Sirainenvoid imap_quota_plugin_init(void)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen{
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen command_register("GETQUOTAROOT", cmd_getquotaroot);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen command_register("GETQUOTA", cmd_getquota);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen command_register("SETQUOTA", cmd_setquota);
378d924da5853145a6df9a299074f04be69986c7Timo Sirainen str_append(capability_string, " QUOTA");
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");
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen}