aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2013-05-30 14:38:24 +0100
committerVsevolod Stakhov <vsevolod@highsecure.ru>2013-05-30 14:38:24 +0100
commit7b3682ce3c78d26dd75782f931611bd09bcc76a5 (patch)
tree03bf5e112472081877f31d50de26613df8d95207
parentedb41f2b5d018399dacf229555e659720f7a97a8 (diff)
downloadrspamd-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.h6
-rw-r--r--src/cfg_utils.c2
-rw-r--r--src/cfg_xml.c116
-rw-r--r--src/cfg_xml.h6
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);