diff --git a/django/http/__init__.py b/django/http/__init__.py index 64b03deb3d..74a5afa84a 100644 --- a/django/http/__init__.py +++ b/django/http/__init__.py @@ -27,8 +27,12 @@ import Cookie _morsel_supports_httponly = Cookie.Morsel._reserved.has_key('httponly') # Some versions of Python 2.7 and later won't need this encoding bug fix: _cookie_encodes_correctly = Cookie.SimpleCookie().value_encode(';') == (';', '"\\073"') +# See ticket #13007, http://bugs.python.org/issue2193 and http://trac.edgewall.org/ticket/2256 +_tc = Cookie.SimpleCookie() +_tc.load('f:oo') +_cookie_allows_colon_in_names = 'Set-Cookie: f:oo=' in _tc.output() -if _morsel_supports_httponly and _cookie_encodes_correctly: +if _morsel_supports_httponly and _cookie_encodes_correctly and _cookie_allows_colon_in_names: SimpleCookie = Cookie.SimpleCookie else: if not _morsel_supports_httponly: @@ -85,6 +89,27 @@ else: return val, encoded + if not _cookie_allows_colon_in_names: + def load(self, rawdata, ignore_parse_errors=False): + if ignore_parse_errors: + self.bad_cookies = [] + self._BaseCookie__set = self._loose_set + super(SimpleCookie, self).load(rawdata) + if ignore_parse_errors: + self._BaseCookie__set = self._strict_set + for key in self.bad_cookies: + del self[key] + + _strict_set = Cookie.BaseCookie._BaseCookie__set + + def _loose_set(self, key, real_value, coded_value): + try: + self._strict_set(key, real_value, coded_value) + except Cookie.CookieError: + self.bad_cookies.append(key) + dict.__setitem__(self, key, None) + + class CompatCookie(SimpleCookie): def __init__(self, *args, **kwargs): super(CompatCookie, self).__init__(*args, **kwargs) @@ -433,7 +458,7 @@ def parse_cookie(cookie): if not isinstance(cookie, Cookie.BaseCookie): try: c = SimpleCookie() - c.load(cookie) + c.load(cookie, ignore_parse_errors=True) except Cookie.CookieError: # Invalid cookie return {} diff --git a/tests/regressiontests/httpwrappers/tests.py b/tests/regressiontests/httpwrappers/tests.py index 69b052f5cd..7d6641a3d7 100644 --- a/tests/regressiontests/httpwrappers/tests.py +++ b/tests/regressiontests/httpwrappers/tests.py @@ -1,7 +1,8 @@ import copy import pickle -from django.http import QueryDict, HttpResponse, SimpleCookie, BadHeaderError +from django.http import (QueryDict, HttpResponse, SimpleCookie, BadHeaderError, + parse_cookie) from django.utils import unittest class QueryDictTests(unittest.TestCase): @@ -274,3 +275,9 @@ class CookieTests(unittest.TestCase): c2 = SimpleCookie() c2.load(c.output()) self.assertEqual(c['test'].value, c2['test'].value) + + def test_nonstandard_keys(self): + """ + Test that a single non-standard cookie name doesn't affect all cookies. Ticket #13007. + """ + self.assertTrue('good_cookie' in parse_cookie('good_cookie=yes;bad:cookie=yes').keys())