static void process_regexp_item (struct rspamd_task *task, void *user_data) { struct regexp_module_item *item = user_data; gint res = FALSE; /* Non-threaded version */ if (item->lua_function) { /* Just call function */ res = FALSE; if (!rspamd_lua_call_expression_func (item->lua_function, task, NULL, &res)) { msg_err_task ("error occurred when checking symbol %s", item->symbol); } } else { /* Process expression */ if (item->expr) { res = rspamd_process_expression (item->expr, 0, task); } else { msg_warn_task ("FIXME: %s symbol is broken with new expressions", item->symbol); } } if (res) { rspamd_task_insert_result (task, item->symbol, res, NULL); } }
/* Return result mark for statfile */ double rspamd_lua_call_cls_post_callbacks (struct rspamd_classifier_config *ccf, struct rspamd_task *task, double in, lua_State *L) { struct classifier_callback_data *cd; struct rspamd_classifier_config **pccf; struct rspamd_task **ptask; double out = in; GList *cur; /* Go throught all callbacks and call them, appending results to list */ cur = g_list_first (ccf->pre_callbacks); while (cur) { cd = cur->data; lua_getglobal (L, cd->name); pccf = lua_newuserdata (L, sizeof (struct rspamd_classifier_config *)); rspamd_lua_setclass (L, "rspamd{classifier}", -1); *pccf = ccf; ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); rspamd_lua_setclass (L, "rspamd{task}", -1); *ptask = task; lua_pushnumber (L, out); if (lua_pcall (L, 3, 1, 0) != 0) { msg_warn_task ("error running function %s: %s", cd->name, lua_tostring (L, -1)); lua_pop (L, 1); } else { if (lua_isnumber (L, 1)) { out = lua_tonumber (L, 1); } lua_pop (L, 1); } cur = g_list_next (cur); } return out; }
/* Called when we have connected to the redis server and got stats */ static void rspamd_redis_connected (redisAsyncContext *c, gpointer r, gpointer priv) { struct redis_stat_runtime *rt = REDIS_RUNTIME (priv); redisReply *reply = r; struct rspamd_task *task; glong val = 0; task = rt->task; if (c->err == 0) { if (r != NULL) { if (G_UNLIKELY (reply->type == REDIS_REPLY_INTEGER)) { val = reply->integer; } else if (reply->type == REDIS_REPLY_STRING) { rspamd_strtol (reply->str, reply->len, &val); } else { if (reply->type != REDIS_REPLY_NIL) { msg_err_task ("bad learned type for %s: %d", rt->stcf->symbol, reply->type); } val = 0; } if (val < 0) { msg_warn_task ("invalid number of learns for %s: %L", rt->stcf->symbol, val); val = 0; } rt->learned = val; msg_debug_task ("connected to redis server, tokens learned for %s: %uL", rt->redis_object_expanded, rt->learned); rspamd_upstream_ok (rt->selected); } } else { msg_err_task ("error getting reply from redis server %s: %s", rspamd_upstream_name (rt->selected), c->errstr); rspamd_upstream_fail (rt->selected); } }
static GList * call_classifier_pre_callback (struct rspamd_classifier_config *ccf, struct rspamd_task *task, lua_State *L, gboolean is_learn, gboolean is_spam) { struct rspamd_classifier_config **pccf; struct rspamd_task **ptask; struct rspamd_statfile_config **pst; GList *res = NULL; pccf = lua_newuserdata (L, sizeof (struct rspamd_classifier_config *)); rspamd_lua_setclass (L, "rspamd{classifier}", -1); *pccf = ccf; ptask = lua_newuserdata (L, sizeof (struct rspamd_task *)); rspamd_lua_setclass (L, "rspamd{task}", -1); *ptask = task; lua_pushboolean (L, is_learn); lua_pushboolean (L, is_spam); if (lua_pcall (L, 4, 1, 0) != 0) { msg_warn_task ("error running pre classifier callback %s", lua_tostring (L, -1)); lua_pop (L, 1); } else { if (lua_istable (L, -1)) { lua_pushnil (L); while (lua_next (L, -2)) { pst = rspamd_lua_check_udata (L, -1, "rspamd{statfile}"); if (pst) { res = g_list_prepend (res, *pst); } lua_pop (L, 1); } } lua_pop (L, 1); } return res; }
gboolean rspamd_task_load_message (struct rspamd_task *task, struct rspamd_http_message *msg, const gchar *start, gsize len) { guint control_len, r; struct ucl_parser *parser; ucl_object_t *control_obj; gchar filepath[PATH_MAX], *fp; gint fd, flen; gpointer map; struct stat st; if (msg) { rspamd_protocol_handle_headers (task, msg); } if (task->flags & RSPAMD_TASK_FLAG_FILE) { g_assert (task->msg.len > 0); r = rspamd_strlcpy (filepath, task->msg.start, MIN (sizeof (filepath), task->msg.len + 1)); rspamd_decode_url (filepath, filepath, r + 1); flen = strlen (filepath); if (filepath[0] == '"' && flen > 2) { /* We need to unquote filepath */ fp = &filepath[1]; fp[flen - 2] = '\0'; } else { fp = &filepath[0]; } if (access (fp, R_OK) == -1 || stat (fp, &st) == -1) { g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Invalid file (%s): %s", fp, strerror (errno)); return FALSE; } fd = open (fp, O_RDONLY); if (fd == -1) { g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Cannot open file (%s): %s", fp, strerror (errno)); return FALSE; } map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); if (map == MAP_FAILED) { close (fd); g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Cannot mmap file (%s): %s", fp, strerror (errno)); return FALSE; } close (fd); task->msg.start = map; task->msg.len = st.st_size; rspamd_mempool_add_destructor (task->task_pool, rspamd_task_unmapper, task); } else { debug_task ("got input of length %z", task->msg.len); task->msg.start = start; task->msg.len = len; if (task->msg.len == 0) { msg_warn_task ("message has invalid message length: %ud", task->msg.len); g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Invalid length"); return FALSE; } if (task->flags & RSPAMD_TASK_FLAG_HAS_CONTROL) { /* We have control chunk, so we need to process it separately */ if (task->msg.len < task->message_len) { msg_warn_task ("message has invalid message length: %ud and total len: %ud", task->message_len, task->msg.len); g_set_error (&task->err, rspamd_task_quark(), RSPAMD_PROTOCOL_ERROR, "Invalid length"); return FALSE; } control_len = task->msg.len - task->message_len; if (control_len > 0) { parser = ucl_parser_new (UCL_PARSER_KEY_LOWERCASE); if (!ucl_parser_add_chunk (parser, task->msg.start, control_len)) { msg_warn_task ("processing of control chunk failed: %s", ucl_parser_get_error (parser)); ucl_parser_free (parser); } else { control_obj = ucl_parser_get_object (parser); ucl_parser_free (parser); rspamd_protocol_handle_control (task, control_obj); ucl_object_unref (control_obj); } task->msg.start += control_len; task->msg.len -= control_len; } } } return TRUE; }