]> source.dussan.org Git - rspamd.git/commitdiff
[Project] Css: Properties attachment logic
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 4 Mar 2021 17:35:51 +0000 (17:35 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Thu, 4 Mar 2021 17:35:51 +0000 (17:35 +0000)
src/libserver/css/css_parser.hxx
src/libserver/css/css_property.cxx
src/libserver/css/css_property.hxx
src/libserver/css/css_rule.cxx
src/libserver/css/css_rule.hxx
src/libserver/css/css_tokeniser.hxx
src/libserver/css/css_value.cxx
src/libserver/css/css_value.hxx

index 7530730e7c81357db8ec060d51320f5b8ecffcfc..5b2d93ae585c58a534cdebc855b8686ed3d74b06 100644 (file)
@@ -56,7 +56,18 @@ public:
                std::vector<consumed_block_ptr> args;
 
                css_function_block(css_parser_token &&tok) :
-                       function(std::forward<css_parser_token>(tok)) {}
+                               function(std::forward<css_parser_token>(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<consumed_block_ptr> empty_block_vec{};
 
        auto is_blocks_vec() const -> bool {
-               return (content.index() == 1);
+               return (std::holds_alternative<std::vector<consumed_block_ptr>>(content));
        }
 
        auto get_blocks_or_empty() const -> const std::vector<consumed_block_ptr>& {
@@ -106,7 +117,7 @@ public:
        }
 
        auto is_token() const -> bool {
-               return (content.index() == 2);
+               return (std::holds_alternative<css_parser_token>(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<css_function_block>(content));
+       }
+
+       auto get_function_or_invalid() const -> const css_function_block& {
+               if (is_token()) {
+                       return std::get<css_function_block>(content);
+               }
+
+               return css_function_block::empty_function();
+       }
+
        auto size() const -> std::size_t {
                auto ret = 0;
 
index 77927d7240c8649ab14020ec811be91494575a32..1ef1ae00929030dddb5b51078a0022656cbe73ce 100644 (file)
@@ -20,9 +20,9 @@
 
 namespace rspamd::css {
 
-constexpr const auto max_type = static_cast<int>(css_property_type::PROPERTY_NYI);
-constexpr frozen::unordered_map<frozen::string, css_property_type, max_type> type_map{
+constexpr const auto type_map = frozen::make_unordered_map<frozen::string, css_property_type>({
                {"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<frozen::string, css_property_type, max_type> 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 {
 
index 3d51bf99f57ff741e172dca9be4781d816d1c528..e529a897420bf6c1af1a66de3d536e5a336111c1 100644 (file)
@@ -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;
+       }
 };
 
 
index 572033e1fabfb47a4417aa5c464ba3fbe56759d3..ce35dc6b093da03275f0091238d8a3e2bbe63517 100644 (file)
 
 namespace rspamd::css {
 
+static auto
+allowed_property_value(const css_property &prop, const css_consumed_block &parser_block)
+       -> std::optional<css_value>
+{
+       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<css_value> &&value)
+{
+       values.emplace_back(std::forward<std::unique_ptr<css_value>>(value));
+}
+
+void css_rule::add_value(const css_value &value)
+{
+       values.emplace_back(std::make_unique<css_value>(css_value{value}));
+}
+
 }
\ No newline at end of file
index 929c5b263b6fdaad30a9d0f5105c832a36a9468a..41a6ef3be22f2373d09b78c780f80e1be84ccc39 100644 (file)
@@ -40,12 +40,8 @@ public:
                prop(prop), values(std::forward<css_values_vec>(values)) {}
        explicit css_rule(const css_property &prop) : prop(prop), values{} {}
        /* Methods */
-       void add_value(std::unique_ptr<css_value> &&value) {
-               values.emplace_back(std::forward<std::unique_ptr<css_value>>(value));
-       }
-       void add_value(const css_value &value) {
-               values.emplace_back(std::make_unique<css_value>(css_value{value}));
-       }
+       void add_value(std::unique_ptr<css_value> &&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; }
 };
index 70128e8c8f967844ce8d186b6ff2e6118be7cba7..7f5505f15c057b54c4b1868448efe1281604279f 100644 (file)
@@ -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<std::string_view>(value);
                }
index ac65c7422b306d3ed6ea6c7c21a0c1d05f3efe54..f00543615c3f823d7d2959314b0a3ca43e41eb1a 100644 (file)
@@ -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<css_parser_token> &args)
+auto css_value::maybe_color_from_function(const css_consumed_block::css_function_block &func)
        -> std::optional<css_value>
 {
-       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<decltype(arg)>;
+
+               if constexpr (std::is_same_v<T, css_color>) {
+                       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<T, double>) {
+                       ret += "size: " + std::to_string(arg);
+               }
+               else if constexpr (std::is_integral_v<T>) {
+                       ret += "integral: " + std::to_string(static_cast<int>(arg));
+               }
+               else {
+                       ret += "nyi";
+               }
+       }, value);
+
+       return ret;
+}
+
 }
index 90ee4533d078ad0ea85121d533735d8bc197201e..a8152ed101c3001667fc4df5f57c8f8725491e20 100644 (file)
@@ -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<css_value, css_parse_error>;
 
        static auto maybe_color_from_string(const std::string_view &input)
                -> std::optional<css_value>;
        static auto maybe_color_from_hex(const std::string_view &input)
                -> std::optional<css_value>;
-       static auto maybe_color_from_function(const std::string_view &func,
-                                                                          const std::vector<css_parser_token> &args)
+       static auto maybe_color_from_function(const css_consumed_block::css_function_block &func)
                -> std::optional<css_value>;
 };