diff options
Diffstat (limited to 'src/libserver/css')
-rw-r--r-- | src/libserver/css/css.cxx | 44 | ||||
-rw-r--r-- | src/libserver/css/css.hxx | 29 | ||||
-rw-r--r-- | src/libserver/css/css_colors_list.hxx | 1404 | ||||
-rw-r--r-- | src/libserver/css/css_parser.cxx | 261 | ||||
-rw-r--r-- | src/libserver/css/css_parser.hxx | 105 | ||||
-rw-r--r-- | src/libserver/css/css_property.cxx | 28 | ||||
-rw-r--r-- | src/libserver/css/css_property.hxx | 60 | ||||
-rw-r--r-- | src/libserver/css/css_rule.cxx | 89 | ||||
-rw-r--r-- | src/libserver/css/css_rule.hxx | 47 | ||||
-rw-r--r-- | src/libserver/css/css_selector.cxx | 54 | ||||
-rw-r--r-- | src/libserver/css/css_selector.hxx | 37 | ||||
-rw-r--r-- | src/libserver/css/css_style.hxx | 30 | ||||
-rw-r--r-- | src/libserver/css/css_tokeniser.cxx | 125 | ||||
-rw-r--r-- | src/libserver/css/css_tokeniser.hxx | 62 | ||||
-rw-r--r-- | src/libserver/css/css_util.cxx | 71 | ||||
-rw-r--r-- | src/libserver/css/css_util.hxx | 4 | ||||
-rw-r--r-- | src/libserver/css/css_value.cxx | 204 | ||||
-rw-r--r-- | src/libserver/css/css_value.hxx | 99 | ||||
-rw-r--r-- | src/libserver/css/parse_error.hxx | 19 |
19 files changed, 1446 insertions, 1326 deletions
diff --git a/src/libserver/css/css.cxx b/src/libserver/css/css.cxx index 7de4ab307..1b369ed17 100644 --- a/src/libserver/css/css.cxx +++ b/src/libserver/css/css.cxx @@ -35,7 +35,7 @@ public: using sel_shared_eq = smart_ptr_equal<css_selector>; using selector_ptr = std::unique_ptr<css_selector>; using selectors_hash = ankerl::unordered_dense::map<selector_ptr, css_declarations_block_ptr, - sel_shared_hash, sel_shared_eq>; + sel_shared_hash, sel_shared_eq>; using universal_selector_t = std::pair<selector_ptr, css_declarations_block_ptr>; selectors_hash tags_selector; selectors_hash class_selectors; @@ -44,16 +44,19 @@ public: }; css_style_sheet::css_style_sheet(rspamd_mempool_t *pool) - : pool(pool), pimpl(new impl) {} -css_style_sheet::~css_style_sheet() {} + : pool(pool), pimpl(new impl) +{ +} +css_style_sheet::~css_style_sheet() +{ +} -auto -css_style_sheet::add_selector_rule(std::unique_ptr<css_selector> &&selector, - css_declarations_block_ptr decls) -> void +auto css_style_sheet::add_selector_rule(std::unique_ptr<css_selector> &&selector, + css_declarations_block_ptr decls) -> void { impl::selectors_hash *target_hash = nullptr; - switch(selector->type) { + switch (selector->type) { case css_selector::selector_type::SELECTOR_ALL: if (pimpl->universal_selector) { /* Another universal selector */ @@ -63,7 +66,7 @@ css_style_sheet::add_selector_rule(std::unique_ptr<css_selector> &&selector, else { msg_debug_css("added universal selector"); pimpl->universal_selector = std::make_pair(std::move(selector), - decls); + decls); } break; case css_selector::selector_type::SELECTOR_CLASS: @@ -95,16 +98,14 @@ css_style_sheet::add_selector_rule(std::unique_ptr<css_selector> &&selector, * merging when finally resolving paths. */ auto sel_str = selector->to_string().value_or("unknown"); - msg_debug_css("found duplicate selector: %*s", (int)sel_str.size(), - sel_str.data()); + msg_debug_css("found duplicate selector: %*s", (int) sel_str.size(), + sel_str.data()); found_it->second->merge_block(*decls); } } } -auto -css_style_sheet::check_tag_block(const rspamd::html::html_tag *tag) -> - rspamd::html::html_block * +auto css_style_sheet::check_tag_block(const rspamd::html::html_tag *tag) -> rspamd::html::html_block * { std::optional<std::string_view> id_comp, class_comp; rspamd::html::html_block *res = nullptr; @@ -114,7 +115,7 @@ css_style_sheet::check_tag_block(const rspamd::html::html_tag *tag) -> } /* First, find id in a tag and a class */ - for (const auto ¶m : tag->components) { + for (const auto ¶m: tag->components) { if (param.type == html::html_component_type::RSPAMD_HTML_COMPONENT_ID) { id_comp = param.value; } @@ -157,9 +158,9 @@ css_style_sheet::check_tag_block(const rspamd::html::html_tag *tag) -> auto elts = sv_split(class_comp.value()); - for (const auto &e : elts) { + for (const auto &e: elts) { auto found_class_sel = pimpl->class_selectors.find( - css_selector{e, css_selector::selector_type::SELECTOR_CLASS}); + css_selector{e, css_selector::selector_type::SELECTOR_CLASS}); if (found_class_sel != pimpl->class_selectors.end()) { const auto &decl = *(found_class_sel->second); @@ -178,7 +179,7 @@ css_style_sheet::check_tag_block(const rspamd::html::html_tag *tag) -> /* Tags part */ if (!pimpl->tags_selector.empty()) { auto found_tag_sel = pimpl->tags_selector.find( - css_selector{static_cast<tag_id_t>(tag->id)}); + css_selector{static_cast<tag_id_t>(tag->id)}); if (found_tag_sel != pimpl->tags_selector.end()) { const auto &decl = *(found_tag_sel->second); @@ -208,14 +209,13 @@ css_style_sheet::check_tag_block(const rspamd::html::html_tag *tag) -> return res; } -auto -css_parse_style(rspamd_mempool_t *pool, +auto css_parse_style(rspamd_mempool_t *pool, std::string_view input, std::shared_ptr<css_style_sheet> &&existing) - -> css_return_pair + -> css_return_pair { auto parse_res = rspamd::css::parse_css(pool, input, - std::forward<std::shared_ptr<css_style_sheet>>(existing)); + std::forward<std::shared_ptr<css_style_sheet>>(existing)); if (parse_res.has_value()) { return std::make_pair(parse_res.value(), css_parse_error()); @@ -224,4 +224,4 @@ css_parse_style(rspamd_mempool_t *pool, return std::make_pair(nullptr, parse_res.error()); } -}
\ No newline at end of file +}// namespace rspamd::css
\ No newline at end of file diff --git a/src/libserver/css/css.hxx b/src/libserver/css/css.hxx index 7768bde55..f0f8120fb 100644 --- a/src/libserver/css/css.hxx +++ b/src/libserver/css/css.hxx @@ -28,20 +28,20 @@ namespace rspamd::html { /* Forward declaration */ struct html_tag; struct html_block; -} +}// namespace rspamd::html namespace rspamd::css { extern int rspamd_css_log_id; -#define msg_debug_css(...) rspamd_conditional_debug_fast (NULL, NULL, \ - rspamd_css_log_id, "css", pool->tag.uid, \ - __FUNCTION__, \ - __VA_ARGS__) -#define msg_err_css(...) rspamd_default_log_function (G_LOG_LEVEL_CRITICAL, \ - "css", pool->tag.uid, \ - __FUNCTION__, \ - __VA_ARGS__) +#define msg_debug_css(...) rspamd_conditional_debug_fast(NULL, NULL, \ + rspamd_css_log_id, "css", pool->tag.uid, \ + __FUNCTION__, \ + __VA_ARGS__) +#define msg_err_css(...) rspamd_default_log_function(G_LOG_LEVEL_CRITICAL, \ + "css", pool->tag.uid, \ + __FUNCTION__, \ + __VA_ARGS__) class css_style_sheet { public: @@ -50,8 +50,8 @@ public: auto add_selector_rule(std::unique_ptr<css_selector> &&selector, css_declarations_block_ptr decls) -> void; - auto check_tag_block(const rspamd::html::html_tag *tag) -> - rspamd::html::html_block *; + auto check_tag_block(const rspamd::html::html_tag *tag) -> rspamd::html::html_block *; + private: class impl; rspamd_mempool_t *pool; @@ -61,9 +61,8 @@ private: using css_return_pair = std::pair<std::shared_ptr<css_style_sheet>, css_parse_error>; auto css_parse_style(rspamd_mempool_t *pool, std::string_view input, - std::shared_ptr<css_style_sheet> &&existing) -> - css_return_pair; + std::shared_ptr<css_style_sheet> &&existing) -> css_return_pair; -} +}// namespace rspamd::css -#endif //RSPAMD_CSS_H
\ No newline at end of file +#endif//RSPAMD_CSS_H
\ No newline at end of file diff --git a/src/libserver/css/css_colors_list.hxx b/src/libserver/css/css_colors_list.hxx index e880aa24b..6dfe54f67 100644 --- a/src/libserver/css/css_colors_list.hxx +++ b/src/libserver/css/css_colors_list.hxx @@ -31,708 +31,708 @@ namespace rspamd::css { * compiler limits... */ static const ankerl::unordered_dense::map<std::string_view, css_color> css_colors_map{ - {"aliceblue", {240, 248, 255}}, - {"antiquewhite", {250, 235, 215}}, - {"antiquewhite1", {255, 239, 219}}, - {"antiquewhite2", {238, 223, 204}}, - {"antiquewhite3", {205, 192, 176}}, - {"antiquewhite4", {139, 131, 120}}, - {"aqua", {0, 255, 255}}, - {"aquamarine", {127, 255, 212}}, - {"aquamarine1", {127, 255, 212}}, - {"aquamarine2", {118, 238, 198}}, - {"aquamarine3", {102, 205, 170}}, - {"aquamarine4", {69, 139, 116}}, - {"azure", {240, 255, 255}}, - {"azure1", {240, 255, 255}}, - {"azure2", {224, 238, 238}}, - {"azure3", {193, 205, 205}}, - {"azure4", {131, 139, 139}}, - {"beige", {245, 245, 220}}, - {"bisque", {255, 228, 196}}, - {"bisque1", {255, 228, 196}}, - {"bisque2", {238, 213, 183}}, - {"bisque3", {205, 183, 158}}, - {"bisque4", {139, 125, 107}}, - {"black", {0, 0, 0}}, - {"blanchedalmond", {255, 235, 205}}, - {"blue", {0, 0, 255}}, - {"blue1", {0, 0, 255}}, - {"blue2", {0, 0, 238}}, - {"blue3", {0, 0, 205}}, - {"blue4", {0, 0, 139}}, - {"blueviolet", {138, 43, 226}}, - {"brown", {165, 42, 42}}, - {"brown1", {255, 64, 64}}, - {"brown2", {238, 59, 59}}, - {"brown3", {205, 51, 51}}, - {"brown4", {139, 35, 35}}, - {"burlywood", {222, 184, 135}}, - {"burlywood1", {255, 211, 155}}, - {"burlywood2", {238, 197, 145}}, - {"burlywood3", {205, 170, 125}}, - {"burlywood4", {139, 115, 85}}, - {"cadetblue", {95, 158, 160}}, - {"cadetblue1", {152, 245, 255}}, - {"cadetblue2", {142, 229, 238}}, - {"cadetblue3", {122, 197, 205}}, - {"cadetblue4", {83, 134, 139}}, - {"chartreuse", {127, 255, 0}}, - {"chartreuse1", {127, 255, 0}}, - {"chartreuse2", {118, 238, 0}}, - {"chartreuse3", {102, 205, 0}}, - {"chartreuse4", {69, 139, 0}}, - {"chocolate", {210, 105, 30}}, - {"chocolate1", {255, 127, 36}}, - {"chocolate2", {238, 118, 33}}, - {"chocolate3", {205, 102, 29}}, - {"chocolate4", {139, 69, 19}}, - {"coral", {255, 127, 80}}, - {"coral1", {255, 114, 86}}, - {"coral2", {238, 106, 80}}, - {"coral3", {205, 91, 69}}, - {"coral4", {139, 62, 47}}, - {"cornflowerblue", {100, 149, 237}}, - {"cornsilk", {255, 248, 220}}, - {"cornsilk1", {255, 248, 220}}, - {"cornsilk2", {238, 232, 205}}, - {"cornsilk3", {205, 200, 177}}, - {"cornsilk4", {139, 136, 120}}, - {"crimson", {220, 20, 60}}, - {"cyan", {0, 255, 255}}, - {"cyan1", {0, 255, 255}}, - {"cyan2", {0, 238, 238}}, - {"cyan3", {0, 205, 205}}, - {"cyan4", {0, 139, 139}}, - {"darkblue", {0, 0, 139}}, - {"darkcyan", {0, 139, 139}}, - {"darkgoldenrod", {184, 134, 11}}, - {"darkgoldenrod1", {255, 185, 15}}, - {"darkgoldenrod2", {238, 173, 14}}, - {"darkgoldenrod3", {205, 149, 12}}, - {"darkgoldenrod4", {139, 101, 8}}, - {"darkgray", {169, 169, 169}}, - {"darkgreen", {0, 100, 0}}, - {"darkgrey", {169, 169, 169}}, - {"darkkhaki", {189, 183, 107}}, - {"darkmagenta", {139, 0, 139}}, - {"darkolivegreen", {85, 107, 47}}, - {"darkolivegreen1", {202, 255, 112}}, - {"darkolivegreen2", {188, 238, 104}}, - {"darkolivegreen3", {162, 205, 90}}, - {"darkolivegreen4", {110, 139, 61}}, - {"darkorange", {255, 140, 0}}, - {"darkorange1", {255, 127, 0}}, - {"darkorange2", {238, 118, 0}}, - {"darkorange3", {205, 102, 0}}, - {"darkorange4", {139, 69, 0}}, - {"darkorchid", {153, 50, 204}}, - {"darkorchid1", {191, 62, 255}}, - {"darkorchid2", {178, 58, 238}}, - {"darkorchid3", {154, 50, 205}}, - {"darkorchid4", {104, 34, 139}}, - {"darkred", {139, 0, 0}}, - {"darksalmon", {233, 150, 122}}, - {"darkseagreen", {143, 188, 143}}, - {"darkseagreen1", {193, 255, 193}}, - {"darkseagreen2", {180, 238, 180}}, - {"darkseagreen3", {155, 205, 155}}, - {"darkseagreen4", {105, 139, 105}}, - {"darkslateblue", {72, 61, 139}}, - {"darkslategray", {47, 79, 79}}, - {"darkslategray1", {151, 255, 255}}, - {"darkslategray2", {141, 238, 238}}, - {"darkslategray3", {121, 205, 205}}, - {"darkslategray4", {82, 139, 139}}, - {"darkslategrey", {47, 79, 79}}, - {"darkturquoise", {0, 206, 209}}, - {"darkviolet", {148, 0, 211}}, - {"deeppink", {255, 20, 147}}, - {"deeppink1", {255, 20, 147}}, - {"deeppink2", {238, 18, 137}}, - {"deeppink3", {205, 16, 118}}, - {"deeppink4", {139, 10, 80}}, - {"deepskyblue", {0, 191, 255}}, - {"deepskyblue1", {0, 191, 255}}, - {"deepskyblue2", {0, 178, 238}}, - {"deepskyblue3", {0, 154, 205}}, - {"deepskyblue4", {0, 104, 139}}, - {"dimgray", {105, 105, 105}}, - {"dimgrey", {105, 105, 105}}, - {"dodgerblue", {30, 144, 255}}, - {"dodgerblue1", {30, 144, 255}}, - {"dodgerblue2", {28, 134, 238}}, - {"dodgerblue3", {24, 116, 205}}, - {"dodgerblue4", {16, 78, 139}}, - {"firebrick", {178, 34, 34}}, - {"firebrick1", {255, 48, 48}}, - {"firebrick2", {238, 44, 44}}, - {"firebrick3", {205, 38, 38}}, - {"firebrick4", {139, 26, 26}}, - {"floralwhite", {255, 250, 240}}, - {"forestgreen", {34, 139, 34}}, - {"fuchsia", {255, 0, 255}}, - {"gainsboro", {220, 220, 220}}, - {"ghostwhite", {248, 248, 255}}, - {"gold", {255, 215, 0}}, - {"gold1", {255, 215, 0}}, - {"gold2", {238, 201, 0}}, - {"gold3", {205, 173, 0}}, - {"gold4", {139, 117, 0}}, - {"goldenrod", {218, 165, 32}}, - {"goldenrod1", {255, 193, 37}}, - {"goldenrod2", {238, 180, 34}}, - {"goldenrod3", {205, 155, 29}}, - {"goldenrod4", {139, 105, 20}}, - {"gray", {190, 190, 190}}, - {"gray0", {0, 0, 0}}, - {"gray1", {3, 3, 3}}, - {"gray10", {26, 26, 26}}, - {"gray100", {255, 255, 255}}, - {"gray11", {28, 28, 28}}, - {"gray12", {31, 31, 31}}, - {"gray13", {33, 33, 33}}, - {"gray14", {36, 36, 36}}, - {"gray15", {38, 38, 38}}, - {"gray16", {41, 41, 41}}, - {"gray17", {43, 43, 43}}, - {"gray18", {46, 46, 46}}, - {"gray19", {48, 48, 48}}, - {"gray2", {5, 5, 5}}, - {"gray20", {51, 51, 51}}, - {"gray21", {54, 54, 54}}, - {"gray22", {56, 56, 56}}, - {"gray23", {59, 59, 59}}, - {"gray24", {61, 61, 61}}, - {"gray25", {64, 64, 64}}, - {"gray26", {66, 66, 66}}, - {"gray27", {69, 69, 69}}, - {"gray28", {71, 71, 71}}, - {"gray29", {74, 74, 74}}, - {"gray3", {8, 8, 8}}, - {"gray30", {77, 77, 77}}, - {"gray31", {79, 79, 79}}, - {"gray32", {82, 82, 82}}, - {"gray33", {84, 84, 84}}, - {"gray34", {87, 87, 87}}, - {"gray35", {89, 89, 89}}, - {"gray36", {92, 92, 92}}, - {"gray37", {94, 94, 94}}, - {"gray38", {97, 97, 97}}, - {"gray39", {99, 99, 99}}, - {"gray4", {10, 10, 10}}, - {"gray40", {102, 102, 102}}, - {"gray41", {105, 105, 105}}, - {"gray42", {107, 107, 107}}, - {"gray43", {110, 110, 110}}, - {"gray44", {112, 112, 112}}, - {"gray45", {115, 115, 115}}, - {"gray46", {117, 117, 117}}, - {"gray47", {120, 120, 120}}, - {"gray48", {122, 122, 122}}, - {"gray49", {125, 125, 125}}, - {"gray5", {13, 13, 13}}, - {"gray50", {127, 127, 127}}, - {"gray51", {130, 130, 130}}, - {"gray52", {133, 133, 133}}, - {"gray53", {135, 135, 135}}, - {"gray54", {138, 138, 138}}, - {"gray55", {140, 140, 140}}, - {"gray56", {143, 143, 143}}, - {"gray57", {145, 145, 145}}, - {"gray58", {148, 148, 148}}, - {"gray59", {150, 150, 150}}, - {"gray6", {15, 15, 15}}, - {"gray60", {153, 153, 153}}, - {"gray61", {156, 156, 156}}, - {"gray62", {158, 158, 158}}, - {"gray63", {161, 161, 161}}, - {"gray64", {163, 163, 163}}, - {"gray65", {166, 166, 166}}, - {"gray66", {168, 168, 168}}, - {"gray67", {171, 171, 171}}, - {"gray68", {173, 173, 173}}, - {"gray69", {176, 176, 176}}, - {"gray7", {18, 18, 18}}, - {"gray70", {179, 179, 179}}, - {"gray71", {181, 181, 181}}, - {"gray72", {184, 184, 184}}, - {"gray73", {186, 186, 186}}, - {"gray74", {189, 189, 189}}, - {"gray75", {191, 191, 191}}, - {"gray76", {194, 194, 194}}, - {"gray77", {196, 196, 196}}, - {"gray78", {199, 199, 199}}, - {"gray79", {201, 201, 201}}, - {"gray8", {20, 20, 20}}, - {"gray80", {204, 204, 204}}, - {"gray81", {207, 207, 207}}, - {"gray82", {209, 209, 209}}, - {"gray83", {212, 212, 212}}, - {"gray84", {214, 214, 214}}, - {"gray85", {217, 217, 217}}, - {"gray86", {219, 219, 219}}, - {"gray87", {222, 222, 222}}, - {"gray88", {224, 224, 224}}, - {"gray89", {227, 227, 227}}, - {"gray9", {23, 23, 23}}, - {"gray90", {229, 229, 229}}, - {"gray91", {232, 232, 232}}, - {"gray92", {235, 235, 235}}, - {"gray93", {237, 237, 237}}, - {"gray94", {240, 240, 240}}, - {"gray95", {242, 242, 242}}, - {"gray96", {245, 245, 245}}, - {"gray97", {247, 247, 247}}, - {"gray98", {250, 250, 250}}, - {"gray99", {252, 252, 252}}, - {"green", {0, 255, 0}}, - {"green1", {0, 255, 0}}, - {"green2", {0, 238, 0}}, - {"green3", {0, 205, 0}}, - {"green4", {0, 139, 0}}, - {"greenyellow", {173, 255, 47}}, - {"grey", {190, 190, 190}}, - {"grey0", {0, 0, 0}}, - {"grey1", {3, 3, 3}}, - {"grey10", {26, 26, 26}}, - {"grey100", {255, 255, 255}}, - {"grey11", {28, 28, 28}}, - {"grey12", {31, 31, 31}}, - {"grey13", {33, 33, 33}}, - {"grey14", {36, 36, 36}}, - {"grey15", {38, 38, 38}}, - {"grey16", {41, 41, 41}}, - {"grey17", {43, 43, 43}}, - {"grey18", {46, 46, 46}}, - {"grey19", {48, 48, 48}}, - {"grey2", {5, 5, 5}}, - {"grey20", {51, 51, 51}}, - {"grey21", {54, 54, 54}}, - {"grey22", {56, 56, 56}}, - {"grey23", {59, 59, 59}}, - {"grey24", {61, 61, 61}}, - {"grey25", {64, 64, 64}}, - {"grey26", {66, 66, 66}}, - {"grey27", {69, 69, 69}}, - {"grey28", {71, 71, 71}}, - {"grey29", {74, 74, 74}}, - {"grey3", {8, 8, 8}}, - {"grey30", {77, 77, 77}}, - {"grey31", {79, 79, 79}}, - {"grey32", {82, 82, 82}}, - {"grey33", {84, 84, 84}}, - {"grey34", {87, 87, 87}}, - {"grey35", {89, 89, 89}}, - {"grey36", {92, 92, 92}}, - {"grey37", {94, 94, 94}}, - {"grey38", {97, 97, 97}}, - {"grey39", {99, 99, 99}}, - {"grey4", {10, 10, 10}}, - {"grey40", {102, 102, 102}}, - {"grey41", {105, 105, 105}}, - {"grey42", {107, 107, 107}}, - {"grey43", {110, 110, 110}}, - {"grey44", {112, 112, 112}}, - {"grey45", {115, 115, 115}}, - {"grey46", {117, 117, 117}}, - {"grey47", {120, 120, 120}}, - {"grey48", {122, 122, 122}}, - {"grey49", {125, 125, 125}}, - {"grey5", {13, 13, 13}}, - {"grey50", {127, 127, 127}}, - {"grey51", {130, 130, 130}}, - {"grey52", {133, 133, 133}}, - {"grey53", {135, 135, 135}}, - {"grey54", {138, 138, 138}}, - {"grey55", {140, 140, 140}}, - {"grey56", {143, 143, 143}}, - {"grey57", {145, 145, 145}}, - {"grey58", {148, 148, 148}}, - {"grey59", {150, 150, 150}}, - {"grey6", {15, 15, 15}}, - {"grey60", {153, 153, 153}}, - {"grey61", {156, 156, 156}}, - {"grey62", {158, 158, 158}}, - {"grey63", {161, 161, 161}}, - {"grey64", {163, 163, 163}}, - {"grey65", {166, 166, 166}}, - {"grey66", {168, 168, 168}}, - {"grey67", {171, 171, 171}}, - {"grey68", {173, 173, 173}}, - {"grey69", {176, 176, 176}}, - {"grey7", {18, 18, 18}}, - {"grey70", {179, 179, 179}}, - {"grey71", {181, 181, 181}}, - {"grey72", {184, 184, 184}}, - {"grey73", {186, 186, 186}}, - {"grey74", {189, 189, 189}}, - {"grey75", {191, 191, 191}}, - {"grey76", {194, 194, 194}}, - {"grey77", {196, 196, 196}}, - {"grey78", {199, 199, 199}}, - {"grey79", {201, 201, 201}}, - {"grey8", {20, 20, 20}}, - {"grey80", {204, 204, 204}}, - {"grey81", {207, 207, 207}}, - {"grey82", {209, 209, 209}}, - {"grey83", {212, 212, 212}}, - {"grey84", {214, 214, 214}}, - {"grey85", {217, 217, 217}}, - {"grey86", {219, 219, 219}}, - {"grey87", {222, 222, 222}}, - {"grey88", {224, 224, 224}}, - {"grey89", {227, 227, 227}}, - {"grey9", {23, 23, 23}}, - {"grey90", {229, 229, 229}}, - {"grey91", {232, 232, 232}}, - {"grey92", {235, 235, 235}}, - {"grey93", {237, 237, 237}}, - {"grey94", {240, 240, 240}}, - {"grey95", {242, 242, 242}}, - {"grey96", {245, 245, 245}}, - {"grey97", {247, 247, 247}}, - {"grey98", {250, 250, 250}}, - {"grey99", {252, 252, 252}}, - {"honeydew", {240, 255, 240}}, - {"honeydew1", {240, 255, 240}}, - {"honeydew2", {224, 238, 224}}, - {"honeydew3", {193, 205, 193}}, - {"honeydew4", {131, 139, 131}}, - {"hotpink", {255, 105, 180}}, - {"hotpink1", {255, 110, 180}}, - {"hotpink2", {238, 106, 167}}, - {"hotpink3", {205, 96, 144}}, - {"hotpink4", {139, 58, 98}}, - {"indianred", {205, 92, 92}}, - {"indianred1", {255, 106, 106}}, - {"indianred2", {238, 99, 99}}, - {"indianred3", {205, 85, 85}}, - {"indianred4", {139, 58, 58}}, - {"indigo", {75, 0, 130}}, - {"ivory", {255, 255, 240}}, - {"ivory1", {255, 255, 240}}, - {"ivory2", {238, 238, 224}}, - {"ivory3", {205, 205, 193}}, - {"ivory4", {139, 139, 131}}, - {"khaki", {240, 230, 140}}, - {"khaki1", {255, 246, 143}}, - {"khaki2", {238, 230, 133}}, - {"khaki3", {205, 198, 115}}, - {"khaki4", {139, 134, 78}}, - {"lavender", {230, 230, 250}}, - {"lavenderblush", {255, 240, 245}}, - {"lavenderblush1", {255, 240, 245}}, - {"lavenderblush2", {238, 224, 229}}, - {"lavenderblush3", {205, 193, 197}}, - {"lavenderblush4", {139, 131, 134}}, - {"lawngreen", {124, 252, 0}}, - {"lemonchiffon", {255, 250, 205}}, - {"lemonchiffon1", {255, 250, 205}}, - {"lemonchiffon2", {238, 233, 191}}, - {"lemonchiffon3", {205, 201, 165}}, - {"lemonchiffon4", {139, 137, 112}}, - {"lightblue", {173, 216, 230}}, - {"lightblue1", {191, 239, 255}}, - {"lightblue2", {178, 223, 238}}, - {"lightblue3", {154, 192, 205}}, - {"lightblue4", {104, 131, 139}}, - {"lightcoral", {240, 128, 128}}, - {"lightcyan", {224, 255, 255}}, - {"lightcyan1", {224, 255, 255}}, - {"lightcyan2", {209, 238, 238}}, - {"lightcyan3", {180, 205, 205}}, - {"lightcyan4", {122, 139, 139}}, - {"lightgoldenrod", {238, 221, 130}}, - {"lightgoldenrod1", {255, 236, 139}}, - {"lightgoldenrod2", {238, 220, 130}}, - {"lightgoldenrod3", {205, 190, 112}}, - {"lightgoldenrod4", {139, 129, 76}}, - {"lightgoldenrodyellow", {250, 250, 210}}, - {"lightgray", {211, 211, 211}}, - {"lightgreen", {144, 238, 144}}, - {"lightgrey", {211, 211, 211}}, - {"lightpink", {255, 182, 193}}, - {"lightpink1", {255, 174, 185}}, - {"lightpink2", {238, 162, 173}}, - {"lightpink3", {205, 140, 149}}, - {"lightpink4", {139, 95, 101}}, - {"lightsalmon", {255, 160, 122}}, - {"lightsalmon1", {255, 160, 122}}, - {"lightsalmon2", {238, 149, 114}}, - {"lightsalmon3", {205, 129, 98}}, - {"lightsalmon4", {139, 87, 66}}, - {"lightseagreen", {32, 178, 170}}, - {"lightskyblue", {135, 206, 250}}, - {"lightskyblue1", {176, 226, 255}}, - {"lightskyblue2", {164, 211, 238}}, - {"lightskyblue3", {141, 182, 205}}, - {"lightskyblue4", {96, 123, 139}}, - {"lightslateblue", {132, 112, 255}}, - {"lightslategray", {119, 136, 153}}, - {"lightslategrey", {119, 136, 153}}, - {"lightsteelblue", {176, 196, 222}}, - {"lightsteelblue1", {202, 225, 255}}, - {"lightsteelblue2", {188, 210, 238}}, - {"lightsteelblue3", {162, 181, 205}}, - {"lightsteelblue4", {110, 123, 139}}, - {"lightyellow", {255, 255, 224}}, - {"lightyellow1", {255, 255, 224}}, - {"lightyellow2", {238, 238, 209}}, - {"lightyellow3", {205, 205, 180}}, - {"lightyellow4", {139, 139, 122}}, - {"lime", {0, 255, 0}}, - {"limegreen", {50, 205, 50}}, - {"linen", {250, 240, 230}}, - {"magenta", {255, 0, 255}}, - {"magenta1", {255, 0, 255}}, - {"magenta2", {238, 0, 238}}, - {"magenta3", {205, 0, 205}}, - {"magenta4", {139, 0, 139}}, - {"maroon", {176, 48, 96}}, - {"maroon1", {255, 52, 179}}, - {"maroon2", {238, 48, 167}}, - {"maroon3", {205, 41, 144}}, - {"maroon4", {139, 28, 98}}, - {"mediumaquamarine", {102, 205, 170}}, - {"mediumblue", {0, 0, 205}}, - {"mediumorchid", {186, 85, 211}}, - {"mediumorchid1", {224, 102, 255}}, - {"mediumorchid2", {209, 95, 238}}, - {"mediumorchid3", {180, 82, 205}}, - {"mediumorchid4", {122, 55, 139}}, - {"mediumpurple", {147, 112, 219}}, - {"mediumpurple1", {171, 130, 255}}, - {"mediumpurple2", {159, 121, 238}}, - {"mediumpurple3", {137, 104, 205}}, - {"mediumpurple4", {93, 71, 139}}, - {"mediumseagreen", {60, 179, 113}}, - {"mediumslateblue", {123, 104, 238}}, - {"mediumspringgreen", {0, 250, 154}}, - {"mediumturquoise", {72, 209, 204}}, - {"mediumvioletred", {199, 21, 133}}, - {"midnightblue", {25, 25, 112}}, - {"mintcream", {245, 255, 250}}, - {"mistyrose", {255, 228, 225}}, - {"mistyrose1", {255, 228, 225}}, - {"mistyrose2", {238, 213, 210}}, - {"mistyrose3", {205, 183, 181}}, - {"mistyrose4", {139, 125, 123}}, - {"moccasin", {255, 228, 181}}, - {"navajowhite", {255, 222, 173}}, - {"navajowhite1", {255, 222, 173}}, - {"navajowhite2", {238, 207, 161}}, - {"navajowhite3", {205, 179, 139}}, - {"navajowhite4", {139, 121, 94}}, - {"navy", {0, 0, 128}}, - {"navyblue", {0, 0, 128}}, - {"oldlace", {253, 245, 230}}, - {"olive", {128, 128, 0}}, - {"olivedrab", {107, 142, 35}}, - {"olivedrab1", {192, 255, 62}}, - {"olivedrab2", {179, 238, 58}}, - {"olivedrab3", {154, 205, 50}}, - {"olivedrab4", {105, 139, 34}}, - {"orange", {255, 165, 0}}, - {"orange1", {255, 165, 0}}, - {"orange2", {238, 154, 0}}, - {"orange3", {205, 133, 0}}, - {"orange4", {139, 90, 0}}, - {"orangered", {255, 69, 0}}, - {"orangered1", {255, 69, 0}}, - {"orangered2", {238, 64, 0}}, - {"orangered3", {205, 55, 0}}, - {"orangered4", {139, 37, 0}}, - {"orchid", {218, 112, 214}}, - {"orchid1", {255, 131, 250}}, - {"orchid2", {238, 122, 233}}, - {"orchid3", {205, 105, 201}}, - {"orchid4", {139, 71, 137}}, - {"palegoldenrod", {238, 232, 170}}, - {"palegreen", {152, 251, 152}}, - {"palegreen1", {154, 255, 154}}, - {"palegreen2", {144, 238, 144}}, - {"palegreen3", {124, 205, 124}}, - {"palegreen4", {84, 139, 84}}, - {"paleturquoise", {175, 238, 238}}, - {"paleturquoise1", {187, 255, 255}}, - {"paleturquoise2", {174, 238, 238}}, - {"paleturquoise3", {150, 205, 205}}, - {"paleturquoise4", {102, 139, 139}}, - {"palevioletred", {219, 112, 147}}, - {"palevioletred1", {255, 130, 171}}, - {"palevioletred2", {238, 121, 159}}, - {"palevioletred3", {205, 104, 137}}, - {"palevioletred4", {139, 71, 93}}, - {"papayawhip", {255, 239, 213}}, - {"peachpuff", {255, 218, 185}}, - {"peachpuff1", {255, 218, 185}}, - {"peachpuff2", {238, 203, 173}}, - {"peachpuff3", {205, 175, 149}}, - {"peachpuff4", {139, 119, 101}}, - {"peru", {205, 133, 63}}, - {"pink", {255, 192, 203}}, - {"pink1", {255, 181, 197}}, - {"pink2", {238, 169, 184}}, - {"pink3", {205, 145, 158}}, - {"pink4", {139, 99, 108}}, - {"plum", {221, 160, 221}}, - {"plum1", {255, 187, 255}}, - {"plum2", {238, 174, 238}}, - {"plum3", {205, 150, 205}}, - {"plum4", {139, 102, 139}}, - {"powderblue", {176, 224, 230}}, - {"purple", {160, 32, 240}}, - {"purple1", {155, 48, 255}}, - {"purple2", {145, 44, 238}}, - {"purple3", {125, 38, 205}}, - {"purple4", {85, 26, 139}}, - {"rebeccapurple", {102, 51, 153}}, - {"red", {255, 0, 0}}, - {"red1", {255, 0, 0}}, - {"red2", {238, 0, 0}}, - {"red3", {205, 0, 0}}, - {"red4", {139, 0, 0}}, - {"rosybrown", {188, 143, 143}}, - {"rosybrown1", {255, 193, 193}}, - {"rosybrown2", {238, 180, 180}}, - {"rosybrown3", {205, 155, 155}}, - {"rosybrown4", {139, 105, 105}}, - {"royalblue", {65, 105, 225}}, - {"royalblue1", {72, 118, 255}}, - {"royalblue2", {67, 110, 238}}, - {"royalblue3", {58, 95, 205}}, - {"royalblue4", {39, 64, 139}}, - {"saddlebrown", {139, 69, 19}}, - {"salmon", {250, 128, 114}}, - {"salmon1", {255, 140, 105}}, - {"salmon2", {238, 130, 98}}, - {"salmon3", {205, 112, 84}}, - {"salmon4", {139, 76, 57}}, - {"sandybrown", {244, 164, 96}}, - {"seagreen", {46, 139, 87}}, - {"seagreen1", {84, 255, 159}}, - {"seagreen2", {78, 238, 148}}, - {"seagreen3", {67, 205, 128}}, - {"seagreen4", {46, 139, 87}}, - {"seashell", {255, 245, 238}}, - {"seashell1", {255, 245, 238}}, - {"seashell2", {238, 229, 222}}, - {"seashell3", {205, 197, 191}}, - {"seashell4", {139, 134, 130}}, - {"sienna", {160, 82, 45}}, - {"sienna1", {255, 130, 71}}, - {"sienna2", {238, 121, 66}}, - {"sienna3", {205, 104, 57}}, - {"sienna4", {139, 71, 38}}, - {"silver", {192, 192, 192}}, - {"skyblue", {135, 206, 235}}, - {"skyblue1", {135, 206, 255}}, - {"skyblue2", {126, 192, 238}}, - {"skyblue3", {108, 166, 205}}, - {"skyblue4", {74, 112, 139}}, - {"slateblue", {106, 90, 205}}, - {"slateblue1", {131, 111, 255}}, - {"slateblue2", {122, 103, 238}}, - {"slateblue3", {105, 89, 205}}, - {"slateblue4", {71, 60, 139}}, - {"slategray", {112, 128, 144}}, - {"slategray1", {198, 226, 255}}, - {"slategray2", {185, 211, 238}}, - {"slategray3", {159, 182, 205}}, - {"slategray4", {108, 123, 139}}, - {"slategrey", {112, 128, 144}}, - {"snow", {255, 250, 250}}, - {"snow1", {255, 250, 250}}, - {"snow2", {238, 233, 233}}, - {"snow3", {205, 201, 201}}, - {"snow4", {139, 137, 137}}, - {"springgreen", {0, 255, 127}}, - {"springgreen1", {0, 255, 127}}, - {"springgreen2", {0, 238, 118}}, - {"springgreen3", {0, 205, 102}}, - {"springgreen4", {0, 139, 69}}, - {"steelblue", {70, 130, 180}}, - {"steelblue1", {99, 184, 255}}, - {"steelblue2", {92, 172, 238}}, - {"steelblue3", {79, 148, 205}}, - {"steelblue4", {54, 100, 139}}, - {"tan", {210, 180, 140}}, - {"tan1", {255, 165, 79}}, - {"tan2", {238, 154, 73}}, - {"tan3", {205, 133, 63}}, - {"tan4", {139, 90, 43}}, - {"teal", {0, 128, 128}}, - {"thistle", {216, 191, 216}}, - {"thistle1", {255, 225, 255}}, - {"thistle2", {238, 210, 238}}, - {"thistle3", {205, 181, 205}}, - {"thistle4", {139, 123, 139}}, - {"tomato", {255, 99, 71}}, - {"tomato1", {255, 99, 71}}, - {"tomato2", {238, 92, 66}}, - {"tomato3", {205, 79, 57}}, - {"tomato4", {139, 54, 38}}, - {"turquoise", {64, 224, 208}}, - {"turquoise1", {0, 245, 255}}, - {"turquoise2", {0, 229, 238}}, - {"turquoise3", {0, 197, 205}}, - {"turquoise4", {0, 134, 139}}, - {"violet", {238, 130, 238}}, - {"violetred", {208, 32, 144}}, - {"violetred1", {255, 62, 150}}, - {"violetred2", {238, 58, 140}}, - {"violetred3", {205, 50, 120}}, - {"violetred4", {139, 34, 82}}, - {"webgray", {128, 128, 128}}, - {"webgreen", {0, 128, 0}}, - {"webgrey", {128, 128, 128}}, - {"webmaroon", {128, 0, 0}}, - {"webpurple", {128, 0, 128}}, - {"wheat", {245, 222, 179}}, - {"wheat1", {255, 231, 186}}, - {"wheat2", {238, 216, 174}}, - {"wheat3", {205, 186, 150}}, - {"wheat4", {139, 126, 102}}, - {"white", {255, 255, 255}}, - {"whitesmoke", {245, 245, 245}}, - {"x11gray", {190, 190, 190}}, - {"x11green", {0, 255, 0}}, - {"x11grey", {190, 190, 190}}, - {"x11maroon", {176, 48, 96}}, - {"x11purple", {160, 32, 240}}, - {"yellow", {255, 255, 0}}, - {"yellow1", {255, 255, 0}}, - {"yellow2", {238, 238, 0}}, - {"yellow3", {205, 205, 0}}, - {"yellow4", {139, 139, 0}}, - {"yellowgreen", {154, 205, 50}}, - {"activeborder", {180, 180, 180}}, - {"activecaption", {153, 180, 209}}, - {"appworkspace", {171, 171, 171}}, - {"background", {0, 0, 0}}, - {"buttonhighlight", {255, 255, 255}}, - {"buttonshadow", {160, 160, 160}}, - {"captiontext", {0, 0, 0}}, - {"inactiveborder", {244, 247, 252}}, - {"inactivecaption", {191, 205, 219}}, - {"inactivecaptiontext", {0, 0, 0}}, - {"infobackground", {255, 255, 225}}, - {"infotext", {0, 0, 0}}, - {"menu", {240, 240, 240}}, - {"menutext", {0, 0, 0}}, - {"scrollbar", {200, 200, 200}}, - {"threeddarkshadow", {0, 0, 0}}, - {"threedface", {0, 0, 0}}, - {"threedhighlight", {0, 0, 0}}, - {"threedlightshadow", {0, 0, 0}}, - {"threedshadow", {0, 0, 0}}, - {"transparent", {0, 0, 0, 0}}, - {"window", {255, 255, 255}}, - {"windowframe", {100, 100, 100}}, - {"windowtext", {0, 0, 0}}, + {"aliceblue", {240, 248, 255}}, + {"antiquewhite", {250, 235, 215}}, + {"antiquewhite1", {255, 239, 219}}, + {"antiquewhite2", {238, 223, 204}}, + {"antiquewhite3", {205, 192, 176}}, + {"antiquewhite4", {139, 131, 120}}, + {"aqua", {0, 255, 255}}, + {"aquamarine", {127, 255, 212}}, + {"aquamarine1", {127, 255, 212}}, + {"aquamarine2", {118, 238, 198}}, + {"aquamarine3", {102, 205, 170}}, + {"aquamarine4", {69, 139, 116}}, + {"azure", {240, 255, 255}}, + {"azure1", {240, 255, 255}}, + {"azure2", {224, 238, 238}}, + {"azure3", {193, 205, 205}}, + {"azure4", {131, 139, 139}}, + {"beige", {245, 245, 220}}, + {"bisque", {255, 228, 196}}, + {"bisque1", {255, 228, 196}}, + {"bisque2", {238, 213, 183}}, + {"bisque3", {205, 183, 158}}, + {"bisque4", {139, 125, 107}}, + {"black", {0, 0, 0}}, + {"blanchedalmond", {255, 235, 205}}, + {"blue", {0, 0, 255}}, + {"blue1", {0, 0, 255}}, + {"blue2", {0, 0, 238}}, + {"blue3", {0, 0, 205}}, + {"blue4", {0, 0, 139}}, + {"blueviolet", {138, 43, 226}}, + {"brown", {165, 42, 42}}, + {"brown1", {255, 64, 64}}, + {"brown2", {238, 59, 59}}, + {"brown3", {205, 51, 51}}, + {"brown4", {139, 35, 35}}, + {"burlywood", {222, 184, 135}}, + {"burlywood1", {255, 211, 155}}, + {"burlywood2", {238, 197, 145}}, + {"burlywood3", {205, 170, 125}}, + {"burlywood4", {139, 115, 85}}, + {"cadetblue", {95, 158, 160}}, + {"cadetblue1", {152, 245, 255}}, + {"cadetblue2", {142, 229, 238}}, + {"cadetblue3", {122, 197, 205}}, + {"cadetblue4", {83, 134, 139}}, + {"chartreuse", {127, 255, 0}}, + {"chartreuse1", {127, 255, 0}}, + {"chartreuse2", {118, 238, 0}}, + {"chartreuse3", {102, 205, 0}}, + {"chartreuse4", {69, 139, 0}}, + {"chocolate", {210, 105, 30}}, + {"chocolate1", {255, 127, 36}}, + {"chocolate2", {238, 118, 33}}, + {"chocolate3", {205, 102, 29}}, + {"chocolate4", {139, 69, 19}}, + {"coral", {255, 127, 80}}, + {"coral1", {255, 114, 86}}, + {"coral2", {238, 106, 80}}, + {"coral3", {205, 91, 69}}, + {"coral4", {139, 62, 47}}, + {"cornflowerblue", {100, 149, 237}}, + {"cornsilk", {255, 248, 220}}, + {"cornsilk1", {255, 248, 220}}, + {"cornsilk2", {238, 232, 205}}, + {"cornsilk3", {205, 200, 177}}, + {"cornsilk4", {139, 136, 120}}, + {"crimson", {220, 20, 60}}, + {"cyan", {0, 255, 255}}, + {"cyan1", {0, 255, 255}}, + {"cyan2", {0, 238, 238}}, + {"cyan3", {0, 205, 205}}, + {"cyan4", {0, 139, 139}}, + {"darkblue", {0, 0, 139}}, + {"darkcyan", {0, 139, 139}}, + {"darkgoldenrod", {184, 134, 11}}, + {"darkgoldenrod1", {255, 185, 15}}, + {"darkgoldenrod2", {238, 173, 14}}, + {"darkgoldenrod3", {205, 149, 12}}, + {"darkgoldenrod4", {139, 101, 8}}, + {"darkgray", {169, 169, 169}}, + {"darkgreen", {0, 100, 0}}, + {"darkgrey", {169, 169, 169}}, + {"darkkhaki", {189, 183, 107}}, + {"darkmagenta", {139, 0, 139}}, + {"darkolivegreen", {85, 107, 47}}, + {"darkolivegreen1", {202, 255, 112}}, + {"darkolivegreen2", {188, 238, 104}}, + {"darkolivegreen3", {162, 205, 90}}, + {"darkolivegreen4", {110, 139, 61}}, + {"darkorange", {255, 140, 0}}, + {"darkorange1", {255, 127, 0}}, + {"darkorange2", {238, 118, 0}}, + {"darkorange3", {205, 102, 0}}, + {"darkorange4", {139, 69, 0}}, + {"darkorchid", {153, 50, 204}}, + {"darkorchid1", {191, 62, 255}}, + {"darkorchid2", {178, 58, 238}}, + {"darkorchid3", {154, 50, 205}}, + {"darkorchid4", {104, 34, 139}}, + {"darkred", {139, 0, 0}}, + {"darksalmon", {233, 150, 122}}, + {"darkseagreen", {143, 188, 143}}, + {"darkseagreen1", {193, 255, 193}}, + {"darkseagreen2", {180, 238, 180}}, + {"darkseagreen3", {155, 205, 155}}, + {"darkseagreen4", {105, 139, 105}}, + {"darkslateblue", {72, 61, 139}}, + {"darkslategray", {47, 79, 79}}, + {"darkslategray1", {151, 255, 255}}, + {"darkslategray2", {141, 238, 238}}, + {"darkslategray3", {121, 205, 205}}, + {"darkslategray4", {82, 139, 139}}, + {"darkslategrey", {47, 79, 79}}, + {"darkturquoise", {0, 206, 209}}, + {"darkviolet", {148, 0, 211}}, + {"deeppink", {255, 20, 147}}, + {"deeppink1", {255, 20, 147}}, + {"deeppink2", {238, 18, 137}}, + {"deeppink3", {205, 16, 118}}, + {"deeppink4", {139, 10, 80}}, + {"deepskyblue", {0, 191, 255}}, + {"deepskyblue1", {0, 191, 255}}, + {"deepskyblue2", {0, 178, 238}}, + {"deepskyblue3", {0, 154, 205}}, + {"deepskyblue4", {0, 104, 139}}, + {"dimgray", {105, 105, 105}}, + {"dimgrey", {105, 105, 105}}, + {"dodgerblue", {30, 144, 255}}, + {"dodgerblue1", {30, 144, 255}}, + {"dodgerblue2", {28, 134, 238}}, + {"dodgerblue3", {24, 116, 205}}, + {"dodgerblue4", {16, 78, 139}}, + {"firebrick", {178, 34, 34}}, + {"firebrick1", {255, 48, 48}}, + {"firebrick2", {238, 44, 44}}, + {"firebrick3", {205, 38, 38}}, + {"firebrick4", {139, 26, 26}}, + {"floralwhite", {255, 250, 240}}, + {"forestgreen", {34, 139, 34}}, + {"fuchsia", {255, 0, 255}}, + {"gainsboro", {220, 220, 220}}, + {"ghostwhite", {248, 248, 255}}, + {"gold", {255, 215, 0}}, + {"gold1", {255, 215, 0}}, + {"gold2", {238, 201, 0}}, + {"gold3", {205, 173, 0}}, + {"gold4", {139, 117, 0}}, + {"goldenrod", {218, 165, 32}}, + {"goldenrod1", {255, 193, 37}}, + {"goldenrod2", {238, 180, 34}}, + {"goldenrod3", {205, 155, 29}}, + {"goldenrod4", {139, 105, 20}}, + {"gray", {190, 190, 190}}, + {"gray0", {0, 0, 0}}, + {"gray1", {3, 3, 3}}, + {"gray10", {26, 26, 26}}, + {"gray100", {255, 255, 255}}, + {"gray11", {28, 28, 28}}, + {"gray12", {31, 31, 31}}, + {"gray13", {33, 33, 33}}, + {"gray14", {36, 36, 36}}, + {"gray15", {38, 38, 38}}, + {"gray16", {41, 41, 41}}, + {"gray17", {43, 43, 43}}, + {"gray18", {46, 46, 46}}, + {"gray19", {48, 48, 48}}, + {"gray2", {5, 5, 5}}, + {"gray20", {51, 51, 51}}, + {"gray21", {54, 54, 54}}, + {"gray22", {56, 56, 56}}, + {"gray23", {59, 59, 59}}, + {"gray24", {61, 61, 61}}, + {"gray25", {64, 64, 64}}, + {"gray26", {66, 66, 66}}, + {"gray27", {69, 69, 69}}, + {"gray28", {71, 71, 71}}, + {"gray29", {74, 74, 74}}, + {"gray3", {8, 8, 8}}, + {"gray30", {77, 77, 77}}, + {"gray31", {79, 79, 79}}, + {"gray32", {82, 82, 82}}, + {"gray33", {84, 84, 84}}, + {"gray34", {87, 87, 87}}, + {"gray35", {89, 89, 89}}, + {"gray36", {92, 92, 92}}, + {"gray37", {94, 94, 94}}, + {"gray38", {97, 97, 97}}, + {"gray39", {99, 99, 99}}, + {"gray4", {10, 10, 10}}, + {"gray40", {102, 102, 102}}, + {"gray41", {105, 105, 105}}, + {"gray42", {107, 107, 107}}, + {"gray43", {110, 110, 110}}, + {"gray44", {112, 112, 112}}, + {"gray45", {115, 115, 115}}, + {"gray46", {117, 117, 117}}, + {"gray47", {120, 120, 120}}, + {"gray48", {122, 122, 122}}, + {"gray49", {125, 125, 125}}, + {"gray5", {13, 13, 13}}, + {"gray50", {127, 127, 127}}, + {"gray51", {130, 130, 130}}, + {"gray52", {133, 133, 133}}, + {"gray53", {135, 135, 135}}, + {"gray54", {138, 138, 138}}, + {"gray55", {140, 140, 140}}, + {"gray56", {143, 143, 143}}, + {"gray57", {145, 145, 145}}, + {"gray58", {148, 148, 148}}, + {"gray59", {150, 150, 150}}, + {"gray6", {15, 15, 15}}, + {"gray60", {153, 153, 153}}, + {"gray61", {156, 156, 156}}, + {"gray62", {158, 158, 158}}, + {"gray63", {161, 161, 161}}, + {"gray64", {163, 163, 163}}, + {"gray65", {166, 166, 166}}, + {"gray66", {168, 168, 168}}, + {"gray67", {171, 171, 171}}, + {"gray68", {173, 173, 173}}, + {"gray69", {176, 176, 176}}, + {"gray7", {18, 18, 18}}, + {"gray70", {179, 179, 179}}, + {"gray71", {181, 181, 181}}, + {"gray72", {184, 184, 184}}, + {"gray73", {186, 186, 186}}, + {"gray74", {189, 189, 189}}, + {"gray75", {191, 191, 191}}, + {"gray76", {194, 194, 194}}, + {"gray77", {196, 196, 196}}, + {"gray78", {199, 199, 199}}, + {"gray79", {201, 201, 201}}, + {"gray8", {20, 20, 20}}, + {"gray80", {204, 204, 204}}, + {"gray81", {207, 207, 207}}, + {"gray82", {209, 209, 209}}, + {"gray83", {212, 212, 212}}, + {"gray84", {214, 214, 214}}, + {"gray85", {217, 217, 217}}, + {"gray86", {219, 219, 219}}, + {"gray87", {222, 222, 222}}, + {"gray88", {224, 224, 224}}, + {"gray89", {227, 227, 227}}, + {"gray9", {23, 23, 23}}, + {"gray90", {229, 229, 229}}, + {"gray91", {232, 232, 232}}, + {"gray92", {235, 235, 235}}, + {"gray93", {237, 237, 237}}, + {"gray94", {240, 240, 240}}, + {"gray95", {242, 242, 242}}, + {"gray96", {245, 245, 245}}, + {"gray97", {247, 247, 247}}, + {"gray98", {250, 250, 250}}, + {"gray99", {252, 252, 252}}, + {"green", {0, 255, 0}}, + {"green1", {0, 255, 0}}, + {"green2", {0, 238, 0}}, + {"green3", {0, 205, 0}}, + {"green4", {0, 139, 0}}, + {"greenyellow", {173, 255, 47}}, + {"grey", {190, 190, 190}}, + {"grey0", {0, 0, 0}}, + {"grey1", {3, 3, 3}}, + {"grey10", {26, 26, 26}}, + {"grey100", {255, 255, 255}}, + {"grey11", {28, 28, 28}}, + {"grey12", {31, 31, 31}}, + {"grey13", {33, 33, 33}}, + {"grey14", {36, 36, 36}}, + {"grey15", {38, 38, 38}}, + {"grey16", {41, 41, 41}}, + {"grey17", {43, 43, 43}}, + {"grey18", {46, 46, 46}}, + {"grey19", {48, 48, 48}}, + {"grey2", {5, 5, 5}}, + {"grey20", {51, 51, 51}}, + {"grey21", {54, 54, 54}}, + {"grey22", {56, 56, 56}}, + {"grey23", {59, 59, 59}}, + {"grey24", {61, 61, 61}}, + {"grey25", {64, 64, 64}}, + {"grey26", {66, 66, 66}}, + {"grey27", {69, 69, 69}}, + {"grey28", {71, 71, 71}}, + {"grey29", {74, 74, 74}}, + {"grey3", {8, 8, 8}}, + {"grey30", {77, 77, 77}}, + {"grey31", {79, 79, 79}}, + {"grey32", {82, 82, 82}}, + {"grey33", {84, 84, 84}}, + {"grey34", {87, 87, 87}}, + {"grey35", {89, 89, 89}}, + {"grey36", {92, 92, 92}}, + {"grey37", {94, 94, 94}}, + {"grey38", {97, 97, 97}}, + {"grey39", {99, 99, 99}}, + {"grey4", {10, 10, 10}}, + {"grey40", {102, 102, 102}}, + {"grey41", {105, 105, 105}}, + {"grey42", {107, 107, 107}}, + {"grey43", {110, 110, 110}}, + {"grey44", {112, 112, 112}}, + {"grey45", {115, 115, 115}}, + {"grey46", {117, 117, 117}}, + {"grey47", {120, 120, 120}}, + {"grey48", {122, 122, 122}}, + {"grey49", {125, 125, 125}}, + {"grey5", {13, 13, 13}}, + {"grey50", {127, 127, 127}}, + {"grey51", {130, 130, 130}}, + {"grey52", {133, 133, 133}}, + {"grey53", {135, 135, 135}}, + {"grey54", {138, 138, 138}}, + {"grey55", {140, 140, 140}}, + {"grey56", {143, 143, 143}}, + {"grey57", {145, 145, 145}}, + {"grey58", {148, 148, 148}}, + {"grey59", {150, 150, 150}}, + {"grey6", {15, 15, 15}}, + {"grey60", {153, 153, 153}}, + {"grey61", {156, 156, 156}}, + {"grey62", {158, 158, 158}}, + {"grey63", {161, 161, 161}}, + {"grey64", {163, 163, 163}}, + {"grey65", {166, 166, 166}}, + {"grey66", {168, 168, 168}}, + {"grey67", {171, 171, 171}}, + {"grey68", {173, 173, 173}}, + {"grey69", {176, 176, 176}}, + {"grey7", {18, 18, 18}}, + {"grey70", {179, 179, 179}}, + {"grey71", {181, 181, 181}}, + {"grey72", {184, 184, 184}}, + {"grey73", {186, 186, 186}}, + {"grey74", {189, 189, 189}}, + {"grey75", {191, 191, 191}}, + {"grey76", {194, 194, 194}}, + {"grey77", {196, 196, 196}}, + {"grey78", {199, 199, 199}}, + {"grey79", {201, 201, 201}}, + {"grey8", {20, 20, 20}}, + {"grey80", {204, 204, 204}}, + {"grey81", {207, 207, 207}}, + {"grey82", {209, 209, 209}}, + {"grey83", {212, 212, 212}}, + {"grey84", {214, 214, 214}}, + {"grey85", {217, 217, 217}}, + {"grey86", {219, 219, 219}}, + {"grey87", {222, 222, 222}}, + {"grey88", {224, 224, 224}}, + {"grey89", {227, 227, 227}}, + {"grey9", {23, 23, 23}}, + {"grey90", {229, 229, 229}}, + {"grey91", {232, 232, 232}}, + {"grey92", {235, 235, 235}}, + {"grey93", {237, 237, 237}}, + {"grey94", {240, 240, 240}}, + {"grey95", {242, 242, 242}}, + {"grey96", {245, 245, 245}}, + {"grey97", {247, 247, 247}}, + {"grey98", {250, 250, 250}}, + {"grey99", {252, 252, 252}}, + {"honeydew", {240, 255, 240}}, + {"honeydew1", {240, 255, 240}}, + {"honeydew2", {224, 238, 224}}, + {"honeydew3", {193, 205, 193}}, + {"honeydew4", {131, 139, 131}}, + {"hotpink", {255, 105, 180}}, + {"hotpink1", {255, 110, 180}}, + {"hotpink2", {238, 106, 167}}, + {"hotpink3", {205, 96, 144}}, + {"hotpink4", {139, 58, 98}}, + {"indianred", {205, 92, 92}}, + {"indianred1", {255, 106, 106}}, + {"indianred2", {238, 99, 99}}, + {"indianred3", {205, 85, 85}}, + {"indianred4", {139, 58, 58}}, + {"indigo", {75, 0, 130}}, + {"ivory", {255, 255, 240}}, + {"ivory1", {255, 255, 240}}, + {"ivory2", {238, 238, 224}}, + {"ivory3", {205, 205, 193}}, + {"ivory4", {139, 139, 131}}, + {"khaki", {240, 230, 140}}, + {"khaki1", {255, 246, 143}}, + {"khaki2", {238, 230, 133}}, + {"khaki3", {205, 198, 115}}, + {"khaki4", {139, 134, 78}}, + {"lavender", {230, 230, 250}}, + {"lavenderblush", {255, 240, 245}}, + {"lavenderblush1", {255, 240, 245}}, + {"lavenderblush2", {238, 224, 229}}, + {"lavenderblush3", {205, 193, 197}}, + {"lavenderblush4", {139, 131, 134}}, + {"lawngreen", {124, 252, 0}}, + {"lemonchiffon", {255, 250, 205}}, + {"lemonchiffon1", {255, 250, 205}}, + {"lemonchiffon2", {238, 233, 191}}, + {"lemonchiffon3", {205, 201, 165}}, + {"lemonchiffon4", {139, 137, 112}}, + {"lightblue", {173, 216, 230}}, + {"lightblue1", {191, 239, 255}}, + {"lightblue2", {178, 223, 238}}, + {"lightblue3", {154, 192, 205}}, + {"lightblue4", {104, 131, 139}}, + {"lightcoral", {240, 128, 128}}, + {"lightcyan", {224, 255, 255}}, + {"lightcyan1", {224, 255, 255}}, + {"lightcyan2", {209, 238, 238}}, + {"lightcyan3", {180, 205, 205}}, + {"lightcyan4", {122, 139, 139}}, + {"lightgoldenrod", {238, 221, 130}}, + {"lightgoldenrod1", {255, 236, 139}}, + {"lightgoldenrod2", {238, 220, 130}}, + {"lightgoldenrod3", {205, 190, 112}}, + {"lightgoldenrod4", {139, 129, 76}}, + {"lightgoldenrodyellow", {250, 250, 210}}, + {"lightgray", {211, 211, 211}}, + {"lightgreen", {144, 238, 144}}, + {"lightgrey", {211, 211, 211}}, + {"lightpink", {255, 182, 193}}, + {"lightpink1", {255, 174, 185}}, + {"lightpink2", {238, 162, 173}}, + {"lightpink3", {205, 140, 149}}, + {"lightpink4", {139, 95, 101}}, + {"lightsalmon", {255, 160, 122}}, + {"lightsalmon1", {255, 160, 122}}, + {"lightsalmon2", {238, 149, 114}}, + {"lightsalmon3", {205, 129, 98}}, + {"lightsalmon4", {139, 87, 66}}, + {"lightseagreen", {32, 178, 170}}, + {"lightskyblue", {135, 206, 250}}, + {"lightskyblue1", {176, 226, 255}}, + {"lightskyblue2", {164, 211, 238}}, + {"lightskyblue3", {141, 182, 205}}, + {"lightskyblue4", {96, 123, 139}}, + {"lightslateblue", {132, 112, 255}}, + {"lightslategray", {119, 136, 153}}, + {"lightslategrey", {119, 136, 153}}, + {"lightsteelblue", {176, 196, 222}}, + {"lightsteelblue1", {202, 225, 255}}, + {"lightsteelblue2", {188, 210, 238}}, + {"lightsteelblue3", {162, 181, 205}}, + {"lightsteelblue4", {110, 123, 139}}, + {"lightyellow", {255, 255, 224}}, + {"lightyellow1", {255, 255, 224}}, + {"lightyellow2", {238, 238, 209}}, + {"lightyellow3", {205, 205, 180}}, + {"lightyellow4", {139, 139, 122}}, + {"lime", {0, 255, 0}}, + {"limegreen", {50, 205, 50}}, + {"linen", {250, 240, 230}}, + {"magenta", {255, 0, 255}}, + {"magenta1", {255, 0, 255}}, + {"magenta2", {238, 0, 238}}, + {"magenta3", {205, 0, 205}}, + {"magenta4", {139, 0, 139}}, + {"maroon", {176, 48, 96}}, + {"maroon1", {255, 52, 179}}, + {"maroon2", {238, 48, 167}}, + {"maroon3", {205, 41, 144}}, + {"maroon4", {139, 28, 98}}, + {"mediumaquamarine", {102, 205, 170}}, + {"mediumblue", {0, 0, 205}}, + {"mediumorchid", {186, 85, 211}}, + {"mediumorchid1", {224, 102, 255}}, + {"mediumorchid2", {209, 95, 238}}, + {"mediumorchid3", {180, 82, 205}}, + {"mediumorchid4", {122, 55, 139}}, + {"mediumpurple", {147, 112, 219}}, + {"mediumpurple1", {171, 130, 255}}, + {"mediumpurple2", {159, 121, 238}}, + {"mediumpurple3", {137, 104, 205}}, + {"mediumpurple4", {93, 71, 139}}, + {"mediumseagreen", {60, 179, 113}}, + {"mediumslateblue", {123, 104, 238}}, + {"mediumspringgreen", {0, 250, 154}}, + {"mediumturquoise", {72, 209, 204}}, + {"mediumvioletred", {199, 21, 133}}, + {"midnightblue", {25, 25, 112}}, + {"mintcream", {245, 255, 250}}, + {"mistyrose", {255, 228, 225}}, + {"mistyrose1", {255, 228, 225}}, + {"mistyrose2", {238, 213, 210}}, + {"mistyrose3", {205, 183, 181}}, + {"mistyrose4", {139, 125, 123}}, + {"moccasin", {255, 228, 181}}, + {"navajowhite", {255, 222, 173}}, + {"navajowhite1", {255, 222, 173}}, + {"navajowhite2", {238, 207, 161}}, + {"navajowhite3", {205, 179, 139}}, + {"navajowhite4", {139, 121, 94}}, + {"navy", {0, 0, 128}}, + {"navyblue", {0, 0, 128}}, + {"oldlace", {253, 245, 230}}, + {"olive", {128, 128, 0}}, + {"olivedrab", {107, 142, 35}}, + {"olivedrab1", {192, 255, 62}}, + {"olivedrab2", {179, 238, 58}}, + {"olivedrab3", {154, 205, 50}}, + {"olivedrab4", {105, 139, 34}}, + {"orange", {255, 165, 0}}, + {"orange1", {255, 165, 0}}, + {"orange2", {238, 154, 0}}, + {"orange3", {205, 133, 0}}, + {"orange4", {139, 90, 0}}, + {"orangered", {255, 69, 0}}, + {"orangered1", {255, 69, 0}}, + {"orangered2", {238, 64, 0}}, + {"orangered3", {205, 55, 0}}, + {"orangered4", {139, 37, 0}}, + {"orchid", {218, 112, 214}}, + {"orchid1", {255, 131, 250}}, + {"orchid2", {238, 122, 233}}, + {"orchid3", {205, 105, 201}}, + {"orchid4", {139, 71, 137}}, + {"palegoldenrod", {238, 232, 170}}, + {"palegreen", {152, 251, 152}}, + {"palegreen1", {154, 255, 154}}, + {"palegreen2", {144, 238, 144}}, + {"palegreen3", {124, 205, 124}}, + {"palegreen4", {84, 139, 84}}, + {"paleturquoise", {175, 238, 238}}, + {"paleturquoise1", {187, 255, 255}}, + {"paleturquoise2", {174, 238, 238}}, + {"paleturquoise3", {150, 205, 205}}, + {"paleturquoise4", {102, 139, 139}}, + {"palevioletred", {219, 112, 147}}, + {"palevioletred1", {255, 130, 171}}, + {"palevioletred2", {238, 121, 159}}, + {"palevioletred3", {205, 104, 137}}, + {"palevioletred4", {139, 71, 93}}, + {"papayawhip", {255, 239, 213}}, + {"peachpuff", {255, 218, 185}}, + {"peachpuff1", {255, 218, 185}}, + {"peachpuff2", {238, 203, 173}}, + {"peachpuff3", {205, 175, 149}}, + {"peachpuff4", {139, 119, 101}}, + {"peru", {205, 133, 63}}, + {"pink", {255, 192, 203}}, + {"pink1", {255, 181, 197}}, + {"pink2", {238, 169, 184}}, + {"pink3", {205, 145, 158}}, + {"pink4", {139, 99, 108}}, + {"plum", {221, 160, 221}}, + {"plum1", {255, 187, 255}}, + {"plum2", {238, 174, 238}}, + {"plum3", {205, 150, 205}}, + {"plum4", {139, 102, 139}}, + {"powderblue", {176, 224, 230}}, + {"purple", {160, 32, 240}}, + {"purple1", {155, 48, 255}}, + {"purple2", {145, 44, 238}}, + {"purple3", {125, 38, 205}}, + {"purple4", {85, 26, 139}}, + {"rebeccapurple", {102, 51, 153}}, + {"red", {255, 0, 0}}, + {"red1", {255, 0, 0}}, + {"red2", {238, 0, 0}}, + {"red3", {205, 0, 0}}, + {"red4", {139, 0, 0}}, + {"rosybrown", {188, 143, 143}}, + {"rosybrown1", {255, 193, 193}}, + {"rosybrown2", {238, 180, 180}}, + {"rosybrown3", {205, 155, 155}}, + {"rosybrown4", {139, 105, 105}}, + {"royalblue", {65, 105, 225}}, + {"royalblue1", {72, 118, 255}}, + {"royalblue2", {67, 110, 238}}, + {"royalblue3", {58, 95, 205}}, + {"royalblue4", {39, 64, 139}}, + {"saddlebrown", {139, 69, 19}}, + {"salmon", {250, 128, 114}}, + {"salmon1", {255, 140, 105}}, + {"salmon2", {238, 130, 98}}, + {"salmon3", {205, 112, 84}}, + {"salmon4", {139, 76, 57}}, + {"sandybrown", {244, 164, 96}}, + {"seagreen", {46, 139, 87}}, + {"seagreen1", {84, 255, 159}}, + {"seagreen2", {78, 238, 148}}, + {"seagreen3", {67, 205, 128}}, + {"seagreen4", {46, 139, 87}}, + {"seashell", {255, 245, 238}}, + {"seashell1", {255, 245, 238}}, + {"seashell2", {238, 229, 222}}, + {"seashell3", {205, 197, 191}}, + {"seashell4", {139, 134, 130}}, + {"sienna", {160, 82, 45}}, + {"sienna1", {255, 130, 71}}, + {"sienna2", {238, 121, 66}}, + {"sienna3", {205, 104, 57}}, + {"sienna4", {139, 71, 38}}, + {"silver", {192, 192, 192}}, + {"skyblue", {135, 206, 235}}, + {"skyblue1", {135, 206, 255}}, + {"skyblue2", {126, 192, 238}}, + {"skyblue3", {108, 166, 205}}, + {"skyblue4", {74, 112, 139}}, + {"slateblue", {106, 90, 205}}, + {"slateblue1", {131, 111, 255}}, + {"slateblue2", {122, 103, 238}}, + {"slateblue3", {105, 89, 205}}, + {"slateblue4", {71, 60, 139}}, + {"slategray", {112, 128, 144}}, + {"slategray1", {198, 226, 255}}, + {"slategray2", {185, 211, 238}}, + {"slategray3", {159, 182, 205}}, + {"slategray4", {108, 123, 139}}, + {"slategrey", {112, 128, 144}}, + {"snow", {255, 250, 250}}, + {"snow1", {255, 250, 250}}, + {"snow2", {238, 233, 233}}, + {"snow3", {205, 201, 201}}, + {"snow4", {139, 137, 137}}, + {"springgreen", {0, 255, 127}}, + {"springgreen1", {0, 255, 127}}, + {"springgreen2", {0, 238, 118}}, + {"springgreen3", {0, 205, 102}}, + {"springgreen4", {0, 139, 69}}, + {"steelblue", {70, 130, 180}}, + {"steelblue1", {99, 184, 255}}, + {"steelblue2", {92, 172, 238}}, + {"steelblue3", {79, 148, 205}}, + {"steelblue4", {54, 100, 139}}, + {"tan", {210, 180, 140}}, + {"tan1", {255, 165, 79}}, + {"tan2", {238, 154, 73}}, + {"tan3", {205, 133, 63}}, + {"tan4", {139, 90, 43}}, + {"teal", {0, 128, 128}}, + {"thistle", {216, 191, 216}}, + {"thistle1", {255, 225, 255}}, + {"thistle2", {238, 210, 238}}, + {"thistle3", {205, 181, 205}}, + {"thistle4", {139, 123, 139}}, + {"tomato", {255, 99, 71}}, + {"tomato1", {255, 99, 71}}, + {"tomato2", {238, 92, 66}}, + {"tomato3", {205, 79, 57}}, + {"tomato4", {139, 54, 38}}, + {"turquoise", {64, 224, 208}}, + {"turquoise1", {0, 245, 255}}, + {"turquoise2", {0, 229, 238}}, + {"turquoise3", {0, 197, 205}}, + {"turquoise4", {0, 134, 139}}, + {"violet", {238, 130, 238}}, + {"violetred", {208, 32, 144}}, + {"violetred1", {255, 62, 150}}, + {"violetred2", {238, 58, 140}}, + {"violetred3", {205, 50, 120}}, + {"violetred4", {139, 34, 82}}, + {"webgray", {128, 128, 128}}, + {"webgreen", {0, 128, 0}}, + {"webgrey", {128, 128, 128}}, + {"webmaroon", {128, 0, 0}}, + {"webpurple", {128, 0, 128}}, + {"wheat", {245, 222, 179}}, + {"wheat1", {255, 231, 186}}, + {"wheat2", {238, 216, 174}}, + {"wheat3", {205, 186, 150}}, + {"wheat4", {139, 126, 102}}, + {"white", {255, 255, 255}}, + {"whitesmoke", {245, 245, 245}}, + {"x11gray", {190, 190, 190}}, + {"x11green", {0, 255, 0}}, + {"x11grey", {190, 190, 190}}, + {"x11maroon", {176, 48, 96}}, + {"x11purple", {160, 32, 240}}, + {"yellow", {255, 255, 0}}, + {"yellow1", {255, 255, 0}}, + {"yellow2", {238, 238, 0}}, + {"yellow3", {205, 205, 0}}, + {"yellow4", {139, 139, 0}}, + {"yellowgreen", {154, 205, 50}}, + {"activeborder", {180, 180, 180}}, + {"activecaption", {153, 180, 209}}, + {"appworkspace", {171, 171, 171}}, + {"background", {0, 0, 0}}, + {"buttonhighlight", {255, 255, 255}}, + {"buttonshadow", {160, 160, 160}}, + {"captiontext", {0, 0, 0}}, + {"inactiveborder", {244, 247, 252}}, + {"inactivecaption", {191, 205, 219}}, + {"inactivecaptiontext", {0, 0, 0}}, + {"infobackground", {255, 255, 225}}, + {"infotext", {0, 0, 0}}, + {"menu", {240, 240, 240}}, + {"menutext", {0, 0, 0}}, + {"scrollbar", {200, 200, 200}}, + {"threeddarkshadow", {0, 0, 0}}, + {"threedface", {0, 0, 0}}, + {"threedhighlight", {0, 0, 0}}, + {"threedlightshadow", {0, 0, 0}}, + {"threedshadow", {0, 0, 0}}, + {"transparent", {0, 0, 0, 0}}, + {"window", {255, 255, 255}}, + {"windowframe", {100, 100, 100}}, + {"windowtext", {0, 0, 0}}, }; -} +}// namespace rspamd::css -#endif //RSPAMD_CSS_COLORS_LIST_HXX +#endif//RSPAMD_CSS_COLORS_LIST_HXX diff --git a/src/libserver/css/css_parser.cxx b/src/libserver/css/css_parser.cxx index d7d56f3e5..aed035aa4 100644 --- a/src/libserver/css/css_parser.cxx +++ b/src/libserver/css/css_parser.cxx @@ -32,7 +32,8 @@ namespace rspamd::css { const css_consumed_block css_parser_eof_block{}; -auto css_consumed_block::attach_block(consumed_block_ptr &&block) -> bool { +auto css_consumed_block::attach_block(consumed_block_ptr &&block) -> bool +{ if (std::holds_alternative<std::monostate>(content)) { /* Switch from monostate */ content = std::vector<consumed_block_ptr>(); @@ -48,7 +49,8 @@ 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 { +auto css_consumed_block::add_function_argument(consumed_block_ptr &&block) -> bool +{ if (!std::holds_alternative<css_function_block>(content)) { return false; } @@ -63,7 +65,7 @@ auto css_consumed_block::token_type_str(void) const -> const char * { const auto *ret = ""; - switch(tag) { + switch (tag) { case parser_tag_type::css_top_block: ret = "top"; break; @@ -93,53 +95,54 @@ auto css_consumed_block::token_type_str(void) const -> const char * return ret; } -auto css_consumed_block::debug_str(void) -> std::string { +auto css_consumed_block::debug_str(void) -> std::string +{ std::string ret = fmt::format(R"("type": "{}", "value": )", token_type_str()); - std::visit([&](auto& arg) { - using T = std::decay_t<decltype(arg)>; + std::visit([&](auto &arg) { + using T = std::decay_t<decltype(arg)>; - if constexpr (std::is_same_v<T, std::vector<consumed_block_ptr>>) { - /* Array of blocks */ - ret += "["; - for (const auto &block : arg) { - ret += "{"; - ret += block->debug_str(); - ret += "}, "; - } + if constexpr (std::is_same_v<T, std::vector<consumed_block_ptr>>) { + /* Array of blocks */ + ret += "["; + for (const auto &block: arg) { + ret += "{"; + ret += block->debug_str(); + ret += "}, "; + } - if (*(--ret.end()) == ' ') { - ret.pop_back(); - ret.pop_back(); /* Last ',' */ - } - ret += "]"; - } - else if constexpr (std::is_same_v<T, std::monostate>) { - /* Empty block */ - ret += R"("empty")"; - } - else if constexpr (std::is_same_v<T, css_function_block>) { - ret += R"({ "content": {"token": )"; - ret += "\"" + arg.function.debug_token_str() + "\", "; - ret += R"("arguments": [)"; - - for (const auto &block : arg.args) { - ret += "{"; - ret += block->debug_str(); - ret += "}, "; - } - if (*(--ret.end()) == ' ') { - ret.pop_back(); - ret.pop_back(); /* Last ',' */ - } - ret += "]}}"; - } - else { - /* Single element block */ - ret += "\"" + arg.debug_token_str() + "\""; - } - }, - content); + if (*(--ret.end()) == ' ') { + ret.pop_back(); + ret.pop_back(); /* Last ',' */ + } + ret += "]"; + } + else if constexpr (std::is_same_v<T, std::monostate>) { + /* Empty block */ + ret += R"("empty")"; + } + else if constexpr (std::is_same_v<T, css_function_block>) { + ret += R"({ "content": {"token": )"; + ret += "\"" + arg.function.debug_token_str() + "\", "; + ret += R"("arguments": [)"; + + for (const auto &block: arg.args) { + ret += "{"; + ret += block->debug_str(); + ret += "}, "; + } + if (*(--ret.end()) == ' ') { + ret.pop_back(); + ret.pop_back(); /* Last ',' */ + } + ret += "]}}"; + } + else { + /* Single element block */ + ret += "\"" + arg.debug_token_str() + "\""; + } + }, + content); return ret; } @@ -147,7 +150,9 @@ auto css_consumed_block::debug_str(void) -> std::string { class css_parser { public: css_parser(void) = delete; /* Require mempool to be set for logging */ - explicit css_parser(rspamd_mempool_t *pool) : pool (pool) { + explicit css_parser(rspamd_mempool_t *pool) + : pool(pool) + { style_object.reset(); error.type = css_parse_error_type::PARSE_ERROR_NO_ERROR; } @@ -156,8 +161,9 @@ public: * This constructor captures existing via unique_ptr, but it does not * destruct it on errors (we assume that it is owned somewhere else) */ - explicit css_parser(std::shared_ptr<css_style_sheet> &&existing, rspamd_mempool_t *pool) : - style_object(existing), pool(pool) { + explicit css_parser(std::shared_ptr<css_style_sheet> &&existing, rspamd_mempool_t *pool) + : style_object(existing), pool(pool) + { error.type = css_parse_error_type::PARSE_ERROR_NO_ERROR; } @@ -171,7 +177,8 @@ public: std::unique_ptr<css_consumed_block> consume_css_rule(const std::string_view &sv); std::optional<css_parse_error> consume_input(const std::string_view &sv); - auto get_object_maybe(void) -> tl::expected<std::shared_ptr<css_style_sheet>, css_parse_error> { + auto get_object_maybe(void) -> tl::expected<std::shared_ptr<css_style_sheet>, css_parse_error> + { if (style_object) { return style_object; } @@ -206,13 +213,12 @@ private: /* * Find if we need to unescape css */ -bool -css_parser::need_unescape(const std::string_view &sv) +bool css_parser::need_unescape(const std::string_view &sv) { bool in_quote = false; char quote_char, prev_c = 0; - for (const auto c : sv) { + for (const auto c: sv) { if (!in_quote) { if (c == '"' || c == '\'') { in_quote = true; @@ -240,12 +246,12 @@ auto css_parser::function_consumer(std::unique_ptr<css_consumed_block> &top) -> auto ret = true, want_more = true; msg_debug_css("consume function block; top block: %s, recursion level %d", - top->token_type_str(), rec_level); + top->token_type_str(), rec_level); if (++rec_level > max_rec) { msg_err_css("max nesting reached, ignore style"); error = css_parse_error(css_parse_error_type::PARSE_ERROR_BAD_NESTING, - "maximum nesting has reached when parsing function value"); + "maximum nesting has reached when parsing function value"); return false; } @@ -270,8 +276,8 @@ auto css_parser::function_consumer(std::unique_ptr<css_consumed_block> &top) -> default: /* Attach everything to the function 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))); + css::css_consumed_block::parser_tag_type::css_function_arg, + std::move(next_token))); break; } } @@ -289,18 +295,18 @@ auto css_parser::simple_block_consumer(std::unique_ptr<css_consumed_block> &top, std::unique_ptr<css_consumed_block> block; msg_debug_css("consume simple block; top block: %s, recursion level %d", - top->token_type_str(), rec_level); + top->token_type_str(), rec_level); if (!consume_current && ++rec_level > max_rec) { msg_err_css("max nesting reached, ignore style"); error = css_parse_error(css_parse_error_type::PARSE_ERROR_BAD_NESTING, - "maximum nesting has reached when parsing simple block value"); + "maximum nesting has reached when parsing simple block value"); return false; } if (!consume_current) { block = std::make_unique<css_consumed_block>( - css_consumed_block::parser_tag_type::css_simple_block); + css_consumed_block::parser_tag_type::css_simple_block); } @@ -327,7 +333,7 @@ auto css_parser::simple_block_consumer(std::unique_ptr<css_consumed_block> &top, if (!consume_current && ret) { msg_debug_css("attached node 'simple block' rule %s; length=%d", - block->token_type_str(), (int)block->size()); + block->token_type_str(), (int) block->size()); top->attach_block(std::move(block)); } @@ -341,18 +347,18 @@ auto css_parser::simple_block_consumer(std::unique_ptr<css_consumed_block> &top, auto css_parser::qualified_rule_consumer(std::unique_ptr<css_consumed_block> &top) -> bool { msg_debug_css("consume qualified block; top block: %s, recursion level %d", - top->token_type_str(), rec_level); + top->token_type_str(), rec_level); if (++rec_level > max_rec) { msg_err_css("max nesting reached, ignore style"); error = css_parse_error(css_parse_error_type::PARSE_ERROR_BAD_NESTING, - "maximum nesting has reached when parsing qualified rule value"); + "maximum nesting has reached when parsing qualified rule value"); return false; } auto ret = true, want_more = true; auto block = std::make_unique<css_consumed_block>( - css_consumed_block::parser_tag_type::css_qualified_rule); + css_consumed_block::parser_tag_type::css_qualified_rule); while (ret && want_more && !eof) { auto next_token = tokeniser->next_token(); @@ -367,12 +373,11 @@ auto css_parser::qualified_rule_consumer(std::unique_ptr<css_consumed_block> &to ret = true; } else { - } break; case css_parser_token::token_type::ocurlbrace_token: ret = simple_block_consumer(block, - css_parser_token::token_type::ecurlbrace_token, false); + css_parser_token::token_type::ecurlbrace_token, false); want_more = false; break; case css_parser_token::token_type::whitespace_token: @@ -388,7 +393,7 @@ auto css_parser::qualified_rule_consumer(std::unique_ptr<css_consumed_block> &to if (ret) { if (top->tag == css_consumed_block::parser_tag_type::css_top_block) { msg_debug_css("attached node qualified rule %s; length=%d", - block->token_type_str(), (int)block->size()); + block->token_type_str(), (int) block->size()); top->attach_block(std::move(block)); } } @@ -401,18 +406,18 @@ auto css_parser::qualified_rule_consumer(std::unique_ptr<css_consumed_block> &to auto css_parser::at_rule_consumer(std::unique_ptr<css_consumed_block> &top) -> bool { msg_debug_css("consume at-rule block; top block: %s, recursion level %d", - top->token_type_str(), rec_level); + top->token_type_str(), rec_level); if (++rec_level > max_rec) { msg_err_css("max nesting reached, ignore style"); error = css_parse_error(css_parse_error_type::PARSE_ERROR_BAD_NESTING, - "maximum nesting has reached when parsing at keyword"); + "maximum nesting has reached when parsing at keyword"); return false; } auto ret = true, want_more = true; auto block = std::make_unique<css_consumed_block>( - css_consumed_block::parser_tag_type::css_at_rule); + css_consumed_block::parser_tag_type::css_at_rule); while (ret && want_more && !eof) { auto next_token = tokeniser->next_token(); @@ -427,12 +432,11 @@ auto css_parser::at_rule_consumer(std::unique_ptr<css_consumed_block> &top) -> b ret = true; } else { - } break; case css_parser_token::token_type::ocurlbrace_token: ret = simple_block_consumer(block, - css_parser_token::token_type::ecurlbrace_token, false); + css_parser_token::token_type::ecurlbrace_token, false); want_more = false; break; case css_parser_token::token_type::whitespace_token: @@ -451,7 +455,7 @@ auto css_parser::at_rule_consumer(std::unique_ptr<css_consumed_block> &top) -> b if (ret) { if (top->tag == css_consumed_block::parser_tag_type::css_top_block) { msg_debug_css("attached node qualified rule %s; length=%d", - block->token_type_str(), (int)block->size()); + block->token_type_str(), (int) block->size()); top->attach_block(std::move(block)); } } @@ -467,11 +471,11 @@ auto css_parser::component_value_consumer(std::unique_ptr<css_consumed_block> &t std::unique_ptr<css_consumed_block> block; msg_debug_css("consume component block; top block: %s, recursion level %d", - top->token_type_str(), rec_level); + top->token_type_str(), rec_level); if (++rec_level > max_rec) { error = css_parse_error(css_parse_error_type::PARSE_ERROR_BAD_NESTING, - "maximum nesting has reached when parsing component value"); + "maximum nesting has reached when parsing component value"); return false; } @@ -484,26 +488,26 @@ auto css_parser::component_value_consumer(std::unique_ptr<css_consumed_block> &t break; case css_parser_token::token_type::ocurlbrace_token: block = std::make_unique<css_consumed_block>( - css_consumed_block::parser_tag_type::css_simple_block); + css_consumed_block::parser_tag_type::css_simple_block); ret = simple_block_consumer(block, - css_parser_token::token_type::ecurlbrace_token, - true); + css_parser_token::token_type::ecurlbrace_token, + true); need_more = false; break; case css_parser_token::token_type::obrace_token: block = std::make_unique<css_consumed_block>( - css_consumed_block::parser_tag_type::css_simple_block); + css_consumed_block::parser_tag_type::css_simple_block); ret = simple_block_consumer(block, - css_parser_token::token_type::ebrace_token, - true); + css_parser_token::token_type::ebrace_token, + true); need_more = false; break; case css_parser_token::token_type::osqbrace_token: block = std::make_unique<css_consumed_block>( - css_consumed_block::parser_tag_type::css_simple_block); + css_consumed_block::parser_tag_type::css_simple_block); ret = simple_block_consumer(block, - css_parser_token::token_type::esqbrace_token, - true); + css_parser_token::token_type::esqbrace_token, + true); need_more = false; break; case css_parser_token::token_type::whitespace_token: @@ -512,8 +516,8 @@ auto css_parser::component_value_consumer(std::unique_ptr<css_consumed_block> &t case css_parser_token::token_type::function_token: { need_more = false; block = std::make_unique<css_consumed_block>( - css_consumed_block::parser_tag_type::css_function, - std::move(next_token)); + css_consumed_block::parser_tag_type::css_function, + std::move(next_token)); /* Consume the rest */ ret = function_consumer(block); @@ -521,8 +525,8 @@ auto css_parser::component_value_consumer(std::unique_ptr<css_consumed_block> &t } default: block = std::make_unique<css_consumed_block>( - css_consumed_block::parser_tag_type::css_component, - std::move(next_token)); + css_consumed_block::parser_tag_type::css_component, + std::move(next_token)); need_more = false; break; } @@ -530,7 +534,7 @@ auto css_parser::component_value_consumer(std::unique_ptr<css_consumed_block> &t if (ret && block) { msg_debug_css("attached node component rule %s; length=%d", - block->token_type_str(), (int)block->size()); + block->token_type_str(), (int) block->size()); top->attach_block(std::move(block)); } @@ -539,14 +543,13 @@ auto css_parser::component_value_consumer(std::unique_ptr<css_consumed_block> &t return ret; } -auto -css_parser::consume_css_blocks(const std::string_view &sv) -> std::unique_ptr<css_consumed_block> +auto css_parser::consume_css_blocks(const std::string_view &sv) -> std::unique_ptr<css_consumed_block> { tokeniser = std::make_unique<css_tokeniser>(pool, sv); auto ret = true; auto consumed_blocks = - std::make_unique<css_consumed_block>(css_consumed_block::parser_tag_type::css_top_block); + std::make_unique<css_consumed_block>(css_consumed_block::parser_tag_type::css_top_block); while (!eof && ret) { auto next_token = tokeniser->next_token(); @@ -567,7 +570,6 @@ css_parser::consume_css_blocks(const std::string_view &sv) -> std::unique_ptr<cs ret = qualified_rule_consumer(consumed_blocks); break; } - } tokeniser.reset(nullptr); /* No longer needed */ @@ -575,14 +577,13 @@ css_parser::consume_css_blocks(const std::string_view &sv) -> std::unique_ptr<cs return consumed_blocks; } -auto -css_parser::consume_css_rule(const std::string_view &sv) -> std::unique_ptr<css_consumed_block> +auto css_parser::consume_css_rule(const std::string_view &sv) -> std::unique_ptr<css_consumed_block> { tokeniser = std::make_unique<css_tokeniser>(pool, sv); auto ret = true; auto rule_block = - std::make_unique<css_consumed_block>(css_consumed_block::parser_tag_type::css_simple_block); + std::make_unique<css_consumed_block>(css_consumed_block::parser_tag_type::css_simple_block); while (!eof && ret) { auto next_token = tokeniser->next_token(); @@ -599,7 +600,6 @@ css_parser::consume_css_rule(const std::string_view &sv) -> std::unique_ptr<css_ ret = component_value_consumer(rule_block); break; } - } tokeniser.reset(nullptr); /* No longer needed */ @@ -616,7 +616,7 @@ css_parser::consume_input(const std::string_view &sv) if (rules.empty()) { if (error.type == css_parse_error_type::PARSE_ERROR_NO_ERROR) { return css_parse_error(css_parse_error_type::PARSE_ERROR_EMPTY, - "no css rules consumed"); + "no css rules consumed"); } else { return error; @@ -627,7 +627,7 @@ css_parser::consume_input(const std::string_view &sv) style_object = std::make_shared<css_style_sheet>(pool); } - for (auto &&rule : rules) { + for (auto &&rule: rules) { /* * For now, we do not need any of the at rules, so we can safely ignore them */ @@ -636,9 +636,9 @@ css_parser::consume_input(const std::string_view &sv) 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; - }); + [](auto &bl) { + return bl->tag == css_consumed_block::parser_tag_type::css_simple_block; + }); if (simple_block != children.end()) { /* @@ -650,8 +650,8 @@ css_parser::consume_input(const std::string_view &sv) /* First, tag all components as preamble */ auto selector_it = children.cbegin(); - auto selector_token_functor = [&selector_it,&simple_block](void) - -> const css_consumed_block & { + auto selector_token_functor = [&selector_it, &simple_block](void) + -> const css_consumed_block & { for (;;) { if (selector_it == simple_block) { return css_parser_eof_block; @@ -668,11 +668,11 @@ css_parser::consume_input(const std::string_view &sv) auto selectors_vec = process_selector_tokens(pool, selector_token_functor); if (selectors_vec.size() > 0) { - msg_debug_css("processed %d selectors", (int)selectors_vec.size()); + msg_debug_css("processed %d selectors", (int) selectors_vec.size()); auto decls_it = (*simple_block)->get_blocks_or_empty().cbegin(); auto decls_end = (*simple_block)->get_blocks_or_empty().cend(); auto declaration_token_functor = [&decls_it, &decls_end](void) - -> const css_consumed_block & { + -> const css_consumed_block & { for (;;) { if (decls_it == decls_end) { return css_parser_eof_block; @@ -687,15 +687,15 @@ css_parser::consume_input(const std::string_view &sv) }; auto declarations_vec = process_declaration_tokens(pool, - declaration_token_functor); + declaration_token_functor); if (declarations_vec && !declarations_vec->get_rules().empty()) { msg_debug_css("processed %d rules", - (int)declarations_vec->get_rules().size()); + (int) declarations_vec->get_rules().size()); - for (auto &&selector : selectors_vec) { + for (auto &&selector: selectors_vec) { style_object->add_selector_rule(std::move(selector), - declarations_vec); + declarations_vec); } } } @@ -704,14 +704,13 @@ css_parser::consume_input(const std::string_view &sv) } auto debug_str = consumed_blocks->debug_str(); - msg_debug_css("consumed css: {%*s}", (int)debug_str.size(), debug_str.data()); + msg_debug_css("consumed css: {%*s}", (int) debug_str.size(), debug_str.data()); return std::nullopt; } -auto -get_selectors_parser_functor(rspamd_mempool_t *pool, - const std::string_view &st) -> blocks_gen_functor +auto get_selectors_parser_functor(rspamd_mempool_t *pool, + const std::string_view &st) -> blocks_gen_functor { css_parser parser(pool); @@ -734,7 +733,7 @@ get_selectors_parser_functor(rspamd_mempool_t *pool, * mutable. */ return [cur, consumed_blocks = std::move(consumed_blocks), last](void) mutable - -> const css_consumed_block & { + -> const css_consumed_block & { if (cur != last) { const auto &ret = (*cur); @@ -747,9 +746,8 @@ get_selectors_parser_functor(rspamd_mempool_t *pool, }; } -auto -get_rules_parser_functor(rspamd_mempool_t *pool, - const std::string_view &st) -> blocks_gen_functor +auto get_rules_parser_functor(rspamd_mempool_t *pool, + const std::string_view &st) -> blocks_gen_functor { css_parser parser(pool); @@ -760,7 +758,7 @@ get_rules_parser_functor(rspamd_mempool_t *pool, auto last = rules.end(); return [cur, consumed_blocks = std::move(consumed_blocks), last](void) mutable - -> const css_consumed_block & { + -> const css_consumed_block & { if (cur != last) { const auto &ret = (*cur); @@ -802,8 +800,7 @@ auto parse_css(rspamd_mempool_t *pool, const std::string_view &st, return tl::make_unexpected(maybe_error.value()); } -auto -parse_css_declaration(rspamd_mempool_t *pool, const std::string_view &st) +auto parse_css_declaration(rspamd_mempool_t *pool, const std::string_view &st) -> rspamd::html::html_block * { std::string_view processed_input; @@ -817,7 +814,7 @@ parse_css_declaration(rspamd_mempool_t *pool, const std::string_view &st) processed_input = std::string_view{nspace, nlen}; } auto &&res = process_declaration_tokens(pool, - get_rules_parser_functor(pool, processed_input)); + get_rules_parser_functor(pool, processed_input)); if (res) { return res->compile_to_block(pool); @@ -826,8 +823,10 @@ parse_css_declaration(rspamd_mempool_t *pool, const std::string_view &st) return nullptr; } -TEST_SUITE("css") { - TEST_CASE("parse colors") { +TEST_SUITE("css") +{ + TEST_CASE("parse colors") + { const std::vector<const char *> cases{ "P { CoLoR: rgb(100%, 50%, 0%); opacity: -1; width: 1em; display: none; } /* very transparent solid orange тест */", "p { color: rgb(100%, 50%, 0%); opacity: 2; display: inline; } /* very transparent solid orange */", @@ -867,17 +866,19 @@ TEST_SUITE("css") { }; rspamd_mempool_t *pool = rspamd_mempool_new(rspamd_mempool_suggest_size(), - "css", 0); - for (const auto &c : cases) { - SUBCASE((std::string("parse css: ") + c).c_str()) { + "css", 0); + for (const auto &c: cases) { + SUBCASE((std::string("parse css: ") + c).c_str()) + { CHECK(parse_css(pool, c, nullptr).value().get() != nullptr); } } /* We now merge all styles together */ - SUBCASE("merged css parse") { + SUBCASE("merged css parse") + { std::shared_ptr<css_style_sheet> merged; - for (const auto &c : cases) { + for (const auto &c: cases) { auto ret = parse_css(pool, c, std::move(merged)); merged.swap(ret.value()); } @@ -888,4 +889,4 @@ TEST_SUITE("css") { rspamd_mempool_delete(pool); } } -} +}// namespace rspamd::css diff --git a/src/libserver/css/css_parser.hxx b/src/libserver/css/css_parser.hxx index 35b51ed23..d5a9671b7 100644 --- a/src/libserver/css/css_parser.hxx +++ b/src/libserver/css/css_parser.hxx @@ -42,7 +42,7 @@ namespace rspamd::css { */ class css_consumed_block { public: - enum class parser_tag_type : std::uint8_t { + enum class parser_tag_type : std::uint8_t { css_top_block = 0, css_qualified_rule, css_at_rule, @@ -58,23 +58,32 @@ public: 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_function_block(css_parser_token &&tok) + : function(std::forward<css_parser_token>(tok)) + { + } - auto as_string() const -> std::string_view { + auto as_string() const -> std::string_view + { return function.get_string_or_default(""); } - static auto empty_function() -> const css_function_block & { + static auto empty_function() -> const css_function_block & + { static const css_function_block invalid( - css_parser_token(css_parser_token::token_type::eof_token, - css_parser_token_placeholder())); + css_parser_token(css_parser_token::token_type::eof_token, + css_parser_token_placeholder())); return invalid; } }; - css_consumed_block() : tag(parser_tag_type::css_eof_block) {} - css_consumed_block(parser_tag_type tag) : tag(tag) { + 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 || tag == parser_tag_type::css_qualified_rule || tag == parser_tag_type::css_simple_block) { @@ -85,8 +94,9 @@ 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) { + explicit css_consumed_block(parser_tag_type tag, css_parser_token &&tok) + : tag(tag) + { if (tag == parser_tag_type::css_function) { content = css_function_block{std::move(tok)}; } @@ -100,18 +110,21 @@ public: /* 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 { + auto assign_token(css_parser_token &&tok) -> void + { 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 is_blocks_vec() const -> bool { + auto is_blocks_vec() const -> bool + { return (std::holds_alternative<std::vector<consumed_block_ptr>>(content)); } - auto get_blocks_or_empty() const -> const std::vector<consumed_block_ptr>& { + auto get_blocks_or_empty() const -> const std::vector<consumed_block_ptr> & + { if (is_blocks_vec()) { return std::get<std::vector<consumed_block_ptr>>(content); } @@ -119,11 +132,13 @@ public: return empty_block_vec; } - auto is_token() const -> bool { + auto is_token() const -> bool + { return (std::holds_alternative<css_parser_token>(content)); } - auto get_token_or_empty() const -> const css_parser_token& { + auto get_token_or_empty() const -> const css_parser_token & + { if (is_token()) { return std::get<css_parser_token>(content); } @@ -131,11 +146,13 @@ public: return css_parser_eof_token(); } - auto is_function() const -> bool { + auto is_function() const -> bool + { return (std::holds_alternative<css_function_block>(content)); } - auto get_function_or_invalid() const -> const css_function_block& { + auto get_function_or_invalid() const -> const css_function_block & + { if (is_function()) { return std::get<css_function_block>(content); } @@ -143,31 +160,33 @@ public: return css_function_block::empty_function(); } - auto size() const -> std::size_t { + auto size() const -> std::size_t + { auto ret = 0; - std::visit([&](auto& arg) { - using T = std::decay_t<decltype(arg)>; - - if constexpr (std::is_same_v<T, std::vector<consumed_block_ptr>>) { - /* Array of blocks */ - ret = arg.size(); - } - else if constexpr (std::is_same_v<T, std::monostate>) { - /* Empty block */ - ret = 0; - } - else { - /* Single element block */ - ret = 1; - } - }, - content); + std::visit([&](auto &arg) { + using T = std::decay_t<decltype(arg)>; + + if constexpr (std::is_same_v<T, std::vector<consumed_block_ptr>>) { + /* Array of blocks */ + ret = arg.size(); + } + else if constexpr (std::is_same_v<T, std::monostate>) { + /* Empty block */ + ret = 0; + } + else { + /* Single element block */ + ret = 1; + } + }, + content); return ret; } - auto is_eof() -> bool { + auto is_eof() -> bool + { return tag == parser_tag_type::css_eof_block; } @@ -177,11 +196,13 @@ public: public: parser_tag_type tag; + private: std::variant<std::monostate, - std::vector<consumed_block_ptr>, - css_parser_token, - css_function_block> content; + std::vector<consumed_block_ptr>, + css_parser_token, + css_function_block> + content; }; extern const css_consumed_block css_parser_eof_block; @@ -218,6 +239,6 @@ auto get_rules_parser_functor(rspamd_mempool_t *pool, auto parse_css_declaration(rspamd_mempool_t *pool, const std::string_view &st) -> rspamd::html::html_block *; -} +}// namespace rspamd::css -#endif //RSPAMD_CSS_PARSER_HXX +#endif//RSPAMD_CSS_PARSER_HXX diff --git a/src/libserver/css/css_property.cxx b/src/libserver/css/css_property.cxx index 992d5a0b0..155710942 100644 --- a/src/libserver/css/css_property.cxx +++ b/src/libserver/css/css_property.cxx @@ -22,18 +22,18 @@ namespace rspamd::css { constexpr const auto prop_names_map = frozen::make_unordered_map<frozen::string, css_property_type>({ - {"font", css_property_type::PROPERTY_FONT}, - {"font-color", css_property_type::PROPERTY_FONT_COLOR}, - {"font-size", css_property_type::PROPERTY_FONT_SIZE}, - {"color", css_property_type::PROPERTY_COLOR}, - {"bgcolor", css_property_type::PROPERTY_BGCOLOR}, - {"background-color", css_property_type::PROPERTY_BGCOLOR}, - {"background", css_property_type::PROPERTY_BACKGROUND}, - {"height", css_property_type::PROPERTY_HEIGHT}, - {"width", css_property_type::PROPERTY_WIDTH}, - {"display", css_property_type::PROPERTY_DISPLAY}, - {"visibility", css_property_type::PROPERTY_VISIBILITY}, - {"opacity", css_property_type::PROPERTY_OPACITY}, + {"font", css_property_type::PROPERTY_FONT}, + {"font-color", css_property_type::PROPERTY_FONT_COLOR}, + {"font-size", css_property_type::PROPERTY_FONT_SIZE}, + {"color", css_property_type::PROPERTY_COLOR}, + {"bgcolor", css_property_type::PROPERTY_BGCOLOR}, + {"background-color", css_property_type::PROPERTY_BGCOLOR}, + {"background", css_property_type::PROPERTY_BACKGROUND}, + {"height", css_property_type::PROPERTY_HEIGHT}, + {"width", css_property_type::PROPERTY_WIDTH}, + {"display", css_property_type::PROPERTY_DISPLAY}, + {"visibility", css_property_type::PROPERTY_VISIBILITY}, + {"opacity", css_property_type::PROPERTY_OPACITY}, }); /* Ensure that we have all cases listed */ @@ -55,7 +55,7 @@ auto token_string_to_property(const std::string_view &inp) } auto css_property::from_token(const css_parser_token &tok) - -> tl::expected<css_property,css_parse_error> + -> tl::expected<css_property, css_parse_error> { if (tok.type == css_parser_token::token_type::ident_token) { auto sv = tok.get_string_or_default(""); @@ -66,4 +66,4 @@ auto css_property::from_token(const css_parser_token &tok) return tl::unexpected{css_parse_error(css_parse_error_type::PARSE_ERROR_NYI)}; } -} +}// namespace rspamd::css diff --git a/src/libserver/css/css_property.hxx b/src/libserver/css/css_property.hxx index 7af6c7bd6..9661222de 100644 --- a/src/libserver/css/css_property.hxx +++ b/src/libserver/css/css_property.hxx @@ -54,15 +54,18 @@ struct alignas(int) css_property { css_property_type type; css_property_flag flag; - css_property(css_property_type t, css_property_flag fl = css_property_flag::FLAG_NORMAL) : - type(t), flag(fl) {} - static tl::expected<css_property,css_parse_error> from_token( - const css_parser_token &tok); + css_property(css_property_type t, css_property_flag fl = css_property_flag::FLAG_NORMAL) + : type(t), flag(fl) + { + } + static tl::expected<css_property, css_parse_error> from_token( + const css_parser_token &tok); - constexpr auto to_string(void) const -> const char * { + constexpr auto to_string(void) const -> const char * + { const char *ret = "nyi"; - switch(type) { + switch (type) { case css_property_type::PROPERTY_FONT: ret = "font"; break; @@ -104,37 +107,45 @@ struct alignas(int) css_property { } /* Helpers to define which values are valid for which properties */ - auto is_color(void) const -> bool { + auto is_color(void) const -> bool + { return type == css_property_type::PROPERTY_COLOR || - type == css_property_type::PROPERTY_BACKGROUND || - type == css_property_type::PROPERTY_BGCOLOR || - type == css_property_type::PROPERTY_FONT_COLOR || - type == css_property_type::PROPERTY_FONT; + type == css_property_type::PROPERTY_BACKGROUND || + type == css_property_type::PROPERTY_BGCOLOR || + type == css_property_type::PROPERTY_FONT_COLOR || + type == css_property_type::PROPERTY_FONT; } - auto is_dimension(void) const -> bool { + auto is_dimension(void) const -> bool + { return type == css_property_type::PROPERTY_HEIGHT || - type == css_property_type::PROPERTY_WIDTH || - type == css_property_type::PROPERTY_FONT_SIZE || - type == css_property_type::PROPERTY_FONT; + type == css_property_type::PROPERTY_WIDTH || + type == css_property_type::PROPERTY_FONT_SIZE || + type == css_property_type::PROPERTY_FONT; } - auto is_normal_number(void) const -> bool { + auto is_normal_number(void) const -> bool + { return type == css_property_type::PROPERTY_OPACITY; } - auto is_display(void) const -> bool { + auto is_display(void) const -> bool + { return type == css_property_type::PROPERTY_DISPLAY; } - auto is_visibility(void) const -> bool { + auto is_visibility(void) const -> bool + { return type == css_property_type::PROPERTY_VISIBILITY; } - auto operator==(const css_property &other) const { return type == other.type; } + auto operator==(const css_property &other) const + { + return type == other.type; + } }; -} +}// namespace rspamd::css /* Make properties hashable */ namespace std { @@ -143,8 +154,9 @@ class hash<rspamd::css::css_property> { public: using is_avalanching = void; /* Mix bits to provide slightly better distribution but being constexpr */ - constexpr size_t operator() (const rspamd::css::css_property &prop) const { - std::size_t key = 0xdeadbeef ^static_cast<std::size_t>(prop.type); + constexpr size_t operator()(const rspamd::css::css_property &prop) const + { + std::size_t key = 0xdeadbeef ^ static_cast<std::size_t>(prop.type); key = (~key) + (key << 21); key = key ^ (key >> 24); key = (key + (key << 3)) + (key << 8); @@ -155,6 +167,6 @@ public: return key; } }; -} +}// namespace std -#endif //RSPAMD_CSS_PROPERTY_HXX
\ No newline at end of file +#endif//RSPAMD_CSS_PROPERTY_HXX
\ No newline at end of file diff --git a/src/libserver/css/css_rule.cxx b/src/libserver/css/css_rule.cxx index 3a93d97d4..4e33ac7a0 100644 --- a/src/libserver/css/css_rule.cxx +++ b/src/libserver/css/css_rule.cxx @@ -32,11 +32,11 @@ void css_rule::override_values(const css_rule &other) static_assert(1 << std::variant_size_v<decltype(css_value::value)> < std::numeric_limits<int>::max()); - for (const auto &v : values) { + for (const auto &v: values) { bits |= static_cast<int>(1 << v.value.index()); } - for (const auto &ov : other.values) { + for (const auto &ov: other.values) { if (isset(&bits, static_cast<int>(1 << ov.value.index()))) { /* We need to override the existing value */ /* @@ -46,7 +46,7 @@ void css_rule::override_values(const css_rule &other) * number of elements about less then 10, so this O(N^2) algorithm * is probably ok here */ - for (auto &v : values) { + for (auto &v: values) { if (v.value.index() == ov.value.index()) { v = ov; } @@ -56,24 +56,24 @@ void css_rule::override_values(const css_rule &other) /* Copy only not set values */ std::copy_if(other.values.begin(), other.values.end(), std::back_inserter(values), - [&bits](const auto &elt) -> bool { - return (bits & (1 << static_cast<int>(elt.value.index()))) == 0; - }); + [&bits](const auto &elt) -> bool { + return (bits & (1 << static_cast<int>(elt.value.index()))) == 0; + }); } void css_rule::merge_values(const css_rule &other) { unsigned int bits = 0; - for (const auto &v : values) { + for (const auto &v: values) { bits |= 1 << v.value.index(); } /* Copy only not set values */ std::copy_if(other.values.begin(), other.values.end(), std::back_inserter(values), - [&bits](const auto &elt) -> bool { - return (bits & (1 << elt.value.index())) == 0; - }); + [&bits](const auto &elt) -> bool { + return (bits & (1 << elt.value.index())) == 0; + }); } auto css_declarations_block::add_rule(rule_shared_ptr rule) -> bool @@ -131,7 +131,7 @@ auto css_declarations_block::add_rule(rule_shared_ptr rule) -> bool return ret; } -} +}// namespace rspamd::css namespace rspamd::css { @@ -139,7 +139,8 @@ namespace rspamd::css { static auto allowed_property_value(const css_property &prop, const css_consumed_block &parser_block) --> std::optional<css_value> { + -> std::optional<css_value> +{ if (prop.is_color()) { if (parser_block.is_token()) { /* A single token */ @@ -207,7 +208,8 @@ allowed_property_value(const css_property &prop, const css_consumed_block &parse auto process_declaration_tokens(rspamd_mempool_t *pool, blocks_gen_functor &&next_block_functor) --> css_declarations_block_ptr { + -> css_declarations_block_ptr +{ css_declarations_block_ptr ret; bool can_continue = true; css_property cur_property{css_property_type::PROPERTY_NYI, @@ -233,7 +235,7 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, /* Component can be a property or a compound list of values */ if (state == parse_property) { cur_property = css_property::from_token(next_tok.get_token_or_empty()) - .value_or(bad_property); + .value_or(bad_property); if (cur_property.type == css_property_type::PROPERTY_NYI) { state = ignore_value; @@ -283,12 +285,12 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, if (parser_tok.get_string_or_default("") == "important") { if (seen_not) { msg_debug_css("add !important flag to property %s", - cur_property.to_string()); + cur_property.to_string()); cur_property.flag = css_property_flag::FLAG_NOT_IMPORTANT; } else { msg_debug_css("add important flag to property %s", - cur_property.to_string()); + cur_property.to_string()); cur_property.flag = css_property_flag::FLAG_IMPORTANT; } @@ -306,8 +308,8 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, if (maybe_value) { msg_debug_css("added value %s to the property %s", - maybe_value.value().debug_str().c_str(), - cur_property.to_string()); + maybe_value.value().debug_str().c_str(), + cur_property.to_string()); cur_rule->add_value(maybe_value.value()); } } @@ -328,8 +330,8 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, if (maybe_value && cur_rule) { msg_debug_css("added value %s to the property %s", - maybe_value.value().debug_str().c_str(), - cur_property.to_string()); + maybe_value.value().debug_str().c_str(), + cur_property.to_string()); cur_rule->add_value(maybe_value.value()); } } @@ -349,13 +351,12 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, return ret; /* copy elision */ } -auto -css_declarations_block::merge_block(const css_declarations_block &other, merge_type how) -> void +auto css_declarations_block::merge_block(const css_declarations_block &other, merge_type how) -> void { const auto &other_rules = other.get_rules(); - for (auto &rule : other_rules) { + for (auto &rule: other_rules) { auto &&found_it = rules.find(rule); if (found_it != rules.end()) { @@ -381,14 +382,13 @@ css_declarations_block::merge_block(const css_declarations_block &other, merge_t } } -auto -css_declarations_block::compile_to_block(rspamd_mempool_t *pool) const -> rspamd::html::html_block * +auto css_declarations_block::compile_to_block(rspamd_mempool_t *pool) const -> rspamd::html::html_block * { auto *block = rspamd_mempool_alloc0_type(pool, rspamd::html::html_block); auto opacity = -1; const css_rule *font_rule = nullptr, *background_rule = nullptr; - for (const auto &rule : rules) { + for (const auto &rule: rules) { auto prop = rule->get_prop().type; const auto &vals = rule->get_values(); @@ -459,7 +459,7 @@ css_declarations_block::compile_to_block(rspamd_mempool_t *pool) const -> rspamd if (!(block->fg_color_mask) && font_rule) { auto &vals = font_rule->get_values(); - for (const auto &val : vals) { + for (const auto &val: vals) { auto maybe_color = val.to_color(); if (maybe_color) { @@ -471,7 +471,7 @@ css_declarations_block::compile_to_block(rspamd_mempool_t *pool) const -> rspamd if (!(block->font_mask) && font_rule) { auto &vals = font_rule->get_values(); - for (const auto &val : vals) { + for (const auto &val: vals) { auto maybe_dim = val.to_dimension(); if (maybe_dim) { @@ -483,7 +483,7 @@ css_declarations_block::compile_to_block(rspamd_mempool_t *pool) const -> rspamd if (!(block->bg_color_mask) && background_rule) { auto &vals = background_rule->get_values(); - for (const auto &val : vals) { + for (const auto &val: vals) { auto maybe_color = val.to_color(); if (maybe_color) { @@ -501,34 +501,31 @@ void css_rule::add_value(const css_value &value) } -TEST_SUITE("css") { - TEST_CASE("simple css rules") { +TEST_SUITE("css") +{ + TEST_CASE("simple css rules") + { const std::vector<std::pair<const char *, std::vector<css_property>>> cases{ - { - "font-size:12.0pt;line-height:115%", - {css_property(css_property_type::PROPERTY_FONT_SIZE)} - }, - { - "font-size:12.0pt;display:none", - {css_property(css_property_type::PROPERTY_FONT_SIZE), - css_property(css_property_type::PROPERTY_DISPLAY)} - } - }; + {"font-size:12.0pt;line-height:115%", + {css_property(css_property_type::PROPERTY_FONT_SIZE)}}, + {"font-size:12.0pt;display:none", + {css_property(css_property_type::PROPERTY_FONT_SIZE), + css_property(css_property_type::PROPERTY_DISPLAY)}}}; auto *pool = rspamd_mempool_new(rspamd_mempool_suggest_size(), - "css", 0); + "css", 0); - for (const auto &c : cases) { + for (const auto &c: cases) { auto res = process_declaration_tokens(pool, - get_rules_parser_functor(pool, c.first)); + get_rules_parser_functor(pool, c.first)); CHECK(res.get() != nullptr); - for (auto i = 0; i < c.second.size(); i ++) { + for (auto i = 0; i < c.second.size(); i++) { CHECK(res->has_property(c.second[i])); } } } } -} // namespace rspamd::css
\ No newline at end of file +}// namespace rspamd::css
\ No newline at end of file diff --git a/src/libserver/css/css_rule.hxx b/src/libserver/css/css_rule.hxx index df385bdad..114b83e11 100644 --- a/src/libserver/css/css_rule.hxx +++ b/src/libserver/css/css_rule.hxx @@ -30,7 +30,7 @@ namespace rspamd::html { /* Forward declaration */ struct html_block; -} +}// namespace rspamd::html namespace rspamd::css { @@ -48,17 +48,31 @@ public: /* Constructors */ css_rule(css_rule &&other) noexcept = default; - explicit css_rule(css_property &&prop, css_values_vec &&values) noexcept : - prop(prop), values(std::forward<css_values_vec>(values)) {} + explicit css_rule(css_property &&prop, css_values_vec &&values) noexcept + : prop(prop), values(std::forward<css_values_vec>(values)) + { + } - explicit css_rule(const css_property &prop) noexcept : prop(prop), values{} {} + explicit css_rule(const css_property &prop) noexcept + : prop(prop), values{} + { + } /* Methods */ /* Comparison is special, as we care merely about property, not the values */ - auto operator==(const css_rule &other) const { return prop == other.prop; } + auto operator==(const css_rule &other) const + { + return prop == other.prop; + } - constexpr const css_values_vec &get_values(void) const { return values; } - constexpr const css_property &get_prop(void) const { return prop; } + constexpr const css_values_vec &get_values(void) const + { + return values; + } + constexpr const css_property &get_prop(void) const + { + return prop; + } /* Import values from another rules according to the importance */ void override_values(const css_rule &other); @@ -66,7 +80,7 @@ public: void add_value(const css_value &value); }; -} +}// namespace rspamd::css /* Make rules hashable by property */ namespace std { @@ -74,12 +88,13 @@ template<> class hash<rspamd::css::css_rule> { public: using is_avalanching = void; - constexpr auto operator()(const rspamd::css::css_rule &rule) const -> auto { + constexpr auto operator()(const rspamd::css::css_rule &rule) const -> auto + { return hash<rspamd::css::css_property>()(rule.get_prop()); } }; -} +}// namespace std namespace rspamd::css { @@ -100,8 +115,9 @@ public: css_declarations_block() = default; auto add_rule(rule_shared_ptr rule) -> bool; auto merge_block(const css_declarations_block &other, - merge_type how = merge_type::merge_duplicate) -> void; - auto get_rules(void) const -> const auto & { + merge_type how = merge_type::merge_duplicate) -> void; + auto get_rules(void) const -> const auto & + { return rules; } @@ -110,7 +126,8 @@ public: * @param prop * @return */ - auto has_property(const css_property &prop) const -> bool { + auto has_property(const css_property &prop) const -> bool + { return (rules.find(css_rule{prop}) != rules.end()); } @@ -131,6 +148,6 @@ auto process_declaration_tokens(rspamd_mempool_t *pool, blocks_gen_functor &&next_token_functor) -> css_declarations_block_ptr; -} +}// namespace rspamd::css -#endif //RSPAMD_CSS_RULE_HXX
\ No newline at end of file +#endif//RSPAMD_CSS_RULE_HXX
\ No newline at end of file diff --git a/src/libserver/css/css_selector.cxx b/src/libserver/css/css_selector.cxx index 86ff482fe..a62ffff9c 100644 --- a/src/libserver/css/css_selector.cxx +++ b/src/libserver/css/css_selector.cxx @@ -59,17 +59,17 @@ auto process_selector_tokens(rspamd_mempool_t *pool, if (delim_c == '.') { cur_selector = std::make_unique<css_selector>( - css_selector::selector_type::SELECTOR_CLASS); + css_selector::selector_type::SELECTOR_CLASS); state = selector_process_state::selector_expect_ident; } else if (delim_c == '#') { cur_selector = std::make_unique<css_selector>( - css_selector::selector_type::SELECTOR_ID); + css_selector::selector_type::SELECTOR_ID); state = selector_process_state::selector_expect_ident; } else if (delim_c == '*') { cur_selector = std::make_unique<css_selector>( - css_selector::selector_type::SELECTOR_ALL); + css_selector::selector_type::SELECTOR_ALL); state = selector_process_state::selector_ident_consumed; } break; @@ -85,14 +85,14 @@ auto process_selector_tokens(rspamd_mempool_t *pool, } case css_parser_token::token_type::hash_token: cur_selector = std::make_unique<css_selector>( - css_selector::selector_type::SELECTOR_ID); + css_selector::selector_type::SELECTOR_ID); cur_selector->value = - parser_tok.get_string_or_default(""); + parser_tok.get_string_or_default(""); state = selector_process_state::selector_ident_consumed; break; default: msg_debug_css("cannot consume more of a selector, invalid parser token: %s; expected start", - next_tok.token_type_str()); + next_tok.token_type_str()); can_continue = false; break; } @@ -108,7 +108,7 @@ auto process_selector_tokens(rspamd_mempool_t *pool, } else { msg_debug_css("cannot consume more of a selector, invalid parser token: %s; expected ident", - next_tok.token_type_str()); + next_tok.token_type_str()); can_continue = false; } } @@ -141,8 +141,8 @@ auto process_selector_tokens(rspamd_mempool_t *pool, } else { auto debug_str = parser_tok.get_string_or_default(""); - msg_debug_css("ignore token %*s", (int)debug_str.size(), - debug_str.data()); + msg_debug_css("ignore token %*s", (int) debug_str.size(), + debug_str.data()); } } } @@ -157,14 +157,12 @@ auto process_selector_tokens(rspamd_mempool_t *pool, } can_continue = false; } - } return ret; /* copy elision */ } -auto -css_selector::debug_str() const -> std::string +auto css_selector::debug_str() const -> std::string { std::string ret; @@ -189,33 +187,34 @@ css_selector::debug_str() const -> std::string else { ret += arg; } - }, value); + }, + value); return ret; } -TEST_SUITE("css") { - TEST_CASE("simple css selectors") { +TEST_SUITE("css") +{ + TEST_CASE("simple css selectors") + { const std::vector<std::pair<const char *, std::vector<css_selector::selector_type>>> cases{ - {"em", {css_selector::selector_type::SELECTOR_TAG}}, - {"*", {css_selector::selector_type::SELECTOR_ALL}}, - {".class", {css_selector::selector_type::SELECTOR_CLASS}}, - {"#id", {css_selector::selector_type::SELECTOR_ID}}, - {"em,.class,#id", {css_selector::selector_type::SELECTOR_TAG, - css_selector::selector_type::SELECTOR_CLASS, - css_selector::selector_type::SELECTOR_ID}}, + {"em", {css_selector::selector_type::SELECTOR_TAG}}, + {"*", {css_selector::selector_type::SELECTOR_ALL}}, + {".class", {css_selector::selector_type::SELECTOR_CLASS}}, + {"#id", {css_selector::selector_type::SELECTOR_ID}}, + {"em,.class,#id", {css_selector::selector_type::SELECTOR_TAG, css_selector::selector_type::SELECTOR_CLASS, css_selector::selector_type::SELECTOR_ID}}, }; auto *pool = rspamd_mempool_new(rspamd_mempool_suggest_size(), - "css", 0); + "css", 0); - for (const auto &c : cases) { + for (const auto &c: cases) { auto res = process_selector_tokens(pool, - get_selectors_parser_functor(pool, c.first)); + get_selectors_parser_functor(pool, c.first)); CHECK(c.second.size() == res.size()); - for (auto i = 0; i < c.second.size(); i ++) { + for (auto i = 0; i < c.second.size(); i++) { CHECK(res[i]->type == c.second[i]); } } @@ -224,5 +223,4 @@ TEST_SUITE("css") { } } -} - +}// namespace rspamd::css diff --git a/src/libserver/css/css_selector.hxx b/src/libserver/css/css_selector.hxx index f49251338..65b185a6e 100644 --- a/src/libserver/css/css_selector.hxx +++ b/src/libserver/css/css_selector.hxx @@ -38,10 +38,10 @@ namespace rspamd::css { */ struct css_selector { enum class selector_type { - SELECTOR_TAG, /* e.g. tr, for this value we use tag_id_t */ + 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_ID, /* e.g. #id */ + SELECTOR_ALL /* * selector */ }; selector_type type; @@ -60,29 +60,39 @@ struct 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> { + 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> { + 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) { + 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) { + 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 { + auto operator==(const css_selector &other) const -> bool + { return type == other.type && value == other.value; } @@ -99,7 +109,7 @@ auto process_selector_tokens(rspamd_mempool_t *pool, blocks_gen_functor &&next_token_functor) -> selectors_vec; -} +}// namespace rspamd::css /* Selectors hashing */ namespace std { @@ -107,7 +117,8 @@ template<> class hash<rspamd::css::css_selector> { public: using is_avalanching = void; - auto operator() (const rspamd::css::css_selector &sel) const -> std::size_t { + 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)); } @@ -118,6 +129,6 @@ public: } } }; -} +}// namespace std -#endif //RSPAMD_CSS_SELECTOR_HXX +#endif//RSPAMD_CSS_SELECTOR_HXX diff --git a/src/libserver/css/css_style.hxx b/src/libserver/css/css_style.hxx index 2a97f8f0e..429e58fdd 100644 --- a/src/libserver/css/css_style.hxx +++ b/src/libserver/css/css_style.hxx @@ -32,29 +32,35 @@ namespace rspamd::css { class css_style { public: /* Make class trivial */ - css_style (const css_style &other) = default; + css_style(const css_style &other) = default; - css_style (const std::shared_ptr<css_style> &_parent) : parent(_parent) { - propagate_from_parent (); + css_style(const std::shared_ptr<css_style> &_parent) + : parent(_parent) + { + propagate_from_parent(); } - css_style (const std::shared_ptr<css_style> &_parent, - const std::vector<std::shared_ptr<css_selector> > &_selectors) : parent(_parent) { - selectors.reserve (_selectors.size ()); + css_style(const std::shared_ptr<css_style> &_parent, + const std::vector<std::shared_ptr<css_selector>> &_selectors) + : parent(_parent) + { + selectors.reserve(_selectors.size()); - for (const auto &sel_ptr : _selectors) { - selectors.emplace_back (sel_ptr); + for (const auto &sel_ptr: _selectors) { + selectors.emplace_back(sel_ptr); } - propagate_from_parent (); + propagate_from_parent(); } + private: - std::vector<std::weak_ptr<css_selector> > selectors; + std::vector<std::weak_ptr<css_selector>> selectors; std::weak_ptr<css_style> parent; std::vector<css_rule> rules; + private: void propagate_from_parent(void); /* Construct full style using parent */ }; -} +}// namespace rspamd::css -#endif //RSPAMD_CSS_STYLE_HXX +#endif//RSPAMD_CSS_STYLE_HXX diff --git a/src/libserver/css/css_tokeniser.cxx b/src/libserver/css/css_tokeniser.cxx index f3c010f1e..6d3f41e8d 100644 --- a/src/libserver/css/css_tokeniser.cxx +++ b/src/libserver/css/css_tokeniser.cxx @@ -35,42 +35,42 @@ auto make_token(const Arg &arg) -> css_parser_token; template<> auto make_token<css_parser_token::token_type::string_token, std::string_view>(const std::string_view &s) - -> css_parser_token + -> css_parser_token { return css_parser_token{css_parser_token::token_type::string_token, s}; } template<> auto make_token<css_parser_token::token_type::ident_token, std::string_view>(const std::string_view &s) --> css_parser_token + -> css_parser_token { return css_parser_token{css_parser_token::token_type::ident_token, s}; } template<> auto make_token<css_parser_token::token_type::function_token, std::string_view>(const std::string_view &s) --> css_parser_token + -> css_parser_token { return css_parser_token{css_parser_token::token_type::function_token, s}; } template<> auto make_token<css_parser_token::token_type::url_token, std::string_view>(const std::string_view &s) --> css_parser_token + -> css_parser_token { return css_parser_token{css_parser_token::token_type::url_token, s}; } template<> auto make_token<css_parser_token::token_type::whitespace_token, std::string_view>(const std::string_view &s) - -> css_parser_token + -> css_parser_token { return css_parser_token{css_parser_token::token_type::whitespace_token, s}; } template<> auto make_token<css_parser_token::token_type::delim_token, char>(const char &c) - -> css_parser_token + -> css_parser_token { return css_parser_token{css_parser_token::token_type::delim_token, c}; } @@ -119,35 +119,33 @@ struct css_dimension_data { */ constexpr const auto max_dims = static_cast<int>(css_parser_token::dim_type::dim_max); constexpr frozen::unordered_map<frozen::string, css_dimension_data, max_dims> dimensions_map{ - {"px", { css_parser_token::dim_type::dim_px, 1.0}}, - /* EM/REM are 16 px, so multiply and round */ - {"em", { css_parser_token::dim_type::dim_em, 16.0}}, - {"rem", { css_parser_token::dim_type::dim_rem, 16.0}}, - /* + {"px", {css_parser_token::dim_type::dim_px, 1.0}}, + /* EM/REM are 16 px, so multiply and round */ + {"em", {css_parser_token::dim_type::dim_em, 16.0}}, + {"rem", {css_parser_token::dim_type::dim_rem, 16.0}}, + /* * Represents the x-height of the element's font. * On fonts with the "x" letter, this is generally the height * of lowercase letters in the font; 1ex = 0.5em in many fonts. */ - {"ex", { css_parser_token::dim_type::dim_ex, 8.0}}, - {"wv", { css_parser_token::dim_type::dim_wv, 8.0}}, - {"wh", { css_parser_token::dim_type::dim_wh, 6.0}}, - {"vmax", { css_parser_token::dim_type::dim_vmax, 8.0}}, - {"vmin", { css_parser_token::dim_type::dim_vmin, 6.0}}, - /* One point. 1pt = 1/72nd of 1in */ - {"pt", { css_parser_token::dim_type::dim_pt, 96.0 / 72.0}}, - /* 96px/2.54 */ - {"cm", { css_parser_token::dim_type::dim_cm, 96.0 / 2.54}}, - {"mm", { css_parser_token::dim_type::dim_mm, 9.60 / 2.54}}, - {"in", { css_parser_token::dim_type::dim_in, 96.0}}, - /* 1pc = 12pt = 1/6th of 1in. */ - {"pc", { css_parser_token::dim_type::dim_pc, 96.0 / 6.0}} -}; - -auto -css_parser_token::adjust_dim(const css_parser_token &dim_token) -> bool + {"ex", {css_parser_token::dim_type::dim_ex, 8.0}}, + {"wv", {css_parser_token::dim_type::dim_wv, 8.0}}, + {"wh", {css_parser_token::dim_type::dim_wh, 6.0}}, + {"vmax", {css_parser_token::dim_type::dim_vmax, 8.0}}, + {"vmin", {css_parser_token::dim_type::dim_vmin, 6.0}}, + /* One point. 1pt = 1/72nd of 1in */ + {"pt", {css_parser_token::dim_type::dim_pt, 96.0 / 72.0}}, + /* 96px/2.54 */ + {"cm", {css_parser_token::dim_type::dim_cm, 96.0 / 2.54}}, + {"mm", {css_parser_token::dim_type::dim_mm, 9.60 / 2.54}}, + {"in", {css_parser_token::dim_type::dim_in, 96.0}}, + /* 1pc = 12pt = 1/6th of 1in. */ + {"pc", {css_parser_token::dim_type::dim_pc, 96.0 / 6.0}}}; + +auto css_parser_token::adjust_dim(const css_parser_token &dim_token) -> bool { if (!std::holds_alternative<float>(value) || - !std::holds_alternative<std::string_view>(dim_token.value)) { + !std::holds_alternative<std::string_view>(dim_token.value)) { /* Invalid tokens */ return false; } @@ -178,8 +176,7 @@ css_parser_token::adjust_dim(const css_parser_token &dim_token) -> bool /* * Consume functions: return a token and advance lexer offset */ -auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token -{ +auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token { auto i = offset; auto need_escape = false; auto allow_middle_minus = false; @@ -187,7 +184,7 @@ auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token auto maybe_escape_sv = [&](auto cur_pos, auto tok_type) -> auto { if (need_escape) { auto escaped = rspamd::css::unescape_css(pool, {&input[offset], - cur_pos - offset}); + cur_pos - offset}); offset = cur_pos; return css_parser_token{tok_type, escaped}; @@ -201,10 +198,10 @@ auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token /* Ident token can start from `-` or `--` */ if (input[i] == '-') { - i ++; + i++; if (i < input.size() && input[i] == '-') { - i ++; + i++; allow_middle_minus = true; } } @@ -212,10 +209,9 @@ auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token while (i < input.size()) { auto c = input[i]; - auto is_plain_c = (allow_number || allow_middle_minus) ? is_plain_ident(c) : - is_plain_ident_start(c); + auto is_plain_c = (allow_number || allow_middle_minus) ? is_plain_ident(c) : is_plain_ident_start(c); if (!is_plain_c) { - if (c == '\\' && i + 1 < input.size ()) { + if (c == '\\' && i + 1 < input.size()) { /* Escape token */ need_escape = true; auto nhex = 0; @@ -240,7 +236,7 @@ auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token /* Single \ + char */ break; } - } while (i < input.size ()); + } while (i < input.size()); } else if (c == '(') { /* Function or url token */ @@ -254,7 +250,7 @@ auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token if (j < input.size() && (input[j] == '"' || input[j] == '\'')) { /* Function token */ auto ret = maybe_escape_sv(i, - css_parser_token::token_type::function_token); + css_parser_token::token_type::function_token); return ret; } else { @@ -266,13 +262,13 @@ auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token if (j < input.size() && input[j] == ')') { /* Valid url token */ auto ret = maybe_escape_sv(j + 1, - css_parser_token::token_type::url_token); + 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); + css_parser_token::token_type::url_token); ret.flags |= css_parser_token::flag_bad_string; return ret; @@ -281,7 +277,7 @@ auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token } else { auto ret = maybe_escape_sv(i, - css_parser_token::token_type::function_token); + css_parser_token::token_type::function_token); return ret; } } @@ -297,23 +293,23 @@ auto css_tokeniser::consume_ident(bool allow_number) -> struct css_parser_token allow_middle_minus = true; } - i ++; + i++; } return maybe_escape_sv(i, css_parser_token::token_type::ident_token); } -auto css_tokeniser::consume_number() -> struct css_parser_token -{ +auto +css_tokeniser::consume_number() -> struct css_parser_token { auto i = offset; auto seen_dot = false, seen_exp = false; if (input[i] == '-' || input[i] == '+') { - i ++; + i++; } if (input[i] == '.' && i < input.size()) { seen_dot = true; - i ++; + i++; } while (i < input.size()) { @@ -336,7 +332,7 @@ auto css_tokeniser::consume_number() -> struct css_parser_token if (i + 1 < input.size()) { auto next_c = input[i + 1]; if (next_c == '+' || next_c == '-') { - i ++; + i++; } else if (!g_ascii_isdigit(next_c)) { /* Not an exponent */ @@ -357,7 +353,7 @@ auto css_tokeniser::consume_number() -> struct css_parser_token } } - i ++; + i++; } if (i > offset) { @@ -368,7 +364,7 @@ auto css_tokeniser::consume_number() -> struct css_parser_token auto num = g_ascii_strtod(numbuf, &endptr); offset = i; - if (fabs (num) >= G_MAXFLOAT || std::isnan(num)) { + if (fabs(num) >= G_MAXFLOAT || std::isnan(num)) { msg_debug_css("invalid number: %s", numbuf); return make_token<css_parser_token::token_type::delim_token>(input[i - 1]); } @@ -390,7 +386,7 @@ auto css_tokeniser::consume_number() -> struct css_parser_token if (!ret.adjust_dim(dim_token)) { auto sv = std::get<std::string_view>(dim_token.value); msg_debug_css("cannot apply dimension from the token %*s; number value = %.1f", - (int) sv.size(), sv.begin(), num); + (int) sv.size(), sv.begin(), num); /* Unconsume ident */ offset = i; } @@ -410,7 +406,7 @@ auto css_tokeniser::consume_number() -> struct css_parser_token } else { msg_err_css("internal error: invalid number, empty token"); - i ++; + i++; } offset = i; @@ -421,8 +417,8 @@ auto css_tokeniser::consume_number() -> struct css_parser_token /* * Main routine to produce lexer tokens */ -auto css_tokeniser::next_token(void) -> struct css_parser_token -{ +auto +css_tokeniser::next_token(void) -> struct css_parser_token { /* Check pushback queue */ if (!backlog.empty()) { auto tok = backlog.front(); @@ -508,7 +504,7 @@ auto css_tokeniser::next_token(void) -> struct css_parser_token /* Should be a error, but we ignore it for now */ } - i ++; + i++; } /* EOF with no quote character, consider it fine */ @@ -531,7 +527,7 @@ auto css_tokeniser::next_token(void) -> struct css_parser_token case '/': if (i + 1 < input.size() && input[i + 1] == '*') { offset = i + 2; - consume_comment(); /* Consume comment and go forward */ + consume_comment(); /* Consume comment and go forward */ return next_token(); /* Tail call */ } else { @@ -550,7 +546,7 @@ auto css_tokeniser::next_token(void) -> struct css_parser_token } auto ret = make_token<css_parser_token::token_type::whitespace_token>( - std::string_view(&input[offset], i - offset)); + std::string_view(&input[offset], i - offset)); offset = i; return ret; } @@ -593,8 +589,7 @@ auto css_tokeniser::next_token(void) -> struct css_parser_token return make_token<css_parser_token::token_type::colon_token>(); case '<': /* Maybe an xml like comment */ - if (i + 3 < input.size () && input[i + 1] == '!' - && input[i + 2] == '-' && input[i + 3] == '-') { + if (i + 3 < input.size() && input[i + 1] == '!' && input[i + 2] == '-' && input[i + 3] == '-') { offset += 3; return make_token<css_parser_token::token_type::cdo_token>(); @@ -691,7 +686,7 @@ auto css_tokeniser::next_token(void) -> struct css_parser_token if (i + 2 < input.size()) { auto next_c = input[i + 1], next_next_c = input[i + 2]; if ((is_plain_ident(next_c) || next_c == '-') && - (is_plain_ident(next_next_c) || next_next_c == '-')) { + (is_plain_ident(next_next_c) || next_next_c == '-')) { offset = i + 1; /* We consume indent, but we allow numbers there */ auto ident_token = consume_ident(true); @@ -728,17 +723,17 @@ auto css_tokeniser::next_token(void) -> struct css_parser_token } break; } - } return make_token<css_parser_token::token_type::eof_token>(); } -constexpr auto css_parser_token::get_token_type() -> const char * +constexpr auto +css_parser_token::get_token_type() -> const char * { const char *ret = "unknown"; - switch(type) { + switch (type) { case token_type::whitespace_token: ret = "whitespace"; break; @@ -825,7 +820,7 @@ auto css_parser_token::debug_token_str() -> std::string ret += std::to_string(arg); } }, - value); + value); if ((flags & (~number_dimension)) != default_flags) { ret += "; flags=" + std::to_string(flags); @@ -838,4 +833,4 @@ auto css_parser_token::debug_token_str() -> std::string return ret; /* Copy elision */ } -}
\ No newline at end of file +}// namespace rspamd::css
\ No newline at end of file diff --git a/src/libserver/css/css_tokeniser.hxx b/src/libserver/css/css_tokeniser.hxx index 897489974..aa6a1a711 100644 --- a/src/libserver/css/css_tokeniser.hxx +++ b/src/libserver/css/css_tokeniser.hxx @@ -45,10 +45,10 @@ struct css_parser_token { cdo_token, /* xml open comment */ cdc_token, /* xml close comment */ delim_token, - obrace_token, /* ( */ - ebrace_token, /* ) */ - osqbrace_token, /* [ */ - esqbrace_token, /* ] */ + obrace_token, /* ( */ + ebrace_token, /* ) */ + osqbrace_token, /* [ */ + esqbrace_token, /* ] */ ocurlbrace_token, /* { */ ecurlbrace_token, /* } */ comma_token, @@ -80,11 +80,11 @@ struct css_parser_token { static const std::uint8_t number_percent = (1u << 2u); static const std::uint8_t flag_bad_dimension = (1u << 3u); - using value_type = std::variant<std::string_view, /* For strings and string like tokens */ - char, /* For delimiters (might need to move to unicode point) */ - float, /* For numeric stuff */ - css_parser_token_placeholder /* For general no token stuff */ - >; + using value_type = std::variant<std::string_view, /* For strings and string like tokens */ + char, /* For delimiters (might need to move to unicode point) */ + float, /* For numeric stuff */ + css_parser_token_placeholder /* For general no token stuff */ + >; /* Typed storage */ value_type value; @@ -96,14 +96,17 @@ struct css_parser_token { dim_type dimension_type; css_parser_token() = delete; - explicit css_parser_token(token_type type, const value_type &value) : - value(value), type(type) {} + explicit css_parser_token(token_type type, const value_type &value) + : value(value), type(type) + { + } css_parser_token(css_parser_token &&other) = default; css_parser_token(const css_parser_token &token) = default; - auto operator=(css_parser_token &&other) -> css_parser_token& = default; + auto operator=(css_parser_token &&other) -> css_parser_token & = default; auto adjust_dim(const css_parser_token &dim_token) -> bool; - auto get_string_or_default(const std::string_view &def) const -> std::string_view { + auto get_string_or_default(const std::string_view &def) const -> std::string_view + { if (std::holds_alternative<std::string_view>(value)) { return std::get<std::string_view>(value); } @@ -114,15 +117,17 @@ struct css_parser_token { return def; } - auto get_delim() const -> char { + auto get_delim() const -> char + { if (std::holds_alternative<char>(value)) { return std::get<char>(value); } - return (char)-1; + return (char) -1; } - auto get_number_or_default(float def) const -> float { + auto get_number_or_default(float def) const -> float + { if (std::holds_alternative<float>(value)) { auto dbl = std::get<float>(value); @@ -136,7 +141,8 @@ struct css_parser_token { return def; } - auto get_normal_number_or_default(float def) const -> float { + auto get_normal_number_or_default(float def) const -> float + { if (std::holds_alternative<float>(value)) { auto dbl = std::get<float>(value); @@ -163,11 +169,11 @@ struct css_parser_token { auto debug_token_str() -> std::string; }; -static auto css_parser_eof_token(void) -> const css_parser_token & { - static css_parser_token eof_tok { +static auto css_parser_eof_token(void) -> const css_parser_token & +{ + static css_parser_token eof_tok{ css_parser_token::token_type::eof_token, - css_parser_token_placeholder() - }; + css_parser_token_placeholder()}; return eof_tok; } @@ -182,13 +188,17 @@ static_assert(std::is_trivially_copyable_v<css_parser_token>); class css_tokeniser { public: css_tokeniser() = delete; - css_tokeniser(rspamd_mempool_t *pool, const std::string_view &sv) : - input(sv), offset(0), pool(pool) {} + css_tokeniser(rspamd_mempool_t *pool, const std::string_view &sv) + : input(sv), offset(0), pool(pool) + { + } auto next_token(void) -> struct css_parser_token; - auto pushback_token(const struct css_parser_token &t) const -> void { + auto pushback_token(const struct css_parser_token &t) const -> void + { backlog.push_back(t); } + private: std::string_view input; std::size_t offset; @@ -199,7 +209,7 @@ private: auto consume_ident(bool allow_number = false) -> struct css_parser_token; }; -} +}// namespace rspamd::css -#endif //RSPAMD_CSS_TOKENISER_HXX +#endif//RSPAMD_CSS_TOKENISER_HXX diff --git a/src/libserver/css/css_util.cxx b/src/libserver/css/css_util.cxx index 7add8043c..07f87229c 100644 --- a/src/libserver/css/css_util.cxx +++ b/src/libserver/css/css_util.cxx @@ -25,7 +25,7 @@ std::string_view unescape_css(rspamd_mempool_t *pool, { auto *nspace = reinterpret_cast<char *>(rspamd_mempool_alloc(pool, sv.length())); auto *d = nspace; - auto nleft = sv.length (); + auto nleft = sv.length(); enum { normal = 0, @@ -37,28 +37,29 @@ std::string_view unescape_css(rspamd_mempool_t *pool, char quote_char, prev_c = 0; auto escape_offset = 0, i = 0; -#define MAYBE_CONSUME_CHAR(c) do { \ - if ((c) == '"' || (c) == '\'') { \ - state = quoted; \ - quote_char = (c); \ - nleft--; \ - *d++ = (c); \ - } \ - else if ((c) == '\\') { \ - escape_offset = i; \ - state = escape; \ - } \ - else { \ - state = normal; \ - nleft--; \ - *d++ = g_ascii_tolower(c); \ - } \ -} while (0) +#define MAYBE_CONSUME_CHAR(c) \ + do { \ + if ((c) == '"' || (c) == '\'') { \ + state = quoted; \ + quote_char = (c); \ + nleft--; \ + *d++ = (c); \ + } \ + else if ((c) == '\\') { \ + escape_offset = i; \ + state = escape; \ + } \ + else { \ + state = normal; \ + nleft--; \ + *d++ = g_ascii_tolower(c); \ + } \ + } while (0) - for (const auto c : sv) { + for (const auto c: sv) { if (nleft == 0) { msg_err_css("cannot unescape css: truncated buffer of size %d", - (int)sv.length()); + (int) sv.length()); break; } switch (state) { @@ -72,7 +73,7 @@ std::string_view unescape_css(rspamd_mempool_t *pool, } } prev_c = c; - nleft --; + nleft--; *d++ = c; break; case escape: @@ -84,19 +85,19 @@ std::string_view unescape_css(rspamd_mempool_t *pool, if (!rspamd_xstrtoul(escape_start, i - escape_offset - 1, &val)) { msg_debug_css("invalid broken escape found at pos %d", - escape_offset); + escape_offset); } else { if (val < 0x80) { /* Trivial case: ascii character */ - *d++ = (unsigned char)g_ascii_tolower(val); - nleft --; + *d++ = (unsigned char) g_ascii_tolower(val); + nleft--; } else { UChar32 uc = val; auto off = 0; UTF8_APPEND_CHAR_SAFE((uint8_t *) d, off, - sv.length (), u_tolower(uc)); + sv.length(), u_tolower(uc)); d += off; nleft -= off; } @@ -105,16 +106,16 @@ std::string_view unescape_css(rspamd_mempool_t *pool, else { /* Empty escape, ignore it */ msg_debug_css("invalid empty escape found at pos %d", - escape_offset); + escape_offset); } if (nleft <= 0) { msg_err_css("cannot unescape css: truncated buffer of size %d", - (int)sv.length()); + (int) sv.length()); } else { /* Escape is done, advance forward */ - if (g_ascii_isspace (c)) { + if (g_ascii_isspace(c)) { state = skip_spaces; } else { @@ -131,21 +132,21 @@ std::string_view unescape_css(rspamd_mempool_t *pool, break; } - i ++; + i++; } return std::string_view{nspace, sv.size() - nleft}; } -} +}// namespace rspamd::css /* C API */ -const gchar *rspamd_css_unescape (rspamd_mempool_t *pool, - const guchar *begin, - gsize len, - gsize *outlen) +const gchar *rspamd_css_unescape(rspamd_mempool_t *pool, + const guchar *begin, + gsize len, + gsize *outlen) { - auto sv = rspamd::css::unescape_css(pool, {(const char*)begin, len}); + auto sv = rspamd::css::unescape_css(pool, {(const char *) begin, len}); const auto *v = sv.begin(); if (outlen) { diff --git a/src/libserver/css/css_util.hxx b/src/libserver/css/css_util.hxx index 5daf9ee82..4837a4611 100644 --- a/src/libserver/css/css_util.hxx +++ b/src/libserver/css/css_util.hxx @@ -32,6 +32,6 @@ namespace rspamd::css { std::string_view unescape_css(rspamd_mempool_t *pool, const std::string_view &sv); -} +}// namespace rspamd::css -#endif //RSPAMD_CSS_UTIL_HXX +#endif//RSPAMD_CSS_UTIL_HXX diff --git a/src/libserver/css/css_value.cxx b/src/libserver/css/css_value.cxx index 7a451e1e5..2546e0159 100644 --- a/src/libserver/css/css_value.cxx +++ b/src/libserver/css/css_value.cxx @@ -27,19 +27,23 @@ /* Helper for unit test stringification */ namespace doctest { -template<> struct StringMaker<rspamd::css::css_color> { - static String convert(const rspamd::css::css_color& value) { +template<> +struct StringMaker<rspamd::css::css_color> { + static String convert(const rspamd::css::css_color &value) + { return fmt::format("r={};g={};b={};alpha={}", - value.r, value.g, value.b, value.alpha).c_str(); + value.r, value.g, value.b, value.alpha) + .c_str(); } }; -} +}// namespace doctest namespace rspamd::css { auto css_value::maybe_color_from_string(const std::string_view &input) --> std::optional<css_value> { + -> std::optional<css_value> +{ if (input.size() > 1 && input.front() == '#') { return css_value::maybe_color_from_hex(input.substr(1)); @@ -55,44 +59,50 @@ auto css_value::maybe_color_from_string(const std::string_view &input) return std::nullopt; } -constexpr static inline auto hexpair_decode(char c1, char c2) -> std::uint8_t { +constexpr static inline auto hexpair_decode(char c1, char c2) -> std::uint8_t +{ std::uint8_t ret = 0; if (c1 >= '0' && c1 <= '9') ret = c1 - '0'; - else if (c1 >= 'A' && c1 <= 'F') ret = c1 - 'A' + 10; - else if (c1 >= 'a' && c1 <= 'f') ret = c1 - 'a' + 10; + else if (c1 >= 'A' && c1 <= 'F') + ret = c1 - 'A' + 10; + else if (c1 >= 'a' && c1 <= 'f') + ret = c1 - 'a' + 10; ret *= 16; if (c2 >= '0' && c2 <= '9') ret += c2 - '0'; - else if (c2 >= 'A' && c2 <= 'F') ret += c2 - 'A' + 10; - else if (c2 >= 'a' && c2 <= 'f') ret += c2 - 'a' + 10; + else if (c2 >= 'A' && c2 <= 'F') + ret += c2 - 'A' + 10; + else if (c2 >= 'a' && c2 <= 'f') + ret += c2 - 'a' + 10; return ret; } auto css_value::maybe_color_from_hex(const std::string_view &input) --> std::optional<css_value> { + -> std::optional<css_value> +{ if (input.length() == 6) { /* Plain RGB */ css_color col(hexpair_decode(input[0], input[1]), - hexpair_decode(input[2], input[3]), - hexpair_decode(input[4], input[5])); + hexpair_decode(input[2], input[3]), + hexpair_decode(input[4], input[5])); return css_value(col); } else if (input.length() == 3) { /* Rgb as 3 hex digests */ css_color col(hexpair_decode(input[0], input[0]), - hexpair_decode(input[1], input[1]), - hexpair_decode(input[2], input[2])); + hexpair_decode(input[1], input[1]), + hexpair_decode(input[2], input[2])); return css_value(col); } else if (input.length() == 8) { /* RGBA */ css_color col(hexpair_decode(input[0], input[1]), - hexpair_decode(input[2], input[3]), - hexpair_decode(input[4], input[5]), - hexpair_decode(input[6], input[7])); + hexpair_decode(input[2], input[3]), + hexpair_decode(input[4], input[5]), + hexpair_decode(input[6], input[7])); return css_value(col); } @@ -100,7 +110,8 @@ auto css_value::maybe_color_from_hex(const std::string_view &input) } constexpr static inline auto rgb_color_component_convert(const css_parser_token &tok) --> std::uint8_t { + -> std::uint8_t +{ std::uint8_t ret = 0; if (tok.type == css_parser_token::token_type::number_token) { @@ -113,7 +124,7 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token else if (dbl < 0) { dbl = 0; } - ret = (std::uint8_t) (dbl / 100.0 * 255.0); + ret = (std::uint8_t)(dbl / 100.0 * 255.0); } else { if (dbl > 255) { @@ -123,7 +134,7 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token dbl = 0; } - ret = (std::uint8_t) (dbl); + ret = (std::uint8_t)(dbl); } } @@ -131,7 +142,8 @@ constexpr static inline auto rgb_color_component_convert(const css_parser_token } constexpr static inline auto alpha_component_convert(const css_parser_token &tok) --> std::uint8_t { + -> std::uint8_t +{ double ret = 1.0; if (tok.type == css_parser_token::token_type::number_token) { @@ -158,11 +170,12 @@ constexpr static inline auto alpha_component_convert(const css_parser_token &tok } } - return (std::uint8_t) (ret * 255.0); + return (std::uint8_t)(ret * 255.0); } constexpr static inline auto h_component_convert(const css_parser_token &tok) --> double { + -> double +{ double ret = 0.0; if (tok.type == css_parser_token::token_type::number_token) { @@ -179,7 +192,7 @@ constexpr static inline auto h_component_convert(const css_parser_token &tok) } else { dbl = ((((int) dbl % 360) + 360) % 360); /* Deal with rotations */ - ret = dbl / 360.0; /* Normalize to 0..1 */ + ret = dbl / 360.0; /* Normalize to 0..1 */ } } @@ -187,7 +200,8 @@ constexpr static inline auto h_component_convert(const css_parser_token &tok) } constexpr static inline auto sl_component_convert(const css_parser_token &tok) --> double { + -> double +{ double ret = 0.0; if (tok.type == css_parser_token::token_type::number_token) { @@ -198,7 +212,8 @@ constexpr static inline auto sl_component_convert(const css_parser_token &tok) } static inline auto hsl_to_rgb(double h, double s, double l) --> css_color { + -> css_color +{ css_color ret; constexpr auto hue2rgb = [](auto p, auto q, auto t) -> auto { @@ -229,9 +244,9 @@ static inline auto hsl_to_rgb(double h, double s, double l) else { auto q = l <= 0.5 ? l * (1.0 + s) : l + s - l * s; auto p = 2.0 * l - q; - ret.r = (std::uint8_t) (hue2rgb(p, q, h + 1.0 / 3.0) * 255); - ret.g = (std::uint8_t) (hue2rgb(p, q, h) * 255); - ret.b = (std::uint8_t) (hue2rgb(p, q, h - 1.0 / 3.0) * 255); + ret.r = (std::uint8_t)(hue2rgb(p, q, h + 1.0 / 3.0) * 255); + ret.g = (std::uint8_t)(hue2rgb(p, q, h) * 255); + ret.b = (std::uint8_t)(hue2rgb(p, q, h - 1.0 / 3.0) * 255); } ret.alpha = 255; @@ -240,7 +255,8 @@ static inline auto hsl_to_rgb(double h, double s, double l) } auto css_value::maybe_color_from_function(const css_consumed_block::css_function_block &func) --> std::optional<css_value> { + -> std::optional<css_value> +{ if (func.as_string() == "rgb" && func.args.size() == 3) { css_color col{rgb_color_component_convert(func.args[0]->get_token_or_empty()), @@ -281,7 +297,8 @@ auto css_value::maybe_color_from_function(const css_consumed_block::css_function } auto css_value::maybe_dimension_from_number(const css_parser_token &tok) --> std::optional<css_value> { + -> std::optional<css_value> +{ if (std::holds_alternative<float>(tok.value)) { auto dbl = std::get<float>(tok.value); css_dimension dim; @@ -302,33 +319,34 @@ auto css_value::maybe_dimension_from_number(const css_parser_token &tok) } constexpr const auto display_names_map = frozen::make_unordered_map<frozen::string, css_display_value>({ - {"hidden", css_display_value::DISPLAY_HIDDEN}, - {"none", css_display_value::DISPLAY_HIDDEN}, - {"inline", css_display_value::DISPLAY_INLINE}, - {"block", css_display_value::DISPLAY_BLOCK}, - {"content", css_display_value::DISPLAY_INLINE}, - {"flex", css_display_value::DISPLAY_BLOCK}, - {"grid", css_display_value::DISPLAY_BLOCK}, - {"inline-block", css_display_value::DISPLAY_INLINE}, - {"inline-flex", css_display_value::DISPLAY_INLINE}, - {"inline-grid", css_display_value::DISPLAY_INLINE}, - {"inline-table", css_display_value::DISPLAY_INLINE}, - {"list-item", css_display_value::DISPLAY_BLOCK}, - {"run-in", css_display_value::DISPLAY_INLINE}, - {"table", css_display_value::DISPLAY_BLOCK}, - {"table-caption", css_display_value::DISPLAY_TABLE_ROW}, - {"table-column-group", css_display_value::DISPLAY_TABLE_ROW}, - {"table-header-group", css_display_value::DISPLAY_TABLE_ROW}, - {"table-footer-group", css_display_value::DISPLAY_TABLE_ROW}, - {"table-row-group", css_display_value::DISPLAY_TABLE_ROW}, - {"table-cell", css_display_value::DISPLAY_TABLE_ROW}, - {"table-column", css_display_value::DISPLAY_TABLE_ROW}, - {"table-row", css_display_value::DISPLAY_TABLE_ROW}, - {"initial", css_display_value::DISPLAY_INLINE}, + {"hidden", css_display_value::DISPLAY_HIDDEN}, + {"none", css_display_value::DISPLAY_HIDDEN}, + {"inline", css_display_value::DISPLAY_INLINE}, + {"block", css_display_value::DISPLAY_BLOCK}, + {"content", css_display_value::DISPLAY_INLINE}, + {"flex", css_display_value::DISPLAY_BLOCK}, + {"grid", css_display_value::DISPLAY_BLOCK}, + {"inline-block", css_display_value::DISPLAY_INLINE}, + {"inline-flex", css_display_value::DISPLAY_INLINE}, + {"inline-grid", css_display_value::DISPLAY_INLINE}, + {"inline-table", css_display_value::DISPLAY_INLINE}, + {"list-item", css_display_value::DISPLAY_BLOCK}, + {"run-in", css_display_value::DISPLAY_INLINE}, + {"table", css_display_value::DISPLAY_BLOCK}, + {"table-caption", css_display_value::DISPLAY_TABLE_ROW}, + {"table-column-group", css_display_value::DISPLAY_TABLE_ROW}, + {"table-header-group", css_display_value::DISPLAY_TABLE_ROW}, + {"table-footer-group", css_display_value::DISPLAY_TABLE_ROW}, + {"table-row-group", css_display_value::DISPLAY_TABLE_ROW}, + {"table-cell", css_display_value::DISPLAY_TABLE_ROW}, + {"table-column", css_display_value::DISPLAY_TABLE_ROW}, + {"table-row", css_display_value::DISPLAY_TABLE_ROW}, + {"initial", css_display_value::DISPLAY_INLINE}, }); auto css_value::maybe_display_from_string(const std::string_view &input) --> std::optional<css_value> { + -> std::optional<css_value> +{ auto f = display_names_map.find(input); if (f != display_names_map.end()) { @@ -339,7 +357,8 @@ auto css_value::maybe_display_from_string(const std::string_view &input) } -auto css_value::debug_str() const -> std::string { +auto css_value::debug_str() const -> std::string +{ std::string ret; std::visit([&](const auto &arg) { @@ -347,7 +366,7 @@ auto css_value::debug_str() const -> std::string { if constexpr (std::is_same_v<T, css_color>) { ret += fmt::format("color: r={};g={};b={};alpha={}", - arg.r, arg.g, arg.b, arg.alpha); + arg.r, arg.g, arg.b, arg.alpha); } else if constexpr (std::is_same_v<T, double>) { ret += "size: " + std::to_string(arg); @@ -381,47 +400,50 @@ auto css_value::debug_str() const -> std::string { else { ret += "nyi"; } - }, value); + }, + value); return ret; } -TEST_SUITE("css") { - TEST_CASE("css hex colors") { - const std::pair<const char*, css_color> hex_tests[] = { - {"000", css_color(0, 0, 0)}, - {"000000", css_color(0, 0, 0)}, - {"f00", css_color(255, 0, 0)}, - {"FEDCBA", css_color(254, 220, 186)}, - {"234", css_color(34, 51, 68)}, +TEST_SUITE("css"){ + TEST_CASE("css hex colors"){ + const std::pair<const char *, css_color> hex_tests[] = { + {"000", css_color(0, 0, 0)}, + {"000000", css_color(0, 0, 0)}, + {"f00", css_color(255, 0, 0)}, + {"FEDCBA", css_color(254, 220, 186)}, + {"234", css_color(34, 51, 68)}, }; - for (const auto &p : hex_tests) { - SUBCASE((std::string("parse hex color: ") + p.first).c_str()) { - auto col_parsed = css_value::maybe_color_from_hex(p.first); - //CHECK_UNARY(col_parsed); - //CHECK_UNARY(col_parsed.value().to_color()); - auto final_col = col_parsed.value().to_color().value(); - CHECK(final_col == p.second); - } - } +for (const auto &p: hex_tests) { + SUBCASE((std::string("parse hex color: ") + p.first).c_str()) + { + auto col_parsed = css_value::maybe_color_from_hex(p.first); + //CHECK_UNARY(col_parsed); + //CHECK_UNARY(col_parsed.value().to_color()); + auto final_col = col_parsed.value().to_color().value(); + CHECK(final_col == p.second); } - TEST_CASE("css colors strings") { - auto passed = 0; - for (const auto &p : css_colors_map) { - /* Match some of the colors selected randomly */ - if (rspamd_random_double_fast() > 0.9) { - auto col_parsed = css_value::maybe_color_from_string(p.first); - auto final_col = col_parsed.value().to_color().value(); - CHECK_MESSAGE(final_col == p.second, p.first.data()); - passed ++; - - if (passed > 20) { - break; - } +} +}// namespace rspamd::css +TEST_CASE("css colors strings") +{ + auto passed = 0; + for (const auto &p: css_colors_map) { + /* Match some of the colors selected randomly */ + if (rspamd_random_double_fast() > 0.9) { + auto col_parsed = css_value::maybe_color_from_string(p.first); + auto final_col = col_parsed.value().to_color().value(); + CHECK_MESSAGE(final_col == p.second, p.first.data()); + passed++; + + if (passed > 20) { + break; } } } -}; - +} +} +; } diff --git a/src/libserver/css/css_value.hxx b/src/libserver/css/css_value.hxx index 8dcfa63da..1d5742126 100644 --- a/src/libserver/css/css_value.hxx +++ b/src/libserver/css/css_value.hxx @@ -37,29 +37,36 @@ struct alignas(int) css_color { std::uint8_t alpha; - css_color(std::uint8_t _r, std::uint8_t _g, std::uint8_t _b, std::uint8_t _alpha = 255) : - r(_r), g(_g), b(_b), alpha(_alpha) {} + css_color(std::uint8_t _r, std::uint8_t _g, std::uint8_t _b, std::uint8_t _alpha = 255) + : r(_r), g(_g), b(_b), alpha(_alpha) + { + } css_color() = default; - constexpr auto to_number() const -> std::uint32_t { - return (std::uint32_t)alpha << 24 | - (std::uint32_t)r << 16 | - (std::uint32_t)g << 8 | - (std::uint32_t)b << 0; + constexpr auto to_number() const -> std::uint32_t + { + return (std::uint32_t) alpha << 24 | + (std::uint32_t) r << 16 | + (std::uint32_t) g << 8 | + (std::uint32_t) b << 0; } - constexpr auto to_rgb() const -> std::uint32_t { - return (std::uint32_t)r << 16 | - (std::uint32_t)g << 8 | - (std::uint32_t)b << 0; + constexpr auto to_rgb() const -> std::uint32_t + { + return (std::uint32_t) r << 16 | + (std::uint32_t) g << 8 | + (std::uint32_t) b << 0; } - friend bool operator==(const css_color& l, const css_color& r) { + friend bool operator==(const css_color &l, const css_color &r) + { return (memcmp(&l, &r, sizeof(css_color)) == 0); } - static auto white() -> css_color { + static auto white() -> css_color + { return css_color{255, 255, 255}; } - static auto black() -> css_color { + static auto black() -> css_color + { return css_color{0, 0, 0}; } }; @@ -85,38 +92,54 @@ enum class css_display_value : std::uint8_t { */ struct css_value { std::variant<css_color, - float, - css_display_value, - css_dimension, - std::monostate> value; - - css_value() {} - css_value(const css_color &color) : - value(color) {} - css_value(float num) : - value(num) {} - css_value(css_dimension dim) : - value(dim) {} - css_value(css_display_value d) : - value(d) {} - - auto to_color(void) const -> std::optional<css_color> { + float, + css_display_value, + css_dimension, + std::monostate> + value; + + css_value() + { + } + css_value(const css_color &color) + : value(color) + { + } + css_value(float num) + : value(num) + { + } + css_value(css_dimension dim) + : value(dim) + { + } + css_value(css_display_value d) + : value(d) + { + } + + auto to_color(void) const -> std::optional<css_color> + { return extract_value_maybe<css_color>(); } - auto to_number(void) const -> std::optional<float> { + auto to_number(void) const -> std::optional<float> + { return extract_value_maybe<float>(); } - auto to_dimension(void) const -> std::optional<css_dimension> { + auto to_dimension(void) const -> std::optional<css_dimension> + { return extract_value_maybe<css_dimension>(); } - auto to_display(void) const -> std::optional<css_display_value> { + auto to_display(void) const -> std::optional<css_display_value> + { return extract_value_maybe<css_display_value>(); } - auto is_valid(void) const -> bool { + auto is_valid(void) const -> bool + { return !(std::holds_alternative<std::monostate>(value)); } @@ -132,9 +155,11 @@ struct css_value { -> std::optional<css_value>; static auto maybe_display_from_string(const std::string_view &input) -> std::optional<css_value>; + private: template<typename T> - auto extract_value_maybe(void) const -> std::optional<T> { + auto extract_value_maybe(void) const -> std::optional<T> + { if (std::holds_alternative<T>(value)) { return std::get<T>(value); } @@ -143,7 +168,7 @@ private: } }; -} +}// namespace rspamd::css -#endif //RSPAMD_CSS_VALUE_HXX +#endif//RSPAMD_CSS_VALUE_HXX diff --git a/src/libserver/css/parse_error.hxx b/src/libserver/css/parse_error.hxx index 57ff0c0ce..22b76f028 100644 --- a/src/libserver/css/parse_error.hxx +++ b/src/libserver/css/parse_error.hxx @@ -42,15 +42,20 @@ struct css_parse_error { css_parse_error_type type = css_parse_error_type::PARSE_ERROR_UNKNOWN_ERROR; std::optional<std::string> description; - explicit css_parse_error (css_parse_error_type type, const std::string &description) : - type(type), description(description) {} - explicit css_parse_error (css_parse_error_type type = css_parse_error_type::PARSE_ERROR_NO_ERROR) : - type(type) {} + explicit css_parse_error(css_parse_error_type type, const std::string &description) + : type(type), description(description) + { + } + explicit css_parse_error(css_parse_error_type type = css_parse_error_type::PARSE_ERROR_NO_ERROR) + : type(type) + { + } - constexpr auto is_fatal(void) const -> bool { + constexpr auto is_fatal(void) const -> bool + { return type < css_parse_error_type::PARSE_ERROR_NO_ERROR; } }; -} -#endif //RSPAMD_PARSE_ERROR_HXX +}// namespace rspamd::css +#endif//RSPAMD_PARSE_ERROR_HXX |