/** * Push an array to lua as table indexed by integers * @param L * @param obj * @return */ static int ucl_object_lua_push_array (lua_State *L, const ucl_object_t *obj) { const ucl_object_t *cur; ucl_object_iter_t it; int i = 1, nelt = 0; if (obj->type == UCL_ARRAY) { nelt = obj->len; it = ucl_object_iterate_new (obj); lua_createtable (L, nelt, 0); while ((cur = ucl_object_iterate_safe (it, true))) { ucl_object_push_lua (L, cur, false); lua_rawseti (L, -2, i); i ++; } } else { /* Optimize allocation by preallocation of table */ LL_FOREACH (obj, cur) { nelt ++; } lua_createtable (L, nelt, 0); LL_FOREACH (obj, cur) { ucl_object_push_lua (L, cur, false); lua_rawseti (L, -2, i); i ++; } }
static gint lua_util_process_message (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *message; gsize mlen; struct rspamd_task *task; struct event_base *base; ucl_object_t *res = NULL; message = luaL_checklstring (L, 2, &mlen); if (cfg != NULL && message != NULL) { base = event_init (); rspamd_init_filters (cfg, FALSE); task = rspamd_task_new (NULL); task->cfg = cfg; task->ev_base = base; task->msg.start = rspamd_mempool_alloc (task->task_pool, mlen + 1); rspamd_strlcpy ((gpointer)task->msg.start, message, mlen + 1); task->msg.len = mlen; task->fin_callback = lua_util_task_fin; task->fin_arg = &res; task->resolver = dns_resolver_init (NULL, base, cfg); task->s = rspamd_session_create (task->task_pool, rspamd_task_fin, rspamd_task_restore, rspamd_task_free_hard, task); if (!rspamd_task_load_message (task, NULL, message, mlen)) { lua_pushnil (L); } else { if (rspamd_task_process (task, RSPAMD_TASK_PROCESS_ALL)) { event_base_loop (base, 0); if (res != NULL) { ucl_object_push_lua (L, res, true); ucl_object_unref (res); } else { ucl_object_push_lua (L, rspamd_protocol_write_ucl (task, NULL), true); rdns_resolver_release (task->resolver->r); rspamd_task_free_hard (task); } } else { lua_pushnil (L); } } event_base_free (base); } else { lua_pushnil (L); } return 1; }
/** * Push a single element of an object to lua * @param L * @param key * @param obj */ static void ucl_object_lua_push_element (lua_State *L, const char *key, const ucl_object_t *obj) { lua_pushstring (L, key); ucl_object_push_lua (L, obj, true); lua_settable (L, -3); }
static gint lua_config_get_all_opt (lua_State * L) { struct rspamd_config *cfg = lua_check_config (L); const gchar *mname; const ucl_object_t *obj; if (cfg) { mname = luaL_checkstring (L, 2); if (mname) { obj = ucl_obj_get_key (cfg->rcl_obj, mname); if (obj != NULL) { return ucl_object_push_lua (L, obj, TRUE); } } } lua_pushnil (L); return 1; }
static gint lua_config_get_module_opt (lua_State * L) { struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *mname, *optname; const ucl_object_t *obj; if (cfg) { mname = luaL_checkstring (L, 2); optname = luaL_checkstring (L, 3); if (mname && optname) { obj = rspamd_config_get_module_opt (cfg, mname, optname); if (obj) { return ucl_object_push_lua (L, obj, TRUE); } } } lua_pushnil (L); return 1; }
static gint lua_classifier_get_param (lua_State *L) { struct rspamd_classifier_config *ccf = lua_check_classifier (L); const gchar *param; const ucl_object_t *value; param = luaL_checkstring (L, 2); if (ccf != NULL && param != NULL) { value = ucl_object_lookup (ccf->opts, param); if (value != NULL) { ucl_object_push_lua (L, value, true); return 1; } } lua_pushnil (L); return 1; }
static gint lua_config_get_all_opt (lua_State * L) { struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *mname; const ucl_object_t *obj, *cur, *cur_elt; ucl_object_iter_t it = NULL; gint i; if (cfg) { mname = luaL_checkstring (L, 2); if (mname) { obj = ucl_obj_get_key (cfg->rcl_obj, mname); /* Flatten object */ if (obj != NULL && (ucl_object_type (obj) == UCL_OBJECT || ucl_object_type (obj) == UCL_ARRAY)) { lua_newtable (L); it = ucl_object_iterate_new (obj); LL_FOREACH (obj, cur) { it = ucl_object_iterate_reset (it, cur); while ((cur_elt = ucl_object_iterate_safe (it, true))) { lua_pushstring (L, ucl_object_key (cur_elt)); ucl_object_push_lua (L, cur_elt, true); lua_settable (L, -3); } } ucl_object_iterate_free (it); return 1; } else if (obj != NULL) {
static gint lua_config_get_key (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L); const gchar *name; size_t namelen; const ucl_object_t *val; name = luaL_checklstring(L, 2, &namelen); if (name && cfg) { val = ucl_object_find_keyl(cfg->rcl_obj, name, namelen); if (val != NULL) { ucl_object_push_lua (L, val, val->type != UCL_ARRAY); } else { lua_pushnil (L); } } else { lua_pushnil (L); } return 1; }
LL_FOREACH (obj, cur) { lua_pushnumber (L, i++); ucl_object_push_lua (L, cur, true); lua_settable (L, -3); }
gboolean rspamadm_execute_lua_ucl_subr (gpointer pL, gint argc, gchar **argv, const ucl_object_t *res, const gchar *script) { lua_State *L = pL; gint err_idx, cb_idx, i, ret; GString *tb; g_assert (script != NULL); g_assert (res != NULL); g_assert (L != NULL); if (luaL_dostring (L, script) != 0) { msg_err ("cannot execute lua script: %s", lua_tostring (L, -1)); return FALSE; } else { if (lua_type (L, -1) == LUA_TFUNCTION) { cb_idx = luaL_ref (L, LUA_REGISTRYINDEX); } else { msg_err ("lua script must return " "function and not %s", lua_typename (L, lua_type (L, -1))); return FALSE; } } lua_pushcfunction (L, &rspamd_lua_traceback); err_idx = lua_gettop (L); /* Push function */ lua_rawgeti (L, LUA_REGISTRYINDEX, cb_idx); /* Push argv */ lua_newtable (L); for (i = 0; i < argc; i ++) { lua_pushstring (L, argv[i]); lua_rawseti (L, -2, i + 1); } /* Push results */ ucl_object_push_lua (L, res, TRUE); if ((ret = lua_pcall (L, 2, 0, err_idx)) != 0) { tb = lua_touserdata (L, -1); msg_err ("call to adm lua script failed (%d): %v", ret, tb); if (tb) { g_string_free (tb, TRUE); } lua_pop (L, 2); return FALSE; } /* error function */ lua_pop (L, 1); luaL_unref (L, LUA_REGISTRYINDEX, cb_idx); return TRUE; }
static gint lua_worker_get_stat (lua_State *L) { struct rspamd_worker *w = lua_check_worker (L, 1); if (w) { rspamd_mempool_stat_t mem_st; struct rspamd_stat *stat, stat_copy; ucl_object_t *top, *sub; gint i; guint64 spam = 0, ham = 0; memset (&mem_st, 0, sizeof (mem_st)); rspamd_mempool_stat (&mem_st); memcpy (&stat_copy, w->srv->stat, sizeof (stat_copy)); stat = &stat_copy; top = ucl_object_typed_new (UCL_OBJECT); ucl_object_insert_key (top, ucl_object_fromint ( stat->messages_scanned), "scanned", 0, false); ucl_object_insert_key (top, ucl_object_fromint ( stat->messages_learned), "learned", 0, false); if (stat->messages_scanned > 0) { sub = ucl_object_typed_new (UCL_OBJECT); for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i++) { ucl_object_insert_key (sub, ucl_object_fromint (stat->actions_stat[i]), rspamd_action_to_str (i), 0, false); if (i < METRIC_ACTION_GREYLIST) { spam += stat->actions_stat[i]; } else { ham += stat->actions_stat[i]; } } ucl_object_insert_key (top, sub, "actions", 0, false); } else { sub = ucl_object_typed_new (UCL_OBJECT); for (i = METRIC_ACTION_REJECT; i <= METRIC_ACTION_NOACTION; i++) { ucl_object_insert_key (sub, 0, rspamd_action_to_str (i), 0, false); } ucl_object_insert_key (top, sub, "actions", 0, false); } ucl_object_insert_key (top, ucl_object_fromint ( spam), "spam_count", 0, false); ucl_object_insert_key (top, ucl_object_fromint ( ham), "ham_count", 0, false); ucl_object_insert_key (top, ucl_object_fromint (stat->connections_count), "connections", 0, false); ucl_object_insert_key (top, ucl_object_fromint (stat->control_connections_count), "control_connections", 0, false); ucl_object_insert_key (top, ucl_object_fromint (mem_st.pools_allocated), "pools_allocated", 0, false); ucl_object_insert_key (top, ucl_object_fromint (mem_st.pools_freed), "pools_freed", 0, false); ucl_object_insert_key (top, ucl_object_fromint (mem_st.bytes_allocated), "bytes_allocated", 0, false); ucl_object_insert_key (top, ucl_object_fromint ( mem_st.chunks_allocated), "chunks_allocated", 0, false); ucl_object_insert_key (top, ucl_object_fromint (mem_st.shared_chunks_allocated), "shared_chunks_allocated", 0, false); ucl_object_insert_key (top, ucl_object_fromint (mem_st.chunks_freed), "chunks_freed", 0, false); ucl_object_insert_key (top, ucl_object_fromint ( mem_st.oversized_chunks), "chunks_oversized", 0, false); ucl_object_push_lua (L, top, true); ucl_object_unref (top); } else { return luaL_error (L, "invalid arguments"); } return 1; }