diff options
-rw-r--r-- | net/base/net_util.cc | 57 | ||||
-rw-r--r-- | net/base/net_util.h | 2 | ||||
-rw-r--r-- | net/base/net_util_unittest.cc | 13 |
3 files changed, 42 insertions, 30 deletions
diff --git a/net/base/net_util.cc b/net/base/net_util.cc index a1b4b73..5c042d1 100644 --- a/net/base/net_util.cc +++ b/net/base/net_util.cc @@ -965,37 +965,44 @@ bool GetHostAndPort(std::string::const_iterator host_and_port_begin, if (host_and_port_begin >= host_and_port_end) return false; - // TODO(eroman): support IPv6 literals. - std::string::const_iterator colon = - std::find(host_and_port_begin, host_and_port_end, ':'); - - if (colon == host_and_port_end) { - // No colon. - host->assign(host_and_port_begin, host_and_port_end); - *port = -1; - return true; - } + // When using url_parse, we use char*. + const char* auth_begin = &(*host_and_port_begin); + int auth_len = host_and_port_end - host_and_port_begin; - if (colon == host_and_port_begin) - return false; // No host. + url_parse::Component auth_component(0, auth_len); + url_parse::Component username_component; + url_parse::Component password_component; + url_parse::Component hostname_component; + url_parse::Component port_component; - if (colon == host_and_port_end - 1) - return false; // There is nothing past the colon. + url_parse::ParseAuthority(auth_begin, auth_component, &username_component, + &password_component, &hostname_component, &port_component); - // Parse the port number to an integer. - std::string port_string(colon + 1, host_and_port_end); - int parsed_port_number = url_parse::ParsePort(port_string.data(), - url_parse::Component(0, port_string.size())); + // There shouldn't be a username/password. + if (username_component.is_valid() || password_component.is_valid()) + return false; - // If parsing failed, port_number will be either PORT_INVALID or - // PORT_UNSPECIFIED, both of which are negative. - if (parsed_port_number < 0) - return false; // Failed parsing the port number. + if (!hostname_component.is_nonempty()) + return false; // Failed parsing. - // Else successfully parsed port number. + int parsed_port_number = -1; + if (port_component.is_nonempty()) { + parsed_port_number = url_parse::ParsePort(auth_begin, port_component); + + // If parsing failed, port_number will be either PORT_INVALID or + // PORT_UNSPECIFIED, both of which are negative. + if (parsed_port_number < 0) + return false; // Failed parsing the port number. + } + + if (port_component.len == 0) + return false; // Reject inputs like "foo:" + + // Pass results back to caller. + host->assign(auth_begin + hostname_component.begin, hostname_component.len); *port = parsed_port_number; - host->assign(host_and_port_begin, colon); - return true; + + return true; // Success. } bool GetHostAndPort(const std::string& host_and_port, diff --git a/net/base/net_util.h b/net/base/net_util.h index e62e95a..1fda9bd 100644 --- a/net/base/net_util.h +++ b/net/base/net_util.h @@ -44,7 +44,7 @@ bool FileURLToFilePath(const GURL& url, std::wstring* file_path); // Saves the result into |*host| and |*port|. If the input did not have // the optional port, sets |*port| to -1. // Returns true if the parsing was successful, false otherwise. -// TODO(eroman): support IPv6 literals. +// The returned host is NOT canonicalized, and may be invalid. bool GetHostAndPort(std::string::const_iterator host_and_port_begin, std::string::const_iterator host_and_port_end, std::string* host, diff --git a/net/base/net_util_unittest.cc b/net/base/net_util_unittest.cc index d3f7b83..c83d510 100644 --- a/net/base/net_util_unittest.cc +++ b/net/base/net_util_unittest.cc @@ -747,11 +747,10 @@ TEST(NetUtilTest, GetHostAndPort) { {"foo:10", true, "foo", 10}, {"foo", true, "foo", -1}, { - // TODO(eroman): support IPv6 literals. "[1080:0:0:0:8:800:200C:4171]:11", - false, - "", - -1, + true, + "[1080:0:0:0:8:800:200C:4171]", + 11, }, // Invalid inputs: {"foo:bar", false, "", -1}, @@ -760,6 +759,12 @@ TEST(NetUtilTest, GetHostAndPort) { {":80", false, "", -1}, {"", false, "", -1}, {"porttoolong:300000", false, "", -1}, + {"usrname@host", false, "", -1}, + {"usrname:password@host", false, "", -1}, + {":password@host", false, "", -1}, + {":password@host:80", false, "", -1}, + {":password@host", false, "", -1}, + {"@host", false, "", -1}, }; for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { |