From: Timo Sirainen Date: Mon, 14 Dec 2009 00:50:58 +0000 (-0500) Subject: expire plugin: Changed configuration. X-Git-Tag: 2.0.beta1~14 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b87daa509bf5b306189282a9df795d094a6d7150;p=thirdparty%2Fdovecot%2Fcore.git expire plugin: Changed configuration. Instead of: expire = box1 7 box2 14 expire_altmove = box3 4 use now: expire = box1 7d expire2 = box2 14d expire3 = box3 4d altmove Instead of 7d and 14d it's also possible to use 1w and 2w. All the regular "time" setting values work actually, minimum expire time is 1sec. --HG-- branch : HEAD --- diff --git a/src/plugins/expire/expire-env.c b/src/plugins/expire/expire-env.c index 32cc4743f2..9a61e313ed 100644 --- a/src/plugins/expire/expire-env.c +++ b/src/plugins/expire/expire-env.c @@ -4,6 +4,7 @@ #include "array.h" #include "str.h" #include "strescape.h" +#include "settings-parser.h" #include "imap-match.h" #include "mail-namespace.h" #include "expire-env.h" @@ -15,7 +16,7 @@ enum expire_type { EXPIRE_TYPE_ALTMOVE }; -struct expire_box { +struct expire_rule { const char *pattern; struct imap_match_glob *glob; @@ -25,101 +26,100 @@ struct expire_box { struct expire_env { pool_t pool; - ARRAY_DEFINE(expire_boxes, struct expire_box); + ARRAY_DEFINE(rules, struct expire_rule); }; -static const char *quoted_string_get(char *const **namesp) -{ - string_t *str = t_str_new(128); - char *const *names = *namesp; - const char *name; - unsigned int i; - - name = (*names) + 1; - for (;;) { - for (i = 0; name[i] != '\0'; i++) { - if (name[i] == '\\' && - name[i+1] != '\0') - i++; - else if (name[i] == '"') - break; - } - str_append_unescaped(str, name, i); - names++; - if (name[i] == '"' || *names == NULL) - break; - - str_append_c(str, ' '); - name = *names; - } - *namesp = names; - return str_c(str); -} - static void expire_env_parse(struct expire_env *env, struct mail_namespace *namespaces, - const char *str, enum expire_type type) + const char *str) { - struct expire_box box; + struct expire_rule rule; struct mail_namespace *ns; - char *const *names; - const char *ns_name; - unsigned int len; - - if (str == NULL) - return; - - names = p_strsplit(env->pool, str, " "); - len = str_array_length((const char *const *)names); - - p_array_init(&env->expire_boxes, env->pool, len / 2); - for (; *names != NULL; names++) { - if (**names == '"') { - /* quoted string. */ - box.pattern = quoted_string_get(&names); - } else { - box.pattern = *names; - names++; - } - if (*names == NULL) { - i_fatal("expire: Missing expire days for mailbox '%s'", - box.pattern); + const char *const *args; + const char *p, *ns_name, *type_str, *error; + + if (*str == '"') { + /* quoted string */ + for (p = ++str; *p != '\0'; p++) { + if (*p == '\\' && p[1] != '\0') + p++; + else if (*p == '"') + break; } + rule.pattern = str_unescape(p_strdup_until(env->pool, str, p)); + if (*p == '"') p++; + } else { + p = strchr(str, ' '); + if (p == NULL) p = str + strlen(str); + rule.pattern = p_strdup_until(env->pool, str, p); + } - ns_name = box.pattern; - ns = mail_namespace_find(namespaces, &ns_name); - if (ns == NULL && *box.pattern != '*') { - i_warning("expire: No namespace found for mailbox: %s", - box.pattern); - } + if (*p == ' ') p++; + args = t_strsplit_spaces(p, " "); - box.glob = imap_match_init(env->pool, box.pattern, TRUE, - ns == NULL ? '/' : ns->sep); - box.type = type; - box.expire_secs = strtoul(*names, NULL, 10) * 3600 * 24; + /* find namespace's separator and create a glob */ + ns_name = rule.pattern; + ns = mail_namespace_find(namespaces, &ns_name); + if (ns == NULL && *rule.pattern != '*') { + i_warning("expire: No namespace found for mailbox: %s", + rule.pattern); + } + rule.glob = imap_match_init(env->pool, rule.pattern, TRUE, + ns == NULL ? '/' : ns->sep); - if (namespaces->user->mail_debug) { - i_debug("expire: pattern=%s type=%s secs=%u", - box.pattern, type == EXPIRE_TYPE_EXPUNGE ? - "expunge" : "altmove", box.expire_secs); - } + /* get expire time */ + if (args[0] == NULL) { + i_fatal("expire: Missing expire time for mailbox '%s'", + rule.pattern); + } + if (is_numeric(args[0], '\0')) { + i_fatal("expire: Missing expire time specifier for mailbox " + "'%s': %s (add e.g. 'days')", rule.pattern, args[0]); + } + if (settings_get_time(args[0], &rule.expire_secs, &error) < 0) { + i_fatal("expire: Invalid time for mailbox '%s': %s", + rule.pattern, error); + } + + /* expire type */ + type_str = args[1] != NULL ? args[1] : "expunge"; + if (strcmp(type_str, "expunge") == 0) + rule.type = EXPIRE_TYPE_EXPUNGE; + else if (strcmp(type_str, "altmove") == 0) + rule.type = EXPIRE_TYPE_ALTMOVE; + else { + i_fatal("expire: Unknown type for mailbox '%s': %s", + rule.pattern, type_str); + } - array_append(&env->expire_boxes, &box, 1); + if (namespaces->user->mail_debug) { + i_debug("expire: pattern=%s secs=%u type=%s", + rule.pattern, rule.expire_secs, type_str); } + array_append(&env->rules, &rule, 1); } -struct expire_env *expire_env_init(struct mail_namespace *namespaces, - const char *expunges, const char *altmoves) +struct expire_env *expire_env_init(struct mail_namespace *namespaces) { + struct mail_user *user = namespaces->user; struct expire_env *env; + const char *rule_str; + char env_name[20]; + unsigned int i; pool_t pool; pool = pool_alloconly_create("Expire pool", 512); env = p_new(pool, struct expire_env, 1); env->pool = pool; + p_array_init(&env->rules, env->pool, 16); + + rule_str = mail_user_set_plugin_getenv(user->set, "expire"); + for (i = 2; rule_str != NULL; i++) { + expire_env_parse(env, namespaces, rule_str); - expire_env_parse(env, namespaces, expunges, EXPIRE_TYPE_EXPUNGE); - expire_env_parse(env, namespaces, altmoves, EXPIRE_TYPE_ALTMOVE); + i_snprintf(env_name, sizeof(env_name), "expire%u", i); + rule_str = mail_user_set_plugin_getenv(user->set, env_name); + } return env; } @@ -131,21 +131,19 @@ void expire_env_deinit(struct expire_env **_env) pool_unref(&env->pool); } -bool expire_box_find(struct expire_env *env, const char *name, - unsigned int *expunge_secs_r, - unsigned int *altmove_secs_r) +bool expire_rule_find(struct expire_env *env, const char *name, + unsigned int *expunge_secs_r, + unsigned int *altmove_secs_r) { - const struct expire_box *expire_boxes; - unsigned int i, count; + const struct expire_rule *rule; unsigned int secs, expunge_min = 0, altmove_min = 0; - expire_boxes = array_get(&env->expire_boxes, &count); - for (i = 0; i < count; i++) { - if (imap_match(expire_boxes[i].glob, name) == IMAP_MATCH_YES) { - secs = expire_boxes[i].expire_secs; + array_foreach(&env->rules, rule) { + if (imap_match(rule->glob, name) == IMAP_MATCH_YES) { + secs = rule->expire_secs; i_assert(secs > 0); - switch (expire_boxes[i].type) { + switch (rule->type) { case EXPIRE_TYPE_EXPUNGE: if (expunge_min == 0 || expunge_min > secs) expunge_min = secs; @@ -162,12 +160,12 @@ bool expire_box_find(struct expire_env *env, const char *name, return expunge_min > 0 || altmove_min > 0; } -unsigned int expire_box_find_min_secs(struct expire_env *env, const char *name, - bool *altmove_r) +unsigned int expire_rule_find_min_secs(struct expire_env *env, const char *name, + bool *altmove_r) { unsigned int secs1, secs2; - (void)expire_box_find(env, name, &secs1, &secs2); + (void)expire_rule_find(env, name, &secs1, &secs2); if (secs1 != 0 && (secs1 < secs2 || secs2 == 0)) { *altmove_r = FALSE; return secs1; diff --git a/src/plugins/expire/expire-env.h b/src/plugins/expire/expire-env.h index b83bfde92c..c8dbec443d 100644 --- a/src/plugins/expire/expire-env.h +++ b/src/plugins/expire/expire-env.h @@ -6,15 +6,14 @@ struct expire_env; struct mail_namespace; -struct expire_env *expire_env_init(struct mail_namespace *namespaces, - const char *expunges, const char *altmoves); +struct expire_env *expire_env_init(struct mail_namespace *namespaces); void expire_env_deinit(struct expire_env **env); -bool expire_box_find(struct expire_env *env, const char *name, - unsigned int *expunge_secs_r, - unsigned int *altmove_secs_r); +bool expire_rule_find(struct expire_env *env, const char *name, + unsigned int *expunge_secs_r, + unsigned int *altmove_secs_r); -unsigned int expire_box_find_min_secs(struct expire_env *env, const char *name, - bool *altmove_r); +unsigned int expire_rule_find_min_secs(struct expire_env *env, const char *name, + bool *altmove_r); #endif diff --git a/src/plugins/expire/expire-plugin.c b/src/plugins/expire/expire-plugin.c index 611f431d38..4b20d32cbc 100644 --- a/src/plugins/expire/expire-plugin.c +++ b/src/plugins/expire/expire-plugin.c @@ -256,7 +256,7 @@ static void expire_mailbox_allocate_init(struct mailbox *box, unsigned int secs; bool altmove; - secs = expire_box_find_min_secs(euser->env, box->vname, &altmove); + secs = expire_rule_find_min_secs(euser->env, box->vname, &altmove); if (box->storage->user->mail_debug) { if (secs == 0) { i_debug("expire: No expiring in mailbox: %s", @@ -293,19 +293,15 @@ static void expire_mail_namespaces_created(struct mail_namespace *ns) { struct mail_user *user = ns->user; struct expire_mail_user *euser; - const char *expunge_env, *altmove_env, *dict_uri, *service_name; + const char *dict_uri, *service_name; service_name = master_service_get_name(master_service); - expunge_env = mail_user_plugin_getenv(user, "expire"); - altmove_env = mail_user_plugin_getenv(user, "expire_altmove"); dict_uri = mail_user_plugin_getenv(user, "expire_dict"); if (strcmp(service_name, "expire-tool") == 0) { /* expire-tool handles all of this internally */ - } else if (expunge_env == NULL && altmove_env == NULL) { - if (user->mail_debug) { - i_debug("expire: No expire or expire_altmove settings - " - "plugin disabled"); - } + } else if (mail_user_plugin_getenv(user, "expire") == NULL) { + if (user->mail_debug) + i_debug("expire: No expire setting - plugin disabled"); } else if (dict_uri == NULL) { i_error("expire plugin: expire_dict setting missing"); } else { @@ -313,7 +309,7 @@ static void expire_mail_namespaces_created(struct mail_namespace *ns) euser->module_ctx.super = user->v; user->v.deinit = expire_mail_user_deinit; - euser->env = expire_env_init(ns, expunge_env, altmove_env); + euser->env = expire_env_init(ns); /* we're using only shared dictionary, the username doesn't matter. */ euser->db = dict_init(dict_uri, DICT_DATA_TYPE_UINT32, "", diff --git a/src/plugins/expire/expire-tool.c b/src/plugins/expire/expire-tool.c index 22c47b7321..79db1c3673 100644 --- a/src/plugins/expire/expire-tool.c +++ b/src/plugins/expire/expire-tool.c @@ -28,7 +28,7 @@ struct expire_context { static int expire_init_user(struct expire_context *ctx, const char *user) { struct mail_storage_service_input input; - const char *expire, *expire_altmove, *errstr; + const char *errstr; int ret; i_set_failure_prefix(t_strdup_printf("expire-tool(%s): ", user)); @@ -46,14 +46,10 @@ static int expire_init_user(struct expire_context *ctx, const char *user) return ret; } - expire = mail_user_set_plugin_getenv(ctx->mail_user->set, "expire"); - expire_altmove = mail_user_set_plugin_getenv(ctx->mail_user->set, - "expire_altmove"); - if (expire == NULL && expire_altmove == NULL) - i_fatal("expire and expire_altmove settings not set"); + if (mail_user_set_plugin_getenv(ctx->mail_user->set, "expire") == NULL) + i_fatal("expire settings not set"); - ctx->env = expire_env_init(ctx->mail_user->namespaces, - expire, expire_altmove); + ctx->env = expire_env_init(ctx->mail_user->namespaces); return 1; } @@ -91,7 +87,7 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user, return ret; } - if (!expire_box_find(ctx->env, mailbox, &expunge_secs, &altmove_secs)) { + if (!expire_rule_find(ctx->env, mailbox, &expunge_secs, &altmove_secs)) { /* we're no longer expunging old messages from here */ if (ctx->testrun) { i_info("%s: mailbox '%s' removed from config",