aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cfg_xml.c38
-rw-r--r--src/cfg_xml.h4
2 files changed, 41 insertions, 1 deletions
diff --git a/src/cfg_xml.c b/src/cfg_xml.c
index 8fad5f03a..30192703c 100644
--- a/src/cfg_xml.c
+++ b/src/cfg_xml.c
@@ -93,6 +93,12 @@ struct xml_parser_rule {
struct xml_default_config_param default_param;
};
+struct xml_subparser {
+ enum xml_read_state state;
+ const GMarkupParser *parser;
+ gpointer user_data;
+};
+
/* Here we describes our basic grammar */
static struct xml_parser_rule grammar[] = {
{ XML_SECTION_MAIN, {
@@ -579,7 +585,8 @@ static struct xml_parser_rule grammar[] = {
GHashTable *module_options = NULL,
*worker_options = NULL,
- *classifier_options = NULL;
+ *classifier_options = NULL,
+ *subparsers = NULL;
GQuark
xml_error_quark (void)
@@ -621,6 +628,8 @@ xml_state_to_string (struct rspamd_xml_userdata *ud)
return "error occured";
case XML_END:
return "read final tag";
+ case XML_SUBPARSER:
+ return "subparser handle";
}
/* Unreached */
return "unknown state";
@@ -1621,6 +1630,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
const gchar **attribute_values, gpointer user_data, GError **error)
{
struct rspamd_xml_userdata *ud = user_data;
+ struct xml_subparser *subparser;
struct classifier_config *ccf;
gchar *res, *condition;
@@ -1719,6 +1729,10 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
/* Create object */
ud->section_pointer = init_view (ud->cfg->cfg_pool);
}
+ else if (subparsers != NULL && (subparser = g_hash_table_lookup (subparsers, element_name)) != NULL) {
+ ud->state = XML_SUBPARSER;
+ g_markup_parse_context_push (context, subparser->parser, subparser->user_data);
+ }
else {
/* Extract other tags */
rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name));
@@ -1755,6 +1769,11 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
/* Save attributes */
ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values);
break;
+ case XML_SUBPARSER:
+ /* Recursive call of this function but with other state */
+ ud->state = XML_READ_PARAM;
+ rspamd_xml_start_element (context, element_name, attribute_names, attribute_values, user_data, error);
+ break;
default:
if (*error == NULL) {
*error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected in this state %s",
@@ -2232,6 +2251,23 @@ register_classifier_opt (const gchar *ctype, const gchar *optname)
}
}
+void
+register_subparser (const gchar *tag, enum xml_read_state state, const GMarkupParser *parser, gpointer user_data)
+{
+ struct xml_subparser *subparser;
+
+ if (subparsers == NULL) {
+ subparsers = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ }
+ subparser = g_malloc (sizeof (struct xml_subparser));
+
+ subparser->parser = parser;
+ subparser->state = state;
+ subparser->user_data = user_data;
+
+ g_hash_table_replace (subparsers, g_strdup (tag), subparser);
+}
+
/* Dumper part */
diff --git a/src/cfg_xml.h b/src/cfg_xml.h
index 659f35c19..2e188d2f6 100644
--- a/src/cfg_xml.h
+++ b/src/cfg_xml.h
@@ -27,6 +27,7 @@ enum xml_read_state {
XML_READ_VALUE,
XML_SKIP_ELEMENTS,
XML_ERROR,
+ XML_SUBPARSER,
XML_END
};
@@ -165,6 +166,9 @@ void register_worker_opt (gint wtype, const gchar *optname, element_handler_func
/* Register new classifier option */
void register_classifier_opt (const gchar *ctype, const gchar *optname);
+/* Register new xml subparser */
+void register_suparser (const gchar *tag, enum xml_read_state state, const GMarkupParser *parser, gpointer user_data);
+
/* Check validity of module option */
gboolean check_module_option (const gchar *mname, const gchar *optname, const gchar *data);