summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRamiro Morales <cramm0@gmail.com>2011-02-13 02:24:05 +0000
committerRamiro Morales <cramm0@gmail.com>2011-02-13 02:24:05 +0000
commitf6aa469b1da50228b7e082c4ac0ecbe57575a373 (patch)
treeac82170632b03cd43b3a3f236a80f225f7e3a4e2
parenta797b7dba0644558ca7bf825b22268f2b4d9d3b5 (diff)
Fixed #13007 -- Made cookie parsing resilent to the presence of cookies with invalid characters in their names. Thanks Warlax for the report, Ubercore for his work on a fix and Jannis and Luke for review and guidance.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@15523 bcc190cf-cafb-0310-a4f2-bffc1f526a37
-rw-r--r--django/http/__init__.py29
-rw-r--r--tests/regressiontests/httpwrappers/tests.py9
2 files changed, 35 insertions, 3 deletions
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())