diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-04-30 13:21:27 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-04-30 13:21:27 +0100 |
commit | aeb6b4cffa612501f5c74300390c4756a98ba17e (patch) | |
tree | 59315b0b80d8e275fdc7c7d9f473d2d647e8db29 /src/libstat/stat_process.c | |
parent | 121f9e8b5434b0d8367b124a39ac73dc8b40c454 (diff) | |
download | rspamd-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.c | 57 |
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; |