aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstat/stat_process.c
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-30 13:21:27 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-04-30 13:21:27 +0100
commitaeb6b4cffa612501f5c74300390c4756a98ba17e (patch)
tree59315b0b80d8e275fdc7c7d9f473d2d647e8db29 /src/libstat/stat_process.c
parent121f9e8b5434b0d8367b124a39ac73dc8b40c454 (diff)
downloadrspamd-aeb6b4cffa612501f5c74300390c4756a98ba17e.tar.gz
rspamd-aeb6b4cffa612501f5c74300390c4756a98ba17e.zip
[Feature] Implement conditional learning for classifiers
Issue: #613
Diffstat (limited to 'src/libstat/stat_process.c')
-rw-r--r--src/libstat/stat_process.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/src/libstat/stat_process.c b/src/libstat/stat_process.c
index 486d82c08..dc0018429 100644
--- a/src/libstat/stat_process.c
+++ b/src/libstat/stat_process.c
@@ -435,7 +435,13 @@ rspamd_stat_classifiers_learn (struct rspamd_stat_ctx *st_ctx,
{
struct rspamd_classifier *cl;
guint i;
- gboolean learned = FALSE, too_small = FALSE, too_large = FALSE;
+ gboolean learned = FALSE, too_small = FALSE, too_large = FALSE,
+ conditionally_skipped = FALSE;
+ lua_State *L;
+ struct rspamd_task **ptask;
+ GList *cur;
+ gint cb_ref;
+ gchar *cond_str = NULL;
/* Check whether we have learned that file */
for (i = 0; i < st_ctx->classifiers->len; i ++) {
@@ -471,6 +477,47 @@ rspamd_stat_classifiers_learn (struct rspamd_stat_ctx *st_ctx,
continue;
}
+ /* Check all conditions for this classifier */
+ cur = cl->cfg->learn_conditions;
+ L = task->cfg->lua_state;
+
+ while (cur) {
+ cb_ref = GPOINTER_TO_INT (cur->data);
+
+ lua_rawgeti (L, LUA_REGISTRYINDEX, cb_ref);
+ /* Push task and two booleans: is_spam and is_unlearn */
+ ptask = lua_newuserdata (L, sizeof (*ptask));
+ *ptask = task;
+ rspamd_lua_setclass (L, "rspamd{task}", -1);
+ lua_pushboolean (L, spam);
+ lua_pushboolean (L,
+ task->flags & RSPAMD_TASK_FLAG_UNLEARN ? true : false);
+
+ if (lua_pcall (L, 3, LUA_MULTRET, 0) != 0) {
+ msg_err_task ("call to %s failed: %s",
+ "condition callback",
+ lua_tostring (L, -1));
+ }
+ else {
+ if (lua_isboolean (L, 1)) {
+ if (!lua_toboolean (L, 1)) {
+ conditionally_skipped = TRUE;
+ /* Also check for error string if needed */
+ if (lua_isstring (L, 2)) {
+ cond_str = rspamd_mempool_strdup (task->task_pool,
+ lua_tostring (L, 2));
+ }
+
+ lua_settop (L, 0);
+ continue; /* Go to the next classifier */
+ }
+ }
+ }
+
+ lua_settop (L, 0);
+ cur = g_list_next (cur);
+ }
+
if (cl->subrs->learn_spam_func (cl, task->tokens, task, spam,
task->flags & RSPAMD_TASK_FLAG_UNLEARN, err)) {
learned = TRUE;
@@ -496,6 +543,14 @@ rspamd_stat_classifiers_learn (struct rspamd_stat_ctx *st_ctx,
task->tokens->len,
cl->cfg->min_tokens);
}
+ else if (conditionally_skipped) {
+ g_set_error (err, rspamd_stat_quark (), 410,
+ "<%s> is skipped for %s classifier: "
+ "%s",
+ task->message_id,
+ cl->cfg->name,
+ cond_str ? cond_str : "unknown reason");
+ }
}
return learned;