diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-03-14 19:13:44 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2016-03-14 19:13:44 +0000 |
commit | bf6fa98b93bab3e796109e3f0098244cdbab1240 (patch) | |
tree | cb31aa632d7a1d38aac4babd48224267ee112f42 /src/libutil | |
parent | 94bc5d9c0640afca52ddc1472b7aa87be48608ca (diff) | |
download | rspamd-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.c | 112 |
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 ++; |