summaryrefslogtreecommitdiffstats
path: root/Lib/cookielib.py
diff options
context:
space:
mode:
Diffstat (limited to 'Lib/cookielib.py')
-rw-r--r--Lib/cookielib.py176
1 files changed, 94 insertions, 82 deletions
diff --git a/Lib/cookielib.py b/Lib/cookielib.py
index f0a89a5..e8fee0e 100644
--- a/Lib/cookielib.py
+++ b/Lib/cookielib.py
@@ -7,9 +7,9 @@ Docstrings, comments and debug strings in this code refer to the
attributes of the HTTP cookie system as cookie-attributes, to distinguish
them clearly from Python attributes.
-Class diagram (note that the classes which do not derive from
-FileCookieJar are not distributed with the Python standard library, but
-are available from http://wwwsearch.sf.net/):
+Class diagram (note that BSDDBCookieJar and the MSIE* classes are not
+distributed with the Python standard library, but are available from
+http://wwwsearch.sf.net/):
CookieJar____
/ \ \
@@ -25,7 +25,10 @@ are available from http://wwwsearch.sf.net/):
"""
-import sys, re, urlparse, copy, time, urllib, logging
+__all__ = ['Cookie', 'CookieJar', 'CookiePolicy', 'DefaultCookiePolicy',
+ 'FileCookieJar', 'LWPCookieJar', 'LoadError', 'MozillaCookieJar']
+
+import re, urlparse, copy, time, urllib
try:
import threading as _threading
except ImportError:
@@ -33,21 +36,27 @@ except ImportError:
import httplib # only for the default HTTP port
from calendar import timegm
-debug = logging.getLogger("cookielib").debug
+debug = False # set to True to enable debugging via the logging module
+logger = None
+
+def _debug(*args):
+ if not debug:
+ return
+ global logger
+ if not logger:
+ import logging
+ logger = logging.getLogger("cookielib")
+ return logger.debug(*args)
+
DEFAULT_HTTP_PORT = str(httplib.HTTP_PORT)
MISSING_FILENAME_TEXT = ("a filename was not supplied (nor was the CookieJar "
"instance initialised with one)")
-def reraise_unmasked_exceptions(unmasked=()):
+def _warn_unhandled_exception():
# There are a few catch-all except: statements in this module, for
- # catching input that's bad in unexpected ways.
- # This function re-raises some exceptions we don't want to trap.
- unmasked = unmasked + (KeyboardInterrupt, SystemExit, MemoryError)
- etype = sys.exc_info()[0]
- if issubclass(etype, unmasked):
- raise
- # swallowed an exception
+ # catching input that's bad in unexpected ways. Warn if any
+ # exceptions are caught there.
import warnings, traceback, StringIO
f = StringIO.StringIO()
traceback.print_exc(None, f)
@@ -613,7 +622,7 @@ def request_port(request):
try:
int(port)
except ValueError:
- debug("nonnumeric port: '%s'", port)
+ _debug("nonnumeric port: '%s'", port)
return None
else:
port = DEFAULT_HTTP_PORT
@@ -904,7 +913,7 @@ class DefaultCookiePolicy(CookiePolicy):
strict about which cookies to accept).
"""
- debug(" - checking cookie %s=%s", cookie.name, cookie.value)
+ _debug(" - checking cookie %s=%s", cookie.name, cookie.value)
assert cookie.name is not None
@@ -920,25 +929,25 @@ class DefaultCookiePolicy(CookiePolicy):
if cookie.version is None:
# Version is always set to 0 by parse_ns_headers if it's a Netscape
# cookie, so this must be an invalid RFC 2965 cookie.
- debug(" Set-Cookie2 without version attribute (%s=%s)",
- cookie.name, cookie.value)
+ _debug(" Set-Cookie2 without version attribute (%s=%s)",
+ cookie.name, cookie.value)
return False
if cookie.version > 0 and not self.rfc2965:
- debug(" RFC 2965 cookies are switched off")
+ _debug(" RFC 2965 cookies are switched off")
return False
elif cookie.version == 0 and not self.netscape:
- debug(" Netscape cookies are switched off")
+ _debug(" Netscape cookies are switched off")
return False
return True
def set_ok_verifiability(self, cookie, request):
if request.is_unverifiable() and is_third_party(request):
if cookie.version > 0 and self.strict_rfc2965_unverifiable:
- debug(" third-party RFC 2965 cookie during "
+ _debug(" third-party RFC 2965 cookie during "
"unverifiable transaction")
return False
elif cookie.version == 0 and self.strict_ns_unverifiable:
- debug(" third-party Netscape cookie during "
+ _debug(" third-party Netscape cookie during "
"unverifiable transaction")
return False
return True
@@ -948,7 +957,7 @@ class DefaultCookiePolicy(CookiePolicy):
# servers that know both V0 and V1 protocols.
if (cookie.version == 0 and self.strict_ns_set_initial_dollar and
cookie.name.startswith("$")):
- debug(" illegal name (starts with '$'): '%s'", cookie.name)
+ _debug(" illegal name (starts with '$'): '%s'", cookie.name)
return False
return True
@@ -958,33 +967,36 @@ class DefaultCookiePolicy(CookiePolicy):
if ((cookie.version > 0 or
(cookie.version == 0 and self.strict_ns_set_path)) and
not req_path.startswith(cookie.path)):
- debug(" path attribute %s is not a prefix of request "
- "path %s", cookie.path, req_path)
+ _debug(" path attribute %s is not a prefix of request "
+ "path %s", cookie.path, req_path)
return False
return True
def set_ok_domain(self, cookie, request):
if self.is_blocked(cookie.domain):
- debug(" domain %s is in user block-list", cookie.domain)
+ _debug(" domain %s is in user block-list", cookie.domain)
return False
if self.is_not_allowed(cookie.domain):
- debug(" domain %s is not in user allow-list", cookie.domain)
+ _debug(" domain %s is not in user allow-list", cookie.domain)
return False
if cookie.domain_specified:
req_host, erhn = eff_request_host(request)
domain = cookie.domain
if self.strict_domain and (domain.count(".") >= 2):
+ # XXX This should probably be compared with the Konqueror
+ # (kcookiejar.cpp) and Mozilla implementations, but it's a
+ # losing battle.
i = domain.rfind(".")
j = domain.rfind(".", 0, i)
if j == 0: # domain like .foo.bar
tld = domain[i+1:]
sld = domain[j+1:i]
- if (sld.lower() in (
- "co", "ac",
- "com", "edu", "org", "net", "gov", "mil", "int") and
- len(tld) == 2):
+ if sld.lower() in ("co", "ac", "com", "edu", "org", "net",
+ "gov", "mil", "int", "aero", "biz", "cat", "coop",
+ "info", "jobs", "mobi", "museum", "name", "pro",
+ "travel", "eu") and len(tld) == 2:
# domain like .co.uk
- debug(" country-code second level domain %s", domain)
+ _debug(" country-code second level domain %s", domain)
return False
if domain.startswith("."):
undotted_domain = domain[1:]
@@ -992,30 +1004,30 @@ class DefaultCookiePolicy(CookiePolicy):
undotted_domain = domain
embedded_dots = (undotted_domain.find(".") >= 0)
if not embedded_dots and domain != ".local":
- debug(" non-local domain %s contains no embedded dot",
- domain)
+ _debug(" non-local domain %s contains no embedded dot",
+ domain)
return False
if cookie.version == 0:
if (not erhn.endswith(domain) and
(not erhn.startswith(".") and
not ("."+erhn).endswith(domain))):
- debug(" effective request-host %s (even with added "
- "initial dot) does not end end with %s",
- erhn, domain)
+ _debug(" effective request-host %s (even with added "
+ "initial dot) does not end end with %s",
+ erhn, domain)
return False
if (cookie.version > 0 or
(self.strict_ns_domain & self.DomainRFC2965Match)):
if not domain_match(erhn, domain):
- debug(" effective request-host %s does not domain-match "
- "%s", erhn, domain)
+ _debug(" effective request-host %s does not domain-match "
+ "%s", erhn, domain)
return False
if (cookie.version > 0 or
(self.strict_ns_domain & self.DomainStrictNoDots)):
host_prefix = req_host[:-len(domain)]
if (host_prefix.find(".") >= 0 and
not IPV4_RE.search(req_host)):
- debug(" host prefix %s for domain %s contains a dot",
- host_prefix, domain)
+ _debug(" host prefix %s for domain %s contains a dot",
+ host_prefix, domain)
return False
return True
@@ -1030,13 +1042,13 @@ class DefaultCookiePolicy(CookiePolicy):
try:
int(p)
except ValueError:
- debug(" bad port %s (not numeric)", p)
+ _debug(" bad port %s (not numeric)", p)
return False
if p == req_port:
break
else:
- debug(" request port (%s) not found in %s",
- req_port, cookie.port)
+ _debug(" request port (%s) not found in %s",
+ req_port, cookie.port)
return False
return True
@@ -1049,7 +1061,7 @@ class DefaultCookiePolicy(CookiePolicy):
"""
# Path has already been checked by .path_return_ok(), and domain
# blocking done by .domain_return_ok().
- debug(" - checking cookie %s=%s", cookie.name, cookie.value)
+ _debug(" - checking cookie %s=%s", cookie.name, cookie.value)
for n in "version", "verifiability", "secure", "expires", "port", "domain":
fn_name = "return_ok_"+n
@@ -1060,34 +1072,34 @@ class DefaultCookiePolicy(CookiePolicy):
def return_ok_version(self, cookie, request):
if cookie.version > 0 and not self.rfc2965:
- debug(" RFC 2965 cookies are switched off")
+ _debug(" RFC 2965 cookies are switched off")
return False
elif cookie.version == 0 and not self.netscape:
- debug(" Netscape cookies are switched off")
+ _debug(" Netscape cookies are switched off")
return False
return True
def return_ok_verifiability(self, cookie, request):
if request.is_unverifiable() and is_third_party(request):
if cookie.version > 0 and self.strict_rfc2965_unverifiable:
- debug(" third-party RFC 2965 cookie during unverifiable "
- "transaction")
+ _debug(" third-party RFC 2965 cookie during unverifiable "
+ "transaction")
return False
elif cookie.version == 0 and self.strict_ns_unverifiable:
- debug(" third-party Netscape cookie during unverifiable "
- "transaction")
+ _debug(" third-party Netscape cookie during unverifiable "
+ "transaction")
return False
return True
def return_ok_secure(self, cookie, request):
if cookie.secure and request.get_type() != "https":
- debug(" secure cookie with non-secure request")
+ _debug(" secure cookie with non-secure request")
return False
return True
def return_ok_expires(self, cookie, request):
if cookie.is_expired(self._now):
- debug(" cookie expired")
+ _debug(" cookie expired")
return False
return True
@@ -1100,8 +1112,8 @@ class DefaultCookiePolicy(CookiePolicy):
if p == req_port:
break
else:
- debug(" request port %s does not match cookie port %s",
- req_port, cookie.port)
+ _debug(" request port %s does not match cookie port %s",
+ req_port, cookie.port)
return False
return True
@@ -1113,17 +1125,17 @@ class DefaultCookiePolicy(CookiePolicy):
if (cookie.version == 0 and
(self.strict_ns_domain & self.DomainStrictNonDomain) and
not cookie.domain_specified and domain != erhn):
- debug(" cookie with unspecified domain does not string-compare "
- "equal to request domain")
+ _debug(" cookie with unspecified domain does not string-compare "
+ "equal to request domain")
return False
if cookie.version > 0 and not domain_match(erhn, domain):
- debug(" effective request-host name %s does not domain-match "
- "RFC 2965 cookie domain %s", erhn, domain)
+ _debug(" effective request-host name %s does not domain-match "
+ "RFC 2965 cookie domain %s", erhn, domain)
return False
if cookie.version == 0 and not ("."+erhn).endswith(domain):
- debug(" request-host %s does not match Netscape cookie domain "
- "%s", req_host, domain)
+ _debug(" request-host %s does not match Netscape cookie domain "
+ "%s", req_host, domain)
return False
return True
@@ -1136,24 +1148,24 @@ class DefaultCookiePolicy(CookiePolicy):
if not erhn.startswith("."):
erhn = "."+erhn
if not (req_host.endswith(domain) or erhn.endswith(domain)):
- #debug(" request domain %s does not match cookie domain %s",
- # req_host, domain)
+ #_debug(" request domain %s does not match cookie domain %s",
+ # req_host, domain)
return False
if self.is_blocked(domain):
- debug(" domain %s is in user block-list", domain)
+ _debug(" domain %s is in user block-list", domain)
return False
if self.is_not_allowed(domain):
- debug(" domain %s is not in user allow-list", domain)
+ _debug(" domain %s is not in user allow-list", domain)
return False
return True
def path_return_ok(self, path, request):
- debug("- checking cookie path=%s", path)
+ _debug("- checking cookie path=%s", path)
req_path = request_path(request)
if not req_path.startswith(path):
- debug(" %s does not path-match %s", req_path, path)
+ _debug(" %s does not path-match %s", req_path, path)
return False
return True
@@ -1215,7 +1227,7 @@ class CookieJar:
cookies = []
if not self._policy.domain_return_ok(domain, request):
return []
- debug("Checking %s for cookies to return", domain)
+ _debug("Checking %s for cookies to return", domain)
cookies_by_path = self._cookies[domain]
for path in cookies_by_path.keys():
if not self._policy.path_return_ok(path, request):
@@ -1223,9 +1235,9 @@ class CookieJar:
cookies_by_name = cookies_by_path[path]
for cookie in cookies_by_name.values():
if not self._policy.return_ok(cookie, request):
- debug(" not returning cookie")
+ _debug(" not returning cookie")
continue
- debug(" it's a match")
+ _debug(" it's a match")
cookies.append(cookie)
return cookies
@@ -1302,7 +1314,7 @@ class CookieJar:
The Cookie2 header is also added unless policy.hide_cookie2 is true.
"""
- debug("add_cookie_header")
+ _debug("add_cookie_header")
self._cookies_lock.acquire()
self._policy._now = self._now = int(time.time())
@@ -1379,7 +1391,7 @@ class CookieJar:
continue
if k == "domain":
if v is None:
- debug(" missing value for domain attribute")
+ _debug(" missing value for domain attribute")
bad_cookie = True
break
# RFC 2965 section 3.3.3
@@ -1389,7 +1401,7 @@ class CookieJar:
# Prefer max-age to expires (like Mozilla)
continue
if v is None:
- debug(" missing or invalid value for expires "
+ _debug(" missing or invalid value for expires "
"attribute: treating as session cookie")
continue
if k == "max-age":
@@ -1397,7 +1409,7 @@ class CookieJar:
try:
v = int(v)
except ValueError:
- debug(" missing or invalid (non-numeric) value for "
+ _debug(" missing or invalid (non-numeric) value for "
"max-age attribute")
bad_cookie = True
break
@@ -1410,7 +1422,7 @@ class CookieJar:
if (k in value_attrs) or (k in boolean_attrs):
if (v is None and
k not in ("port", "comment", "commenturl")):
- debug(" missing value for %s attribute" % k)
+ _debug(" missing value for %s attribute" % k)
bad_cookie = True
break
standard[k] = v
@@ -1496,8 +1508,8 @@ class CookieJar:
self.clear(domain, path, name)
except KeyError:
pass
- debug("Expiring cookie, domain='%s', path='%s', name='%s'",
- domain, path, name)
+ _debug("Expiring cookie, domain='%s', path='%s', name='%s'",
+ domain, path, name)
return None
return Cookie(version,
@@ -1552,8 +1564,8 @@ class CookieJar:
try:
cookies = self._cookies_from_attrs_set(
split_header_words(rfc2965_hdrs), request)
- except:
- reraise_unmasked_exceptions()
+ except Exception:
+ _warn_unhandled_exception()
cookies = []
if ns_hdrs and netscape:
@@ -1561,8 +1573,8 @@ class CookieJar:
# RFC 2109 and Netscape cookies
ns_cookies = self._cookies_from_attrs_set(
parse_ns_headers(ns_hdrs), request)
- except:
- reraise_unmasked_exceptions()
+ except Exception:
+ _warn_unhandled_exception()
ns_cookies = []
self._process_rfc2109_cookies(ns_cookies)
@@ -1612,13 +1624,13 @@ class CookieJar:
def extract_cookies(self, response, request):
"""Extract cookies from response, where allowable given the request."""
- debug("extract_cookies: %s", response.info())
+ _debug("extract_cookies: %s", response.info())
self._cookies_lock.acquire()
self._policy._now = self._now = int(time.time())
for cookie in self.make_cookies(response, request):
if self._policy.set_ok(cookie, request):
- debug(" setting cookie: %s", cookie)
+ _debug(" setting cookie: %s", cookie)
self.set_cookie(cookie)
self._cookies_lock.release()