ParseUrl::ParseResult ParseUrl::Parse()

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;
}