imap-quota-plugin.c revision d337f4291d9ea9cd1adee0f468bc0c3baeabb4fe
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen/* Copyright (c) 2005-2010 Dovecot authors, see the included COPYING file */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "imap-common.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "str.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "ostream.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "imap-quote.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "mail-namespace.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "imap-commands.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "quota.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "quota-plugin.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include "imap-quota-plugin.h"
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen#include <stdlib.h>
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen#define QUOTA_USER_SEPARATOR ':'
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainenconst char *imap_quota_plugin_version = DOVECOT_VERSION;
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainenstatic struct module *imap_quota_module;
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainenstatic void (*next_hook_client_created)(struct client **client);
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainen
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainenstatic const char *
c9099b08b3cae8a849098ca776b4363c6d5f5f36Timo Sirainenimap_quota_root_get_name(struct mail_user *user, struct mail_user *owner,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct quota_root *root)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen{
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen const char *name;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen name = quota_root_get_name(root);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (user == owner || owner == NULL)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return name;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return t_strdup_printf("%s%c%s", owner->username,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen QUOTA_USER_SEPARATOR, name);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen}
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic void
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenquota_reply_write(string_t *str, struct mail_user *user,
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct mail_user *owner, struct quota_root *root)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen{
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen const char *name, *const *list;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen unsigned int i;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen uint64_t value, limit;
fb79b36eb34532dbe67caf99eefe3660b8c841e0Timo Sirainen int ret = 0;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
fb79b36eb34532dbe67caf99eefe3660b8c841e0Timo Sirainen str_append(str, "* QUOTA ");
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen name = imap_quota_root_get_name(user, owner, root);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen imap_quote_append_string(str, name, FALSE);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen str_append(str, " (");
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen list = quota_root_get_resources(root);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen for (i = 0; *list != NULL; list++) {
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen ret = quota_get_resource(root, "", *list, &value, &limit);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (ret < 0)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen break;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (ret > 0) {
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen if (i > 0)
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen str_append_c(str, ' ');
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen str_printfa(str, "%s %llu %llu", *list,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen (unsigned long long)value,
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen (unsigned long long)limit);
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen i++;
7000810786f2959f02cd6d2f4151a9eb61ff5db8Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen }
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen str_append(str, ")\r\n");
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen if (ret < 0)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen str_append(str, "* BAD Internal quota calculation error\r\n");
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen}
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainenstatic bool cmd_getquotaroot(struct client_command_context *cmd)
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen{
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct client *client = cmd->client;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct quota_user *quser = QUOTA_USER_CONTEXT(client->user);
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mail_namespace *ns;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct mailbox *box;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct quota_root_iter *iter;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen struct quota_root *root;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen const char *mailbox, *storage_name, *name;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen string_t *quotaroot_reply, *quota_reply;
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen
d6a7cb184cc882a90aa3d9312082e0029f354ff6Timo Sirainen /* <mailbox> */
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (!client_read_string_args(cmd, 1, &mailbox))
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen return FALSE;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen ns = client_find_namespace(cmd, mailbox, &storage_name, NULL);
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (ns == NULL)
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen return TRUE;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen if (quser == NULL) {
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen client_send_tagline(cmd, "OK No quota.");
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen return TRUE;
f5e8a76a128d4e92f0641135183c164fd5c5ce5eTimo Sirainen }
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen if (ns->owner != NULL && ns->owner != client->user &&
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen !client->user->admin) {
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen client_send_tagline(cmd, "NO Not showing other users' quota.");
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen return TRUE;
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen }
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_READONLY |
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen MAILBOX_FLAG_KEEP_RECENT);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen /* build QUOTAROOT reply and QUOTA reply for all quota roots */
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen quotaroot_reply = t_str_new(128);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen quota_reply = t_str_new(256);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen str_append(quotaroot_reply, "* QUOTAROOT ");
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen imap_quote_append_string(quotaroot_reply, mailbox, FALSE);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen iter = quota_root_iter_init(box);
cc935aff970ed6c24d136cc560c7e705a49d536cTimo Sirainen while ((root = quota_root_iter_next(iter)) != NULL) {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen str_append_c(quotaroot_reply, ' ');
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen name = imap_quota_root_get_name(client->user, ns->owner, root);
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen imap_quote_append_string(quotaroot_reply, name, FALSE);
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen quota_reply_write(quota_reply, client->user, ns->owner, root);
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen }
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen quota_root_iter_deinit(&iter);
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen mailbox_free(&box);
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen /* send replies */
279c6b6d0b0a159c8533102e7e914db21dadcb03Timo Sirainen if (str_len(quota_reply) == 0)
387f9e3b4120273ad0213206a0e9cc2dc0e62ccaTimo Sirainen client_send_tagline(cmd, "OK No quota.");
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen else {
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen client_send_line(client, str_c(quotaroot_reply));
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen o_stream_send(client->output, str_data(quota_reply),
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen str_len(quota_reply));
071543cc13df9600d2e97aa35f28907be5a79477Timo Sirainen client_send_tagline(cmd, "OK Getquotaroot completed.");
27e859cee42654bff801ba96677cfc4e4e0108c7Timo Sirainen }
632018810af689442569cbb0139c55868923ccfeTimo Sirainen return TRUE;
387f9e3b4120273ad0213206a0e9cc2dc0e62ccaTimo Sirainen}
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainenstatic bool cmd_getquota(struct client_command_context *cmd)
632018810af689442569cbb0139c55868923ccfeTimo Sirainen{
632018810af689442569cbb0139c55868923ccfeTimo Sirainen struct mail_user *owner = cmd->client->user;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen struct quota_root *root;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen const char *root_name, *p;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen string_t *quota_reply;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainen /* <quota root> */
387f9e3b4120273ad0213206a0e9cc2dc0e62ccaTimo Sirainen if (!client_read_string_args(cmd, 1, &root_name))
632018810af689442569cbb0139c55868923ccfeTimo Sirainen return FALSE;
632018810af689442569cbb0139c55868923ccfeTimo Sirainen
632018810af689442569cbb0139c55868923ccfeTimo Sirainen root = quota_root_lookup(cmd->client->user, root_name);
632018810af689442569cbb0139c55868923ccfeTimo Sirainen if (root == NULL && cmd->client->user->admin) {
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen /* we're an admin. see if there's a quota root for another
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen user. */
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen p = strchr(root_name, QUOTA_USER_SEPARATOR);
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen if (p != NULL) {
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen owner = mail_user_find(cmd->client->user,
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen t_strdup_until(root_name, p));
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen root = owner == NULL ? NULL :
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen quota_root_lookup(owner, p + 1);
8d3af185ae454653fad60e41c5f36edb1d45c868Timo Sirainen }
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen }
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen if (root == NULL) {
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen client_send_tagline(cmd, "NO Quota root doesn't exist.");
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen return TRUE;
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen }
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen quota_reply = t_str_new(128);
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen quota_reply_write(quota_reply, cmd->client->user, owner, root);
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen o_stream_send(cmd->client->output, str_data(quota_reply),
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen str_len(quota_reply));
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen client_send_tagline(cmd, "OK Getquota completed.");
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen return TRUE;
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen}
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainen
dea8bfa31729dbdde1b12718f1ef98fac4e99db9Timo Sirainenstatic bool cmd_setquota(struct client_command_context *cmd)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen{
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen struct quota_root *root;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen const struct imap_arg *args, *list_args;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen const char *root_name, *name, *value_str, *error;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen uint64_t value;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen /* <quota root> <resource limits> */
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (!client_read_args(cmd, 2, 0, &args))
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return FALSE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (!imap_arg_get_astring(&args[0], &root_name) ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen !imap_arg_get_list(&args[1], &list_args)) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen root = quota_root_lookup(cmd->client->user, root_name);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (root == NULL) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen client_send_tagline(cmd, "NO Quota root doesn't exist.");
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen for (; !IMAP_ARG_IS_EOL(list_args); list_args += 2) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (!imap_arg_get_atom(&list_args[0], &name) ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen !imap_arg_get_atom(&list_args[1], &value_str) ||
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen str_to_uint64(value_str, &value) < 0) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen client_send_command_error(cmd, "Invalid arguments.");
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (quota_set_resource(root, name, value, &error) < 0) {
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen client_send_command_error(cmd, error);
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen }
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen client_send_tagline(cmd, "OK Setquota completed.");
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen return TRUE;
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen}
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainenstatic void imap_quota_client_created(struct client **client)
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen{
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (mail_user_is_plugin_loaded((*client)->user, imap_quota_module))
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen str_append((*client)->capability_string, " QUOTA");
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen
f8740ac53310cd28ba4ec6dc9e9ce6e9a3688f39Timo Sirainen if (next_hook_client_created != NULL)
next_hook_client_created(client);
}
void imap_quota_plugin_init(struct module *module)
{
command_register("GETQUOTAROOT", cmd_getquotaroot, 0);
command_register("GETQUOTA", cmd_getquota, 0);
command_register("SETQUOTA", cmd_setquota, 0);
imap_quota_module = module;
next_hook_client_created = hook_client_created;
hook_client_created = imap_quota_client_created;
}
void imap_quota_plugin_deinit(void)
{
command_unregister("GETQUOTAROOT");
command_unregister("GETQUOTA");
command_unregister("SETQUOTA");
hook_client_created = next_hook_client_created;
}
const char *imap_quota_plugin_dependencies[] = { "quota", NULL };