web/lib/django/http/__init__.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
--- a/web/lib/django/http/__init__.py	Wed May 19 17:43:59 2010 +0200
+++ b/web/lib/django/http/__init__.py	Tue May 25 02:43:45 2010 +0200
@@ -1,6 +1,6 @@
 import os
 import re
-from Cookie import SimpleCookie, CookieError
+from Cookie import BaseCookie, SimpleCookie, CookieError
 from pprint import pformat
 from urllib import urlencode
 from urlparse import urljoin
@@ -183,7 +183,7 @@
         return result
 
     def __deepcopy__(self, memo):
-        import copy
+        import django.utils.copycompat as copy
         result = self.__class__('', mutable=True)
         memo[id(self)] = result
         for key, value in dict.items(self):
@@ -248,16 +248,46 @@
             output.extend([urlencode({k: smart_str(v, self.encoding)}) for v in list_])
         return '&'.join(output)
 
+class CompatCookie(SimpleCookie):
+    """
+    Cookie class that handles some issues with browser compatibility.
+    """
+    def value_encode(self, val):
+        # Some browsers do not support quoted-string from RFC 2109,
+        # including some versions of Safari and Internet Explorer.
+        # These browsers split on ';', and some versions of Safari
+        # are known to split on ', '. Therefore, we encode ';' and ','
+
+        # SimpleCookie already does the hard work of encoding and decoding.
+        # It uses octal sequences like '\\012' for newline etc.
+        # and non-ASCII chars.  We just make use of this mechanism, to
+        # avoid introducing two encoding schemes which would be confusing
+        # and especially awkward for javascript.
+
+        # NB, contrary to Python docs, value_encode returns a tuple containing
+        # (real val, encoded_val)
+        val, encoded = super(CompatCookie, self).value_encode(val)
+
+        encoded = encoded.replace(";", "\\073").replace(",","\\054")
+        # If encoded now contains any quoted chars, we need double quotes
+        # around the whole string.
+        if "\\" in encoded and not encoded.startswith('"'):
+            encoded = '"' + encoded + '"'
+
+        return val, encoded
+
 def parse_cookie(cookie):
     if cookie == '':
         return {}
-    try:
-        c = SimpleCookie()
-        c.load(cookie)
-    except CookieError:
-        # Invalid cookie
-        return {}
-
+    if not isinstance(cookie, BaseCookie):
+        try:
+            c = CompatCookie()
+            c.load(cookie)
+        except CookieError:
+            # Invalid cookie
+            return {}
+    else:
+        c = cookie
     cookiedict = {}
     for key in c.keys():
         cookiedict[key] = c.get(key).value
@@ -286,7 +316,7 @@
         else:
             self._container = [content]
             self._is_string = True
-        self.cookies = SimpleCookie()
+        self.cookies = CompatCookie()
         if status:
             self.status_code = status
 
@@ -404,14 +434,14 @@
 
     def __init__(self, redirect_to):
         HttpResponse.__init__(self)
-        self['Location'] = redirect_to
+        self['Location'] = iri_to_uri(redirect_to)
 
 class HttpResponsePermanentRedirect(HttpResponse):
     status_code = 301
 
     def __init__(self, redirect_to):
         HttpResponse.__init__(self)
-        self['Location'] = redirect_to
+        self['Location'] = iri_to_uri(redirect_to)
 
 class HttpResponseNotModified(HttpResponse):
     status_code = 304