summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2021-03-03 21:41:55 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2021-03-03 21:41:55 +0000
commit7954b67e2d51a94e47e89767c2382da490973f9f (patch)
tree3e13f2260e24f0b57e5655e40128c0db572d3b42 /src
parent25a8f48d565a0450aed3417c88dbeeecdad11532 (diff)
downloadrspamd-7954b67e2d51a94e47e89767c2382da490973f9f.tar.gz
rspamd-7954b67e2d51a94e47e89767c2382da490973f9f.zip
[Porject] Css: Rework functions parsing
Diffstat (limited to 'src')
-rw-r--r--src/libserver/css/css_parser.cxx33
-rw-r--r--src/libserver/css/css_parser.hxx22
-rw-r--r--src/libserver/css/css_tokeniser.cxx51
3 files changed, 80 insertions, 26 deletions
diff --git a/src/libserver/css/css_parser.cxx b/src/libserver/css/css_parser.cxx
index e4a8159f1..014ddf680 100644
--- a/src/libserver/css/css_parser.cxx
+++ b/src/libserver/css/css_parser.cxx
@@ -27,11 +27,11 @@ namespace rspamd::css {
const css_consumed_block css_parser_eof_block{};
auto css_consumed_block::attach_block(consumed_block_ptr &&block) -> bool {
- if (content.index() == 0) {
+ if (std::holds_alternative<std::monostate>(content)) {
/* Switch from monostate */
content = std::vector<consumed_block_ptr>();
}
- else if (content.index() == 2) {
+ else if (!std::holds_alternative<std::vector<consumed_block_ptr>>(content)) {
/* A single component, cannot attach a block ! */
return false;
}
@@ -42,6 +42,17 @@ auto css_consumed_block::attach_block(consumed_block_ptr &&block) -> bool {
return true;
}
+auto css_consumed_block::add_function_argument(consumed_block_ptr &&block) -> bool {
+ if (!std::holds_alternative<css_function_block>(content)) {
+ return false;
+ }
+
+ auto &&func_bloc = std::get<css_function_block>(content);
+ func_bloc.args.push_back(std::move(block));
+
+ return true;
+}
+
auto css_consumed_block::token_type_str(void) const -> const char *
{
const auto *ret = "";
@@ -106,6 +117,18 @@ auto css_consumed_block::debug_str(void) -> std::string {
/* Empty block */
ret += R"("empty")";
}
+ else if constexpr (std::is_same_v<T, css_function_block>) {
+ /* Empty block */
+ ret += R"({ "function:" {"name": )";
+ ret += "\"" + arg.function.debug_token_str() + "\"";
+ ret += R"("arguments:" [)";
+ for (const auto &block : arg.args) {
+ ret += "{";
+ ret += block->debug_str();
+ ret += "}, ";
+ }
+ ret += "]}";
+ }
else {
/* Single element block */
ret += "\"" + arg.debug_token_str() + "\"";
@@ -214,9 +237,13 @@ auto css_parser::function_consumer(std::unique_ptr<css_consumed_block> &top) ->
ret = true;
want_more = false;
break;
+ case css_parser_token::token_type::comma_token:
+ case css_parser_token::token_type::delim_token:
+ case css_parser_token::token_type::obrace_token:
+ break;
default:
/* Attach everything to the function block */
- top->attach_block(std::make_unique<css_consumed_block>(
+ top->add_function_argument(std::make_unique<css_consumed_block>(
css::css_consumed_block::parser_tag_type::css_function_arg,
std::move(next_token)));
break;
diff --git a/src/libserver/css/css_parser.hxx b/src/libserver/css/css_parser.hxx
index de982525a..7530730e7 100644
--- a/src/libserver/css/css_parser.hxx
+++ b/src/libserver/css/css_parser.hxx
@@ -51,6 +51,14 @@ public:
};
using consumed_block_ptr = std::unique_ptr<css_consumed_block>;
+ struct css_function_block {
+ css_parser_token function;
+ std::vector<consumed_block_ptr> args;
+
+ css_function_block(css_parser_token &&tok) :
+ function(std::forward<css_parser_token>(tok)) {}
+ };
+
css_consumed_block() : tag(parser_tag_type::css_eof_block) {}
css_consumed_block(parser_tag_type tag) : tag(tag) {
if (tag == parser_tag_type::css_top_block ||
@@ -64,10 +72,19 @@ public:
}
/* Construct a block from a single lexer token (for trivial blocks) */
explicit css_consumed_block(parser_tag_type tag, css_parser_token &&tok) :
- tag(tag), content(std::move(tok)) {}
+ tag(tag) {
+ if (tag == parser_tag_type::css_function) {
+ content = css_function_block{std::move(tok)};
+ }
+ else {
+ content = std::move(tok);
+ }
+ }
/* Attach a new block to the compound block, consuming block inside */
auto attach_block(consumed_block_ptr &&block) -> bool;
+ /* Attach a new argument to the compound function block, consuming block inside */
+ auto add_function_argument(consumed_block_ptr &&block) -> bool;
auto assign_token(css_parser_token &&tok) -> void {
content = std::move(tok);
@@ -137,7 +154,8 @@ public:
private:
std::variant<std::monostate,
std::vector<consumed_block_ptr>,
- css_parser_token> content;
+ css_parser_token,
+ css_function_block> content;
};
extern const css_consumed_block css_parser_eof_block;
diff --git a/src/libserver/css/css_tokeniser.cxx b/src/libserver/css/css_tokeniser.cxx
index f3a2767bd..1d6e89df7 100644
--- a/src/libserver/css/css_tokeniser.cxx
+++ b/src/libserver/css/css_tokeniser.cxx
@@ -246,34 +246,43 @@ auto css_tokeniser::consume_ident() -> struct css_parser_token
auto j = i + 1;
while (j < input.size() && g_ascii_isspace(input[j])) {
- j ++;
+ j++;
}
- if (input[j] == '"' || input[j] == '\'') {
- /* Function token */
- return maybe_escape_sv(j + 1,
- css_parser_token::token_type::function_token);
- }
- else {
- /* Consume URL token */
- while (j < input.size() && input[j] != ')') {
- j ++;
- }
-
- if (input[j] == ')') {
- /* Valid url token */
- return maybe_escape_sv(j + 1,
- css_parser_token::token_type::url_token);
+ if (input.size() > 3 && input.substr(0, 3) == "url") {
+ if (input[j] == '"' || input[j] == '\'') {
+ /* Function token */
+ auto ret = maybe_escape_sv(i,
+ css_parser_token::token_type::function_token);
+ return ret;
}
else {
- /* Incomplete url token */
- auto ret = maybe_escape_sv(j,
- css_parser_token::token_type::url_token);
+ /* Consume URL token */
+ while (j < input.size() && input[j] != ')') {
+ j++;
+ }
- ret.flags |= css_parser_token::flag_bad_string;
- return ret;
+ if (input[j] == ')') {
+ /* Valid url token */
+ auto ret = maybe_escape_sv(j + 1,
+ css_parser_token::token_type::url_token);
+ return ret;
+ }
+ else {
+ /* Incomplete url token */
+ auto ret = maybe_escape_sv(j,
+ css_parser_token::token_type::url_token);
+
+ ret.flags |= css_parser_token::flag_bad_string;
+ return ret;
+ }
}
}
+ else {
+ auto ret = maybe_escape_sv(i,
+ css_parser_token::token_type::function_token);
+ return ret;
+ }
}
else if (c == '-' && allow_middle_minus) {
i++;