mirror of https://github.com/python/cpython
Remove deprecated SmartCookie and SerialCookie classes.
This commit is contained in:
parent
b17acad68e
commit
6101395e74
|
@ -39,36 +39,6 @@ result, the parsing rules used are a bit less strict.
|
|||
and :meth:`value_encode` to be the identity and :func:`str` respectively.
|
||||
|
||||
|
||||
.. class:: SerialCookie([input])
|
||||
|
||||
This class derives from :class:`BaseCookie` and overrides :meth:`value_decode`
|
||||
and :meth:`value_encode` to be the :func:`pickle.loads` and
|
||||
:func:`pickle.dumps`.
|
||||
|
||||
.. deprecated:: 2.3
|
||||
Reading pickled values from untrusted cookie data is a huge security hole, as
|
||||
pickle strings can be crafted to cause arbitrary code to execute on your server.
|
||||
It is supported for backwards compatibility only, and may eventually go away.
|
||||
|
||||
|
||||
.. class:: SmartCookie([input])
|
||||
|
||||
This class derives from :class:`BaseCookie`. It overrides :meth:`value_decode`
|
||||
to be :func:`pickle.loads` if it is a valid pickle, and otherwise the value
|
||||
itself. It overrides :meth:`value_encode` to be :func:`pickle.dumps` unless it
|
||||
is a string, in which case it returns the value itself.
|
||||
|
||||
.. deprecated:: 2.3
|
||||
The same security warning from :class:`SerialCookie` applies here.
|
||||
|
||||
A further security note is warranted. For backwards compatibility, the
|
||||
:mod:`http.cookies` module exports a class named :class:`Cookie` which is just an
|
||||
alias for :class:`SmartCookie`. This is probably a mistake and will likely be
|
||||
removed in a future version. You should not use the :class:`Cookie` class in
|
||||
your applications, for the same reason why you should not use the
|
||||
:class:`SerialCookie` class.
|
||||
|
||||
|
||||
.. seealso::
|
||||
|
||||
Module :mod:`http.cookiejar`
|
||||
|
@ -212,8 +182,6 @@ The following example demonstrates how to use the :mod:`http.cookies` module.
|
|||
|
||||
>>> from http import cookies
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C = cookies.SerialCookie()
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C["fig"] = "newton"
|
||||
>>> C["sugar"] = "wafer"
|
||||
>>> print(C) # generate HTTP headers
|
||||
|
@ -222,28 +190,28 @@ The following example demonstrates how to use the :mod:`http.cookies` module.
|
|||
>>> print(C.output()) # same thing
|
||||
Set-Cookie: fig=newton
|
||||
Set-Cookie: sugar=wafer
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C["rocky"] = "road"
|
||||
>>> C["rocky"]["path"] = "/cookie"
|
||||
>>> print(C.output(header="Cookie:"))
|
||||
Cookie: rocky=road; Path=/cookie
|
||||
>>> print(C.output(attrs=[], header="Cookie:"))
|
||||
Cookie: rocky=road
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C.load("chips=ahoy; vienna=finger") # load from a string (HTTP header)
|
||||
>>> print(C)
|
||||
Set-Cookie: chips=ahoy
|
||||
Set-Cookie: vienna=finger
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
|
||||
>>> print(C)
|
||||
Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C["oreo"] = "doublestuff"
|
||||
>>> C["oreo"]["path"] = "/"
|
||||
>>> print(C)
|
||||
Set-Cookie: oreo=doublestuff; Path=/
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C["twix"] = "none for you"
|
||||
>>> C["twix"].value
|
||||
'none for you'
|
||||
|
@ -257,24 +225,3 @@ The following example demonstrates how to use the :mod:`http.cookies` module.
|
|||
>>> print(C)
|
||||
Set-Cookie: number=7
|
||||
Set-Cookie: string=seven
|
||||
>>> C = cookies.SerialCookie()
|
||||
>>> C["number"] = 7
|
||||
>>> C["string"] = "seven"
|
||||
>>> C["number"].value
|
||||
7
|
||||
>>> C["string"].value
|
||||
'seven'
|
||||
>>> print(C)
|
||||
Set-Cookie: number="I7\012."
|
||||
Set-Cookie: string="S'seven'\012p1\012."
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C["number"] = 7
|
||||
>>> C["string"] = "seven"
|
||||
>>> C["number"].value
|
||||
7
|
||||
>>> C["string"].value
|
||||
'seven'
|
||||
>>> print(C)
|
||||
Set-Cookie: number="I7\012."
|
||||
Set-Cookie: string=seven
|
||||
|
||||
|
|
|
@ -50,23 +50,14 @@ Importing is easy..
|
|||
|
||||
>>> from http import cookies
|
||||
|
||||
Most of the time you start by creating a cookie. Cookies come in
|
||||
three flavors, each with slightly different encoding semantics, but
|
||||
more on that later.
|
||||
Most of the time you start by creating a cookie.
|
||||
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C = cookies.SerialCookie()
|
||||
>>> C = cookies.SmartCookie()
|
||||
|
||||
[Note: Long-time users of cookies.py will remember using
|
||||
cookies.Cookie() to create an Cookie object. Although deprecated, it
|
||||
is still supported by the code. See the Backward Compatibility notes
|
||||
for more information.]
|
||||
|
||||
Once you've created your Cookie, you can add values just as if it were
|
||||
a dictionary.
|
||||
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C["fig"] = "newton"
|
||||
>>> C["sugar"] = "wafer"
|
||||
>>> C.output()
|
||||
|
@ -77,7 +68,7 @@ appropriate format for a Set-Cookie: header. This is the
|
|||
default behavior. You can change the header and printed
|
||||
attributes by using the .output() function
|
||||
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C["rocky"] = "road"
|
||||
>>> C["rocky"]["path"] = "/cookie"
|
||||
>>> print(C.output(header="Cookie:"))
|
||||
|
@ -89,7 +80,7 @@ The load() method of a Cookie extracts cookies from a string. In a
|
|||
CGI script, you would use this method to extract the cookies from the
|
||||
HTTP_COOKIE environment variable.
|
||||
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C.load("chips=ahoy; vienna=finger")
|
||||
>>> C.output()
|
||||
'Set-Cookie: chips=ahoy\r\nSet-Cookie: vienna=finger'
|
||||
|
@ -98,7 +89,7 @@ The load() method is darn-tootin smart about identifying cookies
|
|||
within a string. Escaped quotation marks, nested semicolons, and other
|
||||
such trickeries do not confuse it.
|
||||
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
|
||||
>>> print(C)
|
||||
Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"
|
||||
|
@ -107,7 +98,7 @@ Each element of the Cookie also supports all of the RFC 2109
|
|||
Cookie attributes. Here's an example which sets the Path
|
||||
attribute.
|
||||
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C["oreo"] = "doublestuff"
|
||||
>>> C["oreo"]["path"] = "/"
|
||||
>>> print(C)
|
||||
|
@ -116,21 +107,11 @@ attribute.
|
|||
Each dictionary element has a 'value' attribute, which gives you
|
||||
back the value associated with the key.
|
||||
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C = cookies.SimpleCookie()
|
||||
>>> C["twix"] = "none for you"
|
||||
>>> C["twix"].value
|
||||
'none for you'
|
||||
|
||||
|
||||
A Bit More Advanced
|
||||
-------------------
|
||||
|
||||
As mentioned before, there are three different flavors of Cookie
|
||||
objects, each with different encoding/decoding semantics. This
|
||||
section briefly discusses the differences.
|
||||
|
||||
SimpleCookie
|
||||
|
||||
The SimpleCookie expects that all values should be standard strings.
|
||||
Just to be sure, SimpleCookie invokes the str() builtin to convert
|
||||
the value to a string, when the values are set dictionary-style.
|
||||
|
@ -145,62 +126,6 @@ the value to a string, when the values are set dictionary-style.
|
|||
>>> C.output()
|
||||
'Set-Cookie: number=7\r\nSet-Cookie: string=seven'
|
||||
|
||||
|
||||
SerialCookie
|
||||
|
||||
The SerialCookie expects that all values should be serialized using
|
||||
pickle. As a result of serializing, SerialCookie can save almost any
|
||||
Python object to a value, and recover the exact same object when the
|
||||
cookie has been returned. (SerialCookie can yield some
|
||||
strange-looking cookie values, however.)
|
||||
|
||||
>>> C = cookies.SerialCookie()
|
||||
>>> C["number"] = 7
|
||||
>>> C["string"] = "seven"
|
||||
>>> C["number"].value
|
||||
7
|
||||
>>> C["string"].value
|
||||
'seven'
|
||||
>>> C.output()
|
||||
'Set-Cookie: number="L7\\012."\r\nSet-Cookie: string="Vseven\\012p0\\012."'
|
||||
|
||||
Be warned, however, if SerialCookie cannot de-serialize a value (because
|
||||
it isn't a valid pickle'd object), IT WILL RAISE AN EXCEPTION.
|
||||
|
||||
|
||||
SmartCookie
|
||||
|
||||
The SmartCookie combines aspects of each of the other two flavors.
|
||||
When setting a value in a dictionary-fashion, the SmartCookie will
|
||||
serialize (ala pickle) the value *if and only if* it isn't a
|
||||
Python string. String objects are *not* serialized. Similarly,
|
||||
when the load() method parses out values, it attempts to de-serialize
|
||||
the value. If it fails, then it fallsback to treating the value
|
||||
as a string.
|
||||
|
||||
>>> C = cookies.SmartCookie()
|
||||
>>> C["number"] = 7
|
||||
>>> C["string"] = "seven"
|
||||
>>> C["number"].value
|
||||
7
|
||||
>>> C["string"].value
|
||||
'seven'
|
||||
>>> C.output()
|
||||
'Set-Cookie: number="L7\\012."\r\nSet-Cookie: string=seven'
|
||||
|
||||
|
||||
Backwards Compatibility
|
||||
-----------------------
|
||||
|
||||
In order to keep compatibilty with earlier versions of Cookie.py,
|
||||
it is still possible to use cookies.Cookie() to create a Cookie. In
|
||||
fact, this simply returns a SmartCookie.
|
||||
|
||||
>>> C = cookies.Cookie()
|
||||
>>> print(C.__class__.__name__)
|
||||
SmartCookie
|
||||
|
||||
|
||||
Finis.
|
||||
""" #"
|
||||
# ^
|
||||
|
@ -215,8 +140,7 @@ from pickle import dumps, loads
|
|||
|
||||
import re, warnings
|
||||
|
||||
__all__ = ["CookieError","BaseCookie","SimpleCookie","SerialCookie",
|
||||
"SmartCookie","Cookie"]
|
||||
__all__ = ["CookieError", "BaseCookie", "SimpleCookie"]
|
||||
|
||||
_nulljoin = ''.join
|
||||
_semispacejoin = '; '.join
|
||||
|
@ -653,70 +577,6 @@ class SimpleCookie(BaseCookie):
|
|||
return strval, _quote( strval )
|
||||
# end SimpleCookie
|
||||
|
||||
class SerialCookie(BaseCookie):
|
||||
"""SerialCookie
|
||||
SerialCookie supports arbitrary objects as cookie values. All
|
||||
values are serialized (using pickle) before being sent to the
|
||||
client. All incoming values are assumed to be valid Pickle
|
||||
representations. IF AN INCOMING VALUE IS NOT IN A VALID PICKLE
|
||||
FORMAT, THEN AN EXCEPTION WILL BE RAISED.
|
||||
|
||||
Note: Large cookie values add overhead because they must be
|
||||
retransmitted on every HTTP transaction.
|
||||
|
||||
Note: HTTP has a 2k limit on the size of a cookie. This class
|
||||
does not check for this limit, so be careful!!!
|
||||
"""
|
||||
def __init__(self, input=None):
|
||||
warnings.warn("SerialCookie class is insecure; do not use it",
|
||||
DeprecationWarning)
|
||||
BaseCookie.__init__(self, input)
|
||||
# end __init__
|
||||
def value_decode(self, val):
|
||||
# This could raise an exception!
|
||||
return loads( _unquote(val).encode('latin-1') ), val
|
||||
def value_encode(self, val):
|
||||
return val, _quote( dumps(val, 0).decode('latin-1') )
|
||||
# end SerialCookie
|
||||
|
||||
class SmartCookie(BaseCookie):
|
||||
"""SmartCookie
|
||||
SmartCookie supports arbitrary objects as cookie values. If the
|
||||
object is a string, then it is quoted. If the object is not a
|
||||
string, however, then SmartCookie will use pickle to serialize
|
||||
the object into a string representation.
|
||||
|
||||
Note: Large cookie values add overhead because they must be
|
||||
retransmitted on every HTTP transaction.
|
||||
|
||||
Note: HTTP has a 2k limit on the size of a cookie. This class
|
||||
does not check for this limit, so be careful!!!
|
||||
"""
|
||||
def __init__(self, input=None):
|
||||
warnings.warn("Cookie/SmartCookie class is insecure; do not use it",
|
||||
DeprecationWarning)
|
||||
BaseCookie.__init__(self, input)
|
||||
# end __init__
|
||||
def value_decode(self, val):
|
||||
strval = _unquote(val)
|
||||
try:
|
||||
return loads(strval.encode('latin-1')), val
|
||||
except:
|
||||
return strval, val
|
||||
def value_encode(self, val):
|
||||
if isinstance(val, str):
|
||||
return val, _quote(val)
|
||||
else:
|
||||
return val, _quote( dumps(val, 0).decode('latin-1') )
|
||||
# end SmartCookie
|
||||
|
||||
|
||||
###########################################################
|
||||
# Backwards Compatibility: Don't break any existing code!
|
||||
|
||||
# We provide Cookie() as an alias for SmartCookie()
|
||||
Cookie = SmartCookie
|
||||
|
||||
#
|
||||
###########################################################
|
||||
|
||||
|
@ -726,8 +586,3 @@ def _test():
|
|||
|
||||
if __name__ == "__main__":
|
||||
_test()
|
||||
|
||||
|
||||
#Local Variables:
|
||||
#tab-width: 4
|
||||
#end:
|
||||
|
|
|
@ -10,7 +10,6 @@ warnings.filterwarnings("ignore",
|
|||
DeprecationWarning)
|
||||
|
||||
class CookieTests(unittest.TestCase):
|
||||
# Currently this only tests SimpleCookie
|
||||
def test_basic(self):
|
||||
cases = [
|
||||
{ 'data': 'chips=ahoy; vienna=finger',
|
||||
|
|
|
@ -60,6 +60,9 @@ Extension Modules
|
|||
Library
|
||||
-------
|
||||
|
||||
- The deprecated ``SmartCookie`` and ``SimpleCookie`` classes have
|
||||
been removed from ``http.cookies``.
|
||||
|
||||
- The ``commands`` module has been removed. Its getoutput() and
|
||||
getstatusoutput() functions have been moved to the ``subprocess`` module.
|
||||
|
||||
|
|
Loading…
Reference in New Issue