aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rspamd.com>2024-09-02 21:46:49 +0600
committerGitHub <noreply@github.com>2024-09-02 21:46:49 +0600
commited6aa0eeb6b9b5b526efa683a29a1ccec59ae609 (patch)
treeb0818aa52dda2560d9185516070d5adea709eb9f
parent77fb571511c987376d10b0b4045ef65d45a33e20 (diff)
parent1b60ee74a01892bdec4424138dd80958c921f3cc (diff)
downloadrspamd-ed6aa0eeb6b9b5b526efa683a29a1ccec59ae609.tar.gz
rspamd-ed6aa0eeb6b9b5b526efa683a29a1ccec59ae609.zip
Merge pull request #5125 from rspamd/vstakhov-lua-fix-register-symbols
[Fix] Unify lua symbols registration
-rw-r--r--src/lua/lua_config.c852
1 files changed, 410 insertions, 442 deletions
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index 717aa81ce..be4dd7081 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -34,7 +34,11 @@
local function foo(task)
-- do something
end
-rspamd_config:register_symbol('SYMBOL', 1.0, foo)
+rspamd_config:register_symbol{
+ name = 'SYMBOL',
+ score = 1.0,
+ callback = foo
+}
-- Get configuration
local tab = rspamd_config:get_all_opt('module') -- get table for module's options
@@ -1957,210 +1961,454 @@ lua_config_get_symbol_flags(lua_State *L)
return 1;
}
-static int
-lua_config_register_symbol(lua_State *L)
+static bool
+lua_config_register_symbol_from_table(lua_State *L, struct rspamd_config *cfg,
+ const char *name, int tbl_idx, int *id_out)
{
- LUA_TRACE_POINT;
- struct rspamd_config *cfg = lua_check_config(L, 1);
- const char *name = NULL, *type_str = NULL,
- *description = NULL, *group = NULL;
- double weight = 0, score = NAN, parent_float = NAN;
- gboolean one_shot = FALSE;
- int ret = -1, cbref = -1;
- unsigned int type = 0, flags = 0;
- int64_t parent = 0, priority = 0, nshots = 0;
+ unsigned int type = SYMBOL_TYPE_NORMAL, priority = 0;
+ double weight = 1.0, score = NAN;
+ const char *type_str, *group = NULL, *description = NULL;
GArray *allowed_ids = NULL, *forbidden_ids = NULL;
- GError *err = NULL;
- int prev_top = lua_gettop(L);
+ int id, nshots, cb_ref, parent = -1;
+ unsigned int flags = 0;
+ gboolean optional = FALSE;
- if (cfg) {
- if (!rspamd_lua_parse_table_arguments(L, 2, &err,
- RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
- "name=S;weight=N;callback=F;type=S;priority=I;parent=D;"
- "score=D;description=S;group=S;one_shot=B;nshots=I",
- &name, &weight, &cbref, &type_str,
- &priority, &parent_float,
- &score, &description, &group, &one_shot, &nshots)) {
- msg_err_config("bad arguments: %e", err);
- g_error_free(err);
- lua_settop(L, prev_top);
+ /*
+ * Table can have the following attributes:
+ * "callback" - should be a callback function
+ * "weight" - optional weight
+ * "priority" - optional priority
+ * "type" - optional type (normal, virtual, callback)
+ * "flags" - optional flags
+ * -- Metric options
+ * "score" - optional default score (overridden by metric)
+ * "group" - optional default group
+ * "one_shot" - optional one shot mode
+ * "description" - optional description
+ */
+ lua_pushvalue(L, tbl_idx); /* Push table on top of the stack */
- return luaL_error(L, "invalid arguments");
- }
+ if (name == NULL) {
+ /* Try to resolve name */
+ lua_pushstring(L, "name");
+ lua_gettable(L, -2);
- /* Deal with flags and ids */
- lua_pushstring(L, "flags");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- flags = lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- }
- lua_pop(L, 1); /* Clean flags */
+ if (lua_type(L, -1) != LUA_TSTRING) {
+ lua_pop(L, 2);
+ luaL_error(L, "name is not specified");
- lua_pushstring(L, "allowed_ids");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ return false;
}
- else if (lua_type(L, -1) == LUA_TTABLE) {
- allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(allowed_ids, v);
- }
+ else {
+ name = lua_tostring(L, -1);
}
+
lua_pop(L, 1);
+ }
- lua_pushstring(L, "forbidden_ids");
- lua_gettable(L, 2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ lua_pushstring(L, "callback");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) != LUA_TFUNCTION) {
+ cb_ref = -1;
+ }
+ else {
+ cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
+ }
+ lua_pop(L, 1);
+
+ /* 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_tointeger(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "optional");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ optional = lua_toboolean(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);
+ }
+ else {
+ type_str = "normal";
+ }
+ lua_pop(L, 1);
+
+ type = lua_parse_symbol_type(type_str);
+
+ if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
+ luaL_error(L, "no symbol name but type is not callback");
+
+ return false;
+ }
+ else if (!(type & SYMBOL_TYPE_VIRTUAL) && cb_ref == -1) {
+ luaL_error(L, "no callback for symbol %s", name);
+
+ return false;
+ }
+
+ lua_pushstring(L, "parent");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ parent = lua_tointeger(L, -1);
+ }
+ lua_pop(L, 1);
+
+
+ /* Deal with flags and ids */
+ lua_pushstring(L, "flags");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ flags = lua_parse_symbol_flags(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
}
- else if (lua_type(L, -1) == LUA_TTABLE) {
- forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(forbidden_ids, v);
- }
+ }
+ lua_pop(L, 1); /* Clean flags */
+
+ lua_pushstring(L, "allowed_ids");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
+ rspamd_lua_table_size(L, -1));
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ uint32_t v = lua_tointeger(L, -1);
+ g_array_append_val(allowed_ids, v);
}
- lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
- if (nshots == 0) {
- nshots = cfg->default_max_shots;
+ lua_pushstring(L, "forbidden_ids");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
+ }
+ else if (lua_type(L, -1) == LUA_TTABLE) {
+ forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
+ rspamd_lua_table_size(L, -1));
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ uint32_t v = lua_tointeger(L, -1);
+ g_array_append_val(forbidden_ids, v);
}
+ }
+ lua_pop(L, 1);
- type = lua_parse_symbol_type(type_str);
+ id = rspamd_register_symbol_fromlua(L,
+ cfg,
+ name,
+ cb_ref,
+ weight,
+ priority,
+ type | flags,
+ parent,
+ allowed_ids, forbidden_ids,
+ optional);
- if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
- lua_settop(L, prev_top);
- return luaL_error(L, "no symbol name but type is not callback");
- }
- else if (!(type & SYMBOL_TYPE_VIRTUAL) && cbref == -1) {
- lua_settop(L, prev_top);
- return luaL_error(L, "no callback for symbol %s", name);
- }
+ if (allowed_ids) {
+ g_array_free(allowed_ids, TRUE);
+ }
+
+ if (forbidden_ids) {
+ g_array_free(forbidden_ids, TRUE);
+ }
+
+ if (id != -1) {
+ if (cb_ref != -1) {
+ /* Check for condition */
+ lua_pushstring(L, "condition");
+ lua_gettable(L, -2);
- if (isnan(parent_float)) {
- parent = -1;
+ if (lua_type(L, -1) == LUA_TFUNCTION) {
+ int condref;
+
+ /* Here we pop function from the stack, so no lua_pop is required */
+ condref = luaL_ref(L, LUA_REGISTRYINDEX);
+ g_assert(name != NULL);
+ rspamd_symcache_add_condition_delayed(cfg->cache,
+ name, L, condref);
+ }
+ else {
+ lua_pop(L, 1);
+ }
}
- else {
- parent = parent_float;
+
+ /* Check for augmentations */
+ lua_pushstring(L, "augmentations");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TTABLE) {
+
+ int aug_tbl_idx = lua_gettop(L);
+ for (lua_pushnil(L); lua_next(L, aug_tbl_idx); lua_pop(L, 1)) {
+ rspamd_symcache_add_symbol_augmentation(cfg->cache, id,
+ lua_tostring(L, -1), NULL);
+ }
}
- ret = rspamd_register_symbol_fromlua(L,
- cfg,
- name,
- cbref,
- weight == 0 ? 1.0 : weight,
- priority,
- type | flags,
- parent,
- allowed_ids, forbidden_ids,
- FALSE);
+ lua_pop(L, 1);
+ }
- if (allowed_ids) {
- g_array_free(allowed_ids, TRUE);
+ /*
+ * Now check if a symbol has not been registered in any metric and
+ * insert default value if applicable
+ */
+ struct rspamd_symbol *sym = g_hash_table_lookup(cfg->symbols, name);
+ if (sym == NULL || (sym->flags & RSPAMD_SYMBOL_FLAG_UNSCORED)) {
+ nshots = cfg->default_max_shots;
+
+ lua_pushstring(L, "score");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TNUMBER) {
+ score = lua_tonumber(L, -1);
+
+ if (sym) {
+ /* Reset unscored flag */
+ sym->flags &= ~RSPAMD_SYMBOL_FLAG_UNSCORED;
+ }
}
+ lua_pop(L, 1);
- if (forbidden_ids) {
- g_array_free(forbidden_ids, TRUE);
+ lua_pushstring(L, "group");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ group = lua_tostring(L, -1);
}
+ lua_pop(L, 1);
+
+ if (!isnan(score) || group != NULL) {
+ lua_pushstring(L, "description");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ description = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+
+ lua_pushstring(L, "one_shot");
+ lua_gettable(L, -2);
- if (ret != -1) {
- if (!isnan(score) || group) {
- if (one_shot) {
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ if (lua_toboolean(L, -1)) {
nshots = 1;
}
+ }
+ lua_pop(L, 1);
- rspamd_config_add_symbol(cfg, name,
- score, description, group, flags,
- 0, nshots);
+ lua_pushstring(L, "one_param");
+ lua_gettable(L, -2);
- lua_pushstring(L, "groups");
- lua_gettable(L, 2);
+ if (lua_type(L, -1) == LUA_TBOOLEAN) {
+ if (lua_toboolean(L, -1)) {
+ flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
+ }
+ }
+ lua_pop(L, 1);
- if (lua_istable(L, -1)) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- if (lua_isstring(L, -1)) {
- rspamd_config_add_symbol_group(cfg, name,
- lua_tostring(L, -1));
- }
- else {
- lua_settop(L, prev_top);
- return luaL_error(L, "invalid groups element");
- }
+ /*
+ * Do not override the existing symbols (using zero priority),
+ * since we are defining default values here
+ */
+ if (!isnan(score)) {
+ rspamd_config_add_symbol(cfg, name, score,
+ description, group, flags, 0, nshots);
+ }
+ else if (group) {
+ /* Add with zero score */
+ rspamd_config_add_symbol(cfg, name, NAN,
+ description, group, flags, 0, nshots);
+ }
+
+ lua_pushstring(L, "groups");
+ lua_gettable(L, -2);
+
+ if (lua_istable(L, -1)) {
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ if (lua_isstring(L, -1)) {
+ rspamd_config_add_symbol_group(cfg, name,
+ lua_tostring(L, -1));
+ }
+ else {
+ lua_pop(L, 2);
+ luaL_error(L, "invalid groups element");
+
+ return false;
}
}
+ }
- lua_pop(L, 1);
+ lua_pop(L, 1);
+ }
+ }
+ else {
+ /* Fill in missing fields from lua definition if they are not set */
+ if (sym->description == NULL) {
+ lua_pushstring(L, "description");
+ lua_gettable(L, -2);
+
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ description = lua_tostring(L, -1);
}
+ lua_pop(L, 1);
- lua_pushstring(L, "augmentations");
- lua_gettable(L, 2);
+ if (description) {
+ sym->description = rspamd_mempool_strdup(cfg->cfg_pool, description);
+ }
+ }
- if (lua_type(L, -1) == LUA_TTABLE) {
- int tbl_idx = lua_gettop(L);
- for (lua_pushnil(L); lua_next(L, tbl_idx); lua_pop(L, 1)) {
- size_t len;
- const char *augmentation = lua_tolstring(L, -1, &len), *eqsign_pos;
+ /* If ungrouped and there is a group defined in lua, change the primary group
+ * Otherwise, add to the list of groups for this symbol. */
+ lua_pushstring(L, "group");
+ lua_gettable(L, -2);
+ if (lua_type(L, -1) == LUA_TSTRING) {
+ group = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+ if (group) {
+ if (sym->flags & RSPAMD_SYMBOL_FLAG_UNGROUPED) {
+ /* Unset the "ungrouped" group */
+ sym->gr = NULL;
+ }
+ /* Add the group. If the symbol was ungrouped, this will
+ * clear RSPAMD_SYMBOL_FLAG_UNGROUPED from the flags. */
+ rspamd_config_add_symbol_group(cfg, name, group);
+ }
+ }
- /* Find `=` symbol and use it as a separator */
- eqsign_pos = memchr(augmentation, '=', len);
- if (eqsign_pos != NULL && eqsign_pos + 1 < augmentation + len) {
- rspamd_ftok_t tok;
+ /* Remove table from stack */
+ lua_pop(L, 1);
- tok.begin = augmentation;
- tok.len = eqsign_pos - augmentation;
- char *augentation_name = rspamd_ftokdup(&tok);
+ *id_out = id;
- tok.begin = eqsign_pos + 1;
- tok.len = (augmentation + len) - tok.begin;
+ return true;
+}
- char *augmentation_value = rspamd_ftokdup(&tok);
+/* Legacy symbol registration */
+static bool
+lua_config_register_symbol_legacy(lua_State *L, struct rspamd_config *cfg, int pos, int *id_out)
+{
+ const char *name = NULL, *type_str = NULL,
+ *description = NULL, *group = NULL;
+ double weight = 0, score = NAN, parent_float = NAN;
+ gboolean one_shot = FALSE;
+ int ret, cbref = -1;
+ unsigned int type = 0, flags = 0;
+ int64_t parent = 0, priority = 0, nshots = 0;
- if (!rspamd_symcache_add_symbol_augmentation(cfg->cache, ret,
- augentation_name, augmentation_value)) {
- lua_settop(L, prev_top);
- g_free(augmentation_value);
- g_free(augentation_name);
+ GError *err = NULL;
+ if (!rspamd_lua_parse_table_arguments(L, pos, &err,
+ RSPAMD_LUA_PARSE_ARGUMENTS_DEFAULT,
+ "name=S;weight=N;callback=F;type=S;priority=I;parent=D;"
+ "score=D;description=S;group=S;one_shot=B;nshots=I",
+ &name, &weight, &cbref, &type_str,
+ &priority, &parent_float,
+ &score, &description, &group, &one_shot, &nshots)) {
+ msg_err_config("bad arguments: %e", err);
+ g_error_free(err);
- return luaL_error(L, "unknown or invalid augmentation %s in symbol %s",
- augmentation, name);
- }
+ return false;
+ }
- g_free(augmentation_value);
- g_free(augentation_name);
- }
- else {
- /* Just a value */
- if (!rspamd_symcache_add_symbol_augmentation(cfg->cache, ret,
- augmentation, NULL)) {
- lua_settop(L, prev_top);
+ type = lua_parse_symbol_type(type_str);
- return luaL_error(L, "unknown augmentation %s in symbol %s",
- augmentation, name);
- }
- }
- }
+ if (!name && !(type & SYMBOL_TYPE_CALLBACK)) {
+ luaL_error(L, "no symbol name but type is not callback");
+
+ return false;
+ }
+ else if (!(type & SYMBOL_TYPE_VIRTUAL) && cbref == -1) {
+ luaL_error(L, "no callback for symbol %s", name);
+
+ return false;
+ }
+
+ if (isnan(parent_float)) {
+ parent = -1;
+ }
+ else {
+ parent = parent_float;
+ }
+
+ ret = rspamd_register_symbol_fromlua(L,
+ cfg,
+ name,
+ cbref,
+ weight == 0 ? 1.0 : weight,
+ priority,
+ type | flags,
+ parent,
+ NULL, NULL,
+ FALSE);
+
+ if (ret != -1) {
+ if (!isnan(score) || group) {
+ if (one_shot) {
+ nshots = 1;
+ }
+ if (nshots == 0) {
+ nshots = cfg->default_max_shots;
}
+
+ rspamd_config_add_symbol(cfg, name, score,
+ description, group, flags, 0, nshots);
}
+
+ *id_out = ret;
+
+ return true;
}
- else {
- lua_settop(L, prev_top);
- return luaL_error(L, "invalid arguments");
+ return false;
+}
+
+static int
+lua_config_register_symbol(lua_State *L)
+{
+ LUA_TRACE_POINT;
+ struct rspamd_config *cfg = lua_check_config(L, 1);
+ int id = -1;
+
+ if (lua_type(L, 2) == LUA_TSTRING) {
+ if (lua_config_register_symbol_legacy(L, cfg, 2, &id)) {
+ lua_pushinteger(L, id);
+
+ return 1;
+ }
+ else {
+ return luaL_error(L, "bad arguments");
+ }
}
+ else if (lua_config_register_symbol_from_table(L, cfg, NULL, 2, &id)) {
+ lua_pushinteger(L, id);
- lua_settop(L, prev_top);
- lua_pushinteger(L, ret);
+ return 1;
+ }
- return 1;
+ return 0;
}
static int
@@ -2647,10 +2895,7 @@ lua_config_newindex(lua_State *L)
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config(L, 1);
const char *name;
- GArray *allowed_ids = NULL, *forbidden_ids = NULL;
- int id, nshots;
- unsigned int flags = 0;
- gboolean optional = FALSE;
+ int id = -1;
name = luaL_checkstring(L, 2);
@@ -2671,291 +2916,14 @@ lua_config_newindex(lua_State *L)
FALSE);
}
else if (lua_type(L, 3) == LUA_TTABLE) {
- unsigned int type = SYMBOL_TYPE_NORMAL, priority = 0;
- int idx;
- double weight = 1.0, score = NAN;
- const char *type_str, *group = NULL, *description = NULL;
-
- /*
- * Table can have the following attributes:
- * "callback" - should be a callback function
- * "weight" - optional weight
- * "priority" - optional priority
- * "type" - optional type (normal, virtual, callback)
- * "flags" - optional flags
- * -- Metric options
- * "score" - optional default score (overridden by metric)
- * "group" - optional default group
- * "one_shot" - optional one shot mode
- * "description" - optional description
- */
- lua_pushvalue(L, 3);
- lua_pushstring(L, "callback");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) != LUA_TFUNCTION) {
- lua_pop(L, 2);
- msg_info_config("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_tointeger(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "optional");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- optional = lua_toboolean(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);
- type = lua_parse_symbol_type(type_str);
- }
- lua_pop(L, 1);
-
- /* Deal with flags and ids */
- lua_pushstring(L, "flags");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- flags = lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- flags |= lua_parse_symbol_flags(lua_tostring(L, -1));
- }
- }
- lua_pop(L, 1); /* Clean flags */
-
- lua_pushstring(L, "allowed_ids");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- allowed_ids = rspamd_process_id_list(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- allowed_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(allowed_ids, v);
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "forbidden_ids");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- forbidden_ids = rspamd_process_id_list(lua_tostring(L, -1));
- }
- else if (lua_type(L, -1) == LUA_TTABLE) {
- forbidden_ids = g_array_sized_new(FALSE, FALSE, sizeof(uint32_t),
- rspamd_lua_table_size(L, -1));
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- uint32_t v = lua_tointeger(L, -1);
- g_array_append_val(forbidden_ids, v);
- }
- }
- lua_pop(L, 1);
-
- id = rspamd_register_symbol_fromlua(L,
- cfg,
- name,
- idx,
- weight,
- priority,
- type | flags,
- -1,
- allowed_ids, forbidden_ids,
- optional);
-
- if (allowed_ids) {
- g_array_free(allowed_ids, TRUE);
- }
-
- if (forbidden_ids) {
- g_array_free(forbidden_ids, TRUE);
- }
-
- if (id != -1) {
- /* Check for condition */
- lua_pushstring(L, "condition");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TFUNCTION) {
- int condref;
-
- /* Here we pop function from the stack, so no lua_pop is required */
- condref = luaL_ref(L, LUA_REGISTRYINDEX);
- g_assert(name != NULL);
- rspamd_symcache_add_condition_delayed(cfg->cache,
- name, L, condref);
- }
- else {
- lua_pop(L, 1);
- }
-
- /* Check for augmentations */
- lua_pushstring(L, "augmentations");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TTABLE) {
-
- int tbl_idx = lua_gettop(L);
- for (lua_pushnil(L); lua_next(L, tbl_idx); lua_pop(L, 1)) {
- rspamd_symcache_add_symbol_augmentation(cfg->cache, id,
- lua_tostring(L, -1), NULL);
- }
- }
-
- lua_pop(L, 1);
- }
-
- /*
- * Now check if a symbol has not been registered in any metric and
- * insert default value if applicable
- */
- struct rspamd_symbol *sym = g_hash_table_lookup(cfg->symbols, name);
- if (sym == NULL || (sym->flags & RSPAMD_SYMBOL_FLAG_UNSCORED)) {
- nshots = cfg->default_max_shots;
-
- lua_pushstring(L, "score");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TNUMBER) {
- score = lua_tonumber(L, -1);
-
- if (sym) {
- /* Reset unscored flag */
- sym->flags &= ~RSPAMD_SYMBOL_FLAG_UNSCORED;
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "group");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- group = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- if (!isnan(score) || group != NULL) {
- lua_pushstring(L, "description");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TSTRING) {
- description = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "one_shot");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- if (lua_toboolean(L, -1)) {
- nshots = 1;
- }
- }
- lua_pop(L, 1);
-
- lua_pushstring(L, "one_param");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TBOOLEAN) {
- if (lua_toboolean(L, -1)) {
- flags |= RSPAMD_SYMBOL_FLAG_ONEPARAM;
- }
- }
- lua_pop(L, 1);
-
- /*
- * Do not override the existing symbols (using zero priority),
- * since we are defining default values here
- */
- if (!isnan(score)) {
- rspamd_config_add_symbol(cfg, name, score,
- description, group, flags, 0, nshots);
- }
- else if (group) {
- /* Add with zero score */
- rspamd_config_add_symbol(cfg, name, NAN,
- description, group, flags, 0, nshots);
- }
-
- lua_pushstring(L, "groups");
- lua_gettable(L, -2);
-
- if (lua_istable(L, -1)) {
- for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
- if (lua_isstring(L, -1)) {
- rspamd_config_add_symbol_group(cfg, name,
- lua_tostring(L, -1));
- }
- else {
- return luaL_error(L, "invalid groups element");
- }
- }
- }
-
- lua_pop(L, 1);
- }
- }
- else {
- /* Fill in missing fields from lua definition if they are not set */
- if (sym->description == NULL) {
- lua_pushstring(L, "description");
- lua_gettable(L, -2);
-
- if (lua_type(L, -1) == LUA_TSTRING) {
- description = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
-
- if (description) {
- sym->description = rspamd_mempool_strdup(cfg->cfg_pool, description);
- }
- }
-
- /* If ungrouped and there is a group defined in lua, change the primary group
- * Otherwise, add to the list of groups for this symbol. */
- lua_pushstring(L, "group");
- lua_gettable(L, -2);
- if (lua_type(L, -1) == LUA_TSTRING) {
- group = lua_tostring(L, -1);
- }
- lua_pop(L, 1);
- if (group) {
- if (sym->flags & RSPAMD_SYMBOL_FLAG_UNGROUPED) {
- /* Unset the "ungrouped" group */
- sym->gr = NULL;
- }
- /* Add the group. If the symbol was ungrouped, this will
- * clear RSPAMD_SYMBOL_FLAG_UNGROUPED from the flags. */
- rspamd_config_add_symbol_group(cfg, name, group);
- }
+ /* Table symbol */
+ if (lua_config_register_symbol_from_table(L, cfg, name, 3, &id)) {
+ lua_pushinteger(L, id);
+ return 1;
}
-
- /* Remove table from stack */
- lua_pop(L, 1);
+ }
+ else {
+ return luaL_error(L, "invalid value for symbol");
}
}
else {