]> source.dussan.org Git - rspamd.git/commitdiff
* Call lua functions like C functions in expressions
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Thu, 8 Apr 2010 15:24:36 +0000 (19:24 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Thu, 8 Apr 2010 15:24:36 +0000 (19:24 +0400)
src/expressions.c
src/lua/lua_common.c
src/lua/lua_common.h

index 34e7b0e283bc14f10ea7bcf61106046e8bb578d4..e52745541b9a98f27c639148cfa2548c83ad773c 100644 (file)
@@ -30,6 +30,7 @@
 #include "fuzzy.h"
 #include "expressions.h"
 #include "html.h"
+#include "lua/lua_common.h"
 
 gboolean                        rspamd_compare_encoding (struct worker_task *task, GList * args, void *unused);
 gboolean                        rspamd_header_exists (struct worker_task *task, GList * args, void *unused);
@@ -721,13 +722,26 @@ gboolean
 call_expression_function (struct expression_function * func, struct worker_task * task)
 {
        struct _fl                     *selected, key;
+#ifdef RSPAMD_MAIN
+       gboolean                        res;
+#endif
 
        key.name = func->name;
 
        selected = bsearch (&key, list_ptr, functions_number, sizeof (struct _fl), fl_cmp);
        if (selected == NULL) {
-               msg_warn ("call to undefined function %s", key.name);
+               /* Try to check lua function */
+#ifdef RSPAMD_MAIN
+               if (! lua_call_expression_func (func->name, task, func->args, &res)) {
+                       msg_warn ("call to undefined function %s", key.name);
+                       return FALSE;
+               }
+               else {
+                       return res;
+               }
+#else
                return FALSE;
+#endif
        }
 
        return selected->func (task, func->args, selected->user_data);
index c73b663bb9d2ed14e636c0f4aa99eafad890c8ee..ac3d3074b1f723b15046b9234a43dd3272283e9c 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #include "lua_common.h"
+#include "../expressions.h"
 
 /* Lua module init function */
 #define MODULE_INIT_FUNC "module_init"
@@ -262,6 +263,7 @@ lua_call_filter (const char *function, struct worker_task *task)
 {
        int                             result;
        struct worker_task            **ptask;
+       lua_State                      *L = task->cfg->lua_state;
 
        lua_getglobal (L, function);
        ptask = lua_newuserdata (L, sizeof (struct worker_task *));
@@ -285,6 +287,7 @@ int
 lua_call_chain_filter (const char *function, struct worker_task *task, int *marks, unsigned int number)
 {
        int                             result, i;
+       lua_State                      *L = task->cfg->lua_state;
 
        lua_getglobal (L, function);
 
@@ -304,6 +307,56 @@ lua_call_chain_filter (const char *function, struct worker_task *task, int *mark
        return result;
 }
 
+/* Call custom lua function in rspamd expression */
+gboolean 
+lua_call_expression_func (const char *function, struct worker_task *task, GList *args, gboolean *res)
+{
+       lua_State                      *L = task->cfg->lua_state;
+       struct worker_task            **ptask;
+       GList                          *cur;
+       struct expression_argument     *arg;
+       int                             nargs = 0;
+
+       lua_getglobal (L, function);
+       ptask = lua_newuserdata (L, sizeof (struct worker_task *));
+       lua_setclass (L, "rspamd{task}", -1);
+       *ptask = task;
+       
+       /* Now push all arguments */
+       cur = args;
+       while (cur) {
+               arg = get_function_arg (cur->data, task, FALSE);
+               if (arg) {
+                       switch (arg->type) {
+                               case EXPRESSION_ARGUMENT_NORMAL:
+                                       lua_pushstring (L, (const gchar *)arg->data);
+                                       break;
+                               case EXPRESSION_ARGUMENT_BOOL:
+                                       lua_pushboolean (L, (gboolean) GPOINTER_TO_SIZE (arg->data));
+                                       break;
+                               default:
+                                       msg_err ("cannot pass custom params to lua function");
+                                       return FALSE;
+                       }
+               }
+               nargs ++;
+               cur = g_list_next (cur);
+       }
+
+       if (lua_pcall (L, nargs, 1, 0) != 0) {
+               msg_info ("call to %s failed", function);
+               return FALSE;
+       }
+
+       if (!lua_isboolean (L, -1)) {
+               msg_info ("function %s must return a boolean", function);
+               return FALSE;
+       }
+       *res = lua_toboolean (L, -1);
+       
+       return TRUE;
+}
+
 /*
  * LUA custom consolidation function
  */
@@ -319,6 +372,7 @@ lua_consolidation_callback (gpointer key, gpointer value, gpointer arg)
        double                          res;
        struct symbol                  *s = (struct symbol *)value;
        struct consolidation_callback_data *data = (struct consolidation_callback_data *)arg;
+       lua_State                      *L = data->task->cfg->lua_state;
 
        lua_getglobal (L, data->func);
 
index 4c8ff25854a17ac2be56aba37e1183695ed22f66..dd4e75a8fc995dd881984c01feab18ba87428be1 100644 (file)
@@ -37,6 +37,7 @@ void init_lua_filters (struct config_file *cfg);
 int lua_call_filter (const char *function, struct worker_task *task);
 int lua_call_chain_filter (const char *function, struct worker_task *task, int *marks, unsigned int number);
 double lua_consolidation_func (struct worker_task *task, const char *metric_name, const char *function_name);
+gboolean lua_call_expression_func (const char *function, struct worker_task *task, GList *args, gboolean *res);
 void add_luabuf (const char *line);
 
 /* Classify functions */