Use array of actions instead of a linked list to speed up processing. * Removed required_score, reject_score and action in metric config, now REJECT is the only default action for a metric.tags/0.6.0
@@ -328,10 +328,9 @@ rspamd_rcl_metric_handler (struct config_file *cfg, rspamd_cl_object_t *obj, | |||
g_set_error (err, CFG_RCL_ERROR, EINVAL, "invalid action definition: %s", cur->key); | |||
return FALSE; | |||
} | |||
action = memory_pool_alloc (cfg->cfg_pool, sizeof (struct metric_action)); | |||
action = &metric->actions[action_value]; | |||
action->action = action_value; | |||
action->score = action_score; | |||
metric->actions = g_list_prepend (metric->actions, action); | |||
} | |||
} | |||
else if (new) { |
@@ -729,8 +729,7 @@ post_load_config (struct config_file *cfg) | |||
if ((def_metric = g_hash_table_lookup (cfg->metrics, DEFAULT_METRIC)) == NULL) { | |||
def_metric = check_metric_conf (cfg, NULL); | |||
def_metric->name = DEFAULT_METRIC; | |||
def_metric->required_score = DEFAULT_SCORE; | |||
def_metric->reject_score = DEFAULT_REJECT_SCORE; | |||
def_metric->actions[METRIC_ACTION_REJECT].score = DEFAULT_SCORE; | |||
cfg->metrics_list = g_list_prepend (cfg->metrics_list, def_metric); | |||
g_hash_table_insert (cfg->metrics, DEFAULT_METRIC, def_metric); | |||
} | |||
@@ -858,12 +857,15 @@ check_statfile_conf (struct config_file *cfg, struct statfile *c) | |||
struct metric * | |||
check_metric_conf (struct config_file *cfg, struct metric *c) | |||
{ | |||
int i; | |||
if (c == NULL) { | |||
c = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct metric)); | |||
c->action = METRIC_ACTION_REJECT; | |||
c->grow_factor = 1.0; | |||
c->symbols = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); | |||
c->descriptions = g_hash_table_new (rspamd_str_hash, rspamd_str_equal); | |||
for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { | |||
c->actions[i].score = -1.0; | |||
} | |||
memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func) g_hash_table_destroy, c->symbols); | |||
memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func) g_hash_table_destroy, c->descriptions); | |||
} |
@@ -442,14 +442,14 @@ static struct xml_parser_rule grammar[] = { | |||
}, | |||
{ | |||
"required_score", | |||
xml_handle_double, | |||
G_STRUCT_OFFSET (struct metric, required_score), | |||
xml_handle_deprecated, | |||
0, | |||
NULL | |||
}, | |||
{ | |||
"reject_score", | |||
xml_handle_double, | |||
G_STRUCT_OFFSET (struct metric, reject_score), | |||
xml_handle_deprecated, | |||
0, | |||
NULL | |||
}, | |||
{ | |||
@@ -1057,7 +1057,7 @@ handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx, | |||
/* First of all check whether we have data with weight (reject:50 for example) */ | |||
if ((p = strchr (data, ':')) == NULL) { | |||
if (check_action_str (data, &res)) { | |||
metric->action = res; | |||
/* XXX: no longer needed */ | |||
return TRUE; | |||
} | |||
return FALSE; | |||
@@ -1067,7 +1067,7 @@ handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx, | |||
return FALSE; | |||
} | |||
else { | |||
action = memory_pool_alloc (cfg->cfg_pool, sizeof (struct metric_action)); | |||
action = &metric->actions[res]; | |||
action->action = res; | |||
errno = 0; | |||
action->score = strtod (p + 1, &errstr); | |||
@@ -1075,7 +1075,6 @@ handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx, | |||
msg_err ("invalid double value: %s", data); | |||
return FALSE; | |||
} | |||
metric->actions = g_list_prepend (metric->actions, action); | |||
} | |||
} | |||
@@ -1797,6 +1796,14 @@ xml_handle_boolean (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GH | |||
return TRUE; | |||
} | |||
gboolean | |||
xml_handle_deprecated (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset) | |||
{ | |||
msg_err ("parameter is depreciated: %s", ctx->section_name); | |||
return TRUE; | |||
} | |||
gboolean | |||
xml_handle_double (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset) | |||
{ |
@@ -116,6 +116,9 @@ gboolean xml_handle_uint16 (struct config_file *cfg, struct rspamd_xml_userdata | |||
/* Flags */ | |||
gboolean xml_handle_boolean (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset); | |||
/* For deprecated attributes */ | |||
gboolean xml_handle_deprecated (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset); | |||
/* Specific params */ | |||
/* Options specific */ | |||
gboolean options_handle_nameserver (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset); |
@@ -40,7 +40,7 @@ struct dynamic_cfg_action { | |||
struct dynamic_cfg_metric { | |||
GList *symbols; | |||
GList *actions; | |||
struct dynamic_cfg_action actions[METRIC_ACTION_MAX]; | |||
gchar *name; | |||
}; | |||
@@ -62,7 +62,6 @@ dynamic_cfg_free (GList *conf_metrics) | |||
GList *cur, *cur_elt; | |||
struct dynamic_cfg_metric *metric; | |||
struct dynamic_cfg_symbol *sym; | |||
struct dynamic_cfg_action *act; | |||
if (conf_metrics) { | |||
cur = conf_metrics; | |||
@@ -78,16 +77,6 @@ dynamic_cfg_free (GList *conf_metrics) | |||
} | |||
g_list_free (metric->symbols); | |||
} | |||
if (metric->actions) { | |||
cur_elt = metric->actions; | |||
while (cur_elt) { | |||
act = cur_elt->data; | |||
g_slice_free1 (sizeof (struct dynamic_cfg_symbol), act); | |||
cur_elt = g_list_next (cur_elt); | |||
} | |||
g_list_free (metric->actions); | |||
} | |||
g_slice_free1 (sizeof (struct dynamic_cfg_metric), metric); | |||
cur = g_list_next (cur); | |||
} | |||
@@ -102,13 +91,14 @@ dynamic_cfg_free (GList *conf_metrics) | |||
static void | |||
apply_dynamic_conf (GList *conf_metrics, struct config_file *cfg) | |||
{ | |||
GList *cur, *cur_elt, *tmp; | |||
GList *cur, *cur_elt; | |||
struct dynamic_cfg_metric *metric; | |||
struct dynamic_cfg_symbol *sym; | |||
struct dynamic_cfg_action *act; | |||
struct metric *real_metric; | |||
struct metric_action *real_act; | |||
gdouble *w; | |||
gint i, j; | |||
cur = conf_metrics; | |||
while (cur) { | |||
@@ -126,22 +116,21 @@ apply_dynamic_conf (GList *conf_metrics, struct config_file *cfg) | |||
cur_elt = g_list_next (cur_elt); | |||
} | |||
cur_elt = metric->actions; | |||
while (cur_elt) { | |||
act = cur_elt->data; | |||
tmp = real_metric->actions; | |||
while (tmp) { | |||
real_act = tmp->data; | |||
for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { | |||
act = &metric->actions[i]; | |||
if (act->value < 0) { | |||
continue; | |||
} | |||
for (j = METRIC_ACTION_REJECT; j < METRIC_ACTION_MAX; j ++) { | |||
real_act = &real_metric->actions[j]; | |||
if (real_act->action == act->action) { | |||
real_act->score = act->value; | |||
} | |||
/* Update required score accordingly to metric's action */ | |||
if (act->action == real_metric->action) { | |||
real_metric->required_score = act->value; | |||
if (act->action == METRIC_ACTION_REJECT) { | |||
real_metric->actions[METRIC_ACTION_REJECT].score = act->value; | |||
} | |||
tmp = g_list_next (tmp); | |||
} | |||
cur_elt = g_list_next (cur_elt); | |||
} | |||
} | |||
cur = g_list_next (cur); | |||
@@ -257,6 +246,9 @@ json_config_fin_cb (memory_pool_t * pool, struct map_cb_data *data) | |||
continue; | |||
} | |||
cur_metric = g_slice_alloc0 (sizeof (struct dynamic_cfg_metric)); | |||
for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { | |||
cur_metric->actions[i].value = -1.0; | |||
} | |||
cur_metric->name = g_strdup (json_string_value (cur_nm)); | |||
cur_nm = json_object_get (cur_elt, "symbols"); | |||
/* Parse symbols */ | |||
@@ -286,17 +278,14 @@ json_config_fin_cb (memory_pool_t * pool, struct map_cb_data *data) | |||
it_val = json_array_get (cur_nm, j); | |||
if (it_val && json_is_object (it_val)) { | |||
if (json_object_get (it_val, "name") && json_object_get (it_val, "value")) { | |||
cur_action = g_slice_alloc0 (sizeof (struct dynamic_cfg_action)); | |||
if (!check_action_str (json_string_value (json_object_get (it_val, "name")), &test_act)) { | |||
msg_err ("unknown action: %s", json_string_value (json_object_get (it_val, "name"))); | |||
g_slice_free1 (sizeof (struct dynamic_cfg_action), cur_action); | |||
continue; | |||
} | |||
cur_action = &cur_metric->actions[test_act]; | |||
cur_action->action = test_act; | |||
cur_action->value = json_number_value (json_object_get (it_val, "value")); | |||
/* Insert action */ | |||
cur_metric->actions = g_list_prepend (cur_metric->actions, cur_action); | |||
} | |||
else { | |||
msg_info ("json symbol object has no mandatory 'name' and 'value' attributes"); | |||
@@ -351,6 +340,8 @@ dump_dynamic_list (gint fd, GList *rules) | |||
struct dynamic_cfg_symbol *sym; | |||
struct dynamic_cfg_action *act; | |||
FILE *f; | |||
gint i; | |||
gboolean start = TRUE; | |||
/* Open buffered stream for the descriptor */ | |||
if ((f = fdopen (fd, "a+")) == NULL) { | |||
@@ -387,16 +378,16 @@ dump_dynamic_list (gint fd, GList *rules) | |||
} | |||
if (metric->actions) { | |||
cur_elt = metric->actions; | |||
fprintf (f, " \"actions\": [\n"); | |||
while (cur_elt) { | |||
act = cur_elt->data; | |||
cur_elt = g_list_next (cur_elt); | |||
if (cur_elt) { | |||
fprintf (f, " {\"name\": \"%s\",\"value\": %.2f},\n", str_action_metric (act->action), act->value); | |||
for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { | |||
act = &metric->actions[i]; | |||
if (act->value < 0) { | |||
continue; | |||
} | |||
else { | |||
fprintf (f, " {\"name\": \"%s\",\"value\": %.2f}\n", str_action_metric (act->action), act->value); | |||
fprintf (f, " %s{\"name\": \"%s\",\"value\": %.2f}\n", | |||
(start ? "" : ","), str_action_metric (act->action), act->value); | |||
if (start) { | |||
start = FALSE; | |||
} | |||
} | |||
fprintf (f, " ]\n"); | |||
@@ -573,7 +564,6 @@ add_dynamic_action (struct config_file *cfg, const gchar *metric_name, guint act | |||
{ | |||
GList *cur; | |||
struct dynamic_cfg_metric *metric = NULL; | |||
struct dynamic_cfg_action *act = NULL; | |||
if (cfg->dynamic_conf == NULL) { | |||
msg_info ("dynamic conf is disabled"); | |||
@@ -592,33 +582,12 @@ add_dynamic_action (struct config_file *cfg, const gchar *metric_name, guint act | |||
if (metric != NULL) { | |||
/* Search for an action */ | |||
cur = metric->actions; | |||
while (cur) { | |||
act = cur->data; | |||
if (act->action == action) { | |||
act->value = value; | |||
msg_debug ("change value of action %d to %.2f", action, value); | |||
break; | |||
} | |||
act = NULL; | |||
cur = g_list_next (cur); | |||
} | |||
if (act == NULL) { | |||
/* Action not found, insert it */ | |||
act = g_slice_alloc (sizeof (struct dynamic_cfg_action)); | |||
act->action = action; | |||
act->value = value; | |||
metric->actions = g_list_prepend (metric->actions, act); | |||
msg_debug ("create action %d in metric %s", action, metric_name); | |||
} | |||
metric->actions[action].value = value; | |||
} | |||
else { | |||
/* Metric not found, create it */ | |||
metric = g_slice_alloc0 (sizeof (struct dynamic_cfg_metric)); | |||
act = g_slice_alloc (sizeof (struct dynamic_cfg_action)); | |||
act->action = action; | |||
act->value = value; | |||
metric->actions = g_list_prepend (metric->actions, act); | |||
metric->actions[action].value = value; | |||
metric->name = g_strdup (metric_name); | |||
cfg->current_dynamic_conf = g_list_prepend (cfg->current_dynamic_conf, metric); | |||
msg_debug ("create metric %s for action %d", metric_name, action); |
@@ -227,7 +227,7 @@ check_metric_is_spam (struct worker_task *task, struct metric *metric) | |||
struct metric_result *res; | |||
double ms, rs; | |||
/* Avoid concurrenting while checking results */ | |||
/* Avoid concurrency while checking results */ | |||
#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) | |||
g_static_mutex_lock (&result_mtx); | |||
#else | |||
@@ -241,9 +241,9 @@ check_metric_is_spam (struct worker_task *task, struct metric *metric) | |||
G_UNLOCK (result_mtx); | |||
#endif | |||
if (!check_metric_settings (res, &ms, &rs)) { | |||
ms = metric->required_score; | |||
ms = metric->actions[METRIC_ACTION_REJECT].score; | |||
} | |||
return res->score >= ms; | |||
return (ms > 0 && res->score >= ms); | |||
} | |||
#if ((GLIB_MAJOR_VERSION == 2) && (GLIB_MINOR_VERSION <= 30)) | |||
@@ -280,7 +280,7 @@ process_filters (struct worker_task *task) | |||
while (cur) { | |||
metric = cur->data; | |||
if (!task->pass_all_filters && | |||
metric->action == METRIC_ACTION_REJECT && | |||
metric->actions[METRIC_ACTION_REJECT].score > 0 && | |||
check_metric_is_spam (task, metric)) { | |||
task->s->wanna_die = TRUE; | |||
check_session_pending (task->s); | |||
@@ -763,9 +763,9 @@ insert_metric_header (gpointer metric_name, gpointer metric_value, gpointer data | |||
rspamd_snprintf (header_name, sizeof (header_name), "X-Spam-%s", metric_res->metric->name); | |||
if (!check_metric_settings (metric_res, &ms, &rs)) { | |||
ms = metric_res->metric->required_score; | |||
ms = metric_res->metric->actions[METRIC_ACTION_REJECT].score; | |||
} | |||
if (metric_res->score >= ms) { | |||
if (ms > 0 && metric_res->score >= ms) { | |||
r += rspamd_snprintf (outbuf + r, sizeof (outbuf) - r, "yes; %.2f/%.2f/%.2f; ", metric_res->score, ms, rs); | |||
} | |||
else { | |||
@@ -835,7 +835,9 @@ str_action_metric (enum rspamd_metric_action action) | |||
case METRIC_ACTION_GREYLIST: | |||
return "greylist"; | |||
case METRIC_ACTION_NOACTION: | |||
return "no action"; | |||
return "no_action"; | |||
case METRIC_ACTION_MAX: | |||
return "invalid max action"; | |||
} | |||
return "unknown action"; | |||
@@ -844,25 +846,26 @@ str_action_metric (enum rspamd_metric_action action) | |||
gint | |||
check_metric_action (double score, double required_score, struct metric *metric) | |||
{ | |||
GList *cur; | |||
struct metric_action *action, *selected_action = NULL; | |||
double max_score = 0; | |||
int i; | |||
if (score >= required_score) { | |||
return metric->action; | |||
return METRIC_ACTION_REJECT; | |||
} | |||
else if (metric->actions == NULL) { | |||
return METRIC_ACTION_NOACTION; | |||
} | |||
else { | |||
cur = metric->actions; | |||
while (cur) { | |||
action = cur->data; | |||
for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { | |||
action = &metric->actions[i]; | |||
if (action->score < 0) { | |||
continue; | |||
} | |||
if (score >= action->score && action->score > max_score) { | |||
selected_action = action; | |||
max_score = action->score; | |||
} | |||
cur = g_list_next (cur); | |||
} | |||
if (selected_action) { | |||
return selected_action->action; |
@@ -42,7 +42,8 @@ enum rspamd_metric_action { | |||
METRIC_ACTION_REWRITE_SUBJECT, | |||
METRIC_ACTION_ADD_HEADER, | |||
METRIC_ACTION_GREYLIST, | |||
METRIC_ACTION_NOACTION | |||
METRIC_ACTION_NOACTION, | |||
METRIC_ACTION_MAX | |||
}; | |||
struct metric_action { | |||
@@ -58,12 +59,9 @@ struct metric { | |||
gchar *func_name; /**< name of consolidation function */ | |||
metric_cons_func func; /**< c consolidation function */ | |||
double grow_factor; /**< grow factor for metric */ | |||
double required_score; /**< required score for this metric */ | |||
double reject_score; /**< reject score for this metric */ | |||
GHashTable *symbols; /**< weights of symbols in metric */ | |||
GHashTable *descriptions; /**< descriptions of symbols in metric */ | |||
enum rspamd_metric_action action; /**< action to do by this metric by default */ | |||
GList *actions; /**< actions that can be performed by this metric */ | |||
struct metric_action actions[METRIC_ACTION_MAX]; /**< all actions of the metric */ | |||
gchar *subject; /**< subject rewrite string */ | |||
}; | |||
@@ -1552,9 +1552,9 @@ lua_task_get_metric_score (lua_State *L) | |||
lua_newtable (L); | |||
lua_pushnumber (L, metric_res->score); | |||
lua_rawseti (L, -2, 1); | |||
lua_pushnumber (L, metric_res->metric->required_score); | |||
lua_pushnumber (L, metric_res->metric->actions[METRIC_ACTION_REJECT].score); | |||
lua_rawseti (L, -2, 2); | |||
lua_pushnumber (L, metric_res->metric->reject_score); | |||
lua_pushnumber (L, metric_res->metric->actions[METRIC_ACTION_REJECT].score); | |||
lua_rawseti (L, -2, 3); | |||
} | |||
else { | |||
@@ -1578,7 +1578,8 @@ lua_task_get_metric_action (lua_State *L) | |||
if (task && metric_name) { | |||
if ((metric_res = g_hash_table_lookup (task->results, metric_name)) != NULL) { | |||
action = check_metric_action (metric_res->score, metric_res->metric->required_score, metric_res->metric); | |||
action = check_metric_action (metric_res->score, | |||
metric_res->metric->actions[METRIC_ACTION_REJECT].score, metric_res->metric); | |||
lua_pushstring (L, str_action_metric (action)); | |||
} | |||
else { |
@@ -113,6 +113,8 @@ str_action_metric_spamc (enum rspamd_metric_action action) | |||
return "greylist"; | |||
case METRIC_ACTION_NOACTION: | |||
return "no action"; | |||
case METRIC_ACTION_MAX: | |||
return "invalid max action"; | |||
} | |||
return "unknown action"; | |||
@@ -1210,15 +1212,15 @@ show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data | |||
} | |||
if (metric_name == NULL || metric_value == NULL) { | |||
m = g_hash_table_lookup (task->cfg->metrics, DEFAULT_METRIC); | |||
default_required_score = m->required_score; | |||
default_required_score = m->actions[METRIC_ACTION_REJECT].score; | |||
default_score = 0; | |||
if (metric_res != NULL && !check_metric_settings (metric_res, &ms, &rs)) { | |||
ms = m->required_score; | |||
rs = m->reject_score; | |||
ms = m->actions[METRIC_ACTION_REJECT].score; | |||
rs = m->actions[METRIC_ACTION_REJECT].score; | |||
} | |||
else if (metric_res == NULL) { | |||
ms = m->required_score; | |||
rs = m->reject_score; | |||
ms = m->actions[METRIC_ACTION_REJECT].score; | |||
rs = m->actions[METRIC_ACTION_REJECT].score; | |||
} | |||
if (!task->is_json) { | |||
@@ -1232,24 +1234,24 @@ show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data | |||
if (!task->is_skipped) { | |||
cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, | |||
cd->log_size - cd->log_offset, | |||
"(%s: F (no action): [0.00/%.2f/%.2f] [", "default", ms, rs); | |||
"(%s: F (no action): [0.00/%.2f] [", "default", ms); | |||
} | |||
else { | |||
cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, | |||
cd->log_size - cd->log_offset, "(%s: S: [0.00/%.2f/%.2f] [", | |||
"default", ms, rs); | |||
cd->log_size - cd->log_offset, "(%s: S: [0.00/%.2f] [", | |||
"default", ms); | |||
} | |||
} | |||
else { | |||
/* XXX: dirty hack */ | |||
if (strcmp (metric_res->metric->name, DEFAULT_METRIC) == 0) { | |||
default_required_score = metric_res->metric->required_score; | |||
default_required_score = metric_res->metric->actions[METRIC_ACTION_REJECT].score; | |||
default_score = metric_res->score; | |||
} | |||
if (!check_metric_settings (metric_res, &ms, &rs)) { | |||
ms = metric_res->metric->required_score; | |||
rs = metric_res->metric->reject_score; | |||
ms = metric_res->metric->actions[METRIC_ACTION_REJECT].score; | |||
rs = metric_res->metric->actions[METRIC_ACTION_REJECT].score; | |||
} | |||
if (!check_metric_action_settings (task, metric_res, | |||
metric_res->score, &action)) { | |||
@@ -1273,15 +1275,15 @@ show_metric_result (gpointer metric_name, gpointer metric_value, void *user_data | |||
cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, | |||
cd->log_size - cd->log_offset, | |||
"(%s: %c (%s): [%.2f/%.2f/%.2f] [", (gchar *) metric_name, | |||
"(%s: %c (%s): [%.2f/%.2f] [", (gchar *) metric_name, | |||
is_spam ? 'T' : 'F', str_action_metric (action), | |||
metric_res->score, ms, rs); | |||
metric_res->score, ms); | |||
} | |||
else { | |||
cd->log_offset += rspamd_snprintf (cd->log_buf + cd->log_offset, | |||
cd->log_size - cd->log_offset, | |||
"(%s: %c (default): [%.2f/%.2f/%.2f] [", | |||
(gchar *) metric_name, 'S', metric_res->score, ms, rs); | |||
"(%s: %c (default): [%.2f/%.2f] [", | |||
(gchar *) metric_name, 'S', metric_res->score, ms); | |||
} | |||
} |
@@ -127,8 +127,9 @@ rspamd_roll_history_update (struct roll_history *history, struct worker_task *ta | |||
} | |||
else { | |||
row->score = metric_res->score; | |||
row->required_score = metric_res->metric->required_score; | |||
row->action = check_metric_action (metric_res->score, metric_res->metric->required_score, metric_res->metric); | |||
row->required_score = metric_res->metric->actions[METRIC_ACTION_REJECT].score; | |||
row->action = check_metric_action (metric_res->score, | |||
metric_res->metric->actions[METRIC_ACTION_REJECT].score, metric_res->metric); | |||
cbdata.pos = row->symbols; | |||
cbdata.remain = sizeof (row->symbols); | |||
g_hash_table_foreach (metric_res->symbols, roll_history_symbols_callback, &cbdata); |
@@ -146,8 +146,8 @@ smtp_metric_callback (gpointer key, gpointer value, gpointer ud) | |||
task = cd->session->task; | |||
if (!check_metric_settings (metric_res, &ms, &rs)) { | |||
ms = metric_res->metric->required_score; | |||
rs = metric_res->metric->reject_score; | |||
ms = metric_res->metric->actions[METRIC_ACTION_REJECT].score; | |||
rs = metric_res->metric->actions[METRIC_ACTION_REJECT].score; | |||
} | |||
if (! check_metric_action_settings (task, metric_res, metric_res->score, &action)) { | |||
action = check_metric_action (metric_res->score, ms, metric_res->metric); |
@@ -364,9 +364,11 @@ http_scan_task_free (gpointer arg) | |||
"\"required_score\":%.2f," | |||
"\"action\":\"%s\"," | |||
"\"symbols\":[", | |||
mres->score >= mres->metric->required_score ? "true" : "false", | |||
cbdata->task->is_skipped ? "true" : "false", mres->score, mres->metric->required_score, | |||
str_action_metric (check_metric_action (mres->score, mres->metric->required_score, mres->metric))); | |||
mres->score >= mres->metric->actions[METRIC_ACTION_REJECT].score ? "true" : "false", | |||
cbdata->task->is_skipped ? "true" : "false", mres->score, | |||
mres->metric->actions[METRIC_ACTION_REJECT].score, | |||
str_action_metric ( | |||
check_metric_action (mres->score, mres->metric->actions[METRIC_ACTION_REJECT].score, mres->metric))); | |||
/* Iterate all symbols */ | |||
g_hash_table_foreach (mres->symbols, http_scan_metric_symbols_callback, cbdata); | |||
evbuffer_add (evb, "]}" CRLF, 4); | |||
@@ -670,31 +672,15 @@ http_set_metric_action (struct config_file *cfg, | |||
json_t *jv, struct metric *metric, enum rspamd_metric_action act) | |||
{ | |||
gdouble actval; | |||
GList *cur; | |||
struct metric_action *act_found; | |||
if (!json_is_number (jv)) { | |||
msg_err ("json element data error"); | |||
return FALSE; | |||
} | |||
actval = json_number_value (jv); | |||
if (metric->action == act && metric->required_score != actval) { | |||
if (metric->actions[act].score != actval) { | |||
return add_dynamic_action (cfg, DEFAULT_METRIC, act, actval); | |||
} | |||
/* Try to search in all metrics */ | |||
/* XXX: clarify this code, currently it looks like a crap */ | |||
cur = metric->actions; | |||
while (cur) { | |||
act_found = cur->data; | |||
if (act_found->action == act) { | |||
if (act_found->score != actval) { | |||
return add_dynamic_action (cfg, DEFAULT_METRIC, act, actval); | |||
} | |||
} | |||
cur = g_list_next (cur); | |||
} | |||
return TRUE; | |||
} | |||
@@ -838,8 +824,9 @@ http_handle_actions (struct evhttp_request *req, gpointer arg) | |||
struct rspamd_webui_worker_ctx *ctx = arg; | |||
struct evbuffer *evb; | |||
struct metric *metric; | |||
GList *cur; | |||
struct metric_action *act; | |||
gboolean start = TRUE; | |||
gint i; | |||
if (!http_check_password (ctx, req)) { | |||
return; | |||
@@ -858,15 +845,16 @@ http_handle_actions (struct evhttp_request *req, gpointer arg) | |||
/* Get actions for default metric */ | |||
metric = g_hash_table_lookup (ctx->cfg->metrics, DEFAULT_METRIC); | |||
if (metric != NULL) { | |||
cur = metric->actions; | |||
while (cur) { | |||
act = cur->data; | |||
cur = g_list_next (cur); | |||
evbuffer_add_printf (evb, "{\"action\":\"%s\",\"value\":%.2f},", str_action_metric (act->action), act->score); | |||
for (i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i ++) { | |||
act = &metric->actions[i]; | |||
if (act->score > 0) { | |||
evbuffer_add_printf (evb, "%s{\"action\":\"%s\",\"value\":%.2f}", | |||
(start ? "" : ","), str_action_metric (act->action), act->score); | |||
if (start) { | |||
start = FALSE; | |||
} | |||
} | |||
} | |||
/* Print default action */ | |||
evbuffer_add_printf (evb, "{\"action\":\"%s\",\"value\":%.2f}", str_action_metric (metric->action), metric->required_score); | |||
} | |||
evbuffer_add (evb, "]" CRLF, 3); |