commit 7a3c590: [Project] Css: Simplify checks

Vsevolod Stakhov vsevolod at highsecure.ru
Thu Feb 18 16:56:28 UTC 2021


Author: Vsevolod Stakhov
Date: 2021-02-18 16:52:20 +0000
URL: https://github.com/rspamd/rspamd/commit/7a3c590d65b4b9a4092018002e53614e61c63b50 (HEAD -> master)

[Project] Css: Simplify checks

---
 src/libserver/css/css_tokeniser.cxx | 130 ++++++++++++------------------------
 src/libserver/css/css_tokeniser.hxx |   8 ++-
 2 files changed, 49 insertions(+), 89 deletions(-)

diff --git a/src/libserver/css/css_tokeniser.cxx b/src/libserver/css/css_tokeniser.cxx
index be2b4f802..f3a2767bd 100644
--- a/src/libserver/css/css_tokeniser.cxx
+++ b/src/libserver/css/css_tokeniser.cxx
@@ -17,6 +17,8 @@
 #include "css_tokeniser.hxx"
 #include "css_util.hxx"
 #include "css.hxx"
+#include "frozen/unordered_map.h"
+#include "frozen/string.h"
 #include <string>
 
 namespace rspamd::css {
@@ -106,6 +108,40 @@ static constexpr inline auto is_plain_ident(char c) -> bool
 	return false;
 };
 
+struct css_dimension_data {
+	css_parser_token::dim_type dtype;
+	double mult;
+};
+
+/*
+ * Maps from css dimensions to the multipliers that look reasonable in email
+ */
+constexpr const auto max_dims = static_cast<int>(css_parser_token::dim_type::dim_max);
+constexpr frozen::unordered_map<frozen::string, css_dimension_data, max_dims> dimensions_map{
+		{"px", { css_parser_token::dim_type::dim_px, 1.0}},
+		/* EM/REM are 16 px, so multiply and round */
+		{"em", { css_parser_token::dim_type::dim_em, 16.0}},
+		{"rem", { css_parser_token::dim_type::dim_rem, 16.0}},
+		/*
+		 * Represents the x-height of the element's font.
+		 * On fonts with the "x" letter, this is generally the height
+		 * of lowercase letters in the font; 1ex = 0.5em in many fonts.
+		 */
+		{"ex", { css_parser_token::dim_type::dim_ex, 8.0}},
+		{"wv", { css_parser_token::dim_type::dim_wv, 8.0}},
+		{"wh", { css_parser_token::dim_type::dim_wh, 6.0}},
+		{"vmax", { css_parser_token::dim_type::dim_vmax, 8.0}},
+		{"vmin", { css_parser_token::dim_type::dim_vmin, 6.0}},
+		/* One point. 1pt = 1/72nd of 1in */
+		{"pt", { css_parser_token::dim_type::dim_pt, 96.0 / 72.0}},
+		/* 96px/2.54 */
+		{"cm", { css_parser_token::dim_type::dim_cm, 96.0 / 2.54}},
+		{"mm", { css_parser_token::dim_type::dim_mm, 9.60 / 2.54}},
+		{"in", { css_parser_token::dim_type::dim_in, 96.0}},
+		/* 1pc = 12pt = 1/6th of 1in. */
+		{"pc", { css_parser_token::dim_type::dim_pc, 96.0 / 6.0}}
+};
+
 auto
 css_parser_token::adjust_dim(const css_parser_token &dim_token) -> bool
 {
@@ -118,93 +154,13 @@ css_parser_token::adjust_dim(const css_parser_token &dim_token) -> bool
 	auto num = std::get<double>(value);
 	auto sv = std::get<std::string_view>(dim_token.value);
 
-	if (sv == "px") {
-		dim_type = css_parser_token::dim_type::dim_px;
-		flags |= css_parser_token::number_dimension;
-		num = (unsigned)num; /* Round to number */
-	}
-	else if (sv == "em") {
-		dim_type = css_parser_token::dim_type::dim_em;
-		flags |= css_parser_token::number_dimension;
-		/* EM is 16 px, so multiply and round */
-		num = (unsigned)(num * 16.0);
-	}
-	else if (sv == "rem") {
-		/* equal to EM in our case */
-		dim_type = css_parser_token::dim_type::dim_rem;
-		flags |= css_parser_token::number_dimension;
-		num = (unsigned)(num * 16.0);
-	}
-	else if (sv == "ex") {
-		/*
-		 * Represents the x-height of the element's font.
-		 * On fonts with the "x" letter, this is generally the height
-		 * of lowercase letters in the font; 1ex = 0.5em in many fonts.
-		 */
-		dim_type = css_parser_token::dim_type::dim_ex;
-		flags |= css_parser_token::number_dimension;
-		num = (unsigned)(num * 8.0);
-	}
-	else if (sv == "wv") {
-		/*
-		 * Vewport width in percentages:
-		 * we assume 1% of viewport width as 8px
-		 */
-		dim_type = css_parser_token::dim_type::dim_wv;
-		flags |= css_parser_token::number_dimension;
-		num = (unsigned)(num * 8.0);
-	}
-	else if (sv == "wh") {
-		/*
-		 * Vewport height in percentages
-		 * we assume 1% of viewport width as 6px
-		 */
-		dim_type = css_parser_token::dim_type::dim_wh;
-		flags |= css_parser_token::number_dimension;
-		num = (unsigned)(num * 6.0);
-	}
-	else if (sv == "vmax") {
-		/*
-		 * Vewport width in percentages
-		 * we assume 1% of viewport width as 6px
-		 */
-		dim_type = css_parser_token::dim_type::dim_vmax;
-		flags |= css_parser_token::number_dimension;
-		num = (unsigned)(num * 8.0);
-	}
-	else if (sv == "vmin") {
-		/*
-		 * Vewport height in percentages
-		 * we assume 1% of viewport width as 6px
-		 */
-		dim_type = css_parser_token::dim_type::dim_vmin;
-		flags |= css_parser_token::number_dimension;
-		num = (unsigned)(num * 6.0);
-	}
-	else if (sv == "pt") {
-		dim_type = css_parser_token::dim_type::dim_pt;
-		flags |= css_parser_token::number_dimension;
-		num = (num * 96.0 / 72.0); /* One point. 1pt = 1/72nd of 1in */
-	}
-	else if (sv == "cm") {
-		dim_type = css_parser_token::dim_type::dim_cm;
-		flags |= css_parser_token::number_dimension;
-		num = (num * 96.0 / 2.54); /* 96px/2.54 */
-	}
-	else if (sv == "mm") {
-		dim_type = css_parser_token::dim_type::dim_mm;
-		flags |= css_parser_token::number_dimension;
-		num = (num * 9.6 / 2.54); /* 9.6px/2.54 */
-	}
-	else if (sv == "in") {
-		dim_type = css_parser_token::dim_type::dim_in;
-		flags |= css_parser_token::number_dimension;
-		num = (num * 96.0); /* 96px */
-	}
-	else if (sv == "pc") {
-		dim_type = css_parser_token::dim_type::dim_pc;
+	auto dim_found = dimensions_map.find(sv);
+
+	if (dim_found != dimensions_map.end()) {
+		auto dim_elt = dim_found->second;
+		dimension_type = dim_elt.dtype;
 		flags |= css_parser_token::number_dimension;
-		num = (num * 96.0 / 6.0); /* 1pc = 12pt = 1/6th of 1in. */
+		num *= dim_elt.mult;
 	}
 	else {
 		flags |= css_parser_token::flag_bad_dimension;
@@ -838,7 +794,7 @@ auto css_parser_token::debug_token_str() -> std::string
 	}
 
 	if (flags & number_dimension) {
-		ret += "; dim=" + std::to_string(static_cast<int>(dim_type));
+		ret += "; dim=" + std::to_string(static_cast<int>(dimension_type));
 	}
 
 	return ret; /* Copy elision */
diff --git a/src/libserver/css/css_tokeniser.hxx b/src/libserver/css/css_tokeniser.hxx
index b39e8431c..70128e8c8 100644
--- a/src/libserver/css/css_tokeniser.hxx
+++ b/src/libserver/css/css_tokeniser.hxx
@@ -56,7 +56,7 @@ struct css_parser_token {
 	};
 
 	enum class dim_type : std::uint8_t {
-		dim_px,
+		dim_px = 0,
 		dim_em,
 		dim_rem,
 		dim_ex,
@@ -69,6 +69,7 @@ struct css_parser_token {
 		dim_mm,
 		dim_in,
 		dim_pc,
+		dim_max,
 	};
 
 	static const std::uint8_t default_flags = 0;
@@ -85,9 +86,12 @@ struct css_parser_token {
 
 	/* Typed storage */
 	value_type value;
+
+	int lineno;
+
 	token_type type;
 	std::uint8_t flags = default_flags;
-	dim_type dim_type;
+	dim_type dimension_type;
 
 	css_parser_token() = delete;
 	explicit css_parser_token(token_type type, const value_type &value) :


More information about the Commits mailing list