diff --git a/include/boost/url/impl/url_view.ipp b/include/boost/url/impl/url_view.ipp index af725c8d..c66cfd54 100644 --- a/include/boost/url/impl/url_view.ipp +++ b/include/boost/url/impl/url_view.ipp @@ -165,7 +165,7 @@ has_userinfo() const noexcept bool url_view:: -has_user() const noexcept +has_username() const noexcept { auto const n = len( detail::id_user); @@ -209,7 +209,7 @@ encoded_userinfo() const noexcept string_view url_view:: -encoded_user() const noexcept +encoded_username() const noexcept { auto s = pt_.get( detail::id_user, @@ -819,11 +819,11 @@ apply_authority(parts& p, { p.resize( part::id_user, - u->user.str.size() + 2); - if(u->pass.has_value()) + u->username.str.size() + 2); + if(u->password.has_value()) p.resize( part::id_password, - u->pass->str.size() + 2); + u->password->str.size() + 2); else p.resize( part::id_password, 1); diff --git a/include/boost/url/rfc/impl/userinfo_bnf.ipp b/include/boost/url/rfc/impl/userinfo_bnf.ipp index a8ae5ffa..228a246b 100644 --- a/include/boost/url/rfc/impl/userinfo_bnf.ipp +++ b/include/boost/url/rfc/impl/userinfo_bnf.ipp @@ -45,11 +45,11 @@ parse( return false; t.str = string_view( start, it - start); - t.user = user; + t.username = user; if(colon.has_value()) - t.pass = pass; + t.password = pass; else - t.pass.reset(); + t.password.reset(); return true; } diff --git a/include/boost/url/rfc/userinfo_bnf.hpp b/include/boost/url/rfc/userinfo_bnf.hpp index 1c523e00..77380267 100644 --- a/include/boost/url/rfc/userinfo_bnf.hpp +++ b/include/boost/url/rfc/userinfo_bnf.hpp @@ -24,9 +24,9 @@ namespace rfc { @par BNF @code - userinfo = user [ ":" [ password ] ] + userinfo = username [ ":" [ password ] ] - user = *( unreserved / pct-encoded / sub-delims ) + username = *( unreserved / pct-encoded / sub-delims ) password = *( unreserved / pct-encoded / sub-delims / ":" ) @endcode @@ -36,9 +36,8 @@ namespace rfc { struct userinfo_bnf { string_view str; - pct_encoded_str user; - optional< - pct_encoded_str> pass; + pct_encoded_str username; + optional password; BOOST_URL_DECL friend diff --git a/include/boost/url/url_view.hpp b/include/boost/url/url_view.hpp index 597375fe..a0f662f6 100644 --- a/include/boost/url/url_view.hpp +++ b/include/boost/url/url_view.hpp @@ -133,7 +133,7 @@ public: /** Return the userinfo if present, or an empty string Returns the userinfo of the URL as an encoded - string. The userinfo includes the user and + string. The userinfo includes the username and password, with a colon separating the components if the password is not empty. @@ -145,17 +145,46 @@ public: string_view encoded_userinfo() const noexcept; - /** Return true if the URL contains a user + /** Return the userinfo if present, or an empty string + + This function returns the userinfo part + of the URL if present, as a decoded string. + + @par Exception Safety + + Strong guarantee. + Calls to allocate may throw. + + @param a An optional allocator the returned + string will use. If this parameter is omitted, + the default allocator is used, and the return + type of the function becomes `std::string`. + + @return A `std::basic_string` using the + specified allocator. + */ + template< + class Allocator = + std::allocator> + string_type + userinfo( + Allocator const& a = {}) const + { + return detail::decode( + encoded_userinfo(), a); + } + + /** Return true if the URL contains a username */ BOOST_URL_DECL bool - has_user() const noexcept; + has_username() const noexcept; - /** Return the user if present, or an empty string + /** Return the username if present, or an empty string - This function returns the user portion of + This function returns the username portion of the userinfo if present, as an encoded string. - The user portion is defined by all of the + The username portion is defined by all of the characters in the userinfo up to but not including the first colon (':"), or the entire userinfo if no colon is present. @@ -166,13 +195,13 @@ public: */ BOOST_URL_DECL string_view - encoded_user() const noexcept; + encoded_username() const noexcept; - /** Return the user if present, or an empty string + /** Return the username if present, or an empty string - This function returns the user portion of + This function returns the username portion of the userinfo if present, as a decoded string. - The user portion is defined by all of the + The username portion is defined by all of the characters in the userinfo up to but not including the first colon (':"), or the entire userinfo if no colon is present. @@ -194,11 +223,11 @@ public: class Allocator = std::allocator> string_type - user( + username( Allocator const& a = {}) const { return detail::decode( - encoded_user(), a); + encoded_username(), a); } /** Return true if the URL contains a password @@ -226,6 +255,8 @@ public: encoded_password(), a); } + //-------------------------------------------- + /** Return the type of host present, if any. @par Exception Safety diff --git a/test/rfc/authority_bnf.cpp b/test/rfc/authority_bnf.cpp index 884f4794..89f221f7 100644 --- a/test/rfc/authority_bnf.cpp +++ b/test/rfc/authority_bnf.cpp @@ -55,9 +55,9 @@ public: if(BOOST_TEST(p.userinfo.has_value())) { BOOST_TEST(p.userinfo->str == "x:y"); - BOOST_TEST(p.userinfo->user.str == "x"); - if(BOOST_TEST(p.userinfo->pass.has_value())) - BOOST_TEST(p.userinfo->pass->str == "y"); + BOOST_TEST(p.userinfo->username.str == "x"); + if(BOOST_TEST(p.userinfo->password.has_value())) + BOOST_TEST(p.userinfo->password->str == "y"); } } } diff --git a/test/rfc/userinfo_bnf.cpp b/test/rfc/userinfo_bnf.cpp index c0a7633c..60d4ccf8 100644 --- a/test/rfc/userinfo_bnf.cpp +++ b/test/rfc/userinfo_bnf.cpp @@ -38,13 +38,13 @@ public: if(! BOOST_TEST(! ec)) return; BOOST_TEST(p.str == s); - BOOST_TEST(p.user.str == s1); + BOOST_TEST(p.username.str == s1); if(s2.has_value()) BOOST_TEST( - p.pass.has_value() && - p.pass->str == *s2); + p.password.has_value() && + p.password->str == *s2); else - BOOST_TEST(! p.pass.has_value()); + BOOST_TEST(! p.password.has_value()); } void diff --git a/test/url_view.cpp b/test/url_view.cpp index d223d530..a77d72a4 100644 --- a/test/url_view.cpp +++ b/test/url_view.cpp @@ -36,14 +36,14 @@ public: BOOST_TEST(url_view("//example.com").host_type() == host_type::name); BOOST_TEST(url_view("//127.0.0.1.9").host_type() == host_type::name); - url_view const v("http://user:pass@example.com:80/path/to/file.txt?k1=v1&k2=v2"); - BOOST_TEST(v.encoded_url() == "http://user:pass@example.com:80/path/to/file.txt?k1=v1&k2=v2"); - BOOST_TEST(v.encoded_origin() == "http://user:pass@example.com:80"); - BOOST_TEST(v.encoded_authority() == "user:pass@example.com:80"); + url_view const v("http://username:pass@example.com:80/path/to/file.txt?k1=v1&k2=v2"); + BOOST_TEST(v.encoded_url() == "http://username:pass@example.com:80/path/to/file.txt?k1=v1&k2=v2"); + BOOST_TEST(v.encoded_origin() == "http://username:pass@example.com:80"); + BOOST_TEST(v.encoded_authority() == "username:pass@example.com:80"); BOOST_TEST(v.scheme() == "http"); - BOOST_TEST(v.encoded_user() == "user"); + BOOST_TEST(v.encoded_username() == "username"); BOOST_TEST(v.encoded_password() == "pass"); - BOOST_TEST(v.encoded_userinfo() == "user:pass"); + BOOST_TEST(v.encoded_userinfo() == "username:pass"); BOOST_TEST(v.encoded_host() == "example.com"); BOOST_TEST(v.has_port()); BOOST_TEST(v.port() == "80"); @@ -52,7 +52,7 @@ public: BOOST_TEST(v.encoded_query() == "k1=v1&k2=v2"); BOOST_TEST(v.encoded_fragment() == ""); - BOOST_TEST(v.user() == "user"); + BOOST_TEST(v.username() == "username"); BOOST_TEST(v.password() == "pass"); BOOST_TEST(v.host() == "example.com"); BOOST_TEST(v.query() == "k1=v1&k2=v2"); @@ -64,25 +64,25 @@ public: void testUser() { - BOOST_TEST(url_view().user() == ""); - BOOST_TEST(url_view("//x/").user() == ""); - BOOST_TEST(url_view("//x@/").user() == "x"); - BOOST_TEST(url_view("//x:@/").user() == "x"); - BOOST_TEST(url_view("//x:y@/").user() == "x"); - BOOST_TEST(url_view("//:y@/").user() == ""); - BOOST_TEST(url_view("//:@/").user() == ""); - BOOST_TEST(url_view("//@/").user() == ""); - BOOST_TEST(url_view("//%3A@/").user() == ":"); + BOOST_TEST(url_view().username() == ""); + BOOST_TEST(url_view("//x/").username() == ""); + BOOST_TEST(url_view("//x@/").username() == "x"); + BOOST_TEST(url_view("//x:@/").username() == "x"); + BOOST_TEST(url_view("//x:y@/").username() == "x"); + BOOST_TEST(url_view("//:y@/").username() == ""); + BOOST_TEST(url_view("//:@/").username() == ""); + BOOST_TEST(url_view("//@/").username() == ""); + BOOST_TEST(url_view("//%3A@/").username() == ":"); - BOOST_TEST(url_view().encoded_user() == ""); - BOOST_TEST(url_view("//x/").encoded_user() == ""); - BOOST_TEST(url_view("//x@/").encoded_user() == "x"); - BOOST_TEST(url_view("//x:@/").encoded_user() == "x"); - BOOST_TEST(url_view("//x:y@/").encoded_user() == "x"); - BOOST_TEST(url_view("//:y@/").encoded_user() == ""); - BOOST_TEST(url_view("//:@/").encoded_user() == ""); - BOOST_TEST(url_view("//@/").encoded_user() == ""); - BOOST_TEST(url_view("//%3A@/").encoded_user() == "%3A"); + BOOST_TEST(url_view().encoded_username() == ""); + BOOST_TEST(url_view("//x/").encoded_username() == ""); + BOOST_TEST(url_view("//x@/").encoded_username() == "x"); + BOOST_TEST(url_view("//x:@/").encoded_username() == "x"); + BOOST_TEST(url_view("//x:y@/").encoded_username() == "x"); + BOOST_TEST(url_view("//:y@/").encoded_username() == ""); + BOOST_TEST(url_view("//:@/").encoded_username() == ""); + BOOST_TEST(url_view("//@/").encoded_username() == ""); + BOOST_TEST(url_view("//%3A@/").encoded_username() == "%3A"); } //------------------------------------------------------ @@ -432,61 +432,99 @@ public: auto u = parse_uri("x://@"); BOOST_TEST(u.has_userinfo()); BOOST_TEST(u.encoded_userinfo() == ""); - BOOST_TEST(u.has_user() == false); - BOOST_TEST(u.encoded_user() == ""); + BOOST_TEST(u.userinfo() == ""); + BOOST_TEST(u.has_username() == false); + BOOST_TEST(u.encoded_username() == ""); + BOOST_TEST(u.username() == ""); BOOST_TEST(u.has_password() == false); BOOST_TEST(u.encoded_password() == ""); + BOOST_TEST(u.password() == ""); } { auto u = parse_uri("x://:@"); BOOST_TEST(u.has_userinfo()); BOOST_TEST(u.encoded_userinfo() == ":"); - BOOST_TEST(u.has_user() == false); - BOOST_TEST(u.encoded_user() == ""); + BOOST_TEST(u.userinfo() == ":"); + BOOST_TEST(u.has_username() == false); + BOOST_TEST(u.encoded_username() == ""); + BOOST_TEST(u.username() == ""); BOOST_TEST(u.has_password() == true); BOOST_TEST(u.encoded_password() == ""); + BOOST_TEST(u.password() == ""); } { - auto u = parse_uri("x://a:@"); + auto u = parse_uri("x://a%41:@"); BOOST_TEST(u.has_userinfo()); - BOOST_TEST(u.encoded_userinfo() == "a:"); - BOOST_TEST(u.has_user() == true); - BOOST_TEST(u.encoded_user() == "a"); + BOOST_TEST(u.encoded_userinfo() == "a%41:"); + BOOST_TEST(u.has_username() == true); + BOOST_TEST(u.encoded_username() == "a%41"); + BOOST_TEST(u.username() == "aA"); BOOST_TEST(u.has_password() == true); BOOST_TEST(u.encoded_password() == ""); + BOOST_TEST(u.password() == ""); } { - auto u = parse_uri("x://:b@"); + auto u = parse_uri("x://:b%42@"); BOOST_TEST(u.has_userinfo()); - BOOST_TEST(u.encoded_userinfo() == ":b"); - BOOST_TEST(u.has_user() == false); - BOOST_TEST(u.encoded_user() == ""); + BOOST_TEST(u.encoded_userinfo() == ":b%42"); + BOOST_TEST(u.has_username() == false); + BOOST_TEST(u.encoded_username() == ""); + BOOST_TEST(u.username() == ""); BOOST_TEST(u.has_password() == true); - BOOST_TEST(u.encoded_password() == "b"); + BOOST_TEST(u.encoded_password() == "b%42"); + BOOST_TEST(u.password() == "bB"); } { auto u = parse_uri("x://a:b@"); BOOST_TEST(u.has_userinfo()); BOOST_TEST(u.encoded_userinfo() == "a:b"); - BOOST_TEST(u.has_user() == true); - BOOST_TEST(u.encoded_user() == "a"); + BOOST_TEST(u.has_username() == true); + BOOST_TEST(u.encoded_username() == "a"); BOOST_TEST(u.has_password() == true); BOOST_TEST(u.encoded_password() == "b"); } + { + auto u = parse_uri("x://%3a:%3a@"); + BOOST_TEST(u.has_userinfo()); + BOOST_TEST(u.encoded_userinfo() == "%3a:%3a"); + BOOST_TEST(u.userinfo() == ":::"); + BOOST_TEST(u.has_username() == true); + BOOST_TEST(u.encoded_username() == "%3a"); + BOOST_TEST(u.username() == ":"); + BOOST_TEST(u.has_password() == true); + BOOST_TEST(u.encoded_password() == "%3a"); + BOOST_TEST(u.password() == ":"); + } + { + auto u = parse_uri("x://%2525@"); + BOOST_TEST(u.has_userinfo()); + BOOST_TEST(u.encoded_userinfo() == "%2525"); + BOOST_TEST(u.userinfo() == "%25"); + BOOST_TEST(u.has_username() == true); + BOOST_TEST(u.encoded_username() == "%2525"); + BOOST_TEST(u.username() == "%25"); + BOOST_TEST(u.has_password() == false); + BOOST_TEST(u.encoded_password() == ""); + BOOST_TEST(u.password() == ""); + } } + //-------------------------------------------- + + //-------------------------------------------- + void testParseUri() { error_code ec; auto const u = urls::parse_uri( - "http://user:pass@www.boost.org:8080/x/y/z?a=b&c=3#frag", + "http://username:pass@www.boost.org:8080/x/y/z?a=b&c=3#frag", ec); if(! BOOST_TEST(! ec)) return; BOOST_TEST(u.has_value()); BOOST_TEST(u->scheme() == "http"); - BOOST_TEST(u->user() == "user"); + BOOST_TEST(u->username() == "username"); BOOST_TEST(u->password() == "pass"); BOOST_TEST(u->host() == "www.boost.org"); BOOST_TEST(u->port() == "8080");