]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
Properly quote and unquote cookie values.
authorBen Darnell <ben@bendarnell.com>
Sun, 10 Jul 2011 22:30:52 +0000 (15:30 -0700)
committerBen Darnell <ben@bendarnell.com>
Sun, 10 Jul 2011 22:30:52 +0000 (15:30 -0700)
Closes #36.

tornado/test/web_test.py
tornado/web.py

index 333555fa4a1203f667c595136299f4e2331276f5..4baeaa142f3abb42d7dc3e18d628fefa9b179a4b 100644 (file)
@@ -73,11 +73,19 @@ class CookieTest(AsyncHTTPTestCase, LogTrapTestCase):
                 self.set_cookie("unicode_args", "blah", domain=u"foo.com",
                                 path=u"/foo")
 
+        class SetCookieSpecialCharHandler(RequestHandler):
+            def get(self):
+                self.set_cookie("equals", "a=b")
+                self.set_cookie("semicolon", "a;b")
+                self.set_cookie("quote", 'a"b')
+
 
         return Application([
                 ("/set", SetCookieHandler),
                 ("/get", GetCookieHandler),
-                ("/set_domain", SetCookieDomainHandler)])
+                ("/set_domain", SetCookieDomainHandler),
+                ("/special_char", SetCookieSpecialCharHandler),
+                ])
 
     def test_set_cookie(self):
         response = self.fetch("/set")
@@ -90,11 +98,37 @@ class CookieTest(AsyncHTTPTestCase, LogTrapTestCase):
         response = self.fetch("/get", headers={"Cookie": "foo=bar"})
         self.assertEqual(response.body, b("bar"))
 
+        response = self.fetch("/get", headers={"Cookie": 'foo="bar"'})
+        self.assertEqual(response.body, b("bar"))
+
     def test_set_cookie_domain(self):
         response = self.fetch("/set_domain")
         self.assertEqual(response.headers.get_list("Set-Cookie"),
                          ["unicode_args=blah; Domain=foo.com; Path=/foo"])
 
+    def test_cookie_special_char(self):
+        response = self.fetch("/special_char")
+        headers = response.headers.get_list("Set-Cookie")
+        self.assertEqual(len(headers), 3)
+        self.assertEqual(headers[0], 'equals="a=b"; Path=/')
+        # python 2.7 octal-escapes the semicolon; older versions leave it alone
+        self.assertTrue(headers[1] in ('semicolon="a;b"; Path=/',
+                                       'semicolon="a\\073b"; Path=/'),
+                        headers[1])
+        self.assertEqual(headers[2], 'quote="a\\"b"; Path=/')
+
+        data = [('foo=a=b', 'a=b'),
+                ('foo="a=b"', 'a=b'),
+                ('foo="a;b"', 'a;b'),
+                #('foo=a\\073b', 'a;b'),  # even encoded, ";" is a delimiter
+                ('foo="a\\073b"', 'a;b'),
+                ('foo="a\\"b"', 'a"b'),
+                ]
+        for header, expected in data:
+            logging.info("trying %r", header)
+            response = self.fetch("/get", headers={"Cookie": header})
+            self.assertEqual(response.body, utf8(expected))
+
 class AuthRedirectRequestHandler(RequestHandler):
     def initialize(self, login_url):
         self.login_url = login_url
index c5b0ed79d7760e2c072c28f5bb9e8afc2250a9cd..6e8d14854d956fcacd52f297e497d5ba9677bed3 100644 (file)
@@ -293,7 +293,7 @@ class RequestHandler(object):
     def cookies(self):
         """A dictionary of Cookie.Morsel objects."""
         if not hasattr(self, "_cookies"):
-            self._cookies = Cookie.BaseCookie()
+            self._cookies = Cookie.SimpleCookie()
             if "Cookie" in self.request.headers:
                 try:
                     self._cookies.load(
@@ -325,7 +325,7 @@ class RequestHandler(object):
             raise ValueError("Invalid cookie %r: %r" % (name, value))
         if not hasattr(self, "_new_cookies"):
             self._new_cookies = []
-        new_cookie = Cookie.BaseCookie()
+        new_cookie = Cookie.SimpleCookie()
         self._new_cookies.append(new_cookie)
         new_cookie[name] = value
         if domain: