You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

107 lines
4.3 KiB

  1. from __future__ import unicode_literals
  2. import sys
  3. from django.utils import six
  4. from django.utils.encoding import force_str
  5. from django.utils.six.moves import http_cookies
  6. # Some versions of Python 2.7 and later won't need this encoding bug fix:
  7. _cookie_encodes_correctly = http_cookies.SimpleCookie().value_encode(';') == (';', '"\\073"')
  8. # See ticket #13007, http://bugs.python.org/issue2193 and http://trac.edgewall.org/ticket/2256
  9. _tc = http_cookies.SimpleCookie()
  10. try:
  11. _tc.load(str('foo:bar=1'))
  12. _cookie_allows_colon_in_names = True
  13. except http_cookies.CookieError:
  14. _cookie_allows_colon_in_names = False
  15. # Cookie pickling bug is fixed in Python 2.7.9 and Python 3.4.3+
  16. # http://bugs.python.org/issue22775
  17. cookie_pickles_properly = (
  18. (sys.version_info[:2] == (2, 7) and sys.version_info >= (2, 7, 9)) or
  19. sys.version_info >= (3, 4, 3)
  20. )
  21. if _cookie_encodes_correctly and _cookie_allows_colon_in_names and cookie_pickles_properly:
  22. SimpleCookie = http_cookies.SimpleCookie
  23. else:
  24. Morsel = http_cookies.Morsel
  25. class SimpleCookie(http_cookies.SimpleCookie):
  26. if not cookie_pickles_properly:
  27. def __setitem__(self, key, value):
  28. # Apply the fix from http://bugs.python.org/issue22775 where
  29. # it's not fixed in Python itself
  30. if isinstance(value, Morsel):
  31. # allow assignment of constructed Morsels (e.g. for pickling)
  32. dict.__setitem__(self, key, value)
  33. else:
  34. super(SimpleCookie, self).__setitem__(key, value)
  35. if not _cookie_encodes_correctly:
  36. def value_encode(self, val):
  37. # Some browsers do not support quoted-string from RFC 2109,
  38. # including some versions of Safari and Internet Explorer.
  39. # These browsers split on ';', and some versions of Safari
  40. # are known to split on ', '. Therefore, we encode ';' and ','
  41. # SimpleCookie already does the hard work of encoding and decoding.
  42. # It uses octal sequences like '\\012' for newline etc.
  43. # and non-ASCII chars. We just make use of this mechanism, to
  44. # avoid introducing two encoding schemes which would be confusing
  45. # and especially awkward for javascript.
  46. # NB, contrary to Python docs, value_encode returns a tuple containing
  47. # (real val, encoded_val)
  48. val, encoded = super(SimpleCookie, self).value_encode(val)
  49. encoded = encoded.replace(";", "\\073").replace(",", "\\054")
  50. # If encoded now contains any quoted chars, we need double quotes
  51. # around the whole string.
  52. if "\\" in encoded and not encoded.startswith('"'):
  53. encoded = '"' + encoded + '"'
  54. return val, encoded
  55. if not _cookie_allows_colon_in_names:
  56. def load(self, rawdata):
  57. self.bad_cookies = set()
  58. if six.PY2 and isinstance(rawdata, six.text_type):
  59. rawdata = force_str(rawdata)
  60. super(SimpleCookie, self).load(rawdata)
  61. for key in self.bad_cookies:
  62. del self[key]
  63. # override private __set() method:
  64. # (needed for using our Morsel, and for laxness with CookieError
  65. def _BaseCookie__set(self, key, real_value, coded_value):
  66. key = force_str(key)
  67. try:
  68. M = self.get(key, Morsel())
  69. M.set(key, real_value, coded_value)
  70. dict.__setitem__(self, key, M)
  71. except http_cookies.CookieError:
  72. if not hasattr(self, 'bad_cookies'):
  73. self.bad_cookies = set()
  74. self.bad_cookies.add(key)
  75. dict.__setitem__(self, key, http_cookies.Morsel())
  76. def parse_cookie(cookie):
  77. if cookie == '':
  78. return {}
  79. if not isinstance(cookie, http_cookies.BaseCookie):
  80. try:
  81. c = SimpleCookie()
  82. c.load(cookie)
  83. except http_cookies.CookieError:
  84. # Invalid cookie
  85. return {}
  86. else:
  87. c = cookie
  88. cookiedict = {}
  89. for key in c.keys():
  90. cookiedict[key] = c.get(key).value
  91. return cookiedict