diff options
Diffstat (limited to 'Lib/cookielib.py')
-rw-r--r-- | Lib/cookielib.py | 176 |
1 files changed, 94 insertions, 82 deletions
diff --git a/Lib/cookielib.py b/Lib/cookielib.py index f0a89a555c..e8fee0ee6b 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() |