diff options
author | Katelyn Gadd <kg@luminance.org> | 2017-10-20 11:53:25 +0300 |
---|---|---|
committer | Marek Safar <marek.safar@gmail.com> | 2017-10-20 11:53:25 +0300 |
commit | 44b21bca28f9d262e07ebd31c39829447582de5f (patch) | |
tree | e503b3e86227e6e1fd28d9004f89f2b6818d7bf0 /mcs | |
parent | c26e069703d74e0b7a5da4b0326ae72cfde3f5d3 (diff) |
Fix bug #58400 - incorrect implementation of LocalPath for file URLs (#5779)
Diffstat (limited to 'mcs')
-rw-r--r-- | mcs/class/System/Test/System/UriTest.cs | 20 | ||||
-rw-r--r-- | mcs/class/System/Test/System/UriTest2.cs | 2 | ||||
-rw-r--r-- | mcs/class/System/Test/System/UriTest3.cs | 32 | ||||
-rw-r--r-- | mcs/class/referencesource/System/net/System/URI.cs | 51 |
4 files changed, 85 insertions, 20 deletions
diff --git a/mcs/class/System/Test/System/UriTest.cs b/mcs/class/System/Test/System/UriTest.cs index 2db2fb21283..2cabd42af7b 100644 --- a/mcs/class/System/Test/System/UriTest.cs +++ b/mcs/class/System/Test/System/UriTest.cs @@ -502,20 +502,14 @@ namespace MonoTests.System uri = new Uri ("file:////////cygwin/tmp/hello.txt"); Assert.AreEqual ("file://cygwin/tmp/hello.txt", uri.ToString (), "#3a"); - if (isWin32) - Assert.AreEqual ("\\\\cygwin\\tmp\\hello.txt", uri.LocalPath, "#3b win32"); - else - Assert.AreEqual ("/tmp/hello.txt", uri.LocalPath, "#3b *nix"); + Assert.AreEqual ("\\\\cygwin\\tmp\\hello.txt", uri.LocalPath, "#3b win32"); Assert.AreEqual ("file", uri.Scheme, "#3c"); Assert.AreEqual ("cygwin", uri.Host, "#3d"); Assert.AreEqual ("/tmp/hello.txt", uri.AbsolutePath, "#3e"); uri = new Uri ("file://mymachine/cygwin/tmp/hello.txt"); Assert.AreEqual ("file://mymachine/cygwin/tmp/hello.txt", uri.ToString (), "#4a"); - if (isWin32) - Assert.AreEqual ("\\\\mymachine\\cygwin\\tmp\\hello.txt", uri.LocalPath, "#4b win32"); - else - Assert.AreEqual ("/cygwin/tmp/hello.txt", uri.LocalPath, "#4b *nix"); + Assert.AreEqual ("\\\\mymachine\\cygwin\\tmp\\hello.txt", uri.LocalPath, "#4b win32"); Assert.AreEqual ("file", uri.Scheme, "#4c"); Assert.AreEqual ("mymachine", uri.Host, "#4d"); Assert.AreEqual ("/cygwin/tmp/hello.txt", uri.AbsolutePath, "#4e"); @@ -537,10 +531,7 @@ namespace MonoTests.System Assert.AreEqual ("/", uri.AbsolutePath, "#6e"); Assert.AreEqual ("/", uri.PathAndQuery, "#6f"); Assert.AreEqual ("file://one_file.txt/", uri.GetLeftPart (UriPartial.Path), "#6g"); - if (isWin32) - Assert.AreEqual ("\\\\one_file.txt", uri.LocalPath, "#6b"); - else - Assert.AreEqual ("/", uri.LocalPath, "#6b"); + Assert.AreEqual ("\\\\one_file.txt", uri.LocalPath, "#6b"); Assert.AreEqual ("file", uri.Scheme, "#6c"); Assert.AreEqual ("one_file.txt", uri.Host, "#6d"); @@ -551,10 +542,7 @@ namespace MonoTests.System Assert.AreEqual ("/", uri.AbsolutePath, "#7e"); Assert.AreEqual ("/", uri.PathAndQuery, "#7f"); Assert.AreEqual ("file://one_file.txt/", uri.GetLeftPart (UriPartial.Path), "#7g"); - if (isWin32) - Assert.AreEqual ("\\\\one_file.txt\\", uri.LocalPath, "#7b"); - else - Assert.AreEqual ("/", uri.LocalPath, "#7b"); + Assert.AreEqual ("\\\\one_file.txt\\", uri.LocalPath, "#7b"); Assert.AreEqual ("file", uri.Scheme, "#7c"); Assert.AreEqual ("one_file.txt", uri.Host, "#7d"); } diff --git a/mcs/class/System/Test/System/UriTest2.cs b/mcs/class/System/Test/System/UriTest2.cs index cbec7b2fc52..85eb8c712cf 100644 --- a/mcs/class/System/Test/System/UriTest2.cs +++ b/mcs/class/System/Test/System/UriTest2.cs @@ -875,7 +875,7 @@ TextWriter sw = Console.Out; if (IriParsing) { Assert.AreEqual ("/dir/subdir/file", uri.AbsolutePath, "AbsolutePath"); Assert.AreEqual ("file://host/dir/subdir/file?this-is-not-a-query#but-this-is-a-fragment", uri.AbsoluteUri, "AbsoluteUri"); - Assert.AreEqual (isWin32 ? "\\\\host\\dir\\subdir\\file" : "/dir/subdir/file", uri.LocalPath, "LocalPath"); + Assert.AreEqual ("\\\\host\\dir\\subdir\\file", uri.LocalPath, "LocalPath"); Assert.AreEqual ("/dir/subdir/file?this-is-not-a-query", uri.PathAndQuery, "PathAndQuery"); Assert.AreEqual ("?this-is-not-a-query", uri.Query, "Query"); Assert.AreEqual ("file", uri.Segments [3], "Segments [3]"); diff --git a/mcs/class/System/Test/System/UriTest3.cs b/mcs/class/System/Test/System/UriTest3.cs index a39ac73d0af..f83ec1c62d1 100644 --- a/mcs/class/System/Test/System/UriTest3.cs +++ b/mcs/class/System/Test/System/UriTest3.cs @@ -696,6 +696,38 @@ namespace MonoTests.System type = Uri.CheckHostName ("3.141592653589793238462643383279502884197169399375105820974944592._om"); Assert.AreEqual (UriHostNameType.Unknown, type, "DomainLabelLength#3"); } + + // https://bugzilla.xamarin.com/show_bug.cgi?id=58400 + [Test] + public static void Test_LocalPath_Bug58400() + { + var uriAndExpected = new [] + { + ("file://host/directory/filename", @"\\host\directory\filename"), + ("file://host/directory/", @"\\host\directory\"), + ("file://host/filename", @"\\host\filename"), + ("file://host/", @"\\host\"), + ("file://host", @"\\host"), + ("file:///directory/filename", "/directory/filename"), + ("file:///directory/", "/directory/"), + ("file:///filename", "/filename"), + ("file:///", "/"), + // This is an invalid URI, technically + ("file://", "/"), + ("file://////hello/world", @"\\hello\world"), + ("file://hello/////world", @"\\hello\\\\\world"), + }; + + foreach (var tup in uriAndExpected) + { + var originalUri = tup.Item1; + var expectedLocalPath = tup.Item2; + var uri = new Uri (originalUri); + var localPath = uri.LocalPath; + + Assert.AreEqual (expectedLocalPath, localPath, originalUri); + } + } } } diff --git a/mcs/class/referencesource/System/net/System/URI.cs b/mcs/class/referencesource/System/net/System/URI.cs index 24ddbc66e15..8a740ce08b8 100644 --- a/mcs/class/referencesource/System/net/System/URI.cs +++ b/mcs/class/referencesource/System/net/System/URI.cs @@ -1070,11 +1070,50 @@ namespace System { EnsureParseRemaining(); #if MONO + // https://bugzilla.xamarin.com/show_bug.cgi?id=58400 + bool isFileUrlWithHost = + (m_Info.Offset.Host != m_Info.Offset.Path) && + // only file URLs + IsFile && + // Paths that got reinterpreted as files would be treated + // as if they have a host, like "/a/b" which maps to "file:///a/b/", + // or "C:\a\b\" which maps to "file:///c:/a/b" + OriginalString.StartsWith("file://", StringComparison.Ordinal) && + // file://localhost/x/y needs to produce /x/y + !IsLoopback; + + // Manually check for "hosts" that are just forward slashes. + if (isFileUrlWithHost) { + isFileUrlWithHost = false; + + for (int i = m_Info.Offset.Host; i < m_Info.Offset.Path; i++) { + if (OriginalString[i] != '/') { + isFileUrlWithHost = true; + break; + } + } + } + + // We need to force generation of a UNC-style path instead of a unix one, + // despite the path not being UNC originally + bool treatAsUncPath = IsUncPath || isFileUrlWithHost; + // // I think this is wrong but it keeps LocalPath fully backward compatible // - if (IsUncOrDosPath && (IsWindowsFileSystem || !IsUncPath)) + if ( + (IsUncOrDosPath && + ( + IsWindowsFileSystem || + !IsUncPath + ) + ) || + // If a path has a host name force it into this branch so the UNC code runs + isFileUrlWithHost + ) #else + bool treatAsUncPath = IsUncPath; + //Other cases will get a Unix-style path if (IsUncOrDosPath) #endif @@ -1083,7 +1122,13 @@ namespace System { int start; // Do we have a valid local path right in m_string? - if (NotAny(Flags.HostNotCanonical|Flags.PathNotCanonical|Flags.ShouldBeCompressed)) { + if ( + NotAny(Flags.HostNotCanonical|Flags.PathNotCanonical|Flags.ShouldBeCompressed) +#if MONO + // This branch drops the host name so we can't use it + && !isFileUrlWithHost +#endif + ) { start = IsUncPath? m_Info.Offset.Host-2 :m_Info.Offset.Path; @@ -1121,7 +1166,7 @@ namespace System { string host = m_Info.Host; result = new char [host.Length + 3 + m_Info.Offset.Fragment - m_Info.Offset.Path ]; - if (IsUncPath) + if (treatAsUncPath) { result[0] = '\\'; result[1] = '\\'; |