diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-03-03 21:41:55 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-03-03 21:41:55 +0000 |
commit | 7954b67e2d51a94e47e89767c2382da490973f9f (patch) | |
tree | 3e13f2260e24f0b57e5655e40128c0db572d3b42 /src | |
parent | 25a8f48d565a0450aed3417c88dbeeecdad11532 (diff) | |
download | rspamd-7954b67e2d51a94e47e89767c2382da490973f9f.tar.gz rspamd-7954b67e2d51a94e47e89767c2382da490973f9f.zip |
[Porject] Css: Rework functions parsing
Diffstat (limited to 'src')
-rw-r--r-- | src/libserver/css/css_parser.cxx | 33 | ||||
-rw-r--r-- | src/libserver/css/css_parser.hxx | 22 | ||||
-rw-r--r-- | src/libserver/css/css_tokeniser.cxx | 51 |
3 files changed, 80 insertions, 26 deletions
diff --git a/src/libserver/css/css_parser.cxx b/src/libserver/css/css_parser.cxx index e4a8159f1..014ddf680 100644 --- a/src/libserver/css/css_parser.cxx +++ b/src/libserver/css/css_parser.cxx @@ -27,11 +27,11 @@ namespace rspamd::css { const css_consumed_block css_parser_eof_block{}; auto css_consumed_block::attach_block(consumed_block_ptr &&block) -> bool { - if (content.index() == 0) { + if (std::holds_alternative<std::monostate>(content)) { /* Switch from monostate */ content = std::vector<consumed_block_ptr>(); } - else if (content.index() == 2) { + else if (!std::holds_alternative<std::vector<consumed_block_ptr>>(content)) { /* A single component, cannot attach a block ! */ return false; } @@ -42,6 +42,17 @@ auto css_consumed_block::attach_block(consumed_block_ptr &&block) -> bool { return true; } +auto css_consumed_block::add_function_argument(consumed_block_ptr &&block) -> bool { + if (!std::holds_alternative<css_function_block>(content)) { + return false; + } + + auto &&func_bloc = std::get<css_function_block>(content); + func_bloc.args.push_back(std::move(block)); + + return true; +} + auto css_consumed_block::token_type_str(void) const -> const char * { const auto *ret = ""; @@ -106,6 +117,18 @@ auto css_consumed_block::debug_str(void) -> std::string { /* Empty block */ ret += R"("empty")"; } + else if constexpr (std::is_same_v<T, css_function_block>) { + /* Empty block */ + ret += R"({ "function:" {"name": )"; + ret += "\"" + arg.function.debug_token_str() + "\""; + ret += R"("arguments:" [)"; + for (const auto &block : arg.args) { + ret += "{"; + ret += block->debug_str(); + ret += "}, "; + } + ret += "]}"; + } else { /* Single element block */ ret += "\"" + arg.debug_token_str() + "\""; @@ -214,9 +237,13 @@ auto css_parser::function_consumer(std::unique_ptr<css_consumed_block> &top) -> ret = true; want_more = false; break; + case css_parser_token::token_type::comma_token: + case css_parser_token::token_type::delim_token: + case css_parser_token::token_type::obrace_token: + break; default: /* Attach everything to the function block */ - top->attach_block(std::make_unique<css_consumed_block>( + top->add_function_argument(std::make_unique<css_consumed_block>( css::css_consumed_block::parser_tag_type::css_function_arg, std::move(next_token))); break; diff --git a/src/libserver/css/css_parser.hxx b/src/libserver/css/css_parser.hxx index de982525a..7530730e7 100644 --- a/src/libserver/css/css_parser.hxx +++ b/src/libserver/css/css_parser.hxx @@ -51,6 +51,14 @@ public: }; using consumed_block_ptr = std::unique_ptr<css_consumed_block>; + struct css_function_block { + css_parser_token function; + std::vector<consumed_block_ptr> args; + + css_function_block(css_parser_token &&tok) : + function(std::forward<css_parser_token>(tok)) {} + }; + css_consumed_block() : tag(parser_tag_type::css_eof_block) {} css_consumed_block(parser_tag_type tag) : tag(tag) { if (tag == parser_tag_type::css_top_block || @@ -64,10 +72,19 @@ public: } /* Construct a block from a single lexer token (for trivial blocks) */ explicit css_consumed_block(parser_tag_type tag, css_parser_token &&tok) : - tag(tag), content(std::move(tok)) {} + tag(tag) { + if (tag == parser_tag_type::css_function) { + content = css_function_block{std::move(tok)}; + } + else { + content = std::move(tok); + } + } /* Attach a new block to the compound block, consuming block inside */ auto attach_block(consumed_block_ptr &&block) -> bool; + /* Attach a new argument to the compound function block, consuming block inside */ + auto add_function_argument(consumed_block_ptr &&block) -> bool; auto assign_token(css_parser_token &&tok) -> void { content = std::move(tok); @@ -137,7 +154,8 @@ public: private: std::variant<std::monostate, std::vector<consumed_block_ptr>, - css_parser_token> content; + css_parser_token, + css_function_block> content; }; extern const css_consumed_block css_parser_eof_block; diff --git a/src/libserver/css/css_tokeniser.cxx b/src/libserver/css/css_tokeniser.cxx index f3a2767bd..1d6e89df7 100644 --- a/src/libserver/css/css_tokeniser.cxx +++ b/src/libserver/css/css_tokeniser.cxx @@ -246,34 +246,43 @@ auto css_tokeniser::consume_ident() -> struct css_parser_token auto j = i + 1; while (j < input.size() && g_ascii_isspace(input[j])) { - j ++; + j++; } - if (input[j] == '"' || input[j] == '\'') { - /* Function token */ - return maybe_escape_sv(j + 1, - css_parser_token::token_type::function_token); - } - else { - /* Consume URL token */ - while (j < input.size() && input[j] != ')') { - j ++; - } - - if (input[j] == ')') { - /* Valid url token */ - return maybe_escape_sv(j + 1, - css_parser_token::token_type::url_token); + if (input.size() > 3 && input.substr(0, 3) == "url") { + if (input[j] == '"' || input[j] == '\'') { + /* Function token */ + auto ret = maybe_escape_sv(i, + css_parser_token::token_type::function_token); + return ret; } else { - /* Incomplete url token */ - auto ret = maybe_escape_sv(j, - css_parser_token::token_type::url_token); + /* Consume URL token */ + while (j < input.size() && input[j] != ')') { + j++; + } - ret.flags |= css_parser_token::flag_bad_string; - return ret; + if (input[j] == ')') { + /* Valid url token */ + auto ret = maybe_escape_sv(j + 1, + css_parser_token::token_type::url_token); + return ret; + } + else { + /* Incomplete url token */ + auto ret = maybe_escape_sv(j, + css_parser_token::token_type::url_token); + + ret.flags |= css_parser_token::flag_bad_string; + return ret; + } } } + else { + auto ret = maybe_escape_sv(i, + css_parser_token::token_type::function_token); + return ret; + } } else if (c == '-' && allow_middle_minus) { i++; |