From: Vsevolod Stakhov Date: Fri, 23 Aug 2013 01:15:03 +0000 (+0100) Subject: Add common principles of rspamd rcl configuration. X-Git-Tag: 0.6.0~205 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=fa8ab8833f3a0b660585a3edc09d33246efffd13;p=rspamd.git Add common principles of rspamd rcl configuration. --- diff --git a/src/cfg_rcl.c b/src/cfg_rcl.c index cf7ab8d93..7ca175123 100644 --- a/src/cfg_rcl.c +++ b/src/cfg_rcl.c @@ -24,8 +24,86 @@ #include "cfg_rcl.h" #include "main.h" +struct rspamd_rcl_section* +rspamd_rcl_config_init (void) +{ + struct rspamd_rcl_section *new; + + new = g_slice_alloc0 (sizeof (struct rspamd_rcl_section)); + + /* TODO: add all known rspamd sections here */ + + return new; +} + +struct rspamd_rcl_section * +rspamd_rcl_config_get_section (struct rspamd_rcl_section *top, + const char *path) +{ + struct rspamd_rcl_section *cur, *found; + char **path_components; + gint ncomponents, i; + + + if (path == NULL) { + return top; + } + + path_components = g_strsplit_set (path, "/", -1); + ncomponents = g_strv_length (path_components); + + cur = top; + for (i = 0; i < ncomponents; i ++) { + if (cur == NULL) { + g_strfreev (path_components); + return NULL; + } + HASH_FIND_STR (cur, path_components[i], found); + if (found == NULL) { + g_strfreev (path_components); + return NULL; + } + cur = found; + } + + g_strfreev (path_components); + return found; +} + gboolean -read_rcl_config (struct config_file *cfg, rspamd_cl_object_t *obj, GError **err) +rspamd_read_rcl_config (struct rspamd_rcl_section *top, + struct config_file *cfg, rspamd_cl_object_t *obj, GError **err) { + rspamd_cl_object_t *found; + struct rspamd_rcl_section *cur, *tmp; + + if (obj->type != RSPAMD_CL_OBJECT) { + g_set_error (err, CFG_RCL_ERROR, EINVAL, "top configuration must be an object"); + return FALSE; + } + + /* Iterate over known sections and ignore unknown ones */ + HASH_ITER (hh, top, cur, tmp) { + HASH_FIND_STR (obj->value.ov, cur->name, found); + if (found == NULL) { + if (cur->required) { + g_set_error (err, CFG_RCL_ERROR, ENOENT, "required section %s is missing", cur->name); + return FALSE; + } + } + else { + /* Check type */ + if (cur->strict_type) { + if (cur->type != found->type) { + g_set_error (err, CFG_RCL_ERROR, EINVAL, "object in section %s has invalid type", cur->name); + return FALSE; + } + } + if (!cur->handler (cfg, found, NULL, cur, err)) { + return FALSE; + } + } + } + return TRUE; } diff --git a/src/cfg_rcl.h b/src/cfg_rcl.h index a0c05f2e2..d02d196b1 100644 --- a/src/cfg_rcl.h +++ b/src/cfg_rcl.h @@ -28,12 +28,59 @@ #include "rcl/rcl.h" #include "main.h" +#define CFG_RCL_ERROR cfg_rcl_error_quark () +static inline GQuark +cfg_rcl_error_quark (void) +{ + return g_quark_from_static_string ("cfg-rcl-error-quark"); +} + +struct rspamd_rcl_section; + +/** + * Common handler type + * @param cfg configuration + * @param obj object to parse + * @param ud user data (depends on section) + * @param err error object + * @return TRUE if a section has been parsed + */ +typedef gboolean (*rspamd_rcl_handler_t) (struct config_file *cfg, rspamd_cl_object_t *obj, + gpointer ud, struct rspamd_rcl_section *section, GError **err); + +struct rspamd_rcl_section { + const gchar *name; /**< name of section */ + rspamd_rcl_handler_t handler; /**< handler of section attributes */ + enum rspamd_cl_type type; /**< type of attribute */ + gboolean required; /**< whether this param is required */ + gboolean strict_type; /**< whether we need strict type */ + UT_hash_handle hh; /** hash handle */ + struct rspamd_rcl_section *subsections; /**< hash table of subsections */ +}; + +/** + * Init common sections known to rspamd + * @return top section + */ +struct rspamd_rcl_section* rspamd_rcl_config_init (void); + +/** + * Get a section specified by path, it understand paths separated by '/' character + * @param top top section + * @param path '/' divided path + * @return + */ +struct rspamd_rcl_section *rspamd_rcl_config_get_section (struct rspamd_rcl_section *top, + const char *path); + /** * Read RCL configuration and parse it to a config file + * @param top top section * @param cfg target configuration * @param obj object to handle * @return TRUE if an object can be parsed */ -gboolean read_rcl_config (struct config_file *cfg, rspamd_cl_object_t *obj, GError **err); +gboolean rspamd_read_rcl_config (struct rspamd_rcl_section *top, + struct config_file *cfg, rspamd_cl_object_t *obj, GError **err); #endif /* CFG_RCL_H_ */