Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
71dad72e
Commit
71dad72e
authored
Dec 23, 2005
by
Neal Norwitz
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SF patch #1157027, cookielib mis-handles RFC 2109 cookies in Netscape mode
parent
a2c110b1
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
100 additions
and
22 deletions
+100
-22
Doc/lib/libcookielib.tex
Doc/lib/libcookielib.tex
+45
-17
Lib/cookielib.py
Lib/cookielib.py
+22
-5
Lib/test/test_cookielib.py
Lib/test/test_cookielib.py
+33
-0
No files found.
Doc/lib/libcookielib.tex
View file @
71dad72e
...
@@ -18,17 +18,18 @@ the server in later HTTP requests.
...
@@ -18,17 +18,18 @@ the server in later HTTP requests.
Both the regular Netscape cookie protocol and the protocol defined by
Both the regular Netscape cookie protocol and the protocol defined by
\rfc
{
2965
}
are handled. RFC 2965 handling is switched off by default.
\rfc
{
2965
}
are handled. RFC 2965 handling is switched off by default.
\rfc
{
2109
}
cookies are parsed as Netscape cookies and subsequently
\rfc
{
2109
}
cookies are parsed as Netscape cookies and subsequently
treated as RFC 2965 cookies. Note that the great majority of cookies
treated either as Netscape or RFC 2965 cookies according to the
on the Internet are Netscape cookies.
\module
{
cookielib
}
attempts to
'policy' in effect. Note that the great majority of cookies on the
follow the de-facto Netscape cookie protocol (which differs
Internet are Netscape cookies.
\module
{
cookielib
}
attempts to follow
substantially from that set out in the original Netscape
the de-facto Netscape cookie protocol (which differs substantially
specification), including taking note of the
\code
{
max-age
}
and
from that set out in the original Netscape specification), including
\code
{
port
}
cookie-attributes introduced with RFC 2109.
\note
{
The
taking note of the
\code
{
max-age
}
and
\code
{
port
}
cookie-attributes
various named parameters found in
\mailheader
{
Set-Cookie
}
and
introduced with RFC 2109.
\note
{
The various named parameters found in
\mailheader
{
Set-Cookie2
}
headers (eg.
\code
{
domain
}
and
\mailheader
{
Set-Cookie
}
and
\mailheader
{
Set-Cookie2
}
headers
\code
{
expires
}
) are conventionally referred to as
\dfn
{
attributes
}
.
(eg.
\code
{
domain
}
and
\code
{
expires
}
) are conventionally referred to
To distinguish them from Python attributes, the documentation for this
as
\dfn
{
attributes
}
. To distinguish them from Python attributes, the
module uses the term
\dfn
{
cookie-attribute
}
instead
}
.
documentation for this module uses the term
\dfn
{
cookie-attribute
}
instead
}
.
The module defines the following exception:
The module defines the following exception:
...
@@ -74,6 +75,7 @@ accepted from / returned to the server.
...
@@ -74,6 +75,7 @@ accepted from / returned to the server.
blocked
_
domains=
\constant
{
None
}
,
blocked
_
domains=
\constant
{
None
}
,
allowed
_
domains=
\constant
{
None
}
,
allowed
_
domains=
\constant
{
None
}
,
netscape=
\constant
{
True
}
, rfc2965=
\constant
{
False
}
,
netscape=
\constant
{
True
}
, rfc2965=
\constant
{
False
}
,
rfc2109
_
as
_
netscape=
\constant
{
None
}
,
hide
_
cookie2=
\constant
{
False
}
,
hide
_
cookie2=
\constant
{
False
}
,
strict
_
domain=
\constant
{
False
}
,
strict
_
domain=
\constant
{
False
}
,
strict
_
rfc2965
_
unverifiable=
\constant
{
True
}
,
strict
_
rfc2965
_
unverifiable=
\constant
{
True
}
,
...
@@ -92,10 +94,14 @@ documentation for \class{CookiePolicy} and \class{DefaultCookiePolicy}
...
@@ -92,10 +94,14 @@ documentation for \class{CookiePolicy} and \class{DefaultCookiePolicy}
objects.
objects.
\class
{
DefaultCookiePolicy
}
implements the standard accept / reject
\class
{
DefaultCookiePolicy
}
implements the standard accept / reject
rules for Netscape and RFC 2965 cookies. RFC 2109 cookies
rules for Netscape and RFC 2965 cookies.
By default,
RFC 2109 cookies
(ie. cookies received in a
\mailheader
{
Set-Cookie
}
header with a
(ie. cookies received in a
\mailheader
{
Set-Cookie
}
header with a
version cookie-attribute of 1) are treated according to the RFC 2965
version cookie-attribute of 1) are treated according to the RFC 2965
rules.
\class
{
DefaultCookiePolicy
}
also provides some parameters to
rules. However, if RFC 2965 handling is turned off or
\member
{
rfc2109
_
as
_
netscape
}
is True, RFC 2109 cookies are
'downgraded' by the
\class
{
CookieJar
}
instance to Netscape cookies, by
setting the
\member
{
version
}
attribute of the
\class
{
Cookie
}
instance
to 0.
\class
{
DefaultCookiePolicy
}
also provides some parameters to
allow some fine-tuning of policy.
allow some fine-tuning of policy.
\end{classdesc}
\end{classdesc}
...
@@ -493,6 +499,17 @@ receiving cookies.
...
@@ -493,6 +499,17 @@ receiving cookies.
which are all initialised from the constructor arguments of the same
which are all initialised from the constructor arguments of the same
name, and which may all be assigned to.
name, and which may all be assigned to.
\begin{memberdesc}
{
rfc2109
_
as
_
netscape
}
If true, request that the
\class
{
CookieJar
}
instance downgrade RFC
2109 cookies (ie. cookies received in a
\mailheader
{
Set-Cookie
}
header
with a version cookie-attribute of 1) to Netscape cookies by setting
the version attribute of the
\class
{
Cookie
}
instance to 0. The
default value is
\constant
{
None
}
, in which case RFC 2109 cookies are
downgraded if and only if RFC 2965 handling is turned off. Therefore,
RFC 2109 cookies are downgraded by default.
\versionadded
{
2.5
}
\end{memberdesc}
General strictness switches:
General strictness switches:
\begin{memberdesc}
{
strict
_
domain
}
\begin{memberdesc}
{
strict
_
domain
}
...
@@ -567,9 +584,10 @@ Equivalent to \code{DomainStrictNoDots|DomainStrictNonDomain}.
...
@@ -567,9 +584,10 @@ Equivalent to \code{DomainStrictNoDots|DomainStrictNonDomain}.
\class
{
Cookie
}
instances have Python attributes roughly corresponding
\class
{
Cookie
}
instances have Python attributes roughly corresponding
to the standard cookie-attributes specified in the various cookie
to the standard cookie-attributes specified in the various cookie
standards. The correspondence is not one-to-one, because there are
standards. The correspondence is not one-to-one, because there are
complicated rules for assigning default values,
and
because the
complicated rules for assigning default values, because the
\code
{
max-age
}
and
\code
{
expires
}
cookie-attributes contain equivalent
\code
{
max-age
}
and
\code
{
expires
}
cookie-attributes contain equivalent
information.
information, and because RFC 2109 cookies may be 'downgraded' by
\module
{
cookielib
}
from version 1 to version 0 (Netscape) cookies.
Assignment to these attributes should not be necessary other than in
Assignment to these attributes should not be necessary other than in
rare circumstances in a
\class
{
CookiePolicy
}
method. The class does
rare circumstances in a
\class
{
CookiePolicy
}
method. The class does
...
@@ -577,8 +595,10 @@ not enforce internal consistency, so you should know what you're
...
@@ -577,8 +595,10 @@ not enforce internal consistency, so you should know what you're
doing if you do that.
doing if you do that.
\begin{memberdesc}
[Cookie]
{
version
}
\begin{memberdesc}
[Cookie]
{
version
}
Integer or
\constant
{
None
}
. Netscape cookies have version 0. RFC
Integer or
\constant
{
None
}
. Netscape cookies have
\member
{
version
}
0.
2965 and RFC 2109 cookies have version 1.
RFC 2965 and RFC 2109 cookies have a
\code
{
version
}
cookie-attribute
of 1. However, note that
\module
{
cookielib
}
may 'downgrade' RFC 2109
cookies to Netscape cookies, in which case
\member
{
version
}
is 0.
\end{memberdesc}
\end{memberdesc}
\begin{memberdesc}
[Cookie]
{
name
}
\begin{memberdesc}
[Cookie]
{
name
}
Cookie name (a string).
Cookie name (a string).
...
@@ -611,6 +631,14 @@ or \constant{None}.
...
@@ -611,6 +631,14 @@ or \constant{None}.
URL linking to a comment from the server explaining the function of
URL linking to a comment from the server explaining the function of
this cookie, or
\constant
{
None
}
.
this cookie, or
\constant
{
None
}
.
\end{memberdesc}
\end{memberdesc}
\begin{memberdesc}
[Cookie]
{
rfc2109
}
True if this cookie was received as an RFC 2109 cookie (ie. the cookie
arrived in a
\mailheader
{
Set-Cookie
}
header, and the value of the
Version cookie-attribute in that header was 1). This attribute is
provided because
\module
{
cookielib
}
may 'downgrade' RFC 2109 cookies
to Netscape cookies, in which case
\member
{
version
}
is 0.
\versionadded
{
2.5
}
\end{memberdesc}
\begin{memberdesc}
[Cookie]
{
port
_
specified
}
\begin{memberdesc}
[Cookie]
{
port
_
specified
}
True if a port or set of ports was explicitly specified by the server
True if a port or set of ports was explicitly specified by the server
...
...
Lib/cookielib.py
View file @
71dad72e
...
@@ -460,10 +460,7 @@ def parse_ns_headers(ns_headers):
...
@@ -460,10 +460,7 @@ def parse_ns_headers(ns_headers):
if lc in known_attrs:
if lc in known_attrs:
k = lc
k = lc
if k == "version":
if k == "version":
# This is an RFC 2109 cookie. Will be treated as RFC 2965
# This is an RFC 2109 cookie.
# cookie in rest of code.
# Probably it should be parsed with split_header_words, but
# that's too much hassle.
version_set = True
version_set = True
if k == "expires":
if k == "expires":
# convert expires date to seconds since epoch
# convert expires date to seconds since epoch
...
@@ -723,7 +720,9 @@ class Cookie:
...
@@ -723,7 +720,9 @@ class Cookie:
discard,
discard,
comment,
comment,
comment_url,
comment_url,
rest):
rest,
rfc2109=False,
):
if version is not None: version = int(version)
if version is not None: version = int(version)
if expires is not None: expires = int(expires)
if expires is not None: expires = int(expires)
...
@@ -750,6 +749,7 @@ class Cookie:
...
@@ -750,6 +749,7 @@ class Cookie:
self.discard = discard
self.discard = discard
self.comment = comment
self.comment = comment
self.comment_url = comment_url
self.comment_url = comment_url
self.rfc2109 = rfc2109
self._rest = copy.copy(rest)
self._rest = copy.copy(rest)
...
@@ -787,6 +787,7 @@ class Cookie:
...
@@ -787,6 +787,7 @@ class Cookie:
attr = getattr(self, name)
attr = getattr(self, name)
args.append("%s=%s" % (name, repr(attr)))
args.append("%s=%s" % (name, repr(attr)))
args.append("rest=%s" % repr(self._rest))
args.append("rest=%s" % repr(self._rest))
args.append("rfc2109=%s" % repr(self.rfc2109))
return "Cookie(%s)" % ", ".join(args)
return "Cookie(%s)" % ", ".join(args)
...
@@ -836,6 +837,7 @@ class DefaultCookiePolicy(CookiePolicy):
...
@@ -836,6 +837,7 @@ class DefaultCookiePolicy(CookiePolicy):
def __init__(self,
def __init__(self,
blocked_domains=None, allowed_domains=None,
blocked_domains=None, allowed_domains=None,
netscape=True, rfc2965=False,
netscape=True, rfc2965=False,
rfc2109_as_netscape=None,
hide_cookie2=False,
hide_cookie2=False,
strict_domain=False,
strict_domain=False,
strict_rfc2965_unverifiable=True,
strict_rfc2965_unverifiable=True,
...
@@ -847,6 +849,7 @@ class DefaultCookiePolicy(CookiePolicy):
...
@@ -847,6 +849,7 @@ class DefaultCookiePolicy(CookiePolicy):
"""
Constructor
arguments
should
be
passed
as
keyword
arguments
only
.
"""
"""
Constructor
arguments
should
be
passed
as
keyword
arguments
only
.
"""
self.netscape = netscape
self.netscape = netscape
self.rfc2965 = rfc2965
self.rfc2965 = rfc2965
self.rfc2109_as_netscape = rfc2109_as_netscape
self.hide_cookie2 = hide_cookie2
self.hide_cookie2 = hide_cookie2
self.strict_domain = strict_domain
self.strict_domain = strict_domain
self.strict_rfc2965_unverifiable = strict_rfc2965_unverifiable
self.strict_rfc2965_unverifiable = strict_rfc2965_unverifiable
...
@@ -1518,6 +1521,18 @@ class CookieJar:
...
@@ -1518,6 +1521,18 @@ class CookieJar:
if cookie: cookies.append(cookie)
if cookie: cookies.append(cookie)
return cookies
return cookies
def _process_rfc2109_cookies(self, cookies):
rfc2109_as_ns = getattr(self._policy, 'rfc2109_as_netscape', None)
if rfc2109_as_ns is None:
rfc2109_as_ns = not self._policy.rfc2965
for cookie in cookies:
if cookie.version == 1:
cookie.rfc2109 = True
if rfc2109_as_ns:
# treat 2109 cookies as Netscape cookies rather than
# as RFC2965 cookies
cookie.version = 0
def make_cookies(self, response, request):
def make_cookies(self, response, request):
"""
Return
sequence
of
Cookie
objects
extracted
from
response
object
.
"""
"""
Return
sequence
of
Cookie
objects
extracted
from
response
object
.
"""
# get cookie-attributes for RFC 2965 and Netscape protocols
# get cookie-attributes for RFC 2965 and Netscape protocols
...
@@ -1543,11 +1558,13 @@ class CookieJar:
...
@@ -1543,11 +1558,13 @@ class CookieJar:
if ns_hdrs and netscape:
if ns_hdrs and netscape:
try:
try:
# RFC 2109 and Netscape cookies
ns_cookies = self._cookies_from_attrs_set(
ns_cookies = self._cookies_from_attrs_set(
parse_ns_headers(ns_hdrs), request)
parse_ns_headers(ns_hdrs), request)
except:
except:
reraise_unmasked_exceptions()
reraise_unmasked_exceptions()
ns_cookies = []
ns_cookies = []
self._process_rfc2109_cookies(ns_cookies)
# Look for Netscape cookies (from Set-Cookie headers) that match
# Look for Netscape cookies (from Set-Cookie headers) that match
# corresponding RFC 2965 cookies (from Set-Cookie2 headers).
# corresponding RFC 2965 cookies (from Set-Cookie2 headers).
...
...
Lib/test/test_cookielib.py
View file @
71dad72e
...
@@ -386,6 +386,39 @@ class CookieTests(TestCase):
...
@@ -386,6 +386,39 @@ class CookieTests(TestCase):
self
.
assertEquals
(
interact_netscape
(
c
,
"http://www.acme.com/foo/"
),
self
.
assertEquals
(
interact_netscape
(
c
,
"http://www.acme.com/foo/"
),
'"spam"; eggs'
)
'"spam"; eggs'
)
def
test_rfc2109_handling
(
self
):
# RFC 2109 cookies are handled as RFC 2965 or Netscape cookies,
# dependent on policy settings
from
cookielib
import
CookieJar
,
DefaultCookiePolicy
for
rfc2109_as_netscape
,
rfc2965
,
version
in
[
# default according to rfc2965 if not explicitly specified
(
None
,
False
,
0
),
(
None
,
True
,
1
),
# explicit rfc2109_as_netscape
(
False
,
False
,
None
),
# version None here means no cookie stored
(
False
,
True
,
1
),
(
True
,
False
,
0
),
(
True
,
True
,
0
),
]:
policy
=
DefaultCookiePolicy
(
rfc2109_as_netscape
=
rfc2109_as_netscape
,
rfc2965
=
rfc2965
)
c
=
CookieJar
(
policy
)
interact_netscape
(
c
,
"http://www.example.com/"
,
"ni=ni; Version=1"
)
try
:
cookie
=
c
.
_cookies
[
"www.example.com"
][
"/"
][
"ni"
]
except
KeyError
:
self
.
assert_
(
version
is
None
)
# didn't expect a stored cookie
else
:
self
.
assertEqual
(
cookie
.
version
,
version
)
# 2965 cookies are unaffected
interact_2965
(
c
,
"http://www.example.com/"
,
"foo=bar; Version=1"
)
if
rfc2965
:
cookie2965
=
c
.
_cookies
[
"www.example.com"
][
"/"
][
"foo"
]
self
.
assertEqual
(
cookie2965
.
version
,
1
)
def
test_ns_parser
(
self
):
def
test_ns_parser
(
self
):
from
cookielib
import
CookieJar
,
DEFAULT_HTTP_PORT
from
cookielib
import
CookieJar
,
DEFAULT_HTTP_PORT
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment