commit ffc6fac: [Project] Css: Properties attachment logic

Vsevolod Stakhov vsevolod at highsecure.ru
Thu Mar 4 20:42:06 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-03-04 17:35:51 +0000
URL: https://github.com/rspamd/rspamd/commit/ffc6fac92c4b8d10a05e35e59ee17b4f7b642406

[Project] Css: Properties attachment logic

---
 src/libserver/css/css_parser.hxx    | 29 ++++++++++++++--
 src/libserver/css/css_property.cxx  |  6 ++--
 src/libserver/css/css_property.hxx  | 15 +++++++++
 src/libserver/css/css_rule.cxx      | 42 ++++++++++++++++++++++-
 src/libserver/css/css_rule.hxx      |  8 ++---
 src/libserver/css/css_tokeniser.hxx |  3 +-
 src/libserver/css/css_value.cxx     | 67 ++++++++++++++++++++++++++-----------
 src/libserver/css/css_value.hxx     |  5 +--
 8 files changed, 139 insertions(+), 36 deletions(-)

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<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;
 
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<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 {
 
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<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
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<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; }
 };
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<std::string_view>(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<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;
+}
+
 }
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<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>;
 };
 


More information about the Commits mailing list