]> source.dussan.org Git - rspamd.git/commitdiff
[Porject] Css: Rework functions parsing
authorVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 3 Mar 2021 21:41:55 +0000 (21:41 +0000)
committerVsevolod Stakhov <vsevolod@highsecure.ru>
Wed, 3 Mar 2021 21:41:55 +0000 (21:41 +0000)
src/libserver/css/css_parser.cxx
src/libserver/css/css_parser.hxx
src/libserver/css/css_tokeniser.cxx
test/lua/unit/css.lua

index e4a8159f17f2a429c79c6a9862dc51d7dccaf04d..014ddf680da901fb5e5a8a97231ec055c92e5587 100644 (file)
@@ -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;
index de982525a010a7e04550d787220a4161344a4c4f..7530730e7c81357db8ec060d51320f5b8ecffcfc 100644 (file)
@@ -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;
index f3a2767bd603282e54980affb476638462b410f6..1d6e89df78840e17e635ea8475dd742878d0a7b6 100644 (file)
@@ -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++;
index a5a8f533f173d633cbc838dd50b509ec1062742e..4bd78b244031549efb130c3627b15771d61f2c62 100644 (file)
@@ -97,6 +97,31 @@ body {
     width: 100%;
   }
 }
+]],
+[[
+/* Colors */
+* { color: hsl(0, 100%, 50%) }   /* red */
+* { color: hsl(120, 100%, 50%) } /* lime */
+* { color: hsl(120, 100%, 25%) } /* dark green */
+* { color: hsl(120, 100%, 75%) } /* light green */
+* { color: hsl(120, 75%, 75%) }  /* pastel green, and so on */
+em { color: #f00 }              /* #rgb */
+em { color: #ff0000 }           /* #rrggbb */
+em { color: rgb(255,0,0) }
+em { color: rgb(100%, 0%, 0%) }
+body {color: black; background: white }
+h1 { color: maroon }
+h2 { color: olive }
+em { color: rgb(255,0,0) }       /* integer range 0 - 255 */
+em { color: rgb(300,0,0) }       /* clipped to rgb(255,0,0) */
+em { color: rgb(255,-10,0) }     /* clipped to rgb(255,0,0) */
+em { color: rgb(110%, 0%, 0%) }  /* clipped to rgb(100%,0%,0%) */
+em { color: rgb(255,0,0) }      /* integer range 0 - 255 */
+em { color: rgba(255,0,0,1)     /* the same, with explicit opacity of 1 */
+em { color: rgb(100%,0%,0%) }   /* float range 0.0% - 100.0% */
+em { color: rgba(100%,0%,0%,1) } /* the same, with explicit opacity of 1 */
+p { color: rgba(0,0,255,0.5) }        /* semi-transparent solid blue */
+p { color: rgba(100%, 50%, 0%, 0.1) } /* very transparent solid orange */
 ]]
   }
   local NULL = ffi.new 'void*'