]> source.dussan.org Git - rspamd.git/commitdiff
Start to eliminate xml configuration.
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 23 Oct 2013 16:30:48 +0000 (17:30 +0100)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 23 Oct 2013 16:30:48 +0000 (17:30 +0100)
src/cfg_utils.c
src/cfg_xml.c
src/cfg_xml.h
src/kvstorage_config.c

index 8a49237ac70ae4dc65230b0587ee5000079e69dc..49fb609ab878974ba74a5906aed503a2fcd0d92a 100644 (file)
@@ -986,18 +986,11 @@ read_xml_config (struct config_file *cfg, const gchar *filename)
        
        /* Prepare xml parser */
        ud.cfg = cfg;
-       ud.state = XML_READ_START;
-       ud.if_stack = g_queue_new ();
-
+       ud.state = 0;
        ctx = g_markup_parse_context_new (&xml_parser, G_MARKUP_TREAT_CDATA_AS_TEXT, &ud, NULL);
        init_kvstorage_config ();
        res = g_markup_parse_context_parse (ctx, data, st.st_size, &err);
 
-       if (g_queue_get_length (ud.if_stack) != 0) {
-               msg_err ("unexpected nesting for if arguments");
-               res = FALSE;
-       }
-
        munmap (data, st.st_size);
 
        return res;
index 6524d050a6f298505974a00a5f68b1734e1282e1..2757fded2677ec03005608fdcc9ae2ddc76f2d34 100644 (file)
 
 #include "lua/lua_common.h"
 
+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,
+       XML_READ_METRIC,
+       XML_READ_WORKER,
+       XML_READ_VIEW,
+       XML_READ_LOGGING,
+       XML_READ_OPTIONS,
+       XML_READ_VALUE,
+       XML_SKIP_ELEMENTS,
+       XML_ERROR,
+       XML_SUBPARSER,
+       XML_END
+};
+
 /* Maximum attributes for param */
 #define MAX_PARAM 64
 
 #define EOL "\n"
 
+#if 0
 #define NULL_ATTR      \
 {                                      \
        NULL,                   \
@@ -640,6 +661,7 @@ GHashTable *module_options = NULL,
                   *worker_options = NULL,
                   *classifier_options = NULL,
                   *subparsers = NULL;
+#endif
 
 GQuark
 xml_error_quark (void)
@@ -710,482 +732,26 @@ extract_attr (const gchar *attr, const gchar **attribute_names, const gchar **at
        return FALSE;
 }
 
-static inline gchar*
-xml_asciiz_string (memory_pool_t *pool, const gchar *text, gsize len)
-{
-       gchar                           *val;
-
-       val = memory_pool_alloc (pool, len + 1);
-       rspamd_strlcpy (val, text, len + 1);
-
-       return val;
-}
 
 /* Find among attributes required ones and form new array of pairs attribute-value */
-static GHashTable *
-process_attrs (struct config_file *cfg, const gchar **attribute_names, const gchar **attribute_values)
+static void
+process_attrs (const gchar **attribute_names, const gchar **attribute_values, ucl_object_t *top)
 {
        const gchar                         **attr, **value;
        GHashTable                     *res;
 
-       if (*attribute_names == NULL) {
-               /* No attributes required */
-               return NULL;
-       }
-
-       res = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
-
        attr = attribute_names;
        value = attribute_values;
        while (*attr) {
                /* Copy attributes to pool */
-               g_hash_table_insert (res, memory_pool_strdup (cfg->cfg_pool, *attr), memory_pool_strdup (cfg->cfg_pool, *value));
+               ucl_object_insert_key (top, ucl_object_fromstring_common (*value, 0, UCL_STRING_PARSE), *attr, 0, TRUE);
                attr ++;
                value ++;
        }
-
-       memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_hash_table_destroy, res);
-
-       return res;
 }
 
-static gboolean
-call_param_handler (struct rspamd_xml_userdata *ctx, const gchar *name, gchar *value, gpointer dest_struct, enum xml_config_section section)
-{
-       struct xml_parser_rule         *rule;
-       struct xml_config_param        *param;
-       guint                           i;
-       
-       /* First find required section */
-       for (i = 0; i < G_N_ELEMENTS (grammar); i ++) {
-               rule = &grammar[i];
-               if (rule->section == section) {
-                       /* Now find attribute in section or call default handler */
-                       param = &rule->params[0];
-                       while (param && param->handler) {
-                               if (param->name && g_ascii_strcasecmp (param->name, name) == 0) {
-                                       /* Call specified handler */
-                                       return param->handler (ctx->cfg, ctx, ctx->cur_attrs, value, param->user_data, dest_struct, param->offset);
-                               }
-                               param ++;
-                       }
-                       if (rule->default_param.handler != NULL) {
-                               /* Call default handler */
-                               return rule->default_param.handler (ctx->cfg, ctx, name, ctx->cur_attrs, value, param->user_data, dest_struct, param->offset);
-                       }
-               }
-       }
-       
-       msg_err ("could not find handler for tag %s at section %d", name, section);
-       return FALSE;
-}
 
 /* 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, gint offset)
-{
-       gchar                           *val;
-       if (g_ascii_strcasecmp (data, "file") == 0) {
-               /* Find filename attribute */
-               if (attrs == NULL || (val = g_hash_table_lookup (attrs, "filename")) == NULL) {
-                       msg_err ("cannot log to file that is not specified");
-                       return FALSE;
-               }
-               cfg->log_type = RSPAMD_LOG_FILE;
-               cfg->log_file = val;
-       }
-       else if (g_ascii_strcasecmp (data, "console") == 0) {
-               cfg->log_type = RSPAMD_LOG_CONSOLE;
-       }
-       else if (g_ascii_strcasecmp (data, "syslog") == 0) {
-               if (attrs == NULL || (val = g_hash_table_lookup (attrs, "facility")) == NULL) {
-                       msg_err ("cannot log to syslog when facility is not specified");
-                       return FALSE;
-               }
-               cfg->log_type = RSPAMD_LOG_SYSLOG;
-               /* Rather ugly check */
-               if (g_ascii_strncasecmp (val, "LOG_AUTH", sizeof ("LOG_AUTH") - 1) == 0 || g_ascii_strncasecmp (val, "auth", sizeof ("auth") - 1) == 0 ) {
-                       cfg->log_facility = LOG_AUTH;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_CRON", sizeof ("LOG_CRON") - 1) == 0 || g_ascii_strncasecmp (val, "cron", sizeof ("cron") - 1) == 0 ) {
-                       cfg->log_facility = LOG_CRON;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_DAEMON", sizeof ("LOG_DAEMON") - 1) == 0 || g_ascii_strncasecmp (val, "daemon", sizeof ("daemon") - 1) == 0 ) {
-                       cfg->log_facility = LOG_DAEMON;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_MAIL", sizeof ("LOG_MAIL") - 1) == 0 || g_ascii_strncasecmp (val, "mail", sizeof ("mail") - 1) == 0) {
-                       cfg->log_facility = LOG_MAIL;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_USER", sizeof ("LOG_USER") - 1) == 0 || g_ascii_strncasecmp (val, "user", sizeof ("user") - 1) == 0 ) {
-                       cfg->log_facility = LOG_USER;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_LOCAL0", sizeof ("LOG_LOCAL0") - 1) == 0 || g_ascii_strncasecmp (val, "local0", sizeof ("local0") - 1) == 0) {
-                       cfg->log_facility = LOG_LOCAL0;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_LOCAL1", sizeof ("LOG_LOCAL1") - 1) == 0 || g_ascii_strncasecmp (val, "local1", sizeof ("local1") - 1) == 0) {
-                       cfg->log_facility = LOG_LOCAL1;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_LOCAL2", sizeof ("LOG_LOCAL2") - 1) == 0 || g_ascii_strncasecmp (val, "local2", sizeof ("local2") - 1) == 0) {
-                       cfg->log_facility = LOG_LOCAL2;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_LOCAL3", sizeof ("LOG_LOCAL3") - 1) == 0 || g_ascii_strncasecmp (val, "local3", sizeof ("local3") - 1) == 0) {
-                       cfg->log_facility = LOG_LOCAL3;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_LOCAL4", sizeof ("LOG_LOCAL4") - 1) == 0 || g_ascii_strncasecmp (val, "local4", sizeof ("local4") - 1) == 0) {
-                       cfg->log_facility = LOG_LOCAL4;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_LOCAL5", sizeof ("LOG_LOCAL5") - 1) == 0 || g_ascii_strncasecmp (val, "local5", sizeof ("local5") - 1) == 0) {
-                       cfg->log_facility = LOG_LOCAL5;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_LOCAL6", sizeof ("LOG_LOCAL6") - 1) == 0 || g_ascii_strncasecmp (val, "local6", sizeof ("local6") - 1) == 0) {
-                       cfg->log_facility = LOG_LOCAL6;
-               }
-               else if (g_ascii_strncasecmp (val, "LOG_LOCAL7", sizeof ("LOG_LOCAL7") - 1) == 0 || g_ascii_strncasecmp (val, "local7", sizeof ("local7") - 1) == 0) {
-                       cfg->log_facility = LOG_LOCAL7;
-               }
-               else {
-                       msg_err ("invalid logging facility: %s", val);
-                       return FALSE;
-               }
-       }
-       else {
-               msg_err ("invalid logging type: %s", data);
-               return FALSE;
-       }
-       
-       return TRUE;
-}
-
-gboolean 
-handle_log_level (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       if (g_ascii_strcasecmp (data, "error") == 0) {
-               cfg->log_level = G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL;
-       }
-       else if (g_ascii_strcasecmp (data, "warning") == 0) {
-               cfg->log_level = G_LOG_LEVEL_WARNING;
-       }
-       else if (g_ascii_strcasecmp (data, "info") == 0) {
-               cfg->log_level = G_LOG_LEVEL_INFO | G_LOG_LEVEL_MESSAGE;
-       }
-       else if (g_ascii_strcasecmp (data, "debug") == 0) {
-               cfg->log_level = G_LOG_LEVEL_DEBUG;
-       }
-       else {
-               msg_err ("unknown log level: %s", data);
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-gboolean
-options_handle_nameserver (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       cfg->nameservers = g_list_prepend (cfg->nameservers, memory_pool_strdup (cfg->cfg_pool, data));
-       return TRUE;
-}
-
-/* Worker section */
-
-struct wrk_cbdata {
-       struct worker_conf *wrk;
-       struct config_file *cfg;
-       struct rspamd_xml_userdata *ctx;
-};
-
-struct wrk_param {
-       gboolean is_list;
-       union {
-               gchar *param;
-               GList *list;
-       } d;
-       GHashTable *attrs;
-};
-
-static void
-worker_foreach_callback (gpointer k, gpointer v, gpointer ud)
-{
-       struct wrk_cbdata              *cd = ud;
-       struct wrk_param               *param = v;
-       struct xml_config_param        *cparam;
-       GList                          *cur;
-       GHashTable                     *worker_config;
-
-       if (!worker_options || (worker_config = g_hash_table_lookup (worker_options, &cd->wrk->type)) == NULL) {
-               return;
-       }
-       if ((cparam = g_hash_table_lookup (worker_config, k)) == NULL) {
-               /* Try to use universal handler if there is no specific handler */
-               if ((cparam = g_hash_table_lookup (worker_config, "*")) != NULL) {
-                       if (cd->wrk->ctx != NULL) {
-                               if (param->is_list) {
-                                       cur = param->d.list;
-                                       while (cur) {
-                                               cparam->handler (cd->cfg, cd->ctx, param->attrs, cur->data, k, cd->wrk->ctx, cparam->offset);
-                                               cur = g_list_next (cur);
-                                       }
-                               }
-                               else {
-                                       cparam->handler (cd->cfg, cd->ctx, param->attrs, param->d.param, k, cd->wrk->ctx, cparam->offset);
-                               }
-                       }
-                       else {
-                               msg_err ("Bad error detected: worker %s has not initialized its context", g_quark_to_string (cd->wrk->type));
-                       }
-               }
-               else {
-                       msg_warn ("unregistered worker attribute '%s' for worker %s", k, g_quark_to_string (cd->wrk->type));
-               }
-       }
-       else {
-
-               if (cd->wrk->ctx != NULL) {
-                       if (param->is_list) {
-                               cur = param->d.list;
-                               while (cur) {
-                                       cparam->handler (cd->cfg, cd->ctx, param->attrs, cur->data, NULL, cd->wrk->ctx, cparam->offset);
-                                       cur = g_list_next (cur);
-                               }
-                       }
-                       else {
-                               cparam->handler (cd->cfg, cd->ctx, param->attrs, param->d.param, NULL, cd->wrk->ctx, cparam->offset);
-                       }
-               }
-               else {
-                       msg_err ("Bad error detected: worker %s has not initialized its context", g_quark_to_string (cd->wrk->type));
-               }
-       }
-}
-
-gboolean 
-worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, const gchar *tag, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       struct worker_conf             *wrk = ctx->section_pointer;
-       const gchar                    *name, *tmp;
-       struct wrk_param               *param;
-
-       if (g_ascii_strcasecmp (tag, "option") == 0 || g_ascii_strcasecmp (tag, "param") == 0)  {
-               if (attrs == NULL || (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);
-       }
-
-       if ((param = g_hash_table_lookup (wrk->params, name)) == NULL) {
-               param = memory_pool_alloc (cfg->cfg_pool, sizeof (struct wrk_param));
-               param->is_list = FALSE;
-               param->d.param = memory_pool_strdup (cfg->cfg_pool, data);
-               g_hash_table_insert (wrk->params, (char *)name, param);
-               /* Copy attributes */
-               param->attrs = g_hash_table_new (rspamd_strcase_hash, rspamd_strcase_equal);
-               memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_hash_table_destroy, param->attrs);
-               rspamd_hash_table_copy (attrs, param->attrs, rspamd_str_pool_copy, rspamd_str_pool_copy, cfg->cfg_pool);
-       }
-       else {
-               if (param->is_list) {
-                       param->d.list = g_list_append (param->d.list, memory_pool_strdup (cfg->cfg_pool, data));
-               }
-               else {
-                       /* Convert to list */
-                       param->is_list = TRUE;
-                       tmp = param->d.param;
-                       param->d.list = g_list_prepend (NULL, (gpointer)tmp);
-                       param->d.list = g_list_append (param->d.list, memory_pool_strdup (cfg->cfg_pool, data));
-                       memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_list_free, param->d.list);
-               }
-               rspamd_hash_table_copy (attrs, param->attrs, rspamd_str_pool_copy, rspamd_str_pool_copy, cfg->cfg_pool);
-       }
-
-       return TRUE;
-}
-
-gboolean 
-worker_handle_type (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       struct worker_conf             *wrk = ctx->section_pointer;
-       GQuark                                                  type;
-       
-       type = g_quark_try_string (data);
-
-       if (type != 0) {
-                wrk->worker = get_worker_by_type (type);
-                if (wrk->worker == NULL) {
-                        msg_err ("unknown worker type: %s", data);
-                        return FALSE;
-                }
-                wrk->type = type;
-                if (wrk->worker->worker_init_func) {
-                        wrk->ctx = wrk->worker->worker_init_func (cfg);
-                }
-       }
-       else {
-               msg_err ("unknown worker type: %s", data);
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-gboolean 
-worker_handle_bind (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       struct worker_conf             *wrk = ctx->section_pointer;
-
-       if (!parse_bind_line (cfg, wrk, data)) {
-               msg_err ("cannot parse bind_socket: %s", data);
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-gboolean
-handle_metric_action (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       struct metric                  *metric = ctx->section_pointer;
-       gchar                          *p, *errstr;
-       gint                            res;
-       struct metric_action           *action;
-
-       /* First of all check whether we have data with weight (reject:50 for example) */
-       if ((p = strchr (data, ':')) == NULL) {
-               if (check_action_str (data, &res)) {
-                       /* XXX: no longer needed */
-                       return TRUE;
-               }
-               return FALSE;
-       }
-       else {
-               if (!check_action_str (data, &res)) {
-                       return FALSE;
-               }
-               else {
-                       action = &metric->actions[res];
-                       action->action = res;
-                       errno = 0;
-                       action->score = strtod (p + 1, &errstr);
-                       if (errno != 0 || (errstr != NULL && *errstr != '\0')) {
-                               msg_err ("invalid double value: %s", data);
-                               return FALSE;
-                       }
-               }
-       }
-
-       return TRUE;
-}
-
-static gint
-symbols_group_find_func (gconstpointer a, gconstpointer b)
-{
-       const struct symbols_group              *gr = a;
-       const gchar                                             *uv = b;
-
-       return g_ascii_strcasecmp (gr->name, uv);
-}
-
-gboolean
-handle_metric_symbol (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       gchar                          *strval, *err, *desc, *group;
-       double                         *value;
-       GList                          *metric_list, *group_list;
-       struct metric                  *metric = ctx->section_pointer;
-       struct symbols_group               *sym_group;
-       struct symbol_def                          *sym_def;
-
-       sym_def = memory_pool_alloc (cfg->cfg_pool, sizeof (struct symbol_def));
-       value = memory_pool_alloc (cfg->cfg_pool, sizeof (double));
-
-       if (attrs == NULL || (strval = g_hash_table_lookup (attrs, "weight")) == NULL) {
-               msg_info ("symbol tag should have \"weight\" attribute, assume weight 1.0");
-               *value = 1.0;
-       }
-       else {
-               errno = 0;
-               *value = strtod (strval, &err);
-               if (errno != 0 || (err != NULL && *err != 0)) {
-                       msg_err ("invalid number: %s, %s", strval, strerror (errno));
-                       return FALSE;
-               }
-       }
-       
-       sym_def->weight_ptr = value;
-       sym_def->name = memory_pool_strdup (cfg->cfg_pool, data);
-
-       if (attrs != NULL) {
-               desc = g_hash_table_lookup (attrs, "description");
-               if (desc) {
-                       sym_def->description = memory_pool_strdup (cfg->cfg_pool, desc);
-                       g_hash_table_insert (metric->descriptions, data, sym_def->description);
-               }
-               else {
-                       sym_def->description = NULL;
-               }
-               group = g_hash_table_lookup (attrs, "group");
-               if (group == NULL) {
-                       group = "ungrouped";
-               }
-       }
-       else {
-               group = "ungrouped";
-               sym_def->description = NULL;
-       }
-
-       g_hash_table_insert (metric->symbols, sym_def->name, value);
-
-       if ((metric_list = g_hash_table_lookup (cfg->metrics_symbols, sym_def->name)) == NULL) {
-               metric_list = g_list_prepend (NULL, metric);
-               memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_list_free, metric_list);
-               g_hash_table_insert (cfg->metrics_symbols, sym_def->name, metric_list);
-       }
-       else {
-               /* Slow but keep start element of list in safe */
-               if (!g_list_find (metric_list, metric)) {
-                       metric_list = g_list_append (metric_list, metric);
-               }
-       }
-
-       /* Search for symbol group */
-       group_list = g_list_find_custom (cfg->symbols_groups, group, symbols_group_find_func);
-       if (group_list == NULL) {
-               /* Create new group */
-               sym_group = memory_pool_alloc (cfg->cfg_pool, sizeof (struct symbols_group));
-               sym_group->name = memory_pool_strdup (cfg->cfg_pool, group);
-               sym_group->symbols = NULL;
-               cfg->symbols_groups = g_list_prepend (cfg->symbols_groups, sym_group);
-       }
-       else {
-               sym_group = group_list->data;
-       }
-       /* Insert symbol */
-       sym_group->symbols = g_list_prepend (sym_group->symbols, sym_def);
-
-       return TRUE;
-}
-
-/* Modules section */
-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)
-{
-       /* XXX: convert to RCL */
-
-       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)
-{
-       /* XXX: Remove, unneeded and never used */
-
-       return TRUE;
-}
 
 static void
 set_lua_globals (struct config_file *cfg, lua_State *L)
@@ -1515,15 +1081,9 @@ handle_classifier_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
                name = memory_pool_strdup (cfg->cfg_pool, tag);
        }
 
-       if (!classifier_options ||
-                       (classifier_config = g_hash_table_lookup (classifier_options, ccf->classifier->name)) == NULL ||
-                       (cparam = g_hash_table_lookup (classifier_config, name)) == NULL) {
-               msg_warn ("unregistered classifier attribute '%s' for classifier %s", name, ccf->classifier->name);
-               return FALSE;
-       }
-       else {
-               g_hash_table_insert (ccf->opts, (char *)name, memory_pool_strdup (cfg->cfg_pool, data));
-       }
+
+       g_hash_table_insert (ccf->opts, (char *)name, memory_pool_strdup (cfg->cfg_pool, data));
+
 
        return TRUE;
 }
@@ -1607,221 +1167,18 @@ handle_statfile_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, c
        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, gint offset)
-{
-       /* Simply assign pointer to pointer */
-       gchar                       **dest;
-
-       dest = (gchar **)G_STRUCT_MEMBER_P (dest_struct, offset);
-       *dest = memory_pool_strdup (cfg->cfg_pool, data);
-
-       return TRUE;
-}
-
-gboolean
-xml_handle_string_list (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       GList                      **dest;
-       gchar                      **tokens, **cur;
-
-       dest = (GList **)G_STRUCT_MEMBER_P (dest_struct, offset);
-       *dest = NULL;
-
-       tokens = g_strsplit_set (data, ";,", 0);
-       if (!tokens || !tokens[0]) {
-               return FALSE;
-       }
-       memory_pool_add_destructor (cfg->cfg_pool, (pool_destruct_func)g_strfreev, tokens);
-       cur = tokens;
-       while (*cur) {
-               *dest = g_list_prepend (*dest, *cur);
-               cur ++;
-       }
-
-       return TRUE;
-}
-
-gboolean
-xml_handle_list (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
+/* XML callbacks */
+void 
+rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names,
+                                                               const gchar **attribute_values, gpointer user_data, GError **error)
 {
-       /* Simply assign pointer to pointer */
-       GList                       **dest;
-
-       dest = (GList **)G_STRUCT_MEMBER_P (dest_struct, offset);
-       *dest = g_list_prepend (*dest, memory_pool_strdup (cfg->cfg_pool, data));
-
-       return TRUE;
-}
-
+       struct rspamd_xml_userdata *ud = user_data;
+       struct xml_subparser       *subparser;
+       struct classifier_config   *ccf;
+       gchar                      *res, *condition;
+       ucl_object_t                *obj;
 
-gboolean 
-xml_handle_size (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       gsize                      *dest;
 
-       dest = (gsize *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       *dest = (gsize)parse_limit (data, -1);
-       
-       return TRUE;
-}
-
-/* Guint64 variant */
-gboolean
-xml_handle_size_64 (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       guint64                    *dest;
-
-       dest = (guint64 *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       *dest = parse_limit (data, -1);
-
-       return TRUE;
-}
-
-gboolean 
-xml_handle_seconds (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       guint32                      *dest;
-
-       dest = (guint32 *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       *dest = rint (cfg_parse_time (data, TIME_SECONDS));
-       
-       return TRUE;
-}
-
-gboolean 
-xml_handle_seconds_double (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       gdouble                      *dest;
-
-       dest = (gdouble *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       *dest = cfg_parse_time (data, TIME_SECONDS);
-
-       return TRUE;
-}
-
-gboolean
-xml_handle_boolean (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       gboolean                    *dest;
-
-       dest = (gboolean *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       *dest = parse_flag (data);
-       /* gchar -> gboolean */
-       if (*dest == -1) {
-               msg_err ("bad boolean: %s", data);
-               return FALSE;
-       }
-       else if (*dest == 1)  {
-               *dest = TRUE;
-       }
-       
-       return TRUE;
-}
-
-gboolean
-xml_handle_deprecated (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-
-       msg_err ("parameter is depreciated: %s", ctx->section_name);
-       return TRUE;
-}
-
-gboolean 
-xml_handle_double (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       double                      *dest;
-       gchar                           *err = NULL;
-
-       dest = (double *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       errno = 0;
-       *dest = strtod (data, &err);
-       if (errno != 0 || (err != NULL && *err != 0)) {
-               msg_err ("invalid number: %s, %s", data, strerror (errno));
-               return FALSE;
-       }
-       
-       return TRUE;
-}
-
-gboolean 
-xml_handle_int (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       gint                            *dest;
-       gchar                           *err = NULL;
-
-       dest = (gint *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       errno = 0;
-       *dest = strtol (data, &err, 10);
-       if (errno != 0 || (err != NULL && *err != 0)) {
-               msg_err ("invalid number: %s, %s", data, strerror (errno));
-               return FALSE;
-       }
-       
-       return TRUE;
-}
-
-gboolean 
-xml_handle_uint32 (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       guint32                         *dest;
-       gchar                           *err = NULL;
-
-       dest = (guint32 *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       errno = 0;
-       *dest = strtoul (data, &err, 10);
-       if (errno != 0 || (err != NULL && *err != 0)) {
-               msg_err ("invalid number: %s, %s", data, strerror (errno));
-               return FALSE;
-       }
-       
-       return TRUE;
-}
-
-gboolean 
-xml_handle_uint16 (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, gchar *data, gpointer user_data, gpointer dest_struct, gint offset)
-{
-       guint16                    *dest;
-       gchar                           *err = NULL;
-
-       dest = (guint16 *)G_STRUCT_MEMBER_P (dest_struct, offset);
-       errno = 0;
-       *dest = strtoul (data, &err, 10);
-       if (errno != 0 || (err != NULL && *err != 0)) {
-               msg_err ("invalid number: %s, %s", data, strerror (errno));
-               return FALSE;
-       }
-       
-       return TRUE;
-}
-
-/* XML callbacks */
-void 
-rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names,
-                                                               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;
-
-
-       if (g_ascii_strcasecmp (element_name, "if") == 0) {
-               /* Push current state to queue */
-               g_queue_push_head (ud->if_stack, GSIZE_TO_POINTER ((gsize)ud->state));
-               /* Now get attributes */
-               ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values);
-               if (ud->cur_attrs == NULL || (condition = g_hash_table_lookup (ud->cur_attrs, "condition")) == NULL) {
-                       msg_err ("unknown condition attribute for if tag");
-                       *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'condition' is required for tag 'if'");
-                       ud->state = XML_ERROR;
-               }
-               else if (! lua_check_condition (ud->cfg, condition)) {
-                       ud->state = XML_SKIP_ELEMENTS;
-               }
-               return;
-       }
        switch (ud->state) {
                case XML_READ_START:
                        if (g_ascii_strcasecmp (element_name, "rspamd") != 0) {
@@ -1835,84 +1192,37 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                        break;
                case XML_READ_PARAM:
                        /* Read parameter name and try to find among list of known parameters */
-                       if (g_ascii_strcasecmp (element_name, "module") == 0) {
-                               /* Read module data */
-                               if (extract_attr ("name", attribute_names, attribute_values, &res)) {
-                                       ud->parent_pointer[0] = memory_pool_strdup (ud->cfg->cfg_pool, res);
-                                       /* Empty list */
-                                       ud->section_pointer = NULL;
-                                       ud->state = XML_READ_MODULE;
-                               }
-                               else {
-                                       *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'name' is required for tag 'module'");
-                                       ud->state = XML_ERROR;
-                               }
-                       }
-                       else if (g_ascii_strcasecmp (element_name, "modules") == 0) {
-                               ud->state = XML_READ_MODULES;   
-                       }
-                       else if (g_ascii_strcasecmp (element_name, "options") == 0) {
-                               ud->state = XML_READ_OPTIONS;
-                       }
-                       else if (g_ascii_strcasecmp (element_name, "logging") == 0) {
-                               ud->state = XML_READ_LOGGING;   
-                       }
-                       else if (g_ascii_strcasecmp (element_name, "metric") == 0) {
-                               ud->state = XML_READ_METRIC;
-                               /* Create object */
-                               ud->section_pointer = check_metric_conf (ud->cfg, NULL);
-                       }
-                       else if (g_ascii_strcasecmp (element_name, "classifier") == 0) {
+                       if (g_ascii_strcasecmp (element_name, "classifier") == 0) {
                                if (extract_attr ("type", attribute_names, attribute_values, &res)) {
                                        ud->state = XML_READ_CLASSIFIER;
-                                       /* Create object */
-                                       ccf = check_classifier_conf (ud->cfg, NULL);
-                                       if ((ccf->classifier = get_classifier (res)) == NULL) {
-                                               *error = g_error_new (xml_error_quark (), XML_INVALID_ATTR, "invalid classifier type: %s", res);
-                                               ud->state = XML_ERROR;
-                                       }
-                                       else {
-                                               ud->section_pointer = ccf;
-                                       }
                                }
                                else {
                                        *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'type' is required for tag 'classifier'");
                                        ud->state = XML_ERROR;
                                }
                        }
-                       else if (g_ascii_strcasecmp (element_name, "worker") == 0) {
-                               ud->state = XML_READ_WORKER;
-                               /* Create object */
-                               ud->section_pointer = check_worker_conf (ud->cfg, NULL);
-                       }
-                       else if (g_ascii_strcasecmp (element_name, "lua") == 0) {
-                               rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name));
-                               ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values);
-                               if (! handle_lua (ud->cfg, ud, ud->cur_attrs, NULL, NULL, ud->cfg, 0)) {
-                                       *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag '%s'", ud->section_name);
-                                       ud->state = XML_ERROR;
+                       else {
+                               /* Legacy XML support */
+                               if (g_ascii_strcasecmp (element_name, "param") == 0) {
+                                       if (extract_attr ("value", attribute_names, attribute_values, &res)) {
+                                               element_name = res;
+                                       }
+                                       else {
+                                               *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'value' is required for tag 'param'");
+                                               ud->state = XML_ERROR;
+                                       }
                                }
-                               else {
-                                       ud->state = XML_READ_VALUE;
+
+                               if (ud->nested == 0) {
+                                       /* Top object */
+                                       obj = ucl_object_new ();
+                                       obj->type = UCL_OBJECT;
+                                       ud->parent_pointer[0] = obj;
+                                       ucl_object_insert_key (ud->cfg->rcl_obj, obj, element_name, 0, true);
+                                       process_attrs (attribute_names, attribute_values, obj);
                                }
-                       }
-                       else if (g_ascii_strcasecmp (element_name, "view") == 0) {
-                               ud->state = XML_READ_VIEW;
-                               /* Create object */
-                               ud->section_pointer = init_view (ud->cfg, ud->cfg->cfg_pool);
-                       }
-#if GLIB_MINOR_VERSION >= 18
-                       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);
-                               rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name));
-                       }
-#endif
-                       else {
-                               /* Extract other tags */
-                               rspamd_strlcpy (ud->section_name, element_name, sizeof (ud->section_name));
-                               ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values);
-                               ud->state = XML_READ_VALUE;
+                               rspamd_strlcpy (ud->section_name[ud->nested], element_name, MAX_NAME);
+                               ud->nested ++;
                        }
                        break;
                case XML_READ_CLASSIFIER:
@@ -1924,43 +1234,10 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                                ud->section_pointer = check_statfile_conf (ud->cfg, NULL);
                        }
                        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_SKIP_ELEMENTS:
-                       /* 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));
+                               rspamd_strlcpy (ud->section_name[ud->nested], element_name, MAX_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:
-               case XML_READ_WORKER:
-               case XML_READ_LOGGING:
-               case XML_READ_VIEW:
-               case XML_READ_OPTIONS:
-                       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_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",
@@ -1970,185 +1247,20 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
        }
 }
 
-#define CHECK_TAG(x, required)                                                                                                                                                                                                                         \
-do {                                                                                                                                                                                                                                                                           \
-if (g_ascii_strcasecmp (element_name, (x)) == 0) {                                                                                                                                                                                     \
-       ud->state = XML_READ_PARAM;                                                                                                                                                                                                                             \
-       res = TRUE;                                                                                                                                                                                                                                                             \
-}                                                                                                                                                                                                                                                                                      \
-else {                                                                                                                                                                                                                                                                         \
-       res = FALSE;                                                                                                                                                                                                                                                    \
-       if ((required) == TRUE) {                                                                                                                                                                                                                               \
-       if (*error == NULL) *error = g_error_new (xml_error_quark (), XML_UNMATCHED_TAG, "element %s is unexpected in this state, expected %s", element_name, (x));     \
-       ud->state = XML_ERROR;                                                                                                                                                                                                                                  \
-       }                                                                                                                                                                                                                                                                               \
-}                                                                                                                                                                                                                                                                                      \
-} while (0)
 
 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;
-       gpointer                    tptr;
-       struct wrk_cbdata           wcd;
-       struct xml_subparser       *subparser;
-       GList                                      *labels;
-       
-       if (g_ascii_strcasecmp (element_name, "if") == 0) {
-               tptr = g_queue_pop_head (ud->if_stack);
 
-               if (tptr == NULL) {
-                       *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is umatched", element_name);
-                       ud->state = XML_ERROR;
-               }
-               /* Restore state */
-               if (ud->state == XML_SKIP_ELEMENTS) {
-                       ud->state = GPOINTER_TO_SIZE (tptr);
-               }
-               /* Skip processing */
+       struct rspamd_xml_userdata *ud = user_data;
 
-               return;
+       if (g_ascii_strcasecmp (ud->section_name[ud->nested], element_name) == 0) {
+               ud->nested --;
        }
-
-       switch (ud->state) {
-               case XML_READ_MODULE_META:
-                       CHECK_TAG ("meta", FALSE);
-                       if (res) {
-                               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) {
-                                       /* Reverse options list */
-                                       ud->parent_pointer[0] = NULL;
-                                       ud->section_pointer = NULL;
-                               }
-                       }
-                       break;
-               case XML_READ_CLASSIFIER:
-                       CHECK_TAG ("classifier", FALSE);
-                       if (res) {
-                               ccf = ud->section_pointer;
-                               if (ccf->statfiles == NULL || !check_classifier_statfiles (ccf)) {
-                                       *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "classifier cannot contains no statfiles or statfiles of the same class");
-                                       ud->state = XML_ERROR;
-                                       return;
-                               }
-                               ud->cfg->classifiers = g_list_prepend (ud->cfg->classifiers, ccf);
-                       }
-                       break;
-               case XML_READ_STATFILE:
-                       CHECK_TAG ("statfile", FALSE);
-                       if (res) {
-                               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) {
-                                       *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "not enough arguments in statfile definition");
-                                       ud->state = XML_ERROR;
-                                       return;
-                               }
-                               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);
-                               if (st->label) {
-                                       if ((labels = g_hash_table_lookup (ccf->labels, st->label))) {
-                                               labels = g_list_append (labels, st);
-                                       }
-                                       else {
-                                               g_hash_table_insert (ccf->labels, st->label, g_list_prepend (NULL, st));
-                                       }
-                               }
-                               ud->section_pointer = ccf;
-                               ud->parent_pointer[0] = NULL;
-                               ud->state = XML_READ_CLASSIFIER;
-                       }
-                       break;
-               case XML_READ_MODULES:
-                       CHECK_TAG ("modules", FALSE);
-                       break;
-               case XML_READ_OPTIONS:
-                       CHECK_TAG ("options", FALSE);
-                       break;
-               case XML_READ_METRIC:
-                       CHECK_TAG ("metric", FALSE);
-                       if (res) {
-                               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;
-                                       return;
-                               }
-                               g_hash_table_insert (ud->cfg->metrics, m->name, m);
-                               ud->cfg->metrics_list = g_list_prepend (ud->cfg->metrics_list, m);
-                       }       
-                       break;
-               case XML_READ_WORKER:
-                       CHECK_TAG ("worker", FALSE);
-                       if (res) {
-                               /* Parse params */
-                               wcd.wrk = ud->section_pointer;
-                               wcd.cfg = ud->cfg;
-                               wcd.ctx = ud;
-                               g_hash_table_foreach (wcd.wrk->params,
-                                               worker_foreach_callback, &wcd);
-                               /* Insert object to list */
-                               ud->cfg->workers = g_list_prepend (ud->cfg->workers, ud->section_pointer);
-                       }
-                       break;
-               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 */
-                       CHECK_TAG (ud->section_name, TRUE);
-                       break;
-               case XML_READ_LOGGING:
-                       CHECK_TAG ("logging", FALSE);
-                       break;
-               case XML_READ_PARAM:
-                       if (g_ascii_strcasecmp (element_name, "rspamd") == 0) {
-                               /* End of document */
-                               ud->state = XML_END; 
-                       }
-                       else {
-                               *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is umatched", element_name);
-                               ud->state = XML_ERROR;
-                       }
-                       break;
-               case XML_SKIP_ELEMENTS:
-                       return;
-#if GLIB_MINOR_VERSION >= 18
-               case XML_SUBPARSER:
-                       CHECK_TAG (ud->section_name, TRUE);
-                       if (subparsers != NULL && (subparser = g_hash_table_lookup (subparsers, element_name)) != NULL) {
-                               if (subparser->fin_func) {
-                                       subparser->fin_func (g_markup_parse_context_pop (context));
-                               }
-                               else {
-                                       g_markup_parse_context_pop (context);
-                               }
-                       }
-                       ud->state = XML_READ_PARAM;
-                       break;
-#endif
-               default:
-                       ud->state = XML_ERROR;
-                       break;
+       else {
+               *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is umatched", element_name);
+               ud->state = XML_ERROR;
        }
-
 }
 #undef CHECK_TAG
 
@@ -2156,95 +1268,11 @@ void
 rspamd_xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len, gpointer user_data, GError **error)
 {
        struct rspamd_xml_userdata *ud = user_data;
-       gchar                           *val;
-       struct config_file *cfg = ud->cfg;
+       ucl_object_t *top;
        
-       /* Strip space symbols */
-       while (*text && g_ascii_isspace (*text)) {
-               text ++;
-       }
-       if (*text == '\0') {
-               /* Skip empty text */
-               return;
-       }
-
-       val = xml_asciiz_string (cfg->cfg_pool, text, text_len);
-
-       switch (ud->state) {
-               case XML_READ_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' data: %s", ud->section_name, val);
-                               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);
-                               ud->state = XML_ERROR;
-                       }
-                       break;
-               case XML_READ_OPTIONS:
-                       if (!call_param_handler (ud, ud->section_name, val, cfg, XML_SECTION_OPTIONS)) {
-                               *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_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' data: %s", ud->section_name, val);
-                               ud->state = XML_ERROR;
-                       }
-                       break;
-               case XML_READ_STATFILE:
-                       if (!call_param_handler (ud, ud->section_name, val, ud->section_pointer, XML_SECTION_STATFILE)) {
-                               *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_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' 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->section_pointer, XML_SECTION_WORKER)) {
-                               *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_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' data: %s", ud->section_name, val);
-                               ud->state = XML_ERROR;
-                       }
-                       break;
-               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' data: %s", ud->section_name, val);
-                               ud->state = XML_ERROR;
-                       }
-                       break;
-               case XML_READ_LOGGING:
-                       if (!call_param_handler (ud, ud->section_name, val, cfg, XML_SECTION_LOGGING)) {
-                               *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_SKIP_ELEMENTS:
-                       /* Do nothing */
-                       return;
-               default:
-                       ud->state = XML_ERROR;
-                       break;
-       }
-
+       top = ud->parent_pointer[ud->nested - 1];
+       ucl_object_insert_key (top, ucl_object_fromstring_common (text, text_len, UCL_STRING_PARSE),
+                       ud->section_name[ud->nested], 0, true);
 }
 
 void 
@@ -2255,179 +1283,11 @@ rspamd_xml_error (GMarkupParseContext *context, GError *error, gpointer user_dat
        msg_err ("xml parser error: %s, at state \"%s\"", error->message, xml_state_to_string (ud));
 }
 
-/* Register handlers for specific parts of config */
-
-/* Checker for module options */
-struct option_callback_data {
-       const gchar *optname;
-       gboolean res;
-       struct xml_config_param *param;
-};
-
-static void
-module_option_callback (gpointer key, gpointer value, gpointer ud)
-{
-       const gchar                      *optname = key;
-       static gchar                      rebuf[512];
-       struct option_callback_data      *cd = ud;
-       GRegex                           *re;
-       GError                           *err = NULL;
-       gsize                             relen;
-
-       if (*optname == '/') {
-               relen = strcspn (optname + 1, "/");
-               if (relen > sizeof (rebuf)) {
-                       relen = sizeof (rebuf);
-               }
-               rspamd_strlcpy (rebuf, optname + 1, relen);
-               /* This is a regexp so compile and check it */
-               re = g_regex_new (rebuf, G_REGEX_CASELESS, 0, &err);
-               if (err != NULL) {
-                       msg_err ("failed to compile regexp for option '%s', error was: %s, regexp was: %s", cd->optname, err->message, rebuf);
-                       return;
-               }
-               if (g_regex_match (re, cd->optname, 0, NULL)) {
-                       cd->res = TRUE;
-                       cd->param = value;
-               }
-       }
-
-       return;
-}
-
-gboolean
-check_module_option (const gchar *mname, const gchar *optname, const gchar *data)
-{
-       struct xml_config_param          *param;
-       enum module_opt_type              type;
-       GHashTable                       *module;
-       gchar                            *err_str;
-       struct option_callback_data       cd;
-       union {
-               gint i;
-               gdouble d;
-               guint ui;
-       }                                 t;
-
-       if (module_options == NULL) {
-               msg_warn ("no module options registered while checking option %s for module %s", mname, optname);
-               return FALSE;
-       }
-       if ((module = g_hash_table_lookup (module_options, mname)) == NULL) {
-               msg_warn ("module %s has not registered any options while checking for option %s", mname, optname);
-               return FALSE;
-       }
-
-       if ((param = g_hash_table_lookup (module, optname)) == NULL) {
-               /* Try to handle regexp options */
-               cd.optname = optname;
-               cd.res = FALSE;
-               g_hash_table_foreach (module, module_option_callback, &cd);
-               if (!cd.res) {
-                       msg_warn ("module %s has not registered option %s", mname, optname);
-                       return FALSE;
-               }
-               param = cd.param;
-       }
-
-       type = param->offset;
-
-       /* Now handle option of each type */
-       switch (type) {
-       case MODULE_OPT_TYPE_STRING:
-       case MODULE_OPT_TYPE_ANY:
-               /* Allways OK */
-               return TRUE;
-       case MODULE_OPT_TYPE_INT:
-               t.i = strtol (data, &err_str, 10);
-               if (*err_str != '\0') {
-                       msg_warn ("non-numeric data for option: '%s' for module: '%s' at position: '%s'", optname, mname, err_str);
-                       return FALSE;
-               }
-               (void)t.i;
-               break;
-       case MODULE_OPT_TYPE_UINT:
-               t.ui = strtoul (data, &err_str, 10);
-               if (*err_str != '\0') {
-                       msg_warn ("non-numeric data for option: '%s' for module: '%s' at position: '%s'", optname, mname, err_str);
-                       return FALSE;
-               }
-               (void)t.ui;
-               break;
-       case MODULE_OPT_TYPE_DOUBLE:
-               t.d = strtod (data, &err_str);
-               if (*err_str != '\0') {
-                       msg_warn ("non-numeric data for option: '%s' for module: '%s' at position: '%s'", optname, mname, err_str);
-                       return FALSE;
-               }
-               (void)t.d;
-               break;
-       case MODULE_OPT_TYPE_TIME:
-               t.ui = cfg_parse_time (data, TIME_SECONDS);
-               if (errno != 0) {
-                       msg_warn ("non-numeric data for option: '%s' for module: '%s': %s", optname, mname, strerror (errno));
-                       return FALSE;
-               }
-               (void)t.ui;
-               break;
-       case MODULE_OPT_TYPE_SIZE:
-               t.ui = parse_limit (data, -1);
-               if (errno != 0) {
-                       msg_warn ("non-numeric data for option: '%s' for module: '%s': %s", optname, mname, strerror (errno));
-                       return FALSE;
-               }
-               (void)t.ui;
-               break;
-       case MODULE_OPT_TYPE_MAP:
-               if (!check_map_proto (data, NULL, NULL)) {
-                       return FALSE;
-               }
-               break;
-       case MODULE_OPT_TYPE_FLAG:
-               if (parse_flag (data) == -1) {
-                       return FALSE;
-               }
-               break;
-       case MODULE_OPT_TYPE_META:
-               msg_warn ("option %s should be meta option for module %s not an ordinary one", optname, mname);
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
 /* Register new module option */
 void
 register_module_opt (const gchar *mname, const gchar *optname, enum module_opt_type type)
 {
-       struct xml_config_param          *param;
-       GHashTable                       *module;
-
-       if (module_options == NULL) {
-               module_options = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
-       }
-       if ((module = g_hash_table_lookup (module_options, mname)) == NULL) {
-               module = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
-               g_hash_table_insert (module_options, (char *)mname, module);
-       }
-       if ((param = g_hash_table_lookup (module, optname)) == NULL) {
-               /* Register new param */
-               param = g_malloc (sizeof (struct xml_config_param));
-               param->handler = NULL;
-               param->offset = type;
-               param->name = optname;
-               g_hash_table_insert (module, (char *)optname, param);
-       }
-       else {
-               /* Param already exists replace it */
-               msg_warn ("replace old handler for param '%s'", optname);
-               g_free (param);
-               param = g_malloc (sizeof (struct xml_config_param));
-               param->handler = NULL;
-               param->offset = type;
-               param->name = optname;
-               g_hash_table_insert (module, (char *)optname, param);
-       }
+       msg_err ("this function is depreciated and must not be used");
 }
 
 /* Register new worker's options */
@@ -2441,447 +1301,11 @@ register_worker_opt (gint wtype, const gchar *optname, element_handler_func func
 void
 register_classifier_opt (const gchar *ctype, const gchar *optname)
 {
-       struct xml_config_param          *param;
-       GHashTable                       *classifier;
-
-       if (classifier_options == NULL) {
-               classifier_options = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
-       }
-       if ((classifier = g_hash_table_lookup (classifier_options, ctype)) == NULL) {
-               classifier = g_hash_table_new (rspamd_str_hash, rspamd_str_equal);
-               g_hash_table_insert (classifier_options, (char *)ctype, classifier);
-       }
-       if ((param = g_hash_table_lookup (classifier, optname)) == NULL) {
-               /* Register new param */
-               param = g_malloc (sizeof (struct xml_config_param));
-               param->handler = NULL;
-               param->user_data = NULL;
-               param->offset = 0;
-               param->name = optname;
-               g_hash_table_insert (classifier, (char *)optname, param);
-       }
-       else {
-               /* Param already exists replace it */
-               msg_warn ("replace old handler for param '%s'", optname);
-               g_free (param);
-               param = g_malloc (sizeof (struct xml_config_param));
-               param->handler = NULL;
-               param->user_data = NULL;
-               param->offset = 0;
-               param->name = optname;
-               g_hash_table_insert (classifier, (char *)optname, param);
-       }
+       msg_err ("this function is depreciated and must not be used");
 }
 
 void
-register_subparser (const gchar *tag, enum xml_read_state state, const GMarkupParser *parser, void (*fin_func)(gpointer ud), gpointer user_data)
-{
-       struct xml_subparser                     *subparser;
-
-       if (subparsers == NULL) {
-               subparsers = g_hash_table_new_full (rspamd_str_hash, rspamd_str_equal, g_free, g_free);
-       }
-       subparser = g_malloc (sizeof (struct xml_subparser));
-
-       subparser->parser = parser;
-       subparser->state = state;
-       subparser->user_data = user_data;
-       subparser->fin_func = fin_func;
-
-       g_hash_table_replace (subparsers, g_strdup (tag), subparser);
-}
-
-
-/* Dumper part */
-
-/* Dump specific sections */
-
-/* Dump main section variables */
-static gboolean
-xml_dump_main (struct config_file *cfg, FILE *f)
+register_subparser (const gchar *tag, int state, const GMarkupParser *parser, void (*fin_func)(gpointer ud), gpointer user_data)
 {
-       gchar                           *escaped_str;
-       
-       /* Print header comment */
-       rspamd_fprintf (f, "<!-- Main section -->" EOL);
-
-       escaped_str = g_markup_escape_text (cfg->temp_dir, -1); 
-       rspamd_fprintf (f, "<tempdir>%s</tempdir>" EOL, escaped_str);
-       g_free (escaped_str);
-
-       escaped_str = g_markup_escape_text (cfg->pid_file, -1); 
-       rspamd_fprintf (f, "<pidfile>%s</pidfile>" EOL, escaped_str);
-       g_free (escaped_str);
-
-       escaped_str = g_markup_escape_text (cfg->filters_str, -1); 
-       rspamd_fprintf (f, "<filters>%s</filters>" EOL, escaped_str);
-       g_free (escaped_str);
-       
-       if (cfg->user_settings_str) {
-               escaped_str = g_markup_escape_text (cfg->user_settings_str, -1); 
-               rspamd_fprintf (f, "<user_settings>%s</user_settings>" EOL, escaped_str);
-               g_free (escaped_str);
-       }
-       if (cfg->domain_settings_str) {
-               escaped_str = g_markup_escape_text (cfg->domain_settings_str, -1); 
-               rspamd_fprintf (f, "<domain_settings>%s</domain_settings>" EOL, escaped_str);
-               g_free (escaped_str);
-       }
-       rspamd_fprintf (f, "<statfile_pool_size>%z</statfile_pool_size>" EOL, cfg->max_statfile_size);
-
-       if (cfg->checksum)  {
-               escaped_str = g_markup_escape_text (cfg->checksum, -1); 
-               rspamd_fprintf (f, "<checksum>%s</checksum>" EOL, escaped_str);
-               g_free (escaped_str);
-       }
-
-       rspamd_fprintf (f, "<raw_mode>%s</raw_mode>" EOL, cfg->raw_mode ? "yes" : "no");
-
-       /* Print footer comment */
-       rspamd_fprintf (f, "<!-- End of main section -->" EOL EOL);
-
-       return TRUE;
-}
-
-/* Dump variables section */
-static void
-xml_variable_callback (gpointer key, gpointer value, gpointer user_data)
-{
-       FILE *f = user_data;
-       gchar                           *escaped_key, *escaped_value;
-
-       escaped_key = g_markup_escape_text (key, -1); 
-       escaped_value = g_markup_escape_text (value, -1);
-       rspamd_fprintf (f,  "<variable name=\"%s\">%s</variable>" EOL, escaped_key, escaped_value);
-       g_free (escaped_key);
-       g_free (escaped_value);
-}
-
-static gboolean
-xml_dump_variables (struct config_file *cfg, FILE *f)
-{
-       /* Print header comment */
-       rspamd_fprintf (f, "<!-- Variables section -->" EOL);
-
-       /* Iterate through variables */
-       g_hash_table_foreach (cfg->variables, xml_variable_callback, (gpointer)f);
-
-       /* Print footer comment */
-       rspamd_fprintf (f, "<!-- End of variables section -->" EOL EOL);
-
-       return TRUE;
-}
-
-/* Composites section */
-static void
-xml_composite_callback (gpointer key, gpointer value, gpointer user_data)
-{
-       FILE *f = user_data;
-       struct expression *expr;
-       gchar                           *escaped_key, *escaped_value;
-       
-       expr = value;
-
-       escaped_key = g_markup_escape_text (key, -1); 
-       escaped_value = g_markup_escape_text (expr->orig, -1);
-       rspamd_fprintf (f,  "<composite name=\"%s\">%s</composite>" EOL, escaped_key, escaped_value);
-       g_free (escaped_key);
-       g_free (escaped_value);
-}
-
-static gboolean
-xml_dump_composites (struct config_file *cfg, FILE *f)
-{
-       /* Print header comment */
-       rspamd_fprintf (f, "<!-- Composites section -->" EOL);
-
-       /* Iterate through variables */
-       g_hash_table_foreach (cfg->composite_symbols, xml_composite_callback, (gpointer)f);
-
-       /* Print footer comment */
-       rspamd_fprintf (f, "<!-- End of composites section -->" EOL EOL);
-
-       return TRUE;
-}
-
-/* Workers */
-static void
-xml_worker_param_callback (gpointer key, gpointer value, gpointer user_data)
-{
-       FILE *f = user_data;
-       gchar                           *escaped_key, *escaped_value;
-
-       escaped_key = g_markup_escape_text (key, -1); 
-       escaped_value = g_markup_escape_text (value, -1);
-       rspamd_fprintf (f,  "    <param name=\"%s\">%s</param>" EOL, escaped_key, escaped_value);
-       g_free (escaped_key);
-       g_free (escaped_value);
-}
-
-static gboolean
-xml_dump_workers (struct config_file *cfg, FILE *f)
-{
-       GList *cur;
-       struct worker_conf *wrk;
-       gchar                           *escaped_str;
-
-       /* Print header comment */
-       rspamd_fprintf (f, "<!-- Workers section -->" EOL);
-
-       /* Iterate through list */
-       cur = g_list_first (cfg->workers);
-       while (cur) {
-               wrk = cur->data;
-               
-               rspamd_fprintf (f, "<worker>" EOL);
-
-               rspamd_fprintf (f, "  <type>%s</type>" EOL, g_quark_to_string (wrk->type));
-
-               rspamd_fprintf (f, "  <count>%ud</count>" EOL, wrk->count);
-               rspamd_fprintf (f, "  <maxfiles>%ud</maxfiles>" EOL, wrk->rlimit_nofile);
-               rspamd_fprintf (f, "  <maxcore>%ud</maxcore>" EOL, wrk->rlimit_maxcore);
-               
-               /* Now dump other attrs */
-               rspamd_fprintf (f, "<!-- Other params -->" EOL);
-               g_hash_table_foreach (wrk->params, xml_worker_param_callback, f);
-
-               rspamd_fprintf (f, "</worker>" EOL);
-
-               cur = g_list_next (cur);
-       }
-
-       /* Print footer comment */
-       rspamd_fprintf (f, "<!-- End of workers section -->" EOL EOL);
-
-       return TRUE;
-}
-
-
-/* Classifiers dump */
-static void
-xml_classifier_callback (gpointer key, gpointer value, gpointer user_data)
-{
-       FILE *f = user_data;
-       gchar                           *escaped_key, *escaped_value;
-
-       escaped_key = g_markup_escape_text (key, -1); 
-       escaped_value = g_markup_escape_text (value, -1);
-       rspamd_fprintf (f,  " <option name=\"%s\">%s</option>" EOL, escaped_key, escaped_value);
-       g_free (escaped_key);
-       g_free (escaped_value);
-}
-
-static gboolean
-xml_dump_classifiers (struct config_file *cfg, FILE *f)
-{
-       GList *cur, *cur_st;
-       struct classifier_config *ccf;
-       struct statfile *st;
-
-       /* Print header comment */
-       rspamd_fprintf (f, "<!-- Classifiers section -->" EOL);
-
-       /* Iterate through classifiers */
-       cur = g_list_first (cfg->classifiers);
-       while (cur) {
-               ccf = cur->data;
-               rspamd_fprintf (f, "<classifier type=\"%s\">" EOL, ccf->classifier->name);
-               rspamd_fprintf (f, " <tokenizer>%s</tokenizer>" EOL, ccf->tokenizer->name);
-               rspamd_fprintf (f, " <metric>%s</metric>" EOL, ccf->metric);
-               g_hash_table_foreach (ccf->opts, xml_classifier_callback, f);
-               /* Statfiles */
-               cur_st = g_list_first (ccf->statfiles);
-               while (cur_st) {
-                       st = cur_st->data;
-                       rspamd_fprintf (f, " <statfile>" EOL);
-                       rspamd_fprintf (f, "  <symbol>%s</symbol>" EOL "  <size>%z</size>" EOL "  <path>%s</path>" EOL,
-                                               st->symbol, st->size, st->path);
-                       rspamd_fprintf (f, "  <normalizer>%s</normalizer>" EOL, st->normalizer_str);
-                       /* Binlog */
-                       if (st->binlog) {
-                               if (st->binlog->affinity == AFFINITY_MASTER) {
-                                       rspamd_fprintf (f, "  <binlog>master</binlog>" EOL);
-                               }
-                               else if (st->binlog->affinity == AFFINITY_SLAVE) {
-                                       rspamd_fprintf (f, "  <binlog>slave</binlog>" EOL);
-                                       rspamd_fprintf (f, "  <binlog_master>%s:%d</binlog_master>" EOL, 
-                                                       st->binlog->master_addr, (gint)ntohs (st->binlog->master_port));
-                               }
-                               rspamd_fprintf (f, "  <binlog_rotate>%T</binlog_rotate>" EOL, st->binlog->rotate_time);
-                       }
-                       rspamd_fprintf (f, " </statfile>" EOL);
-                       cur_st = g_list_next (cur_st);
-               }
-
-               rspamd_fprintf (f, "</classifier>" EOL);
-               cur = g_list_next (cur);
-       }
-
-       /* Print footer comment */
-       rspamd_fprintf (f, "<!-- End of classifiers section -->" EOL EOL);
-
-       return TRUE;
-
-}
-
-/* Logging section */
-static gboolean
-xml_dump_logging (struct config_file *cfg, FILE *f)
-{
-       gchar *escaped_value;
-
-       /* Print header comment */
-       rspamd_fprintf (f, "<!-- Logging section -->" EOL);
-       rspamd_fprintf (f, "<logging>" EOL);
-       
-       /* Level */
-       if (cfg->log_level < G_LOG_LEVEL_WARNING) {
-               rspamd_fprintf (f, " <level>error</level>" EOL);
-       }
-       else if (cfg->log_level < G_LOG_LEVEL_MESSAGE) {
-               rspamd_fprintf (f, " <level>warning</level>" EOL);
-       }
-       else if (cfg->log_level < G_LOG_LEVEL_DEBUG) {
-               rspamd_fprintf (f, " <level>info</level>" EOL);
-       }
-       else {
-               rspamd_fprintf (f, " <level>debug</level>" EOL);
-       }
-       
-       /* Other options */
-       rspamd_fprintf (f, " <log_urls>%s</log_urls>" EOL, cfg->log_urls ? "yes" : "no");
-       if (cfg->log_buf_size != 0) {
-               rspamd_fprintf (f, " <log_buffer>%ud</log_buffer>" EOL, (guint)cfg->log_buf_size);
-       }
-       if (cfg->debug_ip_map != NULL) {
-               escaped_value = g_markup_escape_text (cfg->debug_ip_map, -1);
-               rspamd_fprintf (f, " <debug_ip>%s</debug_ip>" EOL, escaped_value);
-               g_free (escaped_value);
-       }
-       
-       /* Handle type */
-       if (cfg->log_type == RSPAMD_LOG_FILE) {
-               escaped_value = g_markup_escape_text (cfg->log_file, -1);
-               rspamd_fprintf (f, " <type filename=\"%s\">file</type>" EOL, escaped_value);
-               g_free (escaped_value);
-       }
-       else if (cfg->log_type == RSPAMD_LOG_CONSOLE) {
-               rspamd_fprintf (f, " <type>console</type>" EOL);
-       }
-       else if (cfg->log_type == RSPAMD_LOG_SYSLOG) {
-               escaped_value = NULL;
-               switch (cfg->log_facility) {
-                       case LOG_AUTH:
-                               escaped_value = "LOG_AUTH";
-                               break;
-                       case LOG_CRON:
-                               escaped_value = "LOG_CRON";
-                               break;
-                       case LOG_DAEMON:
-                               escaped_value = "LOG_DAEMON";
-                               break;
-                       case LOG_MAIL:
-                               escaped_value = "LOG_MAIL";
-                               break;
-                       case LOG_USER:
-                               escaped_value = "LOG_USER";
-                               break;
-                       case LOG_LOCAL0:
-                               escaped_value = "LOG_LOCAL0";
-                               break;
-                       case LOG_LOCAL1:
-                               escaped_value = "LOG_LOCAL1";
-                               break;
-                       case LOG_LOCAL2:
-                               escaped_value = "LOG_LOCAL2";
-                               break;
-                       case LOG_LOCAL3:
-                               escaped_value = "LOG_LOCAL3";
-                               break;
-                       case LOG_LOCAL4:
-                               escaped_value = "LOG_LOCAL4";
-                               break;
-                       case LOG_LOCAL5:
-                               escaped_value = "LOG_LOCAL5";
-                               break;
-                       case LOG_LOCAL6:
-                               escaped_value = "LOG_LOCAL6";
-                               break;
-                       case LOG_LOCAL7:
-                               escaped_value = "LOG_LOCAL7";
-                               break;
-               }
-               rspamd_fprintf (f, " <type facility=\"%s\">syslog</type>" EOL, escaped_value);
-       }
-       rspamd_fprintf (f, "</logging>" EOL);
-       /* Print footer comment */
-       rspamd_fprintf (f, "<!-- End of logging section -->" EOL EOL);
-
-       return TRUE;
-}
-
-/* Modules */
-static gboolean
-xml_dump_modules_paths (struct config_file *cfg, FILE *f)
-{
-       GList                          *cur;
-       gchar                          *escaped_value;
-       struct script_module           *module;
-
-       /* Print header comment */
-       rspamd_fprintf (f, "<!-- Modules section -->" EOL);
-       rspamd_fprintf (f, "<modules>" EOL);
-
-       cur = cfg->script_modules;
-       while (cur) {
-               module = cur->data;
-               escaped_value = g_markup_escape_text (module->path, -1);
-               rspamd_fprintf (f, " <path>%s</path>" EOL, escaped_value);
-               g_free (escaped_value);
-               cur = g_list_next (cur);
-       }
-
-       rspamd_fprintf (f, "</modules>" EOL);
-       /* Print footer comment */
-       rspamd_fprintf (f, "<!-- End of modules section -->" EOL EOL);
-
-       return TRUE;
-}
-
-
-#define CHECK_RES do { if (!res) { fclose (f); return FALSE; } } while (0)
-gboolean 
-xml_dump_config (struct config_file *cfg, const gchar *filename)
-{
-       FILE *f;
-       gboolean res = FALSE;
-
-       f = fopen (filename, "w");
-       if (f == NULL) {
-               msg_err ("cannot open file '%s': %s", filename, strerror (errno));
-               return FALSE;
-       }
-       
-       /* Header */
-       rspamd_fprintf (f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" EOL "<rspamd>" EOL);
-       /* Now dump all parts of config */
-       res = xml_dump_main (cfg, f);
-       CHECK_RES;
-       res = xml_dump_logging (cfg, f);
-       CHECK_RES;
-       res = xml_dump_variables (cfg, f);
-       CHECK_RES;
-       res = xml_dump_composites (cfg, f);
-       CHECK_RES;
-       res = xml_dump_workers (cfg, f);
-       CHECK_RES;
-       res = xml_dump_classifiers (cfg, f);
-       CHECK_RES;
-       res = xml_dump_modules_paths (cfg, f);
-       CHECK_RES;
-       /* Footer */
-       rspamd_fprintf (f, "</rspamd>" EOL);
-       fclose (f);
-
-       return TRUE;
+       msg_err ("this function is depreciated and must not be used");
 }
index c2930c3651699b2294f99bd5eead9cae1da7853f..9799b49264275562567c520ed9b14e98a06e5b76 100644 (file)
@@ -4,7 +4,7 @@
 #include "config.h"
 #include "cfg_file.h"
 
-#define MAX_NAME 8192
+#define MAX_NAME 128
 
 #define XML_START_MISSING 1
 #define XML_PARAM_MISSING 2
 
 #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,
-       XML_READ_METRIC,
-       XML_READ_WORKER,
-       XML_READ_VIEW,
-       XML_READ_LOGGING,
-       XML_READ_OPTIONS,
-       XML_READ_VALUE,
-       XML_SKIP_ELEMENTS,
-       XML_ERROR,
-       XML_SUBPARSER,
-       XML_END
-};
-
 enum module_opt_type {
        MODULE_OPT_TYPE_STRING = 0,
        MODULE_OPT_TYPE_INT,
@@ -51,13 +31,13 @@ enum module_opt_type {
  * Structure that is used for semantic resolution of configuration
  */
 struct rspamd_xml_userdata {
-       enum xml_read_state state;                              /*< state of parser                                                     */
+       int state;                              /*< state of parser                                                     */
        struct config_file *cfg;                                /*< configuration object                                        */
-       gchar section_name[MAX_NAME];                   /*< current section                                                     */
+       gchar section_name[MAX_INHERIT][MAX_NAME];                      /*< current section                                                     */
        gpointer section_pointer;                               /*< pointer to object related with section      */
        gpointer parent_pointer[MAX_INHERIT];   /*< parent's section object                                     */
        GHashTable *cur_attrs;                                  /*< attributes of current tag                           */
-       GQueue *if_stack;                                               /*< stack of if elements                                        */
+       gint nested;
 };
 
 /* Text is NULL terminated here */
@@ -181,7 +161,7 @@ void register_worker_opt (gint wtype, const gchar *optname, element_handler_func
 void register_classifier_opt (const gchar *ctype, const gchar *optname);
 
 /* Register new xml subparser */
-void register_subparser (const gchar *tag, enum xml_read_state state,
+void register_subparser (const gchar *tag, int state,
                const GMarkupParser *parser, void (*fin_func)(gpointer ud), gpointer user_data);
 
 /* Check validity of module option */
index 406cf7c7324ed4cc758e37e88500a7ef5b780592..dbe58cb112637de38cafc5eae0b8212d8d01c12c 100644 (file)
@@ -516,7 +516,7 @@ init_kvstorage_config (void)
        kv_parser->state = KVSTORAGE_STATE_PARAM;
        kv_parser->pool = memory_pool_new (memory_pool_get_size ());
 
-       register_subparser ("keystorage", XML_READ_START, parser, kvstorage_cleanup, kv_parser);
+       register_subparser ("keystorage", 0, parser, kvstorage_cleanup, kv_parser);
 }
 
 /* Get configuration for kvstorage with specified ID */