]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
GH-126766: `url2pathname()`: handle 'localhost' authority (#127129)
authorBarney Gale <barney.gale@gmail.com>
Fri, 22 Nov 2024 03:17:06 +0000 (03:17 +0000)
committerGitHub <noreply@github.com>
Fri, 22 Nov 2024 03:17:06 +0000 (03:17 +0000)
Discard any 'localhost' authority from the beginning of a `file:` URI. As a
result, file URIs like `//localhost/etc/hosts` are correctly decoded as
`/etc/hosts`.

Lib/nturl2path.py
Lib/test/test_urllib.py
Lib/urllib/request.py
Misc/NEWS.d/next/Library/2024-11-22-02-31-55.gh-issue-126766.jfkhBH.rst [new file with mode: 0644]

index ed7880fd1a775f25bdaf97de73ae3aa706f9e082..3308ee7c1c784ee6d92513618926d2ad0f9f326d 100644 (file)
@@ -15,14 +15,17 @@ def url2pathname(url):
     # become
     #   C:\foo\bar\spam.foo
     import string, urllib.parse
+    if url[:3] == '///':
+        # URL has an empty authority section, so the path begins on the third
+        # character.
+        url = url[2:]
+    elif url[:12] == '//localhost/':
+        # Skip past 'localhost' authority.
+        url = url[11:]
     # Windows itself uses ":" even in URLs.
     url = url.replace(':', '|')
     if not '|' in url:
         # No drive specifier, just convert slashes
-        if url[:3] == '///':
-            # URL has an empty authority section, so the path begins on the
-            # third character.
-            url = url[2:]
         # make sure not to convert quoted slashes :-)
         return urllib.parse.unquote(url.replace('/', '\\'))
     comp = url.split('|')
index 3e5dc256d317a7c7237f291754f5888a45f1d34f..e1c1d3170d980741b40abf18cc5cce432702262a 100644 (file)
@@ -1496,6 +1496,8 @@ class Pathname_Tests(unittest.TestCase):
         # Localhost paths
         self.assertEqual(fn('//localhost/C:/path/to/file'), 'C:\\path\\to\\file')
         self.assertEqual(fn('//localhost/C|/path/to/file'), 'C:\\path\\to\\file')
+        self.assertEqual(fn('//localhost/path/to/file'), '\\path\\to\\file')
+        self.assertEqual(fn('//localhost//server/path/to/file'), '\\\\server\\path\\to\\file')
         # Percent-encoded forward slashes are preserved for backwards compatibility
         self.assertEqual(fn('C:/foo%2fbar'), 'C:\\foo/bar')
         self.assertEqual(fn('//server/share/foo%2fbar'), '\\\\server\\share\\foo/bar')
@@ -1514,7 +1516,7 @@ class Pathname_Tests(unittest.TestCase):
         self.assertEqual(fn('//foo/bar'), '//foo/bar')
         self.assertEqual(fn('///foo/bar'), '/foo/bar')
         self.assertEqual(fn('////foo/bar'), '//foo/bar')
-        self.assertEqual(fn('//localhost/foo/bar'), '//localhost/foo/bar')
+        self.assertEqual(fn('//localhost/foo/bar'), '/foo/bar')
 
     @unittest.skipUnless(os_helper.FS_NONASCII, 'need os_helper.FS_NONASCII')
     def test_url2pathname_nonascii(self):
index bcfdcc51fac369d23fd411fe43ec4223ebca45c2..80be65c613e9710c6f18d98689d55ceb367e24a2 100644 (file)
@@ -1657,6 +1657,9 @@ else:
             # URL has an empty authority section, so the path begins on the
             # third character.
             pathname = pathname[2:]
+        elif pathname[:12] == '//localhost/':
+            # Skip past 'localhost' authority.
+            pathname = pathname[11:]
         encoding = sys.getfilesystemencoding()
         errors = sys.getfilesystemencodeerrors()
         return unquote(pathname, encoding=encoding, errors=errors)
diff --git a/Misc/NEWS.d/next/Library/2024-11-22-02-31-55.gh-issue-126766.jfkhBH.rst b/Misc/NEWS.d/next/Library/2024-11-22-02-31-55.gh-issue-126766.jfkhBH.rst
new file mode 100644 (file)
index 0000000..998c99b
--- /dev/null
@@ -0,0 +1,2 @@
+Fix issue where :func:`urllib.request.url2pathname` failed to discard any
+'localhost' authority present in the URL.