aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2021-02-17 15:56:58 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2021-02-17 15:56:58 +0000
commit66f078e7f124c357eae417c01837e25761701128 (patch)
tree1417c9fecdedea01bb74ce7b977649fe2a433edf /src
parent61a70903cc1a37c51fda5a80ee5bd0a1c838a1fe (diff)
downloadrspamd-66f078e7f124c357eae417c01837e25761701128.tar.gz
rspamd-66f078e7f124c357eae417c01837e25761701128.zip
[Project] Css: Start semantic parsing for rules
Diffstat (limited to 'src')
-rw-r--r--src/libserver/css/css_parser.cxx47
-rw-r--r--src/libserver/css/css_selector.hxx7
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