diff options
author | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-02-17 15:56:58 +0000 |
---|---|---|
committer | Vsevolod Stakhov <vsevolod@highsecure.ru> | 2021-02-17 15:56:58 +0000 |
commit | 66f078e7f124c357eae417c01837e25761701128 (patch) | |
tree | 1417c9fecdedea01bb74ce7b977649fe2a433edf /src/libserver/css | |
parent | 61a70903cc1a37c51fda5a80ee5bd0a1c838a1fe (diff) | |
download | rspamd-66f078e7f124c357eae417c01837e25761701128.tar.gz rspamd-66f078e7f124c357eae417c01837e25761701128.zip |
[Project] Css: Start semantic parsing for rules
Diffstat (limited to 'src/libserver/css')
-rw-r--r-- | src/libserver/css/css_parser.cxx | 47 | ||||
-rw-r--r-- | src/libserver/css/css_selector.hxx | 7 |
2 files changed, 51 insertions, 3 deletions
diff --git a/src/libserver/css/css_parser.cxx b/src/libserver/css/css_parser.cxx index 084d1b50a..a0a9d8847 100644 --- a/src/libserver/css/css_parser.cxx +++ b/src/libserver/css/css_parser.cxx @@ -22,6 +22,7 @@ namespace rspamd::css { +struct css_consumed_block; /* * Represents a consumed token by a parser */ @@ -33,7 +34,8 @@ struct css_consumed_block { css_simple_block, css_function, css_function_arg, - css_component + css_component, + css_selector, }; using consumed_block_ptr = std::unique_ptr<css_consumed_block>; @@ -81,6 +83,17 @@ struct css_consumed_block { content = std::move(tok); } + /* Empty blocks used to avoid type checks in loops */ + const inline static std::vector<consumed_block_ptr> empty_block_vec{}; + + auto get_blocks_or_empty() const -> const std::vector<consumed_block_ptr>& { + if (content.index() == 1) { + return std::get<std::vector<consumed_block_ptr>>(content); + } + + return empty_block_vec; + } + auto token_type_str(void) const -> const char * { const auto *ret = ""; @@ -107,6 +120,9 @@ struct css_consumed_block { case parser_tag_type::css_component: ret = "component"; break; + case parser_tag_type::css_selector: + ret = "selector"; + break; } return ret; @@ -570,6 +586,35 @@ bool css_parser::consume_input(const std::string_view &sv) } + const auto &rules = consumed_blocks->get_blocks_or_empty(); + + for (auto &&rule : rules) { + /* + * For now, we do not need any of the at rules, so we can safely ignore them + */ + auto &&children = rule->get_blocks_or_empty(); + + if (children.size() > 1 && + children[0]->tag == css_consumed_block::parser_tag_type::css_component) { + auto simple_block = std::find_if(children.begin(), children.end(), + [](auto &bl) { + return bl->tag == css_consumed_block::parser_tag_type::css_simple_block; + }); + + if (simple_block != children.end()) { + /* + * We have a component and a simple block, + * so we can parse a declaration + */ + + /* First, tag all components as preamble */ + for (auto it = children.begin(); it != simple_block; ++it) { + (*it)->tag = css_consumed_block::parser_tag_type::css_selector; + } + } + } + } + auto debug_str = consumed_blocks->debug_str(); msg_debug_css("consumed css: {%*s}", (int)debug_str.size(), debug_str.data()); diff --git a/src/libserver/css/css_selector.hxx b/src/libserver/css/css_selector.hxx index c9f3046d5..8611630fd 100644 --- a/src/libserver/css/css_selector.hxx +++ b/src/libserver/css/css_selector.hxx @@ -24,6 +24,7 @@ #include <optional> #include "contrib/expected/expected.hpp" #include "parse_error.hxx" +#include "css_tokeniser.hxx" #include "html_tags.h" namespace rspamd::css { @@ -41,14 +42,14 @@ struct css_selector { selector_type type; std::variant<tag_id_t, std::string> value; - constexpr std::optional<tag_id_t> to_tag (void) const { + auto to_tag(void) const -> std::optional<tag_id_t> { if (type == selector_type::SELECTOR_ELEMENT) { return std::get<tag_id_t>(value); } return std::nullopt; } - constexpr std::optional<const std::string_view> to_string (void) const { + auto to_string(void) const -> std::optional<const std::string_view> { if (type == selector_type::SELECTOR_ELEMENT) { return std::string_view(std::get<std::string>(value)); } @@ -59,6 +60,8 @@ struct css_selector { size_t inlen); }; + + } #endif //RSPAMD_CSS_SELECTOR_HXX |