diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-05-30 14:38:24 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2013-05-30 14:38:24 +0100 |
commit | 7b3682ce3c78d26dd75782f931611bd09bcc76a5 (patch) | |
tree | 03bf5e112472081877f31d50de26613df8d95207 | |
parent | edb41f2b5d018399dacf229555e659720f7a97a8 (diff) | |
download | rspamd-7b3682ce3c78d26dd75782f931611bd09bcc76a5.tar.gz rspamd-7b3682ce3c78d26dd75782f931611bd09bcc76a5.zip |
Add support for meta options for modules.
This is preliminary patch that enables meta options for modules
which would simplify complex options passing.
-rw-r--r-- | src/cfg_file.h | 6 | ||||
-rw-r--r-- | src/cfg_utils.c | 2 | ||||
-rw-r--r-- | src/cfg_xml.c | 116 | ||||
-rw-r--r-- | src/cfg_xml.h | 6 |
4 files changed, 123 insertions, 7 deletions
diff --git a/src/cfg_file.h b/src/cfg_file.h index e87d10316..bb638888d 100644 --- a/src/cfg_file.h +++ b/src/cfg_file.h @@ -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 */ diff --git a/src/cfg_utils.c b/src/cfg_utils.c index a0191b103..4acfead35 100644 --- a/src/cfg_utils.c +++ b/src/cfg_utils.c @@ -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); diff --git a/src/cfg_xml.c b/src/cfg_xml.c index 054377059..3d58d128e 100644 --- a/src/cfg_xml.c +++ b/src/cfg_xml.c @@ -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 }; @@ -558,6 +559,21 @@ static struct xml_parser_rule grammar[] = { } }, { 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); diff --git a/src/cfg_xml.h b/src/cfg_xml.h index ed41c7515..48eac018d 100644 --- a/src/cfg_xml.h +++ b/src/cfg_xml.h @@ -12,10 +12,13 @@ #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); |