summaryrefslogtreecommitdiffstats
path: root/src/lua/lua_cfg_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lua/lua_cfg_file.c')
-rw-r--r--src/lua/lua_cfg_file.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/lua/lua_cfg_file.c b/src/lua/lua_cfg_file.c
new file mode 100644
index 0000000..75bc380
--- /dev/null
+++ b/src/lua/lua_cfg_file.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2023 Vsevolod Stakhov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "lua_common.h"
+#include "expression.h"
+#include "src/libserver/composites/composites.h"
+
+/*
+ * This is implementation of lua routines to handle config file params
+ */
+
+/* Process a single item in 'metrics' table */
+static void
+lua_process_metric(lua_State *L, const gchar *name, struct rspamd_config *cfg)
+{
+ gchar *symbol;
+ const gchar *desc = NULL;
+ gdouble *score;
+ struct rspamd_symbol *s;
+
+ /* Now iterate through module table */
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ /* key - -2, value - -1 */
+ symbol = rspamd_mempool_strdup(cfg->cfg_pool, luaL_checkstring(L, -2));
+ if (symbol != NULL) {
+ if (lua_istable(L, -1)) {
+ /* We got a table, so extract individual attributes */
+ lua_pushstring(L, "weight");
+ lua_gettable(L, -2);
+ if (lua_isnumber(L, -1)) {
+ score = rspamd_mempool_alloc(cfg->cfg_pool, sizeof(double));
+ *score = lua_tonumber(L, -1);
+ }
+ else {
+ msg_warn_config("cannot get weight of symbol: %s", symbol);
+ continue;
+ }
+ lua_pop(L, 1);
+ lua_pushstring(L, "description");
+ lua_gettable(L, -2);
+ if (lua_isstring(L, -1)) {
+ desc = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+ }
+ else if (lua_isnumber(L, -1)) {
+ /* Just got weight */
+ score = rspamd_mempool_alloc(cfg->cfg_pool, sizeof(double));
+ *score = lua_tonumber(L, -1);
+ }
+ else {
+ msg_warn_config("cannot get weight of symbol: %s", symbol);
+ continue;
+ }
+ /* Insert symbol */
+ if ((s =
+ g_hash_table_lookup(cfg->symbols, symbol)) != NULL) {
+ msg_info_config("replacing weight for symbol %s: %.2f -> %.2f",
+ symbol,
+ *s->weight_ptr,
+ *score);
+ s->weight_ptr = score;
+ }
+ else {
+ s = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*s));
+ s->name = symbol;
+ s->weight_ptr = score;
+ g_hash_table_insert(cfg->symbols, symbol, s);
+ }
+
+ if (desc) {
+ s->description = rspamd_mempool_strdup(cfg->cfg_pool, desc);
+ }
+ }
+ }
+}
+
+/* Do post load initialization based on lua */
+void rspamd_lua_post_load_config(struct rspamd_config *cfg)
+{
+ lua_State *L = cfg->lua_state;
+ const gchar *name;
+ ucl_object_t *obj;
+ gsize keylen, i;
+
+ /* First check all module options that may be overridden in 'config' global */
+ lua_getglobal(L, "config");
+
+ if (lua_istable(L, -1)) {
+ /* Iterate to get all keys */
+ GPtrArray *names = g_ptr_array_new_full(rspamd_lua_table_size(L, -1),
+ g_free);
+
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 2)) {
+ gchar *tmp;
+ lua_pushvalue(L, -2);
+ name = luaL_checklstring(L, -1, &keylen);
+
+ if (name && lua_istable(L, -2)) {
+ tmp = g_malloc(keylen + 1);
+ rspamd_strlcpy(tmp, name, keylen + 1);
+ g_ptr_array_add(names, tmp);
+ }
+ }
+
+ PTR_ARRAY_FOREACH(names, i, name)
+ {
+ lua_getfield(L, -1, name);
+
+ if (lua_istable(L, -1)) {
+ obj = ucl_object_lua_import(L, lua_gettop(L));
+
+ if (obj != NULL) {
+ ucl_object_sort_keys(obj, UCL_SORT_KEYS_DEFAULT);
+ ucl_object_insert_key_merged(cfg->cfg_ucl_obj,
+ obj,
+ name,
+ strlen(name),
+ true);
+ }
+ }
+ }
+
+ g_ptr_array_free(names, TRUE);
+ }
+
+ /* Check metrics settings */
+ lua_getglobal(L, "metrics");
+
+ if (lua_istable(L, -1)) {
+ /* Iterate */
+ for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) {
+ /* 'key' is at index -2 and 'value' is at index -1 */
+ /* Key must be a string and value must be a table */
+ name = luaL_checkstring(L, -2);
+ if (name != NULL && lua_istable(L, -1)) {
+ lua_process_metric(L, name, cfg);
+ }
+ }
+ }
+
+ lua_settop(L, 0);
+
+ rspamd_lua_start_gc(cfg);
+}