]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Fix Issue #13642: Unquote before b64encoding user:password during Basic Authentication.
authorSenthil Kumaran <senthil@uthcode.com>
Sat, 14 Jan 2012 11:09:04 +0000 (19:09 +0800)
committerSenthil Kumaran <senthil@uthcode.com>
Sat, 14 Jan 2012 11:09:04 +0000 (19:09 +0800)
Lib/test/test_urllib.py
Lib/urllib/request.py
Misc/NEWS

index 97781d7114f510fd320cb1f431531151347a58d8..5a6dd6541800cbee62d40aa647f18dcc6ebccc40 100644 (file)
@@ -12,6 +12,8 @@ import os
 import sys
 import tempfile
 
+from base64 import b64encode
+
 def hexescape(char):
     """Escape char as RFC 2396 specifies"""
     hex_repr = hex(ord(char))[2:].upper()
@@ -42,8 +44,8 @@ class FakeHTTPMixin(object):
         class FakeSocket(io.BytesIO):
             io_refs = 1
 
-            def sendall(self, str):
-                pass
+            def sendall(self, data):
+                FakeHTTPConnection.buf = data
 
             def makefile(self, *args, **kwds):
                 self.io_refs += 1
@@ -65,8 +67,13 @@ class FakeHTTPMixin(object):
                     io.BytesIO.close(self)
 
         class FakeHTTPConnection(http.client.HTTPConnection):
+
+            # buffer to store data for verification in urlopen tests.
+            buf = None
+
             def connect(self):
                 self.sock = FakeSocket(fakedata)
+
         self._connection_class = http.client.HTTPConnection
         http.client.HTTPConnection = FakeHTTPConnection
 
@@ -268,6 +275,25 @@ Content-Type: text/html; charset=iso-8859-1
         finally:
             self.unfakehttp()
 
+    def test_userpass_inurl_w_spaces(self):
+        self.fakehttp(b"HTTP/1.0 200 OK\r\n\r\nHello!")
+        try:
+            userpass = "a b:c d"
+            url = "http://{}@python.org/".format(userpass)
+            fakehttp_wrapper = http.client.HTTPConnection
+            authorization = ("Authorization: Basic %s\r\n" %
+                             b64encode(userpass.encode("ASCII")).decode("ASCII"))
+            fp = urlopen(url)
+            # The authorization header must be in place
+            self.assertIn(authorization, fakehttp_wrapper.buf.decode("UTF-8"))
+            self.assertEqual(fp.readline(), b"Hello!")
+            self.assertEqual(fp.readline(), b"")
+            # the spaces are quoted in URL so no match
+            self.assertNotEqual(fp.geturl(), url)
+            self.assertEqual(fp.getcode(), 200)
+        finally:
+            self.unfakehttp()
+
 class urlretrieve_FileTests(unittest.TestCase):
     """Test urllib.urlretrieve() on local files"""
 
@@ -1111,6 +1137,9 @@ class Utility_Tests(unittest.TestCase):
         self.assertEqual(('user', 'a\fb'),urllib.parse.splitpasswd('user:a\fb'))
         self.assertEqual(('user', 'a\vb'),urllib.parse.splitpasswd('user:a\vb'))
         self.assertEqual(('user', 'a:b'),urllib.parse.splitpasswd('user:a:b'))
+        self.assertEqual(('user', 'a b'),urllib.parse.splitpasswd('user:a b'))
+        self.assertEqual(('user 2', 'ab'),urllib.parse.splitpasswd('user 2:ab'))
+        self.assertEqual(('user+1', 'a+b'),urllib.parse.splitpasswd('user+1:a+b'))
 
     def test_thishost(self):
         """Test the urllib.request.thishost utility function returns a tuple"""
index 77b7c7ffb2fd60fdc116f7144d3ddaebdba189fb..cf0657158751a8a131c6f1bd17026c4c3a20ed97 100644 (file)
@@ -1661,13 +1661,13 @@ class URLopener:
         if not host: raise IOError('http error', 'no host given')
 
         if proxy_passwd:
-            import base64
+            proxy_passwd = unquote(proxy_passwd)
             proxy_auth = base64.b64encode(proxy_passwd.encode()).decode('ascii')
         else:
             proxy_auth = None
 
         if user_passwd:
-            import base64
+            user_passwd = unquote(user_passwd)
             auth = base64.b64encode(user_passwd.encode()).decode('ascii')
         else:
             auth = None
@@ -1871,7 +1871,6 @@ class URLopener:
                                             time.gmtime(time.time())))
         msg.append('Content-type: %s' % type)
         if encoding == 'base64':
-            import base64
             # XXX is this encoding/decoding ok?
             data = base64.decodebytes(data.encode('ascii')).decode('latin1')
         else:
index 073417d74387125e1d2981e3ac55988686b9f5fb..629dbcc9eb72de104a3309d48fc302fc519ced35 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -97,6 +97,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #13642: Unquote before b64encoding user:password during Basic
+  Authentication. Patch contributed by Joonas Kuorilehto.
+
 - Issue #13726: Fix the ambiguous -S flag in regrtest. It is -o/--slow for slow
   tests.