# HG changeset patch # User Timo Sirainen # Date 1479953182 -7200 # Node ID a29415ef148def78bf9bd94cbd3e091431cad37a # Parent ba5c04b9457b7da49ff1bf8bc449129d5ac8e3ae quota: Don't skip quota checks when moving mails between different quota roots. diff -r ba5c04b9457b -r a29415ef148d src/plugins/quota/quota-storage.c --- a/src/plugins/quota/quota-storage.c Thu Nov 24 20:40:15 2016 +0200 +++ b/src/plugins/quota/quota-storage.c Thu Nov 24 04:06:22 2016 +0200 @@ -185,14 +185,46 @@ MODULE_CONTEXT_SET_SELF(mail, quota_mail_module, qmail); } -static int quota_check(struct mail_save_context *ctx) +static bool +quota_move_requires_check(struct mailbox *dest_box, struct mailbox *src_box) +{ + struct mail_namespace *src_ns = src_box->list->ns; + struct mail_namespace *dest_ns = dest_box->list->ns; + struct quota_user *quser = QUOTA_USER_CONTEXT(src_ns->user); + struct quota_root *const *rootp; + + array_foreach(&quser->quota->roots, rootp) { + bool have_src_quota, have_dest_quota; + + have_src_quota = quota_root_is_namespace_visible(*rootp, src_ns); + have_dest_quota = quota_root_is_namespace_visible(*rootp, dest_ns); + if (have_src_quota == have_dest_quota) { + /* Both/neither have this quota */ + } else if (have_dest_quota) { + /* Destination mailbox has a quota that doesn't exist + in source. We'll need to check if it's being + exceeded. */ + return TRUE; + } else { + /* Source mailbox has a quota root that doesn't exist + in destination. We're not increasing the source + quota, so ignore it. */ + } + } + return FALSE; +} + +static int quota_check(struct mail_save_context *ctx, struct mailbox *src_box) { struct mailbox_transaction_context *t = ctx->transaction; struct quota_transaction_context *qt = QUOTA_CONTEXT(t); int ret; bool too_large; - if (ctx->moving) { + i_assert(!ctx->moving || src_box != NULL); + + if (ctx->moving && + !quota_move_requires_check(ctx->transaction->box, src_box)) { /* the mail is being moved. the quota won't increase (after the following expunge), so allow this even if user is currently over quota */ @@ -242,7 +274,7 @@ quota */ return 0; } - return quota_check(ctx); + return quota_check(ctx, mail->box); } static int @@ -297,11 +329,13 @@ static int quota_save_finish(struct mail_save_context *ctx) { struct quota_mailbox *qbox = QUOTA_CONTEXT(ctx->transaction->box); + struct mailbox *src_box; if (qbox->module_ctx.super.save_finish(ctx) < 0) return -1; - return quota_check(ctx); + src_box = ctx->copy_src_mail == NULL ? NULL : ctx->copy_src_mail->box; + return quota_check(ctx, src_box); } static void quota_mailbox_sync_cleanup(struct quota_mailbox *qbox)