commit fdb004b: [Project] Css: Rework flags of css properties

Vsevolod Stakhov vsevolod at highsecure.ru
Fri Mar 5 21:14:30 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-03-05 21:11:48 +0000
URL: https://github.com/rspamd/rspamd/commit/fdb004b9ce1a64552421ce5dcf1a0da4796f08c5 (HEAD -> master)

[Project] Css: Rework flags of css properties

---
 src/libserver/css/css_parser.hxx    |  2 +-
 src/libserver/css/css_property.cxx  |  9 ++++++---
 src/libserver/css/css_property.hxx  | 12 ++++++++++--
 src/libserver/css/css_rule.cxx      | 36 ++++++++++++++++++++++++++++++++++--
 src/libserver/css/css_tokeniser.hxx |  7 +++++--
 src/libserver/css/css_value.hxx     | 18 ------------------
 test/lua/unit/css.lua               |  4 ++--
 7 files changed, 58 insertions(+), 30 deletions(-)

diff --git a/src/libserver/css/css_parser.hxx b/src/libserver/css/css_parser.hxx
index 887d846ad..d0c378b0f 100644
--- a/src/libserver/css/css_parser.hxx
+++ b/src/libserver/css/css_parser.hxx
@@ -58,7 +58,7 @@ public:
 		css_function_block(css_parser_token &&tok) :
 				function(std::forward<css_parser_token>(tok)) {}
 
-		auto as_string() const -> const std::string_view & {
+		auto as_string() const -> std::string_view {
 			return function.get_string_or_default("");
 		}
 
diff --git a/src/libserver/css/css_property.cxx b/src/libserver/css/css_property.cxx
index 1ef1ae009..b2578a367 100644
--- a/src/libserver/css/css_property.cxx
+++ b/src/libserver/css/css_property.cxx
@@ -32,7 +32,9 @@ constexpr const auto type_map = frozen::make_unordered_map<frozen::string, css_p
 		{"visibility", css_property_type::PROPERTY_VISIBILITY},
 });
 
-auto token_string_to_property(const std::string_view &inp) -> css_property_type {
+auto token_string_to_property(const std::string_view &inp)
+	-> css_property_type
+{
 
 	css_property_type ret = css_property_type::PROPERTY_NYI;
 
@@ -45,12 +47,13 @@ auto token_string_to_property(const std::string_view &inp) -> css_property_type
 	return ret;
 }
 
-auto css_property::from_token(const css_parser_token &tok) -> tl::expected<css_property,css_parse_error>
+auto css_property::from_token(const css_parser_token &tok)
+	-> tl::expected<css_property,css_parse_error>
 {
 	if (tok.type == css_parser_token::token_type::ident_token) {
 		auto sv = tok.get_string_or_default("");
 
-		return css_property{token_string_to_property(sv)};
+		return css_property{token_string_to_property(sv), css_property_flag::FLAG_NORMAL};
 	}
 
 	return tl::unexpected{css_parse_error(css_parse_error_type::PARSE_ERROR_NYI)};
diff --git a/src/libserver/css/css_property.hxx b/src/libserver/css/css_property.hxx
index e529a8974..670dfaddb 100644
--- a/src/libserver/css/css_property.hxx
+++ b/src/libserver/css/css_property.hxx
@@ -29,7 +29,7 @@ namespace rspamd::css {
  * To be extended with properties that are interesting from the email
  * point of view
  */
-enum class css_property_type {
+enum class css_property_type : std::uint16_t {
 	PROPERTY_FONT = 0,
 	PROPERTY_FONT_COLOR,
 	PROPERTY_COLOR,
@@ -42,8 +42,16 @@ enum class css_property_type {
 	PROPERTY_NYI,
 };
 
-struct css_property {
+enum class css_property_flag : std::uint16_t {
+	FLAG_NORMAL,
+	FLAG_IMPORTANT,
+	FLAG_NOT_IMPORTANT
+};
+
+struct alignas(int) css_property {
 	css_property_type type;
+	css_property_flag flag;
+
 	static tl::expected<css_property,css_parse_error> from_token(
 			const css_parser_token &tok);
 
diff --git a/src/libserver/css/css_rule.cxx b/src/libserver/css/css_rule.cxx
index 0e9924029..5bd99bd0e 100644
--- a/src/libserver/css/css_rule.cxx
+++ b/src/libserver/css/css_rule.cxx
@@ -50,8 +50,10 @@ auto process_declaration_tokens(rspamd_mempool_t *pool,
 {
 	declarations_vec ret;
 	bool can_continue = true;
-	css_property cur_property{css_property_type::PROPERTY_NYI};
-	static const css_property bad_property{css_property_type::PROPERTY_NYI};
+	css_property cur_property{css_property_type::PROPERTY_NYI,
+							  css_property_flag::FLAG_NORMAL};
+	static const css_property bad_property{css_property_type::PROPERTY_NYI,
+										   css_property_flag::FLAG_NORMAL};
 	std::unique_ptr<css_rule> cur_rule;
 
 	enum {
@@ -60,6 +62,8 @@ auto process_declaration_tokens(rspamd_mempool_t *pool,
 		ignore_value, /* For unknown properties */
 	} state = parse_property;
 
+	auto seen_not = false;
+
 	while (can_continue) {
 		const auto &next_tok = next_block_functor();
 
@@ -105,8 +109,36 @@ auto process_declaration_tokens(rspamd_mempool_t *pool,
 					if (parser_tok.type == css_parser_token::token_type::semicolon_token) {
 						ret.push_back(std::move(cur_rule));
 						state = parse_property;
+						seen_not = false;
 						continue;
 					}
+					else if (parser_tok.type == css_parser_token::token_type::delim_token) {
+						if (parser_tok.get_string_or_default("") == "!") {
+							/* Probably something like !important */
+							seen_not = true;
+						}
+					}
+					else if (parser_tok.type == css_parser_token::token_type::ident_token) {
+						if (parser_tok.get_string_or_default("") == "important") {
+							if (seen_not) {
+								msg_debug_css("add !important flag to property %s",
+										cur_property.to_string());
+								cur_property.flag = css_property_flag::FLAG_NOT_IMPORTANT;
+							}
+							else {
+								msg_debug_css("add important flag to property %s",
+										cur_property.to_string());
+								cur_property.flag = css_property_flag::FLAG_IMPORTANT;
+							}
+
+							seen_not = false;
+
+							continue;
+						}
+						else {
+							seen_not = false;
+						}
+					}
 				}
 
 				auto maybe_value = allowed_property_value(cur_property, next_tok);
diff --git a/src/libserver/css/css_tokeniser.hxx b/src/libserver/css/css_tokeniser.hxx
index 7f5505f15..3776b36e5 100644
--- a/src/libserver/css/css_tokeniser.hxx
+++ b/src/libserver/css/css_tokeniser.hxx
@@ -100,10 +100,13 @@ struct css_parser_token {
 	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 -> const std::string_view & {
-		if (value.index() == 0) {
+	auto get_string_or_default(const std::string_view &def) const -> std::string_view {
+		if (std::holds_alternative<std::string_view>(value)) {
 			return std::get<std::string_view>(value);
 		}
+		else if (std::holds_alternative<char>(value)) {
+			return std::string_view(&std::get<char>(value), 1);
+		}
 
 		return def;
 	}
diff --git a/src/libserver/css/css_value.hxx b/src/libserver/css/css_value.hxx
index 5f9fa0cee..0e675e0ca 100644
--- a/src/libserver/css/css_value.hxx
+++ b/src/libserver/css/css_value.hxx
@@ -49,15 +49,6 @@ enum class css_display_value {
 	DISPLAY_HIDDEN
 };
 
-/*
- * CSS flags
- */
-enum class css_flag_value {
-	FLAG_INHERIT,
-	FLAG_IMPORTANT,
-	FLAG_NOTIMPORTANT
-};
-
 /*
  * Value handler, uses std::variant instead of polymorphic classes for now
  * for simplicity
@@ -74,7 +65,6 @@ struct css_value {
 	std::variant<css_color,
 			double,
 			css_display_value,
-			css_flag_value,
 			std::monostate> value;
 
 	css_value(const css_color &color) :
@@ -106,14 +96,6 @@ struct css_value {
 		return std::nullopt;
 	}
 
-	constexpr std::optional<css_flag_value> to_flag(void) const {
-		if (type == css_value_type::CSS_VALUE_FLAG) {
-			return std::get<css_flag_value>(value);
-		}
-
-		return std::nullopt;
-	}
-
 	constexpr bool is_valid(void) const {
 		return (type != css_value_type::CSS_VALUE_NYI);
 	}
diff --git a/test/lua/unit/css.lua b/test/lua/unit/css.lua
index 4bd78b244..86119641e 100644
--- a/test/lua/unit/css.lua
+++ b/test/lua/unit/css.lua
@@ -100,8 +100,8 @@ body {
 ]],
 [[
 /* Colors */
-* { color: hsl(0, 100%, 50%) }   /* red */
-* { color: hsl(120, 100%, 50%) } /* lime */
+* { color: hsl(0, 100%, 50%) !important }   /* red */
+* { color: hsl(120, 100%, 50%) important } /* 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 */


More information about the Commits mailing list