From 7954b67e2d51a94e47e89767c2382da490973f9f Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Wed, 3 Mar 2021 21:41:55 +0000 Subject: [PATCH] [Porject] Css: Rework functions parsing --- src/libserver/css/css_parser.cxx | 33 +++++++++++++++++-- src/libserver/css/css_parser.hxx | 22 +++++++++++-- src/libserver/css/css_tokeniser.cxx | 51 +++++++++++++++++------------ test/lua/unit/css.lua | 25 ++++++++++++++ 4 files changed, 105 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(content)) { /* Switch from monostate */ content = std::vector(); } - else if (content.index() == 2) { + else if (!std::holds_alternative>(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(content)) { + return false; + } + + auto &&func_bloc = std::get(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) { + /* 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 &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( + top->add_function_argument(std::make_unique( 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; + struct css_function_block { + css_parser_token function; + std::vector args; + + css_function_block(css_parser_token &&tok) : + function(std::forward(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, - 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++; diff --git a/test/lua/unit/css.lua b/test/lua/unit/css.lua index a5a8f533f..4bd78b244 100644 --- a/test/lua/unit/css.lua +++ b/test/lua/unit/css.lua @@ -97,6 +97,31 @@ body { width: 100%; } } +]], +[[ +/* Colors */ +* { color: hsl(0, 100%, 50%) } /* red */ +* { color: hsl(120, 100%, 50%) } /* lime */ +* { color: hsl(120, 100%, 25%) } /* dark green */ +* { color: hsl(120, 100%, 75%) } /* light green */ +* { color: hsl(120, 75%, 75%) } /* pastel green, and so on */ +em { color: #f00 } /* #rgb */ +em { color: #ff0000 } /* #rrggbb */ +em { color: rgb(255,0,0) } +em { color: rgb(100%, 0%, 0%) } +body {color: black; background: white } +h1 { color: maroon } +h2 { color: olive } +em { color: rgb(255,0,0) } /* integer range 0 - 255 */ +em { color: rgb(300,0,0) } /* clipped to rgb(255,0,0) */ +em { color: rgb(255,-10,0) } /* clipped to rgb(255,0,0) */ +em { color: rgb(110%, 0%, 0%) } /* clipped to rgb(100%,0%,0%) */ +em { color: rgb(255,0,0) } /* integer range 0 - 255 */ +em { color: rgba(255,0,0,1) /* the same, with explicit opacity of 1 */ +em { color: rgb(100%,0%,0%) } /* float range 0.0% - 100.0% */ +em { color: rgba(100%,0%,0%,1) } /* the same, with explicit opacity of 1 */ +p { color: rgba(0,0,255,0.5) } /* semi-transparent solid blue */ +p { color: rgba(100%, 50%, 0%, 0.1) } /* very transparent solid orange */ ]] } local NULL = ffi.new 'void*' -- 2.39.5