aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@rambler-co.ru>2009-09-01 20:02:31 +0400
committerVsevolod Stakhov <vsevolod@rambler-co.ru>2009-09-01 20:02:31 +0400
commit68ddc2c40e474e39496718d54d907314e4c74232 (patch)
tree19b7a3e086c6f615790e2b403f34af80835c27c9 /src
parente38f71e43602a92d9181b6ad1199cb90afe908c4 (diff)
downloadrspamd-68ddc2c40e474e39496718d54d907314e4c74232.tar.gz
rspamd-68ddc2c40e474e39496718d54d907314e4c74232.zip
* New functionality to lua api:
- config class - metric class - textpart class * Add documentation for lua module
Diffstat (limited to 'src')
-rw-r--r--src/lua/lua_common.c14
-rw-r--r--src/lua/lua_common.h2
-rw-r--r--src/lua/lua_config.c102
-rw-r--r--src/lua/lua_message.c2
-rw-r--r--src/lua/lua_task.c118
-rw-r--r--src/lua/rspamd.luadoc100
6 files changed, 336 insertions, 2 deletions
diff --git a/src/lua/lua_common.c b/src/lua/lua_common.c
index eb93dce85..66ae67d58 100644
--- a/src/lua/lua_common.c
+++ b/src/lua/lua_common.c
@@ -43,7 +43,7 @@ static const struct luaL_reg loggerlib_m[] = {
{NULL, NULL}
};
-
+/* Util functions */
void
lua_newclass (lua_State *L, const char *classname, const struct luaL_reg *func)
{
@@ -66,7 +66,8 @@ lua_newclass (lua_State *L, const char *classname, const struct luaL_reg *func)
lua_pop (L, 1);
}
-void lua_setclass (lua_State *L, const char *classname, int objidx)
+void
+lua_setclass (lua_State *L, const char *classname, int objidx)
{
luaL_getmetatable (L, classname);
if (objidx < 0) {
@@ -75,6 +76,15 @@ void lua_setclass (lua_State *L, const char *classname, int objidx)
lua_setmetatable (L, objidx);
}
+/* assume that table is at the top */
+void
+lua_set_table_index (lua_State *L, const char *index, const char *value)
+{
+
+ lua_pushstring (L, index);
+ lua_pushstring (L, value);
+ lua_settable(L, -3);
+}
/*** Logger interface ***/
diff --git a/src/lua/lua_common.h b/src/lua/lua_common.h
index b72171e99..6c9152417 100644
--- a/src/lua/lua_common.h
+++ b/src/lua/lua_common.h
@@ -14,9 +14,11 @@
void lua_newclass (lua_State *L, const char *classname, const struct luaL_reg *func);
void lua_setclass (lua_State *L, const char *classname, int objidx);
+void lua_set_table_index (lua_State *L, const char *index, const char *value);
int luaopen_message (lua_State *L);
int luaopen_task (lua_State *L);
int luaopen_config (lua_State *L);
+int luaopen_metric (lua_State *L);
void init_lua_filters (struct config_file *cfg);
int lua_call_filter (const char *function, struct worker_task *task);
diff --git a/src/lua/lua_config.c b/src/lua/lua_config.c
index e88e53daf..7eb03f871 100644
--- a/src/lua/lua_config.c
+++ b/src/lua/lua_config.c
@@ -37,6 +37,14 @@ static const struct luaL_reg configlib_m[] = {
{NULL, NULL}
};
+/* Metric methods */
+LUA_FUNCTION_DEF(metric, register_symbol);
+
+static const struct luaL_reg metriclib_m[] = {
+ LUA_INTERFACE_DEF(metric, register_symbol),
+ {NULL, NULL}
+};
+
static struct config_file *
lua_check_config (lua_State *L)
{
@@ -45,6 +53,13 @@ lua_check_config (lua_State *L)
return (struct config_file *)ud;
}
+static struct metric *
+lua_check_metric (lua_State *L)
+{
+ void *ud = luaL_checkudata (L, 1, "Rspamd.metric");
+ luaL_argcheck (L, ud != NULL, 1, "'metric' expected");
+ return (struct metric *)ud;
+}
/*** Config functions ***/
static int
@@ -70,6 +85,38 @@ lua_config_get_module_opt (lua_State *L)
}
static int
+lua_config_get_all_opt (lua_State *L)
+{
+ struct config_file *cfg = lua_check_config (L);
+ const char *mname;
+ GList *cur_opt;
+ struct module_opt *cur;
+
+ 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;
+ }
+
+ lua_newtable (L);
+ while (cur_opt) {
+ cur = cur_opt->data;
+ lua_set_table_index (L, cur->param, cur->value);
+ cur_opt = g_list_next (cur_opt);
+ }
+ return 1;
+ }
+ }
+ lua_pushnil (L);
+ return 1;
+}
+
+
+static int
lua_config_get_metric (lua_State *L)
{
struct config_file *cfg = lua_check_config (L);
@@ -83,13 +130,60 @@ lua_config_get_metric (lua_State *L)
pmetric = lua_newuserdata (L, sizeof (struct metric *));
lua_setclass (L, "Rspamd.metric", -1);
*pmetric = metric;
+ return 1;
}
}
+
lua_pushnil (L);
return 1;
}
+/*** Metric functions ***/
+
+struct lua_callback_data {
+ const char *name;
+ lua_State *L;
+};
+
+static void
+lua_metric_symbol_callback (struct worker_task *task, gpointer ud)
+{
+ struct lua_callback_data *cd = ud;
+ struct worker_task **ptask;
+
+ lua_getglobal (cd->L, cd->name);
+ ptask = lua_newuserdata (cd->L, sizeof (struct worker_task *));
+ lua_setclass (cd->L, "Rspamd.task", -1);
+ *ptask = task;
+
+ if (lua_pcall(cd->L, 1, 1, 0) != 0) {
+ msg_warn ("lua_metric_symbol_callback: error running function %s: %s",
+ cd->name, lua_tostring(cd->L, -1));
+ }
+}
+
+static int
+lua_metric_register_symbol (lua_State *L)
+{
+ struct metric *metric = lua_check_metric (L);
+ const char *name, *callback;
+ double weight;
+ struct lua_callback_data *cd;
+
+ if (metric) {
+ name = luaL_checkstring (L, 2);
+ weight = luaL_checknumber (L, 3);
+ callback = luaL_checkstring (L, 4);
+ if (name) {
+ cd = g_malloc (sizeof (struct lua_callback_data));
+ cd->name = g_strdup (name);
+ register_symbol (&metric->cache, name, weight, lua_metric_symbol_callback, cd);
+ }
+ }
+ return 1;
+}
+
int
luaopen_config (lua_State *L)
{
@@ -99,3 +193,11 @@ luaopen_config (lua_State *L)
return 1;
}
+int
+luaopen_metric (lua_State *L)
+{
+ lua_newclass (L, "Rspamd.metric", configlib_m);
+ luaL_openlib (L, "metric", configlib_m, 0);
+
+ return 1;
+}
diff --git a/src/lua/lua_message.c b/src/lua/lua_message.c
index 499945ccb..b178da0d4 100644
--- a/src/lua/lua_message.c
+++ b/src/lua/lua_message.c
@@ -162,6 +162,7 @@ lua_message_set_header (lua_State *L)
return 1;
}
+
int
luaopen_message (lua_State *L)
{
@@ -170,3 +171,4 @@ luaopen_message (lua_State *L)
return 1;
}
+
diff --git a/src/lua/lua_task.c b/src/lua/lua_task.c
index 2e2991265..e3f1e55d6 100644
--- a/src/lua/lua_task.c
+++ b/src/lua/lua_task.c
@@ -24,19 +24,37 @@
#include "lua_common.h"
+#include "../message.h"
/* Task methods */
LUA_FUNCTION_DEF(task, get_message);
LUA_FUNCTION_DEF(task, insert_result);
LUA_FUNCTION_DEF(task, get_urls);
+LUA_FUNCTION_DEF(task, get_text_parts);
static const struct luaL_reg tasklib_m[] = {
LUA_INTERFACE_DEF(task, get_message),
LUA_INTERFACE_DEF(task, insert_result),
LUA_INTERFACE_DEF(task, get_urls),
+ LUA_INTERFACE_DEF(task, get_text_parts),
{NULL, NULL}
};
+/* Textpart methods */
+LUA_FUNCTION_DEF(textpart, get_content);
+LUA_FUNCTION_DEF(textpart, is_empty);
+LUA_FUNCTION_DEF(textpart, is_html);
+LUA_FUNCTION_DEF(textpart, get_fuzzy);
+
+static const struct luaL_reg textpartlib_m[] = {
+ LUA_INTERFACE_DEF(textpart, get_content),
+ LUA_INTERFACE_DEF(textpart, is_empty),
+ LUA_INTERFACE_DEF(textpart, is_html),
+ LUA_INTERFACE_DEF(textpart, get_fuzzy),
+ {NULL, NULL}
+};
+
+/* Utility functions */
static struct worker_task *
lua_check_task (lua_State *L)
{
@@ -45,6 +63,14 @@ lua_check_task (lua_State *L)
return (struct worker_task *)ud;
}
+static struct mime_text_part *
+lua_check_textpart (lua_State *L)
+{
+ void *ud = luaL_checkudata (L, 1, "Rspamd.textpart");
+ luaL_argcheck (L, ud != NULL, 1, "'textpart' expected");
+ return (struct mime_text_part *)ud;
+}
+
/*** Task interface ***/
static int
lua_task_get_message (lua_State *L)
@@ -96,7 +122,90 @@ lua_task_get_urls (lua_State *L)
return 1;
}
+static int
+lua_task_get_text_parts (lua_State *L)
+{
+
+ struct worker_task *task = lua_check_task (L);
+ GList *cur;
+ struct mime_text_part *part, **ppart;
+
+ if (task != NULL) {
+ cur = task->text_parts;
+ while (cur) {
+ part = cur->data;
+ ppart = lua_newuserdata (L, sizeof (struct mime_text_part *));
+ lua_setclass (L, "Rspamd.textpart", -1);
+ *ppart = part;
+ cur = g_list_next (cur);
+ }
+ }
+ lua_pushnil (L);
+ return 1;
+}
+
+/**** Textpart implementation *****/
+
+static int
+lua_textpart_get_content (lua_State *L)
+{
+ struct mime_text_part *part = lua_check_textpart (L);
+
+ if (part == NULL || part->is_empty) {
+ lua_pushnil (L);
+ return 1;
+ }
+
+ lua_pushlstring (L, part->content->data, part->content->len);
+
+ return 1;
+}
+
+static int
+lua_textpart_is_empty (lua_State *L)
+{
+ struct mime_text_part *part = lua_check_textpart (L);
+
+ if (part == NULL) {
+ lua_pushnil (L);
+ return 1;
+ }
+
+ lua_pushboolean (L, part->is_empty);
+
+ return 1;
+}
+
+static int
+lua_textpart_is_html (lua_State *L)
+{
+ struct mime_text_part *part = lua_check_textpart (L);
+
+ if (part == NULL) {
+ lua_pushnil (L);
+ return 1;
+ }
+
+ lua_pushboolean (L, part->is_html);
+
+ return 1;
+}
+
+static int
+lua_textpart_get_fuzzy (lua_State *L)
+{
+ struct mime_text_part *part = lua_check_textpart (L);
+ if (part == NULL || part->is_empty) {
+ lua_pushnil (L);
+ return 1;
+ }
+
+ lua_pushlstring (L, part->fuzzy->hash_pipe, sizeof (part->fuzzy->hash_pipe));
+ return 1;
+}
+
+/* Init part */
int
luaopen_task (lua_State *L)
{
@@ -106,3 +215,12 @@ luaopen_task (lua_State *L)
return 1;
}
+int
+luaopen_textpart (lua_State *L)
+{
+ lua_newclass (L, "Rspamd.textpart", textpartlib_m);
+ luaL_openlib (L, "textpart", textpartlib_m, 0);
+
+ return 1;
+}
+
diff --git a/src/lua/rspamd.luadoc b/src/lua/rspamd.luadoc
new file mode 100644
index 000000000..b83832a29
--- /dev/null
+++ b/src/lua/rspamd.luadoc
@@ -0,0 +1,100 @@
+--- Rspamd interaction package
+-- contains several subclasses:
+-- config - for parsing config files
+-- metric - for handling metrics callbacks
+-- task - for interaction with task object
+-- message - gate to GMime functions
+-- textpart - a single textual part of message
+module Rspamd
+
+--- Each lua module MUST have init function that is called after config file was read:
+-- it should be like
+-- function module:module_init(cfg)
+
+------------------------------------- CONFIG -----------------------------------------
+--
+--- Get module option from config
+-- @param mname module name
+-- @param option option
+-- @return string with value
+function config:get_module_opt (mname, option)
+
+--- Get all module options as a table like ['param' => 'value']
+-- @param mname module name
+-- @return table with options
+function config:get_all_opt (mname)
+
+--- Get specified metric
+-- @param name metric name
+-- @return metric object
+function config:get_metric (name)
+
+------------------------------------- METRIC -----------------------------------------
+
+--- Register symbol in metric
+-- @param symbol name of symbol
+-- @param weight weight of symbol
+-- @param callback fucntion that would be called as callback for symbol
+function metric:register_symbol (symbol, weight, callback)
+
+------------------------------------- TASK -------------------------------------------
+
+--- Get message object from task
+-- @return message object
+function task:get_message ()
+
+--- Insert result to specified metric with specified weight (obsoleted)
+-- @param metric metric name
+-- @param symbol symbol name
+-- @param weight weight of symbol
+function task:insert_result (metric, symbol, weight)
+
+--- Get all urls as array
+-- @return array of urls in textual form
+function task:get_urls ()
+
+--- Get all text parts
+-- @return array of textpart objects
+function task:get_text_parts ()
+
+------------------------------------- TEXTPART ---------------------------------------
+
+--- Get part's content
+-- @return string that contains part's content
+function textpart:get_content ()
+
+--- Check if part is empty
+-- @return boolean value
+function textpart:is_empty ()
+
+--- Check if part is html
+-- @return boolean value
+function textpart:is_html ()
+
+--- Get part's fuzzy
+-- @return string that contains part's fuzzy
+function textpart:get_fuzzy ()
+
+------------------------------------- MESSAGE ----------------------------------------
+
+--- Get message subject
+-- @return message subject
+function message:get_subject ()
+
+--- Get message id
+-- @return message id
+function message:get_message_id ()
+
+--- Get sender of message
+-- @return sender's credits
+function message:get_sender ()
+
+--- Get reply-to field
+-- @return value of reply-to header
+function message:get_reply_to ()
+
+--- Get header
+-- @param header_name name of header
+-- @return array of headers with specified name
+function message:get_header (header_name)
+