diff options
-rw-r--r-- | src/libserver/dynamic_cfg.c | 7 | ||||
-rw-r--r-- | src/libutil/map.c | 230 | ||||
-rw-r--r-- | src/libutil/map.h | 14 | ||||
-rw-r--r-- | src/lua/lua_map.c | 3 | ||||
-rw-r--r-- | src/plugins/surbl.c | 12 |
5 files changed, 191 insertions, 75 deletions
diff --git a/src/libserver/dynamic_cfg.c b/src/libserver/dynamic_cfg.c index 27fec9da9..48ce0725a 100644 --- a/src/libserver/dynamic_cfg.c +++ b/src/libserver/dynamic_cfg.c @@ -133,11 +133,12 @@ apply_dynamic_conf (const ucl_object_t *top, struct rspamd_config *cfg) } /* Callbacks for reading json dynamic rules */ -gchar * +static gchar * json_config_read_cb (rspamd_mempool_t * pool, gchar * chunk, gint len, - struct map_cb_data *data) + struct map_cb_data *data, + gboolean final) { struct config_json_buf *jb, *pd; @@ -165,7 +166,7 @@ json_config_read_cb (rspamd_mempool_t * pool, return NULL; } -void +static void json_config_fin_cb (rspamd_mempool_t * pool, struct map_cb_data *data) { struct config_json_buf *jb; diff --git a/src/libutil/map.c b/src/libutil/map.c index 3d965c5a5..972cae2d2 100644 --- a/src/libutil/map.c +++ b/src/libutil/map.c @@ -377,7 +377,7 @@ http_map_finish (struct rspamd_http_connection *conn, g_assert (in != NULL); - map->read_callback (map->pool, in, inlen, &cbd->cbdata); + map->read_callback (map->pool, in, inlen, &cbd->cbdata, TRUE); map->fin_callback (map->pool, &cbd->cbdata); *map->user_data = cbd->cbdata.cur_data; @@ -473,9 +473,8 @@ read_map_file (struct rspamd_map *map, struct file_map_data *data) } } - map->read_callback (map->pool, bytes, len, &cbdata); - if (len > 0) { + map->read_callback (map->pool, bytes, len, &cbdata, TRUE); map->fin_callback (map->pool, &cbdata); *map->user_data = cbdata.cur_data; } @@ -949,14 +948,40 @@ rspamd_map_add (struct rspamd_config *cfg, /** * FSM for parsing lists */ + +#define MAP_STORE_KEY do { \ + key = rspamd_mempool_alloc (pool, p - c + 1); \ + rspamd_strlcpy (key, c, p - c + 1); \ +} while (0) + +#define MAP_STORE_VALUE do { \ + value = rspamd_mempool_alloc (pool, p - c + 1); \ + rspamd_strlcpy (value, c, p - c + 1); \ + value = g_strstrip (value); \ +} while (0) + gchar * rspamd_parse_kv_list (rspamd_mempool_t * pool, gchar * chunk, gint len, struct map_cb_data *data, insert_func func, - const gchar *default_value) + const gchar *default_value, + gboolean final) { + enum { + map_skip_spaces_before_key = 0, + map_read_key, + map_read_key_quoted, + map_read_key_slashed, + map_skip_spaces_after_key, + map_read_value, + map_read_value_quoted, + map_read_comment_start, + map_skip_comment, + map_read_eol, + }; + gchar *c, *p, *key = NULL, *value = NULL, *end; p = chunk; @@ -965,99 +990,174 @@ rspamd_parse_kv_list (rspamd_mempool_t * pool, while (p < end) { switch (data->state) { - case 0: + case map_skip_spaces_before_key: + if (g_ascii_isspace (*p)) { + p ++; + } + else { + c = p; + data->state = map_read_key; + } + break; + case map_read_key: /* read key */ /* Check here comments, eol and end of buffer */ if (*p == '#') { - if (key != NULL && p - c >= 0) { - value = rspamd_mempool_alloc (pool, p - c + 1); - memcpy (value, c, p - c); - value[p - c] = '\0'; - value = g_strstrip (value); - func (data->cur_data, key, value); - msg_debug_pool ("insert kv pair: %s -> %s", key, value); - } - else if (key == NULL && p - c > 0) { + if (p - c > 0) { + /* Store a single key */ + MAP_STORE_KEY; func (data->cur_data, key, default_value); msg_debug_pool ("insert key only pair: %s -> %s", key, default_value); + key = NULL; } - data->state = 99; + data->state = map_read_comment_start; } else if (*p == '\r' || *p == '\n') { - if (key != NULL && p - c >= 0) { - value = rspamd_mempool_alloc (pool, p - c + 1); - memcpy (value, c, p - c); - value[p - c] = '\0'; - - value = g_strstrip (value); - func (data->cur_data, key, value); - msg_debug_pool ("insert kv pair: %s -> %s", key, value); - } - else if (key == NULL && p - c > 0) { - /* Key only line */ - key = rspamd_mempool_alloc (pool, p - c + 1); - memcpy (key, c, p - c); - key[p - c] = '\0'; - key = g_strstrip (key); + if (p - c > 0) { + /* Store a single key */ + MAP_STORE_KEY; func (data->cur_data, key, default_value); msg_debug_pool ("insert key only pair: %s -> %s", key, default_value); + key = NULL; } - data->state = 100; + + data->state = map_read_eol; key = NULL; } else if (g_ascii_isspace (*p)) { if (p - c > 0) { - key = rspamd_mempool_alloc (pool, p - c + 1); - memcpy (key, c, p - c); - key[p - c] = '\0'; - key = g_strstrip (key); - data->state = 2; + MAP_STORE_KEY; + data->state = map_skip_spaces_after_key; } else { - key = NULL; + /* Should not happen */ + g_assert_not_reached (); } } else { p++; } break; - case 2: - /* Skip spaces before value */ - if (!g_ascii_isspace (*p)) { - c = p; - data->state = 0; + case map_skip_spaces_after_key: + if (g_ascii_isspace (*p)) { + p ++; } else { - p++; + c = p; + data->state = map_read_value; } break; - case 99: - /* SKIP_COMMENT */ - /* Skip comment till end of line */ - if (*p == '\r' || *p == '\n') { - while ((*p == '\r' || *p == '\n') && p < end) { - p++; + case map_read_value: + g_assert (key != NULL); + if (*p == '#') { + if (p - c > 0) { + /* Store a single key */ + MAP_STORE_VALUE; + func (data->cur_data, key, value); + msg_debug_pool ("insert key value pair: %s -> %s", + key, value); + key = NULL; + value = NULL; } - c = p; + else { + func (data->cur_data, key, default_value); + msg_debug_pool ("insert key only pair: %s -> %s", + key, default_value); + key = NULL; + } + + data->state = map_read_comment_start; + } + else if (*p == '\r' || *p == '\n') { + if (p - c > 0) { + /* Store a single key */ + MAP_STORE_VALUE; + func (data->cur_data, key, value); + msg_debug_pool ("insert key value pair: %s -> %s", + key, value); + key = NULL; + value = NULL; + } + else { + func (data->cur_data, key, default_value); + msg_debug_pool ("insert key only pair: %s -> %s", + key, default_value); + key = NULL; + } + + data->state = map_read_eol; key = NULL; - data->state = 0; } else { - p++; + p ++; + } + break; + case map_read_comment_start: + if (*p == '#') { + data->state = map_skip_comment; + p ++; + key = NULL; + value = NULL; + } + else { + g_assert_not_reached (); + } + break; + case map_skip_comment: + if (*p == '\r' || *p == '\n') { + data->state = map_read_eol; + } + else { + p ++; } break; - case 100: + case map_read_eol: /* Skip \r\n and whitespaces */ - if (*p == '\r' || *p == '\n' || g_ascii_isspace (*p)) { + if (*p == '\r' || *p == '\n') { p++; } else { - c = p; + data->state = map_skip_spaces_before_key; + } + break; + default: + g_assert_not_reached (); + break; + } + } + + if (final) { + /* Examine the state */ + switch (data->state) { + case map_read_key: + if (p - c > 0) { + /* Store a single key */ + MAP_STORE_KEY; + func (data->cur_data, key, default_value); + msg_debug_pool ("insert key only pair: %s -> %s", + key, default_value); + key = NULL; + } + break; + case map_read_value: + g_assert (key != NULL); + if (p - c > 0) { + /* Store a single key */ + MAP_STORE_VALUE; + func (data->cur_data, key, value); + msg_debug_pool ("insert key value pair: %s -> %s", + key, value); + key = NULL; + value = NULL; + } + else { + func (data->cur_data, key, default_value); + msg_debug_pool ("insert key only pair: %s -> %s", + key, default_value); key = NULL; - data->state = 0; } break; } @@ -1082,7 +1182,8 @@ gchar * rspamd_hosts_read (rspamd_mempool_t * pool, gchar * chunk, gint len, - struct map_cb_data *data) + struct map_cb_data *data, + gboolean final) { if (data->cur_data == NULL) { data->cur_data = g_hash_table_new (rspamd_strcase_hash, @@ -1093,7 +1194,8 @@ rspamd_hosts_read (rspamd_mempool_t * pool, len, data, (insert_func) g_hash_table_insert, - hash_fill); + hash_fill, + final); } void @@ -1112,7 +1214,8 @@ gchar * rspamd_kv_list_read (rspamd_mempool_t * pool, gchar * chunk, gint len, - struct map_cb_data *data) + struct map_cb_data *data, + gboolean final) { if (data->cur_data == NULL) { data->cur_data = g_hash_table_new (rspamd_strcase_hash, @@ -1123,7 +1226,8 @@ rspamd_kv_list_read (rspamd_mempool_t * pool, len, data, (insert_func) g_hash_table_insert, - ""); + "", + final); } void @@ -1142,7 +1246,8 @@ gchar * rspamd_radix_read (rspamd_mempool_t * pool, gchar * chunk, gint len, - struct map_cb_data *data) + struct map_cb_data *data, + gboolean final) { radix_compressed_t *tree; rspamd_mempool_t *rpool; @@ -1158,7 +1263,8 @@ rspamd_radix_read (rspamd_mempool_t * pool, len, data, (insert_func) radix_tree_insert_helper, - hash_fill); + hash_fill, + final); } void diff --git a/src/libutil/map.h b/src/libutil/map.h index 13def079a..6ceb04e14 100644 --- a/src/libutil/map.h +++ b/src/libutil/map.h @@ -19,7 +19,7 @@ struct map_cb_data; * Callback types */ typedef gchar * (*map_cb_t)(rspamd_mempool_t *pool, gchar *chunk, gint len, - struct map_cb_data *data); + struct map_cb_data *data, gboolean final); typedef void (*map_fin_cb_t)(rspamd_mempool_t *pool, struct map_cb_data *data); /** @@ -80,7 +80,8 @@ typedef void (*insert_func) (gpointer st, gconstpointer key, gchar * rspamd_radix_read (rspamd_mempool_t *pool, gchar *chunk, gint len, - struct map_cb_data *data); + struct map_cb_data *data, + gboolean final); void rspamd_radix_fin (rspamd_mempool_t *pool, struct map_cb_data *data); /** @@ -89,7 +90,8 @@ void rspamd_radix_fin (rspamd_mempool_t *pool, struct map_cb_data *data); gchar * rspamd_hosts_read (rspamd_mempool_t *pool, gchar *chunk, gint len, - struct map_cb_data *data); + struct map_cb_data *data, + gboolean final); void rspamd_hosts_fin (rspamd_mempool_t *pool, struct map_cb_data *data); /** @@ -98,7 +100,8 @@ void rspamd_hosts_fin (rspamd_mempool_t *pool, struct map_cb_data *data); gchar * rspamd_kv_list_read (rspamd_mempool_t *pool, gchar *chunk, gint len, - struct map_cb_data *data); + struct map_cb_data *data, + gboolean final); void rspamd_kv_list_fin (rspamd_mempool_t *pool, struct map_cb_data *data); /** @@ -109,6 +112,7 @@ gchar * rspamd_parse_kv_list (rspamd_mempool_t * pool, gint len, struct map_cb_data *data, insert_func func, - const gchar *default_value); + const gchar *default_value, + gboolean final); #endif diff --git a/src/lua/lua_map.c b/src/lua/lua_map.c index 04c0af005..51db9f97b 100644 --- a/src/lua/lua_map.c +++ b/src/lua/lua_map.c @@ -272,7 +272,8 @@ lua_config_add_kv_map (lua_State *L) static gchar * lua_map_read (rspamd_mempool_t *pool, gchar *chunk, gint len, - struct map_cb_data *data) + struct map_cb_data *data, + gboolean final) { struct lua_map_callback_data *cbdata, *old; diff --git a/src/plugins/surbl.c b/src/plugins/surbl.c index df22b1610..dcf69f8f2 100644 --- a/src/plugins/surbl.c +++ b/src/plugins/surbl.c @@ -114,7 +114,8 @@ static gchar * read_exceptions_list (rspamd_mempool_t * pool, gchar * chunk, gint len, - struct map_cb_data *data) + struct map_cb_data *data, + gboolean final) { if (data->cur_data == NULL) { data->cur_data = rspamd_mempool_alloc0 (pool, @@ -125,7 +126,8 @@ read_exceptions_list (rspamd_mempool_t * pool, len, data, (insert_func) exception_insert, - ""); + "", + final); } static void @@ -208,7 +210,8 @@ static gchar * read_redirectors_list (rspamd_mempool_t * pool, gchar * chunk, gint len, - struct map_cb_data *data) + struct map_cb_data *data, + gboolean final) { struct rspamd_redirector_map_cb *cbdata; @@ -229,7 +232,8 @@ read_redirectors_list (rspamd_mempool_t * pool, len, data, (insert_func) redirector_insert, - ""); + "", + final); } void |