]> source.dussan.org Git - rspamd.git/commitdiff
[Project] More work towards flexible actions
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 14 Jan 2019 16:48:52 +0000 (16:48 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Mon, 14 Jan 2019 16:48:52 +0000 (16:48 +0000)
15 files changed:
src/controller.c
src/libmime/filter.c
src/libmime/filter.h
src/libmime/filter_private.h [new file with mode: 0644]
src/libmime/message.c
src/libserver/cfg_file.h
src/libserver/cfg_file_private.h
src/libserver/cfg_utils.c
src/libserver/events.c
src/libserver/html.c
src/libserver/protocol.c
src/libserver/roll_history.c
src/libserver/task.c
src/lua/lua_task.c
src/worker.c

index ee7e80e20f48e64a771826e6b5d5992828386091..6a839b4dfb1c99ecaf2982c36d9f26a795e37a53 100644 (file)
@@ -15,6 +15,7 @@
  */
 #include "config.h"
 #include "libserver/dynamic_cfg.h"
+#include "libserver/cfg_file_private.h"
 #include "libutil/rrd.h"
 #include "libutil/map.h"
 #include "libutil/map_helpers.h"
@@ -864,8 +865,7 @@ rspamd_controller_handle_actions (struct rspamd_http_connection_entry *conn_ent,
        struct rspamd_http_message *msg)
 {
        struct rspamd_controller_session *session = conn_ent->ud;
-       struct rspamd_action *act;
-       gint i;
+       struct rspamd_action *act, *tmp;
        ucl_object_t *obj, *top;
 
        if (!rspamd_controller_check_password (conn_ent, session, msg, FALSE)) {
@@ -874,15 +874,14 @@ rspamd_controller_handle_actions (struct rspamd_http_connection_entry *conn_ent,
 
        top = ucl_object_typed_new (UCL_ARRAY);
 
-       /* Get actions for default metric */
-       for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) {
-               act = &session->cfg->actions[i];
+       HASH_ITER (hh, session->cfg->actions, act, tmp) {
                obj = ucl_object_typed_new (UCL_OBJECT);
                ucl_object_insert_key (obj,
-                               ucl_object_fromstring (rspamd_action_to_str (
-                                               act->action)), "action", 0, false);
-               ucl_object_insert_key (obj, ucl_object_fromdouble (
-                               act->threshold), "value", 0, false);
+                               ucl_object_fromstring (act->name),
+                               "action", 0, false);
+               ucl_object_insert_key (obj,
+                               ucl_object_fromdouble (act->threshold),
+                               "value", 0, false);
                ucl_array_append (top, obj);
        }
 
index 2bda47fe76b99c925575e907b3ea82d56eb51e2c..46a0e5b927fc6bafe8f47743ca3372a3eb70280e 100644 (file)
@@ -19,6 +19,8 @@
 #include "rspamd.h"
 #include "message.h"
 #include "lua/lua_common.h"
+#include "libserver/cfg_file_private.h"
+#include "libmime/filter_private.h"
 #include <math.h>
 #include "contrib/uthash/utlist.h"
 
@@ -70,14 +72,22 @@ rspamd_create_metric_result (struct rspamd_task *task)
        }
 
        if (task->cfg) {
-               for (i = 0; i < METRIC_ACTION_MAX; i++) {
-                       metric_res->actions_limits[i] = task->cfg->actions[i].threshold;
-               }
-       }
-       else {
-               for (i = 0; i < METRIC_ACTION_MAX; i++) {
-                       metric_res->actions_limits[i] = NAN;
+               struct rspamd_action *act, *tmp;
+
+               metric_res->actions_limits = rspamd_mempool_alloc0 (task->task_pool,
+                       sizeof (struct rspamd_action_result) * HASH_COUNT (task->cfg->actions));
+               i = 0;
+
+               HASH_ITER (hh, task->cfg->actions, act, tmp) {
+                       if (!(act->flags & RSPAMD_ACTION_NO_THRESHOLD)) {
+                               metric_res->actions_limits[i].cur_limit = act->threshold;
+                       }
+                       metric_res->actions_limits[i].action = act;
+
+                       i ++;
                }
+
+               metric_res->nactions = i;
        }
 
        rspamd_mempool_add_destructor (task->task_pool,
@@ -96,7 +106,7 @@ rspamd_pr_sort (const struct rspamd_passthrough_result *pra,
 
 void
 rspamd_add_passthrough_result (struct rspamd_task *task,
-                                                                       enum rspamd_action_type action,
+                                                                       struct rspamd_action *action,
                                                                        guint priority,
                                                                        double target_score,
                                                                        const gchar *message,
@@ -119,13 +129,13 @@ rspamd_add_passthrough_result (struct rspamd_task *task,
 
        if (!isnan (target_score)) {
                msg_info_task ("<%s>: set pre-result to %s (%.2f): '%s' from %s(%d)",
-                               task->message_id, rspamd_action_to_str (action), target_score,
+                               task->message_id, action->name, target_score,
                                message, module, priority);
        }
 
        else {
                msg_info_task ("<%s>: set pre-result to %s (no score): '%s' from %s(%d)",
-                               task->message_id, rspamd_action_to_str (action),
+                               task->message_id, action->name,
                                message, module, priority);
        }
 }
@@ -475,43 +485,50 @@ rspamd_task_add_result_option (struct rspamd_task *task,
        return ret;
 }
 
-enum rspamd_action_type
-rspamd_check_action_metric (struct rspamd_task *task, struct rspamd_metric_result *mres)
+struct rspamd_action*
+rspamd_check_action_metric (struct rspamd_task *task)
 {
-       struct rspamd_action *action, *selected_action = NULL;
+       struct rspamd_action_result *action_lim,
+                       *noaction = NULL;
+       struct rspamd_action *selected_action = NULL;
        struct rspamd_passthrough_result *pr;
        double max_score = -(G_MAXDOUBLE), sc;
        int i;
        gboolean set_action = FALSE;
+       struct rspamd_metric_result *mres = task->result;
 
        /* We are not certain about the results during processing */
-       if (task->result->passthrough_result == NULL) {
-               for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) {
-                       action = &task->cfg->actions[i];
-                       sc = mres->actions_limits[i];
+       if (mres->passthrough_result == NULL) {
+               for (i = 0; i < mres->nactions; i++) {
+                       action_lim = &mres->actions_limits[i];
+                       sc = action_lim->cur_limit;
+
+                       if (action_lim->action->action_type == METRIC_ACTION_NOACTION) {
+                               noaction = action_lim;
+                       }
 
                        if (isnan (sc)) {
                                continue;
                        }
 
                        if (mres->score >= sc && sc > max_score) {
-                               selected_action = action;
+                               selected_action = action_lim->action;
                                max_score = sc;
                        }
                }
 
                if (set_action && selected_action == NULL) {
-                       selected_action = &task->cfg->actions[METRIC_ACTION_NOACTION];
+                       selected_action = noaction->action;
                }
        }
        else {
                /* Peek the highest priority result */
-               pr = task->result->passthrough_result;
+               pr = mres->passthrough_result;
                sc = pr->target_score;
-               selected_action = &task->cfg->actions[pr->action];
+               selected_action = pr->action;
 
                if (!isnan (sc)) {
-                       if (pr->action == METRIC_ACTION_NOACTION) {
+                       if (pr->action->action_type == METRIC_ACTION_NOACTION) {
                                mres->score = MIN (sc, mres->score);
                        }
                        else {
@@ -521,10 +538,10 @@ rspamd_check_action_metric (struct rspamd_task *task, struct rspamd_metric_resul
        }
 
        if (selected_action) {
-               return selected_action->action;
+               return selected_action;
        }
 
-       return METRIC_ACTION_NOACTION;
+       return noaction ? noaction->action : NULL;
 }
 
 struct rspamd_symbol_result*
index 73f8269fa530367cad51410e20fdbb075fab83f5..7ee0f116372e807a737196cfa38ed2cbcb4772d8 100644 (file)
@@ -9,7 +9,6 @@
 #include "config.h"
 #include "rspamd_symcache.h"
 #include "task.h"
-#include "khash.h"
 
 struct rspamd_task;
 struct rspamd_settings;
@@ -25,14 +24,14 @@ enum rspamd_symbol_result_flags {
        RSPAMD_SYMBOL_RESULT_IGNORED = (1 << 0)
 };
 
+struct kh_rspamd_options_hash_s;
+
 /**
  * Rspamd symbol
  */
-
-KHASH_MAP_INIT_STR (rspamd_options_hash, struct rspamd_symbol_option *);
 struct rspamd_symbol_result {
        double score;                                  /**< symbol's score                                                      */
-       khash_t(rspamd_options_hash) *options;         /**< list of symbol's options                            */
+       struct kh_rspamd_options_hash_s *options;         /**< list of symbol's options                         */
        struct rspamd_symbol_option *opts_head;        /**< head of linked list of options                      */
        const gchar *name;
        struct rspamd_symbol *sym;                     /**< symbol configuration                                        */
@@ -40,24 +39,6 @@ struct rspamd_symbol_result {
        enum rspamd_symbol_result_flags flags;
 };
 
-/**
- * Result of metric processing
- */
-KHASH_MAP_INIT_STR (rspamd_symbols_hash, struct rspamd_symbol_result);
-#if UINTPTR_MAX <= UINT_MAX
-/* 32 bit */
-#define rspamd_ptr_hash_func(key) (khint32_t)(((uintptr_t)(key))>>1)
-#else
-/* likely 64 bit */
-#define rspamd_ptr_hash_func(key) (khint32_t)(((uintptr_t)(key))>>3)
-#endif
-#define rspamd_ptr_equal_func(a, b) ((a) == (b))
-KHASH_INIT (rspamd_symbols_group_hash,
-               void *,
-               double,
-               1,
-               rspamd_ptr_hash_func,
-               rspamd_ptr_equal_func);
 
 #define RSPAMD_PASSTHROUGH_NORMAL 1
 #define RSPAMD_PASSTHROUGH_LOW 0
@@ -65,7 +46,7 @@ KHASH_INIT (rspamd_symbols_group_hash,
 #define RSPAMD_PASSTHROUGH_CRITICAL 3
 
 struct rspamd_passthrough_result {
-       enum rspamd_action_type action;
+       struct rspamd_action *action;
        guint priority;
        double target_score;
        const gchar *message;
@@ -73,6 +54,15 @@ struct rspamd_passthrough_result {
        struct rspamd_passthrough_result *prev, *next;
 };
 
+struct rspamd_action_result {
+       gdouble cur_limit;
+       struct rspamd_action *action;
+};
+
+struct kh_rspamd_symbols_hash_s;
+struct kh_rspamd_symbols_group_hash_s;
+
+
 struct rspamd_metric_result {
        double score;                                                                   /**< total score                                                        */
        double grow_factor;                                                             /**< current grow factor                                        */
@@ -81,9 +71,10 @@ struct rspamd_metric_result {
        guint nnegative;
        double positive_score;
        double negative_score;
-       khash_t(rspamd_symbols_hash) *symbols;                  /**< symbols of metric                                          */
-       khash_t(rspamd_symbols_group_hash) *sym_groups; /**< groups of symbols                                          */
-       gdouble actions_limits[METRIC_ACTION_MAX];              /**< set of actions for this metric                     */
+       struct kh_rspamd_symbols_hash_s *symbols;                       /**< symbols of metric                                          */
+       struct kh_rspamd_symbols_group_hash_s *sym_groups; /**< groups of symbols                                               */
+       struct rspamd_action_result *actions_limits;
+       guint nactions;
 };
 
 /**
@@ -103,7 +94,7 @@ struct rspamd_metric_result * rspamd_create_metric_result (struct rspamd_task *t
  * @param module
  */
 void rspamd_add_passthrough_result (struct rspamd_task *task,
-                                                                       enum rspamd_action_type action,
+                                                                       struct rspamd_action *action,
                                                                        guint priority,
                                                                        double target_score,
                                                                        const gchar *message,
@@ -175,10 +166,11 @@ double rspamd_factor_consolidation_func (struct rspamd_task *task,
        const gchar *unused);
 
 
-/*
- * Get action for specific metric
+/**
+ * Check thresholds and return action for a task
+ * @param task
+ * @return
  */
-enum rspamd_action_type rspamd_check_action_metric (struct rspamd_task *task,
-       struct rspamd_metric_result *mres);
+struct rspamd_action* rspamd_check_action_metric (struct rspamd_task *task);
 
 #endif
diff --git a/src/libmime/filter_private.h b/src/libmime/filter_private.h
new file mode 100644 (file)
index 0000000..82322a6
--- /dev/null
@@ -0,0 +1,31 @@
+//
+// Created by Vsevolod Stakhov on 2019-01-14.
+//
+
+#ifndef RSPAMD_FILTER_PRIVATE_H
+#define RSPAMD_FILTER_PRIVATE_H
+
+#include "filter.h"
+#include "contrib/libucl/khash.h"
+
+KHASH_MAP_INIT_STR (rspamd_options_hash, struct rspamd_symbol_option *);
+/**
+ * Result of metric processing
+ */
+KHASH_MAP_INIT_STR (rspamd_symbols_hash, struct rspamd_symbol_result);
+#if UINTPTR_MAX <= UINT_MAX
+/* 32 bit */
+#define rspamd_ptr_hash_func(key) (khint32_t)(((uintptr_t)(key))>>1)
+#else
+/* likely 64 bit */
+#define rspamd_ptr_hash_func(key) (khint32_t)(((uintptr_t)(key))>>3)
+#endif
+#define rspamd_ptr_equal_func(a, b) ((a) == (b))
+KHASH_INIT (rspamd_symbols_group_hash,
+               void *,
+               double,
+               1,
+               rspamd_ptr_hash_func,
+               rspamd_ptr_equal_func);
+
+#endif //RSPAMD_FILTER_PRIVATE_H
index a07cb6c8d3249adc420c93569a1c8d88dd6447ad..cb85a512b911fbd0675079008db898f3895f9050 100644 (file)
@@ -34,6 +34,7 @@
 
 #include <math.h>
 #include <unicode/uchar.h>
+#include <src/libserver/cfg_file_private.h>
 
 #define GTUBE_SYMBOL "GTUBE"
 
@@ -883,23 +884,23 @@ rspamd_message_process_text_part_maybe (struct rspamd_task *task,
 
        act = rspamd_check_gtube (task, text_part);
        if (act != METRIC_ACTION_NOACTION) {
-               struct rspamd_metric_result *mres = task->result;
+               struct rspamd_action *action;
                gdouble score = NAN;
 
-               if (act == METRIC_ACTION_REJECT) {
-                       score = rspamd_task_get_required_score (task, mres);
-               }
-               else {
-                       score = mres->actions_limits[act];
-               }
+               action = rspamd_config_get_action_by_type (task->cfg, act);
 
-               rspamd_add_passthrough_result (task, act, RSPAMD_PASSTHROUGH_CRITICAL,
-                               score, "Gtube pattern", "GTUBE");
+               if (action) {
+                       score = action->threshold;
 
-               if (ucl_object_lookup (task->messages, "smtp_message") == NULL) {
-                       ucl_object_replace_key (task->messages,
-                                       ucl_object_fromstring ("Gtube pattern"), "smtp_message", 0,
-                                       false);
+                       rspamd_add_passthrough_result (task, action,
+                                       RSPAMD_PASSTHROUGH_CRITICAL,
+                                       score, "Gtube pattern", "GTUBE");
+
+                       if (ucl_object_lookup (task->messages, "smtp_message") == NULL) {
+                               ucl_object_replace_key (task->messages,
+                                               ucl_object_fromstring ("Gtube pattern"),
+                                               "smtp_message", 0, false);
+                       }
                }
 
                rspamd_task_insert_result (task, GTUBE_SYMBOL, 0, NULL);
index 0557f44870b5907018c1f4679028a8eec21a5921..5c245a31b4c18bed0c9347b10585c210dc3b336c 100644 (file)
@@ -708,6 +708,9 @@ gboolean rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
 struct rspamd_action * rspamd_config_get_action (struct rspamd_config *cfg,
                                                                                                 const gchar *name);
 
+struct rspamd_action * rspamd_config_get_action_by_type (struct rspamd_config *cfg,
+                                                                                                enum rspamd_action_type type);
+
 #define msg_err_config(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \
         cfg->cfg_pool->tag.tagname, cfg->checksum, \
         G_STRFUNC, \
index 03f735efe4cb0064b8e218e705383e71c8c3de4e..94cb9aa08c57f9b902d699fe0e16b6bd16f221e2 100644 (file)
@@ -26,7 +26,7 @@
  * Action config definition
  */
 struct rspamd_action {
-       enum rspamd_action_type action;
+       enum rspamd_action_type action_type;
        enum rspamd_action_flags flags;
        guint priority;
        gint lua_handler_ref; /* If special handling is needed */
index 1ab2ff05479337d035a6e208960497cb6afd904c..26bf4e4b01744fd44eeaaa59147eab3722e6f5d1 100644 (file)
@@ -141,7 +141,7 @@ rspamd_config_new (enum rspamd_config_init_flags flags)
                action->threshold = NAN;
                action->name = rspamd_mempool_strdup (cfg->cfg_pool,
                                rspamd_action_to_str (i));
-               action->action = i;
+               action->action_type = i;
 
                if (i == METRIC_ACTION_SOFT_REJECT) {
                        action->flags |= RSPAMD_ACTION_NO_THRESHOLD;
@@ -1946,10 +1946,10 @@ rspamd_config_action_from_ucl (struct rspamd_config *cfg,
        act->flags = flags;
 
        if (rspamd_action_from_str (act->name, &std_act)) {
-               act->action = std_act;
+               act->action_type = std_act;
        }
        else {
-               act->action = METRIC_ACTION_CUSTOM;
+               act->action_type = METRIC_ACTION_CUSTOM;
        }
 
        rspamd_actions_sort (cfg);
@@ -2060,6 +2060,21 @@ rspamd_config_get_action (struct rspamd_config *cfg, const gchar *name)
        return res;
 }
 
+struct rspamd_action *
+rspamd_config_get_action_by_type (struct rspamd_config *cfg,
+                                                                 enum rspamd_action_type type)
+{
+       struct rspamd_action *cur, *tmp;
+
+       HASH_ITER (hh, cfg->actions, cur, tmp) {
+               if (cur->action_type == type) {
+                       return cur;
+               }
+       }
+
+       return NULL;
+}
+
 gboolean
 rspamd_config_radix_from_ucl (struct rspamd_config *cfg,
                const ucl_object_t *obj,
index 2fd0c55ff4a5fae541499ebac9684103e4a39645..3f6d47112c183c7923f88bf3874320c999da2240 100644 (file)
@@ -16,6 +16,7 @@
 #include "config.h"
 #include "rspamd.h"
 #include "contrib/uthash/utlist.h"
+#include "contrib/libucl/khash.h"
 #include "events.h"
 #include "cryptobox.h"
 
index 2568d4c2a98730df61656fc740f642cfbf9fc59d..8ebb3862e37fdfc6a6c5b4568c17137becc6dc91 100644 (file)
@@ -22,6 +22,8 @@
 #include "html_colors.h"
 #include "html_entities.h"
 #include "url.h"
+#include "contrib/libucl/khash.h"
+
 #include <unicode/uversion.h>
 #include <unicode/ucnv.h>
 #if U_ICU_VERSION_MAJOR_NUM >= 46
index 35463be525a7b922983af8430d64585c3318eee7..713c544996b4e00c54a009875e0c034f3fa0a4fd 100644 (file)
@@ -19,6 +19,8 @@
 #include "utlist.h"
 #include "http_private.h"
 #include "worker_private.h"
+#include "libserver/cfg_file_private.h"
+#include "libmime/filter_private.h"
 #include "contrib/zstd/zstd.h"
 #include "lua/lua_common.h"
 #include "unix-std.h"
@@ -922,12 +924,12 @@ rspamd_metric_result_ucl (struct rspamd_task *task,
 {
        struct rspamd_symbol_result *sym;
        gboolean is_spam;
-       enum rspamd_action_type action = METRIC_ACTION_NOACTION;
+       struct rspamd_action *action;
        ucl_object_t *obj = NULL, *sobj;
        const gchar *subject;
 
-       action = rspamd_check_action_metric (task, mres);
-       is_spam = (action < METRIC_ACTION_GREYLIST);
+       action = rspamd_check_action_metric (task);
+       is_spam = !(action->flags & RSPAMD_ACTION_HAM);
 
        if (task->cmd != CMD_CHECK_V2) {
                obj = ucl_object_typed_new (UCL_OBJECT);
@@ -955,10 +957,10 @@ rspamd_metric_result_ucl (struct rspamd_task *task,
                        ucl_object_fromdouble (rspamd_task_get_required_score (task, mres)),
                        "required_score", 0, false);
        ucl_object_insert_key (obj,
-                       ucl_object_fromstring (rspamd_action_to_str (action)),
+                       ucl_object_fromstring (action->name),
                        "action", 0, false);
 
-       if (action == METRIC_ACTION_REWRITE_SUBJECT) {
+       if (action->action_type == METRIC_ACTION_REWRITE_SUBJECT) {
                subject = rspamd_protocol_rewrite_subject (task);
 
                if (subject) {
@@ -1253,7 +1255,8 @@ rspamd_protocol_http_reply (struct rspamd_http_message *msg,
        gpointer h, v;
        ucl_object_t *top = NULL;
        rspamd_fstring_t *reply;
-       gint action, flags = RSPAMD_PROTOCOL_DEFAULT;
+       gint flags = RSPAMD_PROTOCOL_DEFAULT;
+       struct rspamd_action *action;
 
        /* Write custom headers */
        g_hash_table_iter_init (&hiter, task->reply_headers);
@@ -1376,19 +1379,24 @@ end:
 
                if (metric_res != NULL) {
 
-                       action = rspamd_check_action_metric (task, metric_res);
+                       action = rspamd_check_action_metric (task);
 
-                       if (action == METRIC_ACTION_SOFT_REJECT &&
+                       /* TODO: handle custom actions in stats */
+                       if (action->action_type == METRIC_ACTION_SOFT_REJECT &&
                                        (task->flags & RSPAMD_TASK_FLAG_GREYLISTED)) {
                                /* Set stat action to greylist to display greylisted messages */
-                               action = METRIC_ACTION_GREYLIST;
+#ifndef HAVE_ATOMIC_BUILTINS
+                               task->worker->srv->stat->actions_stat[METRIC_ACTION_GREYLIST]++;
+#else
+                               __atomic_add_fetch (&task->worker->srv->stat->actions_stat[METRIC_ACTION_GREYLIST],
+                                               1, __ATOMIC_RELEASE);
+#endif
                        }
-
-                       if (action < METRIC_ACTION_MAX) {
+                       else if (action->action_type < METRIC_ACTION_MAX) {
 #ifndef HAVE_ATOMIC_BUILTINS
-                               task->worker->srv->stat->actions_stat[action]++;
+                               task->worker->srv->stat->actions_stat[action->action_type]++;
 #else
-                               __atomic_add_fetch (&task->worker->srv->stat->actions_stat[action],
+                               __atomic_add_fetch (&task->worker->srv->stat->actions_stat[action->action_type],
                                                1, __ATOMIC_RELEASE);
 #endif
                        }
index 3df59781663a81b02ce14878e2c9c77e9d61d44f..c9367409d213ad5fd26186c52d8574cefc000ee6 100644 (file)
@@ -17,6 +17,7 @@
 #include "rspamd.h"
 #include "lua/lua_common.h"
 #include "unix-std.h"
+#include "cfg_file_private.h"
 
 static const gchar rspamd_history_magic_old[] = {'r', 's', 'h', '1'};
 
@@ -101,6 +102,7 @@ rspamd_roll_history_update (struct roll_history *history,
        struct roll_history_row *row;
        struct rspamd_metric_result *metric_res;
        struct history_metric_callback_data cbdata;
+       struct rspamd_action *action;
 
        if (history->disabled) {
                return;
@@ -155,7 +157,8 @@ rspamd_roll_history_update (struct roll_history *history,
        }
        else {
                row->score = metric_res->score;
-               row->action = rspamd_check_action_metric (task, metric_res);
+               action = rspamd_check_action_metric (task);
+               row->action = action->action_type;
                row->required_score = rspamd_task_get_required_score (task, metric_res);
                cbdata.pos = row->symbols;
                cbdata.remain = sizeof (row->symbols);
index eaa379361a665f32ad3fb29a22889726936103f7..df1a561cbb2ab8a36b008c206f98772f6b046c08 100644 (file)
 #include "utlist.h"
 #include "contrib/zstd/zstd.h"
 #include "libserver/mempool_vars_internal.h"
+#include "libserver/cfg_file_private.h"
 #include "libmime/lang_detection.h"
+#include "libmime/filter_private.h"
+
 #include <math.h>
 
 /*
@@ -1072,11 +1075,11 @@ rspamd_task_log_metric_res (struct rspamd_task *task,
        rspamd_fstring_t *symbuf;
        struct rspamd_symbol_result *sym;
        GPtrArray *sorted_symbols;
-       enum rspamd_action_type act;
+       struct rspamd_action *act;
        guint i, j;
 
        mres = task->result;
-       act = rspamd_check_action_metric (task, mres);
+       act = rspamd_check_action_metric (task);
 
        if (mres != NULL) {
                switch (lf->type) {
@@ -1084,7 +1087,7 @@ rspamd_task_log_metric_res (struct rspamd_task *task,
                        if (RSPAMD_TASK_IS_SKIPPED (task)) {
                                res.begin = "S";
                        }
-                       else if (act == METRIC_ACTION_REJECT) {
+                       else if (!(act->flags & RSPAMD_ACTION_HAM)) {
                                res.begin = "T";
                        }
                        else {
@@ -1094,7 +1097,7 @@ rspamd_task_log_metric_res (struct rspamd_task *task,
                        res.len = 1;
                        break;
                case RSPAMD_LOG_ACTION:
-                       res.begin = rspamd_action_to_str (act);
+                       res.begin = act->name;
                        res.len = strlen (res.begin);
                        break;
                case RSPAMD_LOG_SCORES:
@@ -1441,14 +1444,17 @@ rspamd_task_log_variable (struct rspamd_task *task,
                        if (!isnan (pr->target_score)) {
                                var.len = rspamd_snprintf (numbuf, sizeof (numbuf),
                                                "%s \"%s\"; score=%.2f (set by %s)",
-                                               rspamd_action_to_str (pr->action),
-                                               pr->message, pr->target_score, pr->module);
+                                               pr->action->name,
+                                               pr->message,
+                                               pr->target_score,
+                                               pr->module);
                        }
                        else {
                                var.len = rspamd_snprintf (numbuf, sizeof (numbuf),
                                                "%s \"%s\"; score=nan (set by %s)",
-                                               rspamd_action_to_str (pr->action),
-                                               pr->message, pr->module);
+                                               pr->action->name,
+                                               pr->message,
+                                               pr->module);
                        }
                        var.begin = numbuf;
                }
@@ -1536,7 +1542,7 @@ rspamd_task_write_log (struct rspamd_task *task)
 gdouble
 rspamd_task_get_required_score (struct rspamd_task *task, struct rspamd_metric_result *m)
 {
-       guint i;
+       gint i;
 
        if (m == NULL) {
                m = task->result;
@@ -1546,9 +1552,9 @@ rspamd_task_get_required_score (struct rspamd_task *task, struct rspamd_metric_r
                }
        }
 
-       for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_NOACTION; i ++) {
-               if (!isnan (m->actions_limits[i])) {
-                       return m->actions_limits[i];
+       for (i = m->nactions - 1; i >= 0; i --) {
+               if (!isnan (m->actions_limits[i].cur_limit)) {
+                       return m->actions_limits[i].cur_limit;
                }
        }
 
index 00e819f32f196cdb846a1ed42cb3d2d1bf6e8f04..5728b3342b01ab7a9fa0e7d4aba0947891c5466b 100644 (file)
@@ -23,6 +23,8 @@
 #include "libserver/mempool_vars_internal.h"
 #include "libserver/dkim.h"
 #include "libserver/task.h"
+#include "libserver/cfg_file_private.h"
+#include "libmime/filter_private.h"
 #include "libstat/stat_api.h"
 #include "libutil/map_helpers.h"
 
@@ -1653,7 +1655,7 @@ lua_task_set_pre_result (lua_State * L)
        struct rspamd_task *task = lua_check_task (L, 1);
        const gchar *message = NULL, *module = NULL;
        gdouble score = NAN;
-       gint action = METRIC_ACTION_MAX;
+       struct rspamd_action *action;
        guint priority = RSPAMD_PASSTHROUGH_NORMAL;
 
        if (task != NULL) {
@@ -1663,11 +1665,15 @@ lua_task_set_pre_result (lua_State * L)
                        return 0;
                }
 
-               if (lua_type (L, 2) == LUA_TNUMBER) {
-                       action = lua_tointeger (L, 2);
+               if (lua_type (L, 2) == LUA_TSTRING) {
+                       action = rspamd_config_get_action (task->cfg, lua_tostring (L, 2));
                }
-               else if (lua_type (L, 2) == LUA_TSTRING) {
-                       rspamd_action_from_str (lua_tostring (L, 2), &action);
+               else {
+                       return luaL_error (L, "invalid arguments");
+               }
+
+               if (action == NULL) {
+                       return luaL_error (L, "unknown action %s", lua_tostring (L, 2));
                }
 
                if (lua_type (L, 3) == LUA_TSTRING) {
@@ -1698,21 +1704,16 @@ lua_task_set_pre_result (lua_State * L)
                        priority = lua_tonumber (L, 6);
                }
 
-               if (action < METRIC_ACTION_MAX && action >= METRIC_ACTION_REJECT) {
 
-                       rspamd_add_passthrough_result (task, action, priority,
-                                       score, rspamd_mempool_strdup (task->task_pool, message),
-                                       rspamd_mempool_strdup (task->task_pool, module));
+               rspamd_add_passthrough_result (task, action, priority,
+                               score, rspamd_mempool_strdup (task->task_pool, message),
+                               rspamd_mempool_strdup (task->task_pool, module));
 
-                       /* Don't classify or filter message if pre-filter sets results */
-                       task->processed_stages |= (RSPAMD_TASK_STAGE_FILTERS |
-                                       RSPAMD_TASK_STAGE_CLASSIFIERS |
-                                       RSPAMD_TASK_STAGE_CLASSIFIERS_PRE |
-                                       RSPAMD_TASK_STAGE_CLASSIFIERS_POST);
-               }
-               else {
-                       return luaL_error (L, "invalid arguments");
-               }
+               /* Don't classify or filter message if pre-filter sets results */
+               task->processed_stages |= (RSPAMD_TASK_STAGE_FILTERS |
+                                                                  RSPAMD_TASK_STAGE_CLASSIFIERS |
+                                                                  RSPAMD_TASK_STAGE_CLASSIFIERS_PRE |
+                                                                  RSPAMD_TASK_STAGE_CLASSIFIERS_POST);
        }
        else {
                return luaL_error (L, "invalid arguments");
@@ -4360,20 +4361,23 @@ lua_task_set_settings (lua_State *L)
                        /* Adjust desired actions */
                        mres = task->result;
 
-                       for (i = 0; i < METRIC_ACTION_MAX; i++) {
-                               elt = ucl_object_lookup_any (act, rspamd_action_to_str (i),
-                                               rspamd_action_to_str_alt (i), NULL);
+                       for (i = 0; i < mres->nactions; i++) {
+                               struct rspamd_action_result *act_res = &mres->actions_limits[i];
+                               elt = ucl_object_lookup (act, act_res->action->name);
 
                                if (elt) {
-
                                        if (ucl_object_type (elt) == UCL_FLOAT ||
                                                                ucl_object_type (elt) == UCL_INT) {
-                                               mres->actions_limits[i] = ucl_object_todouble (elt);
-                                               msg_debug_task ("adjusted action %s to %.2f",
-                                                               ucl_object_key (elt), mres->actions_limits[i]);
+                                               gdouble nscore =  ucl_object_todouble (elt);
+
+                                               msg_debug_task ("adjusted action %s: %.2f -> %.2f",
+                                                               ucl_object_key (elt),
+                                                               act_res->cur_limit,
+                                                               nscore);
+                                               act_res->cur_limit = nscore;
                                        }
                                        else if (ucl_object_type (elt) == UCL_NULL) {
-                                               mres->actions_limits[i] = NAN;
+                                               act_res->cur_limit = NAN;
                                                msg_info_task ("disabled action %s due to settings",
                                                                ucl_object_key (elt));
                                        }
@@ -4384,6 +4388,8 @@ lua_task_set_settings (lua_State *L)
                vars = ucl_object_lookup (task->settings, "variables");
                if (vars && ucl_object_type (vars) == UCL_OBJECT) {
                        /* Set memory pool variables */
+                       it = NULL;
+
                        while ((cur = ucl_object_iterate (vars, &it, true)) != NULL) {
                                if (ucl_object_type (cur) == UCL_STRING) {
                                        rspamd_mempool_set_variable (task->task_pool,
@@ -4741,6 +4747,7 @@ lua_task_get_metric_result (lua_State *L)
        LUA_TRACE_POINT;
        struct rspamd_task *task = lua_check_task (L, 1);
        struct rspamd_metric_result *metric_res;
+       struct rspamd_action *action;
 
        if (task) {
                metric_res = task->result;
@@ -4760,10 +4767,13 @@ lua_task_get_metric_result (lua_State *L)
                lua_pushnumber (L, metric_res->score);
                lua_settable (L, -3);
 
-               lua_pushstring (L, "action");
-               lua_pushstring (L, rspamd_action_to_str (
-                               rspamd_check_action_metric (task, metric_res)));
-               lua_settable (L, -3);
+               action = rspamd_check_action_metric (task);
+
+               if (action) {
+                       lua_pushstring (L, "action");
+                       lua_pushstring (L, action->name);
+                       lua_settable (L, -3);
+               }
 
                lua_pushstring (L, "nnegative");
                lua_pushnumber (L, metric_res->nnegative);
@@ -4826,13 +4836,13 @@ lua_task_get_metric_action (lua_State *L)
        LUA_TRACE_POINT;
        struct rspamd_task *task = lua_check_task (L, 1);
        struct rspamd_metric_result *metric_res;
-       enum rspamd_action_type action;
+       struct rspamd_action *action;
 
        if (task) {
                metric_res = task->result;
 
-               action = rspamd_check_action_metric (task, metric_res);
-               lua_pushstring (L, rspamd_action_to_str (action));
+               action = rspamd_check_action_metric (task);
+               lua_pushstring (L, action->name);
        }
        else {
                return luaL_error (L, "invalid arguments");
@@ -4880,21 +4890,29 @@ lua_task_disable_action (lua_State *L)
        LUA_TRACE_POINT;
        struct rspamd_task *task = lua_check_task (L, 1);
        const gchar *action_name;
-       gint action;
+       struct rspamd_action_result *action_res;
 
        action_name = luaL_checkstring (L, 2);
 
-       if (task && action_name && rspamd_action_from_str (action_name, &action)) {
-               if (!task->result) {
-                       task->result = rspamd_create_metric_result (task);
-               }
-               if (isnan (task->result->actions_limits[action])) {
-                       lua_pushboolean (L, false);
-               }
-               else {
-                       task->result->actions_limits[action] = NAN;
-                       lua_pushboolean (L, true);
+       if (task && action_name) {
+
+               for (guint i = 0; i < task->result->nactions; i ++) {
+                       action_res = &task->result->actions_limits[i];
+
+                       if (strcmp (action_name, action_res->action->name) == 0) {
+                               if (isnan (action_res->cur_limit)) {
+                                       lua_pushboolean (L, false);
+                               }
+                               else {
+                                       action_res->cur_limit = NAN;
+                                       lua_pushboolean (L, true);
+                               }
+
+                               break;
+                       }
                }
+
+
        }
        else {
                return luaL_error (L, "invalid arguments");
index 5147e0a2d8a6585009a4d05a036b3603a3c298d2..2f7176a8dcbfb8a1f979aa3fe92b37edd29d5e87 100644 (file)
@@ -36,6 +36,7 @@
 #include "libutil/http_private.h"
 #include "libmime/lang_detection.h"
 #include <math.h>
+#include <src/libserver/cfg_file_private.h>
 #include "unix-std.h"
 
 #include "lua/lua_common.h"
@@ -144,11 +145,15 @@ rspamd_task_timeout (gint fd, short what, gpointer ud)
                msg_info_task ("processing of task timed out, forced processing");
 
                if (task->cfg->soft_reject_on_timeout) {
-                       struct rspamd_metric_result *res = task->result;
+                       struct rspamd_action *action, *soft_reject;
 
-                       if (rspamd_check_action_metric (task, res) != METRIC_ACTION_REJECT) {
+                       action = rspamd_check_action_metric (task);
+
+                       if (action->action_type != METRIC_ACTION_REJECT) {
+                               soft_reject = rspamd_config_get_action_by_type (task->cfg,
+                                               METRIC_ACTION_SOFT_REJECT);
                                rspamd_add_passthrough_result (task,
-                                               METRIC_ACTION_SOFT_REJECT,
+                                               soft_reject,
                                                0,
                                                NAN,
                                                "timeout processing message",