]> source.dussan.org Git - rspamd.git/commitdiff
* Add lua functions parsing for module options
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 6 Apr 2010 15:55:11 +0000 (19:55 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Tue, 6 Apr 2010 15:55:11 +0000 (19:55 +0400)
* Add missing sections to XML parser (classifier, statfile, view, settings)
* Add missing params to XML parser
* Implement new commandline options parser (using glib)
* Set version to 0.3.0 as new rspamd would use new config system

CMakeLists.txt
src/cfg_file.h
src/cfg_xml.c
src/cfg_xml.h
src/lua/lua_cfg_file.c
src/lua/lua_common.c
src/lua/lua_common.h
src/main.c

index 480fe88ceea80ec202d14162999f64831cdc0c28..3b93b49c7be6772d4d735fe52861be98726038ce 100644 (file)
@@ -6,8 +6,8 @@
 PROJECT(rspamd C)
 
 SET(RSPAMD_VERSION_MAJOR 0)
-SET(RSPAMD_VERSION_MINOR 2)
-SET(RSPAMD_VERSION_PATCH 9)
+SET(RSPAMD_VERSION_MINOR 3)
+SET(RSPAMD_VERSION_PATCH 0)
 
 SET(RSPAMD_VERSION         "${RSPAMD_VERSION_MAJOR}.${RSPAMD_VERSION_MINOR}.${RSPAMD_VERSION_PATCH}")
 SET(RSPAMD_MASTER_SITE_URL "http://cebka.pp.ru/hg/rspamd")
index 225a940acc430cc1d92026dacd5b79d9f99a1c34..17f81b3a6ac439384a52cd6f492b22a8b6c4bb40 100644 (file)
@@ -102,6 +102,16 @@ struct script_module {
        gchar *path;                                                                    /**< path to module                                                                             */
 };
 
+/**
+ * Type of lua variable
+ */
+enum lua_var_type {
+       LUA_VAR_NUM,
+       LUA_VAR_BOOLEAN,
+       LUA_VAR_STRING,
+       LUA_VAR_FUNCTION,
+       LUA_VAR_UNKNOWN
+};
 /**
  * Module option
  */
@@ -110,13 +120,7 @@ struct module_opt {
        gchar *value;                                                                   /**< paramater value                                                                    */
        gpointer actual_data;                                                   /**< parsed data                                                                                */
        gboolean is_lua;                                                                /**< actually this is lua variable                                              */
-       enum {
-               LUA_VAR_NUM,
-               LUA_VAR_BOOLEAN,
-               LUA_VAR_STRING,
-               LUA_VAR_FUNCTION,
-               LUA_VAR_UNKNOWN
-       } lua_type;                                                                             /**< type of lua variable                                                               */
+       enum lua_var_type lua_type;                                             /**< type of lua variable                                                               */
 };
 
 /**
index 872bd7a00a0fa1f5482f63238b565c2be2f56b48..46ccd1e2e5a2288a3143cdaed9967a8bd7a7ffa7 100644 (file)
@@ -34,6 +34,9 @@
 #include "classifiers/classifiers.h"
 #include "tokenizers/tokenizers.h"
 #include "lua/lua_common.h"
+#include "view.h"
+#include "expressions.h"
+#include "settings.h"
 
 /* Maximum attributes for param */
 #define MAX_PARAM 64
@@ -52,11 +55,11 @@ enum xml_config_section {
        XML_SECTION_WORKER,
        XML_SECTION_METRIC,
        XML_SECTION_CLASSIFIER,
+       XML_SECTION_STATFILE,
        XML_SECTION_FACTORS,
        XML_SECTION_MODULE,
        XML_SECTION_MODULES,
-       XML_SECTION_VIEW,
-       XML_SECTION_SETTINGS
+       XML_SECTION_VIEW
 };
 
 struct xml_config_param {
@@ -117,6 +120,30 @@ static struct xml_parser_rule grammar[] = {
                                G_STRUCT_OFFSET (struct config_file, filters_str),
                                NULL
                        },
+                       {
+                               "variable",
+                               handle_variable,
+                               0,
+                               NULL
+                       },
+                       {
+                               "composite",
+                               handle_composite,
+                               0,
+                               NULL
+                       },
+                       {
+                               "user_settings",
+                               handle_user_settings,
+                               0,
+                               NULL
+                       },
+                       {
+                               "domain_settings",
+                               handle_domain_settings,
+                               0,
+                               NULL
+                       },
                        NULL_ATTR
                },
                NULL_ATTR
@@ -226,6 +253,71 @@ static struct xml_parser_rule grammar[] = {
                NULL_ATTR
        },
        { XML_SECTION_CLASSIFIER, {
+                       {
+                               "metric",
+                               xml_handle_string,
+                               G_STRUCT_OFFSET (struct classifier_config, metric),
+                               NULL
+                       },
+                       {
+                               "tokenizer",
+                               handle_classifier_tokenizer,
+                               0,
+                               NULL
+                       },
+                       {
+                               "option",
+                               handle_classifier_opt,
+                               0,
+                               NULL
+                       },
+                       NULL_ATTR
+               },
+               NULL_ATTR
+       },
+       { XML_SECTION_STATFILE, {
+                       {
+                               "symbol",
+                               xml_handle_string,
+                               G_STRUCT_OFFSET (struct statfile, symbol),
+                               NULL
+                       },
+                       {
+                               "path",
+                               xml_handle_string,
+                               G_STRUCT_OFFSET (struct statfile, path),
+                               NULL
+                       },
+                       {
+                               "size",
+                               xml_handle_size,
+                               G_STRUCT_OFFSET (struct statfile, size),
+                               NULL
+                       },
+                       {
+                               "normalizer",
+                               handle_statfile_normalizer,
+                               0,
+                               NULL
+                       },
+                       {
+                               "binlog",
+                               handle_statfile_binlog,
+                               0,
+                               NULL
+                       },
+                       {
+                               "binlog_rotate",
+                               handle_statfile_binlog_rotate,
+                               0,
+                               NULL
+                       },
+                       {
+                               "binlog_master",
+                               handle_statfile_binlog_master,
+                               0,
+                               NULL
+                       },
                        NULL_ATTR
                },
                NULL_ATTR
@@ -257,20 +349,51 @@ static struct xml_parser_rule grammar[] = {
                }
        },
        { XML_SECTION_MODULES, {
+                       {
+                               "path",
+                               handle_module_path,
+                               0,
+                               NULL
+                       },
                        NULL_ATTR
                },
                NULL_ATTR
        },
        { XML_SECTION_VIEW, {
+                       {
+                               "skip_check",
+                               xml_handle_boolean,
+                               G_STRUCT_OFFSET (struct rspamd_view, skip_check),
+                               NULL
+                       },
+                       {
+                               "ip",
+                               handle_view_ip,
+                               0,
+                               NULL
+                       },
+                       {
+                               "client_ip",
+                               handle_view_client_ip,
+                               0,
+                               NULL
+                       },
+                       {
+                               "from",
+                               handle_view_from,
+                               0,
+                               NULL
+                       },
+                       {
+                               "symbols",
+                               handle_view_symbols,
+                               0,
+                               NULL
+                       },
                        NULL_ATTR
                },
                NULL_ATTR
        },
-       { XML_SECTION_SETTINGS, {
-                       NULL_ATTR
-               },
-               NULL_ATTR
-       }
 };
 
 GQuark
@@ -373,6 +496,7 @@ call_param_handler (struct rspamd_xml_userdata *ctx, const gchar *name, gchar *v
 /* Handlers */
 /* Specific handlers */
 
+/* Logging section */
 gboolean 
 handle_log_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
 {
@@ -471,10 +595,11 @@ handle_log_level (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHas
        return TRUE;
 }
 
+/* Worker section */
 gboolean 
 worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
 {
-       struct worker_conf             *wrk = ctx->other_data;
+       struct worker_conf             *wrk = ctx->section_pointer;
        char                           *name;
 
        if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
@@ -489,7 +614,7 @@ worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, G
 gboolean 
 worker_handle_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
 {
-       struct worker_conf             *wrk = ctx->other_data;
+       struct worker_conf             *wrk = ctx->section_pointer;
 
        
        if (g_ascii_strcasecmp (data, "normal") == 0) {
@@ -519,7 +644,7 @@ worker_handle_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GH
 gboolean 
 worker_handle_bind (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
 {
-       struct worker_conf             *wrk = ctx->other_data;
+       struct worker_conf             *wrk = ctx->section_pointer;
 
        if (!parse_bind_line (cfg, wrk, data)) {
                msg_err ("cannot parse bind_socket: %s", data);
@@ -529,6 +654,7 @@ worker_handle_bind (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GH
        return TRUE;
 }
 
+/* Factors section */
 gboolean 
 handle_factor (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
 {
@@ -554,6 +680,7 @@ handle_factor (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTa
        return TRUE;
 }
 
+/* Modules section */
 gboolean 
 handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
 {
@@ -641,6 +768,243 @@ handle_lua (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable
        return TRUE;
 }
 
+/* Modules section */
+gboolean 
+handle_module_path (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct stat st;
+       struct script_module *cur;
+       glob_t globbuf;
+       char *pattern;
+       size_t len;
+       int i;
+
+       if (stat (data, &st) == -1) {
+               msg_err ("cannot stat path %s, %s", data, strerror (errno));
+               return FALSE;
+       }
+
+       globbuf.gl_offs = 0;
+       len = strlen (data) + sizeof ("*.lua");
+       pattern = g_malloc (len);
+       snprintf (pattern, len, "%s%s", data, "*.lua");
+
+       if (glob (pattern, GLOB_DOOFFS, NULL, &globbuf) == 0) {
+               for (i = 0; i < globbuf.gl_pathc; i ++) {
+                       cur = memory_pool_alloc (cfg->cfg_pool, sizeof (struct script_module));
+                       cur->path = memory_pool_strdup (cfg->cfg_pool, globbuf.gl_pathv[i]);
+                       cfg->script_modules = g_list_prepend (cfg->script_modules, cur);
+               }
+               globfree (&globbuf);
+       }
+       else {
+               msg_err ("glob failed: %s", strerror (errno));
+               return FALSE;
+       }
+       
+       return TRUE;
+}
+
+/* Variables and composites */
+gboolean 
+handle_variable (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       gchar                        *val;
+       
+       if ((val = g_hash_table_lookup (attrs, "name")) == NULL) {
+               msg_err ("'name' attribute is required for tag 'variable'");
+               return FALSE;
+       }
+
+       g_hash_table_insert (cfg->variables, val, memory_pool_strdup (cfg->cfg_pool, data));
+       return TRUE;
+}
+
+gboolean 
+handle_composite (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       gchar                        *val;
+       struct expression            *expr;
+       
+       if ((val = g_hash_table_lookup (attrs, "name")) == NULL) {
+               msg_err ("'name' attribute is required for tag 'composite'");
+               return FALSE;
+       }
+
+       if ((expr = parse_expression (cfg->cfg_pool, data)) == NULL) {
+               msg_err ("cannot parse composite expression: %s", data);
+               return FALSE;
+       }
+       g_hash_table_insert (cfg->composite_symbols, val, expr);
+
+       return TRUE;
+}
+
+/* View section */
+gboolean 
+handle_view_ip (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct rspamd_view          *view = ctx->section_pointer;
+
+       if (!add_view_ip (view, data)) {
+               msg_err ("invalid ip line in view definition: ip = '%s'", data);
+               return FALSE;
+       }
+       
+       return TRUE;
+}
+gboolean 
+handle_view_client_ip (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct rspamd_view          *view = ctx->section_pointer;
+
+       if (!add_view_client_ip (view, data)) {
+               msg_err ("invalid ip line in view definition: ip = '%s'", data);
+               return FALSE;
+       }
+       
+       return TRUE;
+}
+gboolean 
+handle_view_from (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct rspamd_view          *view = ctx->section_pointer;
+
+       if (!add_view_from (view, data)) {
+               msg_err ("invalid from line in view definition: ip = '%s'", data);
+               return FALSE;
+       }
+       
+       return TRUE;
+}
+gboolean 
+handle_view_symbols (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct rspamd_view          *view = ctx->section_pointer;
+
+       if (!add_view_symbols (view, data)) {
+               msg_err ("invalid symbols line in view definition: ip = '%s'", data);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+/* Settings */
+gboolean 
+handle_user_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       if (!read_settings (data, cfg, cfg->user_settings)) {
+               msg_err ("cannot read settings %s", data);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+gboolean 
+handle_domain_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       if (!read_settings (data, cfg, cfg->domain_settings)) {
+               msg_err ("cannot read settings %s", data);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+/* Classifier */
+gboolean 
+handle_classifier_tokenizer (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct classifier_config     *ccf = ctx->section_pointer;
+       
+       if ((ccf->tokenizer = get_tokenizer (data)) == NULL) {
+               msg_err ("unknown tokenizer %s", data);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+gboolean 
+handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct classifier_config     *ccf = ctx->section_pointer;
+       gchar                        *val;
+       
+       if ((val = g_hash_table_lookup (attrs, "name")) == NULL) {
+               msg_err ("'name' attribute is required for tag 'option'");
+               return FALSE;
+       }
+
+       g_hash_table_insert (ccf->opts, val, memory_pool_strdup (cfg->cfg_pool, data));
+       return TRUE;
+}
+
+/* Statfile */
+gboolean 
+handle_statfile_normalizer (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct statfile             *st = ctx->section_pointer;
+       
+       if (!parse_normalizer (cfg, st, data)) {
+               msg_err ("cannot parse normalizer string: %s", data);
+               return FALSE;
+       }
+       
+       return TRUE;
+}
+
+gboolean 
+handle_statfile_binlog (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct statfile             *st = ctx->section_pointer;
+
+       if (st->binlog == NULL) {
+               st->binlog = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct statfile_binlog_params));
+       }
+       if (g_ascii_strcasecmp (data, "master") == 0) {
+               st->binlog->affinity = AFFINITY_MASTER;
+       }
+       else if (g_ascii_strcasecmp (data, "slave") == 0) {
+               st->binlog->affinity = AFFINITY_SLAVE;
+       }
+       else {
+               st->binlog->affinity = AFFINITY_NONE;
+       }
+
+       return TRUE;
+}
+
+gboolean 
+handle_statfile_binlog_rotate (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct statfile             *st = ctx->section_pointer;
+
+       if (st->binlog == NULL) {
+               st->binlog = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct statfile_binlog_params));
+       }
+       st->binlog->rotate_time = parse_seconds (data);
+       
+       return TRUE;
+}
+
+gboolean 
+handle_statfile_binlog_master (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+       struct statfile             *st = ctx->section_pointer;
+       if (st->binlog == NULL) {
+               st->binlog = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct statfile_binlog_params));
+       }
+
+       if (!parse_host_port (data, &st->binlog->master_addr, &st->binlog->master_port)) {
+               msg_err ("cannot parse master address: %s", data);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
 /* Common handlers */
 gboolean 
 xml_handle_string (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset)
@@ -807,7 +1171,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                                        g_strlcpy (ud->section_name, res, sizeof (ud->section_name));
                                        ud->state = XML_READ_METRIC;
                                        /* Create object */
-                                       ud->other_data = memory_pool_alloc0 (ud->cfg->cfg_pool, sizeof (struct metric));
+                                       ud->section_pointer = memory_pool_alloc0 (ud->cfg->cfg_pool, sizeof (struct metric));
                                }
                                else {
                                        *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'name' is required for tag 'metric'");
@@ -819,7 +1183,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                                        g_strlcpy (ud->section_name, res, sizeof (ud->section_name));
                                        ud->state = XML_READ_CLASSIFIER;
                                        /* Create object */
-                                       ud->other_data = check_classifier_cfg (ud->cfg, NULL);
+                                       ud->section_pointer = check_classifier_cfg (ud->cfg, NULL);
                                }
                                else {
                                        *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'type' is required for tag 'classifier'");
@@ -829,28 +1193,30 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                        else if (g_ascii_strcasecmp (element_name, "worker") == 0) {
                                ud->state = XML_READ_WORKER;
                                /* Create object */
-                               ud->other_data = check_worker_conf (ud->cfg, NULL);
+                               ud->section_pointer = check_worker_conf (ud->cfg, NULL);
+                       }
+                       else if (g_ascii_strcasecmp (element_name, "view") == 0) {
+                               ud->state = XML_READ_VIEW;
+                               /* Create object */
+                               ud->section_pointer = init_view (ud->cfg->cfg_pool);
                        }
-                       else if (g_ascii_strcasecmp (element_name, "variable") == 0) {
-                               if (extract_attr ("name", attribute_names, attribute_values, &res)) {
-                                       g_strlcpy (ud->section_name, res, sizeof (ud->section_name));
-                                       ud->state = XML_READ_VARIABLE;
-                               }
-                               else {
-                                       *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'name' is required for tag 'variable'");
-                                       ud->state = XML_ERROR;
-                               }
-                               
-                       } 
                        else {
                                /* Extract other tags */
                                g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name));
                                ud->state = XML_READ_VALUE;
                        }
                        break;
+               case XML_READ_CLASSIFIER:
+                       if (g_ascii_strcasecmp (element_name, "statfile") == 0) {
+                               ud->state = XML_READ_STATFILE;
+
+                               /* Now section pointer is statfile and parent pointer is classifier */
+                               ud->parent_pointer = ud->section_pointer;
+                               ud->section_pointer = memory_pool_alloc0 (ud->cfg->cfg_pool, sizeof (struct statfile));
+                       }
+                       break;
                case XML_READ_MODULE:
                case XML_READ_FACTORS:
-               case XML_READ_CLASSIFIER:
                case XML_READ_STATFILE:
                case XML_READ_WORKER:
                case XML_READ_LOGGING:
@@ -882,6 +1248,9 @@ void
 rspamd_xml_end_element (GMarkupParseContext    *context, const gchar *element_name, gpointer user_data, GError **error)
 {
        struct rspamd_xml_userdata *ud = user_data;
+       struct metric              *m;
+       struct classifier_config   *ccf;
+       struct statfile            *st;
        gboolean res;
        
        switch (ud->state) {
@@ -893,6 +1262,21 @@ rspamd_xml_end_element (GMarkupParseContext       *context, const gchar *element_name,
                        break;
                case XML_READ_STATFILE:
                        CHECK_TAG ("statfile", FALSE);
+                       if (res) {
+                               ccf = ud->parent_pointer;
+                               st = ud->section_pointer;
+                               /* Check statfile and insert it into classifier */
+                               if (st->path == NULL || st->size == 0 || st->symbol == NULL) {
+                                       *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "not enough arguments in statfile definition");
+                                       ud->state = XML_ERROR;
+                               }
+                               ccf->statfiles = g_list_prepend (ccf->statfiles, st);
+                               ud->cfg->statfiles = g_list_prepend (ud->cfg->statfiles, st);
+                               g_hash_table_insert (ud->cfg->classifiers_symbols, st->symbol, ccf);
+                               ud->section_pointer = ccf;
+                               ud->parent_pointer = NULL;
+                               ud->state = XML_READ_CLASSIFIER;
+                       }
                        break;
                case XML_READ_FACTORS:
                        CHECK_TAG ("factors", FALSE);
@@ -900,7 +1284,7 @@ rspamd_xml_end_element (GMarkupParseContext        *context, const gchar *element_name,
                case XML_READ_METRIC:
                        CHECK_TAG ("metric", FALSE);
                        if (res) {
-                               struct metric *m = ud->other_data;
+                               m = ud->section_pointer;
                                if (m->name == NULL) {
                                        *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "metric attribute \"name\" is required but missing");
                                        ud->state = XML_ERROR;
@@ -917,11 +1301,15 @@ rspamd_xml_end_element (GMarkupParseContext      *context, const gchar *element_name,
                        CHECK_TAG ("worker", FALSE);
                        if (res) {
                                /* Insert object to list */
-                               ud->cfg->workers = g_list_prepend (ud->cfg->workers, ud->other_data);
+                               ud->cfg->workers = g_list_prepend (ud->cfg->workers, ud->section_pointer);
                        }
                        break;
-               case XML_READ_VARIABLE:
-                       CHECK_TAG ("variable", TRUE);
+               case XML_READ_VIEW:
+                       CHECK_TAG ("view", FALSE);
+                       if (res) {
+                               /* Insert object to list */
+                               ud->cfg->views = g_list_prepend (ud->cfg->views, ud->section_pointer);
+                       }
                        break;
                case XML_READ_VALUE:
                        /* Check tags parity */
@@ -959,13 +1347,13 @@ rspamd_xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len
 
        switch (ud->state) {
                case XML_READ_MODULE:
-                       if (!call_param_handler (ud, ud->section_name, val, ud->other_data, XML_SECTION_MODULE)) {
+                       if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_MODULE)) {
                                *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
                                ud->state = XML_ERROR;
                        }
                        break;
                case XML_READ_CLASSIFIER:
-                       if (!call_param_handler (ud, ud->section_name, val, ud->other_data, XML_SECTION_CLASSIFIER)) {
+                       if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_CLASSIFIER)) {
                                *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
                                ud->state = XML_ERROR;
                        }
@@ -979,18 +1367,23 @@ rspamd_xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len
                        }
                        break;
                case XML_READ_METRIC:
-                       if (!call_param_handler (ud, ud->section_name, val, ud->other_data, XML_SECTION_METRIC)) {
+                       if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_METRIC)) {
                                *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
                                ud->state = XML_ERROR;
                        }
                        break;
                case XML_READ_WORKER:
-                       if (!call_param_handler (ud, ud->section_name, val, ud->other_data, XML_SECTION_WORKER)) {
+                       if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_WORKER)) {
+                               *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
+                               ud->state = XML_ERROR;
+                       }
+                       break;
+               case XML_READ_VIEW:
+                       if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_VIEW)) {
                                *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
                                ud->state = XML_ERROR;
                        }
                        break;
-               case XML_READ_VARIABLE:
                case XML_READ_VALUE:
                        if (!call_param_handler (ud, ud->section_name, val, cfg, XML_SECTION_MAIN)) {
                                *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
index ec0547ffe9810470a448052eaea18385a371844b..d27f147ca632ecb9159ceb8bdc3ddad4bcdb86c7 100644 (file)
@@ -20,10 +20,10 @@ enum xml_read_state {
        XML_READ_FACTORS,
        XML_READ_METRIC,
        XML_READ_WORKER,
-       XML_READ_VARIABLE,
+       XML_READ_VIEW,
        XML_READ_LOGGING,
-       XML_ERROR,
        XML_READ_VALUE,
+       XML_ERROR,
        XML_END
 };
 
@@ -31,7 +31,8 @@ struct rspamd_xml_userdata {
        enum xml_read_state state;
        struct config_file *cfg;
        gchar section_name[MAX_NAME];
-       gpointer other_data;
+       gpointer section_pointer;
+       gpointer parent_pointer;
        GHashTable *cur_attrs;
 };
 
@@ -88,12 +89,36 @@ gboolean xml_handle_boolean (struct config_file *cfg, struct rspamd_xml_userdata
 gboolean worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
 gboolean worker_handle_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
 gboolean worker_handle_bind (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
 gboolean handle_factor (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
 gboolean handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
 gboolean handle_log_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
 gboolean handle_log_level (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
 gboolean handle_lua (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
 
+gboolean handle_module_path (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+gboolean handle_variable (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_composite (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+gboolean handle_view_ip (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_view_client_ip (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_view_from (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_view_symbols (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+gboolean handle_user_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_domain_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+gboolean handle_classifier_tokenizer (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+gboolean handle_statfile_normalizer (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_statfile_binlog (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_statfile_binlog_rotate (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_statfile_binlog_master (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, int offset);
 
 /* Dumper functions */
 gboolean xml_dump_config (struct config_file *cfg, const char *filename);
index 1ac334299928ae49e63b33c71d0816b6d580c6ba..8be11b02bc6c8860ce7c52846b35aebd6e55358e 100644 (file)
@@ -121,7 +121,7 @@ lua_process_element (struct config_file *cfg, const char *name, struct module_op
                        opt->lua_type = LUA_VAR_STRING;
                        break;
                case LUA_TFUNCTION:
-                       opt->actual_data = (gpointer)lua_topointer (L, idx);
+                       opt->actual_data = memory_pool_strdup (cfg->cfg_pool, lua_tostring (L, idx));
                        opt->lua_type = LUA_VAR_FUNCTION;
                        break;
                case LUA_TNIL:
@@ -152,7 +152,7 @@ lua_module_callback (gpointer key, gpointer value, gpointer ud)
                        lua_getglobal (L, "config");
                        if (lua_istable (L, -1)) {
                                lua_pushstring (L, opt->param);
-                       lua_gettable (L, -2);
+                               lua_gettable (L, -2);
                                if (lua_isnil (L, -1)) {
                                        /* Try to get global variable */
                                        lua_getglobal (L, opt->param);
@@ -194,3 +194,103 @@ lua_post_load_config (struct config_file *cfg)
        /* Now parse all lua params */
        g_hash_table_foreach (cfg->modules_opts, lua_module_callback, cfg);
 }
+
+/* Handle lua dynamic config param */
+gboolean
+lua_handle_param (struct worker_task *task, gchar *mname, gchar *optname, enum lua_var_type expected_type, gpointer *res)
+{
+       lua_State                            *L = task->cfg->lua_state;
+       GList                                *cur;
+       struct module_opt                    *opt;
+       struct worker_task                  **ptask;
+       double                                num_res;
+       gboolean                              bool_res;
+       gchar                                *str_res;
+
+       if ((cur = g_hash_table_lookup (task->cfg->modules_opts, mname)) == NULL) {
+               *res = NULL;
+               return FALSE;
+       }
+       
+       /* Search for specified option */
+       while (cur) {
+               opt = cur->data;
+               if (opt->is_lua && g_ascii_strcasecmp (opt->param, optname) == 0) {
+                       if (opt->lua_type == expected_type) {
+                               /* Just push pointer to res */
+                               *res = opt->actual_data;
+                               return TRUE;
+                       }
+                       else if (opt->lua_type == LUA_VAR_FUNCTION) {
+                               /* Call specified function and expect result of given expected_type */
+                               /* First check function in config table */
+                               lua_getglobal (L, "config");
+                               if (lua_istable (L, -1)) {
+                                       lua_pushstring (L, opt->actual_data);
+                                       lua_gettable (L, -2);
+                                       if (lua_isnil (L, -1)) {
+                                               /* Try to get global variable */
+                                               lua_getglobal (L, opt->actual_data);
+                                       }
+                               }
+                               else {
+                                       /* Try to get global variable */
+                                       lua_getglobal (L, opt->actual_data);
+                               }
+                               if (lua_isnil (L, -1)) {
+                                       msg_err ("function with name %s is not defined", (gchar *)opt->actual_data);
+                                       return FALSE;
+                               }
+                               /* Now we got function in top of stack */
+                               ptask = lua_newuserdata (L, sizeof (struct worker_task *));
+                               lua_setclass (L, "rspamd{task}", -1);
+                               *ptask = task;
+                               /* Call function */
+                               if (lua_pcall (L, 1, 1, 0) != 0) {
+                                       msg_info ("call to %s failed: %s", (gchar *)opt->actual_data, lua_tostring (L, -1));
+                                       *res = NULL;
+                                       return FALSE;
+                               }
+                               /* Get result of specified type */
+                               switch (expected_type) {
+                                       case LUA_VAR_NUM:
+                                               if (!lua_isnumber (L, -1)) {
+                                                       *res = NULL;
+                                                       return FALSE;
+                                               }
+                                               num_res = lua_tonumber (L, -1);
+                                               *res = memory_pool_alloc (task->task_pool, sizeof (double));
+                                               **(double **)res = num_res;
+                                               return TRUE;
+                                       case LUA_VAR_BOOLEAN:
+                                               if (!lua_isboolean (L, -1)) {
+                                                       *res = NULL;
+                                                       return FALSE;
+                                               }
+                                               bool_res = lua_toboolean (L, -1);
+                                               *res = memory_pool_alloc (task->task_pool, sizeof (gboolean));
+                                               **(gboolean **)res = bool_res;
+                                               return TRUE;
+                                       case LUA_VAR_STRING:
+                                               if (!lua_isstring (L, -1)) {
+                                                       *res = NULL;
+                                                       return FALSE;
+                                               }
+                                               str_res = memory_pool_strdup (task->task_pool, lua_tostring (L, -1));
+                                               *res = str_res;
+                                               return TRUE;
+                                       case LUA_VAR_FUNCTION:
+                                       case LUA_VAR_UNKNOWN:
+                                               msg_err ("cannot expect function or unknown types");
+                                               *res = NULL;
+                                               return FALSE;
+                               }
+                       }
+               }
+               cur = g_list_next (cur);
+       }
+
+       /* Option not found */
+       *res = NULL;
+       return FALSE;
+}
index 3d4e29b2813901347b71c106d82e1424bf3c6ec1..c73b663bb9d2ed14e636c0f4aa99eafad890c8ee 100644 (file)
@@ -181,7 +181,7 @@ luaopen_logger (lua_State * L)
 }
 
 void
-init_lua ()
+init_lua (struct config_file *cfg)
 {
        if (L == NULL) {
                L = lua_open ();
@@ -198,6 +198,7 @@ init_lua ()
                (void)luaopen_message (L);
                (void)luaopen_classifier (L);
                (void)luaopen_statfile (L);
+               cfg->lua_state = L;
        }
 }
 
@@ -361,7 +362,6 @@ void
 add_luabuf (const char *line)
 {
        int                             error;
-       init_lua ();
 
        error = luaL_loadbuffer (L, line, strlen (line), "config") || lua_pcall (L, 0, 0, 0);
        if (error) {
index 5de7bdc71150a336787d6ceb0c8daa2ad0e5df5a..4c8ff25854a17ac2be56aba37e1183695ed22f66 100644 (file)
@@ -30,7 +30,7 @@ int luaopen_hash_table (lua_State *L);
 int luaopen_textpart (lua_State *L);
 int luaopen_classifier (lua_State *L);
 int luaopen_statfile (lua_State * L);
-void init_lua ();
+void init_lua (struct config_file *cfg);
 void init_lua_filters (struct config_file *cfg);
 
 /* Filters functions */
@@ -48,6 +48,8 @@ double lua_normalizer_func (double score, void *params);
 /* Config file functions */
 void lua_post_load_config (struct config_file *cfg);
 void lua_process_element (struct config_file *cfg, const char *name, struct module_opt *opt, int idx);
+gboolean lua_handle_param (struct worker_task *task, gchar *mname, gchar *optname, 
+                                                       enum lua_var_type expected_type, gpointer *res);
 
 
 #endif /* WITH_LUA */
index 926d0e5c677b433c3afd35f4ef5daa24d96b8bf8..022773038e8cf5173a023b8a7d4cdd54072fddf9 100644 (file)
@@ -28,6 +28,7 @@
 #include "util.h"
 #include "lmtp.h"
 #include "fuzzy_storage.h"
+#include "cfg_xml.h"
 
 #ifndef WITHOUT_PERL
 
@@ -65,8 +66,14 @@ GQueue                         *signals_info;
 extern int                      yynerrs;
 extern FILE                    *yyin;
 
-static int                      dump_vars = 0;
-static int                      dump_cache = 0;
+static gboolean                 config_test;
+static gboolean                 no_fork;
+static gchar                   *cfg_name;
+static gchar                   *rspamd_user;
+static gchar                   *rspamd_group;
+static gchar                   *rspamd_pidfile;
+static gboolean                 dump_vars;
+static gboolean                 dump_cache;
 
 #ifndef WITHOUT_PERL
 extern void                     xs_init (pTHX);
@@ -76,6 +83,21 @@ extern PerlInterpreter         *perl_interpreter;
 /* List of workers that are pending to start */
 static GList                   *workers_pending = NULL;
 
+/* Commandline options */
+static GOptionEntry entries[] = 
+{
+  { "config-test", 't', 0, G_OPTION_ARG_NONE, &config_test, "Do config test and exit", NULL },
+  { "no-fork", 'f', 0, G_OPTION_ARG_NONE, &no_fork, "Do not daemonize main process", NULL },
+  { "config", 'c', 0, G_OPTION_ARG_STRING, &cfg_name, "Specify config file", NULL },
+  { "user", 'u', 0, G_OPTION_ARG_STRING, &rspamd_user, "User to run rspamd as", NULL },
+  { "group", 'g', 0, G_OPTION_ARG_STRING, &rspamd_group, "Group to run rspamd as", NULL },
+  { "pid", 'p', 0, G_OPTION_ARG_STRING, &rspamd_pidfile, "Path to pidfile", NULL },
+  { "dump-vars", 'V', 0, G_OPTION_ARG_NONE, &dump_vars, "Print all rspamd variables and exit", NULL },
+  { "dump-cache", 'C', 0, G_OPTION_ARG_NONE, &dump_cache, "Dump symbols cache stats and exit", NULL },
+  { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
+};
+
+
 #ifndef HAVE_SA_SIGINFO
 static void
 sig_handler (int signo)
@@ -156,61 +178,22 @@ print_signals_info ()
 static void
 read_cmd_line (int argc, char **argv, struct config_file *cfg)
 {
-       int                             ch;
-       while ((ch = getopt (argc, argv, "tVChfc:u:g:p:")) != -1) {
-               switch (ch) {
-               case 'f':
-                       cfg->no_fork = 1;
-                       break;
-               case 'c':
-                       if (optarg && cfg->cfg_name) {
-                               cfg->cfg_name = memory_pool_strdup (cfg->cfg_pool, optarg);
-                       }
-                       break;
-               case 't':
-                       cfg->config_test = 1;
-                       break;
-               case 'V':
-                       dump_vars = 1;
-                       break;
-               case 'C':
-                       dump_cache = 1;
-                       break;
-               case 'u':
-                       if (optarg) {
-                               cfg->rspamd_user = memory_pool_strdup (cfg->cfg_pool, optarg);
-                       }
-                       break;
-               case 'g':
-                       if (optarg) {
-                               cfg->rspamd_group = memory_pool_strdup (cfg->cfg_pool, optarg);
-                       }
-                       break;
-               case 'p':
-                       if (optarg) {
-                               cfg->pid_file = memory_pool_strdup (cfg->cfg_pool, optarg);
-                       }
-                       break;
-               case 'h':
-               case '?':
-               default:
-                       /* Show help message and exit */
-                       printf ("Rspamd version " RVERSION "\n"
-                               "Usage: rspamd [-t] [-h] [-n] [-f] [-c config_file]\n"
-                               "-h:        This help message\n"
-                               "-t:        Do config test and exit\n"
-                               "-C:        Dump symbols cache stats and exit\n"
-                               "-V         Print all rspamd variables and exit\n"
-                               "-f:        Do not daemonize main process\n"
-                               "-c:        Specify config file (./rspamd.conf is used by default)\n" 
-                               "-u:        User to run rspamd as\n" 
-                               "-g:        Group to run rspamd as\n"
-                               "-p:        Path to pidfile\n"
-                       );
-                       exit (0);
-                       break;
-               }
-       }
+       GError                         *error = NULL;
+       GOptionContext                 *context;
+
+       context = g_option_context_new ("- run rspamd daemon");
+       g_option_context_set_summary (context, "Summary:\n  Rspamd daemon version " RVERSION);
+       g_option_context_add_main_entries (context, entries, NULL);
+       if (!g_option_context_parse (context, &argc, &argv, &error)) {
+               fprintf (stderr, "option parsing failed: %s\n", error->message);
+               exit (1);
+       }
+       cfg->no_fork = no_fork;
+       cfg->config_test = config_test;
+       cfg->rspamd_user = rspamd_user;
+       cfg->rspamd_group = rspamd_group;
+       cfg->cfg_name = cfg_name;
+       cfg->pid_file = rspamd_pidfile;
 }
 
 static void
@@ -598,8 +581,10 @@ main (int argc, char **argv, char **env)
 
        bzero (&signals, sizeof (struct sigaction));
 
-       rspamd->cfg->cfg_name = memory_pool_strdup (rspamd->cfg->cfg_pool, FIXED_CONFIG_FILE);
        read_cmd_line (argc, argv, rspamd->cfg);
+       if (rspamd->cfg->cfg_name == NULL) {
+               rspamd->cfg->cfg_name = FIXED_CONFIG_FILE;
+       }
 
        if (cfg->config_test) {
                cfg->log_level = G_LOG_LEVEL_DEBUG;
@@ -624,7 +609,7 @@ main (int argc, char **argv, char **env)
 #ifndef HAVE_SETPROCTITLE
        init_title (argc, argv, environ);
 #endif
-       init_lua ();
+       init_lua (cfg);
 
        f = fopen (rspamd->cfg->cfg_name, "r");
        if (f == NULL) {