aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lua/lua_config.c108
m---------src/ucl0
2 files changed, 108 insertions, 0 deletions
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index 8e57aae94..162c7b842 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -39,6 +39,7 @@ LUA_FUNCTION_DEF (config, register_function);
LUA_FUNCTION_DEF (config, add_radix_map);
LUA_FUNCTION_DEF (config, add_hash_map);
LUA_FUNCTION_DEF (config, add_kv_map);
+LUA_FUNCTION_DEF (config, add_map);
LUA_FUNCTION_DEF (config, get_classifier);
LUA_FUNCTION_DEF (config, register_symbol);
LUA_FUNCTION_DEF (config, register_symbols);
@@ -58,6 +59,7 @@ static const struct luaL_reg configlib_m[] = {
LUA_INTERFACE_DEF (config, add_radix_map),
LUA_INTERFACE_DEF (config, add_hash_map),
LUA_INTERFACE_DEF (config, add_kv_map),
+ LUA_INTERFACE_DEF (config, add_map),
LUA_INTERFACE_DEF (config, get_classifier),
LUA_INTERFACE_DEF (config, register_symbol),
LUA_INTERFACE_DEF (config, register_symbols),
@@ -543,6 +545,112 @@ lua_config_add_kv_map (lua_State *L)
}
+struct lua_map_callback_data {
+ lua_State *L;
+ gint ref;
+ GString *data;
+};
+
+static gchar *
+lua_map_read (rspamd_mempool_t *pool, gchar *chunk, gint len,
+ struct map_cb_data *data)
+{
+ struct lua_map_callback_data *cbdata, *old;
+
+ if (data->cur_data == NULL) {
+ cbdata = g_slice_alloc (sizeof (*cbdata));
+ old = (struct lua_map_callback_data *)data->prev_data;
+ cbdata->L = old->L;
+ cbdata->ref = old->ref;
+ }
+ else {
+ cbdata = (struct lua_map_callback_data *)data->cur_data;
+ }
+
+ if (cbdata->data == NULL) {
+ cbdata->data = g_string_new_len (chunk, len);
+ }
+ else {
+ g_string_append_len (cbdata->data, chunk, len);
+ }
+
+ return NULL;
+}
+
+void
+lua_map_fin (rspamd_mempool_t * pool, struct map_cb_data *data)
+{
+ struct lua_map_callback_data *cbdata, *old;
+
+ if (data->prev_data) {
+ /* Cleanup old data */
+ old = (struct lua_map_callback_data *)data->prev_data;
+ if (old->data) {
+ g_string_free (old->data, TRUE);
+ }
+ g_slice_free1 (sizeof (*old), old);
+ }
+
+ if (data->cur_data) {
+ cbdata = (struct lua_map_callback_data *)data->cur_data;
+ }
+ else {
+ msg_err ("no data read for map");
+ return;
+ }
+
+ if (cbdata->data != NULL && cbdata->data->len != 0) {
+ lua_rawgeti (cbdata->L, LUA_REGISTRYINDEX, cbdata->ref);
+ lua_pushlstring (cbdata->L, cbdata->data->str, cbdata->data->len);
+
+ if (lua_pcall (cbdata->L, 1, 0, 0) != 0) {
+ msg_info ("call to %s failed: %s", "local function",
+ lua_tostring (cbdata->L, -1));
+ }
+ }
+}
+
+static gint
+lua_config_add_map (lua_State *L)
+{
+ struct rspamd_config *cfg = lua_check_config (L);
+ const gchar *map_line, *description;
+ struct lua_map_callback_data *cbdata, **pcbdata;
+
+ if (cfg) {
+ map_line = luaL_checkstring (L, 2);
+ description = lua_tostring (L, 3);
+
+ if (lua_type (L, 4) == LUA_TFUNCTION) {
+ cbdata = g_slice_alloc (sizeof (*cbdata));
+ cbdata->L = L;
+ cbdata->data = NULL;
+ lua_pushvalue (L, 4);
+ /* Get a reference */
+ cbdata->ref = luaL_ref (L, LUA_REGISTRYINDEX);
+ pcbdata = rspamd_mempool_alloc (cfg->cfg_pool, sizeof (cbdata));
+ *pcbdata = cbdata;
+ if (!add_map (cfg, map_line, description, lua_map_read, lua_map_fin,
+ (void **)pcbdata)) {
+ msg_warn ("invalid hash map %s", map_line);
+ lua_pushboolean (L, false);
+ }
+ else {
+ lua_pushboolean (L, true);
+ }
+ }
+ else {
+ msg_warn ("invalid callback argument for map %s", map_line);
+ lua_pushboolean (L, false);
+ }
+ }
+ else {
+ lua_pushboolean (L, false);
+ }
+
+ return 1;
+}
+
/*** Metric functions ***/
diff --git a/src/ucl b/src/ucl
-Subproject 4d9f818345e831d5f32aada381c90733e41e48f
+Subproject bf78fc2f31981411ff3bb20fb22d11056224f1c