]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Add an emitter from rcl object to lua.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 2 Oct 2013 12:44:01 +0000 (13:44 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 2 Oct 2013 12:44:01 +0000 (13:44 +0100)
src/cfg_file.h
src/cfg_utils.c
src/lua/CMakeLists.txt
src/lua/lua_common.h
src/lua/lua_config.c
src/lua/lua_rcl.c [new file with mode: 0644]

index 89e4870db4afa227de5ec8748026d9dbf36181f3..e7e12297752b95dad4324c1e4407211275d9160e 100644 (file)
@@ -348,8 +348,7 @@ struct config_file {
        GList *workers;                                                                 /**< linked list of all workers params                                  */
        struct rspamd_worker_cfg_parser *wrk_parsers;   /**< hash for worker config parsers, indexed by worker quarks */
        gchar *filters_str;                                                             /**< string of filters                                                                  */
-       GHashTable* modules_opts;                                               /**< hash for module options indexed by module name             */
-       GHashTable* modules_metas;                                              /**< hash for module meta options indexed by module name*/
+       rspamd_cl_object_t *rcl_obj;                                    /**< rcl object                                                                                 */
        GHashTable* variables;                                                  /**< hash of $variables defined in config, indexed by variable name */
        GHashTable* metrics;                                                    /**< hash of metrics indexed by metric name                             */
        GList* symbols_groups;                                                  /**< groups of symbols                                                                  */
@@ -449,7 +448,8 @@ void free_config (struct config_file *cfg);
  * @param opt_name name of option to get
  * @return module value or NULL if option does not defined
  */
-gchar* get_module_opt (struct config_file *cfg, gchar *module_name, gchar *opt_name);
+rspamd_cl_object_t* get_module_opt (struct config_file *cfg, const gchar *module_name,
+               const gchar *opt_name);
 
 /**
  * Parse limit
@@ -534,11 +534,6 @@ gboolean parse_normalizer (struct config_file *cfg, struct statfile *st, const g
  */
 gboolean read_xml_config (struct config_file *cfg, const gchar *filename);
 
-/*
- * Check modules configuration for semantic validity
- */
-gboolean check_modules_config (struct config_file *cfg);
-
 /*
  * Register symbols of classifiers inside metrics
  */
index e7e57cd8a526a4e048f267f1a03321fa38aef03a..906f4406fc4ef8b56a926c2d895e3575a0af6e94 100644 (file)
@@ -241,8 +241,6 @@ init_defaults (struct config_file *cfg)
        cfg->max_diff = 20480;
 
        cfg->max_statfile_size = DEFAULT_STATFILE_SIZE;
-       cfg->modules_opts = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
-       cfg->modules_metas = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
        cfg->variables = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
        cfg->metrics = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
        cfg->c_modules = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
@@ -267,9 +265,7 @@ free_config (struct config_file *cfg)
        struct symbols_group                    *gr;
 
        remove_all_maps (cfg);
-       g_hash_table_remove_all (cfg->modules_opts);
-       g_hash_table_unref (cfg->modules_opts);
-       g_hash_table_unref (cfg->modules_metas);
+       rspamd_cl_obj_unref (cfg->rcl_obj);
        g_hash_table_remove_all (cfg->variables);
        g_hash_table_unref (cfg->variables);
        g_hash_table_remove_all (cfg->metrics);
@@ -303,51 +299,17 @@ free_config (struct config_file *cfg)
        memory_pool_delete (cfg->cfg_pool);
 }
 
-gchar                           *
-get_module_opt (struct config_file *cfg, gchar *module_name, gchar *opt_name)
+rspamd_cl_object_t        *
+get_module_opt (struct config_file *cfg, const gchar *module_name, const gchar *opt_name)
 {
-       GList                          *cur_opt;
-       struct module_opt              *cur;
-       static gchar                     numbuf[64];
+       rspamd_cl_object_t *res = NULL, *sec;
 
-       cur_opt = g_hash_table_lookup (cfg->modules_opts, module_name);
-       if (cur_opt == NULL) {
-               return NULL;
+       sec = rspamd_cl_obj_get_key (cfg->rcl_obj, module_name);
+       if (sec != NULL) {
+               res = rspamd_cl_obj_get_key (cfg->rcl_obj, opt_name);
        }
 
-       while (cur_opt) {
-               cur = cur_opt->data;
-               if (strcmp (cur->param, opt_name) == 0) {
-                       /* Check if it is lua variable */
-                       if (! cur->is_lua) {
-                               /* Plain variable */
-                               return cur->value;
-                       }
-                       else {
-                               /* Check type */
-                               switch (cur->lua_type) {
-                                       case LUA_VAR_NUM:
-                                               /* numbuf is static, so it is safe to return it "as is" */
-                                               snprintf (numbuf, sizeof (numbuf), "%f", *(double *)cur->actual_data);
-                                               return numbuf;
-                                       case LUA_VAR_BOOLEAN:
-                                               snprintf (numbuf, sizeof (numbuf), "%s", *(gboolean *)cur->actual_data ? "yes" : "no");
-                                               return numbuf;
-                                       case LUA_VAR_STRING:
-                                               return (gchar *)cur->actual_data;
-                                       case LUA_VAR_FUNCTION:
-                                               msg_info ("option %s is dynamic, so it cannot be aqquired statically", opt_name);
-                                               return NULL;
-                                       case LUA_VAR_UNKNOWN:
-                                               msg_info ("option %s has unknown type, maybe there is error in LUA code", opt_name);
-                                               return NULL;
-                               }
-                       }
-               }
-               cur_opt = g_list_next (cur_opt);
-       }
-
-       return NULL;
+       return res;
 }
 
 guint64
@@ -696,7 +658,6 @@ post_load_config (struct config_file *cfg)
        struct metric                  *def_metric;
 
        g_hash_table_foreach (cfg->variables, substitute_all_variables, cfg);
-       g_hash_table_foreach (cfg->modules_opts, substitute_module_variables, cfg);
        fill_cfg_params (cfg);
 
 #ifdef HAVE_CLOCK_GETTIME
@@ -1042,44 +1003,6 @@ read_xml_config (struct config_file *cfg, const gchar *filename)
        return res;
 }
 
-static void
-modules_config_callback (gpointer key, gpointer value, gpointer ud)
-{
-       extern GHashTable              *module_options;
-       GHashTable                     *cur_module;
-       GList                          *cur;
-       struct module_opt              *opt;
-       const gchar                    *mname = key;
-       gboolean                       *res = ud;
-
-       if ((cur_module = g_hash_table_lookup (module_options, mname)) == NULL) {
-               msg_warn ("module %s has not registered any options but is presented in configuration", mname);
-               *res = FALSE;
-               return;
-       }
-
-       cur = value;
-       while (cur) {
-               opt = cur->data;
-
-               if (!opt->is_lua && !check_module_option (mname, opt->param, opt->value)) {
-                       *res = FALSE;
-                       return;
-               }
-
-               cur = g_list_next (cur);
-       }
-}
-
-gboolean
-check_modules_config (struct config_file *cfg)
-{
-       gboolean                        res = TRUE;
-
-       g_hash_table_foreach (cfg->modules_opts, modules_config_callback, &res);
-       return res;
-}
-
 static void
 symbols_classifiers_callback (gpointer key, gpointer value, gpointer ud)
 {
index 765d3041d155fd549c931211bb36e9fc825576a3..762c9a10de0cb675895ea8eb9ebcc320f04e9174 100644 (file)
@@ -15,7 +15,8 @@ SET(LUASRC                      lua_common.c
                                          lua_session.c
                                          lua_buffer.c
                                          lua_dns.c
-                                         lua_rsa.c)
+                                         lua_rsa.c
+                                         lua_rcl.c)
 
 ADD_LIBRARY(rspamd-lua ${LINK_TYPE} ${LUASRC})
 SET_TARGET_PROPERTIES(rspamd-lua PROPERTIES VERSION ${RSPAMD_VERSION})
index d03fba0ce80c3edd46422ae79c3d6229876bf165..c83433d810eef874e774a2ab9aa58af9c71045e0 100644 (file)
@@ -6,6 +6,7 @@
 
 #include "main.h"
 #include "cfg_file.h"
+#include "rcl/rcl.h"
 #include <lua.h>
 #include <lauxlib.h>
 #include <lualib.h>
@@ -101,6 +102,13 @@ struct lua_locked_state* init_lua_locked (struct config_file *cfg);
  */
 void free_lua_locked (struct lua_locked_state *st);
 
+/**
+ * Push an rcl object to lua
+ * @param L lua state
+ * @param obj object to push
+ */
+gint lua_rcl_obj_push (lua_State *L, rspamd_cl_object_t *obj);
+
 /**
  * Open libraries functions
  */
index 1da50ad19380f098302627f3fac21b03edb19c56..d3b7c6af948fb70c4c011e5d0f97f7592505590b 100644 (file)
@@ -153,17 +153,17 @@ static gint
 lua_config_get_module_opt (lua_State * L)
 {
        struct config_file             *cfg = lua_check_config (L);
-       const gchar                     *mname, *optname, *val;
+       const gchar                     *mname, *optname;
+       rspamd_cl_object_t              *obj;
 
        if (cfg) {
                mname = luaL_checkstring (L, 2);
                optname = luaL_checkstring (L, 3);
 
                if (mname && optname) {
-                       val = get_module_opt (cfg, (gchar *)mname, (gchar *)optname);
-                       if (val) {
-                               lua_pushstring (L, val);
-                               return 1;
+                       obj = get_module_opt (cfg, mname, optname);
+                       if (obj) {
+                               return lua_rcl_obj_push (L, obj);
                        }
                }
        }
@@ -185,83 +185,21 @@ lua_config_get_mempool (lua_State * L)
        return 1;
 }
 
-static gint
-opt_compare (gconstpointer a, gconstpointer b)
-{
-       const struct module_opt        *o1 = a,
-                                                                  *o2 = b;
-       
-       return g_ascii_strcasecmp (o1->param, o2->param);
-}
-
 static gint
 lua_config_get_all_opt (lua_State * L)
 {
        struct config_file             *cfg = lua_check_config (L);
        const gchar                     *mname;
-       GList                          *cur_opt, *next_opt;
-       struct module_opt              *opt, *tmp;
-       gint                            i;
+       rspamd_cl_object_t              *obj;
 
        if (cfg) {
                mname = luaL_checkstring (L, 2);
 
                if (mname) {
-                       cur_opt = g_hash_table_lookup (cfg->modules_opts, mname);
-                       if (cur_opt == NULL) {
-                               lua_pushnil (L);
-                               return 1;
+                       obj = rspamd_cl_obj_get_key (cfg->rcl_obj, mname);
+                       if (obj != NULL) {
+                               return lua_rcl_obj_push (L, obj);
                        }
-                       /* Sort options in alphabet order by param name */
-                       cur_opt = g_list_sort (cur_opt, opt_compare);
-                       g_hash_table_insert (cfg->modules_opts, (gpointer)mname, cur_opt);
-
-                       lua_newtable (L);
-                       while (cur_opt) {
-                               opt = cur_opt->data;
-                               next_opt = g_list_next (cur_opt);
-                               if (next_opt) {
-                                       tmp = next_opt->data;
-                                       if (g_ascii_strcasecmp (tmp->param, opt->param) == 0) {
-                                               /* We have some common values */
-                                               lua_pushstring (L, opt->param);
-                                               lua_newtable (L);
-                                               /* Now stack looks like:
-                                                * table - parent associated table of options
-                                                * key - string key of this option
-                                                * table - array of values, beginig from 1
-                                                */
-                                               
-                                               for (i = 1; ; i++) {
-                                                       lua_pushinteger (L, i);
-                                                       lua_pushstring (L, opt->value);
-                                                       lua_settable (L, -3);
-
-                                                       cur_opt = g_list_next (cur_opt);
-                                                       if (!cur_opt) {
-                                                               break;
-                                                       }
-                                                       tmp = cur_opt->data;
-                                                       if (g_ascii_strcasecmp (tmp->param, opt->param) != 0) {
-                                                               break;
-                                                       }
-                                                       opt = tmp;
-                                               }
-                                               /* Now set index in parent table */
-                                               lua_settable (L, -3);
-                                               /* Now continue in outter cycle */
-                                               continue;
-                                       }
-                                       else {
-                                               lua_set_table_index (L, opt->param, opt->value);
-                                       }
-                               }
-                               else {
-                                       lua_set_table_index (L, opt->param, opt->value);
-                               }
-                               cur_opt = next_opt;
-                       }
-                       return 1;
                }
        }
        lua_pushnil (L);
diff --git a/src/lua/lua_rcl.c b/src/lua/lua_rcl.c
new file mode 100644 (file)
index 0000000..c992b55
--- /dev/null
@@ -0,0 +1,148 @@
+/* Copyright (c) 2013, Vsevolod Stakhov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *       * Redistributions of source code must retain the above copyright
+ *         notice, this list of conditions and the following disclaimer.
+ *       * Redistributions in binary form must reproduce the above copyright
+ *         notice, this list of conditions and the following disclaimer in the
+ *         documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ''AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "lua_common.h"
+#include "rcl/rcl.h"
+
+/**
+ * @file lua rcl bindings
+ */
+
+static gint lua_rcl_obj_push_array (lua_State *L, rspamd_cl_object_t *obj);
+static gint lua_rcl_obj_push_simple (lua_State *L, rspamd_cl_object_t *obj);
+
+/**
+ * Push a single element of an object to lua
+ * @param L
+ * @param key
+ * @param obj
+ */
+static void
+lua_rcl_obj_push_elt (lua_State *L, const char *key, rspamd_cl_object_t *obj)
+{
+       lua_pushstring (L, key);
+       lua_push_obj_simple (L, obj);
+       lua_settable (L, -3);
+}
+
+/**
+ * Push a single object to lua
+ * @param L
+ * @param obj
+ * @return
+ */
+static gint
+lua_rcl_obj_push_obj (lua_State *L, rspamd_cl_object_t *obj)
+{
+       rspamd_cl_object_t *cur, *tmp;
+
+       if (obj->next != NULL) {
+               /* Actually we need to push this as an array */
+               return lua_rcl_obj_push_array (L, obj);
+       }
+
+       lua_newtable (L);
+       HASH_ITER (hh, obj, cur, tmp) {
+               lua_rcl_obj_push_elt (L, obj->key, obj);
+       }
+
+       return 1;
+}
+
+/**
+ * Push an array to lua as table indexed by integers
+ * @param L
+ * @param obj
+ * @return
+ */
+static gint
+lua_rcl_obj_push_array (lua_State *L, rspamd_cl_object_t *obj)
+{
+       rspamd_cl_object_t *cur;
+       gint i = 1;
+
+       lua_newtable (L);
+
+       LL_FOREACH (obj, cur) {
+               lua_rcl_obj_push (L, cur);
+               lua_rawseti (L, -2, i);
+               i ++;
+       }
+
+       return 1;
+}
+
+/**
+ * Push a simple object to lua depending on its actual type
+ */
+static gint
+lua_rcl_obj_push_simple (lua_State *L, rspamd_cl_object_t *obj)
+{
+       if (obj->next != NULL) {
+               /* Actually we need to push this as an array */
+               return lua_rcl_obj_push_array (L, obj);
+       }
+
+       switch (obj->type) {
+       case RSPAMD_CL_BOOLEAN:
+               lua_pushboolean (L, rspamd_cl_obj_toboolean (obj));
+               break;
+       case RSPAMD_CL_STRING:
+               lua_pushstring (L, rspamd_cl_obj_tostring (obj));
+               break;
+       case RSPAMD_CL_INT:
+#if LUA_VERSION_NUM >= 501
+               lua_pushinteger (L, rspamd_cl_obj_toint (obj));
+#else
+               lua_pushnumber (L, rspamd_cl_obj_toint (obj));
+#endif
+               break;
+       case RSPAMD_CL_FLOAT:
+       case RSPAMD_CL_TIME:
+               lua_pushnumber (L, rspamd_cl_obj_todouble (obj));
+               break;
+       default:
+               lua_pushnil (L);
+               break;
+       }
+
+       return 1;
+}
+
+/**
+ * Push an object to lua
+ * @param L lua state
+ * @param obj object to push
+ */
+gint
+lua_rcl_obj_push (lua_State *L, rspamd_cl_object_t *obj)
+{
+       switch (obj->type) {
+       case RSPAMD_CL_OBJECT:
+               return lua_rcl_obj_push_obj (L, obj->value.ov);
+       case RSPAMD_CL_ARRAY:
+               return lua_rcl_obj_push_array (L, obj->value.ov);
+       default:
+               return lua_rcl_obj_push_simple (L, obj);
+       }
+}