--- /dev/null
+/* Copyright (c) 2024 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "settings-parser.h"
+#include "quota-settings.h"
+
+#undef DEF
+#define DEF(type, name) \
+ SETTING_DEFINE_STRUCT_##type(#name, name, struct quota_settings)
+static const struct setting_define quota_setting_defines[] = {
+ DEF(UINT, quota_mailbox_count),
+ DEF(UINT, quota_mailbox_message_count),
+ DEF(SIZE, quota_mail_size),
+ DEF(STR, quota_exceeded_message),
+
+ SETTING_DEFINE_LIST_END
+};
+
+static const struct quota_settings quota_default_settings = {
+ .quota_mailbox_count = SET_UINT_UNLIMITED,
+ .quota_mail_size = SET_SIZE_UNLIMITED,
+ .quota_mailbox_message_count = SET_UINT_UNLIMITED,
+ .quota_exceeded_message = "Quota exceeded (mailbox for user is full)",
+};
+
+const struct setting_parser_info quota_setting_parser_info = {
+ .name = "quota",
+ .defines = quota_setting_defines,
+ .defaults = "a_default_settings,
+ .struct_size = sizeof(struct quota_settings),
+ .pool_offset1 = 1 + offsetof(struct quota_settings, pool),
+};
+
+struct quota_settings *quota_get_unlimited_set(void)
+{
+ static struct quota_settings set;
+ if (set.pool == NULL) {
+ set = quota_default_settings;
+ set.pool = null_pool;
+ }
+ return &set;
+}
#include "lib.h"
#include "array.h"
#include "istream.h"
+#include "settings.h"
#include "mail-search-build.h"
#include "mail-storage-private.h"
#include "mailbox-list-private.h"
bool directory)
{
struct quota_mailbox *qbox = QUOTA_CONTEXT_REQUIRE(box);
- struct quota_user *quser =
- QUOTA_USER_CONTEXT_REQUIRE(box->storage->user);
- struct quota_legacy_settings *quota_set = quser->quota->set;
+ const struct quota_settings *set;
unsigned int mailbox_count;
+ const char *error;
+
+ if (settings_get(box->event, "a_setting_parser_info, 0,
+ &set, &error) < 0) {
+ mailbox_set_critical(box, "%s", error);
+ return -1;
+ }
+ unsigned int quota_mailbox_count = set->quota_mailbox_count;
+ settings_free(set);
- if (quota_set->max_mailbox_count == 0) {
+ if (quota_mailbox_count == SET_UINT_UNLIMITED) {
/* no mailbox count limit */
} else if (mailbox_is_autocreated(box)) {
/* Always allow autocreated mailbox to be created.
} else if (mailbox_list_get_count(box->list, &mailbox_count) < 0) {
mail_storage_copy_list_error(box->storage, box->list);
return -1;
- } else if (mailbox_count >= quota_set->max_mailbox_count) {
+ } else if (mailbox_count >= quota_mailbox_count) {
mail_storage_set_error(box->storage, MAIL_ERROR_LIMIT,
"Maximum number of mailboxes reached");
return -1;
#include "write-full.h"
#include "eacces-error.h"
#include "wildcard-match.h"
+#include "settings.h"
#include "mailbox-list-private.h"
#include "quota-private.h"
#include "quota-fs.h"
#include <sys/wait.h>
-#define DEFAULT_QUOTA_EXCEEDED_MSG \
- "Quota exceeded (mailbox for user is full)"
-
/* How many seconds after the userdb lookup do we still want to execute the
quota_over_script. This applies to quota_over_flag_lazy_check=yes and also
after unhibernating IMAP connections. */
"server configuration";
case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT:
case QUOTA_ALLOC_RESULT_OVER_QUOTA:
- return qt->quota->set->quota_exceeded_msg;
+ return qt->set->quota_exceeded_message;
case QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT:
return "Too many messages in the mailbox";
}
pool = pool_alloconly_create("quota settings", 2048);
quota_set = p_new(pool, struct quota_legacy_settings, 1);
quota_set->pool = pool;
- quota_set->quota_exceeded_msg =
- mail_user_plugin_getenv(user, "quota_exceeded_message");
- if (quota_set->quota_exceeded_msg == NULL)
- quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG;
-
- const char *mailbox_count =
- mail_user_plugin_getenv(user, "quota_mailbox_count");
- if (mailbox_count != NULL) {
- if (str_to_uint(mailbox_count, "a_set->max_mailbox_count) < 0) {
- *error_r = "Invalid quota_mailbox_count";
- event_unref("a_set->event);
- pool_unref(&pool);
- return -1;
- }
- }
-
- const char *max_size = mail_user_plugin_getenv(user, "quota_mail_size");
- if (max_size != NULL) {
- const char *error = NULL;
- if (str_parse_get_size(max_size, "a_set->max_mail_size,
- &error) < 0) {
- *error_r = t_strdup_printf("quota_max_mail_size: %s",
- error);
- event_unref("a_set->event);
- pool_unref(&pool);
- return -1;
- }
- }
-
- const char *max_box_count =
- mail_user_plugin_getenv(user, "quota_mailbox_message_count");
- if (max_box_count != NULL) {
- if (str_to_uint(max_box_count,
- "a_set->max_messages_per_mailbox) < 0) {
- *error_r = "Invalid quota_mailbox_message_count";
- event_unref("a_set->event);
- pool_unref(&pool);
- return -1;
- }
- }
p_array_init("a_set->root_sets, pool, 4);
if (i_strocpy(root_name, "quota", sizeof(root_name)) < 0)
if (box->storage->user->dsyncing) {
/* ignore quota for dsync */
ctx->limits_set = TRUE;
+ ctx->set = quota_get_unlimited_set();
}
return ctx;
}
enum quota_get_result *error_result_r,
const char **error_r)
{
- const struct quota_legacy_settings *set = ctx->quota->set;
struct quota_root *const *roots;
const char *mailbox_name, *error;
unsigned int i, count;
use_grace = (ctx->box->flags & MAILBOX_FLAG_POST_SESSION) != 0;
ctx->no_quota_updates = TRUE;
+ i_assert(ctx->set == NULL);
+ if (settings_get(ctx->box->event, "a_setting_parser_info,
+ 0, &ctx->set, error_r) < 0) {
+ ctx->failed = TRUE;
+ *error_result_r = QUOTA_GET_RESULT_INTERNAL_ERROR;
+ return -1;
+ }
+
/* find the lowest quota limits from all roots and use them */
roots = array_get(&ctx->quota->roots, &count);
for (i = 0; i < count; i++) {
}
}
- if (set->max_messages_per_mailbox != 0) {
+ if (ctx->set->quota_mailbox_message_count != SET_UINT_UNLIMITED) {
struct mailbox_status status;
mailbox_get_open_status(ctx->box, STATUS_MESSAGES, &status);
- if (status.messages <= set->max_messages_per_mailbox) {
- diff = set->max_messages_per_mailbox - status.messages;
+ if (status.messages <= ctx->set->quota_mailbox_message_count) {
+ diff = ctx->set->quota_mailbox_message_count - status.messages;
if (ctx->count_ceil > diff)
ctx->count_ceil = diff;
} else {
/* over quota */
ctx->count_ceil = 0;
- diff = status.messages - set->max_messages_per_mailbox;
+ diff = status.messages - ctx->set->quota_mailbox_message_count;
if (ctx->count_over < diff)
ctx->count_over = diff;
}
quota_warnings_execute(ctx, *roots);
} T_END;
+ settings_free(ctx->set);
i_free(ctx);
return ret;
}
struct quota_transaction_context *ctx = *_ctx;
*_ctx = NULL;
+ settings_free(ctx->set);
i_free(ctx);
}
return QUOTA_ALLOC_RESULT_TEMPFAIL;
}
- uoff_t max_size = ctx->quota->set->max_mail_size;
+ uoff_t max_size = ctx->set->quota_mail_size;
if (max_size > 0 && size > max_size) {
*error_r = t_strdup_printf(
"Requested allocation size %"PRIuUOFF_T" exceeds max "
if (!quota_transaction_is_over(ctx, size))
return QUOTA_ALLOC_RESULT_OK;
- if (ctx->quota->set->max_messages_per_mailbox != 0) {
+ if (ctx->set->quota_mailbox_message_count != SET_UINT_UNLIMITED) {
struct mailbox_status status;
mailbox_get_open_status(ctx->box, STATUS_MESSAGES, &status);
unsigned int new_count = status.messages + ctx->count_used;
- if (new_count >= ctx->quota->set->max_messages_per_mailbox)
+ if (new_count >= ctx->set->quota_mailbox_message_count)
return QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT;
}