]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
expire plugin: Changed configuration.
authorTimo Sirainen <tss@iki.fi>
Mon, 14 Dec 2009 00:50:58 +0000 (19:50 -0500)
committerTimo Sirainen <tss@iki.fi>
Mon, 14 Dec 2009 00:50:58 +0000 (19:50 -0500)
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

src/plugins/expire/expire-env.c
src/plugins/expire/expire-env.h
src/plugins/expire/expire-plugin.c
src/plugins/expire/expire-tool.c

index 32cc4743f29a3994f239a6fdd8be6d9709a340f1..9a61e313ed73f4d9e715a78de99786e2f1544501 100644 (file)
@@ -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;
index b83bfde92c86036182b697d7ab0fb5155be80525..c8dbec443d1aabf738be95395bf3258b2e0ca203 100644 (file)
@@ -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
index 611f431d386cac0d6e6d175babdcebc2e0bc340c..4b20d32cbcf5728d37710f00e2da2422f1806a00 100644 (file)
@@ -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, "",
index 22c47b732116cbce0809236607f547d3f498d44f..79db1c367382b00ac651b201de07a27b51951b74 100644 (file)
@@ -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",