diff options
Diffstat (limited to 'src/libserver/css/css_selector.hxx')
-rw-r--r-- | src/libserver/css/css_selector.hxx | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/libserver/css/css_selector.hxx b/src/libserver/css/css_selector.hxx new file mode 100644 index 0000000..65b185a --- /dev/null +++ b/src/libserver/css/css_selector.hxx @@ -0,0 +1,134 @@ +/*- + * Copyright 2021 Vsevolod Stakhov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#ifndef RSPAMD_CSS_SELECTOR_HXX +#define RSPAMD_CSS_SELECTOR_HXX + +#include <variant> +#include <string> +#include <optional> +#include <vector> +#include <memory> + +#include "function2/function2.hpp" +#include "parse_error.hxx" +#include "css_parser.hxx" +#include "libserver/html/html_tags.h" +#include "libcryptobox/cryptobox.h" + +namespace rspamd::css { + +/* + * Holds a value for css selector, internal is handled by variant + */ +struct css_selector { + enum class selector_type { + SELECTOR_TAG, /* e.g. tr, for this value we use tag_id_t */ + SELECTOR_CLASS, /* generic class, e.g. .class */ + SELECTOR_ID, /* e.g. #id */ + SELECTOR_ALL /* * selector */ + }; + + selector_type type; + std::variant<tag_id_t, std::string_view> value; + + /* Conditions for the css selector */ + /* Dependency on attributes */ + struct css_attribute_condition { + std::string_view attribute; + std::string_view op = ""; + std::string_view value = ""; + }; + + /* General dependency chain */ + using css_selector_ptr = std::unique_ptr<css_selector>; + using css_selector_dep = std::variant<css_attribute_condition, css_selector_ptr>; + std::vector<css_selector_dep> dependencies; + + auto to_tag(void) const -> std::optional<tag_id_t> + { + if (type == selector_type::SELECTOR_TAG) { + return std::get<tag_id_t>(value); + } + return std::nullopt; + } + + auto to_string(void) const -> std::optional<const std::string_view> + { + if (type != selector_type::SELECTOR_TAG) { + return std::string_view(std::get<std::string_view>(value)); + } + return std::nullopt; + }; + + explicit css_selector(selector_type t) + : type(t) + { + } + explicit css_selector(tag_id_t t) + : type(selector_type::SELECTOR_TAG) + { + value = t; + } + explicit css_selector(const std::string_view &st, selector_type t = selector_type::SELECTOR_ID) + : type(t) + { + value = st; + } + + auto operator==(const css_selector &other) const -> bool + { + return type == other.type && value == other.value; + } + + auto debug_str(void) const -> std::string; +}; + + +using selectors_vec = std::vector<std::unique_ptr<css_selector>>; + +/* + * Consume selectors token and split them to the list of selectors + */ +auto process_selector_tokens(rspamd_mempool_t *pool, + blocks_gen_functor &&next_token_functor) + -> selectors_vec; + +}// namespace rspamd::css + +/* Selectors hashing */ +namespace std { +template<> +class hash<rspamd::css::css_selector> { +public: + using is_avalanching = void; + auto operator()(const rspamd::css::css_selector &sel) const -> std::size_t + { + if (sel.type == rspamd::css::css_selector::selector_type::SELECTOR_TAG) { + return static_cast<std::size_t>(std::get<tag_id_t>(sel.value)); + } + else { + const auto &sv = std::get<std::string_view>(sel.value); + + return rspamd_cryptobox_fast_hash(sv.data(), sv.size(), 0xdeadbabe); + } + } +}; +}// namespace std + +#endif//RSPAMD_CSS_SELECTOR_HXX |