diff --git a/requests/packages/urllib3/__init__.py b/requests/packages/urllib3/__init__.py index d7592ae7..0660b9c8 100644 --- a/requests/packages/urllib3/__init__.py +++ b/requests/packages/urllib3/__init__.py @@ -4,7 +4,7 @@ urllib3 - Thread-safe connection pooling and re-using. __author__ = 'Andrey Petrov (andrey.petrov@shazow.net)' __license__ = 'MIT' -__version__ = 'dev' +__version__ = '1.10.2' from .connectionpool import ( diff --git a/requests/packages/urllib3/_collections.py b/requests/packages/urllib3/_collections.py index 06412ddf..cc424de0 100644 --- a/requests/packages/urllib3/_collections.py +++ b/requests/packages/urllib3/_collections.py @@ -20,8 +20,6 @@ from .packages.six import iterkeys, itervalues, PY3 __all__ = ['RecentlyUsedContainer', 'HTTPHeaderDict'] -MULTIPLE_HEADERS_ALLOWED = frozenset(['cookie', 'set-cookie', 'set-cookie2']) - _Null = object() @@ -143,7 +141,10 @@ class HTTPHeaderDict(dict): def __init__(self, headers=None, **kwargs): dict.__init__(self) if headers is not None: - self.extend(headers) + if isinstance(headers, HTTPHeaderDict): + self._copy_from(headers) + else: + self.extend(headers) if kwargs: self.extend(kwargs) @@ -223,11 +224,8 @@ class HTTPHeaderDict(dict): vals.append(val) else: # vals should be a tuple then, i.e. only one item so far - if key_lower in MULTIPLE_HEADERS_ALLOWED: - # Need to convert the tuple to list for further extension - _dict_setitem(self, key_lower, [vals[0], vals[1], val]) - else: - _dict_setitem(self, key_lower, new_vals) + # Need to convert the tuple to list for further extension + _dict_setitem(self, key_lower, [vals[0], vals[1], val]) def extend(*args, **kwargs): """Generic import function for any type of header-like object. @@ -276,14 +274,17 @@ class HTTPHeaderDict(dict): def __repr__(self): return "%s(%s)" % (type(self).__name__, dict(self.itermerged())) - def copy(self): - clone = type(self)() - for key in self: - val = _dict_getitem(self, key) + def _copy_from(self, other): + for key in other: + val = _dict_getitem(other, key) if isinstance(val, list): # Don't need to convert tuples val = list(val) - _dict_setitem(clone, key, val) + _dict_setitem(self, key, val) + + def copy(self): + clone = type(self)() + clone._copy_from(self) return clone def iteritems(self): diff --git a/requests/packages/urllib3/exceptions.py b/requests/packages/urllib3/exceptions.py index 0c6fd3c5..5d523011 100644 --- a/requests/packages/urllib3/exceptions.py +++ b/requests/packages/urllib3/exceptions.py @@ -157,3 +157,8 @@ class InsecureRequestWarning(SecurityWarning): class SystemTimeWarning(SecurityWarning): "Warned when system time is suspected to be wrong" pass + + +class InsecurePlatformWarning(SecurityWarning): + "Warned when certain SSL configuration is not available on a platform." + pass diff --git a/requests/packages/urllib3/util/ssl_.py b/requests/packages/urllib3/util/ssl_.py index ee1d3223..e7e7dfae 100644 --- a/requests/packages/urllib3/util/ssl_.py +++ b/requests/packages/urllib3/util/ssl_.py @@ -1,7 +1,7 @@ from binascii import hexlify, unhexlify from hashlib import md5, sha1, sha256 -from ..exceptions import SSLError +from ..exceptions import SSLError, InsecurePlatformWarning SSLContext = None @@ -10,6 +10,7 @@ create_default_context = None import errno import ssl +import warnings try: # Test for SSL features from ssl import wrap_socket, CERT_NONE, PROTOCOL_SSLv23 @@ -69,6 +70,14 @@ except ImportError: self.ciphers = cipher_suite def wrap_socket(self, socket, server_hostname=None): + warnings.warn( + 'A true SSLContext object is not available. This prevents ' + 'urllib3 from configuring SSL appropriately and may cause ' + 'certain SSL connections to fail. For more information, see ' + 'https://urllib3.readthedocs.org/en/latest/security.html' + '#insecureplatformwarning.', + InsecurePlatformWarning + ) kwargs = { 'keyfile': self.keyfile, 'certfile': self.certfile,