diff --git a/ircd/rfc3986.cc b/ircd/rfc3986.cc index 5750bc854..761c3e3b1 100644 --- a/ircd/rfc3986.cc +++ b/ircd/rfc3986.cc @@ -8,16 +8,6 @@ // copyright notice and this permission notice is present in all copies. The // full license for this software is available in the LICENSE file. -#pragma GCC visibility push(internal) -namespace ircd::rfc3986 -{ - using namespace ircd::spirit; - - struct encoder extern const encoder; - struct decoder extern const decoder; -} -#pragma GCC visibility pop - namespace ircd::rfc3986::parser { using namespace ircd::spirit; @@ -433,56 +423,62 @@ ircd::rfc3986::uri::uri(const string_view &input) // uri decoding // -struct [[gnu::visibility("internal")]] -ircd::rfc3986::decoder +namespace ircd::rfc3986::parser::decoder { template - using rule = qi::rule; - - [[noreturn]] static void throw_unsafe() + struct [[gnu::visibility("internal")]] rule + :qi::rule { - throw decoding_error + using qi::rule::rule; + }; + + static const auto is_safe + { + [](const char val, auto &c, bool &pass) { - "Unsafe characters in decoding." - }; - } + pass = (val > 0x1F) | (val < 0x00); + attr_at<0>(c) = val; + } + }; - const rule decode_char + const expr decode_char { - lit('%') > qi::uint_parser{} + lit('%') > qi::int_parser{} ,"url decodable character" }; - const rule unreserved_char + const rule decode_char_safe { - // unreserved characters and !$+*'(), - //char_("A-Za-z0-9._~!$+*'(),-") + lit('%') > qi::int_parser{}[is_safe] + ,"url decodable character" + }; + const expr unreserved_char + { + //char_("A-Za-z0-9._~!$+*'(),-") //NOTE: allow any non-control character here. No reason for trouble with //NOTE: already-decoded inputs unless some other grammar expects it. (~ascii::cntrl) - '%' ,"url unreserved characters" }; + const rule decode_safe + { + *(unreserved_char | decode_char_safe) + ,"url safe decode" + }; + const rule decode_unsafe { *((char_ - '%') | decode_char) ,"url unsafe decode" }; - - rule decode_safe - { - *(unreserved_char | decode_char[_pass = ((local::_1 > 0x1F) | (local::_1 < 0x00))]) - ,"url safe decode" - }; } -const ircd::rfc3986::decoder; ircd::const_buffer ircd::rfc3986::decode_unsafe(const mutable_buffer &buf, const string_view &url) -try { const char *start(url.data()), *const stop { @@ -496,7 +492,7 @@ try const bool ok { - ircd::parse(start, stop, decoder.decode_unsafe, mb) + ircd::parse(std::nothrow, start, stop, parser::decoder::decode_unsafe, mb) }; assert(size(mb) <= size(url)); @@ -505,15 +501,10 @@ try data(mb), size(mb) }; } -catch(const qi::expectation_failure &e) -{ - throw expectation_failure{e}; -} ircd::string_view ircd::rfc3986::decode(const mutable_buffer &buf, const string_view &url) -try { const char *start(url.data()), *const stop { @@ -527,7 +518,7 @@ try const bool ok { - ircd::parse(start, stop, decoder.decode_safe, mb) + ircd::parse(start, stop, parser::decoder::decode_safe, mb) }; assert(size(mb) <= size(url)); @@ -536,22 +527,20 @@ try data(mb), size(mb) }; } -catch(const qi::expectation_failure &e) -{ - throw expectation_failure{e}; -} // // uri encoding // -struct [[gnu::visibility("internal")]] -ircd::rfc3986::encoder -:karma::grammar +namespace ircd::rfc3986::parser::encoder { template - using rule = karma::rule; + struct [[gnu::visibility("internal")]] rule + :karma::rule + { + using karma::rule::rule; + }; const rule unreserved { @@ -564,12 +553,7 @@ ircd::rfc3986::encoder *(unreserved | (lit('%') << karma::right_align(2, '0')[karma::upper[karma::hex]])) ,"url encode" }; - - encoder() - :encoder::base_type{encode} - {} } -const ircd::rfc3986::encoder; ircd::string_view ircd::rfc3986::encode(const mutable_buffer &out, @@ -616,7 +600,7 @@ ircd::rfc3986::encode(const mutable_buffer &buf_, const bool ok { - ircd::generate(buf, encoder, url) + ircd::generate(buf, parser::encoder::encode, url) }; return string_view @@ -802,7 +786,7 @@ ircd::rfc3986::valid(std::nothrow_t, { const parser::rule<> only_rule { - rule >> eoi + rule >> parser::eoi }; const char *start(str.data()), *const stop(start + str.size()); @@ -812,17 +796,12 @@ ircd::rfc3986::valid(std::nothrow_t, void ircd::rfc3986::valid(const parser::rule<> &rule, const string_view &str) -try { const parser::rule<> only_rule { - eps > (rule >> eoi) + parser::eps > (rule >> parser::eoi) }; const char *start(str.data()), *const stop(start + str.size()); - ircd::parse(start, stop, only_rule); -} -catch(const qi::expectation_failure &e) -{ - throw expectation_failure{e}; + ircd::parse(start, stop, only_rule); }