diff --git a/panda/src/downloader/urlSpec.I b/panda/src/downloader/urlSpec.I index d639ac0c68..299a54eed5 100644 --- a/panda/src/downloader/urlSpec.I +++ b/panda/src/downloader/urlSpec.I @@ -23,8 +23,8 @@ // Description: //////////////////////////////////////////////////////////////////// INLINE URLSpec:: -URLSpec(const string &url) { - (*this) = url; +URLSpec(const string &url, bool server_name_expected) { + set_url(url, server_name_expected); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/downloader/urlSpec.cxx b/panda/src/downloader/urlSpec.cxx index fdd34b28f8..2b60eabebb 100644 --- a/panda/src/downloader/urlSpec.cxx +++ b/panda/src/downloader/urlSpec.cxx @@ -67,15 +67,15 @@ operator = (const URLSpec ©) { //////////////////////////////////////////////////////////////////// // Function: URLSpec::get_scheme // Access: Published -// Description: Returns the scheme specified by the URL, or "http" -// if no scheme is specified. +// Description: Returns the scheme specified by the URL, or empty +// string if no scheme is specified. //////////////////////////////////////////////////////////////////// string URLSpec:: get_scheme() const { if (has_scheme()) { return _url.substr(0, _scheme_end); } - return "http"; + return string(); } //////////////////////////////////////////////////////////////////// @@ -365,10 +365,12 @@ set_query(const string &query) { // Function: URLSpec::set_url // Access: Published // Description: Completely replaces the URL with the indicated -// string. +// string. If server_name_expected is true, it is a +// hint that an undecorated URL is probably a server +// name, not a local filename. //////////////////////////////////////////////////////////////////// void URLSpec:: -set_url(const string &url) { +set_url(const string &url, bool server_name_expected) { _url = url; _flags = 0; @@ -390,7 +392,7 @@ set_url(const string &url) { _scheme_end = start; size_t next = _url.find_first_of(":/", start); - if (next != string::npos && _url[next] == ':') { + if (next < _url.length() - 1 && _url.substr(next, 2) == ":/") { // We have a scheme. _flags |= F_has_scheme; _scheme_end = next; @@ -411,8 +413,36 @@ set_url(const string &url) { _server_end = start; _port_start = start; _port_end = start; - if (start + 1 < _url.length() && _url.substr(start, 2) == "//") { - // We have an authority specification. + + // Try to determine if an authority is present. It is will + // generally be present if a scheme was present; also, we have a + // hint passed in from the context as to whether we expect an + // authority (e.g. a server name) to be present. + bool has_authority = (has_scheme() || server_name_expected); + + // We also know we have an authority if the url contains two slashes + // at this point. + bool leading_slashes = + (start < _url.length() - 1 && _url.substr(start, 2) == "//"); + if (leading_slashes) { + has_authority = true; + } + + if (has_authority) { + // Now that we know we have an authority, we should ensure there + // are two slashes here, since there should be before the + // authority. + if (!leading_slashes) { + if (start < _url.length() && _url[start] == '/') { + // Well, at least we had one slash. Double it. + _url = _url.substr(0, start + 1) + _url.substr(start); + } else { + // No slashes at all. Insert them. + _url = _url.substr(0, start) + "//" + _url.substr(start); + } + } + + // Begin the actual authority specification. start += 2; _flags |= F_has_authority; _username_start = start; diff --git a/panda/src/downloader/urlSpec.h b/panda/src/downloader/urlSpec.h index dc5d0ce18a..d08165eede 100644 --- a/panda/src/downloader/urlSpec.h +++ b/panda/src/downloader/urlSpec.h @@ -33,7 +33,7 @@ class EXPCL_PANDAEXPRESS URLSpec { PUBLISHED: URLSpec(); - INLINE URLSpec(const string &url); + INLINE URLSpec(const string &url, bool server_name_expected = false); INLINE URLSpec(const URLSpec ©); INLINE void operator = (const string &url); void operator = (const URLSpec ©); @@ -66,7 +66,7 @@ PUBLISHED: void set_path(const string &path); void set_query(const string &query); - void set_url(const string &url); + void set_url(const string &url, bool server_name_expected = false); INLINE operator const string & () const; INLINE const char *c_str() const;