struct rspamd_symbol_def *def; /**< symbol configuration */
};
-struct metric_action {
- enum rspamd_metric_action action;
- gdouble score;
-};
-
-/**
- * Common definition of metric
- */
-struct metric {
- const gchar *name; /**< name of metric */
- gchar *func_name; /**< name of consolidation function */
- gboolean accept_unknown_symbols; /**< if true unknown symbols are registered here */
- gdouble unknown_weight; /**< weight of unknown symbols */
- gdouble grow_factor; /**< grow factor for metric */
- GHashTable *symbols; /**< weights of symbols in metric */
- gchar *subject; /**< subject rewrite string */
- GHashTable * groups; /**< groups of symbols */
- struct metric_action actions[METRIC_ACTION_MAX]; /**< all actions of the metric */
-};
-
/**
* Result of metric processing
*/
struct rspamd_log_format *prev, *next;
};
+enum rspamd_metric_action {
+ METRIC_ACTION_REJECT = 0,
+ METRIC_ACTION_SOFT_REJECT,
+ METRIC_ACTION_REWRITE_SUBJECT,
+ METRIC_ACTION_ADD_HEADER,
+ METRIC_ACTION_GREYLIST,
+ METRIC_ACTION_NOACTION,
+ METRIC_ACTION_MAX
+};
+
+struct metric_action {
+ enum rspamd_metric_action action;
+ gdouble score;
+ guint priority;
+};
+
+/**
+ * Common definition of metric
+ */
+struct metric {
+ const gchar *name; /**< name of metric */
+ gchar *func_name; /**< name of consolidation function */
+ gboolean accept_unknown_symbols; /**< if true unknown symbols are registered here */
+ gdouble unknown_weight; /**< weight of unknown symbols */
+ gdouble grow_factor; /**< grow factor for metric */
+ GHashTable *symbols; /**< weights of symbols in metric */
+ gchar *subject; /**< subject rewrite string */
+ GHashTable * groups; /**< groups of symbols */
+ struct metric_action actions[METRIC_ACTION_MAX]; /**< all actions of the metric */
+};
+
/**
* Structure that stores all config data
*/
* @param one_shot TRUE if symbol can add its score once
* @param rewrite_existing TRUE if we need to rewrite the existing symbol
* @param priority use the following priority for a symbol
- * @return TRUE if symbol has been inserted or FALSE if `rewrite_existing` is not enabled and symbol already exists
+ * @return TRUE if symbol has been inserted or FALSE if symbol already exists with higher priority
*/
gboolean rspamd_config_add_metric_symbol (struct rspamd_config *cfg,
const gchar *metric,
const gchar *group, guint flags,
guint priority);
+/**
+ * Sets action score for a specified metric with the specified priority
+ * @param cfg config file
+ * @param metric metric name (or NULL for default metric)
+ * @param action_name symbolic name of action
+ * @param score score limit
+ * @param priority priority for action
+ * @return TRUE if symbol has been inserted or FALSE if action already exists with higher priority
+ */
+gboolean rspamd_config_set_action_score (struct rspamd_config *cfg,
+ const gchar *metric,
+ const gchar *action_name,
+ gdouble score,
+ guint priority);
+
/**
* Checks if a specified C or lua module is enabled or disabled in the config.
* The logic of check is the following:
return TRUE;
}
+struct metric_actions_cbdata {
+ struct rspamd_config *cfg;
+ struct metric *metric;
+};
+
static gboolean
rspamd_rcl_actions_handler (rspamd_mempool_t *pool, const ucl_object_t *obj,
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
gdouble action_score;
- struct metric_action *action;
- struct metric *metric = ud;
+ struct metric_actions_cbdata *cbdata = ud;
gint action_value;
const ucl_object_t *cur;
ucl_object_iter_t it = NULL;
+ struct metric *metric;
+ struct rspamd_config *cfg;
+
+ metric = cbdata->metric;
+ cfg = cbdata->cfg;
while ((cur = ucl_object_iterate (obj, &it, true)) != NULL) {
if (!rspamd_action_from_str (ucl_object_key (cur), &action_value) ||
return FALSE;
}
else {
- action = &metric->actions[action_value];
- action->action = action_value;
- action->score = action_score;
+ rspamd_config_set_action_score (cfg, metric->name,
+ ucl_object_key (cur), action_score,
+ ucl_object_get_priority (cur));
}
}
struct rspamd_rcl_section *subsection;
struct rspamd_rcl_symbol_data sd;
struct rspamd_symbol_def *sym_def;
+ struct metric_actions_cbdata acts_cbdata;
g_assert (key != NULL);
HASH_FIND_STR (section->subsections, "actions", subsection);
g_assert (subsection != NULL);
- if (!rspamd_rcl_process_section (subsection, metric, val,
+ acts_cbdata.cfg = cfg;
+ acts_cbdata.metric = metric;
+
+ if (!rspamd_rcl_process_section (subsection, &acts_cbdata, val,
cfg->cfg_pool, err)) {
return FALSE;
}
return TRUE;
}
+
+gboolean
+rspamd_config_set_action_score (struct rspamd_config *cfg,
+ const gchar *metric_name,
+ const gchar *action_name,
+ gdouble score,
+ guint priority)
+{
+ struct metric_action *act;
+ struct metric *metric;
+ gint act_num;
+
+ g_assert (cfg != NULL);
+ g_assert (action_name != NULL);
+
+ if (metric_name == NULL) {
+ metric_name = DEFAULT_METRIC;
+ }
+
+ metric = g_hash_table_lookup (cfg->metrics, metric_name);
+
+ if (metric == NULL) {
+ msg_err_config ("metric %s has not been found", metric_name);
+ return FALSE;
+ }
+
+ if (!rspamd_action_from_str (action_name, &act_num)) {
+ msg_err_config ("invalid action name", action_name);
+ return FALSE;
+ }
+
+ g_assert (act_num > 0 && act_num < METRIC_ACTION_MAX);
+
+ act = &metric->actions[act_num];
+
+ if (act->priority > priority) {
+ msg_info_config ("action %s has been already registered with"
+ "priority %ud, do not override (new priority: %ud)",
+ action_name,
+ act->priority,
+ priority);
+ return FALSE;
+ }
+ else {
+ msg_info_config ("action %s has been already registered with"
+ "priority %ud, override it with new priority: %ud, "
+ "old score: %.2f, new score: %.2f",
+ action_name,
+ act->priority,
+ priority,
+ act->score,
+ score);
+
+ act->score = score;
+ act->priority = priority;
+ }
+
+ return TRUE;
+}
const ucl_object_t *cur_elt, *cur_nm, *it_val;
ucl_object_iter_t it = NULL;
struct metric *real_metric;
- struct metric_action *cur_action;
+ const gchar *name;
gdouble nscore;
+ static const guint priority = 3;
while ((cur_elt = ucl_object_iterate (top, &it, true))) {
if (ucl_object_type (cur_elt) != UCL_OBJECT) {
*/
rspamd_config_add_metric_symbol (cfg, real_metric->name,
ucl_object_tostring (n), nscore, NULL, NULL,
- 0, 3);
+ 0, priority);
}
else {
msg_info (
while ((it_val = ucl_object_iterate (cur_nm, &nit, true))) {
if (ucl_object_lookup (it_val, "name") &&
ucl_object_lookup (it_val, "value")) {
- if (!rspamd_action_from_str (ucl_object_tostring (
- ucl_object_lookup (it_val, "name")), &test_act)) {
+ name = ucl_object_tostring (ucl_object_lookup (it_val, "name"));
+
+ if (!name || !rspamd_action_from_str (name, &test_act)) {
msg_err ("unknown action: %s",
ucl_object_tostring (ucl_object_lookup (it_val,
"name")));
continue;
}
- cur_action = &real_metric->actions[test_act];
- cur_action->action = test_act;
- cur_action->score =
- ucl_object_todouble (ucl_object_lookup (it_val,
- "value"));
+ nscore = ucl_object_todouble (ucl_object_lookup (it_val,
+ "value"));
+ rspamd_config_set_action_score (cfg, real_metric->name,
+ name, nscore, priority);
}
else {
msg_info (
CMD_OTHER
};
-enum rspamd_metric_action {
- METRIC_ACTION_REJECT = 0,
- METRIC_ACTION_SOFT_REJECT,
- METRIC_ACTION_REWRITE_SUBJECT,
- METRIC_ACTION_ADD_HEADER,
- METRIC_ACTION_GREYLIST,
- METRIC_ACTION_NOACTION,
- METRIC_ACTION_MAX
-};
-
enum rspamd_task_stage {
RSPAMD_TASK_STAGE_CONNECT = (1 << 0),
RSPAMD_TASK_STAGE_ENVELOPE = (1 << 1),