aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2016-03-14 19:13:44 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2016-03-14 19:13:44 +0000
commitbf6fa98b93bab3e796109e3f0098244cdbab1240 (patch)
treecb31aa632d7a1d38aac4babd48224267ee112f42 /src/libutil
parent94bc5d9c0640afca52ddc1472b7aa87be48608ca (diff)
downloadrspamd-bf6fa98b93bab3e796109e3f0098244cdbab1240.tar.gz
rspamd-bf6fa98b93bab3e796109e3f0098244cdbab1240.zip
[Feature] Allow quoted and slashed keys in maps
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/map.c112
1 files changed, 108 insertions, 4 deletions
diff --git a/src/libutil/map.c b/src/libutil/map.c
index e7a34314e..ac6d58997 100644
--- a/src/libutil/map.c
+++ b/src/libutil/map.c
@@ -989,8 +989,10 @@ rspamd_parse_kv_list (rspamd_mempool_t * pool,
map_read_key_quoted,
map_read_key_slashed,
map_skip_spaces_after_key,
+ map_backslash_quoted,
+ map_backslash_slashed,
+ map_read_key_after_slash,
map_read_value,
- map_read_value_quoted,
map_read_comment_start,
map_skip_comment,
map_read_eol,
@@ -1009,8 +1011,21 @@ rspamd_parse_kv_list (rspamd_mempool_t * pool,
p ++;
}
else {
- c = p;
- data->state = map_read_key;
+ if (*p == '"') {
+ p++;
+ c = p;
+ data->state = map_read_key_quoted;
+ }
+ else if (*p == '/') {
+ /* Note that c is on '/' here as '/' is a part of key */
+ c = p;
+ p++;
+ data->state = map_read_key_slashed;
+ }
+ else {
+ c = p;
+ data->state = map_read_key;
+ }
}
break;
case map_read_key:
@@ -1023,6 +1038,87 @@ rspamd_parse_kv_list (rspamd_mempool_t * pool,
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_KEY;
+ func (data->cur_data, key, default_value);
+ msg_debug_pool ("insert key only pair: %s -> %s",
+ key, default_value);
+ }
+
+ data->state = map_read_eol;
+ key = NULL;
+ }
+ else if (g_ascii_isspace (*p)) {
+ if (p - c > 0) {
+ MAP_STORE_KEY;
+ data->state = map_skip_spaces_after_key;
+ }
+ else {
+ /* Should not happen */
+ g_assert_not_reached ();
+ }
+ }
+ else {
+ p++;
+ }
+ break;
+ case map_read_key_quoted:
+ if (*p == '\\') {
+ data->state = map_backslash_quoted;
+ p ++;
+ }
+ else if (*p == '"') {
+ /* Allow empty keys in this case */
+ if (p - c >= 0) {
+ MAP_STORE_KEY;
+ data->state = map_skip_spaces_after_key;
+ }
+ else {
+ g_assert_not_reached ();
+ }
+ p ++;
+ }
+ else {
+ p ++;
+ }
+ break;
+ case map_read_key_slashed:
+ if (*p == '\\') {
+ data->state = map_backslash_slashed;
+ p ++;
+ }
+ else if (*p == '/') {
+ /* Allow empty keys in this case */
+ if (p - c >= 0) {
+ data->state = map_read_key_after_slash;
+ }
+ else {
+ g_assert_not_reached ();
+ }
+ }
+ else {
+ p ++;
+ }
+ break;
+ case map_read_key_after_slash:
+ /*
+ * This state is equal to reading of key but '/' is not
+ * treated specially
+ */
+ if (*p == '#') {
+ 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;
}
@@ -1052,9 +1148,17 @@ rspamd_parse_kv_list (rspamd_mempool_t * pool,
}
}
else {
- p++;
+ p ++;
}
break;
+ case map_backslash_quoted:
+ p ++;
+ data->state = map_read_key_quoted;
+ break;
+ case map_backslash_slashed:
+ p ++;
+ data->state = map_read_key_slashed;
+ break;
case map_skip_spaces_after_key:
if (g_ascii_isspace (*p)) {
p ++;