%PDF- %PDF-
| Direktori : /lib/python3/dist-packages/mechanize/ |
| Current File : //lib/python3/dist-packages/mechanize/_clientcookie.py |
from __future__ import absolute_import
import re
import time
from .polyglot import (
Cookie as _Cookie, CookieJar as CJ, MozillaCookieJar as MCJ, request_host
as request_host_lc, DEFAULT_HTTP_PORT, CookiePolicy, DefaultCookiePolicy,
FileCookieJar, LoadError, LWPCookieJar, _debug, domain_match,
eff_request_host, escape_path, is_HDN, lwp_cookie_str, reach, request_path,
request_port, user_domain_match, iteritems)
__all__ = [
'DEFAULT_HTTP_PORT', 'CookiePolicy', 'DefaultCookiePolicy',
'request_host_lc', 'MozillaCookieJar', 'escape_path', 'is_HDN',
'request_port', 'LWPCookieJar', 'LoadError', 'reach', 'FileCookieJar',
'lwp_cookie_str', 'domain_match', 'request_path', 'user_domain_match'
]
def effective_request_host(request):
"""Return the effective request-host, as defined by RFC 2965."""
return eff_request_host(request)[1]
def request_is_unverifiable(request):
try:
return request.is_unverifiable()
except AttributeError:
if hasattr(request, "unverifiable"):
return request.unverifiable
else:
raise
def cookies_equal(a, b):
return all(getattr(a, x) == getattr(b, x) for x in Cookie._attrs)
class Cookie(_Cookie):
_attrs = ("version", "name", "value", "port", "port_specified", "domain",
"domain_specified", "domain_initial_dot", "path",
"path_specified", "secure", "expires", "discard", "comment",
"comment_url", "rfc2109", "_rest")
def __eq__(self, other):
return all(getattr(self, a) == getattr(other, a) for a in self._attrs)
def __ne__(self, other):
return not (self == other)
class CookieJar(CJ):
def __getstate__(self):
ans = self.__dict__.copy()
del ans['_cookies_lock']
return ans
def __setstate__(self, val):
for k, v in iteritems(val):
setattr(self, k, v)
def cookies_for_request(self, request):
"""Return a list of cookies to be returned to server.
The returned list of cookie instances is sorted in the order they
should appear in the Cookie: header for return to the server.
See add_cookie_header.__doc__ for the interface required of the
request argument.
"""
with self._cookies_lock:
self._policy._now = self._now = int(time.time())
cookies = self._cookies_for_request(request)
# add cookies in order of most specific (i.e. longest) path first
def key(x):
return len(x.path)
cookies.sort(key=key, reverse=True)
return cookies
def get_policy(self):
return self._policy
def _normalized_cookie_tuples(self, attrs_set):
"""Return list of tuples containing normalised cookie information.
attrs_set is the list of lists of key,value pairs extracted from
the Set-Cookie or Set-Cookie2 headers.
Tuples are name, value, standard, rest, where name and value are the
cookie name and value, standard is a dictionary containing the standard
cookie-attributes (discard, secure, version, expires or max-age,
domain, path and port) and rest is a dictionary containing the rest of
the cookie-attributes.
"""
cookie_tuples = []
boolean_attrs = "discard", "secure"
value_attrs = ("version", "expires", "max-age", "domain", "path",
"port", "comment", "commenturl")
for cookie_attrs in attrs_set:
name, value = cookie_attrs[0]
# Build dictionary of standard cookie-attributes (standard) and
# dictionary of other cookie-attributes (rest).
# Note: expiry time is normalised to seconds since epoch. V0
# cookies should have the Expires cookie-attribute, and V1 cookies
# should have Max-Age, but since V1 includes RFC 2109 cookies (and
# since V0 cookies may be a mish-mash of Netscape and RFC 2109), we
# accept either (but prefer Max-Age).
max_age_set = False
bad_cookie = False
standard = {}
rest = {}
for k, v in cookie_attrs[1:]:
lc = k.lower()
# don't lose case distinction for unknown fields
if lc in value_attrs or lc in boolean_attrs:
k = lc
if k in boolean_attrs and v is None:
# boolean cookie-attribute is present, but has no value
# (like "discard", rather than "port=80")
v = True
if k in standard:
# only first value is significant
continue
if k == "domain":
if v is None:
_debug(" missing value for domain attribute")
bad_cookie = True
break
# RFC 2965 section 3.3.3
v = v.lower()
if k == "expires":
if max_age_set:
# Prefer max-age to expires (like Mozilla)
continue
if v is None:
_debug(" missing or invalid value for expires "
"attribute: treating as session cookie")
continue
if k == "max-age":
max_age_set = True
try:
v = int(v)
except ValueError:
_debug(" missing or invalid (non-numeric) value for "
"max-age attribute")
bad_cookie = True
break
# convert RFC 2965 Max-Age to seconds since epoch
# XXX Strictly you're supposed to follow RFC 2616
# age-calculation rules. Remember that zero Max-Age
# is a request to discard (old and new) cookie, though.
k = "expires"
v = self._now + v
if not v and k == 'path':
# Added by Kovid, not in stdlib implementation
v = '/'
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)
bad_cookie = True
break
standard[k] = v
else:
rest[k] = v
if bad_cookie:
continue
cookie_tuples.append((name, value, standard, rest))
return cookie_tuples
def __getitem__(self, i):
for q, ans in enumerate(self):
if q == i:
return ans
raise IndexError()
try:
from http.cookiejar import NETSCAPE_MAGIC_RGX, NETSCAPE_HEADER_TEXT
except ImportError: # python < 3.10
NETSCAPE_MAGIC_RGX = MCJ.magic_re
NETSCAPE_HEADER_TEXT = MCJ.header
else:
MCJ.header = NETSCAPE_HEADER_TEXT # needed for tests
class MozillaCookieJar(MCJ):
def _really_load(self, f, filename, ignore_discard, ignore_expires):
now = time.time()
magic = f.readline()
if not re.search(NETSCAPE_MAGIC_RGX, magic):
f.close()
raise LoadError(
"%r does not look like a Netscape format cookies file" %
filename)
try:
while 1:
line = f.readline()
if line == "":
break
# last field may be absent, so keep any trailing tab
if line.endswith("\n"):
line = line[:-1]
# skip comments and blank lines XXX what is $ for?
if (line.strip().startswith(("#", "$")) or line.strip() == ""):
continue
(domain, domain_specified, path, secure, expires, name,
value) = line.split("\t", 6) # Changed by Kovid
secure = (secure == "TRUE")
domain_specified = (domain_specified == "TRUE")
if name == "":
# cookies.txt regards 'Set-Cookie: foo' as a cookie
# with no name, whereas cookielib regards it as a
# cookie with no value.
name = value
value = None
initial_dot = domain.startswith(".")
if domain_specified != initial_dot:
raise ValueError()
assert domain_specified == initial_dot
discard = False
if expires == "":
expires = None
discard = True
# assume path_specified is false
c = Cookie(0, name, value, None, False, domain,
domain_specified, initial_dot, path, False, secure,
expires, discard, None, None, {})
if not ignore_discard and c.discard:
continue
if not ignore_expires and c.is_expired(now):
continue
self.set_cookie(c)
except IOError:
raise
except Exception:
raise LoadError("invalid Netscape format cookies file %r: %r" %
(filename, line))