1
/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
3
#include "imap-common.h"
6
#include "imap-quote.h"
7
#include "mail-namespace.h"
8
#include "imap-commands.h"
10
#include "quota-plugin.h"
11
#include "imap-quota-plugin.h"
15
#define QUOTA_USER_SEPARATOR ':'
17
const char *imap_quota_plugin_version = DOVECOT_VERSION;
19
static struct module *imap_quota_module;
20
static void (*next_hook_client_created)(struct client **client);
23
imap_quota_root_get_name(struct mail_user *user, struct mail_user *owner,
24
struct quota_root *root)
28
name = quota_root_get_name(root);
29
if (user == owner || owner == NULL)
31
return t_strdup_printf("%s%c%s", owner->username,
32
QUOTA_USER_SEPARATOR, name);
36
quota_reply_write(string_t *str, struct mail_user *user,
37
struct mail_user *owner, struct quota_root *root)
39
const char *name, *const *list;
41
uint64_t value, limit;
44
str_append(str, "* QUOTA ");
45
name = imap_quota_root_get_name(user, owner, root);
46
imap_quote_append_string(str, name, FALSE);
48
str_append(str, " (");
49
list = quota_root_get_resources(root);
50
for (i = 0; *list != NULL; list++) {
51
ret = quota_get_resource(root, "", *list, &value, &limit);
56
str_append_c(str, ' ');
57
str_printfa(str, "%s %llu %llu", *list,
58
(unsigned long long)value,
59
(unsigned long long)limit);
63
str_append(str, ")\r\n");
66
str_append(str, "* BAD Internal quota calculation error\r\n");
69
static bool cmd_getquotaroot(struct client_command_context *cmd)
71
struct client *client = cmd->client;
72
struct quota_user *quser = QUOTA_USER_CONTEXT(client->user);
73
struct mail_namespace *ns;
75
struct quota_root_iter *iter;
76
struct quota_root *root;
77
const char *mailbox, *name;
78
string_t *quotaroot_reply, *quota_reply;
81
if (!client_read_string_args(cmd, 1, &mailbox))
84
ns = client_find_namespace(cmd, &mailbox);
89
client_send_tagline(cmd, "OK No quota.");
92
if (ns->owner != NULL && ns->owner != client->user &&
93
!client->user->admin) {
94
client_send_tagline(cmd, "NO Not showing other users' quota.");
98
box = mailbox_alloc(ns->list, mailbox, MAILBOX_FLAG_READONLY);
100
/* build QUOTAROOT reply and QUOTA reply for all quota roots */
101
quotaroot_reply = t_str_new(128);
102
quota_reply = t_str_new(256);
103
str_append(quotaroot_reply, "* QUOTAROOT ");
104
imap_quote_append_string(quotaroot_reply, mailbox, FALSE);
106
iter = quota_root_iter_init(box);
107
while ((root = quota_root_iter_next(iter)) != NULL) {
108
str_append_c(quotaroot_reply, ' ');
109
name = imap_quota_root_get_name(client->user, ns->owner, root);
110
imap_quote_append_string(quotaroot_reply, name, FALSE);
112
quota_reply_write(quota_reply, client->user, ns->owner, root);
114
quota_root_iter_deinit(&iter);
118
if (str_len(quota_reply) == 0)
119
client_send_tagline(cmd, "OK No quota.");
121
client_send_line(client, str_c(quotaroot_reply));
122
o_stream_send(client->output, str_data(quota_reply),
123
str_len(quota_reply));
124
client_send_tagline(cmd, "OK Getquotaroot completed.");
129
static bool cmd_getquota(struct client_command_context *cmd)
131
struct mail_user *owner = cmd->client->user;
132
struct quota_root *root;
133
const char *root_name, *p;
134
string_t *quota_reply;
137
if (!client_read_string_args(cmd, 1, &root_name))
140
root = quota_root_lookup(cmd->client->user, root_name);
141
if (root == NULL && cmd->client->user->admin) {
142
/* we're an admin. see if there's a quota root for another
144
p = strchr(root_name, QUOTA_USER_SEPARATOR);
146
owner = mail_user_find(cmd->client->user,
147
t_strdup_until(root_name, p));
148
root = owner == NULL ? NULL :
149
quota_root_lookup(owner, p + 1);
153
client_send_tagline(cmd, "NO Quota root doesn't exist.");
157
quota_reply = t_str_new(128);
158
quota_reply_write(quota_reply, cmd->client->user, owner, root);
159
o_stream_send(cmd->client->output, str_data(quota_reply),
160
str_len(quota_reply));
162
client_send_tagline(cmd, "OK Getquota completed.");
166
static bool cmd_setquota(struct client_command_context *cmd)
168
struct quota_root *root;
169
const struct imap_arg *args, *list_args;
170
const char *root_name, *name, *value_str, *error;
173
/* <quota root> <resource limits> */
174
if (!client_read_args(cmd, 2, 0, &args))
177
if (!imap_arg_get_astring(&args[0], &root_name) ||
178
!imap_arg_get_list(&args[1], &list_args)) {
179
client_send_command_error(cmd, "Invalid arguments.");
183
root = quota_root_lookup(cmd->client->user, root_name);
185
client_send_tagline(cmd, "NO Quota root doesn't exist.");
189
for (; !IMAP_ARG_IS_EOL(list_args); list_args += 2) {
190
if (!imap_arg_get_atom(&list_args[0], &name) ||
191
!imap_arg_get_atom(&list_args[1], &value_str) ||
192
str_to_uint64(value_str, &value) < 0) {
193
client_send_command_error(cmd, "Invalid arguments.");
197
if (quota_set_resource(root, name, value, &error) < 0) {
198
client_send_command_error(cmd, error);
203
client_send_tagline(cmd, "OK Setquota completed.");
207
static void imap_quota_client_created(struct client **client)
209
if (mail_user_is_plugin_loaded((*client)->user, imap_quota_module))
210
str_append((*client)->capability_string, " QUOTA");
212
if (next_hook_client_created != NULL)
213
next_hook_client_created(client);
216
void imap_quota_plugin_init(struct module *module)
218
command_register("GETQUOTAROOT", cmd_getquotaroot, 0);
219
command_register("GETQUOTA", cmd_getquota, 0);
220
command_register("SETQUOTA", cmd_setquota, 0);
222
imap_quota_module = module;
223
next_hook_client_created =
224
imap_client_created_hook_set(imap_quota_client_created);
227
void imap_quota_plugin_deinit(void)
229
command_unregister("GETQUOTAROOT");
230
command_unregister("GETQUOTA");
231
command_unregister("SETQUOTA");
233
imap_client_created_hook_set(next_hook_client_created);
236
const char *imap_quota_plugin_dependencies[] = { "quota", NULL };
237
const char imap_quota_plugin_binary_dependency[] = "imap";