summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2021-03-03 21:41:55 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2021-03-03 21:41:55 +0000
commit7954b67e2d51a94e47e89767c2382da490973f9f (patch)
tree3e13f2260e24f0b57e5655e40128c0db572d3b42
parent25a8f48d565a0450aed3417c88dbeeecdad11532 (diff)
downloadrspamd-7954b67e2d51a94e47e89767c2382da490973f9f.tar.gz
rspamd-7954b67e2d51a94e47e89767c2382da490973f9f.zip
[Porject] Css: Rework functions parsing
-rw-r--r--src/libserver/css/css_parser.cxx33
-rw-r--r--src/libserver/css/css_parser.hxx22
-rw-r--r--src/libserver/css/css_tokeniser.cxx51
-rw-r--r--test/lua/unit/css.lua25
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<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++;
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*'