@@ -1,3 +1,19 @@ | |||
/* | |||
* Copyright 2023 Vsevolod Stakhov | |||
* | |||
* Licensed under the Apache License, Version 2.0 (the "License"); | |||
* you may not use this file except in compliance with the License. | |||
* You may obtain a copy of the License at | |||
* | |||
* http://www.apache.org/licenses/LICENSE-2.0 | |||
* | |||
* Unless required by applicable law or agreed to in writing, software | |||
* distributed under the License is distributed on an "AS IS" BASIS, | |||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
* See the License for the specific language governing permissions and | |||
* limitations under the License. | |||
*/ | |||
/* Copyright (c) 2014, Vsevolod Stakhov | |||
* All rights reserved. | |||
* | |||
@@ -26,11 +42,16 @@ | |||
#ifdef HAVE_CONFIG_H | |||
#include "config.h" | |||
#endif | |||
#include "ucl.h" | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
/* Include C++ guard as Lua headers miss one */ | |||
#include <lua.h> | |||
#include <lauxlib.h> | |||
#include <lualib.h> | |||
#include "ucl.h" | |||
/** | |||
* Closure structure for lua function storing inside UCL | |||
@@ -44,7 +65,7 @@ struct ucl_lua_funcdata { | |||
/** | |||
* Initialize lua UCL API | |||
*/ | |||
UCL_EXTERN int luaopen_ucl (lua_State *L); | |||
UCL_EXTERN int luaopen_ucl(lua_State *L); | |||
/** | |||
* Import UCL object from lua state | |||
@@ -52,7 +73,7 @@ UCL_EXTERN int luaopen_ucl (lua_State *L); | |||
* @param idx index of object at the lua stack to convert to UCL | |||
* @return new UCL object or NULL, the caller should unref object after using | |||
*/ | |||
UCL_EXTERN ucl_object_t* ucl_object_lua_import (lua_State *L, int idx); | |||
UCL_EXTERN ucl_object_t *ucl_object_lua_import(lua_State *L, int idx); | |||
/** | |||
* Import UCL object from lua state, escaping JSON strings | |||
@@ -60,7 +81,7 @@ UCL_EXTERN ucl_object_t* ucl_object_lua_import (lua_State *L, int idx); | |||
* @param idx index of object at the lua stack to convert to UCL | |||
* @return new UCL object or NULL, the caller should unref object after using | |||
*/ | |||
UCL_EXTERN ucl_object_t* ucl_object_lua_import_escape (lua_State *L, int idx); | |||
UCL_EXTERN ucl_object_t *ucl_object_lua_import_escape(lua_State *L, int idx); | |||
/** | |||
* Push an object to lua | |||
@@ -68,18 +89,21 @@ UCL_EXTERN ucl_object_t* ucl_object_lua_import_escape (lua_State *L, int idx); | |||
* @param obj object to push | |||
* @param allow_array traverse over implicit arrays | |||
*/ | |||
UCL_EXTERN int ucl_object_push_lua (lua_State *L, | |||
const ucl_object_t *obj, bool allow_array); | |||
UCL_EXTERN int ucl_object_push_lua(lua_State *L, | |||
const ucl_object_t *obj, bool allow_array); | |||
/** | |||
* Push an object to lua replacing all ucl.null with `false` | |||
* @param L lua state | |||
* @param obj object to push | |||
* @param allow_array traverse over implicit arrays | |||
*/ | |||
UCL_EXTERN int ucl_object_push_lua_filter_nil (lua_State *L, | |||
const ucl_object_t *obj, | |||
bool allow_array); | |||
UCL_EXTERN int ucl_object_push_lua_filter_nil(lua_State *L, | |||
const ucl_object_t *obj, | |||
bool allow_array); | |||
UCL_EXTERN struct ucl_lua_funcdata* ucl_object_toclosure (const ucl_object_t *obj); | |||
UCL_EXTERN struct ucl_lua_funcdata *ucl_object_toclosure(const ucl_object_t *obj); | |||
#ifdef __cplusplus | |||
} /* extern "C" */ | |||
#endif | |||
#endif /* LUA_UCL_H_ */ |
@@ -856,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, \ |
@@ -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" | |||
@@ -31,7 +32,6 @@ | |||
#include <string> | |||
#include <filesystem> | |||
#include <memory> | |||
#include <algorithm> | |||
#include "contrib/ankerl/unordered_dense.h" | |||
#include "fmt/core.h" | |||
#include "libutil/cxx/util.hxx" | |||
@@ -52,20 +52,20 @@ struct rspamd_rcl_default_handler_data { | |||
struct rspamd_rcl_sections_map; | |||
struct rspamd_rcl_section { | |||
struct rspamd_rcl_sections_map *top; | |||
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 */ | |||
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 */ | |||
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 { | |||
@@ -74,10 +74,19 @@ struct rspamd_worker_param_parser { | |||
}; | |||
struct rspamd_worker_cfg_parser { | |||
ankerl::unordered_dense::map<std::pair<std::string, gpointer>, rspamd_worker_param_parser> parsers; /**< parsers hash */ | |||
gint type; /**< workers quark */ | |||
gboolean (*def_obj_parser)(ucl_object_t *obj, gpointer ud); /**< | |||
default object parser */ | |||
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 */ | |||
gpointer def_ud; | |||
}; | |||
@@ -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" |
@@ -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); |
@@ -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; | |||
@@ -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; |
@@ -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; |