static gint lua_config_add_radix_map (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L); const gchar *map_line, *description; radix_compressed_t **r, ***ud; if (cfg) { map_line = luaL_checkstring (L, 2); description = lua_tostring (L, 3); r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (radix_compressed_t *)); *r = radix_create_compressed (); if (!add_map (cfg, map_line, description, read_radix_list, fin_radix_list, (void **)r)) { msg_warn ("invalid radix map %s", map_line); radix_destroy_compressed (*r); lua_pushnil (L); return 1; } ud = lua_newuserdata (L, sizeof (radix_compressed_t *)); *ud = r; rspamd_lua_setclass (L, "rspamd{radix}", -1); return 1; } lua_pushnil (L); return 1; }
static gint lua_config_add_kv_map (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L); const gchar *map_line, *description; GHashTable **r, ***ud; if (cfg) { map_line = luaL_checkstring (L, 2); description = lua_tostring (L, 3); r = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (GHashTable *)); *r = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); if (!add_map (cfg, map_line, description, read_kv_list, fin_kv_list, (void **)r)) { msg_warn ("invalid hash map %s", map_line); g_hash_table_destroy (*r); lua_pushnil (L); return 1; } rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)g_hash_table_destroy, *r); ud = lua_newuserdata (L, sizeof (GHashTable *)); *ud = r; rspamd_lua_setclass (L, "rspamd{hash_table}", -1); return 1; } lua_pushnil (L); return 1; }
static gint lua_config_get_classifier (lua_State * L) { struct rspamd_config *cfg = lua_check_config (L); struct rspamd_classifier_config *clc = NULL, **pclc = NULL; const gchar *name; GList *cur; if (cfg) { name = luaL_checkstring (L, 2); cur = g_list_first (cfg->classifiers); while (cur) { clc = cur->data; if (g_ascii_strcasecmp (clc->classifier->name, name) == 0) { pclc = &clc; break; } cur = g_list_next (cur); } if (pclc) { pclc = lua_newuserdata (L, sizeof (struct rspamd_classifier_config *)); rspamd_lua_setclass (L, "rspamd{classifier}", -1); *pclc = clc; return 1; } } lua_pushnil (L); return 1; }
static gint lua_config_register_symbol (lua_State * L) { struct rspamd_config *cfg = lua_check_config (L); gchar *name; double weight; if (cfg) { name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); weight = luaL_checknumber (L, 3); if (lua_type (L, 4) == LUA_TSTRING) { lua_getglobal (L, luaL_checkstring (L, 4)); } else { lua_pushvalue (L, 4); } if (name) { rspamd_register_symbol_fromlua (L, cfg, name, luaL_ref (L, LUA_REGISTRYINDEX), weight, 0, SYMBOL_TYPE_NORMAL); } } return 0; }
static gint lua_config_register_pre_filter (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L); struct lua_callback_data *cd; if (cfg) { cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); if (lua_type (L, 2) == LUA_TSTRING) { cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); cd->cb_is_ref = FALSE; } else { lua_pushvalue (L, 2); /* Get a reference */ cd->callback.ref = luaL_ref (L, LUA_REGISTRYINDEX); cd->cb_is_ref = TRUE; } cd->L = L; cfg->pre_filters = g_list_prepend (cfg->pre_filters, cd); rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, cd); } return 1; }
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; }
static int lua_config_get_mempool (lua_State * L) { rspamd_mempool_t **ppool; struct rspamd_config *cfg = lua_check_config (L, 1); if (cfg != NULL) { ppool = lua_newuserdata (L, sizeof (rspamd_mempool_t *)); rspamd_lua_setclass (L, "rspamd{mempool}", -1); *ppool = cfg->cfg_pool; } return 1; }
static gint lua_config_add_map (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L); const gchar *map_line, *description; struct lua_map_callback_data *cbdata, **pcbdata; int cbidx; if (cfg) { map_line = luaL_checkstring (L, 2); if (lua_gettop (L) == 4) { description = lua_tostring (L, 3); cbidx = 4; } else { description = NULL; cbidx = 3; } if (lua_type (L, cbidx) == LUA_TFUNCTION) { cbdata = g_slice_alloc (sizeof (*cbdata)); cbdata->L = L; cbdata->data = NULL; lua_pushvalue (L, cbidx); /* Get a reference */ cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX); pcbdata = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (cbdata)); *pcbdata = cbdata; if (!add_map (cfg, map_line, description, lua_map_read, lua_map_fin, (void **)pcbdata)) { msg_warn ("invalid hash map %s", map_line); lua_pushboolean (L, false); } else { lua_pushboolean (L, true); } } else { msg_warn ("invalid callback argument for map %s", map_line); lua_pushboolean (L, false); } } else { lua_pushboolean (L, false); } return 1; }
static gint lua_config_register_virtual_symbol (lua_State * L) { struct rspamd_config *cfg = lua_check_config (L); gchar *name; double weight; if (cfg) { name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); weight = luaL_checknumber (L, 3); if (name) { register_virtual_symbol (&cfg->cache, name, weight); } } return 0; }
static gint lua_config_register_symbols (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L); gint i, top, idx; gchar *sym; gdouble weight = 1.0; if (lua_gettop (L) < 3) { msg_err ("not enough arguments to register a function"); return 0; } if (cfg) { if (lua_type (L, 2) == LUA_TSTRING) { lua_getglobal (L, luaL_checkstring (L, 2)); } else { lua_pushvalue (L, 2); } idx = luaL_ref (L, LUA_REGISTRYINDEX); if (lua_type (L, 3) == LUA_TNUMBER) { weight = lua_tonumber (L, 3); top = 4; } else { top = 3; } sym = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, top)); rspamd_register_symbol_fromlua (L, cfg, sym, idx, weight, 0, SYMBOL_TYPE_NORMAL); for (i = top; i < lua_gettop (L); i++) { sym = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, i + 1)); register_virtual_symbol (&cfg->cache, sym, weight); } } return 0; }
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; }
gint lua_config_radix_from_config (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *mname, *optname; const ucl_object_t *obj; struct rspamd_lua_map *map, **pmap; if (!cfg) { return luaL_error (L, "invalid arguments"); } mname = luaL_checkstring (L, 2); optname = luaL_checkstring (L, 3); if (mname && optname) { obj = rspamd_config_get_module_opt (cfg, mname, optname); if (obj) { map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map)); map->data.radix = radix_create_compressed (); map->type = RSPAMD_LUA_MAP_RADIX; map->data.radix = radix_create_compressed (); map->flags |= RSPAMD_LUA_MAP_FLAG_EMBEDDED; radix_add_generic_iplist (ucl_obj_tostring (obj), &map->data.radix, TRUE); pmap = lua_newuserdata (L, sizeof (void *)); *pmap = map; rspamd_lua_setclass (L, "rspamd{map}", -1); } else { msg_warn_config ("Couldnt find config option [%s][%s]", mname, optname); lua_pushnil (L); } } else { return luaL_error (L, "invalid arguments"); } 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; }
gint lua_config_add_hash_map (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *map_line, *description; struct rspamd_lua_map *map, **pmap; struct rspamd_map *m; if (cfg) { map_line = luaL_checkstring (L, 2); description = lua_tostring (L, 3); map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map)); map->data.hash = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal); map->type = RSPAMD_LUA_MAP_SET; if ((m = rspamd_map_add (cfg, map_line, description, rspamd_hosts_read, rspamd_hosts_fin, (void **)&map->data.hash)) == NULL) { msg_warn_config ("invalid set map %s", map_line); g_hash_table_destroy (map->data.hash); lua_pushnil (L); return 1; } map->map = m; pmap = lua_newuserdata (L, sizeof (void *)); *pmap = map; rspamd_lua_setclass (L, "rspamd{map}", -1); } else { return luaL_error (L, "invalid arguments"); } return 1; }
gint lua_config_add_radix_map (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L, 1); const gchar *map_line, *description; struct rspamd_lua_map *map, **pmap; struct rspamd_map *m; if (cfg) { map_line = luaL_checkstring (L, 2); description = lua_tostring (L, 3); map = rspamd_mempool_alloc0 (cfg->cfg_pool, sizeof (*map)); map->data.radix = radix_create_compressed (); map->type = RSPAMD_LUA_MAP_RADIX; if ((m = rspamd_map_add (cfg, map_line, description, rspamd_radix_read, rspamd_radix_fin, (void **)&map->data.radix)) == NULL) { msg_warn_config ("invalid radix map %s", map_line); radix_destroy_compressed (map->data.radix); lua_pushnil (L); return 1; } map->map = m; pmap = lua_newuserdata (L, sizeof (void *)); *pmap = map; rspamd_lua_setclass (L, "rspamd{map}", -1); } else { return luaL_error (L, "invalid arguments"); } 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; }
static gint lua_config_register_function (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L); gchar *name; struct lua_callback_data *cd; if (cfg) { name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 2)); cd = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (struct lua_callback_data)); if (lua_type (L, 3) == LUA_TSTRING) { cd->callback.name = rspamd_mempool_strdup (cfg->cfg_pool, luaL_checkstring (L, 3)); cd->cb_is_ref = FALSE; } else { lua_pushvalue (L, 3); /* Get a reference */ cd->callback.ref = luaL_ref (L, LUA_REGISTRYINDEX); cd->cb_is_ref = TRUE; } if (name) { cd->L = L; cd->symbol = name; register_expression_function (name, lua_config_function_callback, cd); } rspamd_mempool_add_destructor (cfg->cfg_pool, (rspamd_mempool_destruct_t)lua_destroy_cfg_symbol, cd); } return 1; }
static gint lua_config_newindex (lua_State *L) { struct rspamd_config *cfg = lua_check_config (L); const gchar *name; name = luaL_checkstring (L, 2); if (name != NULL && lua_gettop (L) > 2) { if (lua_type (L, 3) == LUA_TFUNCTION) { /* Normal symbol from just a function */ lua_pushvalue (L, 3); rspamd_register_symbol_fromlua (L, cfg, name, luaL_ref (L, LUA_REGISTRYINDEX), 1.0, 0, SYMBOL_TYPE_NORMAL); } else if (lua_type (L, 3) == LUA_TTABLE) { gint type = SYMBOL_TYPE_NORMAL, priority = 0, idx; gdouble weight = 1.0; const char *type_str; /* * Table can have the following attributes: * "callback" - should be a callback function * "weight" - optional weight * "priority" - optional priority * "type" - optional type (normal, virtual, callback) */ lua_pushstring (L, "callback"); lua_gettable (L, -2); if (lua_type (L, -1) != LUA_TFUNCTION) { lua_pop (L, 1); msg_info ("cannot find callback definition for %s", name); return 0; } idx = luaL_ref (L, LUA_REGISTRYINDEX); /* Optional fields */ lua_pushstring (L, "weight"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TNUMBER) { weight = lua_tonumber (L, -1); } lua_pop (L, 1); lua_pushstring (L, "priority"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TNUMBER) { priority = lua_tonumber (L, -1); } lua_pop (L, 1); lua_pushstring (L, "type"); lua_gettable (L, -2); if (lua_type (L, -1) == LUA_TSTRING) { type_str = lua_tostring (L, -1); if (strcmp (type_str, "normal") == 0) { type = SYMBOL_TYPE_NORMAL; } else if (strcmp (type_str, "virtual") == 0) { type = SYMBOL_TYPE_VIRTUAL; } else if (strcmp (type_str, "callback") == 0) { type = SYMBOL_TYPE_CALLBACK; } else { msg_info ("unknown type: %s", type_str); } } lua_pop (L, 1); rspamd_register_symbol_fromlua (L, cfg, name, idx, weight, priority, type); } } return 0; }