diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-06-10 15:15:45 +0100 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-06-11 15:09:10 +0100 |
commit | 9b2fb6ce7e647bdf719c6598098ecd0f112cb016 (patch) | |
tree | 73b7a3d970167e9a89d6b69eaca56111e8c39085 /src/libserver/css | |
parent | b74798de84b52b960cdf98562a62461363da291e (diff) | |
download | rspamd-9b2fb6ce7e647bdf719c6598098ecd0f112cb016.tar.gz rspamd-9b2fb6ce7e647bdf719c6598098ecd0f112cb016.zip |
[Project] Html/CSS: Add transform from a CSS rule to html block
Diffstat (limited to 'src/libserver/css')
-rw-r--r-- | src/libserver/css/css_rule.cxx | 119 | ||||
-rw-r--r-- | src/libserver/css/css_rule.hxx | 12 | ||||
-rw-r--r-- | src/libserver/css/css_tokeniser.cxx | 6 | ||||
-rw-r--r-- | src/libserver/css/css_tokeniser.hxx | 14 | ||||
-rw-r--r-- | src/libserver/css/css_value.cxx | 10 |
5 files changed, 144 insertions, 17 deletions
diff --git a/src/libserver/css/css_rule.cxx b/src/libserver/css/css_rule.cxx index 2e84aaa1c..d06f0aec0 100644 --- a/src/libserver/css/css_rule.cxx +++ b/src/libserver/css/css_rule.cxx @@ -16,6 +16,7 @@ #include "css_rule.hxx" #include "css.hxx" +#include "libserver/html/html_block.hxx" #include <limits> #define DOCTEST_CONFIG_IMPLEMENTATION_IN_DLL @@ -349,10 +350,11 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, } auto -css_declarations_block::merge_block(const css_declarations_block &other, merge_type how) --> void { +css_declarations_block::merge_block(const css_declarations_block &other, merge_type how) -> void +{ const auto &other_rules = other.get_rules(); + for (auto &rule : other_rules) { auto &&found_it = rules.find(rule); @@ -379,6 +381,119 @@ css_declarations_block::merge_block(const css_declarations_block &other, merge_t } } +auto +css_declarations_block::compile_to_block(rspamd_mempool_t *pool) const -> rspamd::html::html_block * +{ + auto *block = rspamd_mempool_alloc0_type(pool, rspamd::html::html_block); + auto opacity = -1; + const css_rule *font_rule = nullptr, *background_rule = nullptr; + + for (const auto &rule : rules) { + auto prop = rule->get_prop().type; + const auto &vals = rule->get_values(); + + if (vals.empty()) { + continue; + } + + switch (prop) { + case css_property_type::PROPERTY_VISIBILITY: + case css_property_type::PROPERTY_DISPLAY: { + auto disp = vals.back().to_display().value_or(css_display_value::DISPLAY_NORMAL); + block->set_display(disp); + break; + } + case css_property_type::PROPERTY_FONT_SIZE: { + auto fs = vals.back().to_dimension(); + if (fs) { + block->set_font_size(fs.value().dim, fs.value().is_percent); + } + } + case css_property_type::PROPERTY_OPACITY: { + opacity = vals.back().to_number().value_or(opacity); + break; + } + case css_property_type::PROPERTY_FONT_COLOR: { + auto color = vals.back().to_color(); + if (color) { + block->set_fgcolor(color.value()); + } + break; + } + case css_property_type::PROPERTY_BGCOLOR: { + auto color = vals.back().to_color(); + if (color) { + block->set_bgcolor(color.value()); + } + break; + } + case css_property_type::PROPERTY_HEIGHT: { + auto w = vals.back().to_dimension(); + if (w) { + block->set_width(w.value().dim, w.value().is_percent); + } + break; + } + case css_property_type::PROPERTY_WIDTH: { + auto h = vals.back().to_dimension(); + if (h) { + block->set_width(h.value().dim, h.value().is_percent); + } + break; + } + /* Optional attributes */ + case css_property_type::PROPERTY_FONT: + font_rule = rule.get(); + break; + case css_property_type::PROPERTY_BACKGROUND: + background_rule = rule.get(); + break; + default: + /* Do nothing for now */ + break; + } + } + + /* Optional properties */ + if (!(block->mask & rspamd::html::html_block::fg_color_mask) && font_rule) { + auto &vals = font_rule->get_values(); + + for (const auto &val : vals) { + auto maybe_color = val.to_color(); + + if (maybe_color) { + block->set_fgcolor(maybe_color.value()); + } + } + } + + if (!(block->mask & rspamd::html::html_block::font_size_mask) && font_rule) { + auto &vals = font_rule->get_values(); + + for (const auto &val : vals) { + auto maybe_dim = val.to_dimension(); + + if (maybe_dim) { + block->set_font_size(maybe_dim.value().dim, maybe_dim.value().is_percent); + } + } + } + + if (!(block->mask & rspamd::html::html_block::bg_color_mask) && background_rule) { + auto &vals = background_rule->get_values(); + + for (const auto &val : vals) { + auto maybe_color = val.to_color(); + + if (maybe_color) { + block->set_bgcolor(maybe_color.value()); + } + } + } + + return block; +} + void css_rule::add_value(const css_value &value) { values.push_back(value); diff --git a/src/libserver/css/css_rule.hxx b/src/libserver/css/css_rule.hxx index 3353382e7..b29bf298f 100644 --- a/src/libserver/css/css_rule.hxx +++ b/src/libserver/css/css_rule.hxx @@ -26,6 +26,11 @@ #include <vector> #include <memory> +namespace rspamd::html { +/* Forward declaration */ +struct html_block; +} + namespace rspamd::css { class css_rule { @@ -107,6 +112,13 @@ public: return (rules.find(css_rule{prop}) != rules.end()); } + /** + * Compile CSS declaration to the html block + * @param pool used to carry memory requred for html_block + * @return html block structure + */ + auto compile_to_block(rspamd_mempool_t *pool) const -> rspamd::html::html_block *; + private: robin_hood::unordered_flat_set<rule_shared_ptr, rule_shared_hash, rule_shared_eq> rules; }; diff --git a/src/libserver/css/css_tokeniser.cxx b/src/libserver/css/css_tokeniser.cxx index 0b1467d8f..f31fdc009 100644 --- a/src/libserver/css/css_tokeniser.cxx +++ b/src/libserver/css/css_tokeniser.cxx @@ -75,7 +75,7 @@ auto make_token<css_parser_token::token_type::delim_token, char>(const char &c) } template<> -auto make_token<css_parser_token::token_type::number_token, double>(const double &d) +auto make_token<css_parser_token::token_type::number_token, float>(const float &d) -> css_parser_token { return css_parser_token{css_parser_token::token_type::number_token, d}; @@ -145,13 +145,13 @@ constexpr frozen::unordered_map<frozen::string, css_dimension_data, max_dims> di auto css_parser_token::adjust_dim(const css_parser_token &dim_token) -> bool { - if (!std::holds_alternative<double>(value) || + if (!std::holds_alternative<float>(value) || !std::holds_alternative<std::string_view>(dim_token.value)) { /* Invalid tokens */ return false; } - auto num = std::get<double>(value); + auto num = std::get<float>(value); auto sv = std::get<std::string_view>(dim_token.value); auto dim_found = dimensions_map.find(sv); diff --git a/src/libserver/css/css_tokeniser.hxx b/src/libserver/css/css_tokeniser.hxx index a45e56f3f..021284989 100644 --- a/src/libserver/css/css_tokeniser.hxx +++ b/src/libserver/css/css_tokeniser.hxx @@ -80,7 +80,7 @@ struct css_parser_token { using value_type = std::variant<std::string_view, /* For strings and string like tokens */ char, /* For delimiters (might need to move to unicode point) */ - double, /* For numeric stuff */ + float, /* For numeric stuff */ css_parser_token_placeholder /* For general no token stuff */ >; @@ -119,9 +119,9 @@ struct css_parser_token { return (char)-1; } - auto get_number_or_default(double def) const -> double { - if (std::holds_alternative<double>(value)) { - auto dbl = std::get<double>(value); + auto get_number_or_default(float def) const -> float { + if (std::holds_alternative<float>(value)) { + auto dbl = std::get<float>(value); if (flags & css_parser_token::number_percent) { dbl /= 100.0; @@ -133,9 +133,9 @@ struct css_parser_token { return def; } - auto get_normal_number_or_default(double def) const -> double { - if (std::holds_alternative<double>(value)) { - auto dbl = std::get<double>(value); + auto get_normal_number_or_default(float def) const -> float { + if (std::holds_alternative<float>(value)) { + auto dbl = std::get<float>(value); if (flags & css_parser_token::number_percent) { dbl /= 100.0; diff --git a/src/libserver/css/css_value.cxx b/src/libserver/css/css_value.cxx index 9f1f4dd7f..f573e38be 100644 --- a/src/libserver/css/css_value.cxx +++ b/src/libserver/css/css_value.cxx @@ -98,7 +98,7 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token std::uint8_t ret = 0; if (tok.type == css_parser_token::token_type::number_token) { - auto dbl = std::get<double>(tok.value); + auto dbl = std::get<float>(tok.value); if (tok.flags & css_parser_token::number_percent) { if (dbl > 100) { @@ -129,7 +129,7 @@ constexpr static inline auto alpha_component_convert(const css_parser_token &tok double ret = 1.0; if (tok.type == css_parser_token::token_type::number_token) { - auto dbl = std::get<double>(tok.value); + auto dbl = std::get<float>(tok.value); if (tok.flags & css_parser_token::number_percent) { if (dbl > 100) { @@ -160,7 +160,7 @@ constexpr static inline auto h_component_convert(const css_parser_token &tok) double ret = 0.0; if (tok.type == css_parser_token::token_type::number_token) { - auto dbl = std::get<double>(tok.value); + auto dbl = std::get<float>(tok.value); if (tok.flags & css_parser_token::number_percent) { if (dbl > 100) { @@ -276,8 +276,8 @@ auto css_value::maybe_color_from_function(const css_consumed_block::css_function auto css_value::maybe_dimension_from_number(const css_parser_token &tok) -> std::optional<css_value> { - if (std::holds_alternative<double>(tok.value)) { - auto dbl = std::get<double>(tok.value); + if (std::holds_alternative<float>(tok.value)) { + auto dbl = std::get<float>(tok.value); css_dimension dim; dim.dim = dbl; |