summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rspamd.com>2023-08-17 12:44:51 +0100
committerGitHub <noreply@github.com>2023-08-17 12:44:51 +0100
commitdbaf8c69895ec2a90a20dbf41b4fa474ac12910b (patch)
treeb9ff352e71a6a46914859063e00999793c6ba7f6 /src
parente74199003982c88aea6367922042a7291bbe1bde (diff)
parent87c6b54923fb5bc8105d5adecf33b5f7fa926d65 (diff)
downloadrspamd-dbaf8c69895ec2a90a20dbf41b4fa474ac12910b.tar.gz
rspamd-dbaf8c69895ec2a90a20dbf41b4fa474ac12910b.zip
Merge pull request #4573 from rspamd/cfg_utils_rework
[Project] Rewrite configuration utils in C++
Diffstat (limited to 'src')
-rw-r--r--src/controller.c43
-rw-r--r--src/fuzzy_storage.c8
-rw-r--r--src/libmime/lang_detection.c8
-rw-r--r--src/libmime/lang_detection_fasttext.cxx6
-rw-r--r--src/libmime/scan_result.c39
-rw-r--r--src/libserver/CMakeLists.txt86
-rw-r--r--src/libserver/cfg_file.h113
-rw-r--r--src/libserver/cfg_file_private.h13
-rw-r--r--src/libserver/cfg_rcl.cxx (renamed from src/libserver/cfg_rcl.c)1862
-rw-r--r--src/libserver/cfg_rcl.h68
-rw-r--r--src/libserver/cfg_utils.cxx (renamed from src/libserver/cfg_utils.c)1128
-rw-r--r--src/libserver/dns.c10
-rw-r--r--src/libserver/dynamic_cfg.c8
-rw-r--r--src/libserver/fuzzy_backend/fuzzy_backend_redis.c8
-rw-r--r--src/libserver/http/http_context.c8
-rw-r--r--src/libserver/protocol.c123
-rw-r--r--src/libserver/rspamd_symcache.h8
-rw-r--r--src/libserver/symcache/symcache_c.cxx8
-rw-r--r--src/libserver/symcache/symcache_impl.cxx12
-rw-r--r--src/libserver/symcache/symcache_internal.hxx10
-rw-r--r--src/libserver/symcache/symcache_item.cxx8
-rw-r--r--src/libserver/symcache/symcache_item.hxx8
-rw-r--r--src/libstat/backends/redis_backend.c8
-rw-r--r--src/libstat/learn_cache/redis_cache.c8
-rw-r--r--src/libutil/addr.c12
-rw-r--r--src/libutil/cxx/file_util.hxx15
-rw-r--r--src/libutil/cxx/util.hxx64
-rw-r--r--src/libutil/cxx/util_tests.cxx40
-rw-r--r--src/libutil/mem_pool.c17
-rw-r--r--src/libutil/mem_pool.h10
-rw-r--r--src/lua/lua_cfg_file.c8
-rw-r--r--src/lua/lua_common.h11
-rw-r--r--src/lua/lua_config.c47
-rw-r--r--src/lua/lua_task.c20
-rw-r--r--src/lua/lua_util.c14
-rw-r--r--src/plugins/regexp.c8
-rw-r--r--src/rspamadm/configdump.c14
-rw-r--r--src/rspamadm/confighelp.c10
-rw-r--r--src/rspamd.h11
39 files changed, 1856 insertions, 2046 deletions
diff --git a/src/controller.c b/src/controller.c
index a6d8a7ca9..13e6794af 100644
--- a/src/controller.c
+++ b/src/controller.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -870,6 +870,20 @@ rspamd_controller_handle_symbols(struct rspamd_http_connection_entry *conn_ent,
return 0;
}
+static void
+rspamd_controller_actions_cb(struct rspamd_action *act, void *cbd)
+{
+ ucl_object_t *top = (ucl_object_t *) cbd;
+ ucl_object_t *obj = ucl_object_typed_new(UCL_OBJECT);
+ ucl_object_insert_key(obj,
+ ucl_object_fromstring(act->name),
+ "action", 0, false);
+ ucl_object_insert_key(obj,
+ ucl_object_fromdouble(act->threshold),
+ "value", 0, false);
+ ucl_array_append(top, obj);
+}
+
/*
* Actions command handler:
* request: /actions
@@ -884,8 +898,7 @@ rspamd_controller_handle_actions(struct rspamd_http_connection_entry *conn_ent,
struct rspamd_http_message *msg)
{
struct rspamd_controller_session *session = conn_ent->ud;
- struct rspamd_action *act, *tmp;
- ucl_object_t *obj, *top;
+ ucl_object_t *top;
if (!rspamd_controller_check_password(conn_ent, session, msg, FALSE)) {
return 0;
@@ -893,18 +906,7 @@ rspamd_controller_handle_actions(struct rspamd_http_connection_entry *conn_ent,
top = ucl_object_typed_new(UCL_ARRAY);
- HASH_ITER(hh, session->cfg->actions, act, tmp)
- {
- obj = ucl_object_typed_new(UCL_OBJECT);
- ucl_object_insert_key(obj,
- ucl_object_fromstring(act->name),
- "action", 0, false);
- ucl_object_insert_key(obj,
- ucl_object_fromdouble(act->threshold),
- "value", 0, false);
- ucl_array_append(top, obj);
- }
-
+ rspamd_config_actions_foreach(session->cfg, rspamd_controller_actions_cb, top);
rspamd_controller_send_ucl(conn_ent, top);
ucl_object_unref(top);
@@ -2086,7 +2088,6 @@ rspamd_controller_handle_learn_common(
task);
task->fin_arg = conn_ent;
task->http_conn = rspamd_http_connection_ref(conn_ent->conn);
- ;
task->sock = -1;
session->task = task;
@@ -2301,8 +2302,10 @@ rspamd_controller_handle_saveactions(
score = ucl_object_todouble(cur);
}
- if ((isnan(session->cfg->actions[act].threshold) != isnan(score)) ||
- (session->cfg->actions[act].threshold != score)) {
+ struct rspamd_action *cfg_action = rspamd_config_get_action_by_type(ctx->cfg, act);
+
+ if (cfg_action && ((isnan(cfg_action->threshold) != isnan(score)) ||
+ (cfg_action->threshold != score))) {
add_dynamic_action(ctx->cfg, DEFAULT_METRIC, act, score);
added++;
}
diff --git a/src/fuzzy_storage.c b/src/fuzzy_storage.c
index 0110ed8c2..21c5c271e 100644
--- a/src/fuzzy_storage.c
+++ b/src/fuzzy_storage.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -61,7 +61,7 @@ worker_t fuzzy_worker = {
"fuzzy", /* Name */
init_fuzzy, /* Init function */
start_fuzzy, /* Start function */
- RSPAMD_WORKER_HAS_SOCKET,
+ RSPAMD_WORKER_HAS_SOCKET | RSPAMD_WORKER_NO_STRICT_CONFIG,
RSPAMD_WORKER_SOCKET_UDP, /* UDP socket */
RSPAMD_WORKER_VER /* Version info */
};
diff --git a/src/libmime/lang_detection.c b/src/libmime/lang_detection.c
index 52221cd32..aa5447c8b 100644
--- a/src/libmime/lang_detection.c
+++ b/src/libmime/lang_detection.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2017 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -800,7 +800,7 @@ rspamd_language_detector_init(struct rspamd_config *cfg)
ucl_object_t *stop_words;
bool prefer_fasttext = true;
- section = ucl_object_lookup(cfg->rcl_obj, "lang_detection");
+ section = ucl_object_lookup(cfg->cfg_ucl_obj, "lang_detection");
if (section != NULL) {
elt = ucl_object_lookup(section, "languages");
diff --git a/src/libmime/lang_detection_fasttext.cxx b/src/libmime/lang_detection_fasttext.cxx
index f06e8ccb6..a1490fc11 100644
--- a/src/libmime/lang_detection_fasttext.cxx
+++ b/src/libmime/lang_detection_fasttext.cxx
@@ -1,11 +1,11 @@
-/*-
+/*
* 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
+ * 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,
@@ -45,7 +45,7 @@ private:
public:
explicit fasttext_langdet(struct rspamd_config *cfg)
{
- const auto *ucl_obj = cfg->rcl_obj;
+ const auto *ucl_obj = cfg->cfg_ucl_obj;
const auto *opts_section = ucl_object_find_key(ucl_obj, "lang_detection");
if (opts_section) {
diff --git a/src/libmime/scan_result.c b/src/libmime/scan_result.c
index a32c91280..080fc0d51 100644
--- a/src/libmime/scan_result.c
+++ b/src/libmime/scan_result.c
@@ -56,12 +56,25 @@ rspamd_scan_result_dtor(gpointer d)
kh_destroy(rspamd_symbols_group_hash, r->sym_groups);
}
+static void
+rspamd_metric_actions_foreach_cb(int i, struct rspamd_action *act, void *cbd)
+{
+ struct rspamd_scan_result *metric_res = (struct rspamd_scan_result *) cbd;
+ metric_res->actions_config[i].flags = RSPAMD_ACTION_RESULT_DEFAULT;
+ if (!(act->flags & RSPAMD_ACTION_NO_THRESHOLD)) {
+ metric_res->actions_config[i].cur_limit = act->threshold;
+ }
+ else {
+ metric_res->actions_config[i].flags |= RSPAMD_ACTION_RESULT_NO_THRESHOLD;
+ }
+ metric_res->actions_config[i].action = act;
+}
+
struct rspamd_scan_result *
rspamd_create_metric_result(struct rspamd_task *task,
const gchar *name, gint lua_sym_cbref)
{
struct rspamd_scan_result *metric_res;
- guint i;
metric_res = rspamd_mempool_alloc0(task->task_pool,
sizeof(struct rspamd_scan_result));
@@ -89,27 +102,11 @@ rspamd_create_metric_result(struct rspamd_task *task,
}
if (task->cfg) {
- struct rspamd_action *act, *tmp;
-
+ size_t nact = rspamd_config_actions_size(task->cfg);
metric_res->actions_config = rspamd_mempool_alloc0(task->task_pool,
- sizeof(struct rspamd_action_config) * HASH_COUNT(task->cfg->actions));
- i = 0;
-
- HASH_ITER(hh, task->cfg->actions, act, tmp)
- {
- metric_res->actions_config[i].flags = RSPAMD_ACTION_RESULT_DEFAULT;
- if (!(act->flags & RSPAMD_ACTION_NO_THRESHOLD)) {
- metric_res->actions_config[i].cur_limit = act->threshold;
- }
- else {
- metric_res->actions_config[i].flags |= RSPAMD_ACTION_RESULT_NO_THRESHOLD;
- }
- metric_res->actions_config[i].action = act;
-
- i++;
- }
-
- metric_res->nactions = i;
+ sizeof(struct rspamd_action_config) * nact);
+ rspamd_config_actions_foreach_enumerate(task->cfg, rspamd_metric_actions_foreach_cb, metric_res);
+ metric_res->nactions = nact;
}
rspamd_mempool_add_destructor(task->task_pool,
diff --git a/src/libserver/CMakeLists.txt b/src/libserver/CMakeLists.txt
index c4940f917..56cc2444d 100644
--- a/src/libserver/CMakeLists.txt
+++ b/src/libserver/CMakeLists.txt
@@ -1,49 +1,49 @@
# Librspamdserver
ADD_SUBDIRECTORY(css)
SET(LIBRSPAMDSERVERSRC
- ${CMAKE_CURRENT_SOURCE_DIR}/cfg_utils.c
- ${CMAKE_CURRENT_SOURCE_DIR}/cfg_rcl.c
- ${CMAKE_CURRENT_SOURCE_DIR}/composites/composites.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/composites/composites_manager.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/dkim.c
- ${CMAKE_CURRENT_SOURCE_DIR}/dns.c
- ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_cfg.c
- ${CMAKE_CURRENT_SOURCE_DIR}/async_session.c
- ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend.c
- ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend_sqlite.c
- ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend_redis.c
- ${CMAKE_CURRENT_SOURCE_DIR}/milter.c
- ${CMAKE_CURRENT_SOURCE_DIR}/monitored.c
- ${CMAKE_CURRENT_SOURCE_DIR}/protocol.c
- ${CMAKE_CURRENT_SOURCE_DIR}/re_cache.c
- ${CMAKE_CURRENT_SOURCE_DIR}/redis_pool.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/roll_history.c
- ${CMAKE_CURRENT_SOURCE_DIR}/spf.c
- ${CMAKE_CURRENT_SOURCE_DIR}/ssl_util.c
- ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_impl.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_item.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_runtime.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_c.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/task.c
- ${CMAKE_CURRENT_SOURCE_DIR}/url.c
- ${CMAKE_CURRENT_SOURCE_DIR}/worker_util.c
- ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger.c
- ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_file.c
- ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_syslog.c
- ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_console.c
- ${CMAKE_CURRENT_SOURCE_DIR}/http/http_util.c
- ${CMAKE_CURRENT_SOURCE_DIR}/http/http_message.c
- ${CMAKE_CURRENT_SOURCE_DIR}/http/http_connection.c
- ${CMAKE_CURRENT_SOURCE_DIR}/http/http_router.c
- ${CMAKE_CURRENT_SOURCE_DIR}/http/http_context.c
- ${CMAKE_CURRENT_SOURCE_DIR}/maps/map.c
- ${CMAKE_CURRENT_SOURCE_DIR}/maps/map_helpers.c
- ${CMAKE_CURRENT_SOURCE_DIR}/html/html_entities.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/html/html_url.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/html/html.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/html/html_tests.cxx
- ${CMAKE_CURRENT_SOURCE_DIR}/hyperscan_tools.cxx
- ${LIBCSSSRC})
+ ${CMAKE_CURRENT_SOURCE_DIR}/cfg_utils.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/cfg_rcl.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/composites/composites.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/composites/composites_manager.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/dkim.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dns.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dynamic_cfg.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/async_session.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend_sqlite.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/fuzzy_backend/fuzzy_backend_redis.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/milter.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/monitored.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/protocol.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/re_cache.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/redis_pool.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/roll_history.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/spf.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/ssl_util.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_impl.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_item.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_runtime.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/symcache/symcache_c.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/task.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/url.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/worker_util.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_file.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_syslog.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/logger/logger_console.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/http/http_util.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/http/http_message.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/http/http_connection.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/http/http_router.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/http/http_context.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/maps/map.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/maps/map_helpers.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/html/html_entities.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/html/html_url.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/html/html.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/html/html_tests.cxx
+ ${CMAKE_CURRENT_SOURCE_DIR}/hyperscan_tools.cxx
+ ${LIBCSSSRC})
# Librspamd-server
SET(RSPAMD_SERVER ${LIBRSPAMDSERVERSRC} PARENT_SCOPE)
diff --git a/src/libserver/cfg_file.h b/src/libserver/cfg_file.h
index 9b09608f2..3f876ab23 100644
--- a/src/libserver/cfg_file.h
+++ b/src/libserver/cfg_file.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016-2017 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -50,16 +50,6 @@ struct rspamd_cryptobox_pubkey;
struct rspamd_dns_resolver;
/**
- * Types of rspamd bind lines
- */
-enum rspamd_cred_type {
- CRED_NORMAL,
- CRED_CONTROL,
- CRED_LMTP,
- CRED_DELIVERY
-};
-
-/**
* Logging type
*/
enum rspamd_log_type {
@@ -94,17 +84,6 @@ struct script_module {
gchar *digest;
};
-/**
- * Type of lua variable
- */
-enum lua_var_type {
- LUA_VAR_NUM,
- LUA_VAR_BOOLEAN,
- LUA_VAR_STRING,
- LUA_VAR_FUNCTION,
- LUA_VAR_UNKNOWN
-};
-
enum rspamd_symbol_group_flags {
RSPAMD_SYMBOL_GROUP_NORMAL = 0u,
RSPAMD_SYMBOL_GROUP_DISABLED = (1u << 0u),
@@ -229,7 +208,7 @@ struct rspamd_worker_conf {
guint64 rlimit_maxcore; /**< maximum core file size */
GHashTable *params; /**< params for worker */
GQueue *active_workers; /**< linked list of spawned workers */
- gpointer *ctx; /**< worker's context */
+ gpointer ctx; /**< worker's context */
ucl_object_t *options; /**< other worker's options */
struct rspamd_worker_lua_script *scripts; /**< registered lua scripts */
gboolean enabled;
@@ -324,6 +303,7 @@ struct rspamd_config_post_init_script {
};
struct rspamd_lang_detector;
+struct rspamd_rcl_sections_map;
enum rspamd_config_settings_policy {
RSPAMD_SETTINGS_POLICY_DEFAULT = 0,
@@ -356,12 +336,12 @@ struct rspamd_config {
#ifdef WITH_GPERF_TOOLS
gchar *profile_path;
#endif
- gdouble unknown_weight; /**< weight of unknown symbols */
- gdouble grow_factor; /**< grow factor for metric */
- GHashTable *symbols; /**< weights of symbols in metric */
- const gchar *subject; /**< subject rewrite string */
- GHashTable *groups; /**< groups of symbols */
- struct rspamd_action *actions; /**< all actions of the metric */
+ gdouble unknown_weight; /**< weight of unknown symbols */
+ gdouble grow_factor; /**< grow factor for metric */
+ GHashTable *symbols; /**< weights of symbols in metric */
+ const gchar *subject; /**< subject rewrite string */
+ GHashTable *groups; /**< groups of symbols */
+ void *actions; /**< all actions of the metric (opaque type) */
gboolean one_shot_mode; /**< rules add only one symbol */
gboolean check_text_attachements; /**< check text attachements as text */
@@ -412,21 +392,21 @@ struct rspamd_config {
GList *script_modules; /**< linked list of script modules to load */
GHashTable *explicit_modules; /**< modules that should be always loaded */
- GList *filters; /**< linked list of all filters */
- GList *workers; /**< linked list of all workers params */
- GHashTable *wrk_parsers; /**< hash for worker config parsers, indexed by worker quarks */
- ucl_object_t *rcl_obj; /**< rcl object */
- ucl_object_t *config_comments; /**< comments saved from the config */
- ucl_object_t *doc_strings; /**< documentation strings for config options */
- GPtrArray *c_modules; /**< list of C modules */
- void *composites_manager; /**< hash of composite symbols indexed by its name */
- GList *classifiers; /**< list of all classifiers defined */
- GList *statfiles; /**< list of all statfiles in config file order */
- GHashTable *classifiers_symbols; /**< hashtable indexed by symbol name of classifiers */
- GHashTable *cfg_params; /**< all cfg params indexed by its name in this structure */
- gchar *dynamic_conf; /**< path to dynamic configuration */
- ucl_object_t *current_dynamic_conf; /**< currently loaded dynamic configuration */
- gint clock_res; /**< resolution of clock used */
+ GList *filters; /**< linked list of all filters */
+ GList *workers; /**< linked list of all workers params */
+ struct rspamd_rcl_sections_map *rcl_top_section; /**< top section for RCL config */
+ ucl_object_t *cfg_ucl_obj; /**< ucl object */
+ ucl_object_t *config_comments; /**< comments saved from the config */
+ ucl_object_t *doc_strings; /**< documentation strings for config options */
+ GPtrArray *c_modules; /**< list of C modules */
+ void *composites_manager; /**< hash of composite symbols indexed by its name */
+ GList *classifiers; /**< list of all classifiers defined */
+ GList *statfiles; /**< list of all statfiles in config file order */
+ GHashTable *classifiers_symbols; /**< hashtable indexed by symbol name of classifiers */
+ GHashTable *cfg_params; /**< all cfg params indexed by its name in this structure */
+ gchar *dynamic_conf; /**< path to dynamic configuration */
+ ucl_object_t *current_dynamic_conf; /**< currently loaded dynamic configuration */
+ gint clock_res; /**< resolution of clock used */
GList *maps; /**< maps active */
gdouble map_timeout; /**< maps watch timeout */
@@ -487,7 +467,7 @@ struct rspamd_config {
struct rspamd_external_libs_ctx *libs_ctx; /**< context for external libraries */
struct rspamd_monitored_ctx *monitored_ctx; /**< context for monitored resources */
- struct rspamd_redis_pool *redis_pool; /**< redis connection pool */
+ void *redis_pool; /**< redis connection pool */
struct rspamd_re_cache *re_cache; /**< static regexp cache */
@@ -730,7 +710,7 @@ gboolean rspamd_config_is_enabled_from_ucl(rspamd_mempool_t *pool,
/*
* Get action from a string
*/
-gboolean rspamd_action_from_str(const gchar *data, gint *result);
+gboolean rspamd_action_from_str(const gchar *data, enum rspamd_action_type *result);
/*
* Return textual representation of action enumeration
@@ -739,11 +719,6 @@ const gchar *rspamd_action_to_str(enum rspamd_action_type action);
const gchar *rspamd_action_to_str_alt(enum rspamd_action_type action);
-/*
- * Resort all actions (needed to operate with thresholds)
- */
-void rspamd_actions_sort(struct rspamd_config *cfg);
-
/**
* Parse radix tree or radix map from ucl object
* @param cfg configuration object
@@ -811,6 +786,32 @@ struct rspamd_action *rspamd_config_get_action(struct rspamd_config *cfg,
struct rspamd_action *rspamd_config_get_action_by_type(struct rspamd_config *cfg,
enum rspamd_action_type type);
+/**
+ * Iterate over all actions
+ * @param cfg
+ * @param func
+ * @param data
+ */
+void rspamd_config_actions_foreach(struct rspamd_config *cfg,
+ void (*func)(struct rspamd_action *act, void *d),
+ void *data);
+/**
+ * Iterate over all actions with index
+ * @param cfg
+ * @param func
+ * @param data
+ */
+void rspamd_config_actions_foreach_enumerate(struct rspamd_config *cfg,
+ void (*func)(int idx, struct rspamd_action *act, void *d),
+ void *data);
+
+/**
+ * Returns number of actions defined in the config
+ * @param cfg
+ * @return
+ */
+gsize rspamd_config_actions_size(struct rspamd_config *cfg);
+
int rspamd_config_ev_backend_get(struct rspamd_config *cfg);
const gchar *rspamd_config_ev_backend_to_string(int ev_backend, gboolean *effective);
@@ -855,9 +856,9 @@ gboolean rspamd_config_libs(struct rspamd_external_libs_ctx *ctx,
cfg->cfg_pool->tag.tagname, cfg->checksum, \
RSPAMD_LOG_FUNC, \
__VA_ARGS__)
-#define msg_err_config_forced(...) rspamd_default_log_function(G_LOG_LEVEL_CRITICAL | RSPAMD_LOG_FORCED, \
- cfg->cfg_pool->tag.tagname, cfg->checksum, \
- RSPAMD_LOG_FUNC, \
+#define msg_err_config_forced(...) rspamd_default_log_function((gint) G_LOG_LEVEL_CRITICAL | (gint) RSPAMD_LOG_FORCED, \
+ cfg->cfg_pool->tag.tagname, cfg->checksum, \
+ RSPAMD_LOG_FUNC, \
__VA_ARGS__)
#define msg_warn_config(...) rspamd_default_log_function(G_LOG_LEVEL_WARNING, \
cfg->cfg_pool->tag.tagname, cfg->checksum, \
diff --git a/src/libserver/cfg_file_private.h b/src/libserver/cfg_file_private.h
index d221e8427..8c9fc6539 100644
--- a/src/libserver/cfg_file_private.h
+++ b/src/libserver/cfg_file_private.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2019 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -18,9 +18,6 @@
#define RSPAMD_CFG_FILE_PRIVATE_H
#include "cfg_file.h"
-#include "../../contrib/mumhash/mum.h"
-#define HASH_CASELESS
-#include "uthash_strcase.h"
#ifdef __cplusplus
extern "C" {
@@ -31,12 +28,10 @@ extern "C" {
*/
struct rspamd_action {
enum rspamd_action_type action_type;
- enum rspamd_action_flags flags;
+ int flags; /* enum rspamd_action_flags */
guint priority;
- gint lua_handler_ref; /* If special handling is needed */
gdouble threshold;
gchar *name;
- struct UT_hash_handle hh; /* Index by name */
};
#ifdef __cplusplus
diff --git a/src/libserver/cfg_rcl.c b/src/libserver/cfg_rcl.cxx
index 8267a4bc8..134cdec98 100644
--- a/src/libserver/cfg_rcl.c
+++ b/src/libserver/cfg_rcl.cxx
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+#include "lua/lua_common.h"
#include "cfg_rcl.h"
#include "rspamd.h"
#include "cfg_file_private.h"
#include "utlist.h"
#include "cfg_file.h"
-#include "lua/lua_common.h"
#include "expression.h"
#include "src/libserver/composites/composites.h"
#include "libserver/worker_util.h"
@@ -28,59 +29,85 @@
#include "libmime/email_addr.h"
#include "libmime/lang_detection.h"
+#include <string>
+#include <filesystem>
+#include <memory>
+#include "contrib/ankerl/unordered_dense.h"
+#include "fmt/core.h"
+#include "libutil/cxx/util.hxx"
+#include "libutil/cxx/file_util.hxx"
+#include "frozen/unordered_set.h"
+#include "frozen/string.h"
+
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
-#include <math.h>
+#include <cmath>
struct rspamd_rcl_default_handler_data {
struct rspamd_rcl_struct_parser pd;
- gchar *key;
+ std::string key;
rspamd_rcl_default_handler_t handler;
- UT_hash_handle hh;
};
-struct rspamd_rcl_section {
- const gchar *name; /**< name of section */
- const gchar *key_attr;
- const gchar *default_key;
- rspamd_rcl_handler_t handler; /**< handler of section attributes */
- enum ucl_type type; /**< type of attribute */
- gboolean required; /**< whether this param is required */
- gboolean strict_type; /**< whether we need strict type */
- UT_hash_handle hh; /** hash handle */
- struct rspamd_rcl_section *subsections; /**< hash table of subsections */
- struct rspamd_rcl_default_handler_data *default_parser; /**< generic parsing fields */
- rspamd_rcl_section_fin_t fin; /** called at the end of section parsing */
- gpointer fin_ud;
- ucl_object_t *doc_ref; /**< reference to the section's documentation */
-};
+struct rspamd_rcl_sections_map;
-struct rspamd_worker_param_key {
- const gchar *name;
- gpointer ptr;
+struct rspamd_rcl_section {
+ struct rspamd_rcl_sections_map *top{};
+ std::string name; /**< name of section */
+ std::optional<std::string> key_attr;
+ std::optional<std::string> default_key;
+ rspamd_rcl_handler_t handler{}; /**< handler of section attributes */
+ enum ucl_type type; /**< type of attribute */
+ bool required{}; /**< whether this param is required */
+ bool strict_type{}; /**< whether we need strict type */
+ mutable bool processed{}; /**< whether this section was processed */
+ ankerl::unordered_dense::map<std::string, std::shared_ptr<struct rspamd_rcl_section>> subsections;
+ ankerl::unordered_dense::map<std::string, struct rspamd_rcl_default_handler_data> default_parser; /**< generic parsing fields */
+ rspamd_rcl_section_fin_t fin{}; /** called at the end of section parsing */
+ gpointer fin_ud{};
+ ucl_object_t *doc_ref{}; /**< reference to the section's documentation */
};
struct rspamd_worker_param_parser {
rspamd_rcl_default_handler_t handler; /**< handler function */
struct rspamd_rcl_struct_parser parser; /**< parser attributes */
-
- struct rspamd_worker_param_key key;
};
struct rspamd_worker_cfg_parser {
- GHashTable *parsers; /**< parsers hash */
+ struct pair_hash {
+ using is_avalanching = void;
+ template<class T1, class T2>
+ std::size_t operator()(const std::pair<T1, T2> &pair) const
+ {
+ return ankerl::unordered_dense::hash<T1>()(pair.first) ^ ankerl::unordered_dense::hash<T2>()(pair.second);
+ }
+ };
+ ankerl::unordered_dense::map<std::pair<std::string, gpointer>,
+ rspamd_worker_param_parser, pair_hash>
+ parsers; /**< parsers hash */
gint type; /**< workers quark */
- gboolean (*def_obj_parser)(ucl_object_t *obj, gpointer ud); /**<
- default object parser */
+ gboolean (*def_obj_parser)(ucl_object_t *obj, gpointer ud); /**< default object parser */
gpointer def_ud;
};
-static gboolean rspamd_rcl_process_section(struct rspamd_config *cfg,
- struct rspamd_rcl_section *sec,
- gpointer ptr, const ucl_object_t *obj, rspamd_mempool_t *pool,
- GError **err);
+struct rspamd_rcl_sections_map {
+ ankerl::unordered_dense::map<std::string, std::shared_ptr<struct rspamd_rcl_section>> sections;
+ std::vector<std::shared_ptr<struct rspamd_rcl_section>> sections_order;
+ ankerl::unordered_dense::map<int, struct rspamd_worker_cfg_parser> workers_parser;
+ ankerl::unordered_dense::set<std::string> lua_modules_seen;
+};
+
+static bool rspamd_rcl_process_section(struct rspamd_config *cfg,
+ const struct rspamd_rcl_section &sec,
+ gpointer ptr, const ucl_object_t *obj, rspamd_mempool_t *pool,
+ GError **err);
+static bool
+rspamd_rcl_section_parse_defaults(struct rspamd_config *cfg,
+ const struct rspamd_rcl_section &section,
+ rspamd_mempool_t *pool, const ucl_object_t *obj, gpointer ptr,
+ GError **err);
/*
* Common section handlers
@@ -91,15 +118,15 @@ rspamd_rcl_logging_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
GError **err)
{
const ucl_object_t *val;
- const gchar *facility = NULL, *log_type = NULL, *log_level = NULL;
- struct rspamd_config *cfg = ud;
+ const gchar *facility = nullptr, *log_type = nullptr, *log_level = nullptr;
+ auto *cfg = (struct rspamd_config *) ud;
val = ucl_object_lookup(obj, "type");
- if (val != NULL && ucl_object_tostring_safe(val, &log_type)) {
+ if (val != nullptr && ucl_object_tostring_safe(val, &log_type)) {
if (g_ascii_strcasecmp(log_type, "file") == 0) {
/* Need to get filename */
val = ucl_object_lookup(obj, "filename");
- if (val == NULL || val->type != UCL_STRING) {
+ if (val == nullptr || val->type != UCL_STRING) {
g_set_error(err,
CFG_RCL_ERROR,
ENOENT,
@@ -116,7 +143,7 @@ rspamd_rcl_logging_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
cfg->log_facility = LOG_DAEMON;
cfg->log_type = RSPAMD_LOG_SYSLOG;
val = ucl_object_lookup(obj, "facility");
- if (val != NULL && ucl_object_tostring_safe(val, &facility)) {
+ if (val != nullptr && ucl_object_tostring_safe(val, &facility)) {
if (g_ascii_strcasecmp(facility, "LOG_AUTH") == 0 ||
g_ascii_strcasecmp(facility, "auth") == 0) {
cfg->log_facility = LOG_AUTH;
@@ -202,7 +229,7 @@ rspamd_rcl_logging_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
/* Handle log level */
val = ucl_object_lookup(obj, "level");
- if (val != NULL && ucl_object_tostring_safe(val, &log_level)) {
+ if (val != nullptr && ucl_object_tostring_safe(val, &log_level)) {
if (g_ascii_strcasecmp(log_level, "error") == 0) {
cfg->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
}
@@ -234,17 +261,17 @@ rspamd_rcl_logging_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
/* Handle flags */
- val = ucl_object_lookup_any(obj, "color", "log_color", NULL);
+ val = ucl_object_lookup_any(obj, "color", "log_color", nullptr);
if (val && ucl_object_toboolean(val)) {
cfg->log_flags |= RSPAMD_LOG_FLAG_COLOR;
}
- val = ucl_object_lookup_any(obj, "severity", "log_severity", NULL);
+ val = ucl_object_lookup_any(obj, "severity", "log_severity", nullptr);
if (val && ucl_object_toboolean(val)) {
cfg->log_flags |= RSPAMD_LOG_FLAG_SEVERITY;
}
- val = ucl_object_lookup_any(obj, "systemd", "log_systemd", NULL);
+ val = ucl_object_lookup_any(obj, "systemd", "log_systemd", nullptr);
if (val && ucl_object_toboolean(val)) {
cfg->log_flags |= RSPAMD_LOG_FLAG_SYSTEMD;
}
@@ -254,13 +281,13 @@ rspamd_rcl_logging_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
cfg->log_flags |= RSPAMD_LOG_FLAG_RE_CACHE;
}
- val = ucl_object_lookup_any(obj, "usec", "log_usec", NULL);
+ val = ucl_object_lookup_any(obj, "usec", "log_usec", nullptr);
if (val && ucl_object_toboolean(val)) {
cfg->log_flags |= RSPAMD_LOG_FLAG_USEC;
}
- return rspamd_rcl_section_parse_defaults(cfg, section, cfg->cfg_pool, obj,
- cfg, err);
+ return rspamd_rcl_section_parse_defaults(cfg, *section, cfg->cfg_pool, obj,
+ (void *) cfg, err);
}
static gboolean
@@ -269,40 +296,39 @@ rspamd_rcl_options_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
struct rspamd_rcl_section *section, GError **err)
{
const ucl_object_t *dns, *upstream, *neighbours;
- struct rspamd_config *cfg = ud;
- struct rspamd_rcl_section *dns_section, *upstream_section, *neighbours_section;
+ auto *cfg = (struct rspamd_config *) ud;
- HASH_FIND_STR(section->subsections, "dns", dns_section);
+ auto maybe_subsection = rspamd::find_map(section->subsections, "dns");
dns = ucl_object_lookup(obj, "dns");
- if (dns_section != NULL && dns != NULL) {
+ if (maybe_subsection && dns != nullptr) {
if (!rspamd_rcl_section_parse_defaults(cfg,
- dns_section, cfg->cfg_pool, dns,
+ *maybe_subsection.value().get(), cfg->cfg_pool, dns,
cfg, err)) {
return FALSE;
}
}
- HASH_FIND_STR(section->subsections, "upstream", upstream_section);
+ maybe_subsection = rspamd::find_map(section->subsections, "upstream");
- upstream = ucl_object_lookup_any(obj, "upstream", "upstreams", NULL);
- if (upstream_section != NULL && upstream != NULL) {
+ upstream = ucl_object_lookup_any(obj, "upstream", "upstreams", nullptr);
+ if (maybe_subsection && upstream != nullptr) {
if (!rspamd_rcl_section_parse_defaults(cfg,
- upstream_section, cfg->cfg_pool,
+ *maybe_subsection.value().get(), cfg->cfg_pool,
upstream, cfg, err)) {
return FALSE;
}
}
- HASH_FIND_STR(section->subsections, "neighbours", neighbours_section);
+ maybe_subsection = rspamd::find_map(section->subsections, "neighbours");
neighbours = ucl_object_lookup(obj, "neighbours");
- if (neighbours_section != NULL && neighbours != NULL) {
+ if (maybe_subsection && neighbours != nullptr) {
const ucl_object_t *cur;
LL_FOREACH(neighbours, cur)
{
- if (!rspamd_rcl_process_section(cfg, neighbours_section, cfg, cur,
+ if (!rspamd_rcl_process_section(cfg, *maybe_subsection.value().get(), cfg, cur,
pool, err)) {
return FALSE;
}
@@ -310,7 +336,7 @@ rspamd_rcl_options_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
if (rspamd_rcl_section_parse_defaults(cfg,
- section, cfg->cfg_pool, obj,
+ *section, cfg->cfg_pool, obj,
cfg, err)) {
/* We need to init this early */
rspamd_multipattern_library_init(cfg->hs_cache_dir);
@@ -331,27 +357,23 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- struct rspamd_config *cfg = ud;
- struct rspamd_symbols_group *gr;
- const ucl_object_t *val, *elt;
- struct rspamd_rcl_section *subsection;
- struct rspamd_rcl_symbol_data sd;
- const gchar *description = NULL;
+ auto *cfg = static_cast<rspamd_config *>(ud);
+ const gchar *description = nullptr;
- g_assert(key != NULL);
+ g_assert(key != nullptr);
- gr = g_hash_table_lookup(cfg->groups, key);
+ auto *gr = static_cast<rspamd_symbols_group *>(g_hash_table_lookup(cfg->groups, key));
- if (gr == NULL) {
+ if (gr == nullptr) {
gr = rspamd_config_new_group(cfg, key);
}
- if (!rspamd_rcl_section_parse_defaults(cfg, section, pool, obj,
+ if (!rspamd_rcl_section_parse_defaults(cfg, *section, pool, obj,
gr, err)) {
return FALSE;
}
- if ((elt = ucl_object_lookup(obj, "one_shot")) != NULL) {
+ if (const auto *elt = ucl_object_lookup(obj, "one_shot"); elt != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -366,7 +388,7 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "disabled")) != NULL) {
+ if (const auto *elt = ucl_object_lookup(obj, "disabled"); elt != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -381,7 +403,7 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "enabled")) != NULL) {
+ if (const auto *elt = ucl_object_lookup(obj, "enabled"); elt != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -396,7 +418,7 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "public")) != NULL) {
+ if (const auto *elt = ucl_object_lookup(obj, "public"); elt != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -411,7 +433,7 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "private")) != NULL) {
+ if (const auto *elt = ucl_object_lookup(obj, "private"); elt != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -426,23 +448,25 @@ rspamd_rcl_group_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- elt = ucl_object_lookup(obj, "description");
- if (elt) {
+
+ if (const auto *elt = ucl_object_lookup(obj, "description"); elt != nullptr) {
description = ucl_object_tostring(elt);
gr->description = rspamd_mempool_strdup(cfg->cfg_pool,
description);
}
- sd.gr = gr;
- sd.cfg = cfg;
+ struct rspamd_rcl_symbol_data sd = {
+ .gr = gr,
+ .cfg = cfg,
+ };
/* Handle symbols */
- val = ucl_object_lookup(obj, "symbols");
- if (val != NULL && ucl_object_type(val) == UCL_OBJECT) {
- HASH_FIND_STR(section->subsections, "symbols", subsection);
- g_assert(subsection != NULL);
- if (!rspamd_rcl_process_section(cfg, subsection, &sd, val,
+ if (const auto *val = ucl_object_lookup(obj, "symbols"); val != nullptr && ucl_object_type(val) == UCL_OBJECT) {
+ auto subsection = rspamd::find_map(section->subsections, "symbols");
+
+ g_assert(subsection.has_value());
+ if (!rspamd_rcl_process_section(cfg, *subsection.value().get(), &sd, val,
pool, err)) {
return FALSE;
@@ -457,18 +481,18 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- struct rspamd_rcl_symbol_data *sd = ud;
+ auto *sd = static_cast<rspamd_rcl_symbol_data *>(ud);
struct rspamd_config *cfg;
const ucl_object_t *elt;
- const gchar *description = NULL;
+ const gchar *description = nullptr;
gdouble score = NAN;
guint priority = 1, flags = 0;
gint nshots = 0;
- g_assert(key != NULL);
+ g_assert(key != nullptr);
cfg = sd->cfg;
- if ((elt = ucl_object_lookup(obj, "one_shot")) != NULL) {
+ if ((elt = ucl_object_lookup(obj, "one_shot")) != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -483,7 +507,7 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "any_shot")) != NULL) {
+ if ((elt = ucl_object_lookup(obj, "any_shot")) != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -498,7 +522,7 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "one_param")) != NULL) {
+ if ((elt = ucl_object_lookup(obj, "one_param")) != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -514,7 +538,7 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "ignore")) != NULL) {
+ if ((elt = ucl_object_lookup(obj, "ignore")) != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -530,7 +554,7 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "enabled")) != NULL) {
+ if ((elt = ucl_object_lookup(obj, "enabled")) != nullptr) {
if (ucl_object_type(elt) != UCL_BOOLEAN) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -546,7 +570,7 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
}
- if ((elt = ucl_object_lookup(obj, "nshots")) != NULL) {
+ if ((elt = ucl_object_lookup(obj, "nshots")) != nullptr) {
if (ucl_object_type(elt) != UCL_FLOAT && ucl_object_type(elt) != UCL_INT) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -560,7 +584,7 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
nshots = ucl_object_toint(elt);
}
- elt = ucl_object_lookup_any(obj, "score", "weight", NULL);
+ elt = ucl_object_lookup_any(obj, "score", "weight", nullptr);
if (elt) {
if (ucl_object_type(elt) != UCL_FLOAT && ucl_object_type(elt) != UCL_INT) {
g_set_error(err,
@@ -604,7 +628,7 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
else {
rspamd_config_add_symbol(cfg, key, score,
- description, NULL, flags, priority, nshots);
+ description, nullptr, flags, priority, nshots);
}
elt = ucl_object_lookup(obj, "groups");
@@ -615,7 +639,7 @@ rspamd_rcl_symbol_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
gr_it = ucl_object_iterate_new(elt);
- while ((cur_gr = ucl_object_iterate_safe(gr_it, true)) != NULL) {
+ while ((cur_gr = ucl_object_iterate_safe(gr_it, true)) != nullptr) {
rspamd_config_add_symbol_group(cfg, key,
ucl_object_tostring(cur_gr));
}
@@ -631,13 +655,13 @@ rspamd_rcl_actions_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- struct rspamd_config *cfg = ud;
+ auto *cfg = static_cast<rspamd_config *>(ud);
const ucl_object_t *cur;
ucl_object_iter_t it;
it = ucl_object_iterate_new(obj);
- while ((cur = ucl_object_iterate_safe(it, true)) != NULL) {
+ while ((cur = ucl_object_iterate_safe(it, true)) != nullptr) {
gint type = ucl_object_type(cur);
if (type == UCL_NULL) {
@@ -646,13 +670,12 @@ rspamd_rcl_actions_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
else if (type == UCL_OBJECT || type == UCL_FLOAT || type == UCL_INT) {
/* Exceptions */
- struct rspamd_rcl_default_handler_data *sec_cur, *sec_tmp;
- gboolean default_elt = FALSE;
+ auto default_elt = false;
- HASH_ITER(hh, section->default_parser, sec_cur, sec_tmp)
- {
- if (strcmp(ucl_object_key(cur), sec_cur->key) == 0) {
- default_elt = TRUE;
+ for (const auto &[name, def_elt]: section->default_parser) {
+ if (def_elt.key == ucl_object_key(cur)) {
+ default_elt = true;
+ break;
}
}
@@ -678,60 +701,60 @@ rspamd_rcl_actions_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
ucl_object_iterate_free(it);
- return rspamd_rcl_section_parse_defaults(cfg, section, pool, obj, cfg, err);
+ return rspamd_rcl_section_parse_defaults(cfg, *section, pool, obj, cfg, err);
}
-
+constexpr const auto known_worker_attributes = frozen::make_unordered_set<frozen::string>({
+ "bind_socket",
+ "listen",
+ "bind",
+ "count",
+ "max_files",
+ "max_core",
+ "enabled",
+});
static gboolean
rspamd_rcl_worker_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- const ucl_object_t *val, *cur, *cur_obj;
- ucl_object_t *robj;
- ucl_object_iter_t it = NULL;
- const gchar *worker_type, *worker_bind;
- struct rspamd_config *cfg = ud;
- GQuark qtype;
- struct rspamd_worker_conf *wrk;
- struct rspamd_worker_cfg_parser *wparser;
- struct rspamd_worker_param_parser *whandler;
- struct rspamd_worker_param_key srch;
-
- g_assert(key != NULL);
- worker_type = key;
-
- qtype = g_quark_try_string(worker_type);
- if (qtype != 0) {
- wrk = rspamd_config_new_worker(cfg, NULL);
- wrk->options = ucl_object_copy(obj);
- wrk->worker = rspamd_get_worker_by_type(cfg, qtype);
-
- if (wrk->worker == NULL) {
- g_set_error(err,
- CFG_RCL_ERROR,
- EINVAL,
- "unknown worker type: %s",
- worker_type);
- return FALSE;
- }
+ auto *cfg = static_cast<rspamd_config *>(ud);
- wrk->type = qtype;
+ g_assert(key != nullptr);
+ const auto *worker_type = key;
- if (wrk->worker->worker_init_func) {
- wrk->ctx = wrk->worker->worker_init_func(cfg);
- }
- }
- else {
+ auto qtype = g_quark_try_string(worker_type);
+ if (qtype == 0) {
msg_err_config("unknown worker type: %s", worker_type);
- return TRUE;
+ return FALSE;
}
- val = ucl_object_lookup_any(obj, "bind_socket", "listen", "bind", NULL);
+ auto *wrk = rspamd_config_new_worker(cfg, nullptr);
+ wrk->options = ucl_object_copy(obj);
+ wrk->worker = rspamd_get_worker_by_type(cfg, qtype);
+
+ if (wrk->worker == nullptr) {
+ g_set_error(err,
+ CFG_RCL_ERROR,
+ EINVAL,
+ "unknown worker type: %s",
+ worker_type);
+ return FALSE;
+ }
+
+ wrk->type = qtype;
+
+ if (wrk->worker->worker_init_func) {
+ wrk->ctx = wrk->worker->worker_init_func(cfg);
+ }
+
+ const auto *val = ucl_object_lookup_any(obj, "bind_socket", "listen", "bind", nullptr);
/* This name is more logical */
- if (val != NULL) {
- it = ucl_object_iterate_new(val);
+ if (val != nullptr) {
+ auto it = ucl_object_iterate_new(val);
+ const ucl_object_t *cur;
+ const char *worker_bind = nullptr;
- while ((cur = ucl_object_iterate_safe(it, true)) != NULL) {
+ while ((cur = ucl_object_iterate_safe(it, true)) != nullptr) {
if (!ucl_object_tostring_safe(cur, &worker_bind)) {
continue;
}
@@ -749,49 +772,56 @@ rspamd_rcl_worker_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
ucl_object_iterate_free(it);
}
- if (!rspamd_rcl_section_parse_defaults(cfg, section, cfg->cfg_pool, obj,
+ if (!rspamd_rcl_section_parse_defaults(cfg, *section, cfg->cfg_pool, obj,
wrk, err)) {
return FALSE;
}
/* Parse other attributes */
- wparser = g_hash_table_lookup(cfg->wrk_parsers, &qtype);
+ auto maybe_wparser = rspamd::find_map(section->top->workers_parser, wrk->type);
- if (wparser != NULL && obj->type == UCL_OBJECT) {
- it = ucl_object_iterate_new(obj);
+ if (maybe_wparser && obj->type == UCL_OBJECT) {
+ auto &wparser = maybe_wparser.value().get();
+ auto it = ucl_object_iterate_new(obj);
+ const ucl_object_t *cur;
- while ((cur = ucl_object_iterate_full(it, UCL_ITERATE_EXPLICIT)) != NULL) {
- srch.name = ucl_object_key(cur);
- srch.ptr = wrk->ctx; /* XXX: is it valid? Update! no, it is not valid, omfg... */
- whandler = g_hash_table_lookup(wparser->parsers, &srch);
+ while ((cur = ucl_object_iterate_full(it, UCL_ITERATE_EXPLICIT)) != nullptr) {
+ auto srch = std::make_pair(ucl_object_key(cur), (gpointer) wrk->ctx);
+ auto maybe_specific = rspamd::find_map(wparser.parsers, srch);
- if (whandler != NULL) {
+ if (maybe_specific) {
+ auto &whandler = maybe_specific.value().get();
+ const ucl_object_t *cur_obj;
LL_FOREACH(cur, cur_obj)
{
- if (!whandler->handler(cfg->cfg_pool,
- cur_obj,
- &whandler->parser,
- section,
- err)) {
+ if (!whandler.handler(cfg->cfg_pool,
+ cur_obj,
+ (void *) &whandler.parser,
+ section,
+ err)) {
ucl_object_iterate_free(it);
return FALSE;
}
- if (!(whandler->parser.flags & RSPAMD_CL_FLAG_MULTIPLE)) {
+ if (!(whandler.parser.flags & RSPAMD_CL_FLAG_MULTIPLE)) {
break;
}
}
}
+ else if (!(wrk->worker->flags & RSPAMD_WORKER_NO_STRICT_CONFIG) &&
+ known_worker_attributes.find(std::string_view{ucl_object_key(cur)}) == known_worker_attributes.end()) {
+ msg_warn_config("unknown worker attribute: %s; worker type: %s", ucl_object_key(cur), worker_type);
+ }
}
ucl_object_iterate_free(it);
- if (wparser->def_obj_parser != NULL) {
- robj = ucl_object_ref(obj);
+ if (wparser.def_obj_parser != nullptr) {
+ auto *robj = ucl_object_ref(obj);
- if (!wparser->def_obj_parser(robj, wparser->def_ud)) {
+ if (!wparser.def_obj_parser(robj, wparser.def_ud)) {
ucl_object_unref(robj);
return FALSE;
@@ -811,38 +841,35 @@ rspamd_rcl_lua_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- struct rspamd_config *cfg = ud;
- const gchar *lua_src = rspamd_mempool_strdup(pool,
- ucl_object_tostring(obj));
- gchar *cur_dir, *lua_dir, *lua_file;
- lua_State *L = cfg->lua_state;
- gint err_idx;
-
- lua_dir = g_path_get_dirname(lua_src);
- lua_file = g_path_get_basename(lua_src);
-
- if (lua_dir && lua_file) {
- cur_dir = g_malloc(PATH_MAX);
- if (getcwd(cur_dir, PATH_MAX) != NULL && chdir(lua_dir) != -1) {
+ namespace fs = std::filesystem;
+ auto *cfg = static_cast<rspamd_config *>(ud);
+ auto lua_src = fs::path{ucl_object_tostring(obj)};
+ auto *L = RSPAMD_LUA_CFG_STATE(cfg);
+ std::error_code ec1;
+
+ auto lua_dir = fs::weakly_canonical(lua_src.parent_path(), ec1);
+ auto lua_file = lua_src.filename();
+
+ if (!ec1 && !lua_dir.empty() && !lua_file.empty()) {
+ auto cur_dir = fs::current_path(ec1);
+ if (!ec1 && !cur_dir.empty() && ::chdir(lua_dir.c_str()) != -1) {
/* Push traceback function */
lua_pushcfunction(L, &rspamd_lua_traceback);
- err_idx = lua_gettop(L);
+ auto err_idx = lua_gettop(L);
/* Load file */
- if (luaL_loadfile(L, lua_file) != 0) {
+ if (luaL_loadfile(L, lua_file.c_str()) != 0) {
g_set_error(err,
CFG_RCL_ERROR,
EINVAL,
"cannot load lua file %s: %s",
- lua_src,
+ lua_src.c_str(),
lua_tostring(L, -1));
- if (chdir(cur_dir) == -1) {
- msg_err_config("cannot chdir to %s: %s", cur_dir,
+ if (::chdir(cur_dir.c_str()) == -1) {
+ msg_err_config("cannot chdir to %s: %s", cur_dir.c_str(),
strerror(errno));
}
- g_free(cur_dir);
- g_free(lua_dir);
- g_free(lua_file);
+
return FALSE;
}
@@ -852,19 +879,15 @@ rspamd_rcl_lua_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
CFG_RCL_ERROR,
EINVAL,
"cannot init lua file %s: %s",
- lua_src,
+ lua_src.c_str(),
lua_tostring(L, -1));
lua_settop(L, 0);
- if (chdir(cur_dir) == -1) {
- msg_err_config("cannot chdir to %s: %s", cur_dir,
+ if (::chdir(cur_dir.c_str()) == -1) {
+ msg_err_config("cannot chdir to %s: %s", cur_dir.c_str(),
strerror(errno));
}
- g_free(cur_dir);
- g_free(lua_file);
- g_free(lua_dir);
-
return FALSE;
}
@@ -872,27 +895,21 @@ rspamd_rcl_lua_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
else {
g_set_error(err, CFG_RCL_ERROR, ENOENT, "cannot chdir to %s: %s",
- lua_dir, strerror(errno));
- if (chdir(cur_dir) == -1) {
- msg_err_config("cannot chdir to %s: %s", cur_dir, strerror(errno));
+ lua_dir.c_str(), strerror(errno));
+ if (::chdir(cur_dir.c_str()) == -1) {
+ msg_err_config("cannot chdir back to %s: %s", cur_dir.c_str(), strerror(errno));
}
- g_free(cur_dir);
- g_free(lua_dir);
- g_free(lua_file);
+
return FALSE;
}
- if (chdir(cur_dir) == -1) {
- msg_err_config("cannot chdir to %s: %s", cur_dir, strerror(errno));
+ if (::chdir(cur_dir.c_str()) == -1) {
+ msg_err_config("cannot chdir back to %s: %s", cur_dir.c_str(), strerror(errno));
}
- g_free(cur_dir);
- g_free(lua_dir);
- g_free(lua_file);
}
else {
- g_free(lua_dir);
- g_free(lua_file);
+
g_set_error(err, CFG_RCL_ERROR, ENOENT, "cannot find to %s: %s",
- lua_src, strerror(errno));
+ lua_src.c_str(), strerror(errno));
return FALSE;
}
@@ -900,114 +917,35 @@ rspamd_rcl_lua_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
}
gboolean
-rspamd_rcl_add_lua_plugins_path(struct rspamd_config *cfg,
+rspamd_rcl_add_lua_plugins_path(struct rspamd_rcl_sections_map *sections,
+ struct rspamd_config *cfg,
const gchar *path,
gboolean main_path,
- GHashTable *modules_seen,
GError **err)
{
- struct stat st;
- struct script_module *cur_mod, *seen_mod;
- GPtrArray *paths;
- gchar *fname, *ext_pos;
- guint i;
+ namespace fs = std::filesystem;
+ auto dir = fs::path{path};
+ std::error_code ec;
- if (stat(path, &st) == -1) {
+ auto add_single_file = [&](const fs::path &fpath) -> bool {
+ auto fname = fpath.filename();
+ auto modname = fname.string();
- if (errno != ENOENT || main_path) {
- g_set_error(err,
- CFG_RCL_ERROR,
- errno,
- "cannot stat path %s, %s",
- path,
- strerror(errno));
- return FALSE;
+ if (fname.has_extension()) {
+ modname = modname.substr(0, modname.size() - fname.extension().native().size());
}
- else {
- msg_debug_config("optional plugins path %s is absent, skip it", path);
+ auto *cur_mod = rspamd_mempool_alloc_type(cfg->cfg_pool,
+ struct script_module);
+ cur_mod->path = rspamd_mempool_strdup(cfg->cfg_pool, fpath.c_str());
+ cur_mod->name = rspamd_mempool_strdup(cfg->cfg_pool, modname.c_str());
- return TRUE;
+ if (sections->lua_modules_seen.contains(modname)) {
+ msg_info_config("already seen module %s, skip %s",
+ cur_mod->name, cur_mod->path);
+ return false;
}
- }
-
- /* Handle directory */
- if (S_ISDIR(st.st_mode)) {
- paths = rspamd_glob_path(path, "*.lua", TRUE, err);
- if (!paths) {
- return FALSE;
- }
-
- PTR_ARRAY_FOREACH(paths, i, fname)
- {
- cur_mod =
- rspamd_mempool_alloc(cfg->cfg_pool,
- sizeof(struct script_module));
- cur_mod->path = rspamd_mempool_strdup(cfg->cfg_pool, fname);
- cur_mod->name = g_path_get_basename(cur_mod->path);
- rspamd_mempool_add_destructor(cfg->cfg_pool, g_free,
- cur_mod->name);
- ext_pos = strstr(cur_mod->name, ".lua");
-
- if (ext_pos != NULL) {
- *ext_pos = '\0';
- }
-
- if (modules_seen) {
- seen_mod = g_hash_table_lookup(modules_seen, cur_mod->name);
-
- if (seen_mod != NULL) {
- msg_info_config("already seen module %s at %s, skip %s",
- cur_mod->name, seen_mod->path, cur_mod->path);
- continue;
- }
- }
-
- if (cfg->script_modules == NULL) {
- cfg->script_modules = g_list_append(cfg->script_modules,
- cur_mod);
- rspamd_mempool_add_destructor(cfg->cfg_pool,
- (rspamd_mempool_destruct_t) g_list_free,
- cfg->script_modules);
- }
- else {
- cfg->script_modules = g_list_append(cfg->script_modules,
- cur_mod);
- }
-
- if (modules_seen) {
- g_hash_table_insert(modules_seen, cur_mod->name, cur_mod);
- }
- }
-
- g_ptr_array_free(paths, TRUE);
- }
- else {
- /* Handle single file */
- cur_mod =
- rspamd_mempool_alloc(cfg->cfg_pool, sizeof(struct script_module));
- cur_mod->path = rspamd_mempool_strdup(cfg->cfg_pool, path);
- cur_mod->name = g_path_get_basename(cur_mod->path);
- rspamd_mempool_add_destructor(cfg->cfg_pool, g_free,
- cur_mod->name);
- ext_pos = strstr(cur_mod->name, ".lua");
-
- if (ext_pos != NULL) {
- *ext_pos = '\0';
- }
-
- if (modules_seen) {
- seen_mod = g_hash_table_lookup(modules_seen, cur_mod->name);
-
- if (seen_mod != NULL) {
- msg_info_config("already seen module %s at %s, skip %s",
- cur_mod->name, seen_mod->path, cur_mod->path);
-
- return TRUE;
- }
- }
-
- if (cfg->script_modules == NULL) {
+ if (cfg->script_modules == nullptr) {
cfg->script_modules = g_list_append(cfg->script_modules,
cur_mod);
rspamd_mempool_add_destructor(cfg->cfg_pool,
@@ -1019,8 +957,36 @@ rspamd_rcl_add_lua_plugins_path(struct rspamd_config *cfg,
cur_mod);
}
- if (modules_seen) {
- g_hash_table_insert(modules_seen, cur_mod->name, cur_mod);
+ sections->lua_modules_seen.insert(fname.string());
+
+ return true;
+ };
+
+ if (fs::is_regular_file(dir, ec) && dir.has_extension() && dir.extension() == ".lua") {
+ add_single_file(dir);
+ }
+ else if (!fs::is_directory(dir, ec)) {
+ if (!fs::exists(dir) && !main_path) {
+ msg_debug_config("optional plugins path %s is absent, skip it", path);
+
+ return TRUE;
+ }
+
+ g_set_error(err,
+ CFG_RCL_ERROR,
+ errno,
+ "invalid lua path spec %s, %s",
+ path,
+ ec.message().c_str());
+ return FALSE;
+ }
+ else {
+ /* Handle directory */
+ for (const auto &p: fs::recursive_directory_iterator(dir, ec)) {
+ auto fpath = p.path().string();
+ if (p.is_regular_file() && fpath.ends_with(".lua")) {
+ add_single_file(p.path());
+ }
}
}
@@ -1032,26 +998,22 @@ rspamd_rcl_modules_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- const ucl_object_t *val, *cur;
- struct rspamd_config *cfg = ud;
- const gchar *data;
+ auto *cfg = static_cast<rspamd_config *>(ud);
+ const char *data;
if (obj->type == UCL_OBJECT) {
- GHashTable *mods_seen = g_hash_table_new(rspamd_strcase_hash,
- rspamd_strcase_equal);
- val = ucl_object_lookup(obj, "path");
+ const auto *val = ucl_object_lookup(obj, "path");
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_tostring_safe(cur, &data)) {
- if (!rspamd_rcl_add_lua_plugins_path(cfg,
- rspamd_mempool_strdup(cfg->cfg_pool, data),
+ if (!rspamd_rcl_add_lua_plugins_path(section->top,
+ cfg,
+ data,
TRUE,
- mods_seen,
err)) {
- g_hash_table_unref(mods_seen);
-
return FALSE;
}
}
@@ -1062,7 +1024,6 @@ rspamd_rcl_modules_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
CFG_RCL_ERROR,
EINVAL,
"path attribute is missing");
- g_hash_table_unref(mods_seen);
return FALSE;
}
@@ -1070,15 +1031,15 @@ rspamd_rcl_modules_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
val = ucl_object_lookup(obj, "fallback_path");
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_tostring_safe(cur, &data)) {
- if (!rspamd_rcl_add_lua_plugins_path(cfg,
- rspamd_mempool_strdup(cfg->cfg_pool, data),
+ if (!rspamd_rcl_add_lua_plugins_path(section->top,
+ cfg,
+ data,
FALSE,
- mods_seen,
err)) {
- g_hash_table_unref(mods_seen);
return FALSE;
}
@@ -1089,27 +1050,24 @@ rspamd_rcl_modules_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
val = ucl_object_lookup(obj, "try_path");
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_tostring_safe(cur, &data)) {
- if (!rspamd_rcl_add_lua_plugins_path(cfg,
- rspamd_mempool_strdup(cfg->cfg_pool, data),
+ if (!rspamd_rcl_add_lua_plugins_path(section->top,
+ cfg,
+ data,
FALSE,
- mods_seen,
err)) {
- g_hash_table_unref(mods_seen);
return FALSE;
}
}
}
}
-
- g_hash_table_unref(mods_seen);
}
else if (ucl_object_tostring_safe(obj, &data)) {
- if (!rspamd_rcl_add_lua_plugins_path(cfg,
- rspamd_mempool_strdup(cfg->cfg_pool, data), TRUE, NULL, err)) {
+ if (!rspamd_rcl_add_lua_plugins_path(section->top, cfg, data, TRUE, err)) {
return FALSE;
}
}
@@ -1134,36 +1092,33 @@ rspamd_rcl_statfile_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
const gchar *key, gpointer ud,
struct rspamd_rcl_section *section, GError **err)
{
- struct statfile_parser_data *stud = ud;
- struct rspamd_classifier_config *ccf;
- struct rspamd_config *cfg;
- const ucl_object_t *val;
- struct rspamd_statfile_config *st;
+ auto *stud = (struct statfile_parser_data *) ud;
GList *labels;
- g_assert(key != NULL);
+ g_assert(key != nullptr);
- cfg = stud->cfg;
- ccf = stud->ccf;
+ auto *cfg = stud->cfg;
+ auto *ccf = stud->ccf;
- st = rspamd_config_new_statfile(cfg, NULL);
+ auto *st = rspamd_config_new_statfile(cfg, nullptr);
st->symbol = rspamd_mempool_strdup(cfg->cfg_pool, key);
- if (rspamd_rcl_section_parse_defaults(cfg, section, pool, obj, st, err)) {
+ if (rspamd_rcl_section_parse_defaults(cfg, *section, pool, obj, st, err)) {
ccf->statfiles = rspamd_mempool_glist_prepend(pool, ccf->statfiles, st);
- if (st->label != NULL) {
- labels = g_hash_table_lookup(ccf->labels, st->label);
- if (labels != NULL) {
+ if (st->label != nullptr) {
+ labels = (GList *) g_hash_table_lookup(ccf->labels, st->label);
+ if (labels != nullptr) {
+ /* Must use append to preserve the head stored in the hash table */
labels = g_list_append(labels, st);
}
else {
g_hash_table_insert(ccf->labels, st->label,
- g_list_prepend(NULL, st));
+ g_list_prepend(nullptr, st));
}
}
- if (st->symbol != NULL) {
+ if (st->symbol != nullptr) {
g_hash_table_insert(cfg->classifiers_symbols, st->symbol, st);
}
else {
@@ -1177,8 +1132,8 @@ rspamd_rcl_statfile_handler(rspamd_mempool_t *pool, const ucl_object_t *obj,
st->opts = (ucl_object_t *) obj;
st->clcf = ccf;
- val = ucl_object_lookup(obj, "spam");
- if (val == NULL) {
+ const auto *val = ucl_object_lookup(obj, "spam");
+ if (val == nullptr) {
msg_info_config(
"statfile %s has no explicit 'spam' setting, trying to guess by symbol",
st->symbol);
@@ -1216,47 +1171,41 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- const ucl_object_t *val, *cur;
- ucl_object_iter_t it = NULL;
- struct rspamd_config *cfg = ud;
- struct statfile_parser_data stud;
- const gchar *st_key;
- struct rspamd_classifier_config *ccf;
- gboolean res = TRUE;
- struct rspamd_rcl_section *stat_section;
- struct rspamd_tokenizer_config *tkcf = NULL;
- lua_State *L = cfg->lua_state;
+ auto *cfg = static_cast<rspamd_config *>(ud);
- g_assert(key != NULL);
- ccf = rspamd_config_new_classifier(cfg, NULL);
+ g_assert(key != nullptr);
+ auto *ccf = rspamd_config_new_classifier(cfg, nullptr);
+ auto *tkcf = (rspamd_tokenizer_config *) nullptr;
ccf->classifier = rspamd_mempool_strdup(cfg->cfg_pool, key);
- if (rspamd_rcl_section_parse_defaults(cfg, section, cfg->cfg_pool, obj,
+ if (rspamd_rcl_section_parse_defaults(cfg, *section, cfg->cfg_pool, obj,
ccf, err)) {
- HASH_FIND_STR(section->subsections, "statfile", stat_section);
+ auto stat_section = rspamd::find_map(section->subsections, "statfile");
- if (ccf->classifier == NULL) {
- ccf->classifier = "bayes";
+ if (ccf->classifier == nullptr) {
+ ccf->classifier = rspamd_mempool_strdup(cfg->cfg_pool, "bayes");
}
- if (ccf->name == NULL) {
+ if (ccf->name == nullptr) {
ccf->name = ccf->classifier;
}
- it = ucl_object_iterate_new(obj);
+ auto it = ucl_object_iterate_new(obj);
+ const auto *val = obj;
+ auto res = TRUE;
- while ((val = ucl_object_iterate_safe(it, true)) != NULL && res) {
- st_key = ucl_object_key(val);
+ while ((val = ucl_object_iterate_safe(it, true)) != nullptr && res) {
+ const auto *st_key = ucl_object_key(val);
- if (st_key != NULL) {
+ if (st_key != nullptr) {
if (g_ascii_strcasecmp(st_key, "statfile") == 0) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
- stud.cfg = cfg;
- stud.ccf = ccf;
- res = rspamd_rcl_process_section(cfg, stat_section, &stud,
+ struct statfile_parser_data stud = {.cfg = cfg, .ccf = ccf};
+ res = rspamd_rcl_process_section(cfg, *stat_section.value().get(), &stud,
cur, cfg->cfg_pool, err);
if (!res) {
@@ -1267,20 +1216,20 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
}
}
else if (g_ascii_strcasecmp(st_key, "tokenizer") == 0) {
- tkcf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*tkcf));
+ tkcf = rspamd_mempool_alloc0_type(cfg->cfg_pool, rspamd_tokenizer_config);
if (ucl_object_type(val) == UCL_STRING) {
tkcf->name = ucl_object_tostring(val);
}
else if (ucl_object_type(val) == UCL_OBJECT) {
- cur = ucl_object_lookup(val, "name");
- if (cur != NULL) {
+ const auto *cur = ucl_object_lookup(val, "name");
+ if (cur != nullptr) {
tkcf->name = ucl_object_tostring(cur);
tkcf->opts = val;
}
else {
cur = ucl_object_lookup(val, "type");
- if (cur != NULL) {
+ if (cur != nullptr) {
tkcf->name = ucl_object_tostring(cur);
tkcf->opts = val;
}
@@ -1296,17 +1245,18 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
msg_err_config("fatal configuration error, cannot parse statfile definition");
}
- if (tkcf == NULL) {
- tkcf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*tkcf));
- tkcf->name = NULL;
+ if (tkcf == nullptr) {
+ tkcf = rspamd_mempool_alloc0_type(cfg->cfg_pool, rspamd_tokenizer_config);
+ tkcf->name = nullptr;
}
ccf->tokenizer = tkcf;
/* Handle lua conditions */
- val = ucl_object_lookup_any(obj, "learn_condition", NULL);
+ const auto *val = ucl_object_lookup_any(obj, "learn_condition", nullptr);
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_type(cur) == UCL_STRING) {
@@ -1315,14 +1265,14 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
gint ref_idx;
lua_script = ucl_object_tolstring(cur, &slen);
- ref_idx = rspamd_lua_function_ref_from_str(L,
+ ref_idx = rspamd_lua_function_ref_from_str(RSPAMD_LUA_CFG_STATE(cfg),
lua_script, slen, "learn_condition", err);
if (ref_idx == LUA_NOREF) {
return FALSE;
}
- rspamd_lua_add_ref_dtor(L, cfg->cfg_pool, ref_idx);
+ rspamd_lua_add_ref_dtor(RSPAMD_LUA_CFG_STATE(cfg), cfg->cfg_pool, ref_idx);
ccf->learn_conditions = rspamd_mempool_glist_append(
cfg->cfg_pool,
ccf->learn_conditions,
@@ -1331,9 +1281,10 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
}
}
- val = ucl_object_lookup_any(obj, "classify_condition", NULL);
+ val = ucl_object_lookup_any(obj, "classify_condition", nullptr);
if (val) {
+ const auto *cur = val;
LL_FOREACH(val, cur)
{
if (ucl_object_type(cur) == UCL_STRING) {
@@ -1342,14 +1293,14 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
gint ref_idx;
lua_script = ucl_object_tolstring(cur, &slen);
- ref_idx = rspamd_lua_function_ref_from_str(L,
+ ref_idx = rspamd_lua_function_ref_from_str(RSPAMD_LUA_CFG_STATE(cfg),
lua_script, slen, "classify_condition", err);
if (ref_idx == LUA_NOREF) {
return FALSE;
}
- rspamd_lua_add_ref_dtor(L, cfg->cfg_pool, ref_idx);
+ rspamd_lua_add_ref_dtor(RSPAMD_LUA_CFG_STATE(cfg), cfg->cfg_pool, ref_idx);
ccf->classify_conditions = rspamd_mempool_glist_append(
cfg->cfg_pool,
ccf->classify_conditions,
@@ -1361,7 +1312,7 @@ rspamd_rcl_classifier_handler(rspamd_mempool_t *pool,
ccf->opts = (ucl_object_t *) obj;
cfg->classifiers = g_list_prepend(cfg->classifiers, ccf);
- return res;
+ return TRUE;
}
static gboolean
@@ -1372,27 +1323,27 @@ rspamd_rcl_composite_handler(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_config *cfg = ud;
+ auto *cfg = static_cast<rspamd_config *>(ud);
void *composite;
const gchar *composite_name;
- g_assert(key != NULL);
+ g_assert(key != nullptr);
composite_name = key;
- const ucl_object_t *val = ucl_object_lookup(obj, "enabled");
- if (val != NULL && !ucl_object_toboolean(val)) {
+ const auto *val = ucl_object_lookup(obj, "enabled");
+ if (val != nullptr && !ucl_object_toboolean(val)) {
msg_info_config("composite %s is disabled", composite_name);
return TRUE;
}
if ((composite = rspamd_composites_manager_add_from_ucl(cfg->composites_manager,
- composite_name, obj)) != NULL) {
+ composite_name, obj)) != nullptr) {
rspamd_symcache_add_symbol(cfg->cache, composite_name, 0,
- NULL, composite, SYMBOL_TYPE_COMPOSITE, -1);
+ nullptr, composite, SYMBOL_TYPE_COMPOSITE, -1);
}
- return composite != NULL;
+ return composite != nullptr;
}
static gboolean
@@ -1403,11 +1354,10 @@ rspamd_rcl_composites_handler(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- ucl_object_iter_t it = NULL;
- const ucl_object_t *cur;
- gboolean success = TRUE;
+ auto success = TRUE;
- it = ucl_object_iterate_new(obj);
+ auto it = ucl_object_iterate_new(obj);
+ const auto *cur = obj;
while ((cur = ucl_object_iterate_safe(it, true))) {
success = rspamd_rcl_composite_handler(pool, cur,
@@ -1430,14 +1380,11 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_config *cfg = ud;
- const ucl_object_t *hostval, *pathval;
- ucl_object_t *neigh;
- gboolean has_port = FALSE, has_proto = FALSE;
- GString *urlstr;
+ auto *cfg = static_cast<rspamd_config *>(ud);
+ auto has_port = FALSE, has_proto = FALSE;
const gchar *p;
- if (key == NULL) {
+ if (key == nullptr) {
g_set_error(err,
CFG_RCL_ERROR,
EINVAL,
@@ -1445,9 +1392,9 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
return FALSE;
}
- hostval = ucl_object_lookup(obj, "host");
+ const auto *hostval = ucl_object_lookup(obj, "host");
- if (hostval == NULL || ucl_object_type(hostval) != UCL_STRING) {
+ if (hostval == nullptr || ucl_object_type(hostval) != UCL_STRING) {
g_set_error(err,
CFG_RCL_ERROR,
EINVAL,
@@ -1455,44 +1402,43 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
return FALSE;
}
- neigh = ucl_object_typed_new(UCL_OBJECT);
+ auto *neigh = ucl_object_typed_new(UCL_OBJECT);
ucl_object_insert_key(neigh, ucl_object_copy(hostval), "host", 0, false);
- if ((p = strrchr(ucl_object_tostring(hostval), ':')) != NULL) {
+ if ((p = strrchr(ucl_object_tostring(hostval), ':')) != nullptr) {
if (g_ascii_isdigit(p[1])) {
has_port = TRUE;
}
}
- if (strstr(ucl_object_tostring(hostval), "://") != NULL) {
+ if (strstr(ucl_object_tostring(hostval), "://") != nullptr) {
has_proto = TRUE;
}
/* Now make url */
- urlstr = g_string_sized_new(63);
- pathval = ucl_object_lookup(obj, "path");
+ auto urlstr = std::string{};
+ const auto *pathval = ucl_object_lookup(obj, "path");
if (!has_proto) {
- g_string_append_len(urlstr, "http://", sizeof("http://") - 1);
+ urlstr += "http://";
}
- g_string_append(urlstr, ucl_object_tostring(hostval));
+ urlstr += ucl_object_tostring(hostval);
if (!has_port) {
- g_string_append(urlstr, ":11334");
+ urlstr += ":11334";
}
- if (pathval == NULL) {
- g_string_append(urlstr, "/");
+ if (pathval == nullptr) {
+ urlstr += "/";
}
else {
- g_string_append(urlstr, ucl_object_tostring(pathval));
+ urlstr += ucl_object_tostring(pathval);
}
ucl_object_insert_key(neigh,
- ucl_object_fromlstring(urlstr->str, urlstr->len),
+ ucl_object_fromlstring(urlstr.data(), urlstr.size()),
"url", 0, false);
- g_string_free(urlstr, TRUE);
ucl_object_insert_key(cfg->neighbours, neigh, key, 0, true);
return TRUE;
@@ -1500,67 +1446,92 @@ rspamd_rcl_neighbours_handler(rspamd_mempool_t *pool,
struct rspamd_rcl_section *
-rspamd_rcl_add_section(struct rspamd_rcl_section **top,
+rspamd_rcl_add_section(struct rspamd_rcl_sections_map **top,
+ struct rspamd_rcl_section *parent_section,
const gchar *name, const gchar *key_attr, rspamd_rcl_handler_t handler,
enum ucl_type type, gboolean required, gboolean strict_type)
{
- struct rspamd_rcl_section *new;
- ucl_object_t *parent_doc;
-
- new = g_malloc0(sizeof(struct rspamd_rcl_section));
- new->name = name;
- new->key_attr = key_attr;
- new->handler = handler;
- new->type = type;
- new->strict_type = strict_type;
-
- if (*top == NULL) {
- parent_doc = NULL;
- new->doc_ref = NULL;
- }
- else {
- parent_doc = (*top)->doc_ref;
- new->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(parent_doc,
- NULL,
- name,
- type,
- NULL,
- 0,
- NULL,
- 0));
- }
-
- HASH_ADD_KEYPTR(hh, *top, new->name, strlen(new->name), new);
- return new;
+ return rspamd_rcl_add_section_doc(top, parent_section, name, key_attr, handler,
+ type, required, strict_type, nullptr, nullptr);
}
struct rspamd_rcl_section *
-rspamd_rcl_add_section_doc(struct rspamd_rcl_section **top,
+rspamd_rcl_add_section_doc(struct rspamd_rcl_sections_map **top,
+ struct rspamd_rcl_section *parent_section,
const gchar *name, const gchar *key_attr, rspamd_rcl_handler_t handler,
enum ucl_type type, gboolean required, gboolean strict_type,
ucl_object_t *doc_target,
const gchar *doc_string)
{
- struct rspamd_rcl_section *new_section;
-
- new_section = g_malloc0(sizeof(struct rspamd_rcl_section));
- new_section->name = name;
- new_section->key_attr = key_attr;
- new_section->handler = handler;
- new_section->type = type;
- new_section->strict_type = strict_type;
-
- new_section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(doc_target,
- doc_string,
- name,
- type,
- NULL,
- 0,
- NULL,
- 0));
-
- HASH_ADD_KEYPTR(hh, *top, new_section->name, strlen(new_section->name), new_section);
- return new_section;
+ if (top == nullptr) {
+ g_error("invalid arguments to rspamd_rcl_add_section");
+ return nullptr;
+ }
+ if (*top == nullptr) {
+ *top = new rspamd_rcl_sections_map;
+ }
+
+ auto fill_section = [&](struct rspamd_rcl_section *section) {
+ section->name = name;
+ if (key_attr) {
+ section->key_attr = std::string{key_attr};
+ }
+ section->handler = handler;
+ section->type = type;
+ section->strict_type = strict_type;
+
+ if (doc_target == nullptr) {
+ if (parent_section && parent_section->doc_ref) {
+ section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(parent_section->doc_ref,
+ doc_string,
+ name,
+ type,
+ nullptr,
+ 0,
+ nullptr,
+ 0));
+ }
+ else {
+ section->doc_ref = nullptr;
+ }
+ }
+ else {
+ section->doc_ref = ucl_object_ref(rspamd_rcl_add_doc_obj(doc_target,
+ doc_string,
+ name,
+ type,
+ nullptr,
+ 0,
+ nullptr,
+ 0));
+ }
+ section->top = *top;
+ };
+
+ /* Select the appropriate container and insert section inside it */
+ if (parent_section) {
+ auto it = parent_section->subsections.insert(std::make_pair(std::string{name},
+ std::make_shared<rspamd_rcl_section>()));
+ if (!it.second) {
+ g_error("invalid arguments to rspamd_rcl_add_section");
+ return nullptr;
+ }
+
+ fill_section(it.first->second.get());
+ return it.first->second.get();
+ }
+ else {
+ auto it = (*top)->sections.insert(std::make_pair(std::string{name},
+ std::make_shared<rspamd_rcl_section>()));
+ if (!it.second) {
+ g_error("invalid arguments to rspamd_rcl_add_section");
+ return nullptr;
+ }
+
+ (*top)->sections_order.push_back(it.first->second);
+ fill_section(it.first->second.get());
+ return it.first->second.get();
+ }
}
struct rspamd_rcl_default_handler_data *
@@ -1571,34 +1542,32 @@ rspamd_rcl_add_default_handler(struct rspamd_rcl_section *section,
gint flags,
const gchar *doc_string)
{
- struct rspamd_rcl_default_handler_data *nhandler;
+ auto it = section->default_parser.emplace(std::make_pair(std::string{name}, rspamd_rcl_default_handler_data{}));
- nhandler = g_malloc0(sizeof(struct rspamd_rcl_default_handler_data));
- nhandler->key = g_strdup(name);
- nhandler->handler = handler;
- nhandler->pd.offset = offset;
- nhandler->pd.flags = flags;
+ auto &nhandler = it.first->second;
+ nhandler.key = name;
+ nhandler.handler = handler;
+ nhandler.pd.offset = offset;
+ nhandler.pd.flags = flags;
- if (section->doc_ref != NULL) {
+ if (section->doc_ref != nullptr) {
rspamd_rcl_add_doc_obj(section->doc_ref,
doc_string,
name,
UCL_NULL,
handler,
flags,
- NULL,
+ nullptr,
0);
}
- HASH_ADD_KEYPTR(hh, section->default_parser, nhandler->key, strlen(nhandler->key), nhandler);
- return nhandler;
+ return &nhandler;
}
-struct rspamd_rcl_section *
+struct rspamd_rcl_sections_map *
rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
{
- struct rspamd_rcl_section *new = NULL, *sub, *ssub;
-
+ auto *top = new rspamd_rcl_sections_map;
/*
* Important notice:
* the order of parsing is equal to order of this initialization, therefore
@@ -1609,14 +1578,14 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
* Logging section
*/
if (!(skip_sections && g_hash_table_lookup(skip_sections, "logging"))) {
- sub = rspamd_rcl_add_section_doc(&new,
- "logging", NULL,
- rspamd_rcl_logging_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Configure rspamd logging");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "logging", nullptr,
+ rspamd_rcl_logging_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Configure rspamd logging");
/* Default handlers */
rspamd_rcl_add_default_handler(sub,
"log_buffer",
@@ -1675,59 +1644,59 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
"Enable colored output (for console logging)",
"log_color",
UCL_BOOLEAN,
- NULL,
+ nullptr,
0,
- NULL,
+ nullptr,
0);
rspamd_rcl_add_doc_by_path(cfg,
"logging",
"Enable severity logging output (e.g. [error] or [warning])",
"log_severity",
UCL_BOOLEAN,
- NULL,
+ nullptr,
0,
- NULL,
+ nullptr,
0);
rspamd_rcl_add_doc_by_path(cfg,
"logging",
"Enable systemd compatible logging",
"systemd",
UCL_BOOLEAN,
- NULL,
+ nullptr,
0,
- NULL,
+ nullptr,
0);
rspamd_rcl_add_doc_by_path(cfg,
"logging",
"Write statistics of regexp processing to log (useful for hyperscan)",
"log_re_cache",
UCL_BOOLEAN,
- NULL,
+ nullptr,
0,
- NULL,
+ nullptr,
0);
rspamd_rcl_add_doc_by_path(cfg,
"logging",
"Use microseconds resolution for timestamps",
"log_usec",
UCL_BOOLEAN,
- NULL,
+ nullptr,
0,
- NULL,
+ nullptr,
0);
}
if (!(skip_sections && g_hash_table_lookup(skip_sections, "options"))) {
/**
* Options section
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "options", NULL,
- rspamd_rcl_options_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Global rspamd options");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "options", nullptr,
+ rspamd_rcl_options_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Global rspamd options");
rspamd_rcl_add_default_handler(sub,
"cache_file",
rspamd_rcl_parse_struct_string,
@@ -1740,6 +1709,7 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
G_STRUCT_OFFSET(struct rspamd_config, cache_reload_time),
RSPAMD_CL_FLAG_TIME_FLOAT,
"How often cache reload should be performed");
+
/* Old DNS configuration */
rspamd_rcl_add_default_handler(sub,
"dns_nameserver",
@@ -2034,7 +2004,7 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
rspamd_rcl_parse_struct_string,
G_STRUCT_OFFSET(struct rspamd_config, ssl_ciphers),
0,
- "List of ssl ciphers (e.g. HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4)");
+ "List of ssl ciphers (e.g. HIGH:!anullptr:!kRSA:!PSK:!SRP:!MD5:!RC4)");
rspamd_rcl_add_default_handler(sub,
"max_message",
rspamd_rcl_parse_struct_integer,
@@ -2176,17 +2146,17 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
"Events backend to use: kqueue, epoll, select, poll or auto (default: auto)");
/* Neighbours configuration */
- rspamd_rcl_add_section_doc(&sub->subsections, "neighbours", "name",
+ rspamd_rcl_add_section_doc(&top, sub, "neighbours", "name",
rspamd_rcl_neighbours_handler,
UCL_OBJECT, FALSE, TRUE,
cfg->doc_strings,
"List of members of Rspamd cluster");
/* New DNS configuration */
- ssub = rspamd_rcl_add_section_doc(&sub->subsections, "dns", NULL, NULL,
- UCL_OBJECT, FALSE, TRUE,
- cfg->doc_strings,
- "Options for DNS resolver");
+ auto *ssub = rspamd_rcl_add_section_doc(&top, sub, "dns", nullptr, nullptr,
+ UCL_OBJECT, FALSE, TRUE,
+ cfg->doc_strings,
+ "Options for DNS resolver");
rspamd_rcl_add_default_handler(ssub,
"nameserver",
rspamd_rcl_parse_struct_ucl,
@@ -2232,7 +2202,7 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
/* New upstreams configuration */
- ssub = rspamd_rcl_add_section_doc(&sub->subsections, "upstream", NULL, NULL,
+ ssub = rspamd_rcl_add_section_doc(&top, sub, "upstream", nullptr, nullptr,
UCL_OBJECT, FALSE, TRUE,
cfg->doc_strings,
"Upstreams configuration parameters");
@@ -2266,14 +2236,14 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
/**
* Symbols and actions sections
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "actions", NULL,
- rspamd_rcl_actions_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Actions configuration");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "actions", nullptr,
+ rspamd_rcl_actions_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Actions configuration");
rspamd_rcl_add_default_handler(sub,
"unknown_weight",
rspamd_rcl_parse_struct_double,
@@ -2297,19 +2267,19 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
}
if (!(skip_sections && g_hash_table_lookup(skip_sections, "group"))) {
- sub = rspamd_rcl_add_section_doc(&new,
- "group", "name",
- rspamd_rcl_group_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Symbol groups configuration");
- ssub = rspamd_rcl_add_section_doc(&sub->subsections, "symbols", "name",
- rspamd_rcl_symbol_handler,
- UCL_OBJECT, FALSE, TRUE,
- cfg->doc_strings,
- "Symbols configuration");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "group", "name",
+ rspamd_rcl_group_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Symbol groups configuration");
+ rspamd_rcl_add_section_doc(&top, sub, "symbols", "name",
+ rspamd_rcl_symbol_handler,
+ UCL_OBJECT, FALSE, TRUE,
+ cfg->doc_strings,
+ "Symbols configuration");
/* Group part */
rspamd_rcl_add_default_handler(sub,
@@ -2324,14 +2294,13 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
/**
* Worker section
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "worker", "type",
- rspamd_rcl_worker_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Workers common options");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr, "worker", "type",
+ rspamd_rcl_worker_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Workers common options");
rspamd_rcl_add_default_handler(sub,
"count",
rspamd_rcl_parse_struct_integer,
@@ -2362,28 +2331,28 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
/**
* Modules handler
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "modules", NULL,
- rspamd_rcl_modules_handler,
- UCL_OBJECT,
- FALSE,
- FALSE,
- cfg->doc_strings,
- "Lua plugins to load");
+ rspamd_rcl_add_section_doc(&top, nullptr,
+ "modules", nullptr,
+ rspamd_rcl_modules_handler,
+ UCL_OBJECT,
+ FALSE,
+ FALSE,
+ cfg->doc_strings,
+ "Lua plugins to load");
}
if (!(skip_sections && g_hash_table_lookup(skip_sections, "classifier"))) {
/**
* Classifiers handler
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "classifier", "type",
- rspamd_rcl_classifier_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "CLassifier options");
+ auto *sub = rspamd_rcl_add_section_doc(&top, nullptr,
+ "classifier", "type",
+ rspamd_rcl_classifier_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "CLassifier options");
/* Default classifier is 'bayes' for now */
sub->default_key = "bayes";
@@ -2433,14 +2402,14 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
/*
* Statfile defaults
*/
- ssub = rspamd_rcl_add_section_doc(&sub->subsections,
- "statfile", "symbol",
- rspamd_rcl_statfile_handler,
- UCL_OBJECT,
- TRUE,
- TRUE,
- sub->doc_ref,
- "Statfiles options");
+ auto *ssub = rspamd_rcl_add_section_doc(&top, sub,
+ "statfile", "symbol",
+ rspamd_rcl_statfile_handler,
+ UCL_OBJECT,
+ TRUE,
+ TRUE,
+ sub->doc_ref,
+ "Statfiles options");
rspamd_rcl_add_default_handler(ssub,
"label",
rspamd_rcl_parse_struct_string,
@@ -2459,95 +2428,68 @@ rspamd_rcl_config_init(struct rspamd_config *cfg, GHashTable *skip_sections)
/**
* Composites handlers
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "composite", "name",
- rspamd_rcl_composite_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Rspamd composite symbols");
- sub = rspamd_rcl_add_section_doc(&new,
- "composites", NULL,
- rspamd_rcl_composites_handler,
- UCL_OBJECT,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Rspamd composite symbols");
+ rspamd_rcl_add_section_doc(&top, nullptr,
+ "composite", "name",
+ rspamd_rcl_composite_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Rspamd composite symbols");
+ rspamd_rcl_add_section_doc(&top, nullptr,
+ "composites", nullptr,
+ rspamd_rcl_composites_handler,
+ UCL_OBJECT,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Rspamd composite symbols");
}
if (!(skip_sections && g_hash_table_lookup(skip_sections, "lua"))) {
/**
* Lua handler
*/
- sub = rspamd_rcl_add_section_doc(&new,
- "lua", NULL,
- rspamd_rcl_lua_handler,
- UCL_STRING,
- FALSE,
- TRUE,
- cfg->doc_strings,
- "Lua files to load");
- }
-
- return new;
-}
-
-struct rspamd_rcl_section *
-rspamd_rcl_config_get_section(struct rspamd_rcl_section *top,
- const char *path)
-{
- struct rspamd_rcl_section *cur, *found = NULL;
- char **path_components;
- gint ncomponents, i;
-
-
- if (path == NULL) {
- return top;
+ rspamd_rcl_add_section_doc(&top, nullptr,
+ "lua", nullptr,
+ rspamd_rcl_lua_handler,
+ UCL_STRING,
+ FALSE,
+ TRUE,
+ cfg->doc_strings,
+ "Lua files to load");
}
- path_components = g_strsplit_set(path, "/", -1);
- ncomponents = g_strv_length(path_components);
-
- cur = top;
- for (i = 0; i < ncomponents; i++) {
- if (cur == NULL) {
- g_strfreev(path_components);
- return NULL;
- }
- HASH_FIND_STR(cur, path_components[i], found);
- if (found == NULL) {
- g_strfreev(path_components);
- return NULL;
- }
- cur = found;
- }
+ cfg->rcl_top_section = top;
- g_strfreev(path_components);
- return found;
+ return top;
}
-static gboolean
+static bool
rspamd_rcl_process_section(struct rspamd_config *cfg,
- struct rspamd_rcl_section *sec,
+ const struct rspamd_rcl_section &sec,
gpointer ptr, const ucl_object_t *obj, rspamd_mempool_t *pool,
GError **err)
{
ucl_object_iter_t it;
const ucl_object_t *cur;
- gboolean is_nested = TRUE;
- const gchar *key = NULL;
+ auto is_nested = true;
+ const gchar *key = nullptr;
+
+ if (sec.processed) {
+ /* Section has been already processed */
+ return TRUE;
+ }
- g_assert(obj != NULL);
- g_assert(sec->handler != NULL);
+ g_assert(obj != nullptr);
+ g_assert(sec.handler != nullptr);
- if (sec->key_attr != NULL) {
+ if (sec.key_attr) {
it = ucl_object_iterate_new(obj);
- while ((cur = ucl_object_iterate_full(it, UCL_ITERATE_EXPLICIT)) != NULL) {
+ while ((cur = ucl_object_iterate_full(it, UCL_ITERATE_EXPLICIT)) != nullptr) {
if (ucl_object_type(cur) != UCL_OBJECT) {
- is_nested = FALSE;
+ is_nested = false;
break;
}
}
@@ -2555,54 +2497,54 @@ rspamd_rcl_process_section(struct rspamd_config *cfg,
ucl_object_iterate_free(it);
}
else {
- is_nested = FALSE;
+ is_nested = false;
}
if (is_nested) {
/* Just reiterate on all subobjects */
it = ucl_object_iterate_new(obj);
- while ((cur = ucl_object_iterate_full(it, UCL_ITERATE_EXPLICIT)) != NULL) {
- if (!sec->handler(pool, cur, ucl_object_key(cur), ptr, sec, err)) {
+ while ((cur = ucl_object_iterate_full(it, UCL_ITERATE_EXPLICIT)) != nullptr) {
+ if (!sec.handler(pool, cur, ucl_object_key(cur), ptr, const_cast<rspamd_rcl_section *>(&sec), err)) {
ucl_object_iterate_free(it);
- return FALSE;
+ return false;
}
}
ucl_object_iterate_free(it);
- return TRUE;
+ return true;
}
else {
- if (sec->key_attr != NULL) {
+ if (sec.key_attr) {
/* First of all search for required attribute and use it as a key */
- cur = ucl_object_lookup(obj, sec->key_attr);
+ cur = ucl_object_lookup(obj, sec.key_attr.value().c_str());
- if (cur == NULL) {
- if (sec->default_key == NULL) {
+ if (cur == nullptr) {
+ if (!sec.default_key) {
g_set_error(err, CFG_RCL_ERROR, EINVAL, "required attribute "
"'%s' is missing for section '%s', current key: %s",
- sec->key_attr,
- sec->name,
- ucl_object_emit(obj, UCL_EMIT_CONFIG));
+ sec.key_attr.value().c_str(),
+ sec.name.c_str(),
+ ucl_object_key(obj));
- return FALSE;
+ return false;
}
else {
msg_info("using default key '%s' for mandatory field '%s' "
"for section '%s'",
- sec->default_key, sec->key_attr,
- sec->name);
- key = sec->default_key;
+ sec.default_key.value().c_str(), sec.key_attr.value().c_str(),
+ sec.name.c_str());
+ key = sec.default_key.value().c_str();
}
}
else if (ucl_object_type(cur) != UCL_STRING) {
g_set_error(err, CFG_RCL_ERROR, EINVAL, "required attribute %s"
" is not a string for section %s",
- sec->key_attr, sec->name);
+ sec.key_attr.value().c_str(), sec.name.c_str());
- return FALSE;
+ return false;
}
else {
key = ucl_object_tostring(cur);
@@ -2610,18 +2552,15 @@ rspamd_rcl_process_section(struct rspamd_config *cfg,
}
}
- return sec->handler(pool, obj, key, ptr, sec, err);
+ return sec.handler(pool, obj, key, ptr, const_cast<rspamd_rcl_section *>(&sec), err);
}
gboolean
-rspamd_rcl_parse(struct rspamd_rcl_section *top,
+rspamd_rcl_parse(struct rspamd_rcl_sections_map *top,
struct rspamd_config *cfg,
gpointer ptr, rspamd_mempool_t *pool,
const ucl_object_t *obj, GError **err)
{
- const ucl_object_t *found, *cur_obj;
- struct rspamd_rcl_section *cur, *tmp, *found_sec;
-
if (obj->type != UCL_OBJECT) {
g_set_error(err,
CFG_RCL_ERROR,
@@ -2631,24 +2570,22 @@ rspamd_rcl_parse(struct rspamd_rcl_section *top,
}
/* Iterate over known sections and ignore unknown ones */
- HASH_ITER(hh, top, cur, tmp)
- {
- if (strcmp(cur->name, "*") == 0) {
+ for (const auto &sec_ptr: top->sections_order) {
+ if (sec_ptr->name == "*") {
/* Default section handler */
+ const auto *cur_obj = obj;
LL_FOREACH(obj, cur_obj)
{
- HASH_FIND_STR(top, ucl_object_key(cur_obj), found_sec);
-
- if (found_sec == NULL) {
- if (cur->handler != NULL) {
- if (!rspamd_rcl_process_section(cfg, cur, ptr, cur_obj,
+ if (!top->sections.contains(ucl_object_key(cur_obj))) {
+ if (sec_ptr->handler != nullptr) {
+ if (!rspamd_rcl_process_section(cfg, *sec_ptr, ptr, cur_obj,
pool, err)) {
return FALSE;
}
}
else {
rspamd_rcl_section_parse_defaults(cfg,
- cur,
+ *sec_ptr,
pool,
cur_obj,
ptr,
@@ -2658,34 +2595,35 @@ rspamd_rcl_parse(struct rspamd_rcl_section *top,
}
}
else {
- found = ucl_object_lookup(obj, cur->name);
- if (found == NULL) {
- if (cur->required) {
+ const auto *found = ucl_object_lookup(obj, sec_ptr->name.c_str());
+ if (found == nullptr) {
+ if (sec_ptr->required) {
g_set_error(err, CFG_RCL_ERROR, ENOENT,
- "required section %s is missing", cur->name);
+ "required section %s is missing", sec_ptr->name.c_str());
return FALSE;
}
}
else {
/* Check type */
- if (cur->strict_type) {
- if (cur->type != found->type) {
+ if (sec_ptr->strict_type) {
+ if (sec_ptr->type != found->type) {
g_set_error(err, CFG_RCL_ERROR, EINVAL,
- "object in section %s has invalid type", cur->name);
+ "object in section %s has invalid type", sec_ptr->name.c_str());
return FALSE;
}
}
+ const auto *cur_obj = found;
LL_FOREACH(found, cur_obj)
{
- if (cur->handler != NULL) {
- if (!rspamd_rcl_process_section(cfg, cur, ptr, cur_obj,
+ if (sec_ptr->handler != nullptr) {
+ if (!rspamd_rcl_process_section(cfg, *sec_ptr, ptr, cur_obj,
pool, err)) {
return FALSE;
}
}
else {
- rspamd_rcl_section_parse_defaults(cfg, cur,
+ rspamd_rcl_section_parse_defaults(cfg, *sec_ptr,
pool,
cur_obj,
ptr,
@@ -2694,22 +2632,20 @@ rspamd_rcl_parse(struct rspamd_rcl_section *top,
}
}
}
- if (cur->fin) {
- cur->fin(pool, cur->fin_ud);
+ if (sec_ptr->fin) {
+ sec_ptr->fin(pool, sec_ptr->fin_ud);
}
}
return TRUE;
}
-gboolean
+static bool
rspamd_rcl_section_parse_defaults(struct rspamd_config *cfg,
- struct rspamd_rcl_section *section,
+ const struct rspamd_rcl_section &section,
rspamd_mempool_t *pool, const ucl_object_t *obj, gpointer ptr,
GError **err)
{
- const ucl_object_t *found, *cur_obj;
- struct rspamd_rcl_default_handler_data *cur, *tmp;
if (obj->type != UCL_OBJECT) {
g_set_error(err,
@@ -2717,24 +2653,25 @@ rspamd_rcl_section_parse_defaults(struct rspamd_config *cfg,
EINVAL,
"default configuration must be an object for section %s "
"(actual type is %s)",
- section->name, ucl_object_type_to_string(obj->type));
+ section.name.c_str(), ucl_object_type_to_string(ucl_object_type(obj)));
return FALSE;
}
- HASH_ITER(hh, section->default_parser, cur, tmp)
- {
- found = ucl_object_lookup(obj, cur->key);
- if (found != NULL) {
- cur->pd.user_struct = ptr;
- cur->pd.cfg = cfg;
+ for (const auto &cur: section.default_parser) {
+ const auto *found = ucl_object_lookup(obj, cur.first.c_str());
+ if (found != nullptr) {
+ auto new_pd = cur.second.pd;
+ new_pd.user_struct = ptr;
+ new_pd.cfg = cfg;
+ const auto *cur_obj = found;
LL_FOREACH(found, cur_obj)
{
- if (!cur->handler(pool, cur_obj, &cur->pd, section, err)) {
+ if (!cur.second.handler(pool, cur_obj, &new_pd, const_cast<rspamd_rcl_section *>(&section), err)) {
return FALSE;
}
- if (!(cur->pd.flags & RSPAMD_CL_FLAG_MULTIPLE)) {
+ if (!(new_pd.flags & RSPAMD_CL_FLAG_MULTIPLE)) {
break;
}
}
@@ -2751,32 +2688,31 @@ rspamd_rcl_parse_struct_string(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
- gchar **target;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
const gsize num_str_len = 32;
- target = (gchar **) (((gchar *) pd->user_struct) + pd->offset);
+ auto target = (gchar **) (((gchar *) pd->user_struct) + pd->offset);
switch (obj->type) {
case UCL_STRING:
*target =
rspamd_mempool_strdup(pool, ucl_copy_value_trash(obj));
break;
case UCL_INT:
- *target = rspamd_mempool_alloc(pool, num_str_len);
+ *target = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(*target, num_str_len, "%L", obj->value.iv);
break;
case UCL_FLOAT:
- *target = rspamd_mempool_alloc(pool, num_str_len);
+ *target = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(*target, num_str_len, "%f", obj->value.dv);
break;
case UCL_BOOLEAN:
- *target = rspamd_mempool_alloc(pool, num_str_len);
+ *target = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(*target, num_str_len, "%s",
((gboolean) obj->value.iv) ? "true" : "false");
break;
case UCL_NULL:
/* String is enforced to be null */
- *target = NULL;
+ *target = nullptr;
break;
default:
g_set_error(err,
@@ -2798,7 +2734,7 @@ rspamd_rcl_parse_struct_integer(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
union {
gint *ip;
gint32 *i32p;
@@ -2898,7 +2834,7 @@ rspamd_rcl_parse_struct_double(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
gdouble *target;
target = (gdouble *) (((gchar *) pd->user_struct) + pd->offset);
@@ -2923,7 +2859,7 @@ rspamd_rcl_parse_struct_time(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
union {
gint *psec;
guint32 *pu32;
@@ -2987,7 +2923,7 @@ rspamd_rcl_parse_struct_keypair(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
struct rspamd_cryptobox_keypair **target, *kp;
target = (struct rspamd_cryptobox_keypair **) (((gchar *) pd->user_struct) +
@@ -2995,18 +2931,18 @@ rspamd_rcl_parse_struct_keypair(rspamd_mempool_t *pool,
if (obj->type == UCL_OBJECT) {
kp = rspamd_keypair_from_ucl(obj);
- if (kp != NULL) {
+ if (kp != nullptr) {
rspamd_mempool_add_destructor(pool,
(rspamd_mempool_destruct_t) rspamd_keypair_unref, kp);
*target = kp;
}
else {
- gchar *dump = ucl_object_emit(obj, UCL_EMIT_JSON_COMPACT);
+ gchar *dump = (char *) ucl_object_emit(obj, UCL_EMIT_JSON_COMPACT);
g_set_error(err,
CFG_RCL_ERROR,
EINVAL,
"cannot load the keypair specified: %s; section: %s; value: %s",
- ucl_object_key(obj), section->name, dump);
+ ucl_object_key(obj), section->name.c_str(), dump);
free(dump);
return FALSE;
@@ -3031,12 +2967,12 @@ rspamd_rcl_parse_struct_pubkey(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
struct rspamd_cryptobox_pubkey **target, *pk;
gsize len;
const gchar *str;
- gint keypair_type = RSPAMD_KEYPAIR_KEX,
- keypair_mode = RSPAMD_CRYPTOBOX_MODE_25519;
+ rspamd_cryptobox_keypair_type keypair_type = RSPAMD_KEYPAIR_KEX;
+ rspamd_cryptobox_mode keypair_mode = RSPAMD_CRYPTOBOX_MODE_25519;
if (pd->flags & RSPAMD_CL_FLAG_SIGNKEY) {
keypair_type = RSPAMD_KEYPAIR_SIGN;
@@ -3052,7 +2988,7 @@ rspamd_rcl_parse_struct_pubkey(rspamd_mempool_t *pool,
pk = rspamd_pubkey_from_base32(str, len, keypair_type,
keypair_mode);
- if (pk != NULL) {
+ if (pk != nullptr) {
*target = pk;
}
else {
@@ -3081,7 +3017,7 @@ rspamd_rcl_parse_struct_pubkey(rspamd_mempool_t *pool,
static void
rspamd_rcl_insert_string_list_item(gpointer *target, rspamd_mempool_t *pool,
- const gchar *src, gboolean is_hash)
+ std::string_view elt, gboolean is_hash)
{
union {
GHashTable *hv;
@@ -3093,17 +3029,17 @@ rspamd_rcl_insert_string_list_item(gpointer *target, rspamd_mempool_t *pool,
d.p = *target;
if (is_hash) {
- if (d.hv == NULL) {
+ if (d.hv == nullptr) {
d.hv = g_hash_table_new(rspamd_str_hash, rspamd_str_equal);
rspamd_mempool_add_destructor(pool,
(rspamd_mempool_destruct_t) g_hash_table_unref, d.hv);
}
- val = rspamd_mempool_strdup(pool, src);
+ val = rspamd_mempool_strdup_len(pool, elt.data(), elt.size());
g_hash_table_insert(d.hv, val, val);
}
else {
- val = rspamd_mempool_strdup(pool, src);
+ val = rspamd_mempool_strdup_len(pool, elt.data(), elt.size());
d.lv = g_list_prepend(d.lv, val);
}
@@ -3117,51 +3053,50 @@ rspamd_rcl_parse_struct_string_list(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
- gpointer *target;
- gchar *val, **strvec, **cvec;
- const ucl_object_t *cur;
- const gsize num_str_len = 32;
- ucl_object_iter_t iter = NULL;
- gboolean is_hash, need_destructor = TRUE;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
+ constexpr const auto num_str_len = 32;
+ auto need_destructor = true;
- is_hash = pd->flags & RSPAMD_CL_FLAG_STRING_LIST_HASH;
- target = (gpointer *) (((gchar *) pd->user_struct) + pd->offset);
+ auto is_hash = pd->flags & RSPAMD_CL_FLAG_STRING_LIST_HASH;
+ auto *target = (gpointer *) (((gchar *) pd->user_struct) + pd->offset);
- if (!is_hash && *target != NULL) {
+ if (!is_hash && *target != nullptr) {
need_destructor = FALSE;
}
- iter = ucl_object_iterate_new(obj);
+ auto iter = ucl_object_iterate_new(obj);
+ const auto *cur = obj;
- while ((cur = ucl_object_iterate_safe(iter, true)) != NULL) {
+ while ((cur = ucl_object_iterate_safe(iter, true)) != nullptr) {
switch (cur->type) {
- case UCL_STRING:
- strvec = g_strsplit_set(ucl_object_tostring(cur), ",", -1);
- cvec = strvec;
-
- while (*cvec) {
- rspamd_rcl_insert_string_list_item(target, pool, *cvec, is_hash);
- cvec++;
- }
+ case UCL_STRING: {
+ rspamd::string_foreach_delim(ucl_object_tostring(cur), ", ", [&](const auto &elt) {
+ rspamd_rcl_insert_string_list_item(target, pool, elt, is_hash);
+ });
- g_strfreev(strvec);
/* Go to the next object */
continue;
- case UCL_INT:
- val = rspamd_mempool_alloc(pool, num_str_len);
+ }
+ case UCL_INT: {
+ auto *val = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(val, num_str_len, "%L", cur->value.iv);
+ rspamd_rcl_insert_string_list_item(target, pool, val, is_hash);
break;
- case UCL_FLOAT:
- val = rspamd_mempool_alloc(pool, num_str_len);
+ }
+ case UCL_FLOAT: {
+ auto *val = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(val, num_str_len, "%f", cur->value.dv);
+ rspamd_rcl_insert_string_list_item(target, pool, val, is_hash);
break;
- case UCL_BOOLEAN:
- val = rspamd_mempool_alloc(pool, num_str_len);
+ }
+ case UCL_BOOLEAN: {
+ auto *val = (gchar *) rspamd_mempool_alloc(pool, num_str_len);
rspamd_snprintf(val, num_str_len, "%s",
((gboolean) cur->value.iv) ? "true" : "false");
+ rspamd_rcl_insert_string_list_item(target, pool, val, is_hash);
break;
+ }
default:
g_set_error(err,
CFG_RCL_ERROR,
@@ -3173,15 +3108,13 @@ rspamd_rcl_parse_struct_string_list(rspamd_mempool_t *pool,
return FALSE;
}
-
- rspamd_rcl_insert_string_list_item(target, pool, val, is_hash);
}
ucl_object_iterate_free(iter);
#if 0
/* WTF: why don't we allow empty list here?? */
- if (*target == NULL) {
+ if (*target == nullptr) {
g_set_error (err,
CFG_RCL_ERROR,
EINVAL,
@@ -3193,8 +3126,8 @@ rspamd_rcl_parse_struct_string_list(rspamd_mempool_t *pool,
}
#endif
- if (!is_hash && *target != NULL) {
- *target = g_list_reverse(*target);
+ if (!is_hash && *target != nullptr) {
+ *target = g_list_reverse(*(GList **) target);
if (need_destructor) {
rspamd_mempool_add_destructor(pool,
@@ -3213,7 +3146,7 @@ rspamd_rcl_parse_struct_ucl(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
const ucl_object_t **target;
target = (const ucl_object_t **) (((gchar *) pd->user_struct) + pd->offset);
@@ -3231,7 +3164,7 @@ rspamd_rcl_parse_struct_boolean(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
gboolean *target;
target = (gboolean *) (((gchar *) pd->user_struct) + pd->offset);
@@ -3266,7 +3199,7 @@ rspamd_rcl_parse_struct_addr(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
rspamd_inet_addr_t **target;
const gchar *val;
gsize size;
@@ -3305,8 +3238,8 @@ rspamd_rcl_parse_struct_mime_addr(rspamd_mempool_t *pool,
struct rspamd_rcl_section *section,
GError **err)
{
- struct rspamd_rcl_struct_parser *pd = ud;
- GPtrArray **target, *tmp_addr = NULL;
+ auto *pd = (struct rspamd_rcl_struct_parser *) ud;
+ GPtrArray **target, *tmp_addr = nullptr;
const gchar *val;
ucl_object_iter_t it;
const ucl_object_t *cur;
@@ -3314,7 +3247,7 @@ rspamd_rcl_parse_struct_mime_addr(rspamd_mempool_t *pool,
target = (GPtrArray **) (((gchar *) pd->user_struct) + pd->offset);
it = ucl_object_iterate_new(obj);
- while ((cur = ucl_object_iterate_safe(it, true)) != NULL) {
+ while ((cur = ucl_object_iterate_safe(it, true)) != nullptr) {
if (ucl_object_type(cur) == UCL_STRING) {
val = ucl_object_tostring(obj);
tmp_addr = rspamd_email_address_from_mime(pool, val,
@@ -3338,31 +3271,6 @@ rspamd_rcl_parse_struct_mime_addr(rspamd_mempool_t *pool,
return TRUE;
}
-static guint
-rspamd_worker_param_key_hash(gconstpointer p)
-{
- const struct rspamd_worker_param_key *k = p;
- rspamd_cryptobox_fast_hash_state_t st;
-
- rspamd_cryptobox_fast_hash_init(&st, rspamd_hash_seed());
- rspamd_cryptobox_fast_hash_update(&st, k->name, strlen(k->name));
- rspamd_cryptobox_fast_hash_update(&st, &k->ptr, sizeof(gpointer));
-
- return rspamd_cryptobox_fast_hash_final(&st);
-}
-
-static gboolean
-rspamd_worker_param_key_equal(gconstpointer p1, gconstpointer p2)
-{
- const struct rspamd_worker_param_key *k1 = p1, *k2 = p2;
-
- if (k1->ptr == k2->ptr) {
- return strcmp(k1->name, k2->name) == 0;
- }
-
- return FALSE;
-}
-
void rspamd_rcl_register_worker_option(struct rspamd_config *cfg,
GQuark type,
const gchar *name,
@@ -3372,26 +3280,11 @@ void rspamd_rcl_register_worker_option(struct rspamd_config *cfg,
gint flags,
const gchar *doc_string)
{
- struct rspamd_worker_param_parser *nhandler;
- struct rspamd_worker_cfg_parser *nparser;
- struct rspamd_worker_param_key srch;
- const ucl_object_t *doc_workers, *doc_target;
- ucl_object_t *doc_obj;
+ auto parser_it = cfg->rcl_top_section->workers_parser.try_emplace(type, rspamd_worker_cfg_parser{});
+ auto &parser = parser_it.first->second;
+ auto handler_it = parser.parsers.try_emplace(std::make_pair(std::string{name}, target), rspamd_worker_param_parser{});
- nparser = g_hash_table_lookup(cfg->wrk_parsers, &type);
-
- if (nparser == NULL) {
- rspamd_rcl_register_worker_parser(cfg, type, NULL, NULL);
- nparser = g_hash_table_lookup(cfg->wrk_parsers, &type);
-
- g_assert(nparser != NULL);
- }
-
- srch.name = name;
- srch.ptr = target;
-
- nhandler = g_hash_table_lookup(nparser->parsers, &srch);
- if (nhandler != NULL) {
+ if (!handler_it.second) {
msg_warn_config(
"handler for parameter %s is already registered for worker type %s",
name,
@@ -3399,30 +3292,24 @@ void rspamd_rcl_register_worker_option(struct rspamd_config *cfg,
return;
}
- nhandler =
- rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(struct rspamd_worker_param_parser));
- nhandler->key.name = name;
- nhandler->key.ptr = target;
- nhandler->parser.flags = flags;
- nhandler->parser.offset = offset;
- nhandler->parser.user_struct = target;
- nhandler->handler = handler;
-
- g_hash_table_insert(nparser->parsers, &nhandler->key, nhandler);
+ auto &nhandler = handler_it.first->second;
+ nhandler.parser.flags = flags;
+ nhandler.parser.offset = offset;
+ nhandler.parser.user_struct = target;
+ nhandler.handler = handler;
- doc_workers = ucl_object_lookup(cfg->doc_strings, "workers");
+ const auto *doc_workers = ucl_object_lookup(cfg->doc_strings, "workers");
- if (doc_workers == NULL) {
- doc_obj = ucl_object_typed_new(UCL_OBJECT);
+ if (doc_workers == nullptr) {
+ auto *doc_obj = ucl_object_typed_new(UCL_OBJECT);
ucl_object_insert_key(cfg->doc_strings, doc_obj, "workers", 0, false);
doc_workers = doc_obj;
}
- doc_target = ucl_object_lookup(doc_workers, g_quark_to_string(type));
+ const auto *doc_target = ucl_object_lookup(doc_workers, g_quark_to_string(type));
- if (doc_target == NULL) {
- doc_obj = ucl_object_typed_new(UCL_OBJECT);
+ if (doc_target == nullptr) {
+ auto *doc_obj = ucl_object_typed_new(UCL_OBJECT);
ucl_object_insert_key((ucl_object_t *) doc_workers, doc_obj,
g_quark_to_string(type), 0, true);
doc_target = doc_obj;
@@ -3434,41 +3321,15 @@ void rspamd_rcl_register_worker_option(struct rspamd_config *cfg,
UCL_NULL,
handler,
flags,
- NULL,
+ nullptr,
0);
}
-
-void rspamd_rcl_register_worker_parser(struct rspamd_config *cfg, gint type,
- gboolean (*func)(ucl_object_t *, gpointer), gpointer ud)
-{
- struct rspamd_worker_cfg_parser *nparser;
-
- nparser = g_hash_table_lookup(cfg->wrk_parsers, &type);
-
- if (nparser == NULL) {
- /* Allocate new parser for this worker */
- nparser =
- rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(struct rspamd_worker_cfg_parser));
- nparser->type = type;
- nparser->parsers = g_hash_table_new(rspamd_worker_param_key_hash,
- rspamd_worker_param_key_equal);
- rspamd_mempool_add_destructor(cfg->cfg_pool,
- (rspamd_mempool_destruct_t) g_hash_table_unref, nparser->parsers);
-
- g_hash_table_insert(cfg->wrk_parsers, &nparser->type, nparser);
- }
-
- nparser->def_obj_parser = func;
- nparser->def_ud = ud;
-}
-
/* Checksum functions */
static int
rspamd_rcl_emitter_append_c(unsigned char c, size_t nchars, void *ud)
{
- rspamd_cryptobox_hash_state_t *hs = ud;
+ auto *hs = (rspamd_cryptobox_hash_state_t *) ud;
guint64 d[2];
d[0] = nchars;
@@ -3482,7 +3343,7 @@ rspamd_rcl_emitter_append_c(unsigned char c, size_t nchars, void *ud)
static int
rspamd_rcl_emitter_append_len(unsigned const char *str, size_t len, void *ud)
{
- rspamd_cryptobox_hash_state_t *hs = ud;
+ auto *hs = (rspamd_cryptobox_hash_state_t *) ud;
rspamd_cryptobox_hash_update(hs, str, len);
@@ -3491,7 +3352,7 @@ rspamd_rcl_emitter_append_len(unsigned const char *str, size_t len, void *ud)
static int
rspamd_rcl_emitter_append_int(int64_t elt, void *ud)
{
- rspamd_cryptobox_hash_state_t *hs = ud;
+ auto *hs = (rspamd_cryptobox_hash_state_t *) ud;
rspamd_cryptobox_hash_update(hs, (const guchar *) &elt, sizeof(elt));
@@ -3501,36 +3362,16 @@ rspamd_rcl_emitter_append_int(int64_t elt, void *ud)
static int
rspamd_rcl_emitter_append_double(double elt, void *ud)
{
- rspamd_cryptobox_hash_state_t *hs = ud;
+ auto *hs = (rspamd_cryptobox_hash_state_t *) ud;
rspamd_cryptobox_hash_update(hs, (const guchar *) &elt, sizeof(elt));
return 0;
}
-void rspamd_rcl_section_free(gpointer p)
+void rspamd_rcl_sections_free(struct rspamd_rcl_sections_map *sections)
{
- struct rspamd_rcl_section *top = p, *cur, *tmp;
- struct rspamd_rcl_default_handler_data *dh, *dhtmp;
-
- HASH_ITER(hh, top, cur, tmp)
- {
- HASH_DEL(top, cur);
-
- if (cur->subsections) {
- rspamd_rcl_section_free(cur->subsections);
- }
-
- HASH_ITER(hh, cur->default_parser, dh, dhtmp)
- {
- HASH_DEL(cur->default_parser, dh);
- g_free(dh->key);
- g_free(dh);
- }
-
- ucl_object_unref(cur->doc_ref);
- g_free(cur);
- }
+ delete sections;
}
/**
@@ -3554,12 +3395,12 @@ void rspamd_rcl_section_free(gpointer p)
*/
void rspamd_rcl_maybe_apply_lua_transform(struct rspamd_config *cfg)
{
- lua_State *L = cfg->lua_state;
+ auto *L = RSPAMD_LUA_CFG_STATE(cfg);
gint err_idx, ret;
gchar str[PATH_MAX];
static const char *transform_script = "lua_cfg_transform";
- g_assert(L != NULL);
+ g_assert(L != nullptr);
rspamd_snprintf(str, sizeof(str), "return require \"%s\"",
transform_script);
@@ -3589,7 +3430,7 @@ void rspamd_rcl_maybe_apply_lua_transform(struct rspamd_config *cfg)
lua_pushvalue(L, -2);
/* Push the existing config */
- ucl_object_push_lua(L, cfg->rcl_obj, true);
+ ucl_object_push_lua(L, cfg->cfg_ucl_obj, true);
if ((ret = lua_pcall(L, 1, 2, err_idx)) != 0) {
msg_err("call to rspamadm lua script failed (%d): %s", ret,
@@ -3600,10 +3441,10 @@ void rspamd_rcl_maybe_apply_lua_transform(struct rspamd_config *cfg)
}
if (lua_toboolean(L, -2) && lua_type(L, -1) == LUA_TTABLE) {
- ucl_object_t *old_cfg = cfg->rcl_obj;
+ ucl_object_t *old_cfg = cfg->cfg_ucl_obj;
msg_info_config("configuration has been transformed in Lua");
- cfg->rcl_obj = ucl_object_lua_import(L, -1);
+ cfg->cfg_ucl_obj = ucl_object_lua_import(L, -1);
ucl_object_unref(old_cfg);
}
@@ -3617,8 +3458,8 @@ rspamd_rcl_decrypt_handler(struct ucl_parser *parser,
unsigned char **destination, size_t *dest_len,
void *user_data)
{
- GError *err = NULL;
- struct rspamd_cryptobox_keypair *kp = (struct rspamd_cryptobox_keypair *) user_data;
+ GError *err = nullptr;
+ auto *kp = (struct rspamd_cryptobox_keypair *) user_data;
if (!rspamd_keypair_decrypt(kp, source, source_len,
destination, dest_len, &err)) {
@@ -3637,12 +3478,11 @@ rspamd_rcl_jinja_handler(struct ucl_parser *parser,
unsigned char **destination, size_t *dest_len,
void *user_data)
{
- struct rspamd_config *cfg = (struct rspamd_config *) user_data;
- lua_State *L = cfg->lua_state;
- gint err_idx;
+ auto *cfg = (struct rspamd_config *) user_data;
+ auto *L = RSPAMD_LUA_CFG_STATE(cfg);
lua_pushcfunction(L, &rspamd_lua_traceback);
- err_idx = lua_gettop(L);
+ auto err_idx = lua_gettop(L);
/* Obtain function */
if (!rspamd_lua_require_function(L, "lua_util", "jinja_template")) {
@@ -3652,7 +3492,7 @@ rspamd_rcl_jinja_handler(struct ucl_parser *parser,
return false;
}
- lua_pushlstring(L, source, source_len);
+ lua_pushlstring(L, (const char *) source, source_len);
lua_getglobal(L, "rspamd_env");
lua_pushboolean(L, false);
@@ -3669,7 +3509,7 @@ rspamd_rcl_jinja_handler(struct ucl_parser *parser,
gsize nsize;
ndata = lua_tolstring(L, -1, &nsize);
- *destination = UCL_ALLOC(nsize);
+ *destination = (unsigned char *) UCL_ALLOC(nsize);
memcpy(*destination, ndata, nsize);
*dest_len = nsize;
}
@@ -3699,14 +3539,14 @@ void rspamd_config_calculate_cksum(struct rspamd_config *cfg)
struct ucl_emitter_functions f;
/* Calculate checksum */
- rspamd_cryptobox_hash_init(&hs, NULL, 0);
+ rspamd_cryptobox_hash_init(&hs, nullptr, 0);
f.ucl_emitter_append_character = rspamd_rcl_emitter_append_c;
f.ucl_emitter_append_double = rspamd_rcl_emitter_append_double;
f.ucl_emitter_append_int = rspamd_rcl_emitter_append_int;
f.ucl_emitter_append_len = rspamd_rcl_emitter_append_len;
- f.ucl_emitter_free_func = NULL;
+ f.ucl_emitter_free_func = nullptr;
f.ud = &hs;
- ucl_object_emit_full(cfg->rcl_obj, UCL_EMIT_MSGPACK,
+ ucl_object_emit_full(cfg->cfg_ucl_obj, UCL_EMIT_MSGPACK,
&f, cfg->config_comments);
rspamd_cryptobox_hash_final(&hs, cksumbuf);
cfg->checksum = rspamd_encode_base32(cksumbuf, sizeof(cksumbuf), RSPAMD_BASE32_DEFAULT);
@@ -3724,55 +3564,30 @@ rspamd_config_parse_ucl(struct rspamd_config *cfg,
gboolean skip_jinja,
GError **err)
{
- struct stat st;
- gint fd;
- struct ucl_parser *parser;
- gchar keypair_path[PATH_MAX];
- struct rspamd_cryptobox_keypair *decrypt_keypair = NULL;
- gchar *data;
-
- if ((fd = open(filename, O_RDONLY)) == -1) {
- g_set_error(err, cfg_rcl_error_quark(), errno,
- "cannot open %s: %s", filename, strerror(errno));
- return FALSE;
- }
- if (fstat(fd, &st) == -1) {
- g_set_error(err, cfg_rcl_error_quark(), errno,
- "cannot stat %s: %s", filename, strerror(errno));
- close(fd);
+ struct rspamd_cryptobox_keypair *decrypt_keypair = nullptr;
+ auto cfg_file_maybe = rspamd::util::raii_mmaped_file::mmap_shared(filename, O_RDONLY, PROT_READ, 0);
- return FALSE;
- }
- /* Now mmap this file to simplify reading process */
- if ((data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) {
+ if (!cfg_file_maybe) {
g_set_error(err, cfg_rcl_error_quark(), errno,
- "cannot mmap %s: %s", filename, strerror(errno));
- close(fd);
-
+ "cannot open %s: %*s", filename, (int) cfg_file_maybe.error().error_message.size(),
+ cfg_file_maybe.error().error_message.data());
return FALSE;
}
- close(fd);
+ auto &cfg_file = cfg_file_maybe.value();
/* Try to load keyfile if available */
- rspamd_snprintf(keypair_path, sizeof(keypair_path), "%s.key",
- filename);
- if ((fd = open(keypair_path, O_RDONLY)) != -1) {
- struct ucl_parser *kp_parser;
-
- kp_parser = ucl_parser_new(0);
-
- if (ucl_parser_add_fd(kp_parser, fd)) {
- ucl_object_t *kp_obj;
-
- kp_obj = ucl_parser_get_object(kp_parser);
+ rspamd::util::raii_file::open(fmt::format("{}.key", filename), O_RDONLY).map([&](const auto &keyfile) {
+ auto *kp_parser = ucl_parser_new(0);
+ if (ucl_parser_add_fd(kp_parser, keyfile.get_fd())) {
+ auto *kp_obj = ucl_parser_get_object(kp_parser);
- g_assert(kp_obj != NULL);
+ g_assert(kp_obj != nullptr);
decrypt_keypair = rspamd_keypair_from_ucl(kp_obj);
- if (decrypt_keypair == NULL) {
- msg_err_config_forced("cannot load keypair from %s: invalid keypair",
- keypair_path);
+ if (decrypt_keypair == nullptr) {
+ msg_err_config_forced("cannot load keypair from %s.key: invalid keypair",
+ filename);
}
else {
/* Add decryption support to UCL */
@@ -3784,62 +3599,52 @@ rspamd_config_parse_ucl(struct rspamd_config *cfg,
ucl_object_unref(kp_obj);
}
else {
- msg_err_config_forced("cannot load keypair from %s: %s",
- keypair_path, ucl_parser_get_error(kp_parser));
+ msg_err_config_forced("cannot load keypair from %s.key: %s",
+ filename, ucl_parser_get_error(kp_parser));
}
-
ucl_parser_free(kp_parser);
- close(fd);
- }
+ });
- parser = ucl_parser_new(UCL_PARSER_SAVE_COMMENTS);
- rspamd_ucl_add_conf_variables(parser, vars);
- rspamd_ucl_add_conf_macros(parser, cfg);
- ucl_parser_set_filevars(parser, filename, true);
+ auto parser = std::shared_ptr<ucl_parser>(ucl_parser_new(UCL_PARSER_SAVE_COMMENTS), ucl_parser_free);
+ rspamd_ucl_add_conf_variables(parser.get(), vars);
+ rspamd_ucl_add_conf_macros(parser.get(), cfg);
+ ucl_parser_set_filevars(parser.get(), filename, true);
if (inc_trace) {
- ucl_parser_set_include_tracer(parser, inc_trace, trace_data);
+ ucl_parser_set_include_tracer(parser.get(), inc_trace, trace_data);
}
if (decrypt_keypair) {
- struct ucl_parser_special_handler *decrypt_handler;
-
- decrypt_handler = rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(*decrypt_handler));
+ auto *decrypt_handler = rspamd_mempool_alloc0_type(cfg->cfg_pool,
+ struct ucl_parser_special_handler);
decrypt_handler->user_data = decrypt_keypair;
decrypt_handler->magic = encrypted_magic;
decrypt_handler->magic_len = sizeof(encrypted_magic);
decrypt_handler->handler = rspamd_rcl_decrypt_handler;
decrypt_handler->free_function = rspamd_rcl_decrypt_free;
- ucl_parser_add_special_handler(parser, decrypt_handler);
+ ucl_parser_add_special_handler(parser.get(), decrypt_handler);
}
if (!skip_jinja) {
- struct ucl_parser_special_handler *jinja_handler;
-
- jinja_handler = rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(*jinja_handler));
+ auto *jinja_handler = rspamd_mempool_alloc0_type(cfg->cfg_pool,
+ struct ucl_parser_special_handler);
jinja_handler->user_data = cfg;
jinja_handler->flags = UCL_SPECIAL_HANDLER_PREPROCESS_ALL;
jinja_handler->handler = rspamd_rcl_jinja_handler;
- ucl_parser_add_special_handler(parser, jinja_handler);
+ ucl_parser_add_special_handler(parser.get(), jinja_handler);
}
- if (!ucl_parser_add_chunk(parser, data, st.st_size)) {
+ if (!ucl_parser_add_chunk(parser.get(), (unsigned char *) cfg_file.get_map(), cfg_file.get_size())) {
g_set_error(err, cfg_rcl_error_quark(), errno,
- "ucl parser error: %s", ucl_parser_get_error(parser));
- ucl_parser_free(parser);
- munmap(data, st.st_size);
+ "ucl parser error: %s", ucl_parser_get_error(parser.get()));
return FALSE;
}
- munmap(data, st.st_size);
- cfg->rcl_obj = ucl_parser_get_object(parser);
- cfg->config_comments = ucl_object_ref(ucl_parser_get_comments(parser));
- ucl_parser_free(parser);
+ cfg->cfg_ucl_obj = ucl_parser_get_object(parser.get());
+ cfg->config_comments = ucl_object_ref(ucl_parser_get_comments(parser.get()));
return TRUE;
}
@@ -3853,45 +3658,45 @@ rspamd_config_read(struct rspamd_config *cfg,
gboolean skip_jinja,
gchar **lua_env)
{
- GError *err = NULL;
- struct rspamd_rcl_section *top, *logger_section;
- const ucl_object_t *logger_obj;
+ GError *err = nullptr;
- rspamd_lua_set_path(cfg->lua_state, NULL, vars);
+ rspamd_lua_set_path(RSPAMD_LUA_CFG_STATE(cfg), nullptr, vars);
- if (!rspamd_lua_set_env(cfg->lua_state, vars, lua_env, &err)) {
+ if (!rspamd_lua_set_env(RSPAMD_LUA_CFG_STATE(cfg), vars, lua_env, &err)) {
msg_err_config_forced("failed to set up environment: %e", err);
g_error_free(err);
return FALSE;
}
- if (!rspamd_config_parse_ucl(cfg, filename, vars, NULL, NULL, skip_jinja, &err)) {
+ if (!rspamd_config_parse_ucl(cfg, filename, vars, nullptr, nullptr, skip_jinja, &err)) {
msg_err_config_forced("failed to load config: %e", err);
g_error_free(err);
return FALSE;
}
- top = rspamd_rcl_config_init(cfg, NULL);
+ auto *top = rspamd_rcl_config_init(cfg, nullptr);
+ cfg->rcl_top_section = top;
/* Add new paths if defined in options */
- rspamd_lua_set_path(cfg->lua_state, cfg->rcl_obj, vars);
- rspamd_lua_set_globals(cfg, cfg->lua_state);
- rspamd_mempool_add_destructor(cfg->cfg_pool, rspamd_rcl_section_free, top);
- err = NULL;
+ rspamd_lua_set_path(RSPAMD_LUA_CFG_STATE(cfg), cfg->cfg_ucl_obj, vars);
+ rspamd_lua_set_globals(cfg, RSPAMD_LUA_CFG_STATE(cfg));
+ rspamd_mempool_add_destructor(cfg->cfg_pool, (rspamd_mempool_destruct_t) rspamd_rcl_sections_free, top);
+ err = nullptr;
- if (logger_fin != NULL) {
- HASH_FIND_STR(top, "logging", logger_section);
+ /* Pre-init logging if possible */
+ if (logger_fin != nullptr) {
+ auto logging_section_maybe = rspamd::find_map(top->sections, "logging");
- if (logger_section != NULL) {
- logger_obj = ucl_object_lookup_any(cfg->rcl_obj, "logging",
- "logger", NULL);
+ if (logging_section_maybe) {
+ const auto *logger_obj = ucl_object_lookup_any(cfg->cfg_ucl_obj, "logging",
+ "logger", nullptr);
- if (logger_obj == NULL) {
+ if (logger_obj == nullptr) {
logger_fin(cfg->cfg_pool, logger_ud);
}
else {
- if (!rspamd_rcl_process_section(cfg, logger_section, cfg,
+ if (!rspamd_rcl_process_section(cfg, *logging_section_maybe.value().get().get(), cfg,
logger_obj, cfg->cfg_pool, &err)) {
msg_err_config_forced("cannot init logger: %e", err);
g_error_free(err);
@@ -3903,38 +3708,32 @@ rspamd_config_read(struct rspamd_config *cfg,
}
/* Init lua logging */
- lua_State *L = cfg->lua_state;
- gint err_idx;
- struct rspamd_config **pcfg;
-
- lua_pushcfunction(L, &rspamd_lua_traceback);
- err_idx = lua_gettop(L);
+ lua_pushcfunction(RSPAMD_LUA_CFG_STATE(cfg), &rspamd_lua_traceback);
+ auto err_idx = lua_gettop(RSPAMD_LUA_CFG_STATE(cfg));
/* Obtain function */
- if (!rspamd_lua_require_function(L, "lua_util",
+ if (!rspamd_lua_require_function(RSPAMD_LUA_CFG_STATE(cfg), "lua_util",
"init_debug_logging")) {
msg_err_config("cannot require lua_util.init_debug_logging");
- lua_settop(L, err_idx - 1);
+ lua_settop(RSPAMD_LUA_CFG_STATE(cfg), err_idx - 1);
return FALSE;
}
- pcfg = lua_newuserdata(L, sizeof(*pcfg));
- *pcfg = cfg;
- rspamd_lua_setclass(L, "rspamd{config}", -1);
+ void *pcfg = lua_newuserdata(RSPAMD_LUA_CFG_STATE(cfg), sizeof(void *));
+ memcpy(pcfg, &cfg, sizeof(void *));
+ rspamd_lua_setclass(RSPAMD_LUA_CFG_STATE(cfg), "rspamd{config}", -1);
- if (lua_pcall(L, 1, 0, err_idx) != 0) {
+ if (lua_pcall(RSPAMD_LUA_CFG_STATE(cfg), 1, 0, err_idx) != 0) {
msg_err_config("cannot call lua init_debug_logging script: %s",
- lua_tostring(L, -1));
- lua_settop(L, err_idx - 1);
+ lua_tostring(RSPAMD_LUA_CFG_STATE(cfg), -1));
+ lua_settop(RSPAMD_LUA_CFG_STATE(cfg), err_idx - 1);
return FALSE;
}
- lua_settop(L, err_idx - 1);
+ lua_settop(RSPAMD_LUA_CFG_STATE(cfg), err_idx - 1);
}
-
- HASH_DEL(top, logger_section);
}
}
@@ -3942,7 +3741,7 @@ rspamd_config_read(struct rspamd_config *cfg,
rspamd_rcl_maybe_apply_lua_transform(cfg);
rspamd_config_calculate_cksum(cfg);
- if (!rspamd_rcl_parse(top, cfg, cfg, cfg->cfg_pool, cfg->rcl_obj, &err)) {
+ if (!rspamd_rcl_parse(top, cfg, cfg, cfg->cfg_pool, cfg->cfg_ucl_obj, &err)) {
msg_err_config("rcl parse error: %e", err);
if (err) {
@@ -3965,16 +3764,8 @@ rspamd_rcl_doc_obj_from_handler(ucl_object_t *doc_obj,
rspamd_rcl_default_handler_t handler,
gint flags)
{
- gboolean has_example = FALSE, has_type = FALSE;
- const gchar *type = NULL;
-
- if (ucl_object_lookup(doc_obj, "example") != NULL) {
- has_example = TRUE;
- }
-
- if (ucl_object_lookup(doc_obj, "type") != NULL) {
- has_type = TRUE;
- }
+ auto has_example = ucl_object_lookup(doc_obj, "example") != nullptr;
+ auto has_type = ucl_object_lookup(doc_obj, "type") != nullptr;
if (handler == rspamd_rcl_parse_struct_string) {
if (!has_type) {
@@ -3983,7 +3774,7 @@ rspamd_rcl_doc_obj_from_handler(ucl_object_t *doc_obj,
}
}
else if (handler == rspamd_rcl_parse_struct_integer) {
- type = "int";
+ auto *type = "int";
if (flags & RSPAMD_CL_FLAG_INT_16) {
type = "int16";
@@ -4013,7 +3804,7 @@ rspamd_rcl_doc_obj_from_handler(ucl_object_t *doc_obj,
}
}
else if (handler == rspamd_rcl_parse_struct_time) {
- type = "time";
+ auto *type = "time";
if (!has_type) {
ucl_object_insert_key(doc_obj, ucl_object_fromstring(type),
@@ -4029,7 +3820,7 @@ rspamd_rcl_doc_obj_from_handler(ucl_object_t *doc_obj,
ucl_object_insert_key(doc_obj,
ucl_object_fromstring_common("param = \"str1, str2, str3\" OR "
"param = [\"str1\", \"str2\", \"str3\"]",
- 0, 0),
+ 0, static_cast<ucl_string_flags>(0)),
"example",
0,
false);
@@ -4095,8 +3886,8 @@ rspamd_rcl_add_doc_obj(ucl_object_t *doc_target,
{
ucl_object_t *doc_obj;
- if (doc_target == NULL || doc_name == NULL) {
- return NULL;
+ if (doc_target == nullptr || doc_name == nullptr) {
+ return nullptr;
}
doc_obj = ucl_object_typed_new(UCL_OBJECT);
@@ -4104,7 +3895,7 @@ rspamd_rcl_add_doc_obj(ucl_object_t *doc_target,
/* Insert doc string itself */
if (doc_string) {
ucl_object_insert_key(doc_obj,
- ucl_object_fromstring_common(doc_string, 0, 0),
+ ucl_object_fromstring_common(doc_string, 0, static_cast<ucl_string_flags>(0)),
"data", 0, false);
}
else {
@@ -4126,7 +3917,7 @@ rspamd_rcl_add_doc_obj(ucl_object_t *doc_target,
if (default_value) {
ucl_object_insert_key(doc_obj,
- ucl_object_fromstring_common(default_value, 0, 0),
+ ucl_object_fromstring_common(default_value, 0, static_cast<ucl_string_flags>(0)),
"default", 0, false);
}
@@ -4146,11 +3937,9 @@ rspamd_rcl_add_doc_by_path(struct rspamd_config *cfg,
const char *default_value,
gboolean required)
{
- const ucl_object_t *found, *cur;
- ucl_object_t *obj;
- gchar **path_components, **comp;
+ const auto *cur = cfg->doc_strings;
- if (doc_path == NULL) {
+ if (doc_path == nullptr) {
/* Assume top object */
return rspamd_rcl_add_doc_obj(cfg->doc_strings,
doc_string,
@@ -4162,9 +3951,9 @@ rspamd_rcl_add_doc_by_path(struct rspamd_config *cfg,
required);
}
else {
- found = ucl_object_lookup_path(cfg->doc_strings, doc_path);
+ const auto *found = ucl_object_lookup_path(cfg->doc_strings, doc_path);
- if (found != NULL) {
+ if (found != nullptr) {
return rspamd_rcl_add_doc_obj((ucl_object_t *) found,
doc_string,
doc_name,
@@ -4176,35 +3965,25 @@ rspamd_rcl_add_doc_by_path(struct rspamd_config *cfg,
}
/* Otherwise we need to insert all components of the path */
- path_components = g_strsplit_set(doc_path, ".", -1);
- cur = cfg->doc_strings;
-
- for (comp = path_components; *comp != NULL; comp++) {
+ rspamd::string_foreach_delim(doc_path, ".", [&](const std::string_view &elt) {
if (ucl_object_type(cur) != UCL_OBJECT) {
- msg_err_config("Bad path while lookup for '%s' at %s",
- doc_path, *comp);
- g_strfreev(path_components);
-
- return NULL;
+ msg_err_config("Bad path while lookup for '%s' at %*s",
+ doc_path, (int) elt.size(), elt.data());
}
-
- found = ucl_object_lookup(cur, *comp);
-
- if (found == NULL) {
- obj = ucl_object_typed_new(UCL_OBJECT);
+ const auto *found = ucl_object_lookup_len(cur, elt.data(), elt.size());
+ if (found == nullptr) {
+ auto *obj = ucl_object_typed_new(UCL_OBJECT);
ucl_object_insert_key((ucl_object_t *) cur,
obj,
- *comp,
- 0,
+ elt.data(),
+ elt.size(),
true);
cur = obj;
}
else {
cur = found;
}
- }
-
- g_strfreev(path_components);
+ });
}
return rspamd_rcl_add_doc_obj(ucl_object_ref(cur),
@@ -4222,18 +4001,18 @@ rspamd_rcl_add_doc_from_comments(struct rspamd_config *cfg,
ucl_object_t *top_doc, const ucl_object_t *obj,
const ucl_object_t *comments, gboolean is_top)
{
- ucl_object_iter_t it = NULL;
+ ucl_object_iter_t it = nullptr;
const ucl_object_t *cur, *cmt;
ucl_object_t *cur_doc;
if (ucl_object_type(obj) == UCL_OBJECT) {
- while ((cur = ucl_object_iterate(obj, &it, true)) != NULL) {
- cur_doc = NULL;
+ while ((cur = ucl_object_iterate(obj, &it, true)) != nullptr) {
+ cur_doc = nullptr;
- if ((cmt = ucl_comments_find(comments, cur)) != NULL) {
+ if ((cmt = ucl_comments_find(comments, cur)) != nullptr) {
cur_doc = rspamd_rcl_add_doc_obj(top_doc,
ucl_object_tostring(cmt), ucl_object_key(cur),
- ucl_object_type(cur), NULL, 0, NULL, FALSE);
+ ucl_object_type(cur), nullptr, 0, nullptr, FALSE);
}
if (ucl_object_type(cur) == UCL_OBJECT) {
@@ -4251,10 +4030,10 @@ rspamd_rcl_add_doc_from_comments(struct rspamd_config *cfg,
}
}
else if (!is_top) {
- if ((cmt = ucl_comments_find(comments, obj)) != NULL) {
+ if ((cmt = ucl_comments_find(comments, obj)) != nullptr) {
rspamd_rcl_add_doc_obj(top_doc,
ucl_object_tostring(cmt), ucl_object_key(obj),
- ucl_object_type(obj), NULL, 0, NULL, FALSE);
+ ucl_object_type(obj), nullptr, 0, nullptr, FALSE);
}
}
}
@@ -4266,28 +4045,23 @@ rspamd_rcl_add_doc_by_example(struct rspamd_config *cfg,
const gchar *doc_name,
const gchar *example_data, gsize example_len)
{
- struct ucl_parser *parser;
- ucl_object_t *top, *top_doc;
- const ucl_object_t *comments;
-
- parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS | UCL_PARSER_SAVE_COMMENTS);
+ auto parser = std::shared_ptr<ucl_parser>(ucl_parser_new(UCL_PARSER_NO_FILEVARS | UCL_PARSER_SAVE_COMMENTS), ucl_parser_free);
- if (!ucl_parser_add_chunk(parser, example_data, example_len)) {
+ if (!ucl_parser_add_chunk(parser.get(), reinterpret_cast<const unsigned char *>(example_data), example_len)) {
msg_err_config("cannot parse example: %s",
- ucl_parser_get_error(parser));
- ucl_parser_free(parser);
+ ucl_parser_get_error(parser.get()));
- return NULL;
+ return nullptr;
}
- top = ucl_parser_get_object(parser);
- comments = ucl_parser_get_comments(parser);
+ auto *top = ucl_parser_get_object(parser.get());
+ const auto *comments = ucl_parser_get_comments(parser.get());
/* Add top object */
- top_doc = rspamd_rcl_add_doc_by_path(cfg, root_path, doc_string,
- doc_name, ucl_object_type(top), NULL, 0, NULL, FALSE);
+ auto *top_doc = rspamd_rcl_add_doc_by_path(cfg, root_path, doc_string,
+ doc_name, ucl_object_type(top), nullptr, 0, nullptr, FALSE);
ucl_object_insert_key(top_doc,
- ucl_object_fromstring_common(example_data, example_len, 0),
+ ucl_object_fromstring_common(example_data, example_len, static_cast<ucl_string_flags>(0)),
"example", 0, false);
rspamd_rcl_add_doc_from_comments(cfg, top_doc, top, comments, TRUE);
diff --git a/src/libserver/cfg_rcl.h b/src/libserver/cfg_rcl.h
index 6bbeda0e6..766c55e83 100644
--- a/src/libserver/cfg_rcl.h
+++ b/src/libserver/cfg_rcl.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -33,6 +33,7 @@ extern "C" {
#endif
struct rspamd_rcl_section;
+struct rspamd_rcl_sections_map;
struct rspamd_config;
struct rspamd_rcl_default_handler_data;
@@ -59,7 +60,7 @@ struct rspamd_rcl_struct_parser {
struct rspamd_config *cfg;
gpointer user_struct;
goffset offset;
- enum rspamd_rcl_flag flags;
+ int flags; /* enum rspamd_rcl_flag */
};
@@ -120,13 +121,18 @@ struct rspamd_rcl_default_handler_data *rspamd_rcl_add_default_handler(
* @return newly created structure
*/
struct rspamd_rcl_section *rspamd_rcl_add_section(
- struct rspamd_rcl_section **top,
- const gchar *name, const gchar *key_attr,
+ struct rspamd_rcl_sections_map **top,
+ struct rspamd_rcl_section *parent_section,
+ const gchar *name,
+ const gchar *key_attr,
rspamd_rcl_handler_t handler,
- enum ucl_type type, gboolean required, gboolean strict_type);
+ enum ucl_type type,
+ gboolean required,
+ gboolean strict_type);
struct rspamd_rcl_section *rspamd_rcl_add_section_doc(
- struct rspamd_rcl_section **top,
+ struct rspamd_rcl_sections_map **top,
+ struct rspamd_rcl_section *parent_section,
const gchar *name, const gchar *key_attr,
rspamd_rcl_handler_t handler,
enum ucl_type type, gboolean required,
@@ -138,18 +144,8 @@ struct rspamd_rcl_section *rspamd_rcl_add_section_doc(
* Init common sections known to rspamd
* @return top section
*/
-struct rspamd_rcl_section *rspamd_rcl_config_init(struct rspamd_config *cfg,
- GHashTable *skip_sections);
-
-/**
- * Get a section specified by path, it understand paths separated by '/' character
- * @param top top section
- * @param path '/' divided path
- * @return
- */
-struct rspamd_rcl_section *rspamd_rcl_config_get_section(
- struct rspamd_rcl_section *top,
- const char *path);
+struct rspamd_rcl_sections_map *rspamd_rcl_config_init(struct rspamd_config *cfg,
+ GHashTable *skip_sections);
/**
* Parse configuration
@@ -161,25 +157,11 @@ struct rspamd_rcl_section *rspamd_rcl_config_get_section(
* @param err error pointer
* @return
*/
-gboolean rspamd_rcl_parse(struct rspamd_rcl_section *top,
+gboolean rspamd_rcl_parse(struct rspamd_rcl_sections_map *top,
struct rspamd_config *cfg,
gpointer ptr, rspamd_mempool_t *pool,
const ucl_object_t *obj, GError **err);
-
-/**
- * Parse default structure for a section
- * @param section section
- * @param cfg config file
- * @param obj object to parse
- * @param ptr ptr to pass
- * @param err error ptr
- * @return TRUE if the object has been parsed
- */
-gboolean rspamd_rcl_section_parse_defaults(struct rspamd_config *cfg,
- struct rspamd_rcl_section *section,
- rspamd_mempool_t *pool, const ucl_object_t *obj, gpointer ptr,
- GError **err);
/**
* Here is a section of common handlers that accepts rcl_struct_parser
* which itself contains a struct pointer and the offset of a member in a
@@ -376,16 +358,6 @@ void rspamd_rcl_register_worker_option(struct rspamd_config *cfg,
const gchar *doc_string);
/**
- * Register a default parser for a worker
- * @param cfg config structure
- * @param type type of worker (GQuark)
- * @param func handler function
- * @param ud userdata for handler function
- */
-void rspamd_rcl_register_worker_parser(struct rspamd_config *cfg, gint type,
- gboolean (*func)(ucl_object_t *, gpointer), gpointer ud);
-
-/**
* Adds new documentation object to the configuration
* @param doc_target target object where to insert documentation (top object is used if this is NULL)
* @param doc_object documentation object to insert
@@ -448,10 +420,10 @@ ucl_object_t *rspamd_rcl_add_doc_by_example(struct rspamd_config *cfg,
* @param err
* @return
*/
-gboolean rspamd_rcl_add_lua_plugins_path(struct rspamd_config *cfg,
+gboolean rspamd_rcl_add_lua_plugins_path(struct rspamd_rcl_sections_map *sections,
+ struct rspamd_config *cfg,
const gchar *path,
gboolean main_path,
- GHashTable *modules_seen,
GError **err);
@@ -475,7 +447,7 @@ gboolean rspamd_rcl_add_lua_plugins_path(struct rspamd_config *cfg,
* @param cfg
*/
void rspamd_rcl_maybe_apply_lua_transform(struct rspamd_config *cfg);
-void rspamd_rcl_section_free(gpointer p);
+void rspamd_rcl_sections_free(struct rspamd_rcl_sections_map *sections);
void rspamd_config_calculate_cksum(struct rspamd_config *cfg);
diff --git a/src/libserver/cfg_utils.c b/src/libserver/cfg_utils.cxx
index cdb1518a8..5c5a8a24b 100644
--- a/src/libserver/cfg_utils.c
+++ b/src/libserver/cfg_utils.cxx
@@ -15,12 +15,13 @@
*/
#include "config.h"
+#include "lua/lua_common.h"
+#include "lua/lua_thread_pool.h"
+
#include "cfg_file.h"
#include "rspamd.h"
#include "cfg_file_private.h"
-#include "scan_result.h"
-#include "lua/lua_common.h"
-#include "lua/lua_thread_pool.h"
+
#include "maps/map.h"
#include "maps/map_helpers.h"
#include "maps/map_private.h"
@@ -61,6 +62,15 @@
#include "blas-config.h"
+#include <string>
+#include <string_view>
+#include <vector>
+#include "fmt/core.h"
+#include "cxx/util.hxx"
+#include "frozen/unordered_map.h"
+#include "frozen/string.h"
+#include "contrib/ankerl/unordered_dense.h"
+
#define DEFAULT_SCORE 10.0
#define DEFAULT_RLIMIT_NOFILE 2048
@@ -84,7 +94,12 @@
struct rspamd_ucl_map_cbdata {
struct rspamd_config *cfg;
- GString *buf;
+ std::string buf;
+
+ explicit rspamd_ucl_map_cbdata(struct rspamd_config *cfg)
+ : cfg(cfg)
+ {
+ }
};
static gchar *rspamd_ucl_read_cb(gchar *chunk,
gint len,
@@ -99,6 +114,51 @@ RSPAMD_CONSTRUCTOR(rspamd_config_log_init)
rspamd_config_log_id = rspamd_logger_add_debug_module("config");
}
+struct rspamd_actions_list {
+ using action_ptr = std::shared_ptr<rspamd_action>;
+ std::vector<action_ptr> actions;
+ ankerl::unordered_dense::map<std::string_view, action_ptr> actions_by_name;
+
+ explicit rspamd_actions_list()
+ {
+ actions.reserve(METRIC_ACTION_MAX + 2);
+ actions_by_name.reserve(METRIC_ACTION_MAX + 2);
+ }
+
+ void add_action(action_ptr action)
+ {
+ actions.push_back(action);
+ actions_by_name[action->name] = action;
+ sort();
+ }
+
+ void sort()
+ {
+ std::sort(actions.begin(), actions.end(), [](const action_ptr &a1, const action_ptr &a2) -> bool {
+ if (!isnan(a1->threshold) && !isnan(a2->threshold)) {
+ return a1->threshold < a2->threshold;
+ }
+
+ if (isnan(a1->threshold) && isnan(a2->threshold)) {
+ return false;
+ }
+ else if (isnan(a1->threshold)) {
+ return true;
+ }
+
+ return false;
+ });
+ }
+
+ void clear()
+ {
+ actions.clear();
+ actions_by_name.clear();
+ }
+};
+
+#define RSPAMD_CFG_ACTIONS(cfg) (reinterpret_cast<rspamd_actions_list *>((cfg)->actions))
+
gboolean
rspamd_parse_bind_line(struct rspamd_config *cfg,
struct rspamd_worker_conf *cf,
@@ -108,25 +168,29 @@ rspamd_parse_bind_line(struct rspamd_config *cfg,
const gchar *fdname;
gboolean ret = TRUE;
- if (str == NULL) {
+ if (str == nullptr) {
return FALSE;
}
- cnf = g_malloc0(sizeof(struct rspamd_worker_bind_conf));
+ cnf = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_worker_bind_conf);
cnf->cnt = 1024;
- cnf->bind_line = g_strdup(str);
+ cnf->bind_line = rspamd_mempool_strdup(cfg->cfg_pool, str);
+
+ auto bind_line = std::string_view{cnf->bind_line};
- if (g_ascii_strncasecmp(str, "systemd:", sizeof("systemd:") - 1) == 0) {
+ if (bind_line.starts_with("systemd:")) {
/* The actual socket will be passed by systemd environment */
fdname = str + sizeof("systemd:") - 1;
cnf->is_systemd = TRUE;
- cnf->addrs = g_ptr_array_new_full(1, g_free);
+ cnf->addrs = g_ptr_array_new_full(1, nullptr);
+ rspamd_mempool_add_destructor(cfg->cfg_pool,
+ rspamd_ptr_array_free_hard, cnf->addrs);
if (fdname[0]) {
- g_ptr_array_add(cnf->addrs, g_strdup(fdname));
+ g_ptr_array_add(cnf->addrs, rspamd_mempool_strdup(cfg->cfg_pool, fdname));
cnf->cnt = cnf->addrs->len;
- cnf->name = g_strdup(str);
+ cnf->name = rspamd_mempool_strdup(cfg->cfg_pool, str);
LL_PREPEND(cf->bind_conf, cnf);
}
else {
@@ -136,7 +200,7 @@ rspamd_parse_bind_line(struct rspamd_config *cfg,
}
else {
if (rspamd_parse_host_port_priority(str, &cnf->addrs,
- NULL, &cnf->name, DEFAULT_BIND_PORT, TRUE, NULL) == RSPAMD_PARSE_ADDR_FAIL) {
+ nullptr, &cnf->name, DEFAULT_BIND_PORT, TRUE, cfg->cfg_pool) == RSPAMD_PARSE_ADDR_FAIL) {
msg_err_config("cannot parse bind line: %s", str);
ret = FALSE;
}
@@ -146,15 +210,6 @@ rspamd_parse_bind_line(struct rspamd_config *cfg,
}
}
- if (!ret) {
- if (cnf->addrs) {
- g_ptr_array_free(cnf->addrs, TRUE);
- }
-
- g_free(cnf->name);
- g_free(cnf);
- }
-
return ret;
}
@@ -174,15 +229,16 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
cfg->dns_io_per_server = 16;
cfg->unknown_weight = NAN;
+ cfg->actions = (void *) new rspamd_actions_list();
+
/* Add all internal actions to keep compatibility */
for (int i = METRIC_ACTION_REJECT; i < METRIC_ACTION_MAX; i++) {
- struct rspamd_action *action;
- action = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*action));
+ auto &&action = std::make_shared<rspamd_action>();
action->threshold = NAN;
action->name = rspamd_mempool_strdup(cfg->cfg_pool,
- rspamd_action_to_str(i));
- action->action_type = i;
+ rspamd_action_to_str(static_cast<rspamd_action_type>(i)));
+ action->action_type = static_cast<rspamd_action_type>(i);
if (i == METRIC_ACTION_SOFT_REJECT) {
action->flags |= RSPAMD_ACTION_NO_THRESHOLD | RSPAMD_ACTION_HAM;
@@ -194,8 +250,7 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
action->flags |= RSPAMD_ACTION_HAM;
}
- HASH_ADD_KEYPTR(hh, cfg->actions,
- action->name, strlen(action->name), action);
+ RSPAMD_CFG_ACTIONS(cfg)->add_action(std::move(action));
}
/* Disable timeout */
@@ -209,7 +264,6 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
cfg->cfg_params = g_hash_table_new(rspamd_str_hash, rspamd_str_equal);
cfg->debug_modules = g_hash_table_new(rspamd_str_hash, rspamd_str_equal);
cfg->explicit_modules = g_hash_table_new(rspamd_str_hash, rspamd_str_equal);
- cfg->wrk_parsers = g_hash_table_new(g_int_hash, g_int_equal);
cfg->trusted_keys = g_hash_table_new(rspamd_str_hash,
rspamd_str_equal);
@@ -233,11 +287,12 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
cfg->max_opts_len = 4096;
/* Default log line */
- cfg->log_format_str = "id: <$mid>,$if_qid{ qid: <$>,}$if_ip{ ip: $,}"
- "$if_user{ user: $,}$if_smtp_from{ from: <$>,} (default: $is_spam "
- "($action): [$scores] [$symbols_scores_params]), len: $len, time: $time_real, "
- "dns req: $dns_req, digest: <$digest>"
- "$if_smtp_rcpts{ rcpts: <$>, }$if_mime_rcpt{ mime_rcpt: <$>, }";
+ cfg->log_format_str = rspamd_mempool_strdup(cfg->cfg_pool,
+ "id: <$mid>,$if_qid{ qid: <$>,}$if_ip{ ip: $,}"
+ "$if_user{ user: $,}$if_smtp_from{ from: <$>,} (default: $is_spam "
+ "($action): [$scores] [$symbols_scores_params]), len: $len, time: $time_real, "
+ "dns req: $dns_req, digest: <$digest>"
+ "$if_smtp_rcpts{ rcpts: <$>, }$if_mime_rcpt{ mime_rcpt: <$>, }");
/* Allow non-mime input by default */
cfg->allow_raw_input = TRUE;
/* Default maximum words processed */
@@ -252,12 +307,12 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
cfg->full_gc_iters = DEFAULT_GC_MAXITERS;
/* Default hyperscan cache */
- cfg->hs_cache_dir = RSPAMD_DBDIR "/";
+ cfg->hs_cache_dir = rspamd_mempool_strdup(cfg->cfg_pool, RSPAMD_DBDIR "/");
if (!(flags & RSPAMD_CONFIG_INIT_SKIP_LUA)) {
- cfg->lua_state = rspamd_lua_init(flags & RSPAMD_CONFIG_INIT_WIPE_LUA_MEM);
+ cfg->lua_state = (void *) rspamd_lua_init(flags & RSPAMD_CONFIG_INIT_WIPE_LUA_MEM);
cfg->own_lua_state = TRUE;
- cfg->lua_thread_pool = lua_thread_pool_new(cfg->lua_state);
+ cfg->lua_thread_pool = (void *) lua_thread_pool_new(RSPAMD_LUA_CFG_STATE(cfg));
}
cfg->cache = rspamd_symcache_new(cfg);
@@ -269,7 +324,7 @@ rspamd_config_new(enum rspamd_config_init_flags flags)
*/
cfg->enable_shutdown_workaround = TRUE;
- cfg->ssl_ciphers = "HIGH:!aNULL:!kRSA:!PSK:!SRP:!MD5:!RC4";
+ cfg->ssl_ciphers = rspamd_mempool_strdup(cfg->cfg_pool, "HIGH:!anullptr:!kRSA:!PSK:!SRP:!MD5:!RC4");
cfg->max_message = DEFAULT_MAX_MESSAGE;
cfg->max_pic_size = DEFAULT_MAX_PIC;
cfg->images_cache_size = 256;
@@ -295,27 +350,27 @@ void rspamd_config_free(struct rspamd_config *cfg)
struct rspamd_config_settings_elt *set, *stmp;
struct rspamd_worker_log_pipe *lp, *ltmp;
- rspamd_lua_run_config_unload(cfg->lua_state, cfg);
+ rspamd_lua_run_config_unload(RSPAMD_LUA_CFG_STATE(cfg), cfg);
/* Scripts part */
DL_FOREACH_SAFE(cfg->on_term_scripts, sc, sctmp)
{
- luaL_unref(cfg->lua_state, LUA_REGISTRYINDEX, sc->cbref);
+ luaL_unref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX, sc->cbref);
}
DL_FOREACH_SAFE(cfg->on_load_scripts, sc, sctmp)
{
- luaL_unref(cfg->lua_state, LUA_REGISTRYINDEX, sc->cbref);
+ luaL_unref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX, sc->cbref);
}
DL_FOREACH_SAFE(cfg->post_init_scripts, sc, sctmp)
{
- luaL_unref(cfg->lua_state, LUA_REGISTRYINDEX, sc->cbref);
+ luaL_unref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX, sc->cbref);
}
DL_FOREACH_SAFE(cfg->config_unload_scripts, sc, sctmp)
{
- luaL_unref(cfg->lua_state, LUA_REGISTRYINDEX, sc->cbref);
+ luaL_unref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX, sc->cbref);
}
DL_FOREACH_SAFE(cfg->setting_ids, set, stmp)
@@ -329,7 +384,7 @@ void rspamd_config_free(struct rspamd_config *cfg)
g_list_free(cfg->classifiers);
g_list_free(cfg->workers);
rspamd_symcache_destroy(cfg->cache);
- ucl_object_unref(cfg->rcl_obj);
+ ucl_object_unref(cfg->cfg_ucl_obj);
ucl_object_unref(cfg->config_comments);
ucl_object_unref(cfg->doc_strings);
ucl_object_unref(cfg->neighbours);
@@ -338,7 +393,6 @@ void rspamd_config_free(struct rspamd_config *cfg)
g_hash_table_unref(cfg->classifiers_symbols);
g_hash_table_unref(cfg->debug_modules);
g_hash_table_unref(cfg->explicit_modules);
- g_hash_table_unref(cfg->wrk_parsers);
g_hash_table_unref(cfg->trusted_keys);
rspamd_re_cache_unref(cfg->re_cache);
@@ -348,9 +402,9 @@ void rspamd_config_free(struct rspamd_config *cfg)
rspamd_monitored_ctx_destroy(cfg->monitored_ctx);
}
- if (cfg->lua_state && cfg->own_lua_state) {
- lua_thread_pool_free(cfg->lua_thread_pool);
- rspamd_lua_close(cfg->lua_state);
+ if (RSPAMD_LUA_CFG_STATE(cfg) && cfg->own_lua_state) {
+ lua_thread_pool_free((struct lua_thread_pool *) cfg->lua_thread_pool);
+ rspamd_lua_close(RSPAMD_LUA_CFG_STATE(cfg));
}
if (cfg->redis_pool) {
@@ -358,7 +412,7 @@ void rspamd_config_free(struct rspamd_config *cfg)
}
rspamd_upstreams_library_unref(cfg->ups_ctx);
- HASH_CLEAR(hh, cfg->actions);
+ delete RSPAMD_CFG_ACTIONS(cfg);
rspamd_mempool_destructors_enforce(cfg->cfg_pool);
@@ -382,10 +436,10 @@ rspamd_config_get_module_opt(struct rspamd_config *cfg,
const gchar *module_name,
const gchar *opt_name)
{
- const ucl_object_t *res = NULL, *sec;
+ const ucl_object_t *res = nullptr, *sec;
- sec = ucl_obj_get_key(cfg->rcl_obj, module_name);
- if (sec != NULL) {
+ sec = ucl_obj_get_key(cfg->cfg_ucl_obj, module_name);
+ if (sec != nullptr) {
res = ucl_obj_get_key(sec, opt_name);
}
@@ -445,173 +499,123 @@ gint rspamd_config_parse_flag(const gchar *str, guint len)
return -1;
}
+// A mapping between names and log format types + flags
+constexpr const auto config_vars = frozen::make_unordered_map<frozen::string, std::pair<rspamd_log_format_type, int>>({
+ {"mid", {RSPAMD_LOG_MID, 0}},
+ {"qid", {RSPAMD_LOG_QID, 0}},
+ {"user", {RSPAMD_LOG_USER, 0}},
+ {"ip", {RSPAMD_LOG_IP, 0}},
+ {"len", {RSPAMD_LOG_LEN, 0}},
+ {"dns_req", {RSPAMD_LOG_DNS_REQ, 0}},
+ {"smtp_from", {RSPAMD_LOG_SMTP_FROM, 0}},
+ {"mime_from", {RSPAMD_LOG_MIME_FROM, 0}},
+ {"smtp_rcpt", {RSPAMD_LOG_SMTP_RCPT, 0}},
+ {"mime_rcpt", {RSPAMD_LOG_MIME_RCPT, 0}},
+ {"smtp_rcpts", {RSPAMD_LOG_SMTP_RCPTS, 0}},
+ {"mime_rcpts", {RSPAMD_LOG_MIME_RCPTS, 0}},
+ {"time_real", {RSPAMD_LOG_TIME_REAL, 0}},
+ {"time_virtual", {RSPAMD_LOG_TIME_VIRTUAL, 0}},
+ {"lua", {RSPAMD_LOG_LUA, 0}},
+ {"digest", {RSPAMD_LOG_DIGEST, 0}},
+ {"checksum", {RSPAMD_LOG_DIGEST, 0}},
+ {"filename", {RSPAMD_LOG_FILENAME, 0}},
+ {"forced_action", {RSPAMD_LOG_FORCED_ACTION, 0}},
+ {"settings_id", {RSPAMD_LOG_SETTINGS_ID, 0}},
+ {"mempool_size", {RSPAMD_LOG_MEMPOOL_SIZE, 0}},
+ {"mempool_waste", {RSPAMD_LOG_MEMPOOL_WASTE, 0}},
+ {"action", {RSPAMD_LOG_ACTION, 0}},
+ {"scores", {RSPAMD_LOG_SCORES, 0}},
+ {"symbols", {RSPAMD_LOG_SYMBOLS, 0}},
+ {"symbols_scores", {RSPAMD_LOG_SYMBOLS, RSPAMD_LOG_FMT_FLAG_SYMBOLS_SCORES}},
+ {"symbols_params", {RSPAMD_LOG_SYMBOLS, RSPAMD_LOG_FMT_FLAG_SYMBOLS_PARAMS}},
+ {"symbols_scores_params", {RSPAMD_LOG_SYMBOLS, RSPAMD_LOG_FMT_FLAG_SYMBOLS_PARAMS | RSPAMD_LOG_FMT_FLAG_SYMBOLS_SCORES}},
+ {"groups", {RSPAMD_LOG_GROUPS, 0}},
+ {"public_groups", {RSPAMD_LOG_PUBLIC_GROUPS, 0}},
+ {"is_spam", {RSPAMD_LOG_ISSPAM, 0}},
+});
+
static gboolean
rspamd_config_process_var(struct rspamd_config *cfg, const rspamd_ftok_t *var,
const rspamd_ftok_t *content)
{
- guint flags = RSPAMD_LOG_FLAG_DEFAULT;
- struct rspamd_log_format *lf;
- enum rspamd_log_format_type type;
- rspamd_ftok_t tok;
- gint id;
+ g_assert(var != nullptr);
- g_assert(var != NULL);
+ auto flags = 0;
+ auto lc_var = std::string{var->begin, var->len};
+ std::transform(lc_var.begin(), lc_var.end(), lc_var.begin(), g_ascii_tolower);
+ auto tok = std::string_view{lc_var};
- if (var->len > 3 && rspamd_lc_cmp(var->begin, "if_", 3) == 0) {
+ if (var->len > 3 && tok.starts_with("if_")) {
flags |= RSPAMD_LOG_FMT_FLAG_CONDITION;
- tok.begin = var->begin + 3;
- tok.len = var->len - 3;
- }
- else {
- tok.begin = var->begin;
- tok.len = var->len;
+ tok = tok.substr(3);
}
- /* Now compare variable and check what we have */
- if (rspamd_ftok_cstr_equal(&tok, "mid", TRUE)) {
- type = RSPAMD_LOG_MID;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "qid", TRUE)) {
- type = RSPAMD_LOG_QID;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "user", TRUE)) {
- type = RSPAMD_LOG_USER;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "is_spam", TRUE)) {
- type = RSPAMD_LOG_ISSPAM;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "action", TRUE)) {
- type = RSPAMD_LOG_ACTION;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "scores", TRUE)) {
- type = RSPAMD_LOG_SCORES;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "symbols", TRUE)) {
- type = RSPAMD_LOG_SYMBOLS;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "symbols_scores", TRUE)) {
- type = RSPAMD_LOG_SYMBOLS;
- flags |= RSPAMD_LOG_FMT_FLAG_SYMBOLS_SCORES;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "symbols_params", TRUE)) {
- type = RSPAMD_LOG_SYMBOLS;
- flags |= RSPAMD_LOG_FMT_FLAG_SYMBOLS_PARAMS;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "symbols_scores_params", TRUE)) {
- type = RSPAMD_LOG_SYMBOLS;
- flags |= RSPAMD_LOG_FMT_FLAG_SYMBOLS_PARAMS | RSPAMD_LOG_FMT_FLAG_SYMBOLS_SCORES;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "groups", TRUE)) {
- type = RSPAMD_LOG_GROUPS;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "public_groups", TRUE)) {
- type = RSPAMD_LOG_PUBLIC_GROUPS;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "ip", TRUE)) {
- type = RSPAMD_LOG_IP;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "len", TRUE)) {
- type = RSPAMD_LOG_LEN;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "dns_req", TRUE)) {
- type = RSPAMD_LOG_DNS_REQ;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "smtp_from", TRUE)) {
- type = RSPAMD_LOG_SMTP_FROM;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "mime_from", TRUE)) {
- type = RSPAMD_LOG_MIME_FROM;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "smtp_rcpt", TRUE)) {
- type = RSPAMD_LOG_SMTP_RCPT;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "mime_rcpt", TRUE)) {
- type = RSPAMD_LOG_MIME_RCPT;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "smtp_rcpts", TRUE)) {
- type = RSPAMD_LOG_SMTP_RCPTS;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "mime_rcpts", TRUE)) {
- type = RSPAMD_LOG_MIME_RCPTS;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "time_real", TRUE)) {
- type = RSPAMD_LOG_TIME_REAL;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "time_virtual", TRUE)) {
- type = RSPAMD_LOG_TIME_VIRTUAL;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "lua", TRUE)) {
- type = RSPAMD_LOG_LUA;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "digest", TRUE) ||
- rspamd_ftok_cstr_equal(&tok, "checksum", TRUE)) {
- type = RSPAMD_LOG_DIGEST;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "filename", TRUE)) {
- type = RSPAMD_LOG_FILENAME;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "forced_action", TRUE)) {
- type = RSPAMD_LOG_FORCED_ACTION;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "settings_id", TRUE)) {
- type = RSPAMD_LOG_SETTINGS_ID;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "mempool_size", TRUE)) {
- type = RSPAMD_LOG_MEMPOOL_SIZE;
- }
- else if (rspamd_ftok_cstr_equal(&tok, "mempool_waste", TRUE)) {
- type = RSPAMD_LOG_MEMPOOL_WASTE;
- }
- else {
- msg_err_config("unknown log variable: %T", &tok);
- return FALSE;
- }
+ auto maybe_fmt_var = rspamd::find_map(config_vars, tok);
- lf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*lf));
- lf->type = type;
- lf->flags = flags;
+ if (maybe_fmt_var) {
+ auto &fmt_var = maybe_fmt_var.value().get();
+ auto *log_format = rspamd_mempool_alloc0_type(cfg->cfg_pool, rspamd_log_format);
- if (type != RSPAMD_LOG_LUA) {
- if (content && content->len > 0) {
- lf->data = rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(rspamd_ftok_t));
- memcpy(lf->data, content, sizeof(*content));
- lf->len = sizeof(*content);
- }
- }
- else {
- /* Load lua code and ensure that we have function ref returned */
- if (!content || content->len == 0) {
- msg_err_config("lua variable needs content: %T", &tok);
- return FALSE;
- }
+ log_format->type = fmt_var.first;
+ log_format->flags = fmt_var.second | flags;
- if (luaL_loadbuffer(cfg->lua_state, content->begin, content->len,
- "lua log variable") != 0) {
- msg_err_config("error loading lua code: '%T': %s", content,
- lua_tostring(cfg->lua_state, -1));
- return FALSE;
+ if (log_format->type != RSPAMD_LOG_LUA) {
+ if (content && content->len > 0) {
+ log_format->data = rspamd_mempool_alloc0(cfg->cfg_pool,
+ sizeof(rspamd_ftok_t));
+ memcpy(log_format->data, content, sizeof(*content));
+ log_format->len = sizeof(*content);
+ }
}
- if (lua_pcall(cfg->lua_state, 0, 1, 0) != 0) {
- msg_err_config("error executing lua code: '%T': %s", content,
- lua_tostring(cfg->lua_state, -1));
- lua_pop(cfg->lua_state, 1);
+ else {
+ /* Load lua code and ensure that we have function ref returned */
+ if (!content || content->len == 0) {
+ msg_err_config("lua variable needs content: %T", &tok);
+ return FALSE;
+ }
- return FALSE;
- }
+ if (luaL_loadbuffer(RSPAMD_LUA_CFG_STATE(cfg), content->begin, content->len,
+ "lua log variable") != 0) {
+ msg_err_config("error loading lua code: '%T': %s", content,
+ lua_tostring(RSPAMD_LUA_CFG_STATE(cfg), -1));
+ return FALSE;
+ }
+ if (lua_pcall(RSPAMD_LUA_CFG_STATE(cfg), 0, 1, 0) != 0) {
+ msg_err_config("error executing lua code: '%T': %s", content,
+ lua_tostring(RSPAMD_LUA_CFG_STATE(cfg), -1));
+ lua_pop(RSPAMD_LUA_CFG_STATE(cfg), 1);
- if (lua_type(cfg->lua_state, -1) != LUA_TFUNCTION) {
- msg_err_config("lua variable should return function: %T", content);
- lua_pop(cfg->lua_state, 1);
- return FALSE;
+ return FALSE;
+ }
+
+ if (lua_type(RSPAMD_LUA_CFG_STATE(cfg), -1) != LUA_TFUNCTION) {
+ msg_err_config("lua variable should return function: %T", content);
+ lua_pop(RSPAMD_LUA_CFG_STATE(cfg), 1);
+ return FALSE;
+ }
+
+ auto id = luaL_ref(RSPAMD_LUA_CFG_STATE(cfg), LUA_REGISTRYINDEX);
+ log_format->data = GINT_TO_POINTER(id);
+ log_format->len = 0;
}
- id = luaL_ref(cfg->lua_state, LUA_REGISTRYINDEX);
- lf->data = GINT_TO_POINTER(id);
- lf->len = 0;
+ DL_APPEND(cfg->log_format, log_format);
}
+ else {
+ std::string known_formats;
+
+ for (const auto &v: config_vars) {
+ known_formats += std::string_view{v.first.data(), v.first.size()};
+ known_formats += ", ";
+ }
- DL_APPEND(cfg->log_format, lf);
+ if (known_formats.size() > 2) {
+ // Remove last comma
+ known_formats.resize(known_formats.size() - 2);
+ }
+ msg_err_config("unknown log variable: %T, known vars are: \"%s\"", var, known_formats.c_str());
+ return FALSE;
+ }
return TRUE;
}
@@ -621,7 +625,7 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
{
const gchar *p, *c, *end, *s;
gchar *d;
- struct rspamd_log_format *lf = NULL;
+ struct rspamd_log_format *lf = nullptr;
rspamd_ftok_t var, var_content;
enum {
parse_str,
@@ -631,10 +635,10 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
} state = parse_str;
gint braces = 0;
- g_assert(cfg != NULL);
+ g_assert(cfg != nullptr);
c = cfg->log_format_str;
- if (c == NULL) {
+ if (c == nullptr) {
return FALSE;
}
@@ -654,12 +658,12 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
case parse_dollar:
if (p > c) {
/* We have string element that we need to store */
- lf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*lf));
+ lf = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_log_format);
lf->type = RSPAMD_LOG_STRING;
lf->data = rspamd_mempool_alloc(cfg->cfg_pool, p - c + 1);
/* Filter \r\n from the destination */
s = c;
- d = lf->data;
+ d = (char *) lf->data;
while (s < p) {
if (*s != '\r' && *s != '\n') {
@@ -674,7 +678,7 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
lf->len = d - (char *) lf->data;
DL_APPEND(cfg->log_format, lf);
- lf = NULL;
+ lf = nullptr;
}
p++;
c = p;
@@ -695,7 +699,7 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
var.len = p - c;
c = p;
- if (!rspamd_config_process_var(cfg, &var, NULL)) {
+ if (!rspamd_config_process_var(cfg, &var, nullptr)) {
return FALSE;
}
@@ -734,12 +738,12 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
case parse_str:
if (p > c) {
/* We have string element that we need to store */
- lf = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*lf));
+ lf = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_log_format);
lf->type = RSPAMD_LOG_STRING;
lf->data = rspamd_mempool_alloc(cfg->cfg_pool, p - c + 1);
/* Filter \r\n from the destination */
s = c;
- d = lf->data;
+ d = (char *) lf->data;
while (s < p) {
if (*s != '\r' && *s != '\n') {
@@ -754,7 +758,7 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
lf->len = d - (char *) lf->data;
DL_APPEND(cfg->log_format, lf);
- lf = NULL;
+ lf = nullptr;
}
break;
@@ -762,7 +766,7 @@ rspamd_config_parse_log_format(struct rspamd_config *cfg)
var.begin = c;
var.len = p - c;
- if (!rspamd_config_process_var(cfg, &var, NULL)) {
+ if (!rspamd_config_process_var(cfg, &var, nullptr)) {
return FALSE;
}
break;
@@ -783,17 +787,12 @@ rspamd_urls_config_dtor(gpointer _unused)
rspamd_url_deinit();
}
-/*
- * Perform post load actions
- */
-gboolean
-rspamd_config_post_load(struct rspamd_config *cfg,
- enum rspamd_post_load_options opts)
+static void
+rspamd_adjust_clocks_resolution(struct rspamd_config *cfg)
{
#ifdef HAVE_CLOCK_GETTIME
struct timespec ts;
#endif
- gboolean ret = TRUE;
#ifdef HAVE_CLOCK_GETTIME
#ifdef HAVE_CLOCK_PROCESS_CPUTIME_ID
@@ -803,8 +802,6 @@ rspamd_config_post_load(struct rspamd_config *cfg,
#else
clock_getres(CLOCK_REALTIME, &ts);
#endif
- rspamd_logger_configure_modules(cfg->debug_modules);
-
cfg->clock_res = log10(1000000. / ts.tv_nsec);
if (cfg->clock_res < 0) {
cfg->clock_res = 0;
@@ -816,6 +813,20 @@ rspamd_config_post_load(struct rspamd_config *cfg,
/* For gettimeofday */
cfg->clock_res = 1;
#endif
+}
+
+/*
+ * Perform post load actions
+ */
+gboolean
+rspamd_config_post_load(struct rspamd_config *cfg,
+ enum rspamd_post_load_options opts)
+{
+
+ auto ret = TRUE;
+
+ rspamd_adjust_clocks_resolution(cfg);
+ rspamd_logger_configure_modules(cfg->debug_modules);
if (cfg->one_shot_mode) {
msg_info_config("enabling one shot mode (was %d max shots)",
@@ -823,9 +834,6 @@ rspamd_config_post_load(struct rspamd_config *cfg,
cfg->default_max_shots = 1;
}
- rspamd_regexp_library_init(cfg);
- rspamd_multipattern_library_init(cfg->hs_cache_dir);
-
#if defined(WITH_HYPERSCAN) && !defined(__aarch64__) && !defined(__powerpc64__)
if (!cfg->disable_hyperscan) {
if (!(cfg->libs_ctx->crypto_ctx->cpu_config & CPUID_SSSE3)) {
@@ -836,20 +844,21 @@ rspamd_config_post_load(struct rspamd_config *cfg,
}
#endif
+ rspamd_regexp_library_init(cfg);
+ rspamd_multipattern_library_init(cfg->hs_cache_dir);
+
if (opts & RSPAMD_CONFIG_INIT_URL) {
- if (cfg->tld_file == NULL) {
+ if (cfg->tld_file == nullptr) {
/* Try to guess tld file */
- GString *fpath = g_string_new(NULL);
+ auto fpath = fmt::format("{0}{1}{2}", RSPAMD_SHAREDIR,
+ G_DIR_SEPARATOR, "effective_tld_names.dat");
- rspamd_printf_gstring(fpath, "%s%c%s", RSPAMD_SHAREDIR,
- G_DIR_SEPARATOR, "effective_tld_names.dat");
-
- if (access(fpath->str, R_OK) != -1) {
+ if (access(fpath.c_str(), R_OK) != -1) {
msg_debug_config("url_tld option is not specified but %s is available,"
" therefore this file is assumed as TLD file for URL"
" extraction",
- fpath->str);
- cfg->tld_file = rspamd_mempool_strdup(cfg->cfg_pool, fpath->str);
+ fpath.c_str());
+ cfg->tld_file = rspamd_mempool_strdup(cfg->cfg_pool, fpath.c_str());
}
else {
if (opts & RSPAMD_CONFIG_INIT_VALIDATE) {
@@ -857,8 +866,6 @@ rspamd_config_post_load(struct rspamd_config *cfg,
ret = FALSE;
}
}
-
- g_string_free(fpath, TRUE);
}
else {
if (access(cfg->tld_file, R_OK) == -1) {
@@ -870,20 +877,20 @@ rspamd_config_post_load(struct rspamd_config *cfg,
else {
msg_debug_config("cannot access tld file %s: %s", cfg->tld_file,
strerror(errno));
- cfg->tld_file = NULL;
+ cfg->tld_file = nullptr;
}
}
}
if (opts & RSPAMD_CONFIG_INIT_NO_TLD) {
- rspamd_url_init(NULL);
+ rspamd_url_init(nullptr);
}
else {
rspamd_url_init(cfg->tld_file);
}
rspamd_mempool_add_destructor(cfg->cfg_pool, rspamd_urls_config_dtor,
- NULL);
+ nullptr);
}
init_dynamic_config(cfg);
@@ -893,36 +900,46 @@ rspamd_config_post_load(struct rspamd_config *cfg,
/* Parse format string that we have */
if (!rspamd_config_parse_log_format(cfg)) {
msg_err_config("cannot parse log format, task logging will not be available");
+ if (opts & RSPAMD_CONFIG_INIT_VALIDATE) {
+ ret = FALSE;
+ }
}
if (opts & RSPAMD_CONFIG_INIT_SYMCACHE) {
/* Init config cache */
- rspamd_symcache_init(cfg->cache);
+ ret = rspamd_symcache_init(cfg->cache) && ret;
/* Init re cache */
rspamd_re_cache_init(cfg->re_cache, cfg);
/* Try load Hypersan */
- rspamd_re_cache_load_hyperscan(cfg->re_cache,
- cfg->hs_cache_dir ? cfg->hs_cache_dir : RSPAMD_DBDIR "/",
- true);
+ auto hs_ret = rspamd_re_cache_load_hyperscan(cfg->re_cache,
+ cfg->hs_cache_dir ? cfg->hs_cache_dir : RSPAMD_DBDIR "/",
+ true);
+
+ if (hs_ret == RSPAMD_HYPERSCAN_LOAD_ERROR) {
+ msg_debug_config("cannot load hyperscan database, disable it");
+ }
}
if (opts & RSPAMD_CONFIG_INIT_LIBS) {
/* Config other libraries */
- rspamd_config_libs(cfg->libs_ctx, cfg);
+ ret = rspamd_config_libs(cfg->libs_ctx, cfg) && ret;
+
+ if (!ret) {
+ msg_err_config("cannot configure libraries, fatal error");
+ return FALSE;
+ }
}
/* Validate cache */
if (opts & RSPAMD_CONFIG_INIT_VALIDATE) {
/* Check for actions sanity */
- gboolean seen_controller = FALSE;
- GList *cur;
- struct rspamd_worker_conf *wcf;
+ auto seen_controller = FALSE;
- cur = cfg->workers;
+ auto *cur = cfg->workers;
while (cur) {
- wcf = cur->data;
+ auto *wcf = (struct rspamd_worker_conf *) cur->data;
if (wcf->type == g_quark_from_static_string("controller")) {
seen_controller = TRUE;
@@ -942,7 +959,7 @@ rspamd_config_post_load(struct rspamd_config *cfg,
}
if (opts & RSPAMD_CONFIG_INIT_POST_LOAD_LUA) {
- rspamd_lua_run_config_post_init(cfg->lua_state, cfg);
+ rspamd_lua_run_config_post_init(RSPAMD_LUA_CFG_STATE(cfg), cfg);
}
if (opts & RSPAMD_CONFIG_INIT_PRELOAD_MAPS) {
@@ -956,18 +973,18 @@ struct rspamd_classifier_config *
rspamd_config_new_classifier(struct rspamd_config *cfg,
struct rspamd_classifier_config *c)
{
- if (c == NULL) {
+ if (c == nullptr) {
c =
- rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(struct rspamd_classifier_config));
+ rspamd_mempool_alloc0_type(cfg->cfg_pool,
+ struct rspamd_classifier_config);
c->min_prob_strength = 0.05;
c->min_token_hits = 2;
}
- if (c->labels == NULL) {
+ if (c->labels == nullptr) {
c->labels = g_hash_table_new_full(rspamd_str_hash,
rspamd_str_equal,
- NULL,
+ nullptr,
(GDestroyNotify) g_list_free);
rspamd_mempool_add_destructor(cfg->cfg_pool,
(rspamd_mempool_destruct_t) g_hash_table_destroy,
@@ -981,10 +998,9 @@ struct rspamd_statfile_config *
rspamd_config_new_statfile(struct rspamd_config *cfg,
struct rspamd_statfile_config *c)
{
- if (c == NULL) {
+ if (c == nullptr) {
c =
- rspamd_mempool_alloc0(cfg->cfg_pool,
- sizeof(struct rspamd_statfile_config));
+ rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_statfile_config);
}
return c;
@@ -1010,7 +1026,7 @@ rspamd_config_new_group(struct rspamd_config *cfg, const gchar *name)
{
struct rspamd_symbols_group *gr;
- gr = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*gr));
+ gr = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_symbols_group);
gr->symbols = g_hash_table_new(rspamd_strcase_hash,
rspamd_strcase_equal);
rspamd_mempool_add_destructor(cfg->cfg_pool,
@@ -1030,16 +1046,6 @@ static void
rspamd_worker_conf_dtor(struct rspamd_worker_conf *wcf)
{
if (wcf) {
- struct rspamd_worker_bind_conf *cnf, *tmp;
-
- LL_FOREACH_SAFE(wcf->bind_conf, cnf, tmp)
- {
- g_free(cnf->name);
- g_free(cnf->bind_line);
- g_ptr_array_free(cnf->addrs, TRUE);
- g_free(cnf);
- }
-
ucl_object_unref(wcf->options);
g_queue_free(wcf->active_workers);
g_hash_table_unref(wcf->params);
@@ -1050,7 +1056,7 @@ rspamd_worker_conf_dtor(struct rspamd_worker_conf *wcf)
static void
rspamd_worker_conf_cfg_fin(gpointer d)
{
- struct rspamd_worker_conf *wcf = d;
+ auto *wcf = (struct rspamd_worker_conf *) d;
REF_RELEASE(wcf);
}
@@ -1059,13 +1065,13 @@ struct rspamd_worker_conf *
rspamd_config_new_worker(struct rspamd_config *cfg,
struct rspamd_worker_conf *c)
{
- if (c == NULL) {
- c = g_malloc0(sizeof(struct rspamd_worker_conf));
+ if (c == nullptr) {
+ c = g_new0(struct rspamd_worker_conf, 1);
c->params = g_hash_table_new(rspamd_str_hash, rspamd_str_equal);
c->active_workers = g_queue_new();
#ifdef HAVE_SC_NPROCESSORS_ONLN
- c->count = MIN(DEFAULT_MAX_WORKERS,
- MAX(1, sysconf(_SC_NPROCESSORS_ONLN) - 2));
+ auto nproc = sysconf(_SC_NPROCESSORS_ONLN);
+ c->count = MIN(DEFAULT_MAX_WORKERS, MAX(1, nproc - 2));
#else
c->count = DEFAULT_MAX_WORKERS;
#endif
@@ -1086,18 +1092,13 @@ static bool
rspamd_include_map_handler(const guchar *data, gsize len,
const ucl_object_t *args, void *ud)
{
- struct rspamd_config *cfg = (struct rspamd_config *) ud;
- struct rspamd_ucl_map_cbdata *cbdata, **pcbdata;
- gchar *map_line;
+ auto *cfg = (struct rspamd_config *) ud;
- map_line = rspamd_mempool_alloc(cfg->cfg_pool, len + 1);
- rspamd_strlcpy(map_line, data, len + 1);
+ auto ftok = rspamd_ftok_t{.len = len + 1, .begin = (char *) data};
+ auto *map_line = rspamd_mempool_ftokdup(cfg->cfg_pool, &ftok);
- cbdata = g_malloc(sizeof(struct rspamd_ucl_map_cbdata));
- pcbdata = g_malloc(sizeof(struct rspamd_ucl_map_cbdata *));
- cbdata->buf = NULL;
- cbdata->cfg = cfg;
- *pcbdata = cbdata;
+ auto *cbdata = new rspamd_ucl_map_cbdata{cfg};
+ auto **pcbdata = new rspamd_ucl_map_cbdata *(cbdata);
return rspamd_map_add(cfg,
map_line,
@@ -1106,7 +1107,7 @@ rspamd_include_map_handler(const guchar *data, gsize len,
rspamd_ucl_fin_cb,
rspamd_ucl_dtor_cb,
(void **) pcbdata,
- NULL, RSPAMD_MAP_DEFAULT) != NULL;
+ nullptr, RSPAMD_MAP_DEFAULT) != nullptr;
}
/*
@@ -1141,8 +1142,6 @@ void rspamd_ucl_add_conf_variables(struct ucl_parser *parser, GHashTable *vars)
{
GHashTableIter it;
gpointer k, v;
- gchar *hostbuf;
- gsize hostlen;
ucl_parser_register_variable(parser,
RSPAMD_CONFDIR_MACRO,
@@ -1177,7 +1176,7 @@ void rspamd_ucl_add_conf_variables(struct ucl_parser *parser, GHashTable *vars)
ucl_parser_register_variable(parser, RSPAMD_BRANCH_VERSION_MACRO,
RSPAMD_VERSION_BRANCH);
- hostlen = sysconf(_SC_HOST_NAME_MAX);
+ auto hostlen = sysconf(_SC_HOST_NAME_MAX);
if (hostlen <= 0) {
hostlen = 256;
@@ -1186,19 +1185,22 @@ void rspamd_ucl_add_conf_variables(struct ucl_parser *parser, GHashTable *vars)
hostlen++;
}
- hostbuf = g_alloca(hostlen);
- memset(hostbuf, 0, hostlen);
- gethostname(hostbuf, hostlen - 1);
+ auto hostbuf = std::string{};
+ hostbuf.resize(hostlen);
+
+ if (gethostname(hostbuf.data(), hostlen) != 0) {
+ hostbuf = "unknown";
+ }
/* UCL copies variables, so it is safe to pass an ephemeral buffer here */
ucl_parser_register_variable(parser, RSPAMD_HOSTNAME_MACRO,
- hostbuf);
+ hostbuf.c_str());
- if (vars != NULL) {
+ if (vars != nullptr) {
g_hash_table_iter_init(&it, vars);
while (g_hash_table_iter_next(&it, &k, &v)) {
- ucl_parser_register_variable(parser, k, v);
+ ucl_parser_register_variable(parser, (const char *) k, (const char *) v);
}
}
}
@@ -1215,10 +1217,10 @@ void rspamd_ucl_add_conf_macros(struct ucl_parser *parser,
static void
symbols_classifiers_callback(gpointer key, gpointer value, gpointer ud)
{
- struct rspamd_config *cfg = ud;
+ auto *cfg = (struct rspamd_config *) ud;
/* Actually, statistics should act like any ordinary symbol */
- rspamd_symcache_add_symbol(cfg->cache, key, 0, NULL, NULL,
+ rspamd_symcache_add_symbol(cfg->cache, (const char *) key, 0, nullptr, nullptr,
SYMBOL_TYPE_CLASSIFIER | SYMBOL_TYPE_NOSTAT, -1);
}
@@ -1232,16 +1234,13 @@ void rspamd_config_insert_classify_symbols(struct rspamd_config *cfg)
struct rspamd_classifier_config *
rspamd_config_find_classifier(struct rspamd_config *cfg, const gchar *name)
{
- GList *cur;
- struct rspamd_classifier_config *cf;
-
- if (name == NULL) {
- return NULL;
+ if (name == nullptr) {
+ return nullptr;
}
- cur = cfg->classifiers;
+ auto *cur = cfg->classifiers;
while (cur) {
- cf = cur->data;
+ auto *cf = (struct rspamd_classifier_config *) cur->data;
if (g_ascii_strcasecmp(cf->name, name) == 0) {
return cf;
@@ -1250,20 +1249,18 @@ rspamd_config_find_classifier(struct rspamd_config *cfg, const gchar *name)
cur = g_list_next(cur);
}
- return NULL;
+ return nullptr;
}
gboolean
rspamd_config_check_statfiles(struct rspamd_classifier_config *cf)
{
- struct rspamd_statfile_config *st;
gboolean has_other = FALSE, res = FALSE, cur_class = FALSE;
- GList *cur;
/* First check classes directly */
- cur = cf->statfiles;
+ auto *cur = cf->statfiles;
while (cur) {
- st = cur->data;
+ auto *st = (struct rspamd_statfile_config *) cur->data;
if (!has_other) {
cur_class = st->is_spam;
has_other = TRUE;
@@ -1285,7 +1282,7 @@ rspamd_config_check_statfiles(struct rspamd_classifier_config *cf)
has_other = FALSE;
cur = cf->statfiles;
while (cur) {
- st = cur->data;
+ auto *st = (struct rspamd_statfile_config *) cur->data;
if (rspamd_substring_search_caseless(st->symbol,
strlen(st->symbol), "spam", 4) != -1) {
st->is_spam = TRUE;
@@ -1317,55 +1314,50 @@ rspamd_ucl_read_cb(gchar *chunk,
struct map_cb_data *data,
gboolean final)
{
- struct rspamd_ucl_map_cbdata *cbdata = data->cur_data, *prev;
+ auto *cbdata = (struct rspamd_ucl_map_cbdata *) data->cur_data;
+ auto *prev = (struct rspamd_ucl_map_cbdata *) data->prev_data;
- if (cbdata == NULL) {
- cbdata = g_malloc(sizeof(struct rspamd_ucl_map_cbdata));
- prev = data->prev_data;
- cbdata->buf = g_string_sized_new(BUFSIZ);
- cbdata->cfg = prev->cfg;
+ if (cbdata == nullptr) {
+ cbdata = new rspamd_ucl_map_cbdata{prev->cfg};
data->cur_data = cbdata;
}
- g_string_append_len(cbdata->buf, chunk, len);
+ cbdata->buf.append(chunk, len);
/* Say not to copy any part of this buffer */
- return NULL;
+ return nullptr;
}
static void
rspamd_ucl_fin_cb(struct map_cb_data *data, void **target)
{
- struct rspamd_ucl_map_cbdata *cbdata = data->cur_data, *prev =
- data->prev_data;
- ucl_object_t *obj;
- struct ucl_parser *parser;
- ucl_object_iter_t it = NULL;
- const ucl_object_t *cur;
- struct rspamd_config *cfg = data->map->cfg;
-
- if (cbdata == NULL) {
- msg_err_config("map fin error: new data is NULL");
+ auto *cbdata = (struct rspamd_ucl_map_cbdata *) data->cur_data;
+ auto *prev = (struct rspamd_ucl_map_cbdata *) data->prev_data;
+ auto *cfg = data->map->cfg;
+
+ if (cbdata == nullptr) {
+ msg_err_config("map fin error: new data is nullptr");
return;
}
/* New data available */
- parser = ucl_parser_new(0);
- if (!ucl_parser_add_chunk(parser, cbdata->buf->str,
- cbdata->buf->len)) {
+ auto *parser = ucl_parser_new(0);
+ if (!ucl_parser_add_chunk(parser, (unsigned char *) cbdata->buf.data(),
+ cbdata->buf.size())) {
msg_err_config("cannot parse map %s: %s",
data->map->name,
ucl_parser_get_error(parser));
ucl_parser_free(parser);
}
else {
- obj = ucl_parser_get_object(parser);
- ucl_parser_free(parser);
- it = NULL;
+ auto *obj = ucl_parser_get_object(parser);
+ ucl_object_iter_t it = nullptr;
- while ((cur = ucl_object_iterate(obj, &it, true))) {
- ucl_object_replace_key(cbdata->cfg->rcl_obj, (ucl_object_t *) cur,
+ for (auto *cur = ucl_object_iterate(obj, &it, true); cur != nullptr; cur = ucl_object_iterate(obj, &it, true)) {
+ ucl_object_replace_key(cbdata->cfg->cfg_ucl_obj, (ucl_object_t *) cur,
cur->key, cur->keylen, false);
}
+
+ ucl_parser_free(parser);
ucl_object_unref(obj);
}
@@ -1373,25 +1365,15 @@ rspamd_ucl_fin_cb(struct map_cb_data *data, void **target)
*target = data->cur_data;
}
- if (prev != NULL) {
- if (prev->buf != NULL) {
- g_string_free(prev->buf, TRUE);
- }
- g_free(prev);
- }
+ delete prev;
}
static void
rspamd_ucl_dtor_cb(struct map_cb_data *data)
{
- struct rspamd_ucl_map_cbdata *cbdata = data->cur_data;
+ auto *cbdata = (struct rspamd_ucl_map_cbdata *) data->cur_data;
- if (cbdata != NULL) {
- if (cbdata->buf != NULL) {
- g_string_free(cbdata->buf, TRUE);
- }
- g_free(cbdata);
- }
+ delete cbdata;
}
gboolean
@@ -1399,7 +1381,7 @@ rspamd_check_module(struct rspamd_config *cfg, module_t *mod)
{
gboolean ret = TRUE;
- if (mod != NULL) {
+ if (mod != nullptr) {
if (mod->module_version != RSPAMD_CUR_MODULE_VERSION) {
msg_err_config("module %s has incorrect version %xd (%xd expected)",
mod->name, (gint) mod->module_version, RSPAMD_CUR_MODULE_VERSION);
@@ -1428,7 +1410,7 @@ rspamd_check_worker(struct rspamd_config *cfg, worker_t *wrk)
{
gboolean ret = TRUE;
- if (wrk != NULL) {
+ if (wrk != nullptr) {
if (wrk->worker_version != RSPAMD_CUR_WORKER_VERSION) {
msg_err_config("worker %s has incorrect version %xd (%xd expected)",
wrk->name, wrk->worker_version, RSPAMD_CUR_WORKER_VERSION);
@@ -1463,11 +1445,11 @@ rspamd_init_filters(struct rspamd_config *cfg, bool reconfig, bool strict)
/* Init all compiled modules */
- for (pmod = cfg->compiled_modules; pmod != NULL && *pmod != NULL; pmod++) {
+ for (pmod = cfg->compiled_modules; pmod != nullptr && *pmod != nullptr; pmod++) {
mod = *pmod;
if (rspamd_check_module(cfg, mod)) {
if (mod->module_init_func(cfg, &mod_ctx) == 0) {
- g_assert(mod_ctx != NULL);
+ g_assert(mod_ctx != nullptr);
g_ptr_array_add(cfg->c_modules, mod_ctx);
mod_ctx->mod = mod;
mod->ctx_offset = i++;
@@ -1480,7 +1462,7 @@ rspamd_init_filters(struct rspamd_config *cfg, bool reconfig, bool strict)
while (cur) {
/* Perform modules configuring */
- mod_ctx = NULL;
+ mod_ctx = nullptr;
PTR_ARRAY_FOREACH(cfg->c_modules, i, cur_ctx)
{
if (g_ascii_strcasecmp(cur_ctx->mod->name,
@@ -1514,7 +1496,7 @@ rspamd_init_filters(struct rspamd_config *cfg, bool reconfig, bool strict)
}
}
- if (mod_ctx == NULL) {
+ if (mod_ctx == nullptr) {
msg_warn_config("requested unknown module %s", cur->data);
}
@@ -1533,11 +1515,11 @@ rspamd_config_new_symbol(struct rspamd_config *cfg, const gchar *symbol,
{
struct rspamd_symbols_group *sym_group;
struct rspamd_symbol *sym_def;
- gdouble *score_ptr;
+ double *score_ptr;
sym_def =
- rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(struct rspamd_symbol));
- score_ptr = rspamd_mempool_alloc(cfg->cfg_pool, sizeof(gdouble));
+ rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_symbol);
+ score_ptr = rspamd_mempool_alloc_type(cfg->cfg_pool, double);
if (isnan(score)) {
/* In fact, it could be defined later */
@@ -1572,7 +1554,7 @@ rspamd_config_new_symbol(struct rspamd_config *cfg, const gchar *symbol,
g_hash_table_insert(cfg->symbols, sym_def->name, sym_def);
/* Search for symbol group */
- if (group == NULL) {
+ if (group == nullptr) {
group = "ungrouped";
sym_def->flags |= RSPAMD_SYMBOL_FLAG_UNGROUPED;
}
@@ -1582,8 +1564,8 @@ rspamd_config_new_symbol(struct rspamd_config *cfg, const gchar *symbol,
}
}
- sym_group = g_hash_table_lookup(cfg->groups, group);
- if (sym_group == NULL) {
+ sym_group = reinterpret_cast<rspamd_symbols_group *>(g_hash_table_lookup(cfg->groups, group));
+ if (sym_group == nullptr) {
/* Create new group */
sym_group = rspamd_config_new_group(cfg, group);
}
@@ -1611,13 +1593,13 @@ rspamd_config_add_symbol(struct rspamd_config *cfg,
struct rspamd_symbols_group *sym_group;
guint i;
- g_assert(cfg != NULL);
- g_assert(symbol != NULL);
+ g_assert(cfg != nullptr);
+ g_assert(symbol != nullptr);
- sym_def = g_hash_table_lookup(cfg->symbols, symbol);
+ sym_def = reinterpret_cast<rspamd_symbol *>(g_hash_table_lookup(cfg->symbols, symbol));
- if (sym_def != NULL) {
- if (group != NULL) {
+ if (sym_def != nullptr) {
+ if (group != nullptr) {
gboolean has_group = FALSE;
PTR_ARRAY_FOREACH(sym_def->groups, i, sym_group)
@@ -1631,9 +1613,9 @@ rspamd_config_add_symbol(struct rspamd_config *cfg,
if (!has_group) {
/* Non-empty group has a priority over non-grouped one */
- sym_group = g_hash_table_lookup(cfg->groups, group);
+ sym_group = reinterpret_cast<rspamd_symbols_group *>(g_hash_table_lookup(cfg->groups, group));
- if (sym_group == NULL) {
+ if (sym_group == nullptr) {
/* Create new group */
sym_group = rspamd_config_new_group(cfg, group);
}
@@ -1706,12 +1688,12 @@ rspamd_config_add_symbol(struct rspamd_config *cfg,
/* We also check group information in this case */
- if (group != NULL && sym_def->gr != NULL &&
+ if (group != nullptr && sym_def->gr != nullptr &&
strcmp(group, sym_def->gr->name) != 0) {
- sym_group = g_hash_table_lookup(cfg->groups, group);
+ sym_group = reinterpret_cast<rspamd_symbols_group *>(g_hash_table_lookup(cfg->groups, group));
- if (sym_group == NULL) {
+ if (sym_group == nullptr) {
/* Create new group */
sym_group = rspamd_config_new_group(cfg, group);
}
@@ -1745,13 +1727,13 @@ rspamd_config_add_symbol_group(struct rspamd_config *cfg,
struct rspamd_symbols_group *sym_group;
guint i;
- g_assert(cfg != NULL);
- g_assert(symbol != NULL);
- g_assert(group != NULL);
+ g_assert(cfg != nullptr);
+ g_assert(symbol != nullptr);
+ g_assert(group != nullptr);
- sym_def = g_hash_table_lookup(cfg->symbols, symbol);
+ sym_def = reinterpret_cast<rspamd_symbol *>(g_hash_table_lookup(cfg->symbols, symbol));
- if (sym_def != NULL) {
+ if (sym_def != nullptr) {
gboolean has_group = FALSE;
PTR_ARRAY_FOREACH(sym_def->groups, i, sym_group)
@@ -1765,9 +1747,9 @@ rspamd_config_add_symbol_group(struct rspamd_config *cfg,
if (!has_group) {
/* Non-empty group has a priority over non-grouped one */
- sym_group = g_hash_table_lookup(cfg->groups, group);
+ sym_group = reinterpret_cast<rspamd_symbols_group *>(g_hash_table_lookup(cfg->groups, group));
- if (sym_group == NULL) {
+ if (sym_group == nullptr) {
/* Create new group */
sym_group = rspamd_config_new_group(cfg, group);
}
@@ -1791,54 +1773,52 @@ gboolean
rspamd_config_is_enabled_from_ucl(rspamd_mempool_t *pool,
const ucl_object_t *obj)
{
- {
- const ucl_object_t *enabled;
- enabled = ucl_object_lookup(obj, "enabled");
+ const ucl_object_t *enabled;
- if (enabled) {
- if (ucl_object_type(enabled) == UCL_BOOLEAN) {
- return ucl_object_toboolean(enabled);
- }
- else if (ucl_object_type(enabled) == UCL_STRING) {
- gint ret = rspamd_config_parse_flag(ucl_object_tostring(enabled), 0);
+ enabled = ucl_object_lookup(obj, "enabled");
- if (ret == 0) {
- return FALSE;
- }
- else if (ret == -1) {
+ if (enabled) {
+ if (ucl_object_type(enabled) == UCL_BOOLEAN) {
+ return ucl_object_toboolean(enabled);
+ }
+ else if (ucl_object_type(enabled) == UCL_STRING) {
+ gint ret = rspamd_config_parse_flag(ucl_object_tostring(enabled), 0);
- msg_info_pool_check("wrong value for the `enabled` key");
- return FALSE;
- }
- /* Default return is TRUE here */
+ if (ret == 0) {
+ return FALSE;
}
+ else if (ret == -1) {
+
+ msg_info_pool_check("wrong value for the `enabled` key");
+ return FALSE;
+ }
+ /* Default return is TRUE here */
}
}
- {
- const ucl_object_t *disabled;
- disabled = ucl_object_lookup(obj, "disabled");
+ const ucl_object_t *disabled;
- if (disabled) {
- if (ucl_object_type(disabled) == UCL_BOOLEAN) {
- return !ucl_object_toboolean(disabled);
- }
- else if (ucl_object_type(disabled) == UCL_STRING) {
- gint ret = rspamd_config_parse_flag(ucl_object_tostring(disabled), 0);
+ disabled = ucl_object_lookup(obj, "disabled");
- if (ret == 0) {
- return TRUE;
- }
- else if (ret == -1) {
+ if (disabled) {
+ if (ucl_object_type(disabled) == UCL_BOOLEAN) {
+ return !ucl_object_toboolean(disabled);
+ }
+ else if (ucl_object_type(disabled) == UCL_STRING) {
+ gint ret = rspamd_config_parse_flag(ucl_object_tostring(disabled), 0);
- msg_info_pool_check("wrong value for the `disabled` key");
- return FALSE;
- }
+ if (ret == 0) {
+ return TRUE;
+ }
+ else if (ret == -1) {
+ msg_info_pool_check("wrong value for the `disabled` key");
return FALSE;
}
+
+ return FALSE;
}
}
@@ -1853,7 +1833,7 @@ rspamd_config_is_module_enabled(struct rspamd_config *cfg,
const ucl_object_t *conf;
GList *cur;
struct rspamd_symbols_group *gr;
- lua_State *L = cfg->lua_state;
+ lua_State *L = RSPAMD_LUA_CFG_STATE(cfg);
struct module_ctx *cur_ctx;
guint i;
@@ -1865,7 +1845,7 @@ rspamd_config_is_module_enabled(struct rspamd_config *cfg,
}
}
- if (g_hash_table_lookup(cfg->explicit_modules, module_name) != NULL) {
+ if (g_hash_table_lookup(cfg->explicit_modules, module_name) != nullptr) {
/* Always load module */
rspamd_plugins_table_push_elt(L, "enabled", module_name);
@@ -1878,7 +1858,7 @@ rspamd_config_is_module_enabled(struct rspamd_config *cfg,
cur = g_list_first(cfg->filters);
while (cur) {
- if (strcmp(cur->data, module_name) == 0) {
+ if (strcmp((char *) cur->data, module_name) == 0) {
found = TRUE;
break;
}
@@ -1896,9 +1876,9 @@ rspamd_config_is_module_enabled(struct rspamd_config *cfg,
}
}
- conf = ucl_object_lookup(cfg->rcl_obj, module_name);
+ conf = ucl_object_lookup(cfg->cfg_ucl_obj, module_name);
- if (conf == NULL) {
+ if (conf == nullptr) {
rspamd_plugins_table_push_elt(L, "disabled_unconfigured", module_name);
msg_info_config("%s module %s is enabled but has not been configured",
@@ -1924,7 +1904,7 @@ rspamd_config_is_module_enabled(struct rspamd_config *cfg,
}
/* Now we check symbols group */
- gr = g_hash_table_lookup(cfg->groups, module_name);
+ gr = reinterpret_cast<rspamd_symbols_group *>(g_hash_table_lookup(cfg->groups, module_name));
if (gr) {
if (gr->flags & RSPAMD_SYMBOL_GROUP_DISABLED) {
@@ -1949,16 +1929,15 @@ rspamd_config_action_from_ucl(struct rspamd_config *cfg,
const ucl_object_t *obj,
guint priority)
{
- const ucl_object_t *elt;
- gdouble threshold = NAN;
- guint flags = 0, std_act, obj_type;
+ auto threshold = NAN;
+ int flags = 0;
- obj_type = ucl_object_type(obj);
+ auto obj_type = ucl_object_type(obj);
if (obj_type == UCL_OBJECT) {
obj_type = ucl_object_type(obj);
- elt = ucl_object_lookup_any(obj, "score", "threshold", NULL);
+ const auto *elt = ucl_object_lookup_any(obj, "score", "threshold", nullptr);
if (elt) {
threshold = ucl_object_todouble(elt);
@@ -1968,9 +1947,9 @@ rspamd_config_action_from_ucl(struct rspamd_config *cfg,
if (elt && ucl_object_type(elt) == UCL_ARRAY) {
const ucl_object_t *cur;
- ucl_object_iter_t it = NULL;
+ ucl_object_iter_t it = nullptr;
- while ((cur = ucl_object_iterate(elt, &it, true)) != NULL) {
+ while ((cur = ucl_object_iterate(elt, &it, true)) != nullptr) {
if (ucl_object_type(cur) == UCL_STRING) {
const gchar *fl_str = ucl_object_tostring(cur);
@@ -2025,6 +2004,8 @@ rspamd_config_action_from_ucl(struct rspamd_config *cfg,
act->threshold = threshold;
act->flags = flags;
+ enum rspamd_action_type std_act;
+
if (!(flags & RSPAMD_ACTION_MILTER)) {
if (rspamd_action_from_str(act->name, &std_act)) {
act->action_type = std_act;
@@ -2042,13 +2023,12 @@ rspamd_config_set_action_score(struct rspamd_config *cfg,
const gchar *action_name,
const ucl_object_t *obj)
{
- struct rspamd_action *act;
enum rspamd_action_type std_act;
const ucl_object_t *elt;
guint priority = ucl_object_get_priority(obj), obj_type;
- g_assert(cfg != NULL);
- g_assert(action_name != NULL);
+ g_assert(cfg != nullptr);
+ g_assert(action_name != nullptr);
obj_type = ucl_object_type(obj);
@@ -2067,25 +2047,31 @@ rspamd_config_set_action_score(struct rspamd_config *cfg,
* variance of names.
*/
- if (rspamd_action_from_str(action_name, (gint *) &std_act)) {
+ if (rspamd_action_from_str(action_name, &std_act)) {
action_name = rspamd_action_to_str(std_act);
}
- HASH_FIND_STR(cfg->actions, action_name, act);
+ auto actions = RSPAMD_CFG_ACTIONS(cfg);
+ auto existing_act_it = actions->actions_by_name.find(action_name);
- if (act) {
+ if (existing_act_it != actions->actions_by_name.end()) {
+ auto *act = existing_act_it->second.get();
/* Existing element */
if (act->priority <= priority) {
/* We can replace data */
- msg_info_config("action %s has been already registered with "
- "priority %ud, override it with new priority: %ud, "
- "old score: %.2f",
- action_name,
- act->priority,
- priority,
- act->threshold);
+ auto old_pri = act->priority;
+ auto old_thr = act->threshold;
+
if (rspamd_config_action_from_ucl(cfg, act, obj, priority)) {
- rspamd_actions_sort(cfg);
+ msg_info_config("action %s has been already registered with "
+ "priority %ud, override it with new priority: %ud, "
+ "old threshold: %.2f, new threshold: %.2f",
+ action_name,
+ old_pri,
+ priority,
+ old_thr,
+ act->threshold);
+ actions->sort();
}
else {
return FALSE;
@@ -2101,13 +2087,11 @@ rspamd_config_set_action_score(struct rspamd_config *cfg,
}
else {
/* Add new element */
- act = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*act));
+ auto act = std::make_shared<rspamd_action>();
act->name = rspamd_mempool_strdup(cfg->cfg_pool, action_name);
- if (rspamd_config_action_from_ucl(cfg, act, obj, priority)) {
- HASH_ADD_KEYPTR(hh, cfg->actions,
- act->name, strlen(act->name), act);
- rspamd_actions_sort(cfg);
+ if (rspamd_config_action_from_ucl(cfg, act.get(), obj, priority)) {
+ actions->add_action(std::move(act));
}
else {
return FALSE;
@@ -2122,11 +2106,11 @@ rspamd_config_maybe_disable_action(struct rspamd_config *cfg,
const gchar *action_name,
guint priority)
{
- struct rspamd_action *act;
-
- HASH_FIND_STR(cfg->actions, action_name, act);
+ auto actions = RSPAMD_CFG_ACTIONS(cfg);
+ auto maybe_act = rspamd::find_map(actions->actions_by_name, action_name);
- if (act) {
+ if (maybe_act) {
+ auto *act = maybe_act.value().get().get();
if (priority >= act->priority) {
msg_info_config("disable action %s; old priority: %ud, new priority: %ud",
action_name,
@@ -2154,27 +2138,50 @@ rspamd_config_maybe_disable_action(struct rspamd_config *cfg,
struct rspamd_action *
rspamd_config_get_action(struct rspamd_config *cfg, const gchar *name)
{
- struct rspamd_action *res = NULL;
+ auto actions = RSPAMD_CFG_ACTIONS(cfg);
+ auto maybe_act = rspamd::find_map(actions->actions_by_name, name);
- HASH_FIND_STR(cfg->actions, name, res);
+ if (maybe_act) {
+ return maybe_act.value().get().get();
+ }
- return res;
+ return nullptr;
}
struct rspamd_action *
rspamd_config_get_action_by_type(struct rspamd_config *cfg,
enum rspamd_action_type type)
{
- struct rspamd_action *cur, *tmp;
-
- HASH_ITER(hh, cfg->actions, cur, tmp)
- {
- if (cur->action_type == type) {
- return cur;
+ for (const auto &act: RSPAMD_CFG_ACTIONS(cfg)->actions) {
+ if (act->action_type == type) {
+ return act.get();
}
}
- return NULL;
+ return nullptr;
+}
+
+void rspamd_config_actions_foreach(struct rspamd_config *cfg,
+ void (*func)(struct rspamd_action *act, void *d),
+ void *data)
+{
+ for (const auto &act: RSPAMD_CFG_ACTIONS(cfg)->actions) {
+ func(act.get(), data);
+ }
+}
+
+void rspamd_config_actions_foreach_enumerate(struct rspamd_config *cfg,
+ void (*func)(int idx, struct rspamd_action *act, void *d),
+ void *data)
+{
+ for (const auto &[idx, act]: rspamd::enumerate(RSPAMD_CFG_ACTIONS(cfg)->actions)) {
+ func(idx, act.get(), data);
+ }
+}
+
+gsize rspamd_config_actions_size(struct rspamd_config *cfg)
+{
+ return RSPAMD_CFG_ACTIONS(cfg)->actions.size();
}
gboolean
@@ -2183,12 +2190,12 @@ rspamd_config_radix_from_ucl(struct rspamd_config *cfg, const ucl_object_t *obj,
struct rspamd_worker *worker, const gchar *map_name)
{
ucl_type_t type;
- ucl_object_iter_t it = NULL;
+ ucl_object_iter_t it = nullptr;
const ucl_object_t *cur, *cur_elt;
const gchar *str;
/* Cleanup */
- *target = NULL;
+ *target = nullptr;
LL_FOREACH(obj, cur_elt)
{
@@ -2206,7 +2213,7 @@ rspamd_config_radix_from_ucl(struct rspamd_config *cfg, const ucl_object_t *obj,
rspamd_radix_fin,
rspamd_radix_dtor,
(void **) target,
- worker, RSPAMD_MAP_DEFAULT) == NULL) {
+ worker, RSPAMD_MAP_DEFAULT) == nullptr) {
g_set_error(err,
g_quark_from_static_string("rspamd-config"),
EINVAL, "bad map definition %s for %s", str,
@@ -2234,7 +2241,7 @@ rspamd_config_radix_from_ucl(struct rspamd_config *cfg, const ucl_object_t *obj,
rspamd_radix_fin,
rspamd_radix_dtor,
(void **) target,
- worker, RSPAMD_MAP_DEFAULT) == NULL) {
+ worker, RSPAMD_MAP_DEFAULT) == nullptr) {
g_set_error(err,
g_quark_from_static_string("rspamd-config"),
EINVAL, "bad map object for %s", ucl_object_key(obj));
@@ -2247,7 +2254,7 @@ rspamd_config_radix_from_ucl(struct rspamd_config *cfg, const ucl_object_t *obj,
/* List of IP addresses */
it = ucl_object_iterate_new(cur_elt);
- while ((cur = ucl_object_iterate_safe(it, true)) != NULL) {
+ while ((cur = ucl_object_iterate_safe(it, true)) != nullptr) {
if (ucl_object_type(cur) == UCL_STRING) {
@@ -2288,49 +2295,35 @@ rspamd_config_radix_from_ucl(struct rspamd_config *cfg, const ucl_object_t *obj,
return TRUE;
}
+constexpr const auto action_types = frozen::make_unordered_map<frozen::string, enum rspamd_action_type>({
+ {"reject", METRIC_ACTION_REJECT},
+ {"greylist", METRIC_ACTION_GREYLIST},
+ {"add header", METRIC_ACTION_ADD_HEADER},
+ {"add_header", METRIC_ACTION_ADD_HEADER},
+ {"rewrite subject", METRIC_ACTION_REWRITE_SUBJECT},
+ {"rewrite_subject", METRIC_ACTION_REWRITE_SUBJECT},
+ {"soft reject", METRIC_ACTION_SOFT_REJECT},
+ {"soft_reject", METRIC_ACTION_SOFT_REJECT},
+ {"no action", METRIC_ACTION_NOACTION},
+ {"no_action", METRIC_ACTION_NOACTION},
+ {"accept", METRIC_ACTION_NOACTION},
+ {"quarantine", METRIC_ACTION_QUARANTINE},
+ {"discard", METRIC_ACTION_DISCARD},
+
+});
+
gboolean
-rspamd_action_from_str(const gchar *data, gint *result)
+rspamd_action_from_str(const gchar *data, enum rspamd_action_type *result)
{
- guint64 h;
+ auto maybe_action = rspamd::find_map(action_types, std::string_view{data});
- h = rspamd_cryptobox_fast_hash_specific(RSPAMD_CRYPTOBOX_XXHASH64,
- data, strlen(data), 0xdeadbabe);
-
- switch (h) {
- case 0x9917BFDB46332B8CULL: /* reject */
- *result = METRIC_ACTION_REJECT;
- break;
- case 0x7130EE37D07B3715ULL: /* greylist */
- *result = METRIC_ACTION_GREYLIST;
- break;
- case 0xCA6087E05480C60CULL: /* add_header */
- case 0x87A3D27783B16241ULL: /* add header */
- *result = METRIC_ACTION_ADD_HEADER;
- break;
- case 0x4963374ED8B90449ULL: /* rewrite_subject */
- case 0x5C9FC4679C025948ULL: /* rewrite subject */
- *result = METRIC_ACTION_REWRITE_SUBJECT;
- break;
- case 0xFC7D6502EE71FDD9ULL: /* soft reject */
- case 0x73576567C262A82DULL: /* soft_reject */
- *result = METRIC_ACTION_SOFT_REJECT;
- break;
- case 0x207091B927D1EC0DULL: /* no action */
- case 0xB7D92D002CD46325ULL: /* no_action */
- case 0x167C0DF4BAA9BCECULL: /* accept */
- *result = METRIC_ACTION_NOACTION;
- break;
- case 0x4E9666ECCD3FC314ULL: /* quarantine */
- *result = METRIC_ACTION_QUARANTINE;
- break;
- case 0x93B346242F7F69B3ULL: /* discard */
- *result = METRIC_ACTION_DISCARD;
- break;
- default:
- return FALSE;
+ if (maybe_action) {
+ *result = maybe_action.value().get();
+ return true;
+ }
+ else {
+ return false;
}
-
- return TRUE;
}
const gchar *
@@ -2391,36 +2384,6 @@ rspamd_action_to_str_alt(enum rspamd_action_type action)
return "unknown action";
}
-static int
-rspamd_actions_cmp(const struct rspamd_action *a1, const struct rspamd_action *a2)
-{
- if (!isnan(a1->threshold) && !isnan(a2->threshold)) {
- if (a1->threshold < a2->threshold) {
- return -1;
- }
- else if (a1->threshold > a2->threshold) {
- return 1;
- }
-
- return 0;
- }
-
- if (isnan(a1->threshold) && isnan(a2->threshold)) {
- return 0;
- }
- else if (isnan(a1->threshold)) {
- return 1;
- }
- else {
- return -1;
- }
-}
-
-void rspamd_actions_sort(struct rspamd_config *cfg)
-{
- HASH_SORT(cfg->actions, rspamd_actions_cmp);
-}
-
static void
rspamd_config_settings_elt_dtor(struct rspamd_config_settings_elt *e)
{
@@ -2457,7 +2420,7 @@ rspamd_config_find_settings_id_ref(struct rspamd_config *cfg,
}
}
- return NULL;
+ return nullptr;
}
struct rspamd_config_settings_elt *rspamd_config_find_settings_name_ref(
@@ -2489,7 +2452,7 @@ void rspamd_config_register_settings_id(struct rspamd_config *cfg,
DL_DELETE(cfg->setting_ids, elt);
- nelt = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*nelt));
+ nelt = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_config_settings_elt);
nelt->id = id;
nelt->name = rspamd_mempool_strdup(cfg->cfg_pool, name);
@@ -2518,7 +2481,7 @@ void rspamd_config_register_settings_id(struct rspamd_config *cfg,
REF_RELEASE(elt);
}
else {
- elt = rspamd_mempool_alloc0(cfg->cfg_pool, sizeof(*elt));
+ elt = rspamd_mempool_alloc0_type(cfg->cfg_pool, struct rspamd_config_settings_elt);
elt->id = id;
elt->name = rspamd_mempool_strdup(cfg->cfg_pool, name);
@@ -2543,7 +2506,7 @@ void rspamd_config_register_settings_id(struct rspamd_config *cfg,
int rspamd_config_ev_backend_get(struct rspamd_config *cfg)
{
#define AUTO_BACKEND (ev_supported_backends() & ~EVBACKEND_IOURING)
- if (cfg == NULL || cfg->events_backend == NULL) {
+ if (cfg == nullptr || cfg->events_backend == nullptr) {
return AUTO_BACKEND;
}
@@ -2597,9 +2560,9 @@ int rspamd_config_ev_backend_get(struct rspamd_config *cfg)
const gchar *
rspamd_config_ev_backend_to_string(int ev_backend, gboolean *effective)
{
-#define SET_EFFECTIVE(b) \
- do { \
- if ((effective) != NULL) *(effective) = b; \
+#define SET_EFFECTIVE(b) \
+ do { \
+ if ((effective) != nullptr) *(effective) = b; \
} while (0)
if ((ev_backend & EVBACKEND_ALL) == EVBACKEND_ALL) {
@@ -2649,12 +2612,11 @@ struct rspamd_external_libs_ctx *
rspamd_init_libs(void)
{
struct rlimit rlim;
- struct rspamd_external_libs_ctx *ctx;
struct ottery_config *ottery_cfg;
- ctx = g_malloc0(sizeof(*ctx));
+ auto *ctx = g_new0(struct rspamd_external_libs_ctx, 1);
ctx->crypto_ctx = rspamd_cryptobox_init();
- ottery_cfg = g_malloc0(ottery_get_sizeof_config());
+ ottery_cfg = (struct ottery_config *) g_malloc0(ottery_get_sizeof_config());
ottery_config_init(ottery_cfg);
ctx->ottery_cfg = ottery_cfg;
@@ -2664,10 +2626,12 @@ rspamd_init_libs(void)
if ((ctx->crypto_ctx->cpu_config & CPUID_RDRAND) == 0) {
ottery_config_disable_entropy_sources(ottery_cfg,
OTTERY_ENTROPY_SRC_RDRAND);
+ }
+
+ g_assert(ottery_init(ottery_cfg) == 0);
#if OPENSSL_VERSION_NUMBER >= 0x1000104fL && OPENSSL_VERSION_NUMBER < 0x30000000L && !defined(LIBRESSL_VERSION_NUMBER)
- RAND_set_rand_engine(NULL);
+ RAND_set_rand_engine(nullptr);
#endif
- }
/* Configure utf8 library */
guint utf8_flags = 0;
@@ -2681,10 +2645,8 @@ rspamd_init_libs(void)
rspamd_fast_utf8_library_init(utf8_flags);
- g_assert(ottery_init(ottery_cfg) == 0);
-
#ifdef HAVE_LOCALE_H
- if (getenv("LANG") == NULL) {
+ if (getenv("LANG") == nullptr) {
setlocale(LC_ALL, "C");
setlocale(LC_CTYPE, "C");
setlocale(LC_MESSAGES, "C");
@@ -2719,13 +2681,13 @@ rspamd_open_zstd_dictionary(const char *path)
{
struct zstd_dictionary *dict;
- dict = g_malloc0(sizeof(*dict));
+ dict = g_new0(zstd_dictionary, 1);
dict->dict = rspamd_file_xmap(path, PROT_READ, &dict->size, TRUE);
- if (dict->dict == NULL) {
+ if (dict->dict == nullptr) {
g_free(dict);
- return NULL;
+ return nullptr;
}
dict->id = -1;
@@ -2733,7 +2695,7 @@ rspamd_open_zstd_dictionary(const char *path)
if (dict->id == 0) {
g_free(dict);
- return NULL;
+ return nullptr;
}
return dict;
@@ -2749,10 +2711,10 @@ rspamd_free_zstd_dictionary(struct zstd_dictionary *dict)
}
#ifdef HAVE_OPENBLAS_SET_NUM_THREADS
-extern void openblas_set_num_threads(int num_threads);
+extern "C" void openblas_set_num_threads(int num_threads);
#endif
#ifdef HAVE_BLI_THREAD_SET_NUM_THREADS
-extern void bli_thread_set_num_threads(int num_threads);
+extern "C" void bli_thread_set_num_threads(int num_threads);
#endif
gboolean
@@ -2762,35 +2724,43 @@ rspamd_config_libs(struct rspamd_external_libs_ctx *ctx,
size_t r;
gboolean ret = TRUE;
- g_assert(cfg != NULL);
+ g_assert(cfg != nullptr);
- if (ctx != NULL) {
+ if (ctx != nullptr) {
if (cfg->local_addrs) {
+ GError *err = nullptr;
ret = rspamd_config_radix_from_ucl(cfg, cfg->local_addrs,
"Local addresses",
(struct rspamd_radix_map_helper **) ctx->local_addrs,
- NULL,
- NULL, "local addresses");
+ &err,
+ nullptr, "local addresses");
+
+ if (!ret) {
+ msg_err_config("cannot load local addresses: %e", err);
+ g_error_free(err);
+
+ return ret;
+ }
}
rspamd_free_zstd_dictionary(ctx->in_dict);
rspamd_free_zstd_dictionary(ctx->out_dict);
if (ctx->out_zstream) {
- ZSTD_freeCStream(ctx->out_zstream);
- ctx->out_zstream = NULL;
+ ZSTD_freeCStream((ZSTD_CCtx *) ctx->out_zstream);
+ ctx->out_zstream = nullptr;
}
if (ctx->in_zstream) {
- ZSTD_freeDStream(ctx->in_zstream);
- ctx->in_zstream = NULL;
+ ZSTD_freeDStream((ZSTD_DCtx *) ctx->in_zstream);
+ ctx->in_zstream = nullptr;
}
if (cfg->zstd_input_dictionary) {
ctx->in_dict = rspamd_open_zstd_dictionary(
cfg->zstd_input_dictionary);
- if (ctx->in_dict == NULL) {
+ if (ctx->in_dict == nullptr) {
msg_err_config("cannot open zstd dictionary in %s",
cfg->zstd_input_dictionary);
}
@@ -2799,7 +2769,7 @@ rspamd_config_libs(struct rspamd_external_libs_ctx *ctx,
ctx->out_dict = rspamd_open_zstd_dictionary(
cfg->zstd_output_dictionary);
- if (ctx->out_dict == NULL) {
+ if (ctx->out_dict == nullptr) {
msg_err_config("cannot open zstd dictionary in %s",
cfg->zstd_output_dictionary);
}
@@ -2813,7 +2783,7 @@ rspamd_config_libs(struct rspamd_external_libs_ctx *ctx,
/* Toggle FIPS mode */
if (mode == 0) {
#if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
- if (EVP_set_default_properties(NULL, "fips=yes") != 1) {
+ if (EVP_set_default_properties(nullptr, "fips=yes") != 1) {
#else
if (FIPS_mode_set(1) != 1) {
#endif
@@ -2830,7 +2800,7 @@ rspamd_config_libs(struct rspamd_external_libs_ctx *ctx,
#else
msg_err_config("FIPS_mode_set failed: %s",
#endif
- ERR_error_string(err, NULL));
+ ERR_error_string(err, nullptr));
ret = FALSE;
}
else {
@@ -2846,24 +2816,24 @@ rspamd_config_libs(struct rspamd_external_libs_ctx *ctx,
/* Init decompression */
ctx->in_zstream = ZSTD_createDStream();
- r = ZSTD_initDStream(ctx->in_zstream);
+ r = ZSTD_initDStream((ZSTD_DCtx *) ctx->in_zstream);
if (ZSTD_isError(r)) {
msg_err("cannot init decompression stream: %s",
ZSTD_getErrorName(r));
- ZSTD_freeDStream(ctx->in_zstream);
- ctx->in_zstream = NULL;
+ ZSTD_freeDStream((ZSTD_DCtx *) ctx->in_zstream);
+ ctx->in_zstream = nullptr;
}
/* Init compression */
ctx->out_zstream = ZSTD_createCStream();
- r = ZSTD_initCStream(ctx->out_zstream, 1);
+ r = ZSTD_initCStream((ZSTD_CCtx *) ctx->out_zstream, 1);
if (ZSTD_isError(r)) {
msg_err("cannot init compression stream: %s",
ZSTD_getErrorName(r));
- ZSTD_freeCStream(ctx->out_zstream);
- ctx->out_zstream = NULL;
+ ZSTD_freeCStream((ZSTD_CCtx *) ctx->out_zstream);
+ ctx->out_zstream = nullptr;
}
#ifdef HAVE_OPENBLAS_SET_NUM_THREADS
openblas_set_num_threads(cfg->max_blas_threads);
@@ -2881,17 +2851,17 @@ rspamd_libs_reset_decompression(struct rspamd_external_libs_ctx *ctx)
{
gsize r;
- if (ctx->in_zstream == NULL) {
+ if (ctx->in_zstream == nullptr) {
return FALSE;
}
else {
- r = ZSTD_DCtx_reset(ctx->in_zstream, ZSTD_reset_session_only);
+ r = ZSTD_DCtx_reset((ZSTD_DCtx *) ctx->in_zstream, ZSTD_reset_session_only);
if (ZSTD_isError(r)) {
msg_err("cannot init decompression stream: %s",
ZSTD_getErrorName(r));
- ZSTD_freeDStream(ctx->in_zstream);
- ctx->in_zstream = NULL;
+ ZSTD_freeDStream((ZSTD_DCtx *) ctx->in_zstream);
+ ctx->in_zstream = nullptr;
return FALSE;
}
@@ -2905,21 +2875,21 @@ rspamd_libs_reset_compression(struct rspamd_external_libs_ctx *ctx)
{
gsize r;
- if (ctx->out_zstream == NULL) {
+ if (ctx->out_zstream == nullptr) {
return FALSE;
}
else {
/* Dictionary will be reused automatically if specified */
- r = ZSTD_CCtx_reset(ctx->out_zstream, ZSTD_reset_session_only);
+ r = ZSTD_CCtx_reset((ZSTD_CCtx *) ctx->out_zstream, ZSTD_reset_session_only);
if (!ZSTD_isError(r)) {
- r = ZSTD_CCtx_setPledgedSrcSize(ctx->out_zstream, ZSTD_CONTENTSIZE_UNKNOWN);
+ r = ZSTD_CCtx_setPledgedSrcSize((ZSTD_CCtx *) ctx->out_zstream, ZSTD_CONTENTSIZE_UNKNOWN);
}
if (ZSTD_isError(r)) {
msg_err("cannot init compression stream: %s",
ZSTD_getErrorName(r));
- ZSTD_freeCStream(ctx->out_zstream);
- ctx->out_zstream = NULL;
+ ZSTD_freeCStream((ZSTD_CCtx *) ctx->out_zstream);
+ ctx->out_zstream = nullptr;
return FALSE;
}
@@ -2930,7 +2900,7 @@ rspamd_libs_reset_compression(struct rspamd_external_libs_ctx *ctx)
void rspamd_deinit_libs(struct rspamd_external_libs_ctx *ctx)
{
- if (ctx != NULL) {
+ if (ctx != nullptr) {
g_free(ctx->ottery_cfg);
#ifdef HAVE_OPENSSL
@@ -2944,11 +2914,11 @@ void rspamd_deinit_libs(struct rspamd_external_libs_ctx *ctx)
rspamd_free_zstd_dictionary(ctx->out_dict);
if (ctx->out_zstream) {
- ZSTD_freeCStream(ctx->out_zstream);
+ ZSTD_freeCStream((ZSTD_CCtx *) ctx->out_zstream);
}
if (ctx->in_zstream) {
- ZSTD_freeDStream(ctx->in_zstream);
+ ZSTD_freeDStream((ZSTD_DCtx *) ctx->in_zstream);
}
rspamd_cryptobox_deinit(ctx->crypto_ctx);
@@ -2961,7 +2931,7 @@ gboolean
rspamd_ip_is_local_cfg(struct rspamd_config *cfg,
const rspamd_inet_addr_t *addr)
{
- struct rspamd_radix_map_helper *local_addrs = NULL;
+ struct rspamd_radix_map_helper *local_addrs = nullptr;
if (cfg && cfg->libs_ctx) {
local_addrs = *(struct rspamd_radix_map_helper **) cfg->libs_ctx->local_addrs;
@@ -2972,7 +2942,7 @@ rspamd_ip_is_local_cfg(struct rspamd_config *cfg,
}
if (local_addrs) {
- if (rspamd_match_radix_map_addr(local_addrs, addr) != NULL) {
+ if (rspamd_match_radix_map_addr(local_addrs, addr) != nullptr) {
return TRUE;
}
}
diff --git a/src/libserver/dns.c b/src/libserver/dns.c
index 84582202a..abe47dfdc 100644
--- a/src/libserver/dns.c
+++ b/src/libserver/dns.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -948,11 +948,11 @@ rspamd_dns_resolver_init(rspamd_logger_t *logger,
dns_resolver->ups);
cfg->dns_resolver = dns_resolver;
- if (cfg->rcl_obj) {
+ if (cfg->cfg_ucl_obj) {
/* Configure additional options */
const ucl_object_t *opts_section, *dns_section, *tmp;
- opts_section = ucl_object_lookup(cfg->rcl_obj, "options");
+ opts_section = ucl_object_lookup(cfg->cfg_ucl_obj, "options");
if (opts_section) {
/* TODO: implement a more simple merge logic */
diff --git a/src/libserver/dynamic_cfg.c b/src/libserver/dynamic_cfg.c
index 8254ebc91..cd5cc4e30 100644
--- a/src/libserver/dynamic_cfg.c
+++ b/src/libserver/dynamic_cfg.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -36,7 +36,7 @@ struct config_json_buf {
static void
apply_dynamic_conf(const ucl_object_t *top, struct rspamd_config *cfg)
{
- gint test_act;
+ enum rspamd_action_type test_act;
const ucl_object_t *cur_elt, *cur_nm, *it_val;
ucl_object_iter_t it = NULL;
const gchar *name;
diff --git a/src/libserver/fuzzy_backend/fuzzy_backend_redis.c b/src/libserver/fuzzy_backend/fuzzy_backend_redis.c
index 2f9d1ed10..9b5b3bc02 100644
--- a/src/libserver/fuzzy_backend/fuzzy_backend_redis.c
+++ b/src/libserver/fuzzy_backend/fuzzy_backend_redis.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -204,7 +204,7 @@ rspamd_fuzzy_backend_init_redis(struct rspamd_fuzzy_backend *bk,
/* Now try global redis settings */
if (!ret) {
- elt = ucl_object_lookup(cfg->rcl_obj, "redis");
+ elt = ucl_object_lookup(cfg->cfg_ucl_obj, "redis");
if (elt) {
const ucl_object_t *specific_obj;
diff --git a/src/libserver/http/http_context.c b/src/libserver/http/http_context.c
index 721bc2782..f08e33baf 100644
--- a/src/libserver/http/http_context.c
+++ b/src/libserver/http/http_context.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2019 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -210,7 +210,7 @@ rspamd_http_context_create(struct rspamd_config *cfg,
const ucl_object_t *http_obj;
ctx = rspamd_http_context_new_default(cfg, ev_base, ups_ctx);
- http_obj = ucl_object_lookup(cfg->rcl_obj, "http");
+ http_obj = ucl_object_lookup(cfg->cfg_ucl_obj, "http");
if (http_obj) {
const ucl_object_t *server_obj, *client_obj;
diff --git a/src/libserver/protocol.c b/src/libserver/protocol.c
index c8e3fe441..867455754 100644
--- a/src/libserver/protocol.c
+++ b/src/libserver/protocol.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -793,65 +793,66 @@ rspamd_protocol_parse_task_flags(rspamd_mempool_t *pool,
return TRUE;
}
-static struct rspamd_rcl_section *control_parser = NULL;
+static struct rspamd_rcl_sections_map *control_parser = NULL;
-static void
-rspamd_protocol_control_parser_init(void)
+RSPAMD_CONSTRUCTOR(rspamd_protocol_control_parser_ctor)
{
- struct rspamd_rcl_section *sub;
-
- if (control_parser == NULL) {
- sub = rspamd_rcl_add_section(&control_parser,
- "*",
- NULL,
- NULL,
- UCL_OBJECT,
- FALSE,
- TRUE);
- /* Default handlers */
- rspamd_rcl_add_default_handler(sub,
- "ip",
- rspamd_rcl_parse_struct_addr,
- G_STRUCT_OFFSET(struct rspamd_task, from_addr),
- 0,
- NULL);
- rspamd_rcl_add_default_handler(sub,
- "from",
- rspamd_rcl_parse_struct_mime_addr,
- G_STRUCT_OFFSET(struct rspamd_task, from_envelope),
- 0,
- NULL);
- rspamd_rcl_add_default_handler(sub,
- "rcpt",
- rspamd_rcl_parse_struct_mime_addr,
- G_STRUCT_OFFSET(struct rspamd_task, rcpt_envelope),
- 0,
- NULL);
- rspamd_rcl_add_default_handler(sub,
- "helo",
- rspamd_rcl_parse_struct_string,
- G_STRUCT_OFFSET(struct rspamd_task, helo),
- 0,
- NULL);
- rspamd_rcl_add_default_handler(sub,
- "user",
- rspamd_rcl_parse_struct_string,
- G_STRUCT_OFFSET(struct rspamd_task, auth_user),
- 0,
- NULL);
- rspamd_rcl_add_default_handler(sub,
- "pass_all",
- rspamd_protocol_parse_task_flags,
- G_STRUCT_OFFSET(struct rspamd_task, flags),
- 0,
- NULL);
- rspamd_rcl_add_default_handler(sub,
- "json",
- rspamd_protocol_parse_task_flags,
- G_STRUCT_OFFSET(struct rspamd_task, flags),
- 0,
- NULL);
- }
+
+ struct rspamd_rcl_section *sub = rspamd_rcl_add_section(&control_parser, NULL,
+ "*",
+ NULL,
+ NULL,
+ UCL_OBJECT,
+ FALSE,
+ TRUE);
+ /* Default handlers */
+ rspamd_rcl_add_default_handler(sub,
+ "ip",
+ rspamd_rcl_parse_struct_addr,
+ G_STRUCT_OFFSET(struct rspamd_task, from_addr),
+ 0,
+ NULL);
+ rspamd_rcl_add_default_handler(sub,
+ "from",
+ rspamd_rcl_parse_struct_mime_addr,
+ G_STRUCT_OFFSET(struct rspamd_task, from_envelope),
+ 0,
+ NULL);
+ rspamd_rcl_add_default_handler(sub,
+ "rcpt",
+ rspamd_rcl_parse_struct_mime_addr,
+ G_STRUCT_OFFSET(struct rspamd_task, rcpt_envelope),
+ 0,
+ NULL);
+ rspamd_rcl_add_default_handler(sub,
+ "helo",
+ rspamd_rcl_parse_struct_string,
+ G_STRUCT_OFFSET(struct rspamd_task, helo),
+ 0,
+ NULL);
+ rspamd_rcl_add_default_handler(sub,
+ "user",
+ rspamd_rcl_parse_struct_string,
+ G_STRUCT_OFFSET(struct rspamd_task, auth_user),
+ 0,
+ NULL);
+ rspamd_rcl_add_default_handler(sub,
+ "pass_all",
+ rspamd_protocol_parse_task_flags,
+ G_STRUCT_OFFSET(struct rspamd_task, flags),
+ 0,
+ NULL);
+ rspamd_rcl_add_default_handler(sub,
+ "json",
+ rspamd_protocol_parse_task_flags,
+ G_STRUCT_OFFSET(struct rspamd_task, flags),
+ 0,
+ NULL);
+}
+
+RSPAMD_DESTRUCTOR(rspamd_protocol_control_parser_dtor)
+{
+ rspamd_rcl_sections_free(control_parser);
}
gboolean
@@ -860,8 +861,6 @@ rspamd_protocol_handle_control(struct rspamd_task *task,
{
GError *err = NULL;
- rspamd_protocol_control_parser_init();
-
if (!rspamd_rcl_parse(control_parser, task->cfg, task, task->task_pool,
control, &err)) {
msg_warn_protocol("cannot parse control block: %e", err);
diff --git a/src/libserver/rspamd_symcache.h b/src/libserver/rspamd_symcache.h
index f2f95fcc5..45e460c11 100644
--- a/src/libserver/rspamd_symcache.h
+++ b/src/libserver/rspamd_symcache.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -123,7 +123,7 @@ gint rspamd_symcache_add_symbol(struct rspamd_symcache *cache,
gint priority,
symbol_func_t func,
gpointer user_data,
- enum rspamd_symbol_type type,
+ int type,
gint parent);
/**
diff --git a/src/libserver/symcache/symcache_c.cxx b/src/libserver/symcache/symcache_c.cxx
index 52881f77e..06801d244 100644
--- a/src/libserver/symcache/symcache_c.cxx
+++ b/src/libserver/symcache/symcache_c.cxx
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2022 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -63,7 +63,7 @@ gint rspamd_symcache_add_symbol(struct rspamd_symcache *cache,
gint priority,
symbol_func_t func,
gpointer user_data,
- enum rspamd_symbol_type type,
+ int type,
gint parent)
{
auto *real_cache = C_API_SYMCACHE(cache);
diff --git a/src/libserver/symcache/symcache_impl.cxx b/src/libserver/symcache/symcache_impl.cxx
index 94e90751b..6fd705be1 100644
--- a/src/libserver/symcache/symcache_impl.cxx
+++ b/src/libserver/symcache/symcache_impl.cxx
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2022 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -42,7 +42,7 @@ auto symcache::init() -> bool
if (cfg->cache_filename != nullptr) {
msg_debug_cache("loading symcache saved data from %s", cfg->cache_filename);
- res = load_items();
+ load_items();
}
ankerl::unordered_dense::set<int> disabled_ids;
@@ -717,7 +717,7 @@ auto symcache::add_symbol_with_callback(std::string_view name,
int priority,
symbol_func_t func,
void *user_data,
- enum rspamd_symbol_type flags_and_type) -> int
+ int flags_and_type) -> int
{
auto real_type_pair_maybe = item_type_from_c(flags_and_type);
@@ -786,7 +786,7 @@ auto symcache::add_symbol_with_callback(std::string_view name,
return id;
}
-auto symcache::add_virtual_symbol(std::string_view name, int parent_id, enum rspamd_symbol_type flags_and_type) -> int
+auto symcache::add_virtual_symbol(std::string_view name, int parent_id, int flags_and_type) -> int
{
if (name.empty()) {
msg_err_cache("cannot register a virtual symbol with no name; qed");
diff --git a/src/libserver/symcache/symcache_internal.hxx b/src/libserver/symcache/symcache_internal.hxx
index 240939780..255a4b1c1 100644
--- a/src/libserver/symcache/symcache_internal.hxx
+++ b/src/libserver/symcache/symcache_internal.hxx
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2022 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -458,7 +458,7 @@ public:
int priority,
symbol_func_t func,
void *user_data,
- enum rspamd_symbol_type flags_and_type) -> int;
+ int flags_and_type) -> int;
/**
* A method to add a generic virtual symbol with no function associated
* @param name must have some value, or a fatal error will strike you
@@ -467,7 +467,7 @@ public:
* @return id of a new symbol or -1 in case of failure
*/
auto add_virtual_symbol(std::string_view name, int parent_id,
- enum rspamd_symbol_type flags_and_type) -> int;
+ int flags_and_type) -> int;
/**
* Sets a lua callback to be called on peaks in execution time
diff --git a/src/libserver/symcache/symcache_item.cxx b/src/libserver/symcache/symcache_item.cxx
index a468aaf03..24e198dd3 100644
--- a/src/libserver/symcache/symcache_item.cxx
+++ b/src/libserver/symcache/symcache_item.cxx
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2022 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -537,7 +537,7 @@ auto virtual_item::resolve_parent(const symcache &cache) -> bool
return false;
}
-auto item_type_from_c(enum rspamd_symbol_type type) -> tl::expected<std::pair<symcache_item_type, int>, std::string>
+auto item_type_from_c(int type) -> tl::expected<std::pair<symcache_item_type, int>, std::string>
{
constexpr const auto trivial_types = SYMBOL_TYPE_CONNFILTER | SYMBOL_TYPE_PREFILTER | SYMBOL_TYPE_POSTFILTER | SYMBOL_TYPE_IDEMPOTENT | SYMBOL_TYPE_COMPOSITE | SYMBOL_TYPE_CLASSIFIER | SYMBOL_TYPE_VIRTUAL;
diff --git a/src/libserver/symcache/symcache_item.hxx b/src/libserver/symcache/symcache_item.hxx
index 5ceffa121..c159e7c47 100644
--- a/src/libserver/symcache/symcache_item.hxx
+++ b/src/libserver/symcache/symcache_item.hxx
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2022 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -85,7 +85,7 @@ constexpr static auto item_type_to_str(symcache_item_type t) -> const char *
* @param type input type as a C enum
* @return pair of type safe symcache_item_type + the remaining flags or an error
*/
-auto item_type_from_c(enum rspamd_symbol_type type) -> tl::expected<std::pair<symcache_item_type, int>, std::string>;
+auto item_type_from_c(int type) -> tl::expected<std::pair<symcache_item_type, int>, std::string>;
struct item_condition {
private:
diff --git a/src/libstat/backends/redis_backend.c b/src/libstat/backends/redis_backend.c
index 2e4711ae9..a0d11bb0d 100644
--- a/src/libstat/backends/redis_backend.c
+++ b/src/libstat/backends/redis_backend.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -1559,7 +1559,7 @@ rspamd_redis_init(struct rspamd_stat_ctx *ctx,
/* Now try global redis settings */
if (!ret) {
- obj = ucl_object_lookup(cfg->rcl_obj, "redis");
+ obj = ucl_object_lookup(cfg->cfg_ucl_obj, "redis");
if (obj) {
const ucl_object_t *specific_obj;
diff --git a/src/libstat/learn_cache/redis_cache.c b/src/libstat/learn_cache/redis_cache.c
index d5fe4ad48..3026009bc 100644
--- a/src/libstat/learn_cache/redis_cache.c
+++ b/src/libstat/learn_cache/redis_cache.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -275,7 +275,7 @@ rspamd_stat_cache_redis_init(struct rspamd_stat_ctx *ctx,
/* Now try global redis settings */
if (!ret) {
- obj = ucl_object_lookup(cfg->rcl_obj, "redis");
+ obj = ucl_object_lookup(cfg->cfg_ucl_obj, "redis");
if (obj) {
const ucl_object_t *specific_obj;
diff --git a/src/libutil/addr.c b/src/libutil/addr.c
index b54bd5539..e011c991a 100644
--- a/src/libutil/addr.c
+++ b/src/libutil/addr.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -1477,7 +1477,7 @@ rspamd_parse_host_port_priority(const gchar *str,
if (*addrs == NULL) {
*addrs = g_ptr_array_new_full(1,
- (GDestroyNotify) rspamd_inet_address_free);
+ pool == NULL ? NULL : (GDestroyNotify) rspamd_inet_address_free);
if (pool != NULL) {
rspamd_mempool_add_destructor(pool,
@@ -1486,7 +1486,7 @@ rspamd_parse_host_port_priority(const gchar *str,
}
if (v4_any) {
- cur_addr = rspamd_inet_addr_create(AF_INET, pool);
+ cur_addr = rspamd_inet_addr_create(AF_INET, NULL);
rspamd_parse_inet_address_ip4("0.0.0.0",
sizeof("0.0.0.0") - 1, &su.s4.sin_addr);
memcpy(&cur_addr->u.in.addr.s4.sin_addr, &su.s4.sin_addr,
@@ -1496,7 +1496,7 @@ rspamd_parse_host_port_priority(const gchar *str,
g_ptr_array_add(*addrs, cur_addr);
}
if (v6_any) {
- cur_addr = rspamd_inet_addr_create(AF_INET6, pool);
+ cur_addr = rspamd_inet_addr_create(AF_INET6, NULL);
rspamd_parse_inet_address_ip6("::",
sizeof("::") - 1, &su.s6.sin6_addr);
memcpy(&cur_addr->u.in.addr.s6.sin6_addr, &su.s6.sin6_addr,
diff --git a/src/libutil/cxx/file_util.hxx b/src/libutil/cxx/file_util.hxx
index a0c624726..45289053e 100644
--- a/src/libutil/cxx/file_util.hxx
+++ b/src/libutil/cxx/file_util.hxx
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2022 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -33,7 +33,16 @@ public:
virtual ~raii_file() noexcept;
static auto open(const char *fname, int flags) -> tl::expected<raii_file, error>;
+ static auto open(const std::string &fname, int flags) -> tl::expected<raii_file, error>
+ {
+ return open(fname.c_str(), flags);
+ };
static auto create(const char *fname, int flags, int perms) -> tl::expected<raii_file, error>;
+ static auto create(const std::string &fname, int flags, int perms) -> tl::expected<raii_file, error>
+ {
+ return create(fname.c_str(), flags, perms);
+ };
+
static auto create_temp(const char *fname, int flags, int perms) -> tl::expected<raii_file, error>;
static auto mkstemp(const char *pattern, int flags, int perms) -> tl::expected<raii_file, error>;
diff --git a/src/libutil/cxx/util.hxx b/src/libutil/cxx/util.hxx
index 9ef2f6295..32ec0b55c 100644
--- a/src/libutil/cxx/util.hxx
+++ b/src/libutil/cxx/util.hxx
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2021 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -40,6 +40,15 @@ constexpr auto array_of(Ts &&...t) -> std::array<typename std::decay_t<typename
return {{std::forward<T>(t)...}};
}
+/**
+ * Find a value in a map
+ * @tparam C Map type
+ * @tparam K Key type
+ * @tparam V Value type
+ * @param c Map to search
+ * @param k Key to search
+ * @return Value if found or std::nullopt otherwise
+ */
template<class C, class K, class V = typename C::mapped_type, typename std::enable_if_t<std::is_constructible_v<typename C::key_type, K> && std::is_constructible_v<typename C::mapped_type, V>, bool> = false>
constexpr auto find_map(const C &c, const K &k) -> std::optional<std::reference_wrapper<const V>>
{
@@ -53,8 +62,8 @@ constexpr auto find_map(const C &c, const K &k) -> std::optional<std::reference_
}
-template<typename _It>
-inline constexpr auto make_string_view_from_it(_It begin, _It end)
+template<typename It>
+inline constexpr auto make_string_view_from_it(It begin, It end)
{
using result_type = std::string_view;
@@ -91,6 +100,47 @@ inline auto string_foreach_line(const S &input, const F &functor)
}
}
+/**
+ * Iterate over elements in a string
+ * @tparam S string type
+ * @tparam D delimiter type
+ * @tparam F functor type
+ * @param input string to iterate
+ * @param delim delimiter to use
+ * @param functor functor to call
+ * @param ignore_empty ignore empty elements
+ * @return nothing
+ */
+template<class S, class D, class F,
+ typename std::enable_if_t<std::is_invocable_v<F, std::string_view> && std::is_constructible_v<std::string_view, S> && std::is_constructible_v<std::string_view, D>, bool> = true>
+inline auto string_foreach_delim(const S &input, const D &delim, const F &functor, const bool ignore_empty = true) -> void
+{
+ size_t first = 0;
+ auto sv_input = std::string_view{input};
+ auto sv_delim = std::string_view{delim};
+
+ while (first < sv_input.size()) {
+ const auto second = sv_input.find_first_of(sv_delim, first);
+
+ if (first != second || !ignore_empty) {
+ functor(sv_input.substr(first, second - first));
+ }
+
+ if (second == std::string_view::npos) {
+ break;
+ }
+
+ first = second + 1;
+ }
+}
+
+/**
+ * Split string on a character
+ * @tparam S string type
+ * @param input string to split
+ * @param chr character to split on
+ * @return pair of strings
+ */
template<class S, typename std::enable_if_t<std::is_constructible_v<std::string_view, S>, bool> = true>
inline auto string_split_on(const S &input, std::string_view::value_type chr) -> std::pair<std::string_view, std::string_view>
{
@@ -111,6 +161,10 @@ inline auto string_split_on(const S &input, std::string_view::value_type chr) ->
/**
* Enumerate for range loop
+ * @tparam T iterable type
+ * @tparam TIter iterator type
+ * @param iterable iterable object
+ * @return iterator object
*/
template<typename T,
typename TIter = decltype(std::begin(std::declval<T>())),
diff --git a/src/libutil/cxx/util_tests.cxx b/src/libutil/cxx/util_tests.cxx
index 2b3092779..6c3c17799 100644
--- a/src/libutil/cxx/util_tests.cxx
+++ b/src/libutil/cxx/util_tests.cxx
@@ -1,11 +1,11 @@
-/*-
+/*
* 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
+ * 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,
@@ -18,6 +18,7 @@
#define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL
#include "doctest/doctest.h"
+#include <vector>
using namespace rspamd;
using namespace std::literals::string_view_literals;
@@ -43,4 +44,39 @@ TEST_SUITE("cxx utils")
CHECK(res.second == expected.second);
}
}
+
+ TEST_CASE("string_foreach_delim")
+ {
+ std::tuple<std::string_view, std::string_view, std::pair<std::vector<std::string_view>, std::vector<std::string_view>>> cases[] = {
+ {"test"sv, ","sv, {{"test"}, {"test"}}},
+ {"test,test"sv, ","sv, {{"test", "test"}, {"test", "test"}}},
+ {"test, test"sv, ", "sv, {{"test", "test"}, {"test", "", "test"}}},
+ {"test, test,,"sv, ", "sv, {{"test", "test"}, {"test", "", "test", ""}}},
+ };
+
+ for (const auto &c: cases) {
+ auto res = std::vector<std::string_view>();
+ string_foreach_delim(std::get<0>(c), std::get<1>(c), [&](const auto &v) {
+ res.push_back(v);
+ });
+
+ auto compare_vec = []<class T>(const std::vector<T> &v1, const std::vector<T> &v2) {
+ CHECK(v1.size() == v2.size());
+ for (size_t i = 0; i < v1.size(); ++i) {
+ CHECK(v1[i] == v2[i]);
+ }
+ };
+
+ compare_vec(res, std::get<2>(c).first);
+
+ res.clear();
+ // Perform the same test but with no skip empty
+ string_foreach_delim(
+ std::get<0>(c), std::get<1>(c), [&](const auto &v) {
+ res.push_back(v);
+ },
+ false);
+ compare_vec(res, std::get<2>(c).second);
+ }
+ }
} \ No newline at end of file
diff --git a/src/libutil/mem_pool.c b/src/libutil/mem_pool.c
index f5771ff7a..bbd302a23 100644
--- a/src/libutil/mem_pool.c
+++ b/src/libutil/mem_pool.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -605,14 +605,21 @@ rspamd_mempool_alloc_shared_(rspamd_mempool_t *pool, gsize size, gsize alignment
gchar *
rspamd_mempool_strdup_(rspamd_mempool_t *pool, const gchar *src, const gchar *loc)
{
- gsize len;
+ if (src == NULL) {
+ return NULL;
+ }
+ return rspamd_mempool_strdup_len_(pool, src, strlen(src), loc);
+}
+
+gchar *
+rspamd_mempool_strdup_len_(rspamd_mempool_t *pool, const gchar *src, gsize len, const gchar *loc)
+{
gchar *newstr;
if (src == NULL) {
return NULL;
}
- len = strlen(src);
newstr = rspamd_mempool_alloc_(pool, len + 1, MIN_MEM_ALIGNMENT, loc);
memcpy(newstr, src, len);
newstr[len] = '\0';
diff --git a/src/libutil/mem_pool.h b/src/libutil/mem_pool.h
index 23f70092f..425a6b297 100644
--- a/src/libutil/mem_pool.h
+++ b/src/libutil/mem_pool.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2019 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -216,6 +216,10 @@ gchar *rspamd_mempool_strdup_(rspamd_mempool_t *pool, const gchar *src, const gc
RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT);
#define rspamd_mempool_strdup(pool, src) \
rspamd_mempool_strdup_((pool), (src), (G_STRLOC))
+gchar *rspamd_mempool_strdup_len_(rspamd_mempool_t *pool, const gchar *src, gsize len, const gchar *loc)
+ RSPAMD_ATTR_ALLOC_ALIGN(MIN_MEM_ALIGNMENT);
+#define rspamd_mempool_strdup_len(pool, src, len) \
+ rspamd_mempool_strdup_len_((pool), (src), (len), (G_STRLOC))
struct f_str_tok;
diff --git a/src/lua/lua_cfg_file.c b/src/lua/lua_cfg_file.c
index 0386c0969..75bc3806d 100644
--- a/src/lua/lua_cfg_file.c
+++ b/src/lua/lua_cfg_file.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -124,7 +124,7 @@ void rspamd_lua_post_load_config(struct rspamd_config *cfg)
if (obj != NULL) {
ucl_object_sort_keys(obj, UCL_SORT_KEYS_DEFAULT);
- ucl_object_insert_key_merged(cfg->rcl_obj,
+ ucl_object_insert_key_merged(cfg->cfg_ucl_obj,
obj,
name,
strlen(name),
diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h
index bf887e301..cc2b94390 100644
--- a/src/lua/lua_common.h
+++ b/src/lua/lua_common.h
@@ -97,7 +97,7 @@ static inline int lua_absindex(lua_State *L, int i)
extern const luaL_reg null_reg[];
-#define RSPAMD_LUA_API_VERSION 12
+#define RSPAMD_LUA_CFG_STATE(cfg) ((lua_State *) ((cfg)->lua_state))
/**
* Lua IP address structure
*/
@@ -427,15 +427,6 @@ double rspamd_lua_normalize(struct rspamd_config *cfg,
/* Config file functions */
void rspamd_lua_post_load_config(struct rspamd_config *cfg);
-gboolean rspamd_lua_handle_param(struct rspamd_task *task,
- gchar *mname,
- gchar *optname,
- enum lua_var_type expected_type,
- gpointer *res);
-
-gboolean rspamd_lua_check_condition(struct rspamd_config *cfg,
- const gchar *condition);
-
void rspamd_lua_dumpstack(lua_State *L);
/* Set lua path according to the configuration */
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index d36245247..a044827a7 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -1044,7 +1044,7 @@ lua_config_get_all_opt(lua_State *L)
mname = luaL_checkstring(L, 2);
if (mname) {
- obj = ucl_obj_get_key(cfg->rcl_obj, mname);
+ obj = ucl_obj_get_key(cfg->cfg_ucl_obj, mname);
/* Flatten object */
if (obj != NULL && (ucl_object_type(obj) == UCL_OBJECT ||
ucl_object_type(obj) == UCL_ARRAY)) {
@@ -1114,8 +1114,8 @@ lua_config_get_ucl(lua_State *L)
lua_rawgeti(L, LUA_REGISTRYINDEX, cached->ref);
}
else {
- if (cfg->rcl_obj) {
- ucl_object_push_lua(L, cfg->rcl_obj, true);
+ if (cfg->cfg_ucl_obj) {
+ ucl_object_push_lua(L, cfg->cfg_ucl_obj, true);
lua_pushvalue(L, -1);
cached = rspamd_mempool_alloc(cfg->cfg_pool, sizeof(*cached));
cached->L = L;
@@ -1725,7 +1725,7 @@ lua_config_get_key(lua_State *L)
name = luaL_checklstring(L, 2, &namelen);
if (name && cfg) {
- val = ucl_object_lookup_len(cfg->rcl_obj, name, namelen);
+ val = ucl_object_lookup_len(cfg->cfg_ucl_obj, name, namelen);
if (val != NULL) {
ucl_object_push_lua(L, val, val->type != UCL_ARRAY);
}
@@ -2581,24 +2581,27 @@ lua_config_get_metric_action(lua_State *L)
return 1;
}
+static void
+lua_config_actions_cb(struct rspamd_action *act, void *cbd)
+{
+ lua_State *L = (lua_State *) cbd;
+
+ if (!isnan(act->threshold)) {
+ lua_pushstring(L, act->name);
+ lua_pushnumber(L, act->threshold);
+ lua_settable(L, -3);
+ }
+}
+
static gint
lua_config_get_all_actions(lua_State *L)
{
LUA_TRACE_POINT;
struct rspamd_config *cfg = lua_check_config(L, 1);
- struct rspamd_action *act, *tmp;
if (cfg) {
- lua_createtable(L, 0, HASH_COUNT(cfg->actions));
-
- HASH_ITER(hh, cfg->actions, act, tmp)
- {
- if (!isnan(act->threshold)) {
- lua_pushstring(L, act->name);
- lua_pushnumber(L, act->threshold);
- lua_settable(L, -3);
- }
- }
+ lua_createtable(L, 0, rspamd_config_actions_size(cfg));
+ rspamd_config_actions_foreach(cfg, lua_config_actions_cb, L);
}
else {
return luaL_error(L, "invalid arguments, rspamd_config expected");
@@ -4420,7 +4423,7 @@ lua_config_parse_rcl(lua_State *L)
GHashTable *excluded = g_hash_table_new_full(rspamd_str_hash, rspamd_str_equal,
g_free, NULL);
GError *err = NULL;
- struct rspamd_rcl_section *top;
+ struct rspamd_rcl_sections_map *top;
if (cfg) {
if (lua_istable(L, 2)) {
@@ -4436,12 +4439,12 @@ lua_config_parse_rcl(lua_State *L)
top = rspamd_rcl_config_init(cfg, excluded);
- if (!rspamd_rcl_parse(top, cfg, cfg, cfg->cfg_pool, cfg->rcl_obj, &err)) {
+ if (!rspamd_rcl_parse(top, cfg, cfg, cfg->cfg_pool, cfg->cfg_ucl_obj, &err)) {
lua_pushboolean(L, false);
lua_pushfstring(L, "failed to load config: %s", err->message);
g_error_free(err);
g_hash_table_unref(excluded);
- rspamd_rcl_section_free(top);
+ rspamd_rcl_sections_free(top);
return 2;
}
@@ -4451,7 +4454,7 @@ lua_config_parse_rcl(lua_State *L)
}
g_hash_table_unref(excluded);
- rspamd_rcl_section_free(top);
+ rspamd_rcl_sections_free(top);
lua_pushboolean(L, true);
return 1;
diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c
index 4fb6fe347..351dd9208 100644
--- a/src/lua/lua_task.c
+++ b/src/lua/lua_task.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -2299,7 +2299,7 @@ lua_task_set_pre_result(lua_State *L)
}
}
- gint internal_type;
+ enum rspamd_action_type internal_type;
if (strcmp(act_str, "accept") == 0) {
/* Compatibility! */
@@ -2313,14 +2313,6 @@ lua_task_set_pre_result(lua_State *L)
action = rspamd_config_get_action(task->cfg, act_str);
if (action == NULL) {
- struct rspamd_action *tmp;
-
- HASH_ITER(hh, task->cfg->actions, action, tmp)
- {
- msg_err_task("known defined action: %s = %f",
- action->name, action->threshold);
- }
-
return luaL_error(L, "unknown action %s", act_str);
}
@@ -5700,7 +5692,7 @@ lua_task_set_settings(lua_State *L)
const gchar *act_name = ucl_object_key(cur);
struct rspamd_action_config *action_config = NULL;
double act_score;
- int act_type;
+ enum rspamd_action_type act_type;
if (!rspamd_action_from_str(act_name, &act_type)) {
act_type = -1;
@@ -5730,7 +5722,7 @@ lua_task_set_settings(lua_State *L)
if (!isnan(act_score)) {
struct rspamd_action *new_act;
- HASH_FIND_STR(task->cfg->actions, act_name, new_act);
+ new_act = rspamd_config_get_action(task->cfg, act_name);
if (new_act == NULL) {
/* New action! */
diff --git a/src/lua/lua_util.c b/src/lua/lua_util.c
index 503dd8ffb..40f6f6c48 100644
--- a/src/lua/lua_util.c
+++ b/src/lua/lua_util.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -858,7 +858,7 @@ lua_util_config_from_ucl(lua_State *L)
{
LUA_TRACE_POINT;
struct rspamd_config *cfg = NULL, **pcfg;
- struct rspamd_rcl_section *top;
+ struct rspamd_rcl_sections_map *top;
GError *err = NULL;
ucl_object_t *obj;
const char *str_options = NULL;
@@ -882,10 +882,10 @@ lua_util_config_from_ucl(lua_State *L)
cfg = rspamd_config_new(RSPAMD_CONFIG_INIT_SKIP_LUA);
cfg->lua_state = L;
- cfg->rcl_obj = obj;
+ cfg->cfg_ucl_obj = obj;
top = rspamd_rcl_config_init(cfg, NULL);
- if (!rspamd_rcl_parse(top, cfg, cfg, cfg->cfg_pool, cfg->rcl_obj, &err)) {
+ if (!rspamd_rcl_parse(top, cfg, cfg, cfg->cfg_pool, cfg->cfg_ucl_obj, &err)) {
msg_err("rcl parse error: %s", err->message);
ucl_object_unref(obj);
lua_pushnil(L);
@@ -901,6 +901,8 @@ lua_util_config_from_ucl(lua_State *L)
rspamd_lua_setclass(L, "rspamd{config}", -1);
*pcfg = cfg;
}
+
+ rspamd_rcl_sections_free(top);
}
return 1;
diff --git a/src/plugins/regexp.c b/src/plugins/regexp.c
index 22a348669..59a84c507 100644
--- a/src/plugins/regexp.c
+++ b/src/plugins/regexp.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -140,7 +140,7 @@ gint regexp_module_config(struct rspamd_config *cfg, bool validate)
return TRUE;
}
- sec = ucl_object_lookup(cfg->rcl_obj, "regexp");
+ sec = ucl_object_lookup(cfg->cfg_ucl_obj, "regexp");
if (sec == NULL) {
msg_err_config("regexp module enabled, but no rules are defined");
return TRUE;
diff --git a/src/rspamadm/configdump.c b/src/rspamadm/configdump.c
index 23e02db58..dc8b82218 100644
--- a/src/rspamadm/configdump.c
+++ b/src/rspamadm/configdump.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -298,7 +298,7 @@ rspamadm_configdump(gint argc, gchar **argv, const struct rspamadm_command *cmd)
rspamadm_execute_lua_ucl_subr(argc,
argv,
- cfg->rcl_obj,
+ cfg->cfg_ucl_obj,
"plugins_stats",
FALSE);
@@ -316,7 +316,7 @@ rspamadm_configdump(gint argc, gchar **argv, const struct rspamadm_command *cmd)
g_hash_table_iter_init(&it, cfg->symbols);
ucl_object_t *sym_ucl = ucl_object_typed_new(UCL_OBJECT);
- const ucl_object_t *all_symbols_ucl = ucl_object_lookup(cfg->rcl_obj, "symbols");
+ const ucl_object_t *all_symbols_ucl = ucl_object_lookup(cfg->cfg_ucl_obj, "symbols");
while (g_hash_table_iter_next(&it, &sk, &sv)) {
const gchar *sym_name = (const gchar *) sk;
@@ -521,11 +521,11 @@ rspamadm_configdump(gint argc, gchar **argv, const struct rspamadm_command *cmd)
/* Output configuration */
if (argc == 1) {
- rspamadm_dump_section_obj(cfg, cfg->rcl_obj, cfg->doc_strings);
+ rspamadm_dump_section_obj(cfg, cfg->cfg_ucl_obj, cfg->doc_strings);
}
else {
for (i = 1; i < argc; i++) {
- obj = ucl_object_lookup_path(cfg->rcl_obj, argv[i]);
+ obj = ucl_object_lookup_path(cfg->cfg_ucl_obj, argv[i]);
doc_obj = ucl_object_lookup_path(cfg->doc_strings, argv[i]);
if (!obj) {
diff --git a/src/rspamadm/confighelp.c b/src/rspamadm/confighelp.c
index b81f23621..2ad07c0a6 100644
--- a/src/rspamadm/confighelp.c
+++ b/src/rspamadm/confighelp.c
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -233,7 +233,7 @@ rspamadm_confighelp(gint argc, gchar **argv, const struct rspamadm_command *cmd)
rspamd_rcl_config_init(cfg, NULL);
lua_pushboolean(cfg->lua_state, true);
lua_setglobal(cfg->lua_state, "confighelp");
- rspamd_rcl_add_lua_plugins_path(cfg, plugins_path, FALSE, NULL, NULL);
+ rspamd_rcl_add_lua_plugins_path(cfg->rcl_top_section, cfg, plugins_path, FALSE, NULL);
/* Init modules to get documentation strings */
i = 0;
@@ -254,7 +254,7 @@ rspamadm_confighelp(gint argc, gchar **argv, const struct rspamadm_command *cmd)
}
/* Init lua modules */
- rspamd_lua_set_path(cfg->lua_state, cfg->rcl_obj, ucl_vars);
+ rspamd_lua_set_path(cfg->lua_state, cfg->cfg_ucl_obj, ucl_vars);
rspamd_init_lua_filters(cfg, true, false);
if (argc > 1) {
diff --git a/src/rspamd.h b/src/rspamd.h
index b3aef558b..523ea79c3 100644
--- a/src/rspamd.h
+++ b/src/rspamd.h
@@ -1,11 +1,11 @@
-/*-
- * Copyright 2016-2017 Vsevolod Stakhov
+/*
+ * 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
+ * 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,
@@ -68,6 +68,7 @@ enum rspamd_worker_flags {
RSPAMD_WORKER_CONTROLLER = (1 << 6),
RSPAMD_WORKER_NO_TERMINATE_DELAY = (1 << 7),
RSPAMD_WORKER_OLD_CONFIG = (1 << 8),
+ RSPAMD_WORKER_NO_STRICT_CONFIG = (1 << 9),
};
struct rspamd_worker_accept_event {
@@ -352,8 +353,8 @@ struct rspamd_external_libs_ctx {
void **local_addrs;
struct rspamd_cryptobox_library_ctx *crypto_ctx;
struct ottery_config *ottery_cfg;
- SSL_CTX *ssl_ctx;
- SSL_CTX *ssl_ctx_noverify;
+ void *ssl_ctx;
+ void *ssl_ctx_noverify;
struct zstd_dictionary *in_dict;
struct zstd_dictionary *out_dict;
void *out_zstream;