Ticket #12470: 12470-cookie-fix.diff

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

Patch that fixes this at the level of cookie handling

  • django/http/__init__.py

    diff -r 3d401cd0dc82 django/http/__init__.py
    a b  
    248248            output.extend([urlencode({k: smart_str(v, self.encoding)}) for v in list_])
    249249        return '&'.join(output)
    250250
     251class CompatCookie(SimpleCookie):
     252    """
     253    Cookie class that handles some issues with browser compatibility.
     254    """
     255    def value_encode(self, val):
     256        # Some browsers do not support quoted-string from RFC 2109,
     257        # including some versions of Safari and Internet Explorer.
     258        # These browsers split on ';', and some versions of Safari
     259        # are known to split on ", ". Therefore, we encode ';' and ','
     260
     261        # SimpleCookie already does the hard work of encoding and decoding.
     262        # It uses octal sequences like '\\012' for newline etc.
     263        # and non-ASCII chars.  We just make use of this mechanism, to
     264        # avoid introducing two encoding schemes which would be
     265        # confusing and especially awkward for javascript.
     266
     267        # NB, contrary to Python docs, value_encode returns a tuple containing
     268        # (real val, encoded_val)
     269        val, encoded = super(CompatCookie, self).value_encode(val)
     270
     271        encoded = encoded.replace(";", "\\073").replace(",","\\054")
     272        # If encoded now contains any quoted chars, we need
     273        # double quotes around the whole string.
     274        if "\\" in encoded and not encoded.startswith('"'):
     275            encoded = '"' + encoded + '"'
     276
     277        return val, encoded
     278
    251279def parse_cookie(cookie):
    252280    if cookie == '':
    253281        return {}
    254282    if not isinstance(cookie, BaseCookie):
    255283        try:
    256             c = SimpleCookie()
     284            c = CompatCookie()
    257285            c.load(cookie)
    258286        except CookieError:
    259287            # Invalid cookie
     
    288316        else:
    289317            self._container = [content]
    290318            self._is_string = True
    291         self.cookies = SimpleCookie()
     319        self.cookies = CompatCookie()
    292320        if status:
    293321            self.status_code = status
    294322
  • tests/regressiontests/httpwrappers/tests.py

    diff -r 3d401cd0dc82 tests/regressiontests/httpwrappers/tests.py
    a b  
    465465[u'1', u'2', u'3', u'4']
    466466"""
    467467
    468 from django.http import QueryDict, HttpResponse
     468from django.http import QueryDict, HttpResponse, CompatCookie
     469from django.test import TestCase
     470
     471
     472class Cookies(TestCase):
     473
     474    def test_encode(self):
     475        """
     476        Test that we don't output tricky characters in encoded value
     477        """
     478        c = CompatCookie()
     479        c['test'] = "An,awkward;value"
     480        self.assert_(";" not in c.output()) # IE compat
     481        self.assert_("," not in c.output()) # Safari compat
     482
     483    def test_decode(self):
     484        """
     485        Test that we can still preserve semi-colons and commas
     486        """
     487        c = CompatCookie()
     488        c['test'] = "An,awkward;value"
     489        c2 = CompatCookie()
     490        c2.load(c.output())
     491        self.assertEqual(c['test'].value, c2['test'].value)
     492
     493    def test_decode_2(self):
     494        """
     495        Test that we haven't broken normal encoding
     496        """
     497        c = CompatCookie()
     498        c['test'] = "\xf0"
     499        c2 = CompatCookie()
     500        c2.load(c.output())
     501        self.assertEqual(c['test'].value, c2['test'].value)
    469502
    470503if __name__ == "__main__":
    471504    import doctest
Back to Top