]> source.dussan.org Git - rspamd.git/commitdiff
* Wellcome to the XML world
authorVsevolod Stakhov <vsevolod@rambler-co.ru>
Wed, 7 Apr 2010 15:56:23 +0000 (19:56 +0400)
committerVsevolod Stakhov <vsevolod@rambler-co.ru>
Wed, 7 Apr 2010 15:56:23 +0000 (19:56 +0400)
src/cfg_file.h
src/cfg_file.y
src/cfg_utils.c
src/cfg_xml.c
src/cfg_xml.h
src/main.c

index 0cf70e8a00587b65ca977062aae71ef1bf92005f..fb220f4860d60cd9875a8eb2e8cb20ce2e58e264 100644 (file)
@@ -290,6 +290,8 @@ struct config_file {
        GList *views;                                                                   /**< views                                                                                              */
        GHashTable* domain_settings;                    /**< settings per-domains                               */
        GHashTable* user_settings;                      /**< settings per-user                                  */
+       gchar* domain_settings_str;                                             /**< string representation of settings                                  */
+       gchar* user_settings_str;
        
        gchar* checksum;                                                                /**< real checksum of config file                                               */ 
        gchar* dump_checksum;                                                   /**< dump checksum of config file                                               */ 
index 47d3a545c4b6b9c4031ae31de57a4ab0a20ad9a4..58813ad6bff4b774ffd9dda92e278e97d601d5d8 100644 (file)
@@ -1140,6 +1140,7 @@ usersettings:
             yyerror ("yyparse: cannot read settings %s", $3);
             YYERROR;
         }
+               cfg->user_settings_str = memory_pool_strdup (cfg->cfg_pool, $3);
     }
     ;
 domainsettings:
@@ -1148,6 +1149,7 @@ domainsettings:
             yyerror ("yyparse: cannot read settings %s", $3);
             YYERROR;
         }
+               cfg->domain_settings_str = memory_pool_strdup (cfg->cfg_pool, $3);
     }
     ;
 %%
index 9047340fb5bd3a0770229223a1f994f7e025aaf8..4450d6cad05fd7294e1604c6068302e69aa19151 100644 (file)
@@ -862,7 +862,7 @@ read_xml_config (struct config_file *cfg, const gchar *filename)
        ud.cfg = cfg;
        ud.state = XML_READ_START;
 
-       ctx = g_markup_parse_context_new (&xml_parser, G_MARKUP_TREAT_CDATA_AS_TEXT, &ud, NULL);
+       ctx = g_markup_parse_context_new (&xml_parser, G_MARKUP_TREAT_CDATA_AS_TEXT | G_MARKUP_PREFIX_ERROR_POSITION, &ud, NULL);
        res = g_markup_parse_context_parse (ctx, data, st.st_size, &err);
 
        munmap (data, st.st_size);
index c089bf7a075b5b960d32f9d55875573d7917be3e..5acba2d4963d1dcaf296dcf312e8841885753aee 100644 (file)
@@ -41,6 +41,8 @@
 /* Maximum attributes for param */
 #define MAX_PARAM 64
 
+#define EOL "\n"
+
 #define NULL_ATTR      \
 {                                      \
        NULL,                   \
@@ -412,7 +414,7 @@ extract_attr (const gchar *attr, const gchar **attribute_names, const gchar **at
        cur_value = attribute_values;
 
        while (*cur_attr && *cur_value) {
-               if (g_ascii_strcasecmp (*cur_attr, attr)) {
+               if (g_ascii_strcasecmp (*cur_attr, attr) == 0) {
                        *res = (gchar *) *cur_value;
                        return TRUE;
                }
@@ -700,7 +702,7 @@ handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHa
                        is_lua = TRUE;
                }
        }
-       cur_opt = g_hash_table_lookup (cfg->modules_opts, ctx->section_name);
+       cur_opt = g_hash_table_lookup (cfg->modules_opts, ctx->section_pointer);
        if (cur_opt == NULL) {
                /* Insert new option structure */
                cur = memory_pool_alloc0 (cfg->cfg_pool, sizeof (struct module_opt));
@@ -708,7 +710,7 @@ handle_module_opt (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHa
                cur->value = data;
                cur->is_lua = is_lua;
                cur_opt = g_list_prepend (NULL, cur);
-               g_hash_table_insert (cfg->modules_opts, memory_pool_strdup (cfg->cfg_pool, ctx->section_name), cur_opt);
+               g_hash_table_insert (cfg->modules_opts, memory_pool_strdup (cfg->cfg_pool, ctx->section_pointer), cur_opt);
        }
        else {
                /* First try to find option with this name */
@@ -886,6 +888,7 @@ handle_view_symbols (struct config_file *cfg, struct rspamd_xml_userdata *ctx, G
                msg_err ("invalid symbols line in view definition: ip = '%s'", data);
                return FALSE;
        }
+       cfg->domain_settings_str = memory_pool_strdup (cfg->cfg_pool, data);
 
        return TRUE;
 }
@@ -898,6 +901,7 @@ handle_user_settings (struct config_file *cfg, struct rspamd_xml_userdata *ctx,
                msg_err ("cannot read settings %s", data);
                return FALSE;
        }
+       cfg->user_settings_str = memory_pool_strdup (cfg->cfg_pool, data);
 
        return TRUE;
 }
@@ -1134,7 +1138,8 @@ 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;
-       gchar *res;
+       struct classifier_config   *ccf;
+       gchar                      *res;
 
        switch (ud->state) {
                case XML_READ_START:
@@ -1152,7 +1157,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)) {
-                                       g_strlcpy (ud->section_name, res, sizeof (ud->section_name));
+                                       ud->section_pointer = res;
                                        ud->state = XML_READ_MODULE;
                                }
                                else {
@@ -1180,10 +1185,16 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                        }
                        else if (g_ascii_strcasecmp (element_name, "classifier") == 0) {
                                if (extract_attr ("type", attribute_names, attribute_values, &res)) {
-                                       g_strlcpy (ud->section_name, res, sizeof (ud->section_name));
                                        ud->state = XML_READ_CLASSIFIER;
                                        /* Create object */
-                                       ud->section_pointer = check_classifier_cfg (ud->cfg, NULL);
+                                       ccf = check_classifier_cfg (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'");
@@ -1203,6 +1214,7 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                        else {
                                /* Extract other tags */
                                g_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;
                        }
                        break;
@@ -1214,12 +1226,18 @@ rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_nam
                                ud->parent_pointer = ud->section_pointer;
                                ud->section_pointer = memory_pool_alloc0 (ud->cfg->cfg_pool, sizeof (struct statfile));
                        }
+                       else {
+                               g_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:
                case XML_READ_FACTORS:
                case XML_READ_STATFILE:
                case XML_READ_WORKER:
                case XML_READ_LOGGING:
+                       g_strlcpy (ud->section_name, element_name, sizeof (ud->section_name));
                        /* Save attributes */
                        ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values);
                        break;
@@ -1269,6 +1287,7 @@ rspamd_xml_end_element (GMarkupParseContext       *context, const gchar *element_name,
                                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);
@@ -1343,56 +1362,64 @@ rspamd_xml_text (GMarkupParseContext *context, const gchar *text, gsize text_len
        char *val;
        struct config_file *cfg = ud->cfg;
 
+       if (*text == '\n') {
+               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 '%s' data: %s", ud->section_name, val);
+                               *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 '%s' data: %s", ud->section_name, val);
+                               *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_FACTORS:
                        if (!call_param_handler (ud, ud->section_name, val, cfg, XML_SECTION_CLASSIFIER)) {
-                               *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
+                               *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 '%s' data: %s", ud->section_name, val);
+                               *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 '%s' data: %s", ud->section_name, val);
+                               *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 '%s' data: %s", ud->section_name, val);
+                               *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 '%s' data: %s", ud->section_name, val);
+                               *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 '%s' data: %s", ud->section_name, val);
+                               *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;
@@ -1423,30 +1450,42 @@ xml_dump_main (struct config_file *cfg, FILE *f)
        char *escaped_str;
        
        /* Print header comment */
-       fprintf (f, "<!-- Main section -->" CRLF);
+       fprintf (f, "<!-- Main section -->" EOL);
 
        escaped_str = g_markup_escape_text (cfg->temp_dir, -1); 
-       fprintf (f, "<tempdir>%s</tempdir>" CRLF, escaped_str);
+       fprintf (f, "<tempdir>%s</tempdir>" EOL, escaped_str);
        g_free (escaped_str);
 
        escaped_str = g_markup_escape_text (cfg->pid_file, -1); 
-       fprintf (f, "<pidfile>%s</pidfile>" CRLF, escaped_str);
+       fprintf (f, "<pidfile>%s</pidfile>" EOL, escaped_str);
        g_free (escaped_str);
 
        escaped_str = g_markup_escape_text (cfg->filters_str, -1); 
-       fprintf (f, "<filters>%s</filters>" CRLF, escaped_str);
+       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); 
+               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); 
+               fprintf (f, "<domain_settings>%s</domain_settings>" EOL, escaped_str);
+               g_free (escaped_str);
+       }
+       fprintf (f, "<statfile_pool_size>%llu</statfile_pool_size>" EOL, (long long unsigned)cfg->max_statfile_size);
 
        if (cfg->checksum)  {
                escaped_str = g_markup_escape_text (cfg->checksum, -1); 
-               fprintf (f, "<checksum>%s</checksum>" CRLF, escaped_str);
+               fprintf (f, "<checksum>%s</checksum>" EOL, escaped_str);
                g_free (escaped_str);
        }
 
-       fprintf (f, "<raw_mode>%s</raw_mode>" CRLF, cfg->raw_mode ? "yes" : "no");
+       fprintf (f, "<raw_mode>%s</raw_mode>" EOL, cfg->raw_mode ? "yes" : "no");
 
        /* Print footer comment */
-       fprintf (f, "<!-- End of main section -->" CRLF);
+       fprintf (f, "<!-- End of main section -->" EOL EOL);
 
        return TRUE;
 }
@@ -1460,7 +1499,7 @@ xml_variable_callback (gpointer key, gpointer value, gpointer user_data)
 
        escaped_key = g_markup_escape_text (key, -1); 
        escaped_value = g_markup_escape_text (value, -1);
-       fprintf (f,  "<variable name=\"%s\">%s</variable>" CRLF, escaped_key, escaped_value);
+       fprintf (f,  "<variable name=\"%s\">%s</variable>" EOL, escaped_key, escaped_value);
        g_free (escaped_key);
        g_free (escaped_value);
 }
@@ -1469,13 +1508,13 @@ static gboolean
 xml_dump_variables (struct config_file *cfg, FILE *f)
 {
        /* Print header comment */
-       fprintf (f, "<!-- Variables section -->" CRLF);
+       fprintf (f, "<!-- Variables section -->" EOL);
 
        /* Iterate through variables */
        g_hash_table_foreach (cfg->variables, xml_variable_callback, (gpointer)f);
 
        /* Print footer comment */
-       fprintf (f, "<!-- End of variables section -->" CRLF);
+       fprintf (f, "<!-- End of variables section -->" EOL EOL);
 
        return TRUE;
 }
@@ -1492,7 +1531,7 @@ xml_composite_callback (gpointer key, gpointer value, gpointer user_data)
 
        escaped_key = g_markup_escape_text (key, -1); 
        escaped_value = g_markup_escape_text (expr->orig, -1);
-       fprintf (f,  "<composite name=\"%s\">%s</composite>" CRLF, escaped_key, escaped_value);
+       fprintf (f,  "<composite name=\"%s\">%s</composite>" EOL, escaped_key, escaped_value);
        g_free (escaped_key);
        g_free (escaped_value);
 }
@@ -1501,13 +1540,13 @@ static gboolean
 xml_dump_composites (struct config_file *cfg, FILE *f)
 {
        /* Print header comment */
-       fprintf (f, "<!-- Composites section -->" CRLF);
+       fprintf (f, "<!-- Composites section -->" EOL);
 
        /* Iterate through variables */
        g_hash_table_foreach (cfg->composite_symbols, xml_composite_callback, (gpointer)f);
 
        /* Print footer comment */
-       fprintf (f, "<!-- End of composites section -->" CRLF);
+       fprintf (f, "<!-- End of composites section -->" EOL EOL);
 
        return TRUE;
 }
@@ -1521,7 +1560,7 @@ xml_worker_param_callback (gpointer key, gpointer value, gpointer user_data)
 
        escaped_key = g_markup_escape_text (key, -1); 
        escaped_value = g_markup_escape_text (value, -1);
-       fprintf (f,  "    <param name=\"%s\">%s</param>" CRLF, escaped_key, escaped_value);
+       fprintf (f,  "    <param name=\"%s\">%s</param>" EOL, escaped_key, escaped_value);
        g_free (escaped_key);
        g_free (escaped_value);
 }
@@ -1534,47 +1573,47 @@ xml_dump_workers (struct config_file *cfg, FILE *f)
        char *escaped_str;
 
        /* Print header comment */
-       fprintf (f, "<!-- Workers section -->" CRLF);
+       fprintf (f, "<!-- Workers section -->" EOL);
 
        /* Iterate through list */
        cur = g_list_first (cfg->workers);
        while (cur) {
                wrk = cur->data;
                
-               fprintf (f, "<worker>" CRLF);
+               fprintf (f, "<worker>" EOL);
                switch (wrk->type) {
                        case TYPE_WORKER:
-                               fprintf (f, "  <type>normal</type>" CRLF);
+                               fprintf (f, "  <type>normal</type>" EOL);
                                break;
                        case TYPE_CONTROLLER:
-                               fprintf (f, "  <type>controller</type>" CRLF);
+                               fprintf (f, "  <type>controller</type>" EOL);
                                break;
                        case TYPE_FUZZY:
-                               fprintf (f, "  <type>fuzzy</type>" CRLF);
+                               fprintf (f, "  <type>fuzzy</type>" EOL);
                                break;
                        case TYPE_LMTP:
-                               fprintf (f, "  <type>lmtp</type>" CRLF);
+                               fprintf (f, "  <type>lmtp</type>" EOL);
                                break;
                }
                escaped_str = g_markup_escape_text (wrk->bind_host, -1); 
-               fprintf (f, "  <bind_socket>%s</bind_socket>" CRLF, escaped_str);
+               fprintf (f, "  <bind_socket>%s</bind_socket>" EOL, escaped_str);
                g_free (escaped_str);
 
-               fprintf (f, "  <count>%u</count>" CRLF, wrk->count);
-               fprintf (f, "  <maxfiles>%u</maxfiles>" CRLF, wrk->rlimit_nofile);
-               fprintf (f, "  <maxcore>%u</maxcore>" CRLF, wrk->rlimit_maxcore);
+               fprintf (f, "  <count>%u</count>" EOL, wrk->count);
+               fprintf (f, "  <maxfiles>%u</maxfiles>" EOL, wrk->rlimit_nofile);
+               fprintf (f, "  <maxcore>%u</maxcore>" EOL, wrk->rlimit_maxcore);
                
                /* Now dump other attrs */
-               fprintf (f, "<!-- Other params -->" CRLF);
+               fprintf (f, "<!-- Other params -->" EOL);
                g_hash_table_foreach (wrk->params, xml_worker_param_callback, f);
 
-               fprintf (f, "</worker>" CRLF);
+               fprintf (f, "</worker>" EOL);
 
                cur = g_list_next (cur);
        }
 
        /* Print footer comment */
-       fprintf (f, "<!-- End of workers section -->" CRLF);
+       fprintf (f, "<!-- End of workers section -->" EOL EOL);
 
        return TRUE;
 }
@@ -1589,8 +1628,8 @@ xml_module_callback (gpointer key, gpointer value, gpointer user_data)
        struct module_opt *opt;
        
        escaped_key = g_markup_escape_text (key, -1); 
-       fprintf (f, "<!-- %s -->" CRLF, escaped_key);
-       fprintf (f, "<module name=\"%s\">" CRLF, escaped_key);
+       fprintf (f, "<!-- %s -->" EOL, escaped_key);
+       fprintf (f, "<module name=\"%s\">" EOL, escaped_key);
        g_free (escaped_key);
 
        cur = g_list_first (value);
@@ -1598,25 +1637,25 @@ xml_module_callback (gpointer key, gpointer value, gpointer user_data)
                opt = cur->data;
                escaped_key = g_markup_escape_text (opt->param, -1); 
                escaped_value = g_markup_escape_text (opt->value, -1);
-               fprintf (f,  "  <option name=\"%s\">%s</option>" CRLF, escaped_key, escaped_value);
+               fprintf (f,  "  <option name=\"%s\">%s</option>" EOL, escaped_key, escaped_value);
                g_free (escaped_key);
                g_free (escaped_value);
                cur = g_list_next (cur);
        }
-       fprintf (f, "</module>" CRLF);
+       fprintf (f, "</module>" EOL EOL);
 }
 
 static gboolean
 xml_dump_modules (struct config_file *cfg, FILE *f)
 {
        /* Print header comment */
-       fprintf (f, "<!-- Modules section -->" CRLF);
+       fprintf (f, "<!-- Modules section -->" EOL);
 
        /* Iterate through variables */
        g_hash_table_foreach (cfg->modules_opts, xml_module_callback, (gpointer)f);
 
        /* Print footer comment */
-       fprintf (f, "<!-- End of modules section -->" CRLF);
+       fprintf (f, "<!-- End of modules section -->" EOL EOL);
 
        return TRUE;
 }
@@ -1630,7 +1669,7 @@ xml_classifier_callback (gpointer key, gpointer value, gpointer user_data)
 
        escaped_key = g_markup_escape_text (key, -1); 
        escaped_value = g_markup_escape_text (value, -1);
-       fprintf (f,  " <param name=\"%s\">%s</param>" CRLF, escaped_key, escaped_value);
+       fprintf (f,  " <option name=\"%s\">%s</option>" EOL, escaped_key, escaped_value);
        g_free (escaped_key);
        g_free (escaped_value);
 }
@@ -1643,51 +1682,148 @@ xml_dump_classifiers (struct config_file *cfg, FILE *f)
        struct statfile *st;
 
        /* Print header comment */
-       fprintf (f, "<!-- Classifiers section -->" CRLF);
+       fprintf (f, "<!-- Classifiers section -->" EOL);
 
        /* Iterate through classifiers */
        cur = g_list_first (cfg->classifiers);
        while (cur) {
                ccf = cur->data;
-               fprintf (f, "<classifier type=\"%s\">" CRLF, ccf->classifier->name);
-               fprintf (f, " <tokenizer>%s</tokenizer>" CRLF, ccf->tokenizer->name);
-               fprintf (f, " <metric>%s</metric>" CRLF, ccf->metric);
+               fprintf (f, "<classifier type=\"%s\">" EOL, ccf->classifier->name);
+               fprintf (f, " <tokenizer>%s</tokenizer>" EOL, ccf->tokenizer->name);
+               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;
-                       fprintf (f, " <statfile>" CRLF);
-                       fprintf (f, "  <symbol>%s</symbol>" CRLF "  <size>%lu</size>" CRLF "  <path>%s</path>" CRLF,
+                       fprintf (f, " <statfile>" EOL);
+                       fprintf (f, "  <symbol>%s</symbol>" EOL "  <size>%lu</size>" EOL "  <path>%s</path>" EOL,
                                                st->symbol, (long unsigned)st->size, st->path);
-                       fprintf (f, "  <normalizer>%s</normalizer>" CRLF, st->normalizer_str);
+                       fprintf (f, "  <normalizer>%s</normalizer>" EOL, st->normalizer_str);
                        /* Binlog */
                        if (st->binlog) {
                                if (st->binlog->affinity == AFFINITY_MASTER) {
-                                       fprintf (f, "  <binlog>master</binlog>" CRLF);
+                                       fprintf (f, "  <binlog>master</binlog>" EOL);
                                }
                                else if (st->binlog->affinity == AFFINITY_SLAVE) {
-                                       fprintf (f, "  <binlog>slave</binlog>" CRLF);
-                                       fprintf (f, "  <binlog_master>%s:%d</binlog_master>" CRLF
+                                       fprintf (f, "  <binlog>slave</binlog>" EOL);
+                                       fprintf (f, "  <binlog_master>%s:%d</binlog_master>" EOL
                                                        inet_ntoa (st->binlog->master_addr), ntohs (st->binlog->master_port)); 
                                }
-                               fprintf (f, "  <binlog_rotate>%lu</binlog_rotate>" CRLF, (long unsigned)st->binlog->rotate_time);
+                               fprintf (f, "  <binlog_rotate>%lu</binlog_rotate>" EOL, (long unsigned)st->binlog->rotate_time);
                        }
-                       fprintf (f, " </statfile>" CRLF);
+                       fprintf (f, " </statfile>" EOL);
                        cur_st = g_list_next (cur_st);
                }
 
-               fprintf (f, "</classifier>" CRLF);
+               fprintf (f, "</classifier>" EOL);
                cur = g_list_next (cur);
        }
 
        /* Print footer comment */
-       fprintf (f, "<!-- End of modules section -->" CRLF);
+       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 */
+       fprintf (f, "<!-- Logging section -->" EOL);
+       fprintf (f, "<logging>" EOL);
+       
+       /* Level */
+       if (cfg->log_level < G_LOG_LEVEL_WARNING) {
+               fprintf (f, " <level>error</level>" EOL);
+       }
+       else if (cfg->log_level < G_LOG_LEVEL_MESSAGE) {
+               fprintf (f, " <level>warning</level>" EOL);
+       }
+       else if (cfg->log_level < G_LOG_LEVEL_DEBUG) {
+               fprintf (f, " <level>info</level>" EOL);
+       }
+       else {
+               fprintf (f, " <level>debug</level>" EOL);
+       }
+       
+       /* Other options */
+       fprintf (f, " <log_urls>%s</log_urls>" EOL, cfg->log_urls ? "yes" : "no");
+       if (cfg->log_buf_size != 0) {
+               fprintf (f, " <log_buffer>%u</log_buffer>" EOL, (unsigned)cfg->log_buf_size);
+       }
+       if (cfg->debug_ip_map != NULL) {
+               escaped_value = g_markup_escape_text (cfg->debug_ip_map, -1);
+               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);
+               fprintf (f, " <type filename=\"%s\">file</type>" EOL, escaped_value);
+               g_free (escaped_value);
+       }
+       else if (cfg->log_type == RSPAMD_LOG_CONSOLE) {
+               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;
+               }
+               fprintf (f, " <type facility=\"%s\">syslog</type>" EOL, escaped_value);
+       }
+       fprintf (f, "</logging>" EOL);
+       /* Print footer comment */
+       fprintf (f, "<!-- End of logging 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 char *filename)
@@ -1702,10 +1838,12 @@ xml_dump_config (struct config_file *cfg, const char *filename)
        }
        
        /* Header */
-       fprintf (f, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" CRLF "<rspamd>" CRLF);
+       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);
@@ -1717,7 +1855,7 @@ xml_dump_config (struct config_file *cfg, const char *filename)
        res = xml_dump_classifiers (cfg, f);
        CHECK_RES;
        /* Footer */
-       fprintf (f, "</rspamd>" CRLF);
+       fprintf (f, "</rspamd>" EOL);
        fclose (f);
 
        return TRUE;
index d27f147ca632ecb9159ceb8bdc3ddad4bcdb86c7..62e011fc646725d91e3d934e82c858463b2ffd0b 100644 (file)
@@ -10,6 +10,7 @@
 #define XML_PARAM_MISSING 2
 #define XML_EXTRA_ELEMENT 3
 #define XML_UNMATCHED_TAG 4
+#define XML_INVALID_ATTR 5
 
 enum xml_read_state {
        XML_READ_START,
index 022773038e8cf5173a023b8a7d4cdd54072fddf9..442e09de91cf1593bb61eba007306f59640691bc 100644 (file)
@@ -72,6 +72,7 @@ static gchar                   *cfg_name;
 static gchar                   *rspamd_user;
 static gchar                   *rspamd_group;
 static gchar                   *rspamd_pidfile;
+static gchar                   *convert_config;
 static gboolean                 dump_vars;
 static gboolean                 dump_cache;
 
@@ -94,6 +95,7 @@ static GOptionEntry entries[] =
   { "pid", 'p', 0, G_OPTION_ARG_STRING, &rspamd_pidfile, "Path to pidfile", NULL },
   { "dump-vars", 'V', 0, G_OPTION_ARG_NONE, &dump_vars, "Print all rspamd variables and exit", NULL },
   { "dump-cache", 'C', 0, G_OPTION_ARG_NONE, &dump_cache, "Dump symbols cache stats and exit", NULL },
+  { "convert-config", 'X', 0, G_OPTION_ARG_STRING, &convert_config, "Convert old style of config to xml one", NULL },
   { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL }
 };
 
@@ -535,11 +537,95 @@ wait_for_workers (gpointer key, gpointer value, gpointer unused)
        return TRUE;
 }
 
+static gboolean
+convert_old_config (struct rspamd_main *rspamd) 
+{
+       FILE *f;
+
+       f = fopen (rspamd->cfg->cfg_name, "r");
+       if (f == NULL) {
+               msg_err ("cannot open file: %s", rspamd->cfg->cfg_name);
+               return EBADF;
+       }
+       yyin = f;
+
+       if (yyparse () != 0 || yynerrs > 0) {
+               msg_err ("cannot parse config file, %d errors", yynerrs);
+               return EBADF;
+       }
+
+       /* Strictly set temp dir */
+       if (!rspamd->cfg->temp_dir) {
+               msg_warn ("tempdir is not set, trying to use $TMPDIR");
+               rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, getenv ("TMPDIR"));
+
+               if (!rspamd->cfg->temp_dir) {
+                       msg_warn ("$TMPDIR is empty too, using /tmp as default");
+                       rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, "/tmp");
+               }
+       }
+
+
+       fclose (f);
+       /* Dump it to xml */
+       if (get_config_checksum (rspamd->cfg)) {
+               if (xml_dump_config (rspamd->cfg, convert_config)) {
+                       rspamd->cfg->cfg_name = convert_config;
+                       return TRUE;
+               }
+       }
+       
+       return FALSE;
+}
+
+static gboolean
+load_rspamd_config (struct rspamd_main *rspamd)
+{
+       GList                          *l;
+       struct filter                  *filt;
+       struct module_ctx              *cur_module = NULL;
+
+       if (! read_xml_config (rspamd->cfg, rspamd->cfg->cfg_name)) {
+               return FALSE;
+       }
+
+       /* Strictly set temp dir */
+       if (!rspamd->cfg->temp_dir) {
+               msg_warn ("tempdir is not set, trying to use $TMPDIR");
+               rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, getenv ("TMPDIR"));
+
+               if (!rspamd->cfg->temp_dir) {
+                       msg_warn ("$TMPDIR is empty too, using /tmp as default");
+                       rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, "/tmp");
+               }
+       }
+
+       /* Do post-load actions */
+       post_load_config (rspamd->cfg);
+       /* Init counters */
+       counters = rspamd_hash_new_shared (rspamd->server_pool, g_str_hash, g_str_equal, 64);
+
+       /* Init C modules */
+       l = g_list_first (rspamd->cfg->filters);
+
+       while (l) {
+               filt = l->data;
+               if (filt->module) {
+                       cur_module = memory_pool_alloc (rspamd->cfg->cfg_pool, sizeof (struct module_ctx));
+                       if (filt->module->module_init_func (cfg, &cur_module) == 0) {
+                               g_hash_table_insert (cfg->c_modules, (gpointer) filt->module->name, cur_module);
+                       }
+               }
+               l = g_list_next (l);
+       }
+       
+       return TRUE;
+}
+
 int
 main (int argc, char **argv, char **env)
 {
        struct rspamd_main             *rspamd;
-       struct module_ctx              *cur_module = NULL;
        int                             res = 0, i;
        struct sigaction                signals;
        struct rspamd_worker           *cur;
@@ -547,7 +633,6 @@ main (int argc, char **argv, char **env)
        struct metric                  *metric;
        struct cache_item              *item;
        struct filter                  *filt;
-       FILE                           *f;
        pid_t                           wrk;
        GList                          *l;
 #ifndef WITHOUT_PERL
@@ -610,41 +695,15 @@ main (int argc, char **argv, char **env)
        init_title (argc, argv, environ);
 #endif
        init_lua (cfg);
-
-       f = fopen (rspamd->cfg->cfg_name, "r");
-       if (f == NULL) {
-               msg_err ("cannot open file: %s", rspamd->cfg->cfg_name);
-               return EBADF;
-       }
-       yyin = f;
-
-       if (yyparse () != 0 || yynerrs > 0) {
-               msg_err ("cannot parse config file, %d errors", yynerrs);
-               return EBADF;
-       }
-
-       fclose (f);
-       /* Dump it to xml */
-       if (get_config_checksum (rspamd->cfg)) {
-               xml_dump_config (rspamd->cfg, "/tmp/rspamd.xml");
+       
+       if (convert_config != NULL) {
+               if (! convert_old_config (rspamd)) {
+                       exit (EXIT_FAILURE);
+               }
        }
-       /* Do post-load actions */
-       post_load_config (rspamd->cfg);
-       /* Init counters */
-       counters = rspamd_hash_new_shared (rspamd->server_pool, g_str_hash, g_str_equal, 64);
 
-       /* Init C modules */
-       l = g_list_first (rspamd->cfg->filters);
-
-       while (l) {
-               filt = l->data;
-               if (filt->module) {
-                       cur_module = memory_pool_alloc (rspamd->cfg->cfg_pool, sizeof (struct module_ctx));
-                       if (filt->module->module_init_func (cfg, &cur_module) == 0) {
-                               g_hash_table_insert (cfg->c_modules, (gpointer) filt->module->name, cur_module);
-                       }
-               }
-               l = g_list_next (l);
+       if (! load_rspamd_config (rspamd)) {
+               exit (EXIT_FAILURE);
        }
 
        if (cfg->config_test || dump_vars || dump_cache) {
@@ -704,17 +763,6 @@ main (int argc, char **argv, char **env)
        msg_info ("rspamd " RVERSION " is starting");
        rspamd->cfg->cfg_name = memory_pool_strdup (rspamd->cfg->cfg_pool, rspamd->cfg->cfg_name);
 
-       /* Strictly set temp dir */
-       if (!rspamd->cfg->temp_dir) {
-               msg_warn ("tempdir is not set, trying to use $TMPDIR");
-               rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, getenv ("TMPDIR"));
-
-               if (!rspamd->cfg->temp_dir) {
-                       msg_warn ("$TMPDIR is empty too, using /tmp as default");
-                       rspamd->cfg->temp_dir = memory_pool_strdup (rspamd->cfg->cfg_pool, "/tmp");
-               }
-       }
-
        if (!rspamd->cfg->no_fork && daemon (0, 0) == -1) {
                fprintf (stderr, "Cannot daemonize\n");
                exit (-errno);