diff --git a/netwerk/base/nsStandardURL.cpp b/netwerk/base/nsStandardURL.cpp index 4ae6fc51629..aa2cffa20ab 100644 --- a/netwerk/base/nsStandardURL.cpp +++ b/netwerk/base/nsStandardURL.cpp @@ -1187,6 +1187,29 @@ nsStandardURL::GetOriginCharset(nsACString &result) return NS_OK; } +static bool +IsSpecialProtocol(const nsACString &input) +{ + nsACString::const_iterator start, end; + input.BeginReading(start); + nsACString::const_iterator iterator(start); + input.EndReading(end); + + while (iterator != end && *iterator != ':') { + iterator++; + } + + nsAutoCString protocol(nsDependentCSubstring(start.get(), iterator.get())); + + return protocol.LowerCaseEqualsLiteral("http") || + protocol.LowerCaseEqualsLiteral("https") || + protocol.LowerCaseEqualsLiteral("ftp") || + protocol.LowerCaseEqualsLiteral("ws") || + protocol.LowerCaseEqualsLiteral("wss") || + protocol.LowerCaseEqualsLiteral("file") || + protocol.LowerCaseEqualsLiteral("gopher"); +} + NS_IMETHODIMP nsStandardURL::SetSpec(const nsACString &input) { @@ -1217,12 +1240,35 @@ nsStandardURL::SetSpec(const nsACString &input) Clear(); // filter out unexpected chars "\r\n\t" if necessary - nsAutoCString buf1; - if (net_FilterURIString(spec, buf1)) { - spec = buf1.get(); - specLength = buf1.Length(); + nsAutoCString filteredURI; + if (!net_FilterURIString(spec, filteredURI)) { + // Copy the content into filteredURI even if no whitespace was stripped. + // We need a non-const buffer to perform backslash replacement. + filteredURI = input; } + if (IsSpecialProtocol(filteredURI)) { + // Bug 652186: Replace all backslashes with slashes when parsing paths + // Stop when we reach the query or the hash. + nsAutoCString::iterator start; + nsAutoCString::iterator end; + filteredURI.BeginWriting(start); + filteredURI.EndWriting(end); + while (start != end) { + if (*start == '?' || *start == '#') { + break; + } + if (*start == '\\') { + *start = '/'; + } + start++; + } + } + + spec = filteredURI.get(); + specLength = filteredURI.Length(); + + // parse the given URL... nsresult rv = ParseURL(spec, specLength); if (NS_SUCCEEDED(rv)) { @@ -2004,12 +2050,15 @@ nsStandardURL::Resolve(const nsACString &in, nsACString &out) // filter out unexpected chars "\r\n\t" if necessary nsAutoCString buf; int32_t relpathLen; - if (net_FilterURIString(relpath, buf)) { - relpath = buf.get(); - relpathLen = buf.Length(); - } else - relpathLen = flat.Length(); - + if (!net_FilterURIString(relpath, buf)) { + // Copy the content into filteredURI even if no whitespace was stripped. + // We need a non-const buffer to perform backslash replacement. + buf = in; + } + + relpath = buf.get(); + relpathLen = buf.Length(); + char *result = nullptr; LOG(("nsStandardURL::Resolve [this=%p spec=%s relpath=%s]\n", @@ -2046,6 +2095,30 @@ nsStandardURL::Resolve(const nsACString &in, nsACString &out) // reset the scheme and assume a relative url if (NS_FAILED(rv)) scheme.Reset(); + nsAutoCString protocol(Segment(scheme)); + nsAutoCString baseProtocol(Scheme()); + + // We need to do backslash replacement for the following cases: + // 1. The input is an absolute path with a http/https/ftp scheme + // 2. The input is a relative path, and the base URL has a http/https/ftp scheme + if ((protocol.IsEmpty() && IsSpecialProtocol(baseProtocol)) || + IsSpecialProtocol(protocol)) { + + nsAutoCString::iterator start; + nsAutoCString::iterator end; + buf.BeginWriting(start); + buf.EndWriting(end); + while (start != end) { + if (*start == '?' || *start == '#') { + break; + } + if (*start == '\\') { + *start = '/'; + } + start++; + } + } + if (scheme.mLen >= 0) { // add some flags to coalesceFlag if it is an ftp-url // need this later on when coalescing the resulting URL diff --git a/netwerk/test/unit/test_standardurl.js b/netwerk/test/unit/test_standardurl.js index ee1ee0251fe..1eaaa601438 100644 --- a/netwerk/test/unit/test_standardurl.js +++ b/netwerk/test/unit/test_standardurl.js @@ -333,3 +333,16 @@ add_test(function test_filterWhitespace() do_check_eq(url.spec, "http://example.com/path/to%20the/file.ext?query#hash"); run_next_test(); }); + +add_test(function test_backslashReplacement() +{ + var url = stringToURL("http:\\\\test.com\\path/to\\file?query\\backslash#hash\\"); + do_check_eq(url.spec, "http://test.com/path/to/file?query\\backslash#hash\\"); + + url = stringToURL("http:\\\\test.com\\example.org/path\\to/file"); + do_check_eq(url.spec, "http://test.com/example.org/path/to/file"); + do_check_eq(url.host, "test.com"); + do_check_eq(url.path, "/example.org/path/to/file"); + + run_next_test(); +});