From: Vsevolod Stakhov Date: Thu, 4 Mar 2021 17:35:51 +0000 (+0000) Subject: [Project] Css: Properties attachment logic X-Git-Tag: 3.0~615 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=ffc6fac92c4b8d10a05e35e59ee17b4f7b642406;p=rspamd.git [Project] Css: Properties attachment logic --- diff --git a/src/libserver/css/css_parser.hxx b/src/libserver/css/css_parser.hxx index 7530730e7..5b2d93ae5 100644 --- a/src/libserver/css/css_parser.hxx +++ b/src/libserver/css/css_parser.hxx @@ -56,7 +56,18 @@ public: std::vector args; css_function_block(css_parser_token &&tok) : - function(std::forward(tok)) {} + function(std::forward(tok)) {} + + auto as_string() const -> const std::string_view & { + return function.get_string_or_default(""); + } + + static auto empty_function() -> const css_function_block & { + static const css_function_block invalid( + css_parser_token(css_parser_token::token_type::eof_token, + css_parser_token_placeholder())); + return invalid; + } }; css_consumed_block() : tag(parser_tag_type::css_eof_block) {} @@ -94,7 +105,7 @@ public: const inline static std::vector empty_block_vec{}; auto is_blocks_vec() const -> bool { - return (content.index() == 1); + return (std::holds_alternative>(content)); } auto get_blocks_or_empty() const -> const std::vector& { @@ -106,7 +117,7 @@ public: } auto is_token() const -> bool { - return (content.index() == 2); + return (std::holds_alternative(content)); } auto get_token_or_empty() const -> const css_parser_token& { @@ -117,6 +128,18 @@ public: return css_parser_eof_token(); } + auto is_function() const -> bool { + return (std::holds_alternative(content)); + } + + auto get_function_or_invalid() const -> const css_function_block& { + if (is_token()) { + return std::get(content); + } + + return css_function_block::empty_function(); + } + auto size() const -> std::size_t { auto ret = 0; diff --git a/src/libserver/css/css_property.cxx b/src/libserver/css/css_property.cxx index 77927d724..1ef1ae009 100644 --- a/src/libserver/css/css_property.cxx +++ b/src/libserver/css/css_property.cxx @@ -20,9 +20,9 @@ namespace rspamd::css { -constexpr const auto max_type = static_cast(css_property_type::PROPERTY_NYI); -constexpr frozen::unordered_map type_map{ +constexpr const auto type_map = frozen::make_unordered_map({ {"font", css_property_type::PROPERTY_FONT}, + {"font-color", css_property_type::PROPERTY_FONT_COLOR}, {"color", css_property_type::PROPERTY_COLOR}, {"bgcolor", css_property_type::PROPERTY_BGCOLOR}, {"background", css_property_type::PROPERTY_BACKGROUND}, @@ -30,7 +30,7 @@ constexpr frozen::unordered_map typ {"width", css_property_type::PROPERTY_WIDTH}, {"display", css_property_type::PROPERTY_DISPLAY}, {"visibility", css_property_type::PROPERTY_VISIBILITY}, -}; +}); auto token_string_to_property(const std::string_view &inp) -> css_property_type { diff --git a/src/libserver/css/css_property.hxx b/src/libserver/css/css_property.hxx index 3d51bf99f..e529a8974 100644 --- a/src/libserver/css/css_property.hxx +++ b/src/libserver/css/css_property.hxx @@ -31,6 +31,7 @@ namespace rspamd::css { */ enum class css_property_type { PROPERTY_FONT = 0, + PROPERTY_FONT_COLOR, PROPERTY_COLOR, PROPERTY_BGCOLOR, PROPERTY_BACKGROUND, @@ -53,6 +54,9 @@ struct css_property { case css_property_type::PROPERTY_FONT: ret = "font"; break; + case css_property_type::PROPERTY_FONT_COLOR: + ret = "font-color"; + break; case css_property_type::PROPERTY_COLOR: ret = "color"; break; @@ -80,6 +84,17 @@ struct css_property { return ret; } + + constexpr auto is_color(void) const -> bool { + return type == css_property_type::PROPERTY_COLOR || + type == css_property_type::PROPERTY_BACKGROUND || + type == css_property_type::PROPERTY_BGCOLOR || + type == css_property_type::PROPERTY_FONT_COLOR; + } + constexpr auto is_dimension(void) const -> bool { + return type == css_property_type::PROPERTY_HEIGHT || + type == css_property_type::PROPERTY_WIDTH; + } }; diff --git a/src/libserver/css/css_rule.cxx b/src/libserver/css/css_rule.cxx index 572033e1f..ce35dc6b0 100644 --- a/src/libserver/css/css_rule.cxx +++ b/src/libserver/css/css_rule.cxx @@ -18,6 +18,32 @@ namespace rspamd::css { +static auto +allowed_property_value(const css_property &prop, const css_consumed_block &parser_block) + -> std::optional +{ + if (prop.is_color()) { + if (parser_block.is_token()) { + /* A single token */ + const auto &tok = parser_block.get_token_or_empty(); + + if (tok.type == css_parser_token::token_type::hash_token) { + return css_value::maybe_color_from_hex(tok.get_string_or_default("")); + } + else if (tok.type == css_parser_token::token_type::string_token) { + return css_value::maybe_color_from_string(tok.get_string_or_default("")); + } + } + else if (parser_block.is_function()) { + const auto &func = parser_block.get_function_or_invalid(); + + return css_value::maybe_color_from_function(func); + } + } + + return std::nullopt; +} + auto process_declaration_tokens(rspamd_mempool_t *pool, const blocks_gen_functor &next_block_functor) -> declarations_vec @@ -83,9 +109,12 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, } } - auto maybe_value = css_value::from_css_block(next_tok); + auto maybe_value = allowed_property_value(cur_property, next_tok); if (maybe_value) { + msg_debug_css("added value %s to the property %s", + maybe_value.value().debug_str().c_str(), + cur_property.to_string()); cur_rule->add_value(maybe_value.value()); } } @@ -119,4 +148,15 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, return ret; /* copy elision */ } + +void css_rule::add_value(std::unique_ptr &&value) +{ + values.emplace_back(std::forward>(value)); +} + +void css_rule::add_value(const css_value &value) +{ + values.emplace_back(std::make_unique(css_value{value})); +} + } \ No newline at end of file diff --git a/src/libserver/css/css_rule.hxx b/src/libserver/css/css_rule.hxx index 929c5b263..41a6ef3be 100644 --- a/src/libserver/css/css_rule.hxx +++ b/src/libserver/css/css_rule.hxx @@ -40,12 +40,8 @@ public: prop(prop), values(std::forward(values)) {} explicit css_rule(const css_property &prop) : prop(prop), values{} {} /* Methods */ - void add_value(std::unique_ptr &&value) { - values.emplace_back(std::forward>(value)); - } - void add_value(const css_value &value) { - values.emplace_back(std::make_unique(css_value{value})); - } + void add_value(std::unique_ptr &&value); + void add_value(const css_value &value); constexpr const css_values_vec& get_values(void) const { return values; } constexpr const css_property& get_prop(void) const { return prop; } }; diff --git a/src/libserver/css/css_tokeniser.hxx b/src/libserver/css/css_tokeniser.hxx index 70128e8c8..7f5505f15 100644 --- a/src/libserver/css/css_tokeniser.hxx +++ b/src/libserver/css/css_tokeniser.hxx @@ -99,7 +99,8 @@ struct css_parser_token { css_parser_token(css_parser_token &&other) = default; auto operator=(css_parser_token &&other) -> css_parser_token& = default; auto adjust_dim(const css_parser_token &dim_token) -> bool; - auto get_string_or_default(const std::string_view &def) const -> std::string_view { + + auto get_string_or_default(const std::string_view &def) const -> const std::string_view & { if (value.index() == 0) { return std::get(value); } diff --git a/src/libserver/css/css_value.cxx b/src/libserver/css/css_value.cxx index ac65c7422..f00543615 100644 --- a/src/libserver/css/css_value.cxx +++ b/src/libserver/css/css_value.cxx @@ -240,41 +240,41 @@ static inline auto hsl_to_rgb(double h, double s, double l) return ret; } -auto css_value::maybe_color_from_function(const std::string_view &func, - const std::vector &args) +auto css_value::maybe_color_from_function(const css_consumed_block::css_function_block &func) -> std::optional { - if (func == "rgb" && args.size() == 3) { - css_color col{rgb_color_component_convert(args[0]), - rgb_color_component_convert(args[1]), - rgb_color_component_convert(args[2])}; + + if (func.as_string() == "rgb" && func.args.size() == 3) { + css_color col{rgb_color_component_convert(func.args[0]->get_token_or_empty()), + rgb_color_component_convert(func.args[1]->get_token_or_empty()), + rgb_color_component_convert(func.args[2]->get_token_or_empty())}; return css_value(col); } - else if (func == "rgba" && args.size() == 4) { - css_color col{rgb_color_component_convert(args[0]), - rgb_color_component_convert(args[1]), - rgb_color_component_convert(args[2]), - alpha_component_convert(args[3])}; + else if (func.as_string() == "rgba" && func.args.size() == 4) { + css_color col{rgb_color_component_convert(func.args[0]->get_token_or_empty()), + rgb_color_component_convert(func.args[1]->get_token_or_empty()), + rgb_color_component_convert(func.args[2]->get_token_or_empty()), + alpha_component_convert(func.args[3]->get_token_or_empty())}; return css_value(col); } - else if (func == "hsl" && args.size() == 3) { - auto h = h_component_convert(args[0]); - auto s = sl_component_convert(args[1]); - auto l = sl_component_convert(args[2]); + else if (func.as_string() == "hsl" && func.args.size() == 3) { + auto h = h_component_convert(func.args[0]->get_token_or_empty()); + auto s = sl_component_convert(func.args[1]->get_token_or_empty()); + auto l = sl_component_convert(func.args[2]->get_token_or_empty()); auto col = hsl_to_rgb(h, s, l); return css_value(col); } - else if (func == "hsla" && args.size() == 4) { - auto h = h_component_convert(args[0]); - auto s = sl_component_convert(args[1]); - auto l = sl_component_convert(args[2]); + else if (func.as_string() == "hsla" && func.args.size() == 4) { + auto h = h_component_convert(func.args[0]->get_token_or_empty()); + auto s = sl_component_convert(func.args[1]->get_token_or_empty()); + auto l = sl_component_convert(func.args[2]->get_token_or_empty()); auto col = hsl_to_rgb(h, s, l); - col.alpha = alpha_component_convert(args[3]); + col.alpha = alpha_component_convert(func.args[3]->get_token_or_empty()); return css_value(col); } @@ -282,4 +282,31 @@ auto css_value::maybe_color_from_function(const std::string_view &func, return std::nullopt; } +auto css_value::debug_str() const -> std::string +{ + std::string ret; + + std::visit([&](auto& arg) { + using T = std::decay_t; + + if constexpr (std::is_same_v) { + ret += "color: r=" + std::to_string(arg.r) + + "; g=" + std::to_string(arg.g) + + "; b=" + std::to_string(arg.b) + + "; a=" + std::to_string(arg.alpha); + } + else if constexpr (std::is_same_v) { + ret += "size: " + std::to_string(arg); + } + else if constexpr (std::is_integral_v) { + ret += "integral: " + std::to_string(static_cast(arg)); + } + else { + ret += "nyi"; + } + }, value); + + return ret; +} + } diff --git a/src/libserver/css/css_value.hxx b/src/libserver/css/css_value.hxx index 90ee4533d..a8152ed10 100644 --- a/src/libserver/css/css_value.hxx +++ b/src/libserver/css/css_value.hxx @@ -118,14 +118,15 @@ struct css_value { return (type != css_value_type::CSS_VALUE_NYI); } + auto debug_str() const -> std::string; + static auto from_css_block(const css_consumed_block &bl) -> tl::expected; static auto maybe_color_from_string(const std::string_view &input) -> std::optional; static auto maybe_color_from_hex(const std::string_view &input) -> std::optional; - static auto maybe_color_from_function(const std::string_view &func, - const std::vector &args) + static auto maybe_color_from_function(const css_consumed_block::css_function_block &func) -> std::optional; };