*/
struct rspamd_regexp {
enum rspamd_regexp_type type; /**< regexp type */
- char *regexp_text; /**< regexp text representation */
+ gchar *regexp_text; /**< regexp text representation */
GRegex *regexp; /**< glib regexp structure */
GRegex *raw_regexp; /**< glib regexp structure for raw matching */
- char *header; /**< header name for header regexps */
+ gchar *header; /**< header name for header regexps */
};
/**
* script module list item
*/
struct script_module {
- char *name; /**< name of module */
- char *path; /**< path to module */
+ gchar *name; /**< name of module */
+ gchar *path; /**< path to module */
};
/**
* Module option
*/
struct module_opt {
- char *param; /**< parameter name */
- char *value; /**< paramater value */
+ gchar *param; /**< parameter name */
+ gchar *value; /**< paramater value */
};
/**
* Statfile autolearn parameters
*/
struct statfile_autolearn_params {
- const char *metric; /**< metric name for autolearn triggering */
+ const gchar *metric; /**< metric name for autolearn triggering */
double threshold_min; /**< threshold mark */
double threshold_max; /**< threshold mark */
GList *symbols; /**< list of symbols */
* Statfile config definition
*/
struct statfile {
- char *symbol; /**< symbol of statfile */
- char *path; /**< filesystem pattern (with %r or %f) */
- size_t size; /**< size of statfile */
+ gchar *symbol; /**< symbol of statfile */
+ gchar *path; /**< filesystem pattern (with %r or %f) */
+ gsize size; /**< size of statfile */
GList *sections; /**< list of sections in statfile */
struct statfile_autolearn_params *autolearn; /**< autolearn params */
struct statfile_binlog_params *binlog; /**< binlog params */
*/
struct classifier_config {
GList *statfiles; /**< statfiles list */
- char *metric; /**< metric of this classifier */
+ gchar *metric; /**< metric of this classifier */
struct classifier *classifier; /**< classifier interface */
struct tokenizer *tokenizer; /**< tokenizer used for classifier */
GHashTable *opts; /**< other options */
*/
struct worker_conf {
int type; /**< worker type */
- char *bind_host; /**< bind line */
+ gchar *bind_host; /**< bind line */
struct in_addr bind_addr; /**< bind address in case of TCP socket */
uint16_t bind_port; /**< bind port in case of TCP socket */
uint16_t bind_family; /**< bind type (AF_UNIX or AF_INET) */
* Structure that stores all config data
*/
struct config_file {
- char *rspamd_user; /**< user to run as */
- char *rspamd_group; /**< group to run as */
+ gchar *rspamd_user; /**< user to run as */
+ gchar *rspamd_group; /**< group to run as */
memory_pool_t *cfg_pool; /**< memory pool for config */
- char *cfg_name; /**< name of config file */
- char *pid_file; /**< name of pid file */
- char *temp_dir; /**< dir for temp files */
+ gchar *cfg_name; /**< name of config file */
+ gchar *pid_file; /**< name of pid file */
+ gchar *temp_dir; /**< dir for temp files */
#ifdef WITH_GPERF_TOOLS
- char *profile_path;
+ gchar *profile_path;
#endif
gboolean no_fork; /**< if 1 do not call daemon() */
enum rspamd_log_type log_type; /**< log type */
int log_facility; /**< log facility in case of syslog */
int log_level; /**< log level trigger */
- char *log_file; /**< path to logfile in case of file logging */
+ gchar *log_file; /**< path to logfile in case of file logging */
gboolean log_buffered; /**< whether logging is buffered */
uint32_t log_buf_size; /**< length of log buffer */
- char *debug_ip_map; /**< turn on debugging for specified ip addresses */
+ gchar *debug_ip_map; /**< turn on debugging for specified ip addresses */
gboolean log_urls; /**< whether we should log URLs */
- size_t max_statfile_size; /**< maximum size for statfile */
+ gsize max_statfile_size; /**< maximum size for statfile */
struct memcached_server memcached_servers[MAX_MEMCACHED_SERVERS]; /**< memcached servers */
- size_t memcached_servers_num; /**< number of memcached servers */
+ gsize memcached_servers_num; /**< number of memcached servers */
memc_proto_t memcached_protocol; /**< memcached protocol */
unsigned int memcached_error_time; /**< memcached error time (see upstream documentation) */
unsigned int memcached_dead_time; /**< memcached dead time */
unsigned int memcached_connect_timeout; /**< connection timeout */
gboolean delivery_enable; /**< is delivery agent is enabled */
- char *deliver_host; /**< host for mail deliviring */
+ gchar *deliver_host; /**< host for mail deliviring */
struct in_addr deliver_addr; /**< its address */
uint16_t deliver_port; /**< port for deliviring */
uint16_t deliver_family; /**< socket family for delivirnig */
- char *deliver_agent_path; /**< deliver to pipe instead of socket */
+ gchar *deliver_agent_path; /**< deliver to pipe instead of socket */
gboolean deliver_lmtp; /**< use LMTP instead of SMTP */
GList *script_modules; /**< linked list of script modules to load */
GList *filters; /**< linked list of all filters */
GList *workers; /**< linked list of all workers params */
- char *filters_str; /**< string of filters */
+ gchar *filters_str; /**< string of filters */
GHashTable* modules_opts; /**< hash for module options indexed by module name */
GHashTable* variables; /**< hash of $variables defined in config, indexed by variable name */
GHashTable* metrics; /**< hash of metrics indexed by metric name */
* @param str line that describes server's credits
* @return 1 if line was successfully parsed and 0 in case of error
*/
-int add_memcached_server (struct config_file *cf, char *str);
+int add_memcached_server (struct config_file *cf, gchar *str);
/**
* Parse host:port line
* @param port port
* @return TRUE if string was parsed
*/
-gboolean parse_host_port (const char *str, struct in_addr *ina, uint16_t *port);
+gboolean parse_host_port (const gchar *str, struct in_addr *ina, uint16_t *port);
/**
* Parse bind credits
* @param type type of credits
* @return 1 if line was successfully parsed and 0 in case of error
*/
-int parse_bind_line (struct config_file *cfg, struct worker_conf *cf, char *str);
+int parse_bind_line (struct config_file *cfg, struct worker_conf *cf, gchar *str);
/**
* Init default values
* @param opt_name name of option to get
* @return module value or NULL if option does not defined
*/
-char* get_module_opt (struct config_file *cfg, char *module_name, char *opt_name);
+gchar* get_module_opt (struct config_file *cfg, gchar *module_name, gchar *opt_name);
/**
* Parse limit
* @param limit string representation of limit (eg. 1M)
* @return numeric value of limit
*/
-size_t parse_limit (const char *limit);
+gsize parse_limit (const gchar *limit);
/**
* Parse seconds
* @param t string representation of seconds (eg. 1D)
* @return numeric value of string
*/
-unsigned int parse_seconds (const char *t);
+unsigned int parse_seconds (const gchar *t);
/**
* Parse flag
* @param str string representation of flag (eg. 'on')
* @return numeric value of flag (0 or 1)
*/
-char parse_flag (const char *str);
+gchar parse_flag (const gchar *str);
/**
* Substitutes variable in specified string, may be recursive (eg. ${var1${var2}})
* @param recursive whether do recursive scanning
* @return new string with substituted variables (uses cfg memory pool for allocating)
*/
-char* substitute_variable (struct config_file *cfg, char *name, char *str, u_char recursive);
+gchar* substitute_variable (struct config_file *cfg, gchar *name, gchar *str, guchar recursive);
/**
* Do post load actions for config
* Replace all \" with a single " in given string
* @param line input string
*/
-void unescape_quotes (char *line);
+void unescape_quotes (gchar *line);
-GList* parse_comma_list (memory_pool_t *pool, char *line);
+GList* parse_comma_list (memory_pool_t *pool, gchar *line);
struct classifier_config* check_classifier_cfg (struct config_file *cfg, struct classifier_config *c);
struct worker_conf* check_worker_conf (struct config_file *cfg, struct worker_conf *c);
-gboolean parse_normalizer (struct config_file *cfg, struct statfile *st, const char *line);
-gboolean read_xml_config (struct config_file *cfg, const char *filename);
+gboolean parse_normalizer (struct config_file *cfg, struct statfile *st, const gchar *line);
+gboolean read_xml_config (struct config_file *cfg, const gchar *filename);
int yylex (void);
int yyparse (void);
void yyrestart (FILE *);
-void parse_err (const char *fmt, ...);
-void parse_warn (const char *fmt, ...);
+void parse_err (const gchar *fmt, ...);
+void parse_warn (const gchar *fmt, ...);
#endif /* ifdef CFG_FILE_H */
/*
#define DEFAULT_RLIMIT_MAXCORE 0
extern int yylineno;
-extern char *yytext;
+extern gchar *yytext;
int
-add_memcached_server (struct config_file *cf, char *str)
+add_memcached_server (struct config_file *cf, gchar *str)
{
struct memcached_server *mc;
uint16_t port;
}
gboolean
-parse_host_port (const char *str, struct in_addr *ina, uint16_t *port)
+parse_host_port (const gchar *str, struct in_addr *ina, uint16_t *port)
{
- char **tokens, *err_str;
+ gchar **tokens, *err_str;
struct hostent *hent;
unsigned int port_parsed, saved_errno = errno;
}
int
-parse_bind_line (struct config_file *cfg, struct worker_conf *cf, char *str)
+parse_bind_line (struct config_file *cfg, struct worker_conf *cf, gchar *str)
{
- char **host;
+ gchar **host;
int16_t *family, *port;
struct in_addr *addr;
/* Try to check path of bind credit */
struct stat st;
int fd;
- char *copy = memory_pool_strdup (cfg->cfg_pool, str);
+ gchar *copy = memory_pool_strdup (cfg->cfg_pool, str);
if (stat (copy, &st) == -1) {
if (errno == ENOENT) {
if ((fd = open (str, O_RDWR | O_TRUNC | O_CREAT, S_IWUSR | S_IRUSR)) == -1) {
memory_pool_delete (cfg->cfg_pool);
}
-char *
-get_module_opt (struct config_file *cfg, char *module_name, char *opt_name)
+gchar *
+get_module_opt (struct config_file *cfg, gchar *module_name, gchar *opt_name)
{
GList *cur_opt;
struct module_opt *cur;
return NULL;
}
-size_t
-parse_limit (const char *limit)
+gsize
+parse_limit (const gchar *limit)
{
- size_t result = 0;
- char *err_str;
+ gsize result = 0;
+ gchar *err_str;
if (!limit || *limit == '\0')
return 0;
}
unsigned int
-parse_seconds (const char *t)
+parse_seconds (const gchar *t)
{
unsigned int result = 0;
- char *err_str;
+ gchar *err_str;
if (!t || *t == '\0')
return 0;
return result;
}
-char
-parse_flag (const char *str)
+gchar
+parse_flag (const gchar *str)
{
if (!str || !*str)
return -1;
* Try to substitute all variables in given string
* Return: newly allocated string with substituted variables (original string may be freed if variables are found)
*/
-char *
-substitute_variable (struct config_file *cfg, char *name, char *str, u_char recursive)
+gchar *
+substitute_variable (struct config_file *cfg, gchar *name, gchar *str, guchar recursive)
{
- char *var, *new, *v_begin, *v_end, *p, t;
- size_t len;
+ gchar *var, *new, *v_begin, *v_end, *p, t;
+ gsize len;
gboolean changed = FALSE;
if (str == NULL) {
struct config_file *cfg = (struct config_file *)data;
/* Do recursive substitution */
- (void)substitute_variable (cfg, (char *)key, (char *)value, 1);
+ (void)substitute_variable (cfg, (gchar *)key, (gchar *)value, 1);
}
static void
-parse_filters_str (struct config_file *cfg, const char *str)
+parse_filters_str (struct config_file *cfg, const gchar *str)
{
gchar **strvec, **p;
struct filter *cur;
void
-parse_err (const char *fmt, ...)
+parse_err (const gchar *fmt, ...)
{
va_list aq;
- char logbuf[BUFSIZ], readbuf[32];
+ gchar logbuf[BUFSIZ], readbuf[32];
int r;
va_start (aq, fmt);
}
void
-parse_warn (const char *fmt, ...)
+parse_warn (const gchar *fmt, ...)
{
va_list aq;
- char logbuf[BUFSIZ], readbuf[32];
+ gchar logbuf[BUFSIZ], readbuf[32];
int r;
va_start (aq, fmt);
}
void
-unescape_quotes (char *line)
+unescape_quotes (gchar *line)
{
- char *c = line, *t;
+ gchar *c = line, *t;
while (*c) {
if (*c == '\\' && *(c + 1) == '"') {
}
GList *
-parse_comma_list (memory_pool_t * pool, char *line)
+parse_comma_list (memory_pool_t * pool, gchar *line)
{
GList *res = NULL;
- char *c, *p, *str;
+ gchar *c, *p, *str;
c = line;
p = c;
}
static gboolean
-parse_internal_normalizer (struct config_file *cfg, struct statfile *st, const char *line)
+parse_internal_normalizer (struct config_file *cfg, struct statfile *st, const gchar *line)
{
double *max;
- char *err;
+ gchar *err;
/* Line contains maximum value for internal normalizer */
max = memory_pool_alloc (cfg->cfg_pool, sizeof (double));
#ifdef WITH_LUA
static gboolean
-parse_lua_normalizer (struct config_file *cfg, struct statfile *st, const char *line)
+parse_lua_normalizer (struct config_file *cfg, struct statfile *st, const gchar *line)
{
- char *code_begin;
+ gchar *code_begin;
GList *params = NULL;
int len;
gboolean
-parse_normalizer (struct config_file *cfg, struct statfile *st, const char *line)
+parse_normalizer (struct config_file *cfg, struct statfile *st, const gchar *line)
{
- char *params_begin;
+ gchar *params_begin;
params_begin = strchr (line, ':');
if (params_begin == NULL) {
};
gboolean
-read_xml_config (struct config_file *cfg, const char *filename)
+read_xml_config (struct config_file *cfg, const gchar *filename)
{
struct stat st;
int fd;
#include "config.h"
#include "cfg_xml.h"
#include "logger.h"
+#include "util.h"
+
+/* Maximum attributes for param */
+#define MAX_PARAM 64
+
+#define NULL_ATTR \
+{ \
+ NULL, \
+ NULL, \
+ 0, \
+ NULL \
+} \
+
+/* Basic xml parsing functions */
+gboolean xml_handle_string (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+/* Numeric params */
+gboolean xml_handle_size (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean xml_handle_double (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean xml_handle_seconds (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean xml_handle_int (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean xml_handle_uint32 (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean xml_handle_uint16 (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+/* Flags */
+gboolean xml_handle_boolean (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+/* Specific params */
+gboolean worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+gboolean handle_factor (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset);
+
+
+enum xml_config_section {
+ XML_SECTION_MAIN,
+ XML_SECTION_LOGGING,
+ XML_SECTION_WORKER,
+ XML_SECTION_METRIC,
+ XML_SECTION_CLASSIFIER,
+ XML_SECTION_FACTORS,
+ XML_SECTION_MODULE,
+ XML_SECTION_MODULES,
+ XML_SECTION_VIEW,
+ XML_SECTION_SETTINGS
+};
+
+struct xml_config_param {
+ const char *name;
+ element_handler_func handler;
+ int offset;
+ gpointer user_data;
+};
+
+struct xml_parser_rule {
+ enum xml_config_section section;
+ struct xml_config_param params[MAX_PARAM];
+ struct xml_config_param default_param;
+};
+
+/* Here we describes our basic grammar */
+static struct xml_parser_rule grammar[] = {
+ { XML_SECTION_MAIN, {
+ {
+ "pidfile",
+ xml_handle_string,
+ G_STRUCT_OFFSET (struct config_file, pid_file),
+ NULL
+ },
+ {
+ "statfile_pool_size",
+ xml_handle_size,
+ G_STRUCT_OFFSET (struct config_file, max_statfile_size),
+ NULL
+ },
+ {
+ "filters",
+ xml_handle_string,
+ G_STRUCT_OFFSET (struct config_file, filters_str),
+ NULL
+ },
+ NULL_ATTR
+ },
+ NULL_ATTR
+ },
+ { XML_SECTION_LOGGING, {
+ NULL_ATTR
+ },
+ NULL_ATTR
+ },
+ { XML_SECTION_WORKER, {
+ NULL_ATTR
+ },
+ {
+ NULL,
+ worker_handle_param,
+ 0,
+ NULL
+ },
+ },
+ { XML_SECTION_METRIC, {
+ NULL_ATTR
+ },
+ NULL_ATTR
+ },
+ { XML_SECTION_CLASSIFIER, {
+ NULL_ATTR
+ },
+ NULL_ATTR
+ },
+ { XML_SECTION_FACTORS, {
+ {
+ "grow_factor",
+ xml_handle_double,
+ G_STRUCT_OFFSET (struct config_file, grow_factor),
+ NULL
+ },
+ NULL_ATTR
+ },
+ {
+ NULL,
+ handle_factor,
+ 0,
+ NULL
+ }
+ },
+ { XML_SECTION_MODULE, {
+ NULL_ATTR
+ },
+ NULL_ATTR
+ },
+ { XML_SECTION_MODULES, {
+ NULL_ATTR
+ },
+ NULL_ATTR
+ },
+ { XML_SECTION_VIEW, {
+ NULL_ATTR
+ },
+ NULL_ATTR
+ },
+ { XML_SECTION_SETTINGS, {
+ NULL_ATTR
+ },
+ NULL_ATTR
+ }
+};
GQuark
xml_error_quark (void)
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)
+{
+ 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));
+ 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, const gchar *value, gpointer dest_struct, enum xml_config_section section)
+{
+ struct xml_parser_rule *rule;
+ struct xml_config_param *param;
+ int 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) {
+ param = &rule->default_param;
+ /* Call default handler */
+ return param->handler (ctx->cfg, ctx, ctx->cur_attrs, value, param->user_data, dest_struct, param->offset);
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+gboolean
+worker_handle_param (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+
+}
+
+gboolean
+handle_factor (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+
+}
+
static void
xml_parse_module_opt (struct rspamd_xml_userdata *ud, const gchar *text, gsize len)
{
}
+/* Common handlers */
+gboolean
+xml_handle_string (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+ /* Simply assign pointer to pointer */
+ gchar **dest;
+
+ dest = (char **)G_STRUCT_MEMBER_P (dest_struct, offset);
+ *dest = memory_pool_strdup (cfg->cfg_pool, data);
+
+ return TRUE;
+}
+
+
+gboolean
+xml_handle_size (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+ gsize *dest;
+
+ dest = (gsize *)G_STRUCT_MEMBER_P (dest_struct, offset);
+ *dest = parse_limit (data);
+
+ return TRUE;
+}
+
+gboolean
+xml_handle_seconds (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+ time_t *dest;
+
+ dest = (time_t *)G_STRUCT_MEMBER_P (dest_struct, offset);
+ *dest = parse_seconds (data);
+
+ return TRUE;
+}
+
+gboolean
+xml_handle_boolean (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int 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_double (struct config_file *cfg, struct rspamd_xml_userdata *ctx, GHashTable *attrs, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+ double *dest;
+ char *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, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+ int *dest;
+ char *err = NULL;
+
+ dest = (int *)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, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+ uint32_t *dest;
+ char *err = NULL;
+
+ dest = (uint32_t *)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, const gchar *data, gpointer user_data, gpointer dest_struct, int offset)
+{
+ uint16_t *dest;
+ char *err = NULL;
+
+ dest = (uint16_t *)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;
+}
+
void
rspamd_xml_start_element (GMarkupParseContext *context, const gchar *element_name, const gchar **attribute_names,
const gchar **attribute_values, gpointer user_data, GError **error)
if (g_ascii_strcasecmp (element_name, "module") == 0) {
/* Read module data */
if (extract_attr ("name", attribute_names, attribute_values, &res)) {
- ud->section_name = g_strdup (res);
+ g_strlcpy (ud->section_name, res, sizeof (res));
ud->state = XML_READ_MODULE;
}
else {
}
else if (g_ascii_strcasecmp (element_name, "metric") == 0) {
if (extract_attr ("name", attribute_names, attribute_values, &res)) {
- ud->section_name = g_strdup (res);
+ g_strlcpy (ud->section_name, res, sizeof (res));
ud->state = XML_READ_METRIC;
}
else {
}
else if (g_ascii_strcasecmp (element_name, "classifier") == 0) {
if (extract_attr ("type", attribute_names, attribute_values, &res)) {
- ud->section_name = g_strdup (res);
+ g_strlcpy (ud->section_name, res, sizeof (res));
ud->state = XML_READ_CLASSIFIER;
}
else {
}
}
else if (g_ascii_strcasecmp (element_name, "worker") == 0) {
- if (extract_attr ("type", attribute_names, attribute_values, &res)) {
- ud->section_name = g_strdup (res);
- ud->state = XML_READ_WORKER;
- }
- else {
- *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'type' is required for tag 'worker'");
- ud->state = XML_ERROR;
- }
+ ud->state = XML_READ_WORKER;
}
else {
/* Other params */
if (g_ascii_strcasecmp (element_name, "variable") == 0) {
if (extract_attr ("name", attribute_names, attribute_values, &res)) {
- ud->section_name = g_strdup (res);
+ g_strlcpy (ud->section_name, res, sizeof (res));
ud->state = XML_READ_VARIABLE;
}
else {
}
break;
case XML_READ_MODULE:
- if (g_ascii_strcasecmp (element_name, "param") == 0) {
- if (extract_attr ("name", attribute_names, attribute_values, &res)) {
- ud->other_data = g_strdup (res);
- }
- else {
- *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'name' is required for tag 'param'");
- ud->state = XML_ERROR;
- }
- }
- break;
+ case XML_READ_FACTORS:
case XML_READ_CLASSIFIER:
- break;
case XML_READ_STATFILE:
- break;
- case XML_READ_FACTORS:
- if (g_ascii_strcasecmp (element_name, "factor") == 0) {
- if (extract_attr ("name", attribute_names, attribute_values, &res)) {
- ud->other_data = g_strdup (res);
- }
- else {
- *error = g_error_new (xml_error_quark (), XML_PARAM_MISSING, "param 'name' is required for tag 'factor'");
- ud->state = XML_ERROR;
- }
- }
- break;
case XML_READ_WORKER:
- break;
case XML_READ_LOGGING:
+ /* Save attributes */
+ ud->cur_attrs = process_attrs (ud->cfg, attribute_names, attribute_values);
break;
default:
*error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "element %s is unexpected in this state", element_name);
if (g_ascii_strcasecmp (element_name, (x)) == 0) { \
ud->state = XML_READ_PARAM; \
res = TRUE; \
- if (!required) { \
- g_free (ud->section_name); \
- } \
} \
else { \
res = FALSE; \
{
struct rspamd_xml_userdata *ud = user_data;
char *val;
- double *tmp;
+ struct config_file *cfg = ud->cfg;
+
+ val = xml_asciiz_string (cfg->cfg_pool, text, text_len);
switch (ud->state) {
case XML_READ_MODULE:
- if (ud->other_data) {
- /* Insert or replace module's option */
- xml_parse_module_opt (ud, text, text_len);
- g_free (ud->other_data);
+ if (!call_param_handler (ud, ud->section_name, val, ud->other_data, XML_SECTION_MODULE)) {
+ *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%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->other_data, XML_SECTION_CLASSIFIER)) {
+ *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
+ ud->state = XML_ERROR;
+ }
break;
case XML_READ_STATFILE:
break;
case XML_READ_FACTORS:
- if (ud->other_data) {
- /* Assume that we have factor name in other_data */
- val = xml_asciiz_string (ud->cfg->cfg_pool, text, text_len);
- tmp = memory_pool_alloc (ud->cfg->cfg_pool, sizeof (double));
- *tmp = strtod (val, NULL);
- g_hash_table_insert (ud->cfg->factors, ud->other_data, tmp);
- g_free (ud->other_data);
+ 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);
+ ud->state = XML_ERROR;
}
break;
case XML_READ_METRIC:
+ if (!call_param_handler (ud, ud->section_name, val, ud->other_data, XML_SECTION_METRIC)) {
+ *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
+ ud->state = XML_ERROR;
+ }
break;
case XML_READ_WORKER:
- break;
- case XML_READ_VARIABLE:
- if (ud->other_data) {
- /* Assume that we have factor name in other_data */
- val = xml_asciiz_string (ud->cfg->cfg_pool, text, text_len);
- g_hash_table_insert (ud->cfg->variables, ud->other_data, val);
- g_free (ud->other_data);
+ if (!call_param_handler (ud, ud->section_name, val, ud->other_data, XML_SECTION_WORKER)) {
+ *error = g_error_new (xml_error_quark (), XML_EXTRA_ELEMENT, "cannot parse tag's '%s' data: %s", ud->section_name, val);
+ ud->state = XML_ERROR;
}
break;
+ case XML_READ_VARIABLE:
case XML_READ_PIDFILE:
- val = xml_asciiz_string (ud->cfg->cfg_pool, text, text_len);
- ud->cfg->pid_file = val;
- break;
case XML_READ_STATFILE_POOL:
- val = xml_asciiz_string (ud->cfg->cfg_pool, text, text_len);
- ud->cfg->max_statfile_size = strtoull (val, NULL, 10);
- break;
case XML_READ_FILTERS:
- val = xml_asciiz_string (ud->cfg->cfg_pool, text, text_len);
- ud->cfg->filters_str = val;
+ 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);
+ 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);
+ ud->state = XML_ERROR;
+ }
break;
case XML_READ_PARAM:
break;