/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "wildcard-match.h"
#include "quota-private.h"
#include <ctype.h>
struct quota_rule *
{
return rule;
}
return NULL;
}
static struct quota_rule *
const char *name)
{
return rule;
}
return NULL;
}
static int
struct quota_rule *rule,
{
*error_r = "Invalid percentage";
return -1;
}
*error_r = "Default rule can't be a percentage";
return -1;
}
else
i_unreached();
return 0;
}
const char **error_r)
{
case '\0':
/* default */
break;
case 'B':
multiply = 1;
break;
case 'K':
multiply = 1024;
break;
case 'M':
break;
case 'G':
break;
case 'T':
break;
case '%':
multiply = 0;
error_r) < 0)
return -1;
break;
default:
return -1;
}
return 0;
}
static void
{
if (rule->bytes_percent != 0)
if (rule->count_percent != 0)
}
{
}
}
bytes_limit, 0);
i_debug("Quota root %s: Recalculated relative rules with "
(long long)bytes_limit, (long long)count_limit,
}
}
static int
const char *full_rule_def,
bool relative_rule, const char **error_r)
{
multiply = 1;
value = "";
else
if (*value == '+') {
if (!relative_rule) {
*error_r = "Rule limit cannot have '+'";
return -1;
}
value++;
i_warning("quota root %s rule %s: "
"obsolete configuration for rule '%s' "
"should be changed to '%s=+%s'",
}
multiply = 1024;
"Invalid storage limit: %s", value);
return -1;
}
"Invalid bytes limit: %s", value);
return -1;
}
"Invalid bytes messages: %s", value);
return -1;
}
} else {
"Unknown rule limit name: %s", key);
return -1;
}
"Invalid rule limit value '%s': %s",
return -1;
}
}
if (!relative_rule) {
if (rule->bytes_limit < 0) {
*error_r = "Bytes limit can't be negative";
return -1;
}
if (rule->count_limit < 0) {
*error_r = "Count limit can't be negative";
return -1;
}
}
return 0;
}
{
const char *p, *mailbox_mask;
int ret = 0;
if (p == NULL) {
*error_r = "Invalid rule";
return -1;
}
/* <mailbox mask>:<quota limits> */
} else {
}
}
if (strcmp(p, "ignore") == 0) {
i_debug("Quota rule: root=%s mailbox=%s ignored",
}
return 0;
}
*error_r = "backend rule not supported";
ret = -1;
p + 8, error_r))
ret = -1;
} else {
relative_rule, error_r) < 0)
ret = -1;
}
const char *rule_plus =
i_debug("Quota rule: root=%s mailbox=%s "
"bytes=%s%lld%s messages=%s%lld%s",
(long long)rule->bytes_limit,
(long long)rule->count_limit,
}
return ret;
}
{
const char *p, *q;
int ret;
*error_r = "No command specified";
return -1;
}
if (*rule_def == '+') {
/* warn when exceeding quota */
q = rule_def+1;
} else if (*rule_def == '-') {
/* warn when going below quota */
q = rule_def+1;
} else {
/* default: same as '+' */
q = rule_def;
}
if (ret < 0)
return -1;
if (reverse)
}
return 0;
}
{
const char *p;
/* default */
}
return -1;
return -1;
i_debug("Quota grace: root=%s bytes=%lld%s",
}
return 0;
}
const char **reason_r)
{
if (!w->reverse) {
/* over quota (default) */
return TRUE;
}
return TRUE;
}
} else {
return TRUE;
}
return TRUE;
}
}
return FALSE;
}
{
if (ctx->count_used < 0) {
/* we've deleted some messages. we should be ok, unless we
were already over quota and still are after these
deletions. */
if (ctx->count_over > 0) {
return TRUE;
}
} else {
/* count limit reached */
return TRUE;
}
}
if (ctx->bytes_used < 0) {
/* we've deleted some messages. same logic as above. */
if (ctx->bytes_over > 0) {
/* even after deletions we're over quota */
return TRUE;
}
return TRUE;
} else {
if (size > bytes_deleted &&
return TRUE;
}
} else if (size == 0) {
/* we need to explicitly test this case, since the generic
check would fail if user is already over quota */
if (ctx->bytes_over > 0)
return TRUE;
} else {
/* bytes limit reached */
return TRUE;
}
}
return FALSE;
}