Code

Ticket #12470: 12470-cookie-fix.diff

File 12470-cookie-fix.diff, 3.5 KB (added by lukeplant, 4 years ago)

Patch that fixes this at the level of cookie handling

Line 
1diff -r 3d401cd0dc82 django/http/__init__.py
2--- a/django/http/__init__.py   Sat Jan 23 14:37:10 2010 +0000
3+++ b/django/http/__init__.py   Sat Jan 23 16:41:21 2010 +0000
4@@ -248,12 +248,40 @@
5             output.extend([urlencode({k: smart_str(v, self.encoding)}) for v in list_])
6         return '&'.join(output)
7 
8+class CompatCookie(SimpleCookie):
9+    """
10+    Cookie class that handles some issues with browser compatibility.
11+    """
12+    def value_encode(self, val):
13+        # Some browsers do not support quoted-string from RFC 2109,
14+        # including some versions of Safari and Internet Explorer.
15+        # These browsers split on ';', and some versions of Safari
16+        # are known to split on ", ". Therefore, we encode ';' and ','
17+
18+        # SimpleCookie already does the hard work of encoding and decoding.
19+        # It uses octal sequences like '\\012' for newline etc.
20+        # and non-ASCII chars.  We just make use of this mechanism, to
21+        # avoid introducing two encoding schemes which would be
22+        # confusing and especially awkward for javascript.
23+
24+        # NB, contrary to Python docs, value_encode returns a tuple containing
25+        # (real val, encoded_val)
26+        val, encoded = super(CompatCookie, self).value_encode(val)
27+
28+        encoded = encoded.replace(";", "\\073").replace(",","\\054")
29+        # If encoded now contains any quoted chars, we need
30+        # double quotes around the whole string.
31+        if "\\" in encoded and not encoded.startswith('"'):
32+            encoded = '"' + encoded + '"'
33+
34+        return val, encoded
35+
36 def parse_cookie(cookie):
37     if cookie == '':
38         return {}
39     if not isinstance(cookie, BaseCookie):
40         try:
41-            c = SimpleCookie()
42+            c = CompatCookie()
43             c.load(cookie)
44         except CookieError:
45             # Invalid cookie
46@@ -288,7 +316,7 @@
47         else:
48             self._container = [content]
49             self._is_string = True
50-        self.cookies = SimpleCookie()
51+        self.cookies = CompatCookie()
52         if status:
53             self.status_code = status
54 
55diff -r 3d401cd0dc82 tests/regressiontests/httpwrappers/tests.py
56--- a/tests/regressiontests/httpwrappers/tests.py       Sat Jan 23 14:37:10 2010 +0000
57+++ b/tests/regressiontests/httpwrappers/tests.py       Sat Jan 23 16:41:21 2010 +0000
58@@ -465,7 +465,40 @@
59 [u'1', u'2', u'3', u'4']
60 """
61 
62-from django.http import QueryDict, HttpResponse
63+from django.http import QueryDict, HttpResponse, CompatCookie
64+from django.test import TestCase
65+
66+
67+class Cookies(TestCase):
68+
69+    def test_encode(self):
70+        """
71+        Test that we don't output tricky characters in encoded value
72+        """
73+        c = CompatCookie()
74+        c['test'] = "An,awkward;value"
75+        self.assert_(";" not in c.output()) # IE compat
76+        self.assert_("," not in c.output()) # Safari compat
77+
78+    def test_decode(self):
79+        """
80+        Test that we can still preserve semi-colons and commas
81+        """
82+        c = CompatCookie()
83+        c['test'] = "An,awkward;value"
84+        c2 = CompatCookie()
85+        c2.load(c.output())
86+        self.assertEqual(c['test'].value, c2['test'].value)
87+
88+    def test_decode_2(self):
89+        """
90+        Test that we haven't broken normal encoding
91+        """
92+        c = CompatCookie()
93+        c['test'] = "\xf0"
94+        c2 = CompatCookie()
95+        c2.load(c.output())
96+        self.assertEqual(c['test'].value, c2['test'].value)
97 
98 if __name__ == "__main__":
99     import doctest