in database/src/desktop/util_desktop.cc [267:361]
ParseUrl::ParseResult ParseUrl::Parse(const std::string& url) {
hostname.clear();
ns.clear();
secure = true;
path.clear();
if (url.empty()) {
return kParseErrorEmpty;
}
// Find the protocol. It is ok to not specify any protocol. If not, it
// defaults to a secured connection.
int protocol_end = url.find("://");
int hostname_start = 0;
if (protocol_end != std::string::npos) {
if (protocol_end == 4 && url.compare(0, protocol_end, "http") == 0) {
hostname_start = 7; // "http://"
secure = false;
} else if (protocol_end == 5 &&
url.compare(0, protocol_end, "https") == 0) {
hostname_start = 8; // "https://"
} else {
return kParseErrorUnknownProtocol;
}
}
// hostname_end is the index of the first '/' or the length of the hostname if
// no '/' is found
int hostname_end = url.find_first_of('/', hostname_start);
if (hostname_end == std::string::npos) {
// Hostname does not end with '/'
hostname_end = url.length();
}
if (hostname_end == hostname_start) {
return kParseErrorEmptyHostname;
}
hostname = url.substr(hostname_start, hostname_end - hostname_start);
if ((hostname_end + 1) < url.length()) {
path = url.substr(hostname_end + 1, url.length() - hostname_end - 1);
}
// Starting position of current segment, which is separated by '.'
auto it_seg_start = hostname.begin();
// Starting position of port number after the first ':'
// Port number is optional.
auto it_port_start = hostname.end();
for (auto it_char = hostname.begin(); it_char != hostname.end(); ++it_char) {
if (it_port_start == hostname.end()) {
// Parsing non-port section
if (*it_char == '.' || *it_char == ':') {
if (it_char == it_seg_start) {
return kParseErrorEmptySegment;
} else {
// If this is the end of the first segment, this segment should be the
// namespace
if (it_seg_start == hostname.begin()) {
ns = std::string(it_seg_start, it_char);
}
it_seg_start = it_char + 1;
// Start port parsing
if (*it_char == ':') {
it_port_start = it_char + 1;
}
}
} else if (!isalnum(*it_char) && *it_char != '-') {
// unsupported character
return kParseErrorUnsupportedCharacter;
}
} else {
// parsing the port section
if (!isdigit(*it_char)) {
return kParseErrorInvalidPort;
}
}
}
// Check the last segment
if (it_seg_start == hostname.end()) {
return kParseErrorEmptySegment;
}
if (ns.empty()) {
return kParseErrorEmptyNamespace;
}
return kParseOk;
}