]> source.dussan.org Git - rspamd.git/commitdiff
Add support for meta options for modules.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 30 May 2013 13:38:24 +0000 (14:38 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 30 May 2013 13:38:24 +0000 (14:38 +0100)
This is preliminary patch that enables meta options for modules
which would simplify complex options passing.

src/cfg_file.h
src/cfg_utils.c
src/cfg_xml.c
src/cfg_xml.h

index e87d10316ccee3bae93ebf51103e3fbdd7473ff8..bb638888da22fc1dbae5f02203a9b0c040cc3977 100644 (file)
@@ -138,6 +138,11 @@ struct module_opt {
        enum lua_var_type lua_type;                                             /**< type of lua variable                                                               */
 };
 
+struct module_meta_opt {
+       gchar *name;                                                                    /**< Name of meta option                                                                */
+       GList *options;                                                                 /**< List of struct module_opt                                                  */
+};
+
 /**
  * Symbol definition
  */
@@ -323,6 +328,7 @@ struct config_file {
        GList *workers;                                                                 /**< linked list of all workers params                                  */
        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*/
        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                                                                  */
index a0191b103fe1f17483628bdab18c0b6a0c5f3e12..4acfead35271a750c0aed5130dc2482969205790 100644 (file)
@@ -216,6 +216,7 @@ init_defaults (struct config_file *cfg)
 
        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);
@@ -242,6 +243,7 @@ free_config (struct config_file *cfg)
        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);
        g_hash_table_remove_all (cfg->variables);
        g_hash_table_unref (cfg->variables);
        g_hash_table_remove_all (cfg->metrics);
index 054377059f39d723f050cd1630094f377c5c054f..3d58d128e2103342f1555cb2cad9b6952cd47ab8 100644 (file)
@@ -70,6 +70,7 @@ enum xml_config_section {
        XML_SECTION_CLASSIFIER,
        XML_SECTION_STATFILE,
        XML_SECTION_MODULE,
+       XML_SECTION_MODULE_META,
        XML_SECTION_MODULES,
        XML_SECTION_VIEW
 };
@@ -557,6 +558,21 @@ static struct xml_parser_rule grammar[] = {
                                NULL
                }
        },
+       { XML_SECTION_MODULE, {
+                       {
+                               "name",
+                               xml_handle_string,
+                               G_STRUCT_OFFSET (struct module_meta_opt, name),
+                               NULL
+                       },
+                       NULL_ATTR
+               },
+               {
+                       handle_module_meta,
+                       0,
+                       NULL
+               }
+       },
        { XML_SECTION_MODULE, {
                        NULL_ATTR
                },
@@ -641,6 +657,8 @@ xml_state_to_string (struct rspamd_xml_userdata *ud)
                        return "read param";
                case XML_READ_MODULE:
                        return "read module section";
+               case XML_READ_MODULE_META:
+                       return "read module meta section";
                case XML_READ_OPTIONS:
                        return "read options section";
                case XML_READ_MODULES:
@@ -1199,6 +1217,53 @@ handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, con
        return TRUE;
 }
 
+gboolean
+handle_module_meta (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
+{
+       gchar                          *val;
+       struct module_opt              *cur;
+       struct module_meta_opt         *meta;
+       gboolean                        is_lua = FALSE;
+       const gchar                    *name;
+
+       if (g_ascii_strcasecmp (tag, "option") == 0 || g_ascii_strcasecmp (tag, "param") == 0) {
+               if ((name = g_hash_table_lookup (attrs, "name")) == NULL) {
+                       msg_err ("worker param tag must have \"name\" attribute");
+                       return FALSE;
+               }
+       }
+       else {
+               name = memory_pool_strdup (cfg->cfg_pool, tag);
+       }
+
+       meta = ctx->section_pointer;
+       cur = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct module_opt));
+       /* Check for options */
+       if (attrs != NULL) {
+               if ((val = g_hash_table_lookup (attrs, "lua")) != NULL && g_ascii_strcasecmp (val, "yes") == 0) {
+                       is_lua = TRUE;
+               }
+               if ((val = g_hash_table_lookup (attrs, "description")) != NULL) {
+                       cur->description = memory_pool_strdup (cfg->cfg_pool, val);
+               }
+               if ((val = g_hash_table_lookup (attrs, "group")) != NULL) {
+                       cur->group = memory_pool_strdup (cfg->cfg_pool, val);
+               }
+       }
+       /*
+        * XXX: in fact we cannot check for lua modules and need to do it in post-config procedure
+        * so just insert any options provided and try to handle them in further process
+        */
+
+       /* Insert option */
+       cur->param = (char *)name;
+       cur->value = data;
+       cur->is_lua = is_lua;
+       meta->options = g_list_prepend (meta->options, cur);
+
+       return TRUE;
+}
+
 static void
 set_lua_globals (struct config_file *cfg, lua_State *L)
 {
@@ -1842,7 +1907,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                        if (g_ascii_strcasecmp (element_name, "module") == 0) {
                                /* Read module data */
                                if (extract_attr ("name", attribute_names, attribute_values, &res)) {
-                                       ud->parent_pointer = memory_pool_strdup (ud->cfg->cfg_pool, res);
+                                       ud->parent_pointer[0] = memory_pool_strdup (ud->cfg->cfg_pool, res);
                                        /* Empty list */
                                        ud->section_pointer = NULL;
                                        ud->state = XML_READ_MODULE;
@@ -1924,7 +1989,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                                ud->state = XML_READ_STATFILE;
 
                                /* Now section pointer is statfile and parent pointer is classifier */
-                               ud->parent_pointer = ud->section_pointer;
+                               ud->parent_pointer[0] = ud->section_pointer;
                                ud->section_pointer = check_statfile_conf (ud->cfg, NULL);
                        }
                        else {
@@ -1937,6 +2002,18 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                        /* Do nothing */
                        return;
                case XML_READ_MODULE:
+                       if (g_ascii_strcasecmp (element_name, "meta") == 0) {
+                               ud->parent_pointer[1] = ud->section_pointer;
+                               ud->state = XML_READ_MODULE_META;
+                               ud->section_pointer = memory_pool_alloc0 (ud->cfg->cfg_pool, sizeof (struct module_meta_opt));
+                       }
+                       else {
+                               rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name));
+                               /* Save attributes */
+                               ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values);
+                       }
+                       break;
+               case XML_READ_MODULE_META:
                case XML_READ_METRIC:
                case XML_READ_MODULES:
                case XML_READ_STATFILE:
@@ -2007,12 +2084,33 @@ rspamd_xml_end_element (GMarkupParseContext     *context, const gchar *element_name,
        }
 
        switch (ud->state) {
+               case XML_READ_MODULE_META:
+                       CHECK_TAG ("meta", FALSE);
+                       if (res) {
+                               if (ud->section_pointer != NULL) {
+                                       struct module_meta_opt *meta = ud->section_pointer;
+                                       if (meta->name == NULL) {
+                                               msg_err ("module %s has unnamed meta option, skip it", ud->parent_pointer[0]);
+                                       }
+                                       else {
+                                               g_hash_table_insert (ud->cfg->modules_metas, ud->parent_pointer[0], meta);
+                                       }
+                                       if (meta->options != NULL) {
+                                               memory_pool_add_destructor (ud->cfg->cfg_pool, (pool_destruct_func)g_list_free, meta->options);
+                                       }
+                               }
+                               ud->section_pointer = ud->parent_pointer[1];
+                               ud->parent_pointer[1] = NULL;
+                               ud->state = XML_READ_MODULE;
+                       }
+                       break;
                case XML_READ_MODULE:
                        CHECK_TAG ("module", FALSE);
                        if (res) {
                                if (ud->section_pointer != NULL) {
-                                       g_hash_table_insert (ud->cfg->modules_opts, ud->parent_pointer, ud->section_pointer);
-                                       ud->parent_pointer = NULL;
+                                       g_hash_table_insert (ud->cfg->modules_opts, ud->parent_pointer[0], ud->section_pointer);
+                                       memory_pool_add_destructor (ud->cfg->cfg_pool, (pool_destruct_func)g_list_free, ud->section_pointer);
+                                       ud->parent_pointer[0] = NULL;
                                        ud->section_pointer = NULL;
                                }
                        }
@@ -2032,7 +2130,7 @@ rspamd_xml_end_element (GMarkupParseContext       *context, const gchar *element_name,
                case XML_READ_STATFILE:
                        CHECK_TAG ("statfile", FALSE);
                        if (res) {
-                               ccf = ud->parent_pointer;
+                               ccf = ud->parent_pointer[0];
                                st = ud->section_pointer;
                                /* Check statfile and insert it into classifier */
                                if (st->path == NULL || st->size == 0 || st->symbol == NULL) {
@@ -2052,7 +2150,7 @@ rspamd_xml_end_element (GMarkupParseContext       *context, const gchar *element_name,
                                        }
                                }
                                ud->section_pointer = ccf;
-                               ud->parent_pointer = NULL;
+                               ud->parent_pointer[0] = NULL;
                                ud->state = XML_READ_CLASSIFIER;
                        }
                        break;
@@ -2161,6 +2259,12 @@ rspamd_xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len
                                ud->state = XML_ERROR;
                        }
                        break;
+               case XML_READ_MODULE_META:
+                       if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_MODULE_META)) {
+                               *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val);
+                               ud->state = XML_ERROR;
+                       }
+                       break;
                case XML_READ_MODULES:
                        if (!call_param_handler (ud, ud->section_name, val, cfg, XML_SECTION_MODULES)) {
                                *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s' data: %s", ud->section_name, val);
index ed41c7515da2065f00d91e72700b08102db10b35..48eac018da5e5349b9f9fba763f98d3898ee3b91 100644 (file)
 #define XML_UNMATCHED_TAG 4
 #define XML_INVALID_ATTR 5
 
+#define MAX_INHERIT 5
+
 enum xml_read_state {
        XML_READ_START,
        XML_READ_PARAM,
        XML_READ_MODULE,
+       XML_READ_MODULE_META,
        XML_READ_MODULES,
        XML_READ_CLASSIFIER,
        XML_READ_STATFILE,
@@ -51,7 +54,7 @@ struct rspamd_xml_userdata {
        struct config_file *cfg;                                /*< configuration object                                        */
        gchar section_name[MAX_NAME];                   /*< current section                                                     */
        gpointer section_pointer;                               /*< pointer to object related with section      */
-       gpointer parent_pointer;                                /*< parent's section object                                     */
+       gpointer parent_pointer[MAX_INHERIT];   /*< parent's section object                                     */
        GHashTable *cur_attrs;                                  /*< attributes of current tag                           */
        GQueue *if_stack;                                               /*< stack of if elements                                        */
 };
@@ -126,6 +129,7 @@ gboolean handle_metric_action (struct config_file *cfg, struct rspamd_xml_userda
 
 /* Handle common module option */
 gboolean handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
+gboolean handle_module_meta (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);
 
 /* Handle loging params */
 gboolean handle_log_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset);