/home/fresvfqn/waterdamagerestorationandrepairsmithtown.com/Compressed/http.tar
cookiejar.py000064400000226043150532417300007073 0ustar00r"""HTTP cookie handling for web clients.

This module has (now fairly distant) origins in Gisle Aas' Perl module
HTTP::Cookies, from the libwww-perl library.

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 BSDDBCookieJar and the MSIE* classes are not
distributed with the Python standard library, but are available from
http://wwwsearch.sf.net/):

                        CookieJar____
                        /     \      \
            FileCookieJar      \      \
             /    |   \         \      \
 MozillaCookieJar | LWPCookieJar \      \
                  |               |      \
                  |   ---MSIEBase |       \
                  |  /      |     |        \
                  | /   MSIEDBCookieJar BSDDBCookieJar
                  |/
               MSIECookieJar

"""

__all__ = ['Cookie', 'CookieJar', 'CookiePolicy', 'DefaultCookiePolicy',
           'FileCookieJar', 'LWPCookieJar', 'LoadError', 'MozillaCookieJar']

import os
import copy
import datetime
import re
import time
import urllib.parse, urllib.request
import threading as _threading
import http.client  # only for the default HTTP port
from calendar import timegm

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("http.cookiejar")
    return logger.debug(*args)


DEFAULT_HTTP_PORT = str(http.client.HTTP_PORT)
MISSING_FILENAME_TEXT = ("a filename was not supplied (nor was the CookieJar "
                         "instance initialised with one)")

def _warn_unhandled_exception():
    # There are a few catch-all except: statements in this module, for
    # catching input that's bad in unexpected ways.  Warn if any
    # exceptions are caught there.
    import io, warnings, traceback
    f = io.StringIO()
    traceback.print_exc(None, f)
    msg = f.getvalue()
    warnings.warn("http.cookiejar bug!\n%s" % msg, stacklevel=2)


# Date/time conversion
# -----------------------------------------------------------------------------

EPOCH_YEAR = 1970
def _timegm(tt):
    year, month, mday, hour, min, sec = tt[:6]
    if ((year >= EPOCH_YEAR) and (1 <= month <= 12) and (1 <= mday <= 31) and
        (0 <= hour <= 24) and (0 <= min <= 59) and (0 <= sec <= 61)):
        return timegm(tt)
    else:
        return None

DAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun",
          "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
MONTHS_LOWER = []
for month in MONTHS: MONTHS_LOWER.append(month.lower())

def time2isoz(t=None):
    """Return a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like "YYYY-MM-DD hh:mm:ssZ",
    representing Universal Time (UTC, aka GMT).  An example of this format is:

    1994-11-24 08:49:37Z

    """
    if t is None:
        dt = datetime.datetime.utcnow()
    else:
        dt = datetime.datetime.utcfromtimestamp(t)
    return "%04d-%02d-%02d %02d:%02d:%02dZ" % (
        dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)

def time2netscape(t=None):
    """Return a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like this:

    Wed, DD-Mon-YYYY HH:MM:SS GMT

    """
    if t is None:
        dt = datetime.datetime.utcnow()
    else:
        dt = datetime.datetime.utcfromtimestamp(t)
    return "%s, %02d-%s-%04d %02d:%02d:%02d GMT" % (
        DAYS[dt.weekday()], dt.day, MONTHS[dt.month-1],
        dt.year, dt.hour, dt.minute, dt.second)


UTC_ZONES = {"GMT": None, "UTC": None, "UT": None, "Z": None}

TIMEZONE_RE = re.compile(r"^([-+])?(\d\d?):?(\d\d)?$", re.ASCII)
def offset_from_tz_string(tz):
    offset = None
    if tz in UTC_ZONES:
        offset = 0
    else:
        m = TIMEZONE_RE.search(tz)
        if m:
            offset = 3600 * int(m.group(2))
            if m.group(3):
                offset = offset + 60 * int(m.group(3))
            if m.group(1) == '-':
                offset = -offset
    return offset

def _str2time(day, mon, yr, hr, min, sec, tz):
    yr = int(yr)
    if yr > datetime.MAXYEAR:
        return None

    # translate month name to number
    # month numbers start with 1 (January)
    try:
        mon = MONTHS_LOWER.index(mon.lower())+1
    except ValueError:
        # maybe it's already a number
        try:
            imon = int(mon)
        except ValueError:
            return None
        if 1 <= imon <= 12:
            mon = imon
        else:
            return None

    # make sure clock elements are defined
    if hr is None: hr = 0
    if min is None: min = 0
    if sec is None: sec = 0

    day = int(day)
    hr = int(hr)
    min = int(min)
    sec = int(sec)

    if yr < 1000:
        # find "obvious" year
        cur_yr = time.localtime(time.time())[0]
        m = cur_yr % 100
        tmp = yr
        yr = yr + cur_yr - m
        m = m - tmp
        if abs(m) > 50:
            if m > 0: yr = yr + 100
            else: yr = yr - 100

    # convert UTC time tuple to seconds since epoch (not timezone-adjusted)
    t = _timegm((yr, mon, day, hr, min, sec, tz))

    if t is not None:
        # adjust time using timezone string, to get absolute time since epoch
        if tz is None:
            tz = "UTC"
        tz = tz.upper()
        offset = offset_from_tz_string(tz)
        if offset is None:
            return None
        t = t - offset

    return t

STRICT_DATE_RE = re.compile(
    r"^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) "
    r"(\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$", re.ASCII)
WEEKDAY_RE = re.compile(
    r"^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*", re.I | re.ASCII)
LOOSE_HTTP_DATE_RE = re.compile(
    r"""^
    (\d\d?)            # day
       (?:\s+|[-\/])
    (\w+)              # month
        (?:\s+|[-\/])
    (\d+)              # year
    (?:
          (?:\s+|:)    # separator before clock
       (\d\d?):(\d\d)  # hour:min
       (?::(\d\d))?    # optional seconds
    )?                 # optional clock
       \s*
    (?:
       ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+) # timezone
       \s*
    )?
    (?:
       \(\w+\)         # ASCII representation of timezone in parens.
       \s*
    )?$""", re.X | re.ASCII)
def http2time(text):
    """Returns time in seconds since epoch of time represented by a string.

    Return value is an integer.

    None is returned if the format of str is unrecognized, the time is outside
    the representable range, or the timezone string is not recognized.  If the
    string contains no timezone, UTC is assumed.

    The timezone in the string may be numerical (like "-0800" or "+0100") or a
    string timezone (like "UTC", "GMT", "BST" or "EST").  Currently, only the
    timezone strings equivalent to UTC (zero offset) are known to the function.

    The function loosely parses the following formats:

    Wed, 09 Feb 1994 22:23:32 GMT       -- HTTP format
    Tuesday, 08-Feb-94 14:15:29 GMT     -- old rfc850 HTTP format
    Tuesday, 08-Feb-1994 14:15:29 GMT   -- broken rfc850 HTTP format
    09 Feb 1994 22:23:32 GMT            -- HTTP format (no weekday)
    08-Feb-94 14:15:29 GMT              -- rfc850 format (no weekday)
    08-Feb-1994 14:15:29 GMT            -- broken rfc850 format (no weekday)

    The parser ignores leading and trailing whitespace.  The time may be
    absent.

    If the year is given with only 2 digits, the function will select the
    century that makes the year closest to the current date.

    """
    # fast exit for strictly conforming string
    m = STRICT_DATE_RE.search(text)
    if m:
        g = m.groups()
        mon = MONTHS_LOWER.index(g[1].lower()) + 1
        tt = (int(g[2]), mon, int(g[0]),
              int(g[3]), int(g[4]), float(g[5]))
        return _timegm(tt)

    # No, we need some messy parsing...

    # clean up
    text = text.lstrip()
    text = WEEKDAY_RE.sub("", text, 1)  # Useless weekday

    # tz is time zone specifier string
    day, mon, yr, hr, min, sec, tz = [None]*7

    # loose regexp parse
    m = LOOSE_HTTP_DATE_RE.search(text)
    if m is not None:
        day, mon, yr, hr, min, sec, tz = m.groups()
    else:
        return None  # bad format

    return _str2time(day, mon, yr, hr, min, sec, tz)

ISO_DATE_RE = re.compile(
    r"""^
    (\d{4})              # year
       [-\/]?
    (\d\d?)              # numerical month
       [-\/]?
    (\d\d?)              # day
   (?:
         (?:\s+|[-:Tt])  # separator before clock
      (\d\d?):?(\d\d)    # hour:min
      (?::?(\d\d(?:\.\d*)?))?  # optional seconds (and fractional)
   )?                    # optional clock
      \s*
   (?:
      ([-+]?\d\d?:?(:?\d\d)?
       |Z|z)             # timezone  (Z is "zero meridian", i.e. GMT)
      \s*
   )?$""", re.X | re. ASCII)
def iso2time(text):
    """
    As for http2time, but parses the ISO 8601 formats:

    1994-02-03 14:15:29 -0100    -- ISO 8601 format
    1994-02-03 14:15:29          -- zone is optional
    1994-02-03                   -- only date
    1994-02-03T14:15:29          -- Use T as separator
    19940203T141529Z             -- ISO 8601 compact format
    19940203                     -- only date

    """
    # clean up
    text = text.lstrip()

    # tz is time zone specifier string
    day, mon, yr, hr, min, sec, tz = [None]*7

    # loose regexp parse
    m = ISO_DATE_RE.search(text)
    if m is not None:
        # XXX there's an extra bit of the timezone I'm ignoring here: is
        #   this the right thing to do?
        yr, mon, day, hr, min, sec, tz, _ = m.groups()
    else:
        return None  # bad format

    return _str2time(day, mon, yr, hr, min, sec, tz)


# Header parsing
# -----------------------------------------------------------------------------

def unmatched(match):
    """Return unmatched part of re.Match object."""
    start, end = match.span(0)
    return match.string[:start]+match.string[end:]

HEADER_TOKEN_RE =        re.compile(r"^\s*([^=\s;,]+)")
HEADER_QUOTED_VALUE_RE = re.compile(r"^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"")
HEADER_VALUE_RE =        re.compile(r"^\s*=\s*([^\s;,]*)")
HEADER_ESCAPE_RE = re.compile(r"\\(.)")
def split_header_words(header_values):
    r"""Parse header values into a list of lists containing key,value pairs.

    The function knows how to deal with ",", ";" and "=" as well as quoted
    values after "=".  A list of space separated tokens are parsed as if they
    were separated by ";".

    If the header_values passed as argument contains multiple values, then they
    are treated as if they were a single value separated by comma ",".

    This means that this function is useful for parsing header fields that
    follow this syntax (BNF as from the HTTP/1.1 specification, but we relax
    the requirement for tokens).

      headers           = #header
      header            = (token | parameter) *( [";"] (token | parameter))

      token             = 1*<any CHAR except CTLs or separators>
      separators        = "(" | ")" | "<" | ">" | "@"
                        | "," | ";" | ":" | "\" | <">
                        | "/" | "[" | "]" | "?" | "="
                        | "{" | "}" | SP | HT

      quoted-string     = ( <"> *(qdtext | quoted-pair ) <"> )
      qdtext            = <any TEXT except <">>
      quoted-pair       = "\" CHAR

      parameter         = attribute "=" value
      attribute         = token
      value             = token | quoted-string

    Each header is represented by a list of key/value pairs.  The value for a
    simple token (not part of a parameter) is None.  Syntactically incorrect
    headers will not necessarily be parsed as you would want.

    This is easier to describe with some examples:

    >>> split_header_words(['foo="bar"; port="80,81"; discard, bar=baz'])
    [[('foo', 'bar'), ('port', '80,81'), ('discard', None)], [('bar', 'baz')]]
    >>> split_header_words(['text/html; charset="iso-8859-1"'])
    [[('text/html', None), ('charset', 'iso-8859-1')]]
    >>> split_header_words([r'Basic realm="\"foo\bar\""'])
    [[('Basic', None), ('realm', '"foobar"')]]

    """
    assert not isinstance(header_values, str)
    result = []
    for text in header_values:
        orig_text = text
        pairs = []
        while text:
            m = HEADER_TOKEN_RE.search(text)
            if m:
                text = unmatched(m)
                name = m.group(1)
                m = HEADER_QUOTED_VALUE_RE.search(text)
                if m:  # quoted value
                    text = unmatched(m)
                    value = m.group(1)
                    value = HEADER_ESCAPE_RE.sub(r"\1", value)
                else:
                    m = HEADER_VALUE_RE.search(text)
                    if m:  # unquoted value
                        text = unmatched(m)
                        value = m.group(1)
                        value = value.rstrip()
                    else:
                        # no value, a lone token
                        value = None
                pairs.append((name, value))
            elif text.lstrip().startswith(","):
                # concatenated headers, as per RFC 2616 section 4.2
                text = text.lstrip()[1:]
                if pairs: result.append(pairs)
                pairs = []
            else:
                # skip junk
                non_junk, nr_junk_chars = re.subn(r"^[=\s;]*", "", text)
                assert nr_junk_chars > 0, (
                    "split_header_words bug: '%s', '%s', %s" %
                    (orig_text, text, pairs))
                text = non_junk
        if pairs: result.append(pairs)
    return result

HEADER_JOIN_ESCAPE_RE = re.compile(r"([\"\\])")
def join_header_words(lists):
    """Do the inverse (almost) of the conversion done by split_header_words.

    Takes a list of lists of (key, value) pairs and produces a single header
    value.  Attribute values are quoted if needed.

    >>> join_header_words([[("text/plain", None), ("charset", "iso-8859-1")]])
    'text/plain; charset="iso-8859-1"'
    >>> join_header_words([[("text/plain", None)], [("charset", "iso-8859-1")]])
    'text/plain, charset="iso-8859-1"'

    """
    headers = []
    for pairs in lists:
        attr = []
        for k, v in pairs:
            if v is not None:
                if not re.search(r"^\w+$", v):
                    v = HEADER_JOIN_ESCAPE_RE.sub(r"\\\1", v)  # escape " and \
                    v = '"%s"' % v
                k = "%s=%s" % (k, v)
            attr.append(k)
        if attr: headers.append("; ".join(attr))
    return ", ".join(headers)

def strip_quotes(text):
    if text.startswith('"'):
        text = text[1:]
    if text.endswith('"'):
        text = text[:-1]
    return text

def parse_ns_headers(ns_headers):
    """Ad-hoc parser for Netscape protocol cookie-attributes.

    The old Netscape cookie format for Set-Cookie can for instance contain
    an unquoted "," in the expires field, so we have to use this ad-hoc
    parser instead of split_header_words.

    XXX This may not make the best possible effort to parse all the crap
    that Netscape Cookie headers contain.  Ronald Tschalar's HTTPClient
    parser is probably better, so could do worse than following that if
    this ever gives any trouble.

    Currently, this is also used for parsing RFC 2109 cookies.

    """
    known_attrs = ("expires", "domain", "path", "secure",
                   # RFC 2109 attrs (may turn up in Netscape cookies, too)
                   "version", "port", "max-age")

    result = []
    for ns_header in ns_headers:
        pairs = []
        version_set = False

        # XXX: The following does not strictly adhere to RFCs in that empty
        # names and values are legal (the former will only appear once and will
        # be overwritten if multiple occurrences are present). This is
        # mostly to deal with backwards compatibility.
        for ii, param in enumerate(ns_header.split(';')):
            param = param.strip()

            key, sep, val = param.partition('=')
            key = key.strip()

            if not key:
                if ii == 0:
                    break
                else:
                    continue

            # allow for a distinction between present and empty and missing
            # altogether
            val = val.strip() if sep else None

            if ii != 0:
                lc = key.lower()
                if lc in known_attrs:
                    key = lc

                if key == "version":
                    # This is an RFC 2109 cookie.
                    if val is not None:
                        val = strip_quotes(val)
                    version_set = True
                elif key == "expires":
                    # convert expires date to seconds since epoch
                    if val is not None:
                        val = http2time(strip_quotes(val))  # None if invalid
            pairs.append((key, val))

        if pairs:
            if not version_set:
                pairs.append(("version", "0"))
            result.append(pairs)

    return result


IPV4_RE = re.compile(r"\.\d+$", re.ASCII)
def is_HDN(text):
    """Return True if text is a host domain name."""
    # XXX
    # This may well be wrong.  Which RFC is HDN defined in, if any (for
    #  the purposes of RFC 2965)?
    # For the current implementation, what about IPv6?  Remember to look
    #  at other uses of IPV4_RE also, if change this.
    if IPV4_RE.search(text):
        return False
    if text == "":
        return False
    if text[0] == "." or text[-1] == ".":
        return False
    return True

def domain_match(A, B):
    """Return True if domain A domain-matches domain B, according to RFC 2965.

    A and B may be host domain names or IP addresses.

    RFC 2965, section 1:

    Host names can be specified either as an IP address or a HDN string.
    Sometimes we compare one host name with another.  (Such comparisons SHALL
    be case-insensitive.)  Host A's name domain-matches host B's if

         *  their host name strings string-compare equal; or

         * A is a HDN string and has the form NB, where N is a non-empty
            name string, B has the form .B', and B' is a HDN string.  (So,
            x.y.com domain-matches .Y.com but not Y.com.)

    Note that domain-match is not a commutative operation: a.b.c.com
    domain-matches .c.com, but not the reverse.

    """
    # Note that, if A or B are IP addresses, the only relevant part of the
    # definition of the domain-match algorithm is the direct string-compare.
    A = A.lower()
    B = B.lower()
    if A == B:
        return True
    if not is_HDN(A):
        return False
    i = A.rfind(B)
    if i == -1 or i == 0:
        # A does not have form NB, or N is the empty string
        return False
    if not B.startswith("."):
        return False
    if not is_HDN(B[1:]):
        return False
    return True

def liberal_is_HDN(text):
    """Return True if text is a sort-of-like a host domain name.

    For accepting/blocking domains.

    """
    if IPV4_RE.search(text):
        return False
    return True

def user_domain_match(A, B):
    """For blocking/accepting domains.

    A and B may be host domain names or IP addresses.

    """
    A = A.lower()
    B = B.lower()
    if not (liberal_is_HDN(A) and liberal_is_HDN(B)):
        if A == B:
            # equal IP addresses
            return True
        return False
    initial_dot = B.startswith(".")
    if initial_dot and A.endswith(B):
        return True
    if not initial_dot and A == B:
        return True
    return False

cut_port_re = re.compile(r":\d+$", re.ASCII)
def request_host(request):
    """Return request-host, as defined by RFC 2965.

    Variation from RFC: returned value is lowercased, for convenient
    comparison.

    """
    url = request.get_full_url()
    host = urllib.parse.urlparse(url)[1]
    if host == "":
        host = request.get_header("Host", "")

    # remove port, if present
    host = cut_port_re.sub("", host, 1)
    return host.lower()

def eff_request_host(request):
    """Return a tuple (request-host, effective request-host name).

    As defined by RFC 2965, except both are lowercased.

    """
    erhn = req_host = request_host(request)
    if req_host.find(".") == -1 and not IPV4_RE.search(req_host):
        erhn = req_host + ".local"
    return req_host, erhn

def request_path(request):
    """Path component of request-URI, as defined by RFC 2965."""
    url = request.get_full_url()
    parts = urllib.parse.urlsplit(url)
    path = escape_path(parts.path)
    if not path.startswith("/"):
        # fix bad RFC 2396 absoluteURI
        path = "/" + path
    return path

def request_port(request):
    host = request.host
    i = host.find(':')
    if i >= 0:
        port = host[i+1:]
        try:
            int(port)
        except ValueError:
            _debug("nonnumeric port: '%s'", port)
            return None
    else:
        port = DEFAULT_HTTP_PORT
    return port

# Characters in addition to A-Z, a-z, 0-9, '_', '.', and '-' that don't
# need to be escaped to form a valid HTTP URL (RFCs 2396 and 1738).
HTTP_PATH_SAFE = "%/;:@&=+$,!~*'()"
ESCAPED_CHAR_RE = re.compile(r"%([0-9a-fA-F][0-9a-fA-F])")
def uppercase_escaped_char(match):
    return "%%%s" % match.group(1).upper()
def escape_path(path):
    """Escape any invalid characters in HTTP URL, and uppercase all escapes."""
    # There's no knowing what character encoding was used to create URLs
    # containing %-escapes, but since we have to pick one to escape invalid
    # path characters, we pick UTF-8, as recommended in the HTML 4.0
    # specification:
    # http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.2.1
    # And here, kind of: draft-fielding-uri-rfc2396bis-03
    # (And in draft IRI specification: draft-duerst-iri-05)
    # (And here, for new URI schemes: RFC 2718)
    path = urllib.parse.quote(path, HTTP_PATH_SAFE)
    path = ESCAPED_CHAR_RE.sub(uppercase_escaped_char, path)
    return path

def reach(h):
    """Return reach of host h, as defined by RFC 2965, section 1.

    The reach R of a host name H is defined as follows:

       *  If

          -  H is the host domain name of a host; and,

          -  H has the form A.B; and

          -  A has no embedded (that is, interior) dots; and

          -  B has at least one embedded dot, or B is the string "local".
             then the reach of H is .B.

       *  Otherwise, the reach of H is H.

    >>> reach("www.acme.com")
    '.acme.com'
    >>> reach("acme.com")
    'acme.com'
    >>> reach("acme.local")
    '.local'

    """
    i = h.find(".")
    if i >= 0:
        #a = h[:i]  # this line is only here to show what a is
        b = h[i+1:]
        i = b.find(".")
        if is_HDN(h) and (i >= 0 or b == "local"):
            return "."+b
    return h

def is_third_party(request):
    """

    RFC 2965, section 3.3.6:

        An unverifiable transaction is to a third-party host if its request-
        host U does not domain-match the reach R of the request-host O in the
        origin transaction.

    """
    req_host = request_host(request)
    if not domain_match(req_host, reach(request.origin_req_host)):
        return True
    else:
        return False


class Cookie:
    """HTTP Cookie.

    This class represents both Netscape and RFC 2965 cookies.

    This is deliberately a very simple class.  It just holds attributes.  It's
    possible to construct Cookie instances that don't comply with the cookie
    standards.  CookieJar.make_cookies is the factory function for Cookie
    objects -- it deals with cookie parsing, supplying defaults, and
    normalising to the representation used in this class.  CookiePolicy is
    responsible for checking them to see whether they should be accepted from
    and returned to the server.

    Note that the port may be present in the headers, but unspecified ("Port"
    rather than"Port=80", for example); if this is the case, port is None.

    """

    def __init__(self, version, name, value,
                 port, port_specified,
                 domain, domain_specified, domain_initial_dot,
                 path, path_specified,
                 secure,
                 expires,
                 discard,
                 comment,
                 comment_url,
                 rest,
                 rfc2109=False,
                 ):

        if version is not None: version = int(version)
        if expires is not None: expires = int(float(expires))
        if port is None and port_specified is True:
            raise ValueError("if port is None, port_specified must be false")

        self.version = version
        self.name = name
        self.value = value
        self.port = port
        self.port_specified = port_specified
        # normalise case, as per RFC 2965 section 3.3.3
        self.domain = domain.lower()
        self.domain_specified = domain_specified
        # Sigh.  We need to know whether the domain given in the
        # cookie-attribute had an initial dot, in order to follow RFC 2965
        # (as clarified in draft errata).  Needed for the returned $Domain
        # value.
        self.domain_initial_dot = domain_initial_dot
        self.path = path
        self.path_specified = path_specified
        self.secure = secure
        self.expires = expires
        self.discard = discard
        self.comment = comment
        self.comment_url = comment_url
        self.rfc2109 = rfc2109

        self._rest = copy.copy(rest)

    def has_nonstandard_attr(self, name):
        return name in self._rest
    def get_nonstandard_attr(self, name, default=None):
        return self._rest.get(name, default)
    def set_nonstandard_attr(self, name, value):
        self._rest[name] = value

    def is_expired(self, now=None):
        if now is None: now = time.time()
        if (self.expires is not None) and (self.expires <= now):
            return True
        return False

    def __str__(self):
        if self.port is None: p = ""
        else: p = ":"+self.port
        limit = self.domain + p + self.path
        if self.value is not None:
            namevalue = "%s=%s" % (self.name, self.value)
        else:
            namevalue = self.name
        return "<Cookie %s for %s>" % (namevalue, limit)

    def __repr__(self):
        args = []
        for name in ("version", "name", "value",
                     "port", "port_specified",
                     "domain", "domain_specified", "domain_initial_dot",
                     "path", "path_specified",
                     "secure", "expires", "discard", "comment", "comment_url",
                     ):
            attr = getattr(self, name)
            args.append("%s=%s" % (name, repr(attr)))
        args.append("rest=%s" % repr(self._rest))
        args.append("rfc2109=%s" % repr(self.rfc2109))
        return "%s(%s)" % (self.__class__.__name__, ", ".join(args))


class CookiePolicy:
    """Defines which cookies get accepted from and returned to server.

    May also modify cookies, though this is probably a bad idea.

    The subclass DefaultCookiePolicy defines the standard rules for Netscape
    and RFC 2965 cookies -- override that if you want a customized policy.

    """
    def set_ok(self, cookie, request):
        """Return true if (and only if) cookie should be accepted from server.

        Currently, pre-expired cookies never get this far -- the CookieJar
        class deletes such cookies itself.

        """
        raise NotImplementedError()

    def return_ok(self, cookie, request):
        """Return true if (and only if) cookie should be returned to server."""
        raise NotImplementedError()

    def domain_return_ok(self, domain, request):
        """Return false if cookies should not be returned, given cookie domain.
        """
        return True

    def path_return_ok(self, path, request):
        """Return false if cookies should not be returned, given cookie path.
        """
        return True


class DefaultCookiePolicy(CookiePolicy):
    """Implements the standard rules for accepting and returning cookies."""

    DomainStrictNoDots = 1
    DomainStrictNonDomain = 2
    DomainRFC2965Match = 4

    DomainLiberal = 0
    DomainStrict = DomainStrictNoDots|DomainStrictNonDomain

    def __init__(self,
                 blocked_domains=None, allowed_domains=None,
                 netscape=True, rfc2965=False,
                 rfc2109_as_netscape=None,
                 hide_cookie2=False,
                 strict_domain=False,
                 strict_rfc2965_unverifiable=True,
                 strict_ns_unverifiable=False,
                 strict_ns_domain=DomainLiberal,
                 strict_ns_set_initial_dollar=False,
                 strict_ns_set_path=False,
                 secure_protocols=("https", "wss")
                 ):
        """Constructor arguments should be passed as keyword arguments only."""
        self.netscape = netscape
        self.rfc2965 = rfc2965
        self.rfc2109_as_netscape = rfc2109_as_netscape
        self.hide_cookie2 = hide_cookie2
        self.strict_domain = strict_domain
        self.strict_rfc2965_unverifiable = strict_rfc2965_unverifiable
        self.strict_ns_unverifiable = strict_ns_unverifiable
        self.strict_ns_domain = strict_ns_domain
        self.strict_ns_set_initial_dollar = strict_ns_set_initial_dollar
        self.strict_ns_set_path = strict_ns_set_path
        self.secure_protocols = secure_protocols

        if blocked_domains is not None:
            self._blocked_domains = tuple(blocked_domains)
        else:
            self._blocked_domains = ()

        if allowed_domains is not None:
            allowed_domains = tuple(allowed_domains)
        self._allowed_domains = allowed_domains

    def blocked_domains(self):
        """Return the sequence of blocked domains (as a tuple)."""
        return self._blocked_domains
    def set_blocked_domains(self, blocked_domains):
        """Set the sequence of blocked domains."""
        self._blocked_domains = tuple(blocked_domains)

    def is_blocked(self, domain):
        for blocked_domain in self._blocked_domains:
            if user_domain_match(domain, blocked_domain):
                return True
        return False

    def allowed_domains(self):
        """Return None, or the sequence of allowed domains (as a tuple)."""
        return self._allowed_domains
    def set_allowed_domains(self, allowed_domains):
        """Set the sequence of allowed domains, or None."""
        if allowed_domains is not None:
            allowed_domains = tuple(allowed_domains)
        self._allowed_domains = allowed_domains

    def is_not_allowed(self, domain):
        if self._allowed_domains is None:
            return False
        for allowed_domain in self._allowed_domains:
            if user_domain_match(domain, allowed_domain):
                return False
        return True

    def set_ok(self, cookie, request):
        """
        If you override .set_ok(), be sure to call this method.  If it returns
        false, so should your subclass (assuming your subclass wants to be more
        strict about which cookies to accept).

        """
        _debug(" - checking cookie %s=%s", cookie.name, cookie.value)

        assert cookie.name is not None

        for n in "version", "verifiability", "name", "path", "domain", "port":
            fn_name = "set_ok_"+n
            fn = getattr(self, fn_name)
            if not fn(cookie, request):
                return False

        return True

    def set_ok_version(self, cookie, request):
        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)
            return False
        if cookie.version > 0 and not self.rfc2965:
            _debug("   RFC 2965 cookies are switched off")
            return False
        elif cookie.version == 0 and not self.netscape:
            _debug("   Netscape cookies are switched off")
            return False
        return True

    def set_ok_verifiability(self, cookie, request):
        if request.unverifiable and is_third_party(request):
            if cookie.version > 0 and self.strict_rfc2965_unverifiable:
                _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")
                return False
        return True

    def set_ok_name(self, cookie, request):
        # Try and stop servers setting V0 cookies designed to hack other
        # 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)
            return False
        return True

    def set_ok_path(self, cookie, request):
        if cookie.path_specified:
            req_path = request_path(request)
            if ((cookie.version > 0 or
                 (cookie.version == 0 and self.strict_ns_set_path)) and
                not self.path_return_ok(cookie.path, request)):
                _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)
            return False
        if self.is_not_allowed(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", "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)
                        return False
            if domain.startswith("."):
                undotted_domain = domain[1:]
            else:
                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)
                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 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)
                    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)
                    return False
        return True

    def set_ok_port(self, cookie, request):
        if cookie.port_specified:
            req_port = request_port(request)
            if req_port is None:
                req_port = "80"
            else:
                req_port = str(req_port)
            for p in cookie.port.split(","):
                try:
                    int(p)
                except ValueError:
                    _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)
                return False
        return True

    def return_ok(self, cookie, request):
        """
        If you override .return_ok(), be sure to call this method.  If it
        returns false, so should your subclass (assuming your subclass wants to
        be more strict about which cookies to return).

        """
        # 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)

        for n in "version", "verifiability", "secure", "expires", "port", "domain":
            fn_name = "return_ok_"+n
            fn = getattr(self, fn_name)
            if not fn(cookie, request):
                return False
        return True

    def return_ok_version(self, cookie, request):
        if cookie.version > 0 and not self.rfc2965:
            _debug("   RFC 2965 cookies are switched off")
            return False
        elif cookie.version == 0 and not self.netscape:
            _debug("   Netscape cookies are switched off")
            return False
        return True

    def return_ok_verifiability(self, cookie, request):
        if request.unverifiable and is_third_party(request):
            if cookie.version > 0 and self.strict_rfc2965_unverifiable:
                _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")
                return False
        return True

    def return_ok_secure(self, cookie, request):
        if cookie.secure and request.type not in self.secure_protocols:
            _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")
            return False
        return True

    def return_ok_port(self, cookie, request):
        if cookie.port:
            req_port = request_port(request)
            if req_port is None:
                req_port = "80"
            for p in cookie.port.split(","):
                if p == req_port:
                    break
            else:
                _debug("   request port %s does not match cookie port %s",
                       req_port, cookie.port)
                return False
        return True

    def return_ok_domain(self, cookie, request):
        req_host, erhn = eff_request_host(request)
        domain = cookie.domain

        if domain and not domain.startswith("."):
            dotdomain = "." + domain
        else:
            dotdomain = domain

        # strict check of non-domain cookies: Mozilla does this, MSIE5 doesn't
        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")
            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)
            return False
        if cookie.version == 0 and not ("."+erhn).endswith(dotdomain):
            _debug("   request-host %s does not match Netscape cookie domain "
                   "%s", req_host, domain)
            return False
        return True

    def domain_return_ok(self, domain, request):
        # Liberal check of.  This is here as an optimization to avoid
        # having to load lots of MSIE cookie files unless necessary.
        req_host, erhn = eff_request_host(request)
        if not req_host.startswith("."):
            req_host = "."+req_host
        if not erhn.startswith("."):
            erhn = "."+erhn
        if domain and not domain.startswith("."):
            dotdomain = "." + domain
        else:
            dotdomain = domain
        if not (req_host.endswith(dotdomain) or erhn.endswith(dotdomain)):
            #_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)
            return False
        if self.is_not_allowed(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)
        req_path = request_path(request)
        pathlen = len(path)
        if req_path == path:
            return True
        elif (req_path.startswith(path) and
              (path.endswith("/") or req_path[pathlen:pathlen+1] == "/")):
            return True

        _debug("  %s does not path-match %s", req_path, path)
        return False

def vals_sorted_by_key(adict):
    keys = sorted(adict.keys())
    return map(adict.get, keys)

def deepvalues(mapping):
    """Iterates over nested mapping, depth-first, in sorted order by key."""
    values = vals_sorted_by_key(mapping)
    for obj in values:
        mapping = False
        try:
            obj.items
        except AttributeError:
            pass
        else:
            mapping = True
            yield from deepvalues(obj)
        if not mapping:
            yield obj


# Used as second parameter to dict.get() method, to distinguish absent
# dict key from one with a None value.
class Absent: pass

class CookieJar:
    """Collection of HTTP cookies.

    You may not need to know about this class: try
    urllib.request.build_opener(HTTPCookieProcessor).open(url).
    """

    non_word_re = re.compile(r"\W")
    quote_re = re.compile(r"([\"\\])")
    strict_domain_re = re.compile(r"\.?[^.]*")
    domain_re = re.compile(r"[^.]*")
    dots_re = re.compile(r"^\.+")

    magic_re = re.compile(r"^\#LWP-Cookies-(\d+\.\d+)", re.ASCII)

    def __init__(self, policy=None):
        if policy is None:
            policy = DefaultCookiePolicy()
        self._policy = policy

        self._cookies_lock = _threading.RLock()
        self._cookies = {}

    def set_policy(self, policy):
        self._policy = policy

    def _cookies_for_domain(self, domain, request):
        cookies = []
        if not self._policy.domain_return_ok(domain, request):
            return []
        _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):
                continue
            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")
                    continue
                _debug("   it's a match")
                cookies.append(cookie)
        return cookies

    def _cookies_for_request(self, request):
        """Return a list of cookies to be returned to server."""
        cookies = []
        for domain in self._cookies.keys():
            cookies.extend(self._cookies_for_domain(domain, request))
        return cookies

    def _cookie_attrs(self, cookies):
        """Return a list of cookie-attributes to be returned to server.

        like ['foo="bar"; $Path="/"', ...]

        The $Version attribute is also added when appropriate (currently only
        once per request).

        """
        # add cookies in order of most specific (ie. longest) path first
        cookies.sort(key=lambda a: len(a.path), reverse=True)

        version_set = False

        attrs = []
        for cookie in cookies:
            # set version of Cookie header
            # XXX
            # What should it be if multiple matching Set-Cookie headers have
            #  different versions themselves?
            # Answer: there is no answer; was supposed to be settled by
            #  RFC 2965 errata, but that may never appear...
            version = cookie.version
            if not version_set:
                version_set = True
                if version > 0:
                    attrs.append("$Version=%s" % version)

            # quote cookie value if necessary
            # (not for Netscape protocol, which already has any quotes
            #  intact, due to the poorly-specified Netscape Cookie: syntax)
            if ((cookie.value is not None) and
                self.non_word_re.search(cookie.value) and version > 0):
                value = self.quote_re.sub(r"\\\1", cookie.value)
            else:
                value = cookie.value

            # add cookie-attributes to be returned in Cookie header
            if cookie.value is None:
                attrs.append(cookie.name)
            else:
                attrs.append("%s=%s" % (cookie.name, value))
            if version > 0:
                if cookie.path_specified:
                    attrs.append('$Path="%s"' % cookie.path)
                if cookie.domain.startswith("."):
                    domain = cookie.domain
                    if (not cookie.domain_initial_dot and
                        domain.startswith(".")):
                        domain = domain[1:]
                    attrs.append('$Domain="%s"' % domain)
                if cookie.port is not None:
                    p = "$Port"
                    if cookie.port_specified:
                        p = p + ('="%s"' % cookie.port)
                    attrs.append(p)

        return attrs

    def add_cookie_header(self, request):
        """Add correct Cookie: header to request (urllib.request.Request object).

        The Cookie2 header is also added unless policy.hide_cookie2 is true.

        """
        _debug("add_cookie_header")
        self._cookies_lock.acquire()
        try:

            self._policy._now = self._now = int(time.time())

            cookies = self._cookies_for_request(request)

            attrs = self._cookie_attrs(cookies)
            if attrs:
                if not request.has_header("Cookie"):
                    request.add_unredirected_header(
                        "Cookie", "; ".join(attrs))

            # if necessary, advertise that we know RFC 2965
            if (self._policy.rfc2965 and not self._policy.hide_cookie2 and
                not request.has_header("Cookie2")):
                for cookie in cookies:
                    if cookie.version != 1:
                        request.add_unredirected_header("Cookie2", '$Version="1"')
                        break

        finally:
            self._cookies_lock.release()

        self.clear_expired_cookies()

    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 (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 _cookie_from_cookie_tuple(self, tup, request):
        # standard is dict of standard cookie-attributes, rest is dict of the
        # rest of them
        name, value, standard, rest = tup

        domain = standard.get("domain", Absent)
        path = standard.get("path", Absent)
        port = standard.get("port", Absent)
        expires = standard.get("expires", Absent)

        # set the easy defaults
        version = standard.get("version", None)
        if version is not None:
            try:
                version = int(version)
            except ValueError:
                return None  # invalid version, ignore cookie
        secure = standard.get("secure", False)
        # (discard is also set if expires is Absent)
        discard = standard.get("discard", False)
        comment = standard.get("comment", None)
        comment_url = standard.get("commenturl", None)

        # set default path
        if path is not Absent and path != "":
            path_specified = True
            path = escape_path(path)
        else:
            path_specified = False
            path = request_path(request)
            i = path.rfind("/")
            if i != -1:
                if version == 0:
                    # Netscape spec parts company from reality here
                    path = path[:i]
                else:
                    path = path[:i+1]
            if len(path) == 0: path = "/"

        # set default domain
        domain_specified = domain is not Absent
        # but first we have to remember whether it starts with a dot
        domain_initial_dot = False
        if domain_specified:
            domain_initial_dot = bool(domain.startswith("."))
        if domain is Absent:
            req_host, erhn = eff_request_host(request)
            domain = erhn
        elif not domain.startswith("."):
            domain = "."+domain

        # set default port
        port_specified = False
        if port is not Absent:
            if port is None:
                # Port attr present, but has no value: default to request port.
                # Cookie should then only be sent back on that port.
                port = request_port(request)
            else:
                port_specified = True
                port = re.sub(r"\s+", "", port)
        else:
            # No port attr present.  Cookie can be sent back on any port.
            port = None

        # set default expires and discard
        if expires is Absent:
            expires = None
            discard = True
        elif expires <= self._now:
            # Expiry date in past is request to delete cookie.  This can't be
            # in DefaultCookiePolicy, because can't delete cookies there.
            try:
                self.clear(domain, path, name)
            except KeyError:
                pass
            _debug("Expiring cookie, domain='%s', path='%s', name='%s'",
                   domain, path, name)
            return None

        return Cookie(version,
                      name, value,
                      port, port_specified,
                      domain, domain_specified, domain_initial_dot,
                      path, path_specified,
                      secure,
                      expires,
                      discard,
                      comment,
                      comment_url,
                      rest)

    def _cookies_from_attrs_set(self, attrs_set, request):
        cookie_tuples = self._normalized_cookie_tuples(attrs_set)

        cookies = []
        for tup in cookie_tuples:
            cookie = self._cookie_from_cookie_tuple(tup, request)
            if cookie: cookies.append(cookie)
        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):
        """Return sequence of Cookie objects extracted from response object."""
        # get cookie-attributes for RFC 2965 and Netscape protocols
        headers = response.info()
        rfc2965_hdrs = headers.get_all("Set-Cookie2", [])
        ns_hdrs = headers.get_all("Set-Cookie", [])
        self._policy._now = self._now = int(time.time())

        rfc2965 = self._policy.rfc2965
        netscape = self._policy.netscape

        if ((not rfc2965_hdrs and not ns_hdrs) or
            (not ns_hdrs and not rfc2965) or
            (not rfc2965_hdrs and not netscape) or
            (not netscape and not rfc2965)):
            return []  # no relevant cookie headers: quick exit

        try:
            cookies = self._cookies_from_attrs_set(
                split_header_words(rfc2965_hdrs), request)
        except Exception:
            _warn_unhandled_exception()
            cookies = []

        if ns_hdrs and netscape:
            try:
                # RFC 2109 and Netscape cookies
                ns_cookies = self._cookies_from_attrs_set(
                    parse_ns_headers(ns_hdrs), request)
            except Exception:
                _warn_unhandled_exception()
                ns_cookies = []
            self._process_rfc2109_cookies(ns_cookies)

            # Look for Netscape cookies (from Set-Cookie headers) that match
            # corresponding RFC 2965 cookies (from Set-Cookie2 headers).
            # For each match, keep the RFC 2965 cookie and ignore the Netscape
            # cookie (RFC 2965 section 9.1).  Actually, RFC 2109 cookies are
            # bundled in with the Netscape cookies for this purpose, which is
            # reasonable behaviour.
            if rfc2965:
                lookup = {}
                for cookie in cookies:
                    lookup[(cookie.domain, cookie.path, cookie.name)] = None

                def no_matching_rfc2965(ns_cookie, lookup=lookup):
                    key = ns_cookie.domain, ns_cookie.path, ns_cookie.name
                    return key not in lookup
                ns_cookies = filter(no_matching_rfc2965, ns_cookies)

            if ns_cookies:
                cookies.extend(ns_cookies)

        return cookies

    def set_cookie_if_ok(self, cookie, request):
        """Set a cookie if policy says it's OK to do so."""
        self._cookies_lock.acquire()
        try:
            self._policy._now = self._now = int(time.time())

            if self._policy.set_ok(cookie, request):
                self.set_cookie(cookie)


        finally:
            self._cookies_lock.release()

    def set_cookie(self, cookie):
        """Set a cookie, without checking whether or not it should be set."""
        c = self._cookies
        self._cookies_lock.acquire()
        try:
            if cookie.domain not in c: c[cookie.domain] = {}
            c2 = c[cookie.domain]
            if cookie.path not in c2: c2[cookie.path] = {}
            c3 = c2[cookie.path]
            c3[cookie.name] = cookie
        finally:
            self._cookies_lock.release()

    def extract_cookies(self, response, request):
        """Extract cookies from response, where allowable given the request."""
        _debug("extract_cookies: %s", response.info())
        self._cookies_lock.acquire()
        try:
            for cookie in self.make_cookies(response, request):
                if self._policy.set_ok(cookie, request):
                    _debug(" setting cookie: %s", cookie)
                    self.set_cookie(cookie)
        finally:
            self._cookies_lock.release()

    def clear(self, domain=None, path=None, name=None):
        """Clear some cookies.

        Invoking this method without arguments will clear all cookies.  If
        given a single argument, only cookies belonging to that domain will be
        removed.  If given two arguments, cookies belonging to the specified
        path within that domain are removed.  If given three arguments, then
        the cookie with the specified name, path and domain is removed.

        Raises KeyError if no matching cookie exists.

        """
        if name is not None:
            if (domain is None) or (path is None):
                raise ValueError(
                    "domain and path must be given to remove a cookie by name")
            del self._cookies[domain][path][name]
        elif path is not None:
            if domain is None:
                raise ValueError(
                    "domain must be given to remove cookies by path")
            del self._cookies[domain][path]
        elif domain is not None:
            del self._cookies[domain]
        else:
            self._cookies = {}

    def clear_session_cookies(self):
        """Discard all session cookies.

        Note that the .save() method won't save session cookies anyway, unless
        you ask otherwise by passing a true ignore_discard argument.

        """
        self._cookies_lock.acquire()
        try:
            for cookie in self:
                if cookie.discard:
                    self.clear(cookie.domain, cookie.path, cookie.name)
        finally:
            self._cookies_lock.release()

    def clear_expired_cookies(self):
        """Discard all expired cookies.

        You probably don't need to call this method: expired cookies are never
        sent back to the server (provided you're using DefaultCookiePolicy),
        this method is called by CookieJar itself every so often, and the
        .save() method won't save expired cookies anyway (unless you ask
        otherwise by passing a true ignore_expires argument).

        """
        self._cookies_lock.acquire()
        try:
            now = time.time()
            for cookie in self:
                if cookie.is_expired(now):
                    self.clear(cookie.domain, cookie.path, cookie.name)
        finally:
            self._cookies_lock.release()

    def __iter__(self):
        return deepvalues(self._cookies)

    def __len__(self):
        """Return number of contained cookies."""
        i = 0
        for cookie in self: i = i + 1
        return i

    def __repr__(self):
        r = []
        for cookie in self: r.append(repr(cookie))
        return "<%s[%s]>" % (self.__class__.__name__, ", ".join(r))

    def __str__(self):
        r = []
        for cookie in self: r.append(str(cookie))
        return "<%s[%s]>" % (self.__class__.__name__, ", ".join(r))


# derives from OSError for backwards-compatibility with Python 2.4.0
class LoadError(OSError): pass

class FileCookieJar(CookieJar):
    """CookieJar that can be loaded from and saved to a file."""

    def __init__(self, filename=None, delayload=False, policy=None):
        """
        Cookies are NOT loaded from the named file until either the .load() or
        .revert() method is called.

        """
        CookieJar.__init__(self, policy)
        if filename is not None:
            filename = os.fspath(filename)
        self.filename = filename
        self.delayload = bool(delayload)

    def save(self, filename=None, ignore_discard=False, ignore_expires=False):
        """Save cookies to a file."""
        raise NotImplementedError()

    def load(self, filename=None, ignore_discard=False, ignore_expires=False):
        """Load cookies from a file."""
        if filename is None:
            if self.filename is not None: filename = self.filename
            else: raise ValueError(MISSING_FILENAME_TEXT)

        with open(filename) as f:
            self._really_load(f, filename, ignore_discard, ignore_expires)

    def revert(self, filename=None,
               ignore_discard=False, ignore_expires=False):
        """Clear all cookies and reload cookies from a saved file.

        Raises LoadError (or OSError) if reversion is not successful; the
        object's state will not be altered if this happens.

        """
        if filename is None:
            if self.filename is not None: filename = self.filename
            else: raise ValueError(MISSING_FILENAME_TEXT)

        self._cookies_lock.acquire()
        try:

            old_state = copy.deepcopy(self._cookies)
            self._cookies = {}
            try:
                self.load(filename, ignore_discard, ignore_expires)
            except OSError:
                self._cookies = old_state
                raise

        finally:
            self._cookies_lock.release()


def lwp_cookie_str(cookie):
    """Return string representation of Cookie in the LWP cookie file format.

    Actually, the format is extended a bit -- see module docstring.

    """
    h = [(cookie.name, cookie.value),
         ("path", cookie.path),
         ("domain", cookie.domain)]
    if cookie.port is not None: h.append(("port", cookie.port))
    if cookie.path_specified: h.append(("path_spec", None))
    if cookie.port_specified: h.append(("port_spec", None))
    if cookie.domain_initial_dot: h.append(("domain_dot", None))
    if cookie.secure: h.append(("secure", None))
    if cookie.expires: h.append(("expires",
                               time2isoz(float(cookie.expires))))
    if cookie.discard: h.append(("discard", None))
    if cookie.comment: h.append(("comment", cookie.comment))
    if cookie.comment_url: h.append(("commenturl", cookie.comment_url))

    keys = sorted(cookie._rest.keys())
    for k in keys:
        h.append((k, str(cookie._rest[k])))

    h.append(("version", str(cookie.version)))

    return join_header_words([h])

class LWPCookieJar(FileCookieJar):
    """
    The LWPCookieJar saves a sequence of "Set-Cookie3" lines.
    "Set-Cookie3" is the format used by the libwww-perl library, not known
    to be compatible with any browser, but which is easy to read and
    doesn't lose information about RFC 2965 cookies.

    Additional methods

    as_lwp_str(ignore_discard=True, ignore_expired=True)

    """

    def as_lwp_str(self, ignore_discard=True, ignore_expires=True):
        """Return cookies as a string of "\\n"-separated "Set-Cookie3" headers.

        ignore_discard and ignore_expires: see docstring for FileCookieJar.save

        """
        now = time.time()
        r = []
        for cookie in self:
            if not ignore_discard and cookie.discard:
                continue
            if not ignore_expires and cookie.is_expired(now):
                continue
            r.append("Set-Cookie3: %s" % lwp_cookie_str(cookie))
        return "\n".join(r+[""])

    def save(self, filename=None, ignore_discard=False, ignore_expires=False):
        if filename is None:
            if self.filename is not None: filename = self.filename
            else: raise ValueError(MISSING_FILENAME_TEXT)

        with open(filename, "w") as f:
            # There really isn't an LWP Cookies 2.0 format, but this indicates
            # that there is extra information in here (domain_dot and
            # port_spec) while still being compatible with libwww-perl, I hope.
            f.write("#LWP-Cookies-2.0\n")
            f.write(self.as_lwp_str(ignore_discard, ignore_expires))

    def _really_load(self, f, filename, ignore_discard, ignore_expires):
        magic = f.readline()
        if not self.magic_re.search(magic):
            msg = ("%r does not look like a Set-Cookie3 (LWP) format "
                   "file" % filename)
            raise LoadError(msg)

        now = time.time()

        header = "Set-Cookie3:"
        boolean_attrs = ("port_spec", "path_spec", "domain_dot",
                         "secure", "discard")
        value_attrs = ("version",
                       "port", "path", "domain",
                       "expires",
                       "comment", "commenturl")

        try:
            while 1:
                line = f.readline()
                if line == "": break
                if not line.startswith(header):
                    continue
                line = line[len(header):].strip()

                for data in split_header_words([line]):
                    name, value = data[0]
                    standard = {}
                    rest = {}
                    for k in boolean_attrs:
                        standard[k] = False
                    for k, v in data[1:]:
                        if k is not None:
                            lc = k.lower()
                        else:
                            lc = None
                        # 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:
                            if v is None: v = True
                            standard[k] = v
                        elif k in value_attrs:
                            standard[k] = v
                        else:
                            rest[k] = v

                    h = standard.get
                    expires = h("expires")
                    discard = h("discard")
                    if expires is not None:
                        expires = iso2time(expires)
                    if expires is None:
                        discard = True
                    domain = h("domain")
                    domain_specified = domain.startswith(".")
                    c = Cookie(h("version"), name, value,
                               h("port"), h("port_spec"),
                               domain, domain_specified, h("domain_dot"),
                               h("path"), h("path_spec"),
                               h("secure"),
                               expires,
                               discard,
                               h("comment"),
                               h("commenturl"),
                               rest)
                    if not ignore_discard and c.discard:
                        continue
                    if not ignore_expires and c.is_expired(now):
                        continue
                    self.set_cookie(c)
        except OSError:
            raise
        except Exception:
            _warn_unhandled_exception()
            raise LoadError("invalid Set-Cookie3 format file %r: %r" %
                            (filename, line))


class MozillaCookieJar(FileCookieJar):
    """

    WARNING: you may want to backup your browser's cookies file if you use
    this class to save cookies.  I *think* it works, but there have been
    bugs in the past!

    This class differs from CookieJar only in the format it uses to save and
    load cookies to and from a file.  This class uses the Mozilla/Netscape
    `cookies.txt' format.  lynx uses this file format, too.

    Don't expect cookies saved while the browser is running to be noticed by
    the browser (in fact, Mozilla on unix will overwrite your saved cookies if
    you change them on disk while it's running; on Windows, you probably can't
    save at all while the browser is running).

    Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
    Netscape cookies on saving.

    In particular, the cookie version and port number information is lost,
    together with information about whether or not Path, Port and Discard were
    specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
    domain as set in the HTTP header started with a dot (yes, I'm aware some
    domains in Netscape files start with a dot and some don't -- trust me, you
    really don't want to know any more about this).

    Note that though Mozilla and Netscape use the same format, they use
    slightly different headers.  The class saves cookies using the Netscape
    header by default (Mozilla can cope with that).

    """
    magic_re = re.compile("#( Netscape)? HTTP Cookie File")
    header = """\
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

"""

    def _really_load(self, f, filename, ignore_discard, ignore_expires):
        now = time.time()

        magic = f.readline()
        if not self.magic_re.search(magic):
            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")
                secure = (secure == "TRUE")
                domain_specified = (domain_specified == "TRUE")
                if name == "":
                    # cookies.txt regards 'Set-Cookie: foo' as a cookie
                    # with no name, whereas http.cookiejar regards it as a
                    # cookie with no value.
                    name = value
                    value = None

                initial_dot = domain.startswith(".")
                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 OSError:
            raise
        except Exception:
            _warn_unhandled_exception()
            raise LoadError("invalid Netscape format cookies file %r: %r" %
                            (filename, line))

    def save(self, filename=None, ignore_discard=False, ignore_expires=False):
        if filename is None:
            if self.filename is not None: filename = self.filename
            else: raise ValueError(MISSING_FILENAME_TEXT)

        with open(filename, "w") as f:
            f.write(self.header)
            now = time.time()
            for cookie in self:
                if not ignore_discard and cookie.discard:
                    continue
                if not ignore_expires and cookie.is_expired(now):
                    continue
                if cookie.secure: secure = "TRUE"
                else: secure = "FALSE"
                if cookie.domain.startswith("."): initial_dot = "TRUE"
                else: initial_dot = "FALSE"
                if cookie.expires is not None:
                    expires = str(cookie.expires)
                else:
                    expires = ""
                if cookie.value is None:
                    # cookies.txt regards 'Set-Cookie: foo' as a cookie
                    # with no name, whereas http.cookiejar regards it as a
                    # cookie with no value.
                    name = ""
                    value = cookie.name
                else:
                    name = cookie.name
                    value = cookie.value
                f.write(
                    "\t".join([cookie.domain, initial_dot, cookie.path,
                               secure, expires, name, value])+
                    "\n")
client.py000064400000154231150532417300006402 0ustar00r"""HTTP/1.1 client library

<intro stuff goes here>
<other stuff, too>

HTTPConnection goes through a number of "states", which define when a client
may legally make another request or fetch the response for a particular
request. This diagram details these state transitions:

    (null)
      |
      | HTTPConnection()
      v
    Idle
      |
      | putrequest()
      v
    Request-started
      |
      | ( putheader() )*  endheaders()
      v
    Request-sent
      |\_____________________________
      |                              | getresponse() raises
      | response = getresponse()     | ConnectionError
      v                              v
    Unread-response                Idle
    [Response-headers-read]
      |\____________________
      |                     |
      | response.read()     | putrequest()
      v                     v
    Idle                  Req-started-unread-response
                     ______/|
                   /        |
   response.read() |        | ( putheader() )*  endheaders()
                   v        v
       Request-started    Req-sent-unread-response
                            |
                            | response.read()
                            v
                          Request-sent

This diagram presents the following rules:
  -- a second request may not be started until {response-headers-read}
  -- a response [object] cannot be retrieved until {request-sent}
  -- there is no differentiation between an unread response body and a
     partially read response body

Note: this enforcement is applied by the HTTPConnection class. The
      HTTPResponse class does not enforce this state machine, which
      implies sophisticated clients may accelerate the request/response
      pipeline. Caution should be taken, though: accelerating the states
      beyond the above pattern may imply knowledge of the server's
      connection-close behavior for certain requests. For example, it
      is impossible to tell whether the server will close the connection
      UNTIL the response headers have been read; this means that further
      requests cannot be placed into the pipeline until it is known that
      the server will NOT be closing the connection.

Logical State                  __state            __response
-------------                  -------            ----------
Idle                           _CS_IDLE           None
Request-started                _CS_REQ_STARTED    None
Request-sent                   _CS_REQ_SENT       None
Unread-response                _CS_IDLE           <response_class>
Req-started-unread-response    _CS_REQ_STARTED    <response_class>
Req-sent-unread-response       _CS_REQ_SENT       <response_class>
"""

import email.parser
import email.message
import http
import io
import re
import socket
import collections.abc
from urllib.parse import urlsplit

# HTTPMessage, parse_headers(), and the HTTP status code constants are
# intentionally omitted for simplicity
__all__ = ["HTTPResponse", "HTTPConnection",
           "HTTPException", "NotConnected", "UnknownProtocol",
           "UnknownTransferEncoding", "UnimplementedFileMode",
           "IncompleteRead", "InvalidURL", "ImproperConnectionState",
           "CannotSendRequest", "CannotSendHeader", "ResponseNotReady",
           "BadStatusLine", "LineTooLong", "RemoteDisconnected", "error",
           "responses"]

HTTP_PORT = 80
HTTPS_PORT = 443

_UNKNOWN = 'UNKNOWN'

# connection states
_CS_IDLE = 'Idle'
_CS_REQ_STARTED = 'Request-started'
_CS_REQ_SENT = 'Request-sent'


# hack to maintain backwards compatibility
globals().update(http.HTTPStatus.__members__)

# another hack to maintain backwards compatibility
# Mapping status codes to official W3C names
responses = {v: v.phrase for v in http.HTTPStatus.__members__.values()}

# maximal line length when calling readline().
_MAXLINE = 65536
_MAXHEADERS = 100

# Header name/value ABNF (http://tools.ietf.org/html/rfc7230#section-3.2)
#
# VCHAR          = %x21-7E
# obs-text       = %x80-FF
# header-field   = field-name ":" OWS field-value OWS
# field-name     = token
# field-value    = *( field-content / obs-fold )
# field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
# field-vchar    = VCHAR / obs-text
#
# obs-fold       = CRLF 1*( SP / HTAB )
#                ; obsolete line folding
#                ; see Section 3.2.4

# token          = 1*tchar
#
# tchar          = "!" / "#" / "$" / "%" / "&" / "'" / "*"
#                / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
#                / DIGIT / ALPHA
#                ; any VCHAR, except delimiters
#
# VCHAR defined in http://tools.ietf.org/html/rfc5234#appendix-B.1

# the patterns for both name and value are more lenient than RFC
# definitions to allow for backwards compatibility
_is_legal_header_name = re.compile(rb'[^:\s][^:\r\n]*').fullmatch
_is_illegal_header_value = re.compile(rb'\n(?![ \t])|\r(?![ \t\n])').search

# These characters are not allowed within HTTP URL paths.
#  See https://tools.ietf.org/html/rfc3986#section-3.3 and the
#  https://tools.ietf.org/html/rfc3986#appendix-A pchar definition.
# Prevents CVE-2019-9740.  Includes control characters such as \r\n.
# We don't restrict chars above \x7f as putrequest() limits us to ASCII.
_contains_disallowed_url_pchar_re = re.compile('[\x00-\x20\x7f]')
# Arguably only these _should_ allowed:
#  _is_allowed_url_pchars_re = re.compile(r"^[/!$&'()*+,;=:@%a-zA-Z0-9._~-]+$")
# We are more lenient for assumed real world compatibility purposes.

# These characters are not allowed within HTTP method names
# to prevent http header injection.
_contains_disallowed_method_pchar_re = re.compile('[\x00-\x1f]')

# We always set the Content-Length header for these methods because some
# servers will otherwise respond with a 411
_METHODS_EXPECTING_BODY = {'PATCH', 'POST', 'PUT'}


def _encode(data, name='data'):
    """Call data.encode("latin-1") but show a better error message."""
    try:
        return data.encode("latin-1")
    except UnicodeEncodeError as err:
        raise UnicodeEncodeError(
            err.encoding,
            err.object,
            err.start,
            err.end,
            "%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') "
            "if you want to send it encoded in UTF-8." %
            (name.title(), data[err.start:err.end], name)) from None


class HTTPMessage(email.message.Message):
    # XXX The only usage of this method is in
    # http.server.CGIHTTPRequestHandler.  Maybe move the code there so
    # that it doesn't need to be part of the public API.  The API has
    # never been defined so this could cause backwards compatibility
    # issues.

    def getallmatchingheaders(self, name):
        """Find all header lines matching a given header name.

        Look through the list of headers and find all lines matching a given
        header name (and their continuation lines).  A list of the lines is
        returned, without interpretation.  If the header does not occur, an
        empty list is returned.  If the header occurs multiple times, all
        occurrences are returned.  Case is not important in the header name.

        """
        name = name.lower() + ':'
        n = len(name)
        lst = []
        hit = 0
        for line in self.keys():
            if line[:n].lower() == name:
                hit = 1
            elif not line[:1].isspace():
                hit = 0
            if hit:
                lst.append(line)
        return lst

def _read_headers(fp):
    """Reads potential header lines into a list from a file pointer.

    Length of line is limited by _MAXLINE, and number of
    headers is limited by _MAXHEADERS.
    """
    headers = []
    while True:
        line = fp.readline(_MAXLINE + 1)
        if len(line) > _MAXLINE:
            raise LineTooLong("header line")
        headers.append(line)
        if len(headers) > _MAXHEADERS:
            raise HTTPException("got more than %d headers" % _MAXHEADERS)
        if line in (b'\r\n', b'\n', b''):
            break
    return headers

def parse_headers(fp, _class=HTTPMessage):
    """Parses only RFC2822 headers from a file pointer.

    email Parser wants to see strings rather than bytes.
    But a TextIOWrapper around self.rfile would buffer too many bytes
    from the stream, bytes which we later need to read as bytes.
    So we read the correct bytes here, as bytes, for email Parser
    to parse.

    """
    headers = _read_headers(fp)
    hstring = b''.join(headers).decode('iso-8859-1')
    return email.parser.Parser(_class=_class).parsestr(hstring)


class HTTPResponse(io.BufferedIOBase):

    # See RFC 2616 sec 19.6 and RFC 1945 sec 6 for details.

    # The bytes from the socket object are iso-8859-1 strings.
    # See RFC 2616 sec 2.2 which notes an exception for MIME-encoded
    # text following RFC 2047.  The basic status line parsing only
    # accepts iso-8859-1.

    def __init__(self, sock, debuglevel=0, method=None, url=None):
        # If the response includes a content-length header, we need to
        # make sure that the client doesn't read more than the
        # specified number of bytes.  If it does, it will block until
        # the server times out and closes the connection.  This will
        # happen if a self.fp.read() is done (without a size) whether
        # self.fp is buffered or not.  So, no self.fp.read() by
        # clients unless they know what they are doing.
        self.fp = sock.makefile("rb")
        self.debuglevel = debuglevel
        self._method = method

        # The HTTPResponse object is returned via urllib.  The clients
        # of http and urllib expect different attributes for the
        # headers.  headers is used here and supports urllib.  msg is
        # provided as a backwards compatibility layer for http
        # clients.

        self.headers = self.msg = None

        # from the Status-Line of the response
        self.version = _UNKNOWN # HTTP-Version
        self.status = _UNKNOWN  # Status-Code
        self.reason = _UNKNOWN  # Reason-Phrase

        self.chunked = _UNKNOWN         # is "chunked" being used?
        self.chunk_left = _UNKNOWN      # bytes left to read in current chunk
        self.length = _UNKNOWN          # number of bytes left in response
        self.will_close = _UNKNOWN      # conn will close at end of response

    def _read_status(self):
        line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
        if len(line) > _MAXLINE:
            raise LineTooLong("status line")
        if self.debuglevel > 0:
            print("reply:", repr(line))
        if not line:
            # Presumably, the server closed the connection before
            # sending a valid response.
            raise RemoteDisconnected("Remote end closed connection without"
                                     " response")
        try:
            version, status, reason = line.split(None, 2)
        except ValueError:
            try:
                version, status = line.split(None, 1)
                reason = ""
            except ValueError:
                # empty version will cause next test to fail.
                version = ""
        if not version.startswith("HTTP/"):
            self._close_conn()
            raise BadStatusLine(line)

        # The status code is a three-digit number
        try:
            status = int(status)
            if status < 100 or status > 999:
                raise BadStatusLine(line)
        except ValueError:
            raise BadStatusLine(line)
        return version, status, reason

    def begin(self):
        if self.headers is not None:
            # we've already started reading the response
            return

        # read until we get a non-100 response
        while True:
            version, status, reason = self._read_status()
            if status != CONTINUE:
                break
            # skip the header from the 100 response
            skipped_headers = _read_headers(self.fp)
            if self.debuglevel > 0:
                print("headers:", skipped_headers)
            del skipped_headers

        self.code = self.status = status
        self.reason = reason.strip()
        if version in ("HTTP/1.0", "HTTP/0.9"):
            # Some servers might still return "0.9", treat it as 1.0 anyway
            self.version = 10
        elif version.startswith("HTTP/1."):
            self.version = 11   # use HTTP/1.1 code for HTTP/1.x where x>=1
        else:
            raise UnknownProtocol(version)

        self.headers = self.msg = parse_headers(self.fp)

        if self.debuglevel > 0:
            for hdr, val in self.headers.items():
                print("header:", hdr + ":", val)

        # are we using the chunked-style of transfer encoding?
        tr_enc = self.headers.get("transfer-encoding")
        if tr_enc and tr_enc.lower() == "chunked":
            self.chunked = True
            self.chunk_left = None
        else:
            self.chunked = False

        # will the connection close at the end of the response?
        self.will_close = self._check_close()

        # do we have a Content-Length?
        # NOTE: RFC 2616, S4.4, #3 says we ignore this if tr_enc is "chunked"
        self.length = None
        length = self.headers.get("content-length")
        if length and not self.chunked:
            try:
                self.length = int(length)
            except ValueError:
                self.length = None
            else:
                if self.length < 0:  # ignore nonsensical negative lengths
                    self.length = None
        else:
            self.length = None

        # does the body have a fixed length? (of zero)
        if (status == NO_CONTENT or status == NOT_MODIFIED or
            100 <= status < 200 or      # 1xx codes
            self._method == "HEAD"):
            self.length = 0

        # if the connection remains open, and we aren't using chunked, and
        # a content-length was not provided, then assume that the connection
        # WILL close.
        if (not self.will_close and
            not self.chunked and
            self.length is None):
            self.will_close = True

    def _check_close(self):
        conn = self.headers.get("connection")
        if self.version == 11:
            # An HTTP/1.1 proxy is assumed to stay open unless
            # explicitly closed.
            if conn and "close" in conn.lower():
                return True
            return False

        # Some HTTP/1.0 implementations have support for persistent
        # connections, using rules different than HTTP/1.1.

        # For older HTTP, Keep-Alive indicates persistent connection.
        if self.headers.get("keep-alive"):
            return False

        # At least Akamai returns a "Connection: Keep-Alive" header,
        # which was supposed to be sent by the client.
        if conn and "keep-alive" in conn.lower():
            return False

        # Proxy-Connection is a netscape hack.
        pconn = self.headers.get("proxy-connection")
        if pconn and "keep-alive" in pconn.lower():
            return False

        # otherwise, assume it will close
        return True

    def _close_conn(self):
        fp = self.fp
        self.fp = None
        fp.close()

    def close(self):
        try:
            super().close() # set "closed" flag
        finally:
            if self.fp:
                self._close_conn()

    # These implementations are for the benefit of io.BufferedReader.

    # XXX This class should probably be revised to act more like
    # the "raw stream" that BufferedReader expects.

    def flush(self):
        super().flush()
        if self.fp:
            self.fp.flush()

    def readable(self):
        """Always returns True"""
        return True

    # End of "raw stream" methods

    def isclosed(self):
        """True if the connection is closed."""
        # NOTE: it is possible that we will not ever call self.close(). This
        #       case occurs when will_close is TRUE, length is None, and we
        #       read up to the last byte, but NOT past it.
        #
        # IMPLIES: if will_close is FALSE, then self.close() will ALWAYS be
        #          called, meaning self.isclosed() is meaningful.
        return self.fp is None

    def read(self, amt=None):
        if self.fp is None:
            return b""

        if self._method == "HEAD":
            self._close_conn()
            return b""

        if amt is not None:
            # Amount is given, implement using readinto
            b = bytearray(amt)
            n = self.readinto(b)
            return memoryview(b)[:n].tobytes()
        else:
            # Amount is not given (unbounded read) so we must check self.length
            # and self.chunked

            if self.chunked:
                return self._readall_chunked()

            if self.length is None:
                s = self.fp.read()
            else:
                try:
                    s = self._safe_read(self.length)
                except IncompleteRead:
                    self._close_conn()
                    raise
                self.length = 0
            self._close_conn()        # we read everything
            return s

    def readinto(self, b):
        """Read up to len(b) bytes into bytearray b and return the number
        of bytes read.
        """

        if self.fp is None:
            return 0

        if self._method == "HEAD":
            self._close_conn()
            return 0

        if self.chunked:
            return self._readinto_chunked(b)

        if self.length is not None:
            if len(b) > self.length:
                # clip the read to the "end of response"
                b = memoryview(b)[0:self.length]

        # we do not use _safe_read() here because this may be a .will_close
        # connection, and the user is reading more bytes than will be provided
        # (for example, reading in 1k chunks)
        n = self.fp.readinto(b)
        if not n and b:
            # Ideally, we would raise IncompleteRead if the content-length
            # wasn't satisfied, but it might break compatibility.
            self._close_conn()
        elif self.length is not None:
            self.length -= n
            if not self.length:
                self._close_conn()
        return n

    def _read_next_chunk_size(self):
        # Read the next chunk size from the file
        line = self.fp.readline(_MAXLINE + 1)
        if len(line) > _MAXLINE:
            raise LineTooLong("chunk size")
        i = line.find(b";")
        if i >= 0:
            line = line[:i] # strip chunk-extensions
        try:
            return int(line, 16)
        except ValueError:
            # close the connection as protocol synchronisation is
            # probably lost
            self._close_conn()
            raise

    def _read_and_discard_trailer(self):
        # read and discard trailer up to the CRLF terminator
        ### note: we shouldn't have any trailers!
        while True:
            line = self.fp.readline(_MAXLINE + 1)
            if len(line) > _MAXLINE:
                raise LineTooLong("trailer line")
            if not line:
                # a vanishingly small number of sites EOF without
                # sending the trailer
                break
            if line in (b'\r\n', b'\n', b''):
                break

    def _get_chunk_left(self):
        # return self.chunk_left, reading a new chunk if necessary.
        # chunk_left == 0: at the end of the current chunk, need to close it
        # chunk_left == None: No current chunk, should read next.
        # This function returns non-zero or None if the last chunk has
        # been read.
        chunk_left = self.chunk_left
        if not chunk_left: # Can be 0 or None
            if chunk_left is not None:
                # We are at the end of chunk, discard chunk end
                self._safe_read(2)  # toss the CRLF at the end of the chunk
            try:
                chunk_left = self._read_next_chunk_size()
            except ValueError:
                raise IncompleteRead(b'')
            if chunk_left == 0:
                # last chunk: 1*("0") [ chunk-extension ] CRLF
                self._read_and_discard_trailer()
                # we read everything; close the "file"
                self._close_conn()
                chunk_left = None
            self.chunk_left = chunk_left
        return chunk_left

    def _readall_chunked(self):
        assert self.chunked != _UNKNOWN
        value = []
        try:
            while True:
                chunk_left = self._get_chunk_left()
                if chunk_left is None:
                    break
                value.append(self._safe_read(chunk_left))
                self.chunk_left = 0
            return b''.join(value)
        except IncompleteRead:
            raise IncompleteRead(b''.join(value))

    def _readinto_chunked(self, b):
        assert self.chunked != _UNKNOWN
        total_bytes = 0
        mvb = memoryview(b)
        try:
            while True:
                chunk_left = self._get_chunk_left()
                if chunk_left is None:
                    return total_bytes

                if len(mvb) <= chunk_left:
                    n = self._safe_readinto(mvb)
                    self.chunk_left = chunk_left - n
                    return total_bytes + n

                temp_mvb = mvb[:chunk_left]
                n = self._safe_readinto(temp_mvb)
                mvb = mvb[n:]
                total_bytes += n
                self.chunk_left = 0

        except IncompleteRead:
            raise IncompleteRead(bytes(b[0:total_bytes]))

    def _safe_read(self, amt):
        """Read the number of bytes requested.

        This function should be used when <amt> bytes "should" be present for
        reading. If the bytes are truly not available (due to EOF), then the
        IncompleteRead exception can be used to detect the problem.
        """
        data = self.fp.read(amt)
        if len(data) < amt:
            raise IncompleteRead(data, amt-len(data))
        return data

    def _safe_readinto(self, b):
        """Same as _safe_read, but for reading into a buffer."""
        amt = len(b)
        n = self.fp.readinto(b)
        if n < amt:
            raise IncompleteRead(bytes(b[:n]), amt-n)
        return n

    def read1(self, n=-1):
        """Read with at most one underlying system call.  If at least one
        byte is buffered, return that instead.
        """
        if self.fp is None or self._method == "HEAD":
            return b""
        if self.chunked:
            return self._read1_chunked(n)
        if self.length is not None and (n < 0 or n > self.length):
            n = self.length
        result = self.fp.read1(n)
        if not result and n:
            self._close_conn()
        elif self.length is not None:
            self.length -= len(result)
        return result

    def peek(self, n=-1):
        # Having this enables IOBase.readline() to read more than one
        # byte at a time
        if self.fp is None or self._method == "HEAD":
            return b""
        if self.chunked:
            return self._peek_chunked(n)
        return self.fp.peek(n)

    def readline(self, limit=-1):
        if self.fp is None or self._method == "HEAD":
            return b""
        if self.chunked:
            # Fallback to IOBase readline which uses peek() and read()
            return super().readline(limit)
        if self.length is not None and (limit < 0 or limit > self.length):
            limit = self.length
        result = self.fp.readline(limit)
        if not result and limit:
            self._close_conn()
        elif self.length is not None:
            self.length -= len(result)
        return result

    def _read1_chunked(self, n):
        # Strictly speaking, _get_chunk_left() may cause more than one read,
        # but that is ok, since that is to satisfy the chunked protocol.
        chunk_left = self._get_chunk_left()
        if chunk_left is None or n == 0:
            return b''
        if not (0 <= n <= chunk_left):
            n = chunk_left # if n is negative or larger than chunk_left
        read = self.fp.read1(n)
        self.chunk_left -= len(read)
        if not read:
            raise IncompleteRead(b"")
        return read

    def _peek_chunked(self, n):
        # Strictly speaking, _get_chunk_left() may cause more than one read,
        # but that is ok, since that is to satisfy the chunked protocol.
        try:
            chunk_left = self._get_chunk_left()
        except IncompleteRead:
            return b'' # peek doesn't worry about protocol
        if chunk_left is None:
            return b'' # eof
        # peek is allowed to return more than requested.  Just request the
        # entire chunk, and truncate what we get.
        return self.fp.peek(chunk_left)[:chunk_left]

    def fileno(self):
        return self.fp.fileno()

    def getheader(self, name, default=None):
        '''Returns the value of the header matching *name*.

        If there are multiple matching headers, the values are
        combined into a single string separated by commas and spaces.

        If no matching header is found, returns *default* or None if
        the *default* is not specified.

        If the headers are unknown, raises http.client.ResponseNotReady.

        '''
        if self.headers is None:
            raise ResponseNotReady()
        headers = self.headers.get_all(name) or default
        if isinstance(headers, str) or not hasattr(headers, '__iter__'):
            return headers
        else:
            return ', '.join(headers)

    def getheaders(self):
        """Return list of (header, value) tuples."""
        if self.headers is None:
            raise ResponseNotReady()
        return list(self.headers.items())

    # We override IOBase.__iter__ so that it doesn't check for closed-ness

    def __iter__(self):
        return self

    # For compatibility with old-style urllib responses.

    def info(self):
        '''Returns an instance of the class mimetools.Message containing
        meta-information associated with the URL.

        When the method is HTTP, these headers are those returned by
        the server at the head of the retrieved HTML page (including
        Content-Length and Content-Type).

        When the method is FTP, a Content-Length header will be
        present if (as is now usual) the server passed back a file
        length in response to the FTP retrieval request. A
        Content-Type header will be present if the MIME type can be
        guessed.

        When the method is local-file, returned headers will include
        a Date representing the file's last-modified time, a
        Content-Length giving file size, and a Content-Type
        containing a guess at the file's type. See also the
        description of the mimetools module.

        '''
        return self.headers

    def geturl(self):
        '''Return the real URL of the page.

        In some cases, the HTTP server redirects a client to another
        URL. The urlopen() function handles this transparently, but in
        some cases the caller needs to know which URL the client was
        redirected to. The geturl() method can be used to get at this
        redirected URL.

        '''
        return self.url

    def getcode(self):
        '''Return the HTTP status code that was sent with the response,
        or None if the URL is not an HTTP URL.

        '''
        return self.status

class HTTPConnection:

    _http_vsn = 11
    _http_vsn_str = 'HTTP/1.1'

    response_class = HTTPResponse
    default_port = HTTP_PORT
    auto_open = 1
    debuglevel = 0

    @staticmethod
    def _is_textIO(stream):
        """Test whether a file-like object is a text or a binary stream.
        """
        return isinstance(stream, io.TextIOBase)

    @staticmethod
    def _get_content_length(body, method):
        """Get the content-length based on the body.

        If the body is None, we set Content-Length: 0 for methods that expect
        a body (RFC 7230, Section 3.3.2). We also set the Content-Length for
        any method if the body is a str or bytes-like object and not a file.
        """
        if body is None:
            # do an explicit check for not None here to distinguish
            # between unset and set but empty
            if method.upper() in _METHODS_EXPECTING_BODY:
                return 0
            else:
                return None

        if hasattr(body, 'read'):
            # file-like object.
            return None

        try:
            # does it implement the buffer protocol (bytes, bytearray, array)?
            mv = memoryview(body)
            return mv.nbytes
        except TypeError:
            pass

        if isinstance(body, str):
            return len(body)

        return None

    def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
                 source_address=None, blocksize=8192):
        self.timeout = timeout
        self.source_address = source_address
        self.blocksize = blocksize
        self.sock = None
        self._buffer = []
        self.__response = None
        self.__state = _CS_IDLE
        self._method = None
        self._tunnel_host = None
        self._tunnel_port = None
        self._tunnel_headers = {}

        (self.host, self.port) = self._get_hostport(host, port)

        self._validate_host(self.host)

        # This is stored as an instance variable to allow unit
        # tests to replace it with a suitable mockup
        self._create_connection = socket.create_connection

    def set_tunnel(self, host, port=None, headers=None):
        """Set up host and port for HTTP CONNECT tunnelling.

        In a connection that uses HTTP CONNECT tunneling, the host passed to the
        constructor is used as a proxy server that relays all communication to
        the endpoint passed to `set_tunnel`. This done by sending an HTTP
        CONNECT request to the proxy server when the connection is established.

        This method must be called before the HTTP connection has been
        established.

        The headers argument should be a mapping of extra HTTP headers to send
        with the CONNECT request.
        """

        if self.sock:
            raise RuntimeError("Can't set up tunnel for established connection")

        self._tunnel_host, self._tunnel_port = self._get_hostport(host, port)
        if headers:
            self._tunnel_headers = headers
        else:
            self._tunnel_headers.clear()

    def _get_hostport(self, host, port):
        if port is None:
            i = host.rfind(':')
            j = host.rfind(']')         # ipv6 addresses have [...]
            if i > j:
                try:
                    port = int(host[i+1:])
                except ValueError:
                    if host[i+1:] == "": # http://foo.com:/ == http://foo.com/
                        port = self.default_port
                    else:
                        raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
                host = host[:i]
            else:
                port = self.default_port
            if host and host[0] == '[' and host[-1] == ']':
                host = host[1:-1]

        return (host, port)

    def set_debuglevel(self, level):
        self.debuglevel = level

    def _tunnel(self):
        connect_str = "CONNECT %s:%d HTTP/1.0\r\n" % (self._tunnel_host,
            self._tunnel_port)
        connect_bytes = connect_str.encode("ascii")
        self.send(connect_bytes)
        for header, value in self._tunnel_headers.items():
            header_str = "%s: %s\r\n" % (header, value)
            header_bytes = header_str.encode("latin-1")
            self.send(header_bytes)
        self.send(b'\r\n')

        response = self.response_class(self.sock, method=self._method)
        (version, code, message) = response._read_status()

        if code != http.HTTPStatus.OK:
            self.close()
            raise OSError("Tunnel connection failed: %d %s" % (code,
                                                               message.strip()))
        while True:
            line = response.fp.readline(_MAXLINE + 1)
            if len(line) > _MAXLINE:
                raise LineTooLong("header line")
            if not line:
                # for sites which EOF without sending a trailer
                break
            if line in (b'\r\n', b'\n', b''):
                break

            if self.debuglevel > 0:
                print('header:', line.decode())

    def connect(self):
        """Connect to the host and port specified in __init__."""
        self.sock = self._create_connection(
            (self.host,self.port), self.timeout, self.source_address)
        self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

        if self._tunnel_host:
            self._tunnel()

    def close(self):
        """Close the connection to the HTTP server."""
        self.__state = _CS_IDLE
        try:
            sock = self.sock
            if sock:
                self.sock = None
                sock.close()   # close it manually... there may be other refs
        finally:
            response = self.__response
            if response:
                self.__response = None
                response.close()

    def send(self, data):
        """Send `data' to the server.
        ``data`` can be a string object, a bytes object, an array object, a
        file-like object that supports a .read() method, or an iterable object.
        """

        if self.sock is None:
            if self.auto_open:
                self.connect()
            else:
                raise NotConnected()

        if self.debuglevel > 0:
            print("send:", repr(data))
        if hasattr(data, "read") :
            if self.debuglevel > 0:
                print("sendIng a read()able")
            encode = self._is_textIO(data)
            if encode and self.debuglevel > 0:
                print("encoding file using iso-8859-1")
            while 1:
                datablock = data.read(self.blocksize)
                if not datablock:
                    break
                if encode:
                    datablock = datablock.encode("iso-8859-1")
                self.sock.sendall(datablock)
            return
        try:
            self.sock.sendall(data)
        except TypeError:
            if isinstance(data, collections.abc.Iterable):
                for d in data:
                    self.sock.sendall(d)
            else:
                raise TypeError("data should be a bytes-like object "
                                "or an iterable, got %r" % type(data))

    def _output(self, s):
        """Add a line of output to the current request buffer.

        Assumes that the line does *not* end with \\r\\n.
        """
        self._buffer.append(s)

    def _read_readable(self, readable):
        if self.debuglevel > 0:
            print("sendIng a read()able")
        encode = self._is_textIO(readable)
        if encode and self.debuglevel > 0:
            print("encoding file using iso-8859-1")
        while True:
            datablock = readable.read(self.blocksize)
            if not datablock:
                break
            if encode:
                datablock = datablock.encode("iso-8859-1")
            yield datablock

    def _send_output(self, message_body=None, encode_chunked=False):
        """Send the currently buffered request and clear the buffer.

        Appends an extra \\r\\n to the buffer.
        A message_body may be specified, to be appended to the request.
        """
        self._buffer.extend((b"", b""))
        msg = b"\r\n".join(self._buffer)
        del self._buffer[:]
        self.send(msg)

        if message_body is not None:

            # create a consistent interface to message_body
            if hasattr(message_body, 'read'):
                # Let file-like take precedence over byte-like.  This
                # is needed to allow the current position of mmap'ed
                # files to be taken into account.
                chunks = self._read_readable(message_body)
            else:
                try:
                    # this is solely to check to see if message_body
                    # implements the buffer API.  it /would/ be easier
                    # to capture if PyObject_CheckBuffer was exposed
                    # to Python.
                    memoryview(message_body)
                except TypeError:
                    try:
                        chunks = iter(message_body)
                    except TypeError:
                        raise TypeError("message_body should be a bytes-like "
                                        "object or an iterable, got %r"
                                        % type(message_body))
                else:
                    # the object implements the buffer interface and
                    # can be passed directly into socket methods
                    chunks = (message_body,)

            for chunk in chunks:
                if not chunk:
                    if self.debuglevel > 0:
                        print('Zero length chunk ignored')
                    continue

                if encode_chunked and self._http_vsn == 11:
                    # chunked encoding
                    chunk = f'{len(chunk):X}\r\n'.encode('ascii') + chunk \
                        + b'\r\n'
                self.send(chunk)

            if encode_chunked and self._http_vsn == 11:
                # end chunked transfer
                self.send(b'0\r\n\r\n')

    def putrequest(self, method, url, skip_host=False,
                   skip_accept_encoding=False):
        """Send a request to the server.

        `method' specifies an HTTP request method, e.g. 'GET'.
        `url' specifies the object being requested, e.g. '/index.html'.
        `skip_host' if True does not add automatically a 'Host:' header
        `skip_accept_encoding' if True does not add automatically an
           'Accept-Encoding:' header
        """

        # if a prior response has been completed, then forget about it.
        if self.__response and self.__response.isclosed():
            self.__response = None


        # in certain cases, we cannot issue another request on this connection.
        # this occurs when:
        #   1) we are in the process of sending a request.   (_CS_REQ_STARTED)
        #   2) a response to a previous request has signalled that it is going
        #      to close the connection upon completion.
        #   3) the headers for the previous response have not been read, thus
        #      we cannot determine whether point (2) is true.   (_CS_REQ_SENT)
        #
        # if there is no prior response, then we can request at will.
        #
        # if point (2) is true, then we will have passed the socket to the
        # response (effectively meaning, "there is no prior response"), and
        # will open a new one when a new request is made.
        #
        # Note: if a prior response exists, then we *can* start a new request.
        #       We are not allowed to begin fetching the response to this new
        #       request, however, until that prior response is complete.
        #
        if self.__state == _CS_IDLE:
            self.__state = _CS_REQ_STARTED
        else:
            raise CannotSendRequest(self.__state)

        self._validate_method(method)

        # Save the method for use later in the response phase
        self._method = method

        url = url or '/'
        self._validate_path(url)

        request = '%s %s %s' % (method, url, self._http_vsn_str)

        self._output(self._encode_request(request))

        if self._http_vsn == 11:
            # Issue some standard headers for better HTTP/1.1 compliance

            if not skip_host:
                # this header is issued *only* for HTTP/1.1
                # connections. more specifically, this means it is
                # only issued when the client uses the new
                # HTTPConnection() class. backwards-compat clients
                # will be using HTTP/1.0 and those clients may be
                # issuing this header themselves. we should NOT issue
                # it twice; some web servers (such as Apache) barf
                # when they see two Host: headers

                # If we need a non-standard port,include it in the
                # header.  If the request is going through a proxy,
                # but the host of the actual URL, not the host of the
                # proxy.

                netloc = ''
                if url.startswith('http'):
                    nil, netloc, nil, nil, nil = urlsplit(url)

                if netloc:
                    try:
                        netloc_enc = netloc.encode("ascii")
                    except UnicodeEncodeError:
                        netloc_enc = netloc.encode("idna")
                    self.putheader('Host', netloc_enc)
                else:
                    if self._tunnel_host:
                        host = self._tunnel_host
                        port = self._tunnel_port
                    else:
                        host = self.host
                        port = self.port

                    try:
                        host_enc = host.encode("ascii")
                    except UnicodeEncodeError:
                        host_enc = host.encode("idna")

                    # As per RFC 273, IPv6 address should be wrapped with []
                    # when used as Host header

                    if host.find(':') >= 0:
                        host_enc = b'[' + host_enc + b']'

                    if port == self.default_port:
                        self.putheader('Host', host_enc)
                    else:
                        host_enc = host_enc.decode("ascii")
                        self.putheader('Host', "%s:%s" % (host_enc, port))

            # note: we are assuming that clients will not attempt to set these
            #       headers since *this* library must deal with the
            #       consequences. this also means that when the supporting
            #       libraries are updated to recognize other forms, then this
            #       code should be changed (removed or updated).

            # we only want a Content-Encoding of "identity" since we don't
            # support encodings such as x-gzip or x-deflate.
            if not skip_accept_encoding:
                self.putheader('Accept-Encoding', 'identity')

            # we can accept "chunked" Transfer-Encodings, but no others
            # NOTE: no TE header implies *only* "chunked"
            #self.putheader('TE', 'chunked')

            # if TE is supplied in the header, then it must appear in a
            # Connection header.
            #self.putheader('Connection', 'TE')

        else:
            # For HTTP/1.0, the server will assume "not chunked"
            pass

    def _encode_request(self, request):
        # ASCII also helps prevent CVE-2019-9740.
        return request.encode('ascii')

    def _validate_method(self, method):
        """Validate a method name for putrequest."""
        # prevent http header injection
        match = _contains_disallowed_method_pchar_re.search(method)
        if match:
            raise ValueError(
                    f"method can't contain control characters. {method!r} "
                    f"(found at least {match.group()!r})")

    def _validate_path(self, url):
        """Validate a url for putrequest."""
        # Prevent CVE-2019-9740.
        match = _contains_disallowed_url_pchar_re.search(url)
        if match:
            raise InvalidURL(f"URL can't contain control characters. {url!r} "
                             f"(found at least {match.group()!r})")

    def _validate_host(self, host):
        """Validate a host so it doesn't contain control characters."""
        # Prevent CVE-2019-18348.
        match = _contains_disallowed_url_pchar_re.search(host)
        if match:
            raise InvalidURL(f"URL can't contain control characters. {host!r} "
                             f"(found at least {match.group()!r})")

    def putheader(self, header, *values):
        """Send a request header line to the server.

        For example: h.putheader('Accept', 'text/html')
        """
        if self.__state != _CS_REQ_STARTED:
            raise CannotSendHeader()

        if hasattr(header, 'encode'):
            header = header.encode('ascii')

        if not _is_legal_header_name(header):
            raise ValueError('Invalid header name %r' % (header,))

        values = list(values)
        for i, one_value in enumerate(values):
            if hasattr(one_value, 'encode'):
                values[i] = one_value.encode('latin-1')
            elif isinstance(one_value, int):
                values[i] = str(one_value).encode('ascii')

            if _is_illegal_header_value(values[i]):
                raise ValueError('Invalid header value %r' % (values[i],))

        value = b'\r\n\t'.join(values)
        header = header + b': ' + value
        self._output(header)

    def endheaders(self, message_body=None, *, encode_chunked=False):
        """Indicate that the last header line has been sent to the server.

        This method sends the request to the server.  The optional message_body
        argument can be used to pass a message body associated with the
        request.
        """
        if self.__state == _CS_REQ_STARTED:
            self.__state = _CS_REQ_SENT
        else:
            raise CannotSendHeader()
        self._send_output(message_body, encode_chunked=encode_chunked)

    def request(self, method, url, body=None, headers={}, *,
                encode_chunked=False):
        """Send a complete request to the server."""
        self._send_request(method, url, body, headers, encode_chunked)

    def _send_request(self, method, url, body, headers, encode_chunked):
        # Honor explicitly requested Host: and Accept-Encoding: headers.
        header_names = frozenset(k.lower() for k in headers)
        skips = {}
        if 'host' in header_names:
            skips['skip_host'] = 1
        if 'accept-encoding' in header_names:
            skips['skip_accept_encoding'] = 1

        self.putrequest(method, url, **skips)

        # chunked encoding will happen if HTTP/1.1 is used and either
        # the caller passes encode_chunked=True or the following
        # conditions hold:
        # 1. content-length has not been explicitly set
        # 2. the body is a file or iterable, but not a str or bytes-like
        # 3. Transfer-Encoding has NOT been explicitly set by the caller

        if 'content-length' not in header_names:
            # only chunk body if not explicitly set for backwards
            # compatibility, assuming the client code is already handling the
            # chunking
            if 'transfer-encoding' not in header_names:
                # if content-length cannot be automatically determined, fall
                # back to chunked encoding
                encode_chunked = False
                content_length = self._get_content_length(body, method)
                if content_length is None:
                    if body is not None:
                        if self.debuglevel > 0:
                            print('Unable to determine size of %r' % body)
                        encode_chunked = True
                        self.putheader('Transfer-Encoding', 'chunked')
                else:
                    self.putheader('Content-Length', str(content_length))
        else:
            encode_chunked = False

        for hdr, value in headers.items():
            self.putheader(hdr, value)
        if isinstance(body, str):
            # RFC 2616 Section 3.7.1 says that text default has a
            # default charset of iso-8859-1.
            body = _encode(body, 'body')
        self.endheaders(body, encode_chunked=encode_chunked)

    def getresponse(self):
        """Get the response from the server.

        If the HTTPConnection is in the correct state, returns an
        instance of HTTPResponse or of whatever object is returned by
        the response_class variable.

        If a request has not been sent or if a previous response has
        not be handled, ResponseNotReady is raised.  If the HTTP
        response indicates that the connection should be closed, then
        it will be closed before the response is returned.  When the
        connection is closed, the underlying socket is closed.
        """

        # if a prior response has been completed, then forget about it.
        if self.__response and self.__response.isclosed():
            self.__response = None

        # if a prior response exists, then it must be completed (otherwise, we
        # cannot read this response's header to determine the connection-close
        # behavior)
        #
        # note: if a prior response existed, but was connection-close, then the
        # socket and response were made independent of this HTTPConnection
        # object since a new request requires that we open a whole new
        # connection
        #
        # this means the prior response had one of two states:
        #   1) will_close: this connection was reset and the prior socket and
        #                  response operate independently
        #   2) persistent: the response was retained and we await its
        #                  isclosed() status to become true.
        #
        if self.__state != _CS_REQ_SENT or self.__response:
            raise ResponseNotReady(self.__state)

        if self.debuglevel > 0:
            response = self.response_class(self.sock, self.debuglevel,
                                           method=self._method)
        else:
            response = self.response_class(self.sock, method=self._method)

        try:
            try:
                response.begin()
            except ConnectionError:
                self.close()
                raise
            assert response.will_close != _UNKNOWN
            self.__state = _CS_IDLE

            if response.will_close:
                # this effectively passes the connection to the response
                self.close()
            else:
                # remember this, so we can tell when it is complete
                self.__response = response

            return response
        except:
            response.close()
            raise

try:
    import ssl
except ImportError:
    pass
else:
    class HTTPSConnection(HTTPConnection):
        "This class allows communication via SSL."

        default_port = HTTPS_PORT

        # XXX Should key_file and cert_file be deprecated in favour of context?

        def __init__(self, host, port=None, key_file=None, cert_file=None,
                     timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
                     source_address=None, *, context=None,
                     check_hostname=None, blocksize=8192):
            super(HTTPSConnection, self).__init__(host, port, timeout,
                                                  source_address,
                                                  blocksize=blocksize)
            if (key_file is not None or cert_file is not None or
                        check_hostname is not None):
                import warnings
                warnings.warn("key_file, cert_file and check_hostname are "
                              "deprecated, use a custom context instead.",
                              DeprecationWarning, 2)
            self.key_file = key_file
            self.cert_file = cert_file
            if context is None:
                context = ssl._create_default_https_context()
                # enable PHA for TLS 1.3 connections if available
                if context.post_handshake_auth is not None:
                    context.post_handshake_auth = True
            will_verify = context.verify_mode != ssl.CERT_NONE
            if check_hostname is None:
                check_hostname = context.check_hostname
            if check_hostname and not will_verify:
                raise ValueError("check_hostname needs a SSL context with "
                                 "either CERT_OPTIONAL or CERT_REQUIRED")
            if key_file or cert_file:
                context.load_cert_chain(cert_file, key_file)
                # cert and key file means the user wants to authenticate.
                # enable TLS 1.3 PHA implicitly even for custom contexts.
                if context.post_handshake_auth is not None:
                    context.post_handshake_auth = True
            self._context = context
            if check_hostname is not None:
                self._context.check_hostname = check_hostname

        def connect(self):
            "Connect to a host on a given (SSL) port."

            super().connect()

            if self._tunnel_host:
                server_hostname = self._tunnel_host
            else:
                server_hostname = self.host

            self.sock = self._context.wrap_socket(self.sock,
                                                  server_hostname=server_hostname)

    __all__.append("HTTPSConnection")

class HTTPException(Exception):
    # Subclasses that define an __init__ must call Exception.__init__
    # or define self.args.  Otherwise, str() will fail.
    pass

class NotConnected(HTTPException):
    pass

class InvalidURL(HTTPException):
    pass

class UnknownProtocol(HTTPException):
    def __init__(self, version):
        self.args = version,
        self.version = version

class UnknownTransferEncoding(HTTPException):
    pass

class UnimplementedFileMode(HTTPException):
    pass

class IncompleteRead(HTTPException):
    def __init__(self, partial, expected=None):
        self.args = partial,
        self.partial = partial
        self.expected = expected
    def __repr__(self):
        if self.expected is not None:
            e = ', %i more expected' % self.expected
        else:
            e = ''
        return '%s(%i bytes read%s)' % (self.__class__.__name__,
                                        len(self.partial), e)
    __str__ = object.__str__

class ImproperConnectionState(HTTPException):
    pass

class CannotSendRequest(ImproperConnectionState):
    pass

class CannotSendHeader(ImproperConnectionState):
    pass

class ResponseNotReady(ImproperConnectionState):
    pass

class BadStatusLine(HTTPException):
    def __init__(self, line):
        if not line:
            line = repr(line)
        self.args = line,
        self.line = line

class LineTooLong(HTTPException):
    def __init__(self, line_type):
        HTTPException.__init__(self, "got more than %d bytes when reading %s"
                                     % (_MAXLINE, line_type))

class RemoteDisconnected(ConnectionResetError, BadStatusLine):
    def __init__(self, *pos, **kw):
        BadStatusLine.__init__(self, "")
        ConnectionResetError.__init__(self, *pos, **kw)

# for backwards compatibility
error = HTTPException
__pycache__/cookies.cpython-38.pyc000064400000035646150532417300013056 0ustar00U

e5d�O�
@stdZddlZddlZdddgZdjZdjZdjZGd	d�de�Z	ej
ejd
ZedZ
dd
�eed��eeee
��D�Ze�ed�ded�di�e�de�e��jZdd�Ze�d�Ze�d�Zdd�Zddddddd gZdd!d"d#d$d%d&d'd(d)d*d+d,g
Zdeefd-d.�ZGd/d0�d0e�Z d1Z!e!d2Z"e�d3e!d4e"d5ej#ej$B�Z%Gd6d�de�Z&Gd7d�de&�Z'dS)8a.

Here's a sample session to show how to use this module.
At the moment, this is the only documentation.

The Basics
----------

Importing is easy...

   >>> from http import cookies

Most of the time you start by creating a cookie.

   >>> C = cookies.SimpleCookie()

Once you've created your Cookie, you can add values just as if it were
a dictionary.

   >>> C = cookies.SimpleCookie()
   >>> C["fig"] = "newton"
   >>> C["sugar"] = "wafer"
   >>> C.output()
   'Set-Cookie: fig=newton\r\nSet-Cookie: sugar=wafer'

Notice that the printable representation of a Cookie is the
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.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

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.SimpleCookie()
   >>> C.load("chips=ahoy; vienna=finger")
   >>> C.output()
   'Set-Cookie: chips=ahoy\r\nSet-Cookie: vienna=finger'

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.SimpleCookie()
   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
   >>> print(C)
   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"

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.SimpleCookie()
   >>> C["oreo"] = "doublestuff"
   >>> C["oreo"]["path"] = "/"
   >>> print(C)
   Set-Cookie: oreo=doublestuff; Path=/

Each dictionary element has a 'value' attribute, which gives you
back the value associated with the key.

   >>> C = cookies.SimpleCookie()
   >>> C["twix"] = "none for you"
   >>> C["twix"].value
   'none for you'

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.

   >>> C = cookies.SimpleCookie()
   >>> C["number"] = 7
   >>> C["string"] = "seven"
   >>> C["number"].value
   '7'
   >>> C["string"].value
   'seven'
   >>> C.output()
   'Set-Cookie: number=7\r\nSet-Cookie: string=seven'

Finis.
�N�CookieError�
BaseCookie�SimpleCookie�z; � c@seZdZdS)rN)�__name__�
__module__�__qualname__�r
r
�$/usr/lib64/python3.8/http/cookies.pyr�sz!#$%&'*+-.^_`|~:z
 ()/<=>?@[]{}cCsi|]}|d|�qS)z\%03or
)�.0�nr
r
r�
<dictcomp>�s�r��"�\"�\z\\z[%s]+cCs*|dkst|�r|Sd|�t�dSdS)z�Quote a string for use in a cookie header.

    If the string does not need to be double-quoted, then just return the
    string.  Otherwise, surround the string in doublequotes and quote
    (with a \) special characters.
    Nr)�
_is_legal_key�	translate�_Translator��strr
r
r�_quote�srz\\[0-3][0-7][0-7]z[\\].cCsN|dkst|�dkr|S|ddks0|ddkr4|S|dd�}d}t|�}g}d|krf|k�rFnn�t�||�}t�||�}|s�|s�|�||d���qFd}}|r�|�d�}|r�|�d�}|�r|r�||k�r|�|||��|�||d�|d}qP|�|||��|�tt||d|d�d���|d}qPt|�S)N�rr������)	�len�
_OctalPatt�search�
_QuotePatt�append�start�chr�int�	_nulljoin)r�ir
�resZo_matchZq_match�j�kr
r
r�_unquote�s6


$
r+ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc	CsRddlm}m}|�}|||�\	}}}}	}
}}}
}d|||||||	|
|fS)Nr)�gmtime�timez#%s, %02d %3s %4d %02d:%02d:%02d GMT)r-r,)ZfutureZweekdaynameZ	monthnamer,r-ZnowZyearZmonthZdayZhhZmmZssZwd�y�zr
r
r�_getdate�s�r0c
@s�eZdZdZdddddddd	d
d�	Zdd
hZdd�Zedd��Zedd��Z	edd��Z
dd�Zd2dd�Zdd�Z
ejZdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd3d*d+�ZeZd,d-�Zd4d.d/�Zd5d0d1�ZdS)6�MorselaCA class to hold ONE (key, value) pair.

    In a cookie, each such pair may have several attributes, so this class is
    used to keep the attributes associated with the appropriate key,value pair.
    This class also includes a coded_value attribute, which is used to hold
    the network representation of the value.
    �expires�Path�CommentZDomainzMax-AgeZSecureZHttpOnlyZVersionZSameSite)	r2�path�commentZdomain�max-age�secure�httponly�versionZsamesiter8r9cCs0d|_|_|_|jD]}t�||d�qdS)Nr)�_key�_value�_coded_value�	_reserved�dict�__setitem__)�self�keyr
r
r�__init__ s
zMorsel.__init__cCs|jS�N)r;�rAr
r
rrB(sz
Morsel.keycCs|jSrD)r<rEr
r
r�value,szMorsel.valuecCs|jSrD)r=rEr
r
r�coded_value0szMorsel.coded_valuecCs2|��}||jkr td|f��t�|||�dS�NzInvalid attribute %r)�lowerr>rr?r@)rA�K�Vr
r
rr@4s
zMorsel.__setitem__NcCs.|��}||jkr td|f��t�|||�SrH)rIr>rr?�
setdefault)rArB�valr
r
rrL:s
zMorsel.setdefaultcCs>t|t�stSt�||�o<|j|jko<|j|jko<|j|jkSrD)�
isinstancer1�NotImplementedr?�__eq__r<r;r=�rAZmorselr
r
rrP@s

�
�
�z
Morsel.__eq__cCs$t�}t�||�|j�|j�|SrD)r1r?�update�__dict__rQr
r
r�copyJszMorsel.copycCsRi}t|���D]0\}}|��}||jkr8td|f��|||<qt�||�dSrH)r?�itemsrIr>rrR)rA�values�datarBrMr
r
rrRPs

z
Morsel.updatecCs|��|jkSrD)rIr>)rArJr
r
r�
isReservedKeyYszMorsel.isReservedKeycCsH|��|jkrtd|f��t|�s2td|f��||_||_||_dS)Nz Attempt to set a reserved key %rzIllegal key %r)rIr>rrr;r<r=)rArBrMZ	coded_valr
r
r�set\sz
Morsel.setcCs|j|j|jd�S)N)rBrFrG�r;r<r=rEr
r
r�__getstate__gs�zMorsel.__getstate__cCs"|d|_|d|_|d|_dS)NrBrFrGrZ)rA�stater
r
r�__setstate__ns

zMorsel.__setstate__�Set-Cookie:cCsd||�|�fS)Nz%s %s)�OutputString)rA�attrs�headerr
r
r�outputssz
Morsel.outputcCsd|jj|��fS)N�<%s: %s>)�	__class__rr_rEr
r
r�__repr__xszMorsel.__repr__cCsd|�|��dd�S)Nz�
        <script type="text/javascript">
        <!-- begin hiding
        document.cookie = "%s";
        // end hiding -->
        </script>
        rr)r_�replace)rAr`r
r
r�	js_output{s�zMorsel.js_outputcCs$g}|j}|d|j|jf�|dkr,|j}t|���}|D]�\}}|dkrNq<||krXq<|dkr�t|t�r�|d|j|t|�f�q<|dkr�t|t�r�|d|j||f�q<|dkr�t|t	�r�|d|j|t
|�f�q<||jk�r|�r|t	|j|��q<|d|j||f�q<t|�S)N�%s=%srr2r7z%s=%dr6)
r"rBrGr>�sortedrUrNr%r0rr�_flags�_semispacejoin)rAr`�resultr"rUrBrFr
r
rr_�s,zMorsel.OutputString)N)Nr^)N)N)rrr	�__doc__r>rjrC�propertyrBrFrGr@rLrP�object�__ne__rTrRrXrYr[r]rb�__str__rergr_r
r
r
rr1�sD�



	


r1z,\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=z\[\]z�
    \s*                            # Optional whitespace at start of cookie
    (?P<key>                       # Start of group 'key'
    [a	]+?   # Any word of at least one letter
    )                              # End of group 'key'
    (                              # Optional group: there may not be a value.
    \s*=\s*                          # Equal Sign
    (?P<val>                         # Start of group 'val'
    "(?:[^\\"]|\\.)*"                  # Any doublequoted string
    |                                  # or
    \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT  # Special case for "expires" attr
    |                                  # or
    [a-]*      # Any word or empty string
    )                                # End of group 'val'
    )?                             # End of optional value group
    \s*                            # Any number of spaces.
    (\s+|;|$)                      # Ending either at space, semicolon, or EOS.
    c@sneZdZdZdd�Zdd�Zddd�Zd	d
�Zdd�Zddd�Z	e	Z
dd�Zddd�Zdd�Z
efdd�ZdS)rz'A container class for a set of Morsels.cCs||fS)a
real_value, coded_value = value_decode(STRING)
        Called prior to setting a cookie's value from the network
        representation.  The VALUE is the value read from HTTP
        header.
        Override this function to modify the behavior of cookies.
        r
�rArMr
r
r�value_decode�szBaseCookie.value_decodecCst|�}||fS)z�real_value, coded_value = value_encode(VALUE)
        Called prior to setting a cookie's value from the dictionary
        representation.  The VALUE is the value being assigned.
        Override this function to modify the behavior of cookies.
        r�rArMZstrvalr
r
r�value_encode�szBaseCookie.value_encodeNcCs|r|�|�dSrD)�load)rA�inputr
r
rrC�szBaseCookie.__init__cCs.|�|t��}|�|||�t�|||�dS)z+Private method for setting a cookie's valueN)�getr1rYr?r@)rArBZ
real_valuerG�Mr
r
rZ__set�szBaseCookie.__setcCs:t|t�rt�|||�n|�|�\}}|�|||�dS)zDictionary style assignment.N)rNr1r?r@ru�_BaseCookie__set)rArBrF�rval�cvalr
r
rr@�s
zBaseCookie.__setitem__r^�
cCs:g}t|���}|D]\}}|�|�||��q|�|�S)z"Return a string suitable for HTTP.)rirUr"rb�join)rAr`ra�seprlrUrBrFr
r
rrb�s
zBaseCookie.outputcCsJg}t|���}|D] \}}|�d|t|j�f�qd|jjt|�fS)Nrhrc)rirUr"�reprrFrdr�
_spacejoin)rA�lrUrBrFr
r
rre�s
zBaseCookie.__repr__cCs6g}t|���}|D]\}}|�|�|��qt|�S)z(Return a string suitable for JavaScript.)rirUr"rgr&)rAr`rlrUrBrFr
r
rrgs
zBaseCookie.js_outputcCs4t|t�r|�|�n|��D]\}}|||<qdS)z�Load cookies from a string (presumably HTTP_COOKIE) or
        from a dictionary.  Loading cookies from a dictionary 'd'
        is equivalent to calling:
            map(Cookie.__setitem__, d.keys(), d.values())
        N)rNr�_BaseCookie__parse_stringrU)rAZrawdatarBrFr
r
rrv
s


zBaseCookie.loadcCs�d}t|�}g}d}d}d}d|kr2|k�rnn�|�||�}	|	sJ�q|	�d�|	�d�}
}|	�d�}|
ddkr�|s|q|�||
dd�|f�q|
��tjkr�|s�dS|dkr�|
��tjkr�|�||
df�q�dSn|�||
t	|�f�q|dk	�r|�||
|�
|�f�d}qdSqd}|D]Z\}
}
}|
|k�rP|dk	�sFt�|||
<n,|
|k�s^t�|\}}|�|
||�||
}�q$dS)	NrFrrrBrM�$T)
r�match�group�endr"rIr1r>rjr+rs�AssertionErrorrz)rArZpattr'r
Zparsed_itemsZmorsel_seenZTYPE_ATTRIBUTEZ
TYPE_KEYVALUEr�rBrFry�tpr{r|r
r
rZ__parse_stringsJ



zBaseCookie.__parse_string)N)Nr^r})N)rrr	rmrsrurCrzr@rbrqrergrv�_CookiePatternr�r
r
r
rr�s		
	

c@s eZdZdZdd�Zdd�ZdS)rz�
    SimpleCookie supports strings as cookie values.  When setting
    the value using the dictionary assignment notation, SimpleCookie
    calls the builtin str() to convert the value to a string.  Values
    received from HTTP are kept as strings.
    cCst|�|fSrD)r+rrr
r
rrs\szSimpleCookie.value_decodecCst|�}|t|�fSrD)rrrtr
r
rru_szSimpleCookie.value_encodeN)rrr	rmrsrur
r
r
rrUs)(rm�re�string�__all__r~r&rkr��	ExceptionrZ
ascii_lettersZdigitsZ_LegalCharsZ_UnescapedCharsrY�range�map�ordrrR�compile�escape�	fullmatchrrrr!r+Z_weekdaynameZ
_monthnamer0r?r1Z_LegalKeyCharsZ_LegalValueChars�ASCII�VERBOSEr�rrr
r
r
r�<module>'sr]
��

2�4����
�
__pycache__/__init__.cpython-38.opt-2.pyc000064400000012411150532417300014102 0ustar00U

e5d��@s&ddlmZdgZGdd�de�ZdS)�)�IntEnum�
HTTPStatusc@seZdZd@dd�ZdZdZdZdZdZd	Z	d
Z
dZdZd
Z
dZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZd Z d!Z!d"Z"d#Z#d$Z$d%Z%d&Z&d'Z'd(Z(d)Z)d*Z*d+Z+d,Z,d-Z-d.Z.d/Z/d0Z0d1Z1d2Z2d3Z3d4Z4d5Z5d6Z6d7Z7d8Z8d9Z9d:Z:d;Z;d<Z<d=Z=d>Z>d?S)Ar�cCs"t�||�}||_||_||_|S)N)�int�__new__�_value_�phrase�description)�cls�valuerr	�obj�r
�%/usr/lib64/python3.8/http/__init__.pyrs
zHTTPStatus.__new__)�dZContinuez!Request received, please continue)�ezSwitching Protocolsz.Switching to new protocol; obey Upgrade header)�fZ
Processing)���OKz#Request fulfilled, document follows)��ZCreatedzDocument created, URL follows)��ZAcceptedz/Request accepted, processing continues off-line)��zNon-Authoritative InformationzRequest fulfilled from cache)��z
No Contentz"Request fulfilled, nothing follows)��z
Reset Contentz"Clear input form for further input)��zPartial ContentzPartial content follows)��zMulti-Status)��zAlready Reported)��zIM Used)i,zMultiple Choicesz,Object has several resources -- see URI list)i-zMoved Permanently�(Object moved permanently -- see URI list)i.ZFound�(Object moved temporarily -- see URI list)i/z	See Otherz'Object moved -- see Method and URL list)i0zNot Modifiedz)Document has not changed since given time)i1z	Use Proxyz@You must use proxy specified in Location to access this resource)i3zTemporary Redirectr)i4zPermanent Redirectr)i�zBad Requestz(Bad request syntax or unsupported method)i�ZUnauthorizedz*No permission -- see authorization schemes)i�zPayment Requiredz"No payment -- see charging schemes)i�Z	Forbiddenz0Request forbidden -- authorization will not help)i�z	Not FoundzNothing matches the given URI)i�zMethod Not Allowedz-Specified method is invalid for this resource)i�zNot Acceptablez%URI not available in preferred format)i�zProxy Authentication Requiredz7You must authenticate with this proxy before proceeding)i�zRequest Timeoutz"Request timed out; try again later)i�ZConflictzRequest conflict)i�ZGonez5URI no longer exists and has been permanently removed)i�zLength Requiredz"Client must specify Content-Length)i�zPrecondition Failedz Precondition in headers is false)i�zRequest Entity Too LargezEntity is too large)i�zRequest-URI Too LongzURI is too long)i�zUnsupported Media Typez!Entity body in unsupported format)i�zRequested Range Not SatisfiablezCannot satisfy request range)i�zExpectation Failedz'Expect condition could not be satisfied)i�zMisdirected Requestz(Server is not able to produce a response)i�zUnprocessable Entity)i�ZLocked)i�zFailed Dependency)i�zUpgrade Required)i�zPrecondition Requiredz8The origin server requires the request to be conditional)i�zToo Many RequestszOThe user has sent too many requests in a given amount of time ("rate limiting"))i�zRequest Header Fields Too LargezVThe server is unwilling to process the request because its header fields are too large)i�zUnavailable For Legal ReasonszOThe server is denying access to the resource as a consequence of a legal demand)i�zInternal Server ErrorzServer got itself in trouble)i�zNot Implementedz&Server does not support this operation)i�zBad Gatewayz+Invalid responses from another server/proxy)i�zService Unavailablez8The server cannot process the request due to a high load)i�zGateway Timeoutz4The gateway server did not receive a timely response)i�zHTTP Version Not SupportedzCannot fulfill request)i�zVariant Also Negotiates)i�zInsufficient Storage)i�z
Loop Detected)i�zNot Extended)i�zNetwork Authentication Requiredz7The client needs to authenticate to gain network accessN)r)?�__name__�
__module__�__qualname__rZCONTINUEZSWITCHING_PROTOCOLSZ
PROCESSINGrZCREATEDZACCEPTEDZNON_AUTHORITATIVE_INFORMATIONZ
NO_CONTENTZ
RESET_CONTENTZPARTIAL_CONTENTZMULTI_STATUSZALREADY_REPORTEDZIM_USEDZMULTIPLE_CHOICESZMOVED_PERMANENTLYZFOUNDZ	SEE_OTHERZNOT_MODIFIEDZ	USE_PROXYZTEMPORARY_REDIRECTZPERMANENT_REDIRECTZBAD_REQUESTZUNAUTHORIZEDZPAYMENT_REQUIREDZ	FORBIDDENZ	NOT_FOUNDZMETHOD_NOT_ALLOWEDZNOT_ACCEPTABLEZPROXY_AUTHENTICATION_REQUIREDZREQUEST_TIMEOUTZCONFLICTZGONEZLENGTH_REQUIREDZPRECONDITION_FAILEDZREQUEST_ENTITY_TOO_LARGEZREQUEST_URI_TOO_LONGZUNSUPPORTED_MEDIA_TYPEZREQUESTED_RANGE_NOT_SATISFIABLEZEXPECTATION_FAILEDZMISDIRECTED_REQUESTZUNPROCESSABLE_ENTITYZLOCKEDZFAILED_DEPENDENCYZUPGRADE_REQUIREDZPRECONDITION_REQUIREDZTOO_MANY_REQUESTSZREQUEST_HEADER_FIELDS_TOO_LARGEZUNAVAILABLE_FOR_LEGAL_REASONSZINTERNAL_SERVER_ERRORZNOT_IMPLEMENTEDZBAD_GATEWAYZSERVICE_UNAVAILABLEZGATEWAY_TIMEOUTZHTTP_VERSION_NOT_SUPPORTEDZVARIANT_ALSO_NEGOTIATESZINSUFFICIENT_STORAGEZ
LOOP_DETECTEDZNOT_EXTENDEDZNETWORK_AUTHENTICATION_REQUIREDr
r
r
rrsx
	N)�enumr�__all__rr
r
r
r�<module>s__pycache__/cookiejar.cpython-38.opt-1.pyc000064400000150304150532417300014314 0ustar00U

e5d#,�@sdZddddddddgZd	d
lZd	d
lZd	d
lZd	d
lZd	d
lZd	d
lZd	d
l	Zd	d
l
Zd	d
lZ
d	dlmZdZd
ad
d�Zee
jj�ZdZdd�ZdZdd�ZdddddddgZddddd d!d"d#d$d%d&d'gZgZeD]Ze�e� ��q�dud(d)�Z!dvd*d+�Z"d
d
d
d
d,�Z#e�$d-ej%�Z&d.d/�Z'd0d1�Z(e�$d2ej%�Z)e�$d3ej*ej%B�Z+e�$d4ej,ej%B�Z-d5d6�Z.e�$d7ej,ej%B�Z/d8d9�Z0d:d;�Z1e�$d<�Z2e�$d=�Z3e�$d>�Z4e�$d?�Z5d@dA�Z6e�$dB�Z7dCdD�Z8dEdF�Z9dGdH�Z:e�$dIej%�Z;dJdK�Z<dLdM�Z=dNdO�Z>dPdQ�Z?e�$dRej%�Z@dSdT�ZAdUdV�ZBdWdX�ZCdYdZ�ZDd[ZEe�$d\�ZFd]d^�ZGd_d`�ZHdadb�ZIdcdd�ZJGded�d�ZKGdfd�d�ZLGdgd�deL�ZMdhdi�ZNdjdk�ZOGdldm�dm�ZPGdnd�d�ZQGdod�deR�ZSGdpd�deQ�ZTdqdr�ZUGdsd�deT�ZVGdtd�deT�ZWd
S)wa�HTTP cookie handling for web clients.

This module has (now fairly distant) origins in Gisle Aas' Perl module
HTTP::Cookies, from the libwww-perl library.

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 BSDDBCookieJar and the MSIE* classes are not
distributed with the Python standard library, but are available from
http://wwwsearch.sf.net/):

                        CookieJar____
                        /     \      \
            FileCookieJar      \      \
             /    |   \         \      \
 MozillaCookieJar | LWPCookieJar \      \
                  |               |      \
                  |   ---MSIEBase |       \
                  |  /      |     |        \
                  | /   MSIEDBCookieJar BSDDBCookieJar
                  |/
               MSIECookieJar

�Cookie�	CookieJar�CookiePolicy�DefaultCookiePolicy�
FileCookieJar�LWPCookieJar�	LoadError�MozillaCookieJar�N)�timegmFcGs(tsdStsddl}|�d�atj|�S)Nr	zhttp.cookiejar)�debug�logger�loggingZ	getLogger)�argsr
�r�&/usr/lib64/python3.8/http/cookiejar.py�_debug,s
rzQa filename was not supplied (nor was the CookieJar instance initialised with one)cCsJddl}ddl}ddl}|��}|�d|�|��}|jd|dd�dS)Nr	zhttp.cookiejar bug!
%s�)�
stacklevel)�io�warnings�	traceback�StringIO�	print_exc�getvalue�warn)rrr�f�msgrrr�_warn_unhandled_exception:s
ri�cCs�|dd�\}}}}}}|tkr�d|kr4dkr�nnhd|krLdkr�nnPd|krddkr�nn8d|kr|dkr�nn d|kr�dkr�nnt|�SdSdS)	N����r	��;�=)�
EPOCH_YEARr
)�tt�year�monthZmday�hour�min�secrrr�_timegmIs&8��
��
��
r,ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs@|dkrtj��}ntj�|�}d|j|j|j|j|j|jfS)aHReturn a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like "YYYY-MM-DD hh:mm:ssZ",
    representing Universal Time (UTC, aka GMT).  An example of this format is:

    1994-11-24 08:49:37Z

    Nz%04d-%02d-%02d %02d:%02d:%02dZ)	�datetime�utcnow�utcfromtimestampr'r(�dayr)�minute�second��tZdtrrr�	time2isozWs�r5cCsR|dkrtj��}ntj�|�}dt|��|jt|jd|j|j	|j
|jfS)z�Return a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like this:

    Wed, DD-Mon-YYYY HH:MM:SS GMT

    Nz#%s, %02d-%s-%04d %02d:%02d:%02d GMTr)r-r.r/�DAYSZweekdayr0�MONTHSr(r'r)r1r2r3rrr�
time2netscapejs
�r8)ZGMT�UTCZUT�Zz^([-+])?(\d\d?):?(\d\d)?$cCsjd}|tkrd}nTt�|�}|rfdt|�d��}|�d�rR|dt|�d��}|�d�dkrf|}|S)Nr	ir��<r�-)�	UTC_ZONES�TIMEZONE_RE�search�int�group)�tz�offset�mrrr�offset_from_tz_string�s

rFc
Cs�t|�}|tjkrdSzt�|���d}Wn^tk
r�zt|�}Wntk
r`YYdSXd|krvdkr�nn|}nYdSYnX|dkr�d}|dkr�d}|dkr�d}t|�}t|�}t|�}t|�}|dk�r6t�t���d}|d}	|}
|||	}|	|
}	t	|	�dk�r6|	dk�r.|d}n|d}t
|||||||f�}|dk	�r�|dk�rdd}|��}t|�}|dk�r�dS||}|S)Nrr r	i��d�2r9)
rAr-ZMAXYEAR�MONTHS_LOWER�index�lower�
ValueError�time�	localtime�absr,�upperrF)
r0�mon�yr�hrr*r+rCZimonZcur_yrrEZtmpr4rDrrr�	_str2time�sV







rTzV^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$z+^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*a�^
    (\d\d?)            # day
       (?:\s+|[-\/])
    (\w+)              # month
        (?:\s+|[-\/])
    (\d+)              # year
    (?:
          (?:\s+|:)    # separator before clock
       (\d\d?):(\d\d)  # hour:min
       (?::(\d\d))?    # optional seconds
    )?                 # optional clock
       \s*
    (?:
       ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+) # timezone
       \s*
    )?
    (?:
       \(\w+\)         # ASCII representation of timezone in parens.
       \s*
    )?$cCs�t�|�}|rl|��}t�|d���d}t|d�|t|d�t|d�t|d�t|d�f}t|�S|�	�}t
�d|d�}dgd	\}}}}}}	}
t�|�}|dk	r�|��\}}}}}}	}
ndSt
||||||	|
�S)
a�Returns time in seconds since epoch of time represented by a string.

    Return value is an integer.

    None is returned if the format of str is unrecognized, the time is outside
    the representable range, or the timezone string is not recognized.  If the
    string contains no timezone, UTC is assumed.

    The timezone in the string may be numerical (like "-0800" or "+0100") or a
    string timezone (like "UTC", "GMT", "BST" or "EST").  Currently, only the
    timezone strings equivalent to UTC (zero offset) are known to the function.

    The function loosely parses the following formats:

    Wed, 09 Feb 1994 22:23:32 GMT       -- HTTP format
    Tuesday, 08-Feb-94 14:15:29 GMT     -- old rfc850 HTTP format
    Tuesday, 08-Feb-1994 14:15:29 GMT   -- broken rfc850 HTTP format
    09 Feb 1994 22:23:32 GMT            -- HTTP format (no weekday)
    08-Feb-94 14:15:29 GMT              -- rfc850 format (no weekday)
    08-Feb-1994 14:15:29 GMT            -- broken rfc850 format (no weekday)

    The parser ignores leading and trailing whitespace.  The time may be
    absent.

    If the year is given with only 2 digits, the function will select the
    century that makes the year closest to the current date.

    rrr	r;���N�)�STRICT_DATE_REr@�groupsrIrJrKrA�floatr,�lstrip�
WEEKDAY_RE�sub�LOOSE_HTTP_DATE_RErT)�textrE�grQr&r0rRrSr*r+rCrrr�	http2time�s$



�
rba�^
    (\d{4})              # year
       [-\/]?
    (\d\d?)              # numerical month
       [-\/]?
    (\d\d?)              # day
   (?:
         (?:\s+|[-:Tt])  # separator before clock
      (\d\d?):?(\d\d)    # hour:min
      (?::?(\d\d(?:\.\d*)?))?  # optional seconds (and fractional)
   )?                    # optional clock
      \s*
   (?:
      ([-+]?\d\d?:?(:?\d\d)?
       |Z|z)             # timezone  (Z is "zero meridian", i.e. GMT)
      \s*
   )?$c
Csd|��}dgd\}}}}}}}t�|�}|dk	rL|��\}}}}}}}}	ndSt|||||||�S)av
    As for http2time, but parses the ISO 8601 formats:

    1994-02-03 14:15:29 -0100    -- ISO 8601 format
    1994-02-03 14:15:29          -- zone is optional
    1994-02-03                   -- only date
    1994-02-03T14:15:29          -- Use T as separator
    19940203T141529Z             -- ISO 8601 compact format
    19940203                     -- only date

    NrX)r\�ISO_DATE_REr@rZrT)
r`r0rQrRrSr*r+rCrE�_rrr�iso2time+s

recCs*|�d�\}}|jd|�|j|d�S)z)Return unmatched part of re.Match object.r	N)�span�string)�match�start�endrrr�	unmatchedLsrkz^\s*([^=\s;,]+)z&^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"z^\s*=\s*([^\s;,]*)z\\(.)c
Csg}|D]�}|}g}|r�t�|�}|r�t|�}|�d�}t�|�}|rft|�}|�d�}t�d|�}n.t�|�}|r�t|�}|�d�}|��}nd}|�	||f�q|�
��d�r�|�
�dd�}|r�|�	|�g}qt�
dd|�\}}	|}q|r|�	|�q|S)amParse header values into a list of lists containing key,value pairs.

    The function knows how to deal with ",", ";" and "=" as well as quoted
    values after "=".  A list of space separated tokens are parsed as if they
    were separated by ";".

    If the header_values passed as argument contains multiple values, then they
    are treated as if they were a single value separated by comma ",".

    This means that this function is useful for parsing header fields that
    follow this syntax (BNF as from the HTTP/1.1 specification, but we relax
    the requirement for tokens).

      headers           = #header
      header            = (token | parameter) *( [";"] (token | parameter))

      token             = 1*<any CHAR except CTLs or separators>
      separators        = "(" | ")" | "<" | ">" | "@"
                        | "," | ";" | ":" | "\" | <">
                        | "/" | "[" | "]" | "?" | "="
                        | "{" | "}" | SP | HT

      quoted-string     = ( <"> *(qdtext | quoted-pair ) <"> )
      qdtext            = <any TEXT except <">>
      quoted-pair       = "\" CHAR

      parameter         = attribute "=" value
      attribute         = token
      value             = token | quoted-string

    Each header is represented by a list of key/value pairs.  The value for a
    simple token (not part of a parameter) is None.  Syntactically incorrect
    headers will not necessarily be parsed as you would want.

    This is easier to describe with some examples:

    >>> split_header_words(['foo="bar"; port="80,81"; discard, bar=baz'])
    [[('foo', 'bar'), ('port', '80,81'), ('discard', None)], [('bar', 'baz')]]
    >>> split_header_words(['text/html; charset="iso-8859-1"'])
    [[('text/html', None), ('charset', 'iso-8859-1')]]
    >>> split_header_words([r'Basic realm="\"foo\bar\""'])
    [[('Basic', None), ('realm', '"foobar"')]]

    rz\1N�,z^[=\s;]*rW)�HEADER_TOKEN_REr@rkrB�HEADER_QUOTED_VALUE_RE�HEADER_ESCAPE_REr^�HEADER_VALUE_RE�rstrip�appendr\�
startswith�re�subn)
Z
header_values�resultr`Z	orig_text�pairsrE�name�valueZnon_junkZ
nr_junk_charsrrr�split_header_wordsUs>.







rz�([\"\\])cCs|g}|D]h}g}|D]F\}}|dk	rPt�d|�sDt�d|�}d|}d||f}|�|�q|r|�d�|��qd�|�S)a�Do the inverse (almost) of the conversion done by split_header_words.

    Takes a list of lists of (key, value) pairs and produces a single header
    value.  Attribute values are quoted if needed.

    >>> join_header_words([[("text/plain", None), ("charset", "iso-8859-1")]])
    'text/plain; charset="iso-8859-1"'
    >>> join_header_words([[("text/plain", None)], [("charset", "iso-8859-1")]])
    'text/plain, charset="iso-8859-1"'

    Nz^\w+$�\\\1z"%s"�%s=%s�; �, )rtr@�HEADER_JOIN_ESCAPE_REr^rr�join)Zlists�headersrw�attr�k�vrrr�join_header_words�sr�cCs0|�d�r|dd�}|�d�r,|dd�}|S)N�"r���)rs�endswith�r`rrr�strip_quotes�s


r�cCs�d}g}|D]�}g}d}t|�d��D]�\}}|��}|�d�\}}	}
|��}|sb|dkr&q�nq&|	rn|
��nd}
|dkr�|��}||kr�|}|dkr�|
dk	r�t|
�}
d}n|d	kr�|
dk	r�tt|
��}
|�||
f�q&|r|s�|�d
�|�|�q|S)a5Ad-hoc parser for Netscape protocol cookie-attributes.

    The old Netscape cookie format for Set-Cookie can for instance contain
    an unquoted "," in the expires field, so we have to use this ad-hoc
    parser instead of split_header_words.

    XXX This may not make the best possible effort to parse all the crap
    that Netscape Cookie headers contain.  Ronald Tschalar's HTTPClient
    parser is probably better, so could do worse than following that if
    this ever gives any trouble.

    Currently, this is also used for parsing RFC 2109 cookies.

    )�expires�domain�path�secure�version�port�max-ageF�;�=r	Nr�Tr�)r��0)�	enumerate�split�strip�	partitionrKr�rbrr)Z
ns_headersZknown_attrsrvZ	ns_headerrw�version_setZiiZparam�key�sep�val�lcrrr�parse_ns_headers�s>
r�z\.\d+$cCs:t�|�rdS|dkrdS|ddks2|ddkr6dSdS)z*Return True if text is a host domain name.FrWr	�.r�T��IPV4_REr@r�rrr�is_HDNs
r�cCsl|��}|��}||krdSt|�s(dS|�|�}|dksB|dkrFdS|�d�sTdSt|dd��shdSdS)a�Return True if domain A domain-matches domain B, according to RFC 2965.

    A and B may be host domain names or IP addresses.

    RFC 2965, section 1:

    Host names can be specified either as an IP address or a HDN string.
    Sometimes we compare one host name with another.  (Such comparisons SHALL
    be case-insensitive.)  Host A's name domain-matches host B's if

         *  their host name strings string-compare equal; or

         * A is a HDN string and has the form NB, where N is a non-empty
            name string, B has the form .B', and B' is a HDN string.  (So,
            x.y.com domain-matches .Y.com but not Y.com.)

    Note that domain-match is not a commutative operation: a.b.c.com
    domain-matches .c.com, but not the reverse.

    TFr�r	r�rN)rKr��rfindrs)�A�B�irrr�domain_matchs

r�cCst�|�rdSdS)zdReturn True if text is a sort-of-like a host domain name.

    For accepting/blocking domains.

    FTr�r�rrr�liberal_is_HDNFs
r�cCs`|��}|��}t|�r t|�s0||kr,dSdS|�d�}|rL|�|�rLdS|s\||kr\dSdS)z\For blocking/accepting domains.

    A and B may be host domain names or IP addresses.

    TFr�)rKr�rsr�)r�r��initial_dotrrr�user_domain_matchPs
r�z:\d+$cCsB|��}tj�|�d}|dkr,|�dd�}t�d|d�}|��S)z�Return request-host, as defined by RFC 2965.

    Variation from RFC: returned value is lowercased, for convenient
    comparison.

    rrWZHost)�get_full_url�urllib�parseZurlparseZ
get_header�cut_port_rer^rK)�request�url�hostrrr�request_hostesr�cCs4t|�}}|�d�dkr,t�|�s,|d}||fS)zzReturn a tuple (request-host, effective request-host name).

    As defined by RFC 2965, except both are lowercased.

    r�r��.local)r��findr�r@)r��erhn�req_hostrrr�eff_request_hostusr�cCs4|��}tj�|�}t|j�}|�d�s0d|}|S)z6Path component of request-URI, as defined by RFC 2965.�/)r�r�r�Zurlsplit�escape_pathr�rs)r�r��partsr�rrr�request_path�s

r�cCs`|j}|�d�}|dkrX||dd�}zt|�Wq\tk
rTtd|�YdSXnt}|S)N�:r	rznonnumeric port: '%s')r�r�rArLr�DEFAULT_HTTP_PORT)r�r�r�r�rrr�request_port�s


r�z%/;:@&=+$,!~*'()z%([0-9a-fA-F][0-9a-fA-F])cCsd|�d���S)Nz%%%sr)rBrP)rhrrr�uppercase_escaped_char�sr�cCstj�|t�}t�t|�}|S)zEEscape any invalid characters in HTTP URL, and uppercase all escapes.)r�r�Zquote�HTTP_PATH_SAFE�ESCAPED_CHAR_REr^r�)r�rrrr��s
r�cCsP|�d�}|dkrL||dd�}|�d�}t|�rL|dksD|dkrLd|S|S)aBReturn reach of host h, as defined by RFC 2965, section 1.

    The reach R of a host name H is defined as follows:

       *  If

          -  H is the host domain name of a host; and,

          -  H has the form A.B; and

          -  A has no embedded (that is, interior) dots; and

          -  B has at least one embedded dot, or B is the string "local".
             then the reach of H is .B.

       *  Otherwise, the reach of H is H.

    >>> reach("www.acme.com")
    '.acme.com'
    >>> reach("acme.com")
    'acme.com'
    >>> reach("acme.local")
    '.local'

    r�r	rNZlocal)r�r�)�hr��brrr�reach�s

r�cCs$t|�}t|t|j��sdSdSdS)z�

    RFC 2965, section 3.3.6:

        An unverifiable transaction is to a third-party host if its request-
        host U does not domain-match the reach R of the request-host O in the
        origin transaction.

    TFN)r�r�r�Zorigin_req_host)r�r�rrr�is_third_party�s
r�c@sNeZdZdZddd�Zdd�Zddd	�Zd
d�Zddd
�Zdd�Z	dd�Z
dS)ra�HTTP Cookie.

    This class represents both Netscape and RFC 2965 cookies.

    This is deliberately a very simple class.  It just holds attributes.  It's
    possible to construct Cookie instances that don't comply with the cookie
    standards.  CookieJar.make_cookies is the factory function for Cookie
    objects -- it deals with cookie parsing, supplying defaults, and
    normalising to the representation used in this class.  CookiePolicy is
    responsible for checking them to see whether they should be accepted from
    and returned to the server.

    Note that the port may be present in the headers, but unspecified ("Port"
    rather than"Port=80", for example); if this is the case, port is None.

    FcCs�|dk	rt|�}|dk	r$tt|��}|dkr<|dkr<td��||_||_||_||_||_|��|_	||_
||_|	|_|
|_
||_||_|
|_||_||_||_t�|�|_dS)NTz-if port is None, port_specified must be false)rAr[rLr�rxryr��port_specifiedrKr��domain_specified�domain_initial_dotr��path_specifiedr�r��discard�comment�comment_url�rfc2109�copy�_rest)�selfr�rxryr�r�r�r�r�r�r�r�r�r�r�r��restr�rrr�__init__�s.

zCookie.__init__cCs
||jkS�N�r�)r�rxrrr�has_nonstandard_attrszCookie.has_nonstandard_attrNcCs|j�||�Sr�)r��get)r�rx�defaultrrr�get_nonstandard_attrszCookie.get_nonstandard_attrcCs||j|<dSr�r�)r�rxryrrr�set_nonstandard_attr szCookie.set_nonstandard_attrcCs,|dkrt��}|jdk	r(|j|kr(dSdS�NTF)rMr�)r��nowrrr�
is_expired#s
zCookie.is_expiredcCsX|jdkrd}n
d|j}|j||j}|jdk	rFd|j|jf}n|j}d||fS)NrWr�r}z<Cookie %s for %s>)r�r�r�ryrx)r��p�limitZ	namevaluerrr�__str__)s


zCookie.__str__cCslg}dD]$}t||�}|�d|t|�f�q|�dt|j��|�dt|j��d|jjd�|�fS)N)r�rxryr�r�r�r�r�r�r�r�r�r�r�r�r}zrest=%sz
rfc2109=%sz%s(%s)r)�getattrrr�reprr�r��	__class__�__name__r�)r�rrxr�rrr�__repr__3s
zCookie.__repr__)F)N)N)r��
__module__�__qualname__�__doc__r�r�r�r�r�r�r�rrrrr�s�
*


c@s0eZdZdZdd�Zdd�Zdd�Zdd	�Zd
S)ra Defines which cookies get accepted from and returned to server.

    May also modify cookies, though this is probably a bad idea.

    The subclass DefaultCookiePolicy defines the standard rules for Netscape
    and RFC 2965 cookies -- override that if you want a customized policy.

    cCs
t��dS)z�Return true if (and only if) cookie should be accepted from server.

        Currently, pre-expired cookies never get this far -- the CookieJar
        class deletes such cookies itself.

        N��NotImplementedError�r��cookier�rrr�set_okKszCookiePolicy.set_okcCs
t��dS)zAReturn true if (and only if) cookie should be returned to server.Nr�r�rrr�	return_okTszCookiePolicy.return_okcCsdS)zMReturn false if cookies should not be returned, given cookie domain.
        Tr)r�r�r�rrr�domain_return_okXszCookiePolicy.domain_return_okcCsdS)zKReturn false if cookies should not be returned, given cookie path.
        Tr)r�r�r�rrr�path_return_ok]szCookiePolicy.path_return_okN)r�r�r�r�r�r�r�r�rrrrrBs
	c
@s�eZdZdZdZdZdZdZeeBZdddddddddeddd	f
d
d�Z	dd
�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Zd2d3�Zd4d5�Zd6d7�ZdS)8rzBImplements the standard rules for accepting and returning cookies.rrrUr	NTF)ZhttpsZwsscCsv||_||_||_||_||_||_|	|_|
|_||_||_	|
|_
|dk	rVt|�|_nd|_|dk	rlt|�}||_
dS)zAConstructor arguments should be passed as keyword arguments only.Nr)�netscape�rfc2965�rfc2109_as_netscape�hide_cookie2�
strict_domain�strict_rfc2965_unverifiable�strict_ns_unverifiable�strict_ns_domain�strict_ns_set_initial_dollar�strict_ns_set_path�secure_protocols�tuple�_blocked_domains�_allowed_domains)r��blocked_domains�allowed_domainsr�r�r�r�r�r�r�r�r�r�r�rrrr�ms"zDefaultCookiePolicy.__init__cCs|jS)z4Return the sequence of blocked domains (as a tuple).)r��r�rrrr��sz#DefaultCookiePolicy.blocked_domainscCst|�|_dS)z$Set the sequence of blocked domains.N)r�r�)r�r�rrr�set_blocked_domains�sz'DefaultCookiePolicy.set_blocked_domainscCs |jD]}t||�rdSqdSr�)r�r�)r�r�Zblocked_domainrrr�
is_blocked�s

zDefaultCookiePolicy.is_blockedcCs|jS)z=Return None, or the sequence of allowed domains (as a tuple).)r�rrrrr�sz#DefaultCookiePolicy.allowed_domainscCs|dk	rt|�}||_dS)z-Set the sequence of allowed domains, or None.N)r�r�)r�rrrr�set_allowed_domains�sz'DefaultCookiePolicy.set_allowed_domainscCs.|jdkrdS|jD]}t||�rdSqdS)NFT)r�r�)r�r�Zallowed_domainrrr�is_not_allowed�s


z"DefaultCookiePolicy.is_not_allowedcCs@td|j|j�dD]&}d|}t||�}|||�sdSqdS)z�
        If you override .set_ok(), be sure to call this method.  If it returns
        false, so should your subclass (assuming your subclass wants to be more
        strict about which cookies to accept).

        � - checking cookie %s=%s)r��
verifiabilityrxr�r�r�Zset_ok_FT�rrxryr��r�r�r��nZfn_name�fnrrrr��s

zDefaultCookiePolicy.set_okcCsZ|jdkrtd|j|j�dS|jdkr:|js:td�dS|jdkrV|jsVtd�dSdS)Nz0   Set-Cookie2 without version attribute (%s=%s)Fr	�$   RFC 2965 cookies are switched off�$   Netscape cookies are switched offT)r�rrxryr�r�r�rrr�set_ok_version�s
�z"DefaultCookiePolicy.set_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS�Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT�Zunverifiabler�r�r�rr�r�rrr�set_ok_verifiability�sz(DefaultCookiePolicy.set_ok_verifiabilitycCs0|jdkr,|jr,|j�d�r,td|j�dSdS)Nr	�$z'   illegal name (starts with '$'): '%s'FT)r�r�rxrsrr�rrr�set_ok_name�s
�zDefaultCookiePolicy.set_ok_namecCsL|jrHt|�}|jdks(|jdkrH|jrH|�|j|�sHtd|j|�dSdS)Nr	z7   path attribute %s is not a prefix of request path %sFT)r�r�r�r�r�r�r)r�r�r��req_pathrrr�set_ok_path�s
����zDefaultCookiePolicy.set_ok_pathc
Cs�|�|j�rtd|j�dS|�|j�r8td|j�dS|j�r�t|�\}}|j}|jr�|�d�dkr�|�d�}|�dd|�}|dkr�||dd�}||d|�}	|	�	�dkr�t
|�dkr�td	|�dS|�d�r�|dd�}
n|}
|
�d�dk}|�s|d
k�rtd|�dS|j
dk�rX|�|��sX|�d��sXd|�|��sXtd||�dS|j
dk�sr|j|j@�r�t||��s�td
||�dS|j
dk�s�|j|j@�r�|dt
|��}|�d�dk�r�t�|��s�td||�dSdS)N�"   domain %s is in user block-listF�&   domain %s is not in user allow-listr�rr	r)�coZacZcomZeduZorgZnetZgovZmilrAZaeroZbiz�catZcoop�infoZjobsZmobiZmuseumrxZproZtravelZeuz&   country-code second level domain %sr�z/   non-local domain %s contains no embedded dotzO   effective request-host %s (even with added initial dot) does not end with %sz5   effective request-host %s does not domain-match %sz.   host prefix %s for domain %s contains a dotT)rr�rrr�r�r��countr�rK�lenrsr�r�r�r��DomainRFC2965Matchr��DomainStrictNoDotsr�r@)
r�r�r�r�r�r�r��jZtldZsldZundotted_domainZ
embedded_dotsZhost_prefixrrr�
set_ok_domain�s|

�

����
��
���z!DefaultCookiePolicy.set_ok_domainc	Cs�|jr�t|�}|dkrd}nt|�}|j�d�D]@}zt|�Wn"tk
rbtd|�YdSX||kr0q�q0td||j�dSdS)N�80rlz   bad port %s (not numeric)Fz$   request port (%s) not found in %sT)r�r��strr�r�rArLr�r�r�r�Zreq_portr�rrr�set_ok_port+s&

�zDefaultCookiePolicy.set_ok_portcCs@td|j|j�dD]&}d|}t||�}|||�sdSqdS)z�
        If you override .return_ok(), be sure to call this method.  If it
        returns false, so should your subclass (assuming your subclass wants to
        be more strict about which cookies to return).

        r)r�rr�r�r�r�Z
return_ok_FTrr	rrrr�@s	

zDefaultCookiePolicy.return_okcCs<|jdkr|jstd�dS|jdkr8|js8td�dSdS)Nr	rFr
T)r�r�rr�r�rrr�return_ok_versionRsz%DefaultCookiePolicy.return_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdSrrr�rrr�return_ok_verifiability[sz+DefaultCookiePolicy.return_ok_verifiabilitycCs"|jr|j|jkrtd�dSdS)Nz(   secure cookie with non-secure requestFT)r��typer�rr�rrr�return_ok_securegsz$DefaultCookiePolicy.return_ok_securecCs|�|j�rtd�dSdS)Nz   cookie expiredFT)r��_nowrr�rrr�return_ok_expiresmsz%DefaultCookiePolicy.return_ok_expirescCsN|jrJt|�}|dkrd}|j�d�D]}||kr&qJq&td||j�dSdS)Nr!rlz0   request port %s does not match cookie port %sFT)r�r�r�rr#rrr�return_ok_portss�z"DefaultCookiePolicy.return_ok_portcCs�t|�\}}|j}|r*|�d�s*d|}n|}|jdkr^|j|j@r^|js^||kr^td�dS|jdkr�t||�s�td||�dS|jdkr�d|�	|�s�td||�dSdS)Nr�r	zQ   cookie with unspecified domain does not string-compare equal to request domainFzQ   effective request-host name %s does not domain-match RFC 2965 cookie domain %sz;   request-host %s does not match Netscape cookie domain %sT)
r�r�rsr�r��DomainStrictNonDomainr�rr�r�)r�r�r�r�r�r��	dotdomainrrr�return_ok_domain�s6


�����z$DefaultCookiePolicy.return_ok_domaincCs�t|�\}}|�d�sd|}|�d�s0d|}|rH|�d�sHd|}n|}|�|�sd|�|�sddS|�|�r|td|�dS|�|�r�td|�dSdS)Nr�FrrT)r�rsr�rrr)r�r�r�r�r�r-rrrr��s"






z$DefaultCookiePolicy.domain_return_okcCsbtd|�t|�}t|�}||kr&dS|�|�rR|�d�sN|||d�dkrRdStd||�dS)Nz- checking cookie path=%sTr�rz  %s does not path-match %sF)rr�rrsr�)r�r�r�rZpathlenrrrr��s

��z"DefaultCookiePolicy.path_return_ok) r�r�r�r�rr,rZ
DomainLiberalZDomainStrictr�r�rrrrrr�rrrrr r$r�r%r&r(r*r+r.r�r�rrrrrcsT�
#	;	cCst|���}t|j|�Sr�)�sorted�keys�mapr�)Zadictr0rrr�vals_sorted_by_key�sr2c	csVt|�}|D]D}d}z
|jWntk
r2YnXd}t|�EdH|s|VqdS)zBIterates over nested mapping, depth-first, in sorted order by key.FTN)r2�items�AttributeError�
deepvalues)�mapping�values�objrrrr5�s
r5c@seZdZdS)�AbsentN�r�r�r�rrrrr9�sr9c@s�eZdZdZe�d�Ze�d�Ze�d�Ze�d�Z	e�d�Z
e�dej�Zd3d	d
�Z
dd�Zd
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd4d%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Z d1d2�Z!dS)5rz�Collection of HTTP cookies.

    You may not need to know about this class: try
    urllib.request.build_opener(HTTPCookieProcessor).open(url).
    z\Wr{z\.?[^.]*z[^.]*z^\.+z^\#LWP-Cookies-(\d+\.\d+)NcCs(|dkrt�}||_t��|_i|_dSr�)r�_policy�
_threading�RLock�
_cookies_lock�_cookies�r��policyrrrr��s

zCookieJar.__init__cCs
||_dSr�)r;r@rrr�
set_policy�szCookieJar.set_policycCs�g}|j�||�sgStd|�|j|}|��D]T}|j�||�sFq2||}|��D].}|j�||�srtd�qVtd�|�|�qVq2|S)Nz!Checking %s for cookies to returnz   not returning cookiez   it's a match)	r;r�rr?r0r�r7r�rr)r�r�r��cookiesZcookies_by_pathr�Zcookies_by_namer�rrr�_cookies_for_domain�s 

zCookieJar._cookies_for_domaincCs*g}|j��D]}|�|�||��q|S)z2Return a list of cookies to be returned to server.)r?r0�extendrD)r�r�rCr�rrr�_cookies_for_requestszCookieJar._cookies_for_requestc	Cs<|jdd�dd�d}g}|D�]}|j}|sHd}|dkrH|�d|�|jdk	rz|j�|j�rz|dkrz|j�d	|j�}n|j}|jdkr�|�|j�n|�d
|j|f�|dkr|j	r�|�d|j
�|j�d��r|j}|j
s�|�d�r�|d
d�}|�d|�|jdk	rd}|j�r,|d|j}|�|�q|S)z�Return a list of cookie-attributes to be returned to server.

        like ['foo="bar"; $Path="/"', ...]

        The $Version attribute is also added when appropriate (currently only
        once per request).

        cSs
t|j�Sr�)rr�)�arrr�<lambda>�z)CookieJar._cookie_attrs.<locals>.<lambda>T)r��reverseFr	z$Version=%sNr|r}z
$Path="%s"r�rz$Domain="%s"z$Portz="%s")�sortr�rrry�non_word_rer@�quote_rer^rxr�r�r�rsr�r�r�)	r�rCr��attrsr�r�ryr�r�rrr�
_cookie_attrssF


��
�
zCookieJar._cookie_attrscCs�td�|j��z�tt���|j_|_|�|�}|�	|�}|r^|�
d�s^|�dd�|��|jj
r�|jjs�|�
d�s�|D]}|jdkr||�dd�q�q|W5|j��X|��dS)z�Add correct Cookie: header to request (urllib.request.Request object).

        The Cookie2 header is also added unless policy.hide_cookie2 is true.

        �add_cookie_headerrr~ZCookie2rz$Version="1"N)rr>�acquire�releaserArMr;r)rFrOZ
has_headerZadd_unredirected_headerr�r�r�r��clear_expired_cookies)r�r�rCrNr�rrrrPIs*



��

zCookieJar.add_cookie_headerc
Cs�g}d}d}|D�]z}|d\}}d}d}	i}
i}|dd�D�]0\}}
|��}||ks`||krd|}||krx|
dkrxd}
||
kr�q>|dkr�|
dkr�td	�d}	�qr|
��}
|d
kr�|r�q>|
dkr�td�q>|dk�r d}zt|
�}
Wn*tk
�rtd
�d}	Y�qrYnXd
}|j|
}
||k�s4||k�rh|
dk�r^|dk�r^td|�d}	�qr|
|
|<q>|
||<q>|	�rzq|�|||
|f�q|S)aReturn 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.

        )r�r�)r�r�r�r�r�r�r��
commenturlr	FrNTr�z%   missing value for domain attributer�zM   missing or invalid value for expires attribute: treating as session cookier�z?   missing or invalid (non-numeric) value for max-age attribute)r�r�rTz!   missing value for %s attribute)rKrrArLr)rr)r��	attrs_set�
cookie_tuples�
boolean_attrs�value_attrsZcookie_attrsrxryZmax_age_setZ
bad_cookie�standardr�r�r�r�rrr�_normalized_cookie_tuplesjsh





�

z#CookieJar._normalized_cookie_tuplescCs&|\}}}}|�dt�}|�dt�}|�dt�}	|�dt�}
|�dd�}|dk	rtzt|�}Wntk
rrYdSX|�dd�}|�dd�}
|�d	d�}|�d
d�}|tk	r�|dkr�d}t|�}nXd}t|�}|�d
�}|dk�r|dkr�|d|�}n|d|d�}t|�dk�rd
}|tk	}d}|�r:t|�	d��}|tk�rVt
|�\}}|}n|�	d��sjd|}d}|	tk	�r�|	dk�r�t|�}	nd}t�
dd|	�}	nd}	|
tk�r�d}
d}
nH|
|jk�rz|�|||�Wntk
�r�YnXtd|||�dSt||||	||||||||
|
|||�S)Nr�r�r�r�r�r�Fr�r�rTrWTr�r�r	rr�z\s+z2Expiring cookie, domain='%s', path='%s', name='%s')r�r9rArLr�r�r�r�boolrsr�r�rtr^r)�clear�KeyErrorrr)r��tupr�rxryrYr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrr�_cookie_from_cookie_tuple�s�







��z#CookieJar._cookie_from_cookie_tuplecCs6|�|�}g}|D]}|�||�}|r|�|�q|Sr�)rZr_rr)r�rUr�rVrCr^r�rrr�_cookies_from_attrs_set's
z!CookieJar._cookies_from_attrs_setcCsHt|jdd�}|dkr |jj}|D]}|jdkr$d|_|r$d|_q$dS)Nr�rTr	)r�r;r�r�r�)r�rCZ
rfc2109_as_nsr�rrr�_process_rfc2109_cookies0s

z"CookieJar._process_rfc2109_cookiesc
Cs:|��}|�dg�}|�dg�}tt���|j_|_|jj}|jj}|sN|rf|sV|rf|s^|rf|sj|sjgSz|�t	|�|�}Wnt
k
r�t�g}YnX|�r6|�r6z|�t|�|�}	Wnt
k
r�t�g}	YnX|�
|	�|�r&i}
|D]}d|
|j|j|jf<q�|
fdd�}t||	�}	|	�r6|�|	�|S)zAReturn sequence of Cookie objects extracted from response object.zSet-Cookie2z
Set-CookieNcSs|j|j|jf}||kSr�)r�r�rx)Z	ns_cookie�lookupr�rrr�no_matching_rfc2965isz3CookieJar.make_cookies.<locals>.no_matching_rfc2965)rZget_allrArMr;r)r�r�r`rz�	Exceptionrr�rar�r�rx�filterrE)
r��responser�r�Zrfc2965_hdrsZns_hdrsr�r�rCZ
ns_cookiesrbr�rcrrr�make_cookies<s^�������
�



zCookieJar.make_cookiescCsN|j��z2tt���|j_|_|j�||�r:|�|�W5|j��XdS)z-Set a cookie if policy says it's OK to do so.N)	r>rQrRrArMr;r)r��
set_cookier�rrr�set_cookie_if_okss
zCookieJar.set_cookie_if_okcCsl|j}|j��zJ|j|kr&i||j<||j}|j|krDi||j<||j}|||j<W5|j��XdS)z?Set a cookie, without checking whether or not it should be set.N)r?r>rQrRr�r�rx)r�r��cZc2Zc3rrrrh�s






zCookieJar.set_cookiecCsbtd|���|j��z8|�||�D]&}|j�||�r&td|�|�|�q&W5|j��XdS)zAExtract cookies from response, where allowable given the request.zextract_cookies: %sz setting cookie: %sN)	rrr>rQrRrgr;r�rh)r�rfr�r�rrr�extract_cookies�s

zCookieJar.extract_cookiescCst|dk	r2|dks|dkr td��|j|||=n>|dk	rX|dkrJtd��|j||=n|dk	rj|j|=ni|_dS)a�Clear some cookies.

        Invoking this method without arguments will clear all cookies.  If
        given a single argument, only cookies belonging to that domain will be
        removed.  If given two arguments, cookies belonging to the specified
        path within that domain are removed.  If given three arguments, then
        the cookie with the specified name, path and domain is removed.

        Raises KeyError if no matching cookie exists.

        Nz8domain and path must be given to remove a cookie by namez.domain must be given to remove cookies by path)rLr?)r�r�r�rxrrrr\�s��
zCookieJar.clearcCsD|j��z(|D]}|jr|�|j|j|j�qW5|j��XdS)z�Discard all session cookies.

        Note that the .save() method won't save session cookies anyway, unless
        you ask otherwise by passing a true ignore_discard argument.

        N)r>rQrRr�r\r�r�rx)r�r�rrr�clear_session_cookies�s
zCookieJar.clear_session_cookiescCsP|j��z4t��}|D]"}|�|�r|�|j|j|j�qW5|j��XdS)a�Discard all expired cookies.

        You probably don't need to call this method: expired cookies are never
        sent back to the server (provided you're using DefaultCookiePolicy),
        this method is called by CookieJar itself every so often, and the
        .save() method won't save expired cookies anyway (unless you ask
        otherwise by passing a true ignore_expires argument).

        N)	r>rQrRrMr�r\r�r�rx)r�r�r�rrrrS�s


zCookieJar.clear_expired_cookiescCs
t|j�Sr�)r5r?rrrr�__iter__�szCookieJar.__iter__cCsd}|D]}|d}q|S)z#Return number of contained cookies.r	rr)r�r�r�rrr�__len__�s
zCookieJar.__len__cCs2g}|D]}|�t|��qd|jjd�|�fS�Nz<%s[%s]>r)rrr�r�r�r��r��rr�rrrr��szCookieJar.__repr__cCs2g}|D]}|�t|��qd|jjd�|�fSro)rrr"r�r�r�rprrrr��szCookieJar.__str__)N)NNN)"r�r�r�r�rt�compilerLrMZstrict_domain_reZ	domain_reZdots_re�ASCII�magic_rer�rBrDrFrOrPrZr_r`rargrirhrkr\rlrSrmrnr�r�rrrrr�s8





;!a\	7


c@seZdZdS)rNr:rrrrr�sc@s8eZdZdZddd�Zd
dd�Zddd	�Zdd
d�ZdS)rz6CookieJar that can be loaded from and saved to a file.NFcCs2t�||�|dk	rt�|�}||_t|�|_dS)z}
        Cookies are NOT loaded from the named file until either the .load() or
        .revert() method is called.

        N)rr��os�fspath�filenamer[�	delayload)r�rwrxrArrrr��s

zFileCookieJar.__init__cCs
t��dS)zSave cookies to a file.Nr�)r�rw�ignore_discard�ignore_expiresrrr�save�szFileCookieJar.savec	CsJ|dkr"|jdk	r|j}ntt��t|��}|�||||�W5QRXdS)zLoad cookies from a file.N)rwrL�MISSING_FILENAME_TEXT�open�_really_load�r�rwryrzrrrr�loads

zFileCookieJar.loadcCs�|dkr"|jdk	r|j}ntt��|j��zFt�|j�}i|_z|�	|||�Wnt
k
rn||_�YnXW5|j��XdS)z�Clear all cookies and reload cookies from a saved file.

        Raises LoadError (or OSError) if reversion is not successful; the
        object's state will not be altered if this happens.

        N)rwrLr|r>rQrRr�Zdeepcopyr?r��OSError)r�rwryrzZ	old_staterrr�revert	s

zFileCookieJar.revert)NFN)NFF)NFF)NFF)r�r�r�r�r�r{r�r�rrrrr�s


	�cCs |j|jfd|jfd|jfg}|jdk	r8|�d|jf�|jrH|�d�|jrX|�d�|jrh|�d�|j	rx|�d�|j
r�|�d	tt|j
��f�|j
r�|�d
�|jr�|�d|jf�|jr�|�d|jf�t|j���}|D]}|�|t|j|�f�q�|�d
t|j�f�t|g�S)z�Return string representation of Cookie in the LWP cookie file format.

    Actually, the format is extended a bit -- see module docstring.

    r�r�Nr�)�	path_specN)�	port_specN)�
domain_dotN)r�Nr�)r�Nr�rTr�)rxryr�r�r�rrr�r�r�r�r�r5r[r�r�r�r/r�r0r"r�r�)r�r�r0r�rrr�lwp_cookie_str$s:
�




�
r�c@s,eZdZdZddd�Zddd�Zd	d
�ZdS)
ra[
    The LWPCookieJar saves a sequence of "Set-Cookie3" lines.
    "Set-Cookie3" is the format used by the libwww-perl library, not known
    to be compatible with any browser, but which is easy to read and
    doesn't lose information about RFC 2965 cookies.

    Additional methods

    as_lwp_str(ignore_discard=True, ignore_expired=True)

    TcCsTt��}g}|D]2}|s |jr q|s0|�|�r0q|�dt|��qd�|dg�S)z�Return cookies as a string of "\n"-separated "Set-Cookie3" headers.

        ignore_discard and ignore_expires: see docstring for FileCookieJar.save

        zSet-Cookie3: %s�
rW)rMr�r�rrr�r�)r�ryrzr�rqr�rrr�
as_lwp_strMs
zLWPCookieJar.as_lwp_strNFc	CsX|dkr"|jdk	r|j}ntt��t|d��"}|�d�|�|�||��W5QRXdS)N�wz#LWP-Cookies-2.0
)rwrLr|r}�writer�rrrrr{]s

zLWPCookieJar.savecCs0|��}|j�|�s$d|}t|��t��}d}d}	d}
�z�|��}|dkrP�q�|�|�s\q<|t|�d���}t|g�D�]f}|d\}
}i}i}|	D]}d||<q�|dd�D]n\}}|dk	r�|�	�}nd}||
ks�||	kr�|}||	k�r|dkr�d	}|||<q�||
k�r|||<q�|||<q�|j
}|d
�}|d�}|dk	�rJt|�}|dk�rXd	}|d�}|�d
�}t|d�|
||d�|d�|||d�|d�|d�|d�|||d�|d�|�}|�s�|j
�r�qz|�s�|�|��r�qz|�|�qzq<WnBtk
�r�Yn,tk
�r*t�td||f��YnXdS)Nz5%r does not look like a Set-Cookie3 (LWP) format filezSet-Cookie3:)r�r�r�r�r�)r�r�r�r�r�r�rTrWr	FrTr�r�r�r�r�r�r�r�r�r�r�r�rTz&invalid Set-Cookie3 format file %r: %r)�readlinertr@rrMrsrr�rzrKr�rerr�r�rhr�rdr)r�rrwryrz�magicrr��headerrWrX�line�datarxryrYr�r�r�r�r�r�r�r�r�rjrrrr~is��










�
�zLWPCookieJar._really_load)TT)NFF)r�r�r�r�r�r{r~rrrrr@s

c@s0eZdZdZe�d�ZdZdd�Zd
dd	�Z	dS)ra�

    WARNING: you may want to backup your browser's cookies file if you use
    this class to save cookies.  I *think* it works, but there have been
    bugs in the past!

    This class differs from CookieJar only in the format it uses to save and
    load cookies to and from a file.  This class uses the Mozilla/Netscape
    `cookies.txt' format.  lynx uses this file format, too.

    Don't expect cookies saved while the browser is running to be noticed by
    the browser (in fact, Mozilla on unix will overwrite your saved cookies if
    you change them on disk while it's running; on Windows, you probably can't
    save at all while the browser is running).

    Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
    Netscape cookies on saving.

    In particular, the cookie version and port number information is lost,
    together with information about whether or not Path, Port and Discard were
    specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
    domain as set in the HTTP header started with a dot (yes, I'm aware some
    domains in Netscape files start with a dot and some don't -- trust me, you
    really don't want to know any more about this).

    Note that though Mozilla and Netscape use the same format, they use
    slightly different headers.  The class saves cookies using the Netscape
    header by default (Mozilla can cope with that).

    z#( Netscape)? HTTP Cookie Filezr# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

cCsbt��}|��}|j�|�s(td|��z�|��}|dkr>�q|�d�rT|dd�}|���d�s*|��dkrpq*|�d�\}}	}
}}}
}|dk}|	dk}	|
dkr�|}
d}|�d�}d	}|dkr�d}d
}t	d|
|dd	||	||
d	|||ddi�}|s�|j
r�q*|�s|�|��rq*|�|�q*WnBt
k
�r2�Yn,tk
�r\t�td||f��YnXdS)
Nz4%r does not look like a Netscape format cookies filerWr�r�)�#r�	�TRUEr�FTr	z+invalid Netscape format cookies file %r: %r)rMr�rtr@rr�r�rsr�rr�r�rhr�rdr)r�rrwryrzr�r�r�r�r�r�r�r�rxryr�r�rjrrrr~�sr��

��
�

�zMozillaCookieJar._really_loadNFc
Cs�|dkr"|jdk	r|j}ntt��t|d���}|�|j�t��}|D]�}|sV|jrVqF|sf|�|�rfqF|j	rrd}nd}|j
�d�r�d}nd}|jdk	r�t
|j�}	nd}	|jdkr�d}
|j}n|j}
|j}|�d�|j
||j||	|
|g�d�qFW5QRXdS)Nr�r�ZFALSEr�rWr�r�)rwrLr|r}r�r�rMr�r�r�r�rsr�r"ryrxr�r�)r�rwryrzrr�r�r�r�r�rxryrrrr{ sH



���zMozillaCookieJar.save)NFF)
r�r�r�r�rtrrrtr�r~r{rrrrr�s

A)N)N)Xr��__all__rur�r-rtrMZurllib.parser�Zurllib.requestZ	threadingr<Zhttp.clientZhttpZcalendarr
rrrr"ZclientZ	HTTP_PORTr�r|rr%r,r6r7rIr(rrrKr5r8r>rrrsr?rFrTrY�Ir]�Xr_rbrcrerkrmrnrprorzr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrr2r5r9rr�rrr�rrrrrr�<module>s��
�

8�
�
�8
�!



U
D'


#b!b7x__pycache__/server.cpython-38.pyc000064400000104101150532417300012707 0ustar00U

e5d��@s
dZdZdddddgZddlZddlZddlZddlZddlZ	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlZddlZddlZddlZddlZddlZdd	lmZdd
l	mZdZdZGd
d�dej�ZGdd�deje�Z Gdd�dej!�Z"Gdd�de"�Z#dd�Z$da%dd�Z&dd�Z'Gdd�de#�Z(dd�Z)e"e dddfdd�Z*e+dk�rddl,Z,e,�-�Z.e.j/dd d!d"�e.j/d#d$d%d&d'�e.j/d(d)e
�0�d*d+�e.j/d,d-de1d.d/d0�e.�2�Z3e3j4�r�e(Z5nee#e3j6d1�Z5Gd2d3�d3e �Z7e*e5e7e3j8e3j9d4�dS)5a@HTTP server classes.

Note: BaseHTTPRequestHandler doesn't implement any HTTP request; see
SimpleHTTPRequestHandler for simple implementations of GET, HEAD and POST,
and CGIHTTPRequestHandler for CGI scripts.

It does, however, optionally implement HTTP/1.1 persistent connections,
as of version 0.3.

Notes on CGIHTTPRequestHandler
------------------------------

This class implements GET and POST requests to cgi-bin scripts.

If the os.fork() function is not present (e.g. on Windows),
subprocess.Popen() is used as a fallback, with slightly altered semantics.

In all cases, the implementation is intentionally naive -- all
requests are executed synchronously.

SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
-- it may execute arbitrary Python code or external programs.

Note that status code 200 is sent prior to execution of a CGI script, so
scripts cannot send other status codes such as 302 (redirect).

XXX To do:

- log requests even later (to capture byte count)
- log user-agent header and other interesting goodies
- send error log to separate file
z0.6�
HTTPServer�ThreadingHTTPServer�BaseHTTPRequestHandler�SimpleHTTPRequestHandler�CGIHTTPRequestHandler�N)�partial)�
HTTPStatusa�<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: %(code)d</p>
        <p>Message: %(message)s.</p>
        <p>Error code explanation: %(code)s - %(explain)s.</p>
    </body>
</html>
ztext/html;charset=utf-8c@seZdZdZdd�ZdS)r�cCs4tj�|�|jdd�\}}t�|�|_||_dS)z.Override server_bind to store the server name.N�)�socketserver�	TCPServer�server_bindZserver_address�socketZgetfqdn�server_name�server_port)�self�host�port�r�#/usr/lib64/python3.8/http/server.pyr
�szHTTPServer.server_bindN)�__name__�
__module__�__qualname__Zallow_reuse_addressr
rrrrr�sc@seZdZdZdS)rTN)rrrZdaemon_threadsrrrrr�sc
@sJeZdZdZdej��dZdeZ	e
ZeZ
dZdd�Zdd	�Zd
d�Zdd
�ZdFdd�ZdGdd�ZdHdd�Zdd�Zdd�Zdd�ZdIdd�Zdd�Ze�d d!�e�ed"�ed#d$��D��Z d%e e!d&�<d'd(�Z"d)d*�Z#dJd+d,�Z$d-d.�Z%d/d0d1d2d3d4d5gZ&dd6d7d8d9d:d;d<d=d>d?d@dAg
Z'dBdC�Z(dDZ)e*j+j,Z-dEd!�e.j/�0�D�Z1dS)Kra�HTTP request handler base class.

    The following explanation of HTTP serves to guide you through the
    code as well as to expose any misunderstandings I may have about
    HTTP (so you don't need to read the code to figure out I'm wrong
    :-).

    HTTP (HyperText Transfer Protocol) is an extensible protocol on
    top of a reliable stream transport (e.g. TCP/IP).  The protocol
    recognizes three parts to a request:

    1. One line identifying the request type and path
    2. An optional set of RFC-822-style headers
    3. An optional data part

    The headers and data are separated by a blank line.

    The first line of the request has the form

    <command> <path> <version>

    where <command> is a (case-sensitive) keyword such as GET or POST,
    <path> is a string containing path information for the request,
    and <version> should be the string "HTTP/1.0" or "HTTP/1.1".
    <path> is encoded using the URL encoding scheme (using %xx to signify
    the ASCII character with hex code xx).

    The specification specifies that lines are separated by CRLF but
    for compatibility with the widest range of clients recommends
    servers also handle LF.  Similarly, whitespace in the request line
    is treated sensibly (allowing multiple spaces between components
    and allowing trailing whitespace).

    Similarly, for output, lines ought to be separated by CRLF pairs
    but most clients grok LF characters just fine.

    If the first line of the request has the form

    <command> <path>

    (i.e. <version> is left out) then this is assumed to be an HTTP
    0.9 request; this form has no optional headers and data part and
    the reply consists of just the data.

    The reply form of the HTTP 1.x protocol again has three parts:

    1. One line giving the response code
    2. An optional set of RFC-822-style headers
    3. The data

    Again, the headers and data are separated by a blank line.

    The response code line has the form

    <version> <responsecode> <responsestring>

    where <version> is the protocol version ("HTTP/1.0" or "HTTP/1.1"),
    <responsecode> is a 3-digit response code indicating success or
    failure of the request, and <responsestring> is an optional
    human-readable string explaining what the response code means.

    This server parses the request and the headers, and then calls a
    function specific to the request type (<command>).  Specifically,
    a request SPAM will be handled by a method do_SPAM().  If no
    such method exists the server sends an error response to the
    client.  If it exists, it is called with no arguments:

    do_SPAM()

    Note that the request name is case sensitive (i.e. SPAM and spam
    are different requests).

    The various request details are stored in instance variables:

    - client_address is the client IP address in the form (host,
    port);

    - command, path and version are the broken-down request line;

    - headers is an instance of email.message.Message (or a derived
    class) containing the header information;

    - rfile is a file object open for reading positioned at the
    start of the optional input data part;

    - wfile is a file object open for writing.

    IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!

    The first thing to be written must be the response line.  Then
    follow 0 or more header lines, then a blank line, and then the
    actual data (if any).  The meaning of the header lines depends on
    the command executed by the server; in most cases, when data is
    returned, there should be at least one header line of the form

    Content-type: <type>/<subtype>

    where <type> and <subtype> should be registered MIME types,
    e.g. "text/html" or "text/plain".

    zPython/rz	BaseHTTP/�HTTP/0.9c
Cs�d|_|j|_}d|_t|jd�}|�d�}||_|��}t	|�dkrLdSt	|�dk�r&|d}zT|�
d	�srt�|�d
d�d}|�d�}t	|�d
kr�t�t|d�t|d�f}Wn,tt
fk
r�|�tjd|�YdSX|dk�r|jdk�rd|_|dk�r |�tjd|�dS||_d
t	|�k�rBdk�sZn|�tjd|�dS|dd
�\}}t	|�d
k�r�d|_|dk�r�|�tjd|�dS|||_|_|j�
d��r�d
|j�d
�|_ztjj|j|jd�|_Wn�tjjk
�r(}z|�tjdt|��WY�dSd}~XYnBtjjk
�rh}z|�tjdt|��WY�dSd}~XYnX|j�dd�}	|	��dk�r�d|_n |	��dk�r�|jdk�r�d|_|j�dd�}
|
��dk�r�|jdk�r�|jdk�r�|� ��s�dSdS) aHParse a request (internal).

        The request should be stored in self.raw_requestline; the results
        are in self.command, self.path, self.request_version and
        self.headers.

        Return True for success, False for failure; on failure, any relevant
        error response has already been sent back.

        NTz
iso-8859-1z
rF����zHTTP/�/r	�.r
zBad request version (%r))r	r	zHTTP/1.1)r
rzInvalid HTTP version (%s)zBad request syntax (%r)ZGETzBad HTTP/0.9 request type (%r)z//)Z_classz
Line too longzToo many headers�
Connection��close�
keep-aliveZExpectz100-continue)!�command�default_request_version�request_version�close_connection�str�raw_requestline�rstrip�requestline�split�len�
startswith�
ValueError�int�
IndexError�
send_errorrZBAD_REQUEST�protocol_versionZHTTP_VERSION_NOT_SUPPORTED�path�lstrip�http�clientZ
parse_headers�rfile�MessageClass�headersZLineTooLongZREQUEST_HEADER_FIELDS_TOO_LARGEZ
HTTPException�get�lower�handle_expect_100)r�versionr)�wordsZbase_version_numberZversion_numberr"r2�errZconntypeZexpectrrr�
parse_requests�


�
��
�
������
z$BaseHTTPRequestHandler.parse_requestcCs|�tj�|��dS)a7Decide what to do with an "Expect: 100-continue" header.

        If the client is expecting a 100 Continue response, we must
        respond with either a 100 Continue or a final response before
        waiting for the request body. The default is to always respond
        with a 100 Continue. You can behave differently (for example,
        reject unauthorized requests) by overriding this method.

        This method should either return True (possibly after sending
        a 100 Continue response) or send an error response and return
        False.

        T)�send_response_onlyrZCONTINUE�end_headers�rrrrr;xsz(BaseHTTPRequestHandler.handle_expect_100c
Cs�z�|j�d�|_t|j�dkrBd|_d|_d|_|�tj	�WdS|jsTd|_
WdS|��sbWdSd|j}t||�s�|�tj
d|j�WdSt||�}|�|j��Wn<tjk
r�}z|�d|�d|_
WY�dSd}~XYnXdS)	z�Handle a single HTTP request.

        You normally don't need to override this method; see the class
        __doc__ string for information on how to handle specific HTTP
        commands such as GET and POST.

        iirNTZdo_zUnsupported method (%r)zRequest timed out: %r)r6�readliner'r+r)r$r"r0rZREQUEST_URI_TOO_LONGr%r?�hasattr�NOT_IMPLEMENTED�getattr�wfile�flushrZtimeout�	log_error)rZmname�method�errr�handle_one_request�s6

�
z)BaseHTTPRequestHandler.handle_one_requestcCs"d|_|��|js|��qdS)z&Handle multiple requests if necessary.TN)r%rLrBrrr�handle�szBaseHTTPRequestHandler.handleNcCsz|j|\}}Wntk
r.d\}}YnX|dkr<|}|dkrH|}|�d||�|�||�|�dd�d}|dkr�|tjtjtjfkr�|j	|t
j|dd�t
j|dd�d	�}|�d
d�}|�d|j
�|�d
tt|���|��|jdk�r|�r|j�|�dS)akSend and log an error reply.

        Arguments are
        * code:    an HTTP error code
                   3 digits
        * message: a simple optional 1 line reason phrase.
                   *( HTAB / SP / VCHAR / %x80-FF )
                   defaults to short entry matching the response code
        * explain: a detailed message defaults to the long entry
                   matching the response code.

        This sends an error response (so it must be called before any
        output has been generated), logs the error, and finally sends
        a piece of HTML explaining the error to the user.

        )�???rNNzcode %d, message %srr ��F��quote)�code�message�explainzUTF-8�replacezContent-Type�Content-LengthZHEAD)�	responses�KeyErrorrI�
send_response�send_headerrZ
NO_CONTENTZ
RESET_CONTENT�NOT_MODIFIED�error_message_format�html�escape�encode�error_content_typer&r+rAr"rG�write)rrRrSrTZshortmsgZlongmsgZbodyZcontentrrrr0�s:���z!BaseHTTPRequestHandler.send_errorcCs:|�|�|�||�|�d|���|�d|���dS)z�Add the response header to the headers buffer and log the
        response code.

        Also send two standard headers with the server software
        version and the current date.

        ZServerZDateN)�log_requestr@rZ�version_string�date_time_string�rrRrSrrrrY�s
z$BaseHTTPRequestHandler.send_responsecCsd|jdkr`|dkr0||jkr,|j|d}nd}t|d�s@g|_|j�d|j||f�dd��dS)	zSend the response header only.rNrr�_headers_bufferz
%s %d %s
�latin-1�strict)r$rWrDrf�appendr1r_rerrrr@�s



��z)BaseHTTPRequestHandler.send_response_onlycCsl|jdkr6t|d�sg|_|j�d||f�dd��|��dkrh|��dkrVd|_n|��d	krhd
|_dS)z)Send a MIME header to the headers buffer.rrfz%s: %s
rgrhZ
connectionr Tr!FN)r$rDrfrir_r:r%)r�keyword�valuerrrrZs

�z"BaseHTTPRequestHandler.send_headercCs"|jdkr|j�d�|��dS)z,Send the blank line ending the MIME headers.rs
N)r$rfri�
flush_headersrBrrrrAs
z"BaseHTTPRequestHandler.end_headerscCs(t|d�r$|j�d�|j��g|_dS)Nrf�)rDrGra�joinrfrBrrrrls
z$BaseHTTPRequestHandler.flush_headers�-cCs.t|t�r|j}|�d|jt|�t|��dS)zNLog an accepted request.

        This is called by send_response().

        z
"%s" %s %sN)�
isinstancerrk�log_messager)r&)rrR�sizerrrrb s
�z"BaseHTTPRequestHandler.log_requestcGs|j|f|��dS)z�Log an error.

        This is called when a request cannot be fulfilled.  By
        default it passes the message on to log_message().

        Arguments are the same as for log_message().

        XXX This should go to the separate error log.

        N)rq)r�format�argsrrrrI+sz BaseHTTPRequestHandler.log_errorcCsi|]}|d|d���qS)z\xZ02xr)�.0�crrr�
<dictcomp>;sz!BaseHTTPRequestHandler.<dictcomp>� ��z\\�\cGs2||}tj�d|��|��|�|j�f�dS)aZLog an arbitrary message.

        This is used by all other logging functions.  Override
        it if you have specific logging wishes.

        The first argument, FORMAT, is a format string for the
        message to be logged.  If the format string contains
        any % escapes requiring parameters, they should be
        specified as subsequent arguments (it's just like
        printf!).

        The client ip and current date/time are prefixed to
        every message.

        Unicode control characters are replaced with escaped hex
        before writing the output to stderr.

        z%s - - [%s] %s
N)�sys�stderrra�address_string�log_date_time_string�	translate�_control_char_table)rrsrtrSrrrrq>s
��z"BaseHTTPRequestHandler.log_messagecCs|jd|jS)z*Return the server software version string.� )�server_version�sys_versionrBrrrrcXsz%BaseHTTPRequestHandler.version_stringcCs |dkrt��}tjj|dd�S)z@Return the current date and time formatted for a message header.NT)Zusegmt)�time�email�utilsZ
formatdate)rZ	timestamprrrrd\sz'BaseHTTPRequestHandler.date_time_stringc	CsBt��}t�|�\	}}}}}}}}	}
d||j|||||f}|S)z.Return the current time formatted for logging.z%02d/%3s/%04d %02d:%02d:%02d)r��	localtime�	monthname)rZnowZyearZmonthZdayZhhZmmZss�x�y�z�srrrrbs�z+BaseHTTPRequestHandler.log_date_time_stringZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs
|jdS)zReturn the client address.r)�client_addressrBrrrr~psz%BaseHTTPRequestHandler.address_string�HTTP/1.0cCsi|]}||j|jf�qSr)�phraseZdescription)ru�vrrrrws�)NN)N)N)roro)N)2rrr�__doc__r|r<r*r��__version__r��DEFAULT_ERROR_MESSAGEr\�DEFAULT_ERROR_CONTENT_TYPEr`r#r?r;rLrMr0rYr@rZrArlrbrIr&�	maketrans�	itertools�chain�ranger��ordrqrcrdrZweekdaynamer�r~r1r4r5ZHTTPMessager7r�__members__�valuesrWrrrrr�s^gj%
5


�
�	�cs�eZdZdZdeZdd��fdd�
Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zdd�Zdd�Z
ejsle��ej��Ze�ddddd���ZS)raWSimple HTTP request handler with GET and HEAD commands.

    This serves files from the current directory and any of its
    subdirectories.  The MIME type for files is determined by
    calling the .guess_type() method.

    The GET and HEAD requests are identical except that the HEAD
    request omits the actual contents of the file.

    zSimpleHTTP/N��	directorycs(|dkrt��}||_t�j||�dS�N)�os�getcwdr��super�__init__)rr�rt�kwargs��	__class__rrr��sz!SimpleHTTPRequestHandler.__init__cCs.|��}|r*z|�||j�W5|��XdS)zServe a GET request.N)�	send_headr �copyfilerG�r�frrr�do_GET�s
zSimpleHTTPRequestHandler.do_GETcCs|��}|r|��dS)zServe a HEAD request.N)r�r r�rrr�do_HEAD�sz SimpleHTTPRequestHandler.do_HEADcCs^|�|j�}d}tj�|�r�tj�|j�}|j�d�s�|�t	j
�|d|d|dd|d|df}tj�|�}|�d|�|�
�dSd	D]&}tj�||�}tj�|�r�|}q�q�|�|�S|�|�}|�d�r�|�t	jd
�dSzt|d�}Wn&tk
�r|�t	jd
�YdSX�z"t�|���}d|jk�r�d
|jk�r�ztj�|jd�}	Wnttttfk
�r|YnzX|	j dk�r�|	j!t"j#j$d�}	|	j t"j#j$k�r�t"j"�%|j&t"j#j$�}
|
j!dd�}
|
|	k�r�|�t	j'�|�
�|�(�WdS|�t	j)�|�d|�|�dt*|d��|�d|�+|j&��|�
�|WS|�(��YnXdS)a{Common code for GET and HEAD commands.

        This sends the response code and MIME headers.

        Return value is either a file object (which has to be copied
        to the outputfile by the caller unless the command was HEAD,
        and must be closed by the caller under all circumstances), or
        None, in which case the caller has nothing further to do.

        Nrrr	r
r�ZLocation)z
index.htmlz	index.htmzFile not found�rbzIf-Modified-Sincez
If-None-Match)�tzinfo)Zmicrosecond�Content-typerV�z
Last-Modified),�translate_pathr2r��isdir�urllib�parseZurlsplit�endswithrYrZMOVED_PERMANENTLYZ
urlunsplitrZrArn�exists�list_directory�
guess_typer0�	NOT_FOUND�open�OSError�fstat�filenor8r�r�Zparsedate_to_datetime�	TypeErrorr/�
OverflowErrorr-r�rU�datetime�timezoneZutcZ
fromtimestamp�st_mtimer[r �OKr&rd)rr2r��partsZ	new_partsZnew_url�indexZctypeZfsZimsZ
last_modifrrrr��s��


���

�z"SimpleHTTPRequestHandler.send_headc
	Cs�zt�|�}Wn$tk
r2|�tjd�YdSX|jdd�d�g}ztjj	|j
dd�}Wn"tk
r�tj�	|j
�}YnXtj
|dd	�}t��}d
|}|�d�|�d�|�d
|�|�d|�|�d|�|�d�|D]v}tj
�||�}|}	}
tj
�|��r$|d}	|d}
tj
�|��r:|d}	|�dtjj|
dd�tj
|	dd	�f�q�|�d�d�|��|d�}t��}|�|�|�d�|�tj�|�dd|�|�dtt|���|��|S)z�Helper to produce a directory listing (absent index.html).

        Return value is either a file object, or None (indicating an
        error).  In either case, the headers are sent, making the
        interface the same as for send_head().

        zNo permission to list directoryNcSs|��Sr�)r:)�arrr�<lambda>rmz9SimpleHTTPRequestHandler.list_directory.<locals>.<lambda>)�key�
surrogatepass��errorsFrPzDirectory listing for %szZ<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">z
<html>
<head>z@<meta http-equiv="Content-Type" content="text/html; charset=%s">z<title>%s</title>
</head>z<body>
<h1>%s</h1>z	<hr>
<ul>r�@z<li><a href="%s">%s</a></li>z</ul>
<hr>
</body>
</html>
�
�surrogateescaperr�ztext/html; charset=%srV) r��listdirr�r0rr��sortr�r��unquoter2�UnicodeDecodeErrorr]r^r|�getfilesystemencodingrirnr��islinkrQr_�io�BytesIOra�seekrYr�rZr&r+rA)
rr2�list�rZdisplaypath�enc�title�name�fullnameZdisplaynameZlinknameZencodedr�rrrr�sh�
�


�
���


z'SimpleHTTPRequestHandler.list_directorycCs�|�dd�d}|�dd�d}|���d�}ztjj|dd�}Wn tk
rbtj�|�}YnXt�|�}|�d�}t	d|�}|j
}|D]0}tj�
|�s�|tjtjfkr�q�tj�||�}q�|r�|d7}|S)	z�Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        �?r	r�#rr�r�N)r*r(r�r�r�r�r��	posixpath�normpath�filterr�r�r2�dirname�curdir�pardirrn)rr2Ztrailing_slashr=Zwordrrrr�:s$	


z'SimpleHTTPRequestHandler.translate_pathcCst�||�dS)a�Copy all data between two file objects.

        The SOURCE argument is a file object open for reading
        (or anything with a read() method) and the DESTINATION
        argument is a file object open for writing (or
        anything with a write() method).

        The only reason for overriding this would be to change
        the block size or perhaps to replace newlines by CRLF
        -- note however that this the default server uses this
        to copy binary data as well.

        N)�shutilZcopyfileobj)r�sourceZ
outputfilerrrr�Xsz!SimpleHTTPRequestHandler.copyfilecCsLt�|�\}}||jkr"|j|S|��}||jkr>|j|S|jdSdS)a�Guess the type of a file.

        Argument is a PATH (a filename).

        Return value is a string of the form type/subtype,
        usable for a MIME Content-type header.

        The default implementation looks the file's extension
        up in the table self.extensions_map, using application/octet-stream
        as a default; however it would be permissible (if
        slow) to look inside the data to make a better guess.

        rN)r��splitext�extensions_mapr:)rr2�baseZextrrrr�hs



z#SimpleHTTPRequestHandler.guess_typezapplication/octet-streamz
text/plain)r�.pyz.cz.h)rrrr�r�r�r�r�r�r�r�r�r�r��	mimetypesZinitedZinitZ	types_map�copyr��update�
__classcell__rrr�rr�s&	W:
�c	Cs�|�d�\}}}tj�|�}|�d�}g}|dd�D],}|dkrL|��q6|r6|dkr6|�|�q6|r�|��}|r�|dkr�|��d}q�|dkr�d}nd}|r�d�||f�}dd�|�|f}d�|�}|S)a�
    Given a URL path, remove extra '/'s and '.' path elements and collapse
    any '..' references and returns a collapsed path.

    Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
    The utility of this function is limited to is_cgi method and helps
    preventing some security attacks.

    Returns: The reconstituted URL, which will always start with a '/'.

    Raises: IndexError if too many '..' occur within the path.

    r�rNrz..rr)�	partitionr�r�r�r*�poprirn)	r2�_�query�
path_partsZ
head_parts�partZ	tail_partZ	splitpath�collapsed_pathrrr�_url_collapse_path�s.


r�cCsrtrtSzddl}Wntk
r*YdSXz|�d�daWn.tk
rldtdd�|��D��aYnXtS)	z$Internal routine to get nobody's uidrNr�nobodyr
r	css|]}|dVqdS)r
Nr)rur�rrr�	<genexpr>�sznobody_uid.<locals>.<genexpr>)r��pwd�ImportError�getpwnamrX�maxZgetpwall)r�rrr�
nobody_uid�s r�cCst�|tj�S)zTest for executable file.)r��access�X_OK)r2rrr�
executable�src@sVeZdZdZeed�ZdZdd�Zdd�Z	dd	�Z
d
dgZdd
�Zdd�Z
dd�ZdS)rz�Complete HTTP server with GET, HEAD and POST commands.

    GET and HEAD also support running CGI scripts.

    The POST command is *only* implemented for CGI scripts.

    �forkrcCs$|��r|��n|�tjd�dS)zRServe a POST request.

        This is only implemented for CGI scripts.

        zCan only POST to CGI scriptsN)�is_cgi�run_cgir0rrErBrrr�do_POST�s
�zCGIHTTPRequestHandler.do_POSTcCs|��r|��St�|�SdS)z-Version of send_head that support CGI scriptsN)rrrr�rBrrrr��szCGIHTTPRequestHandler.send_headcCsPt|j�}|�dd�}|d|�||dd�}}||jkrL||f|_dSdS)a3Test whether self.path corresponds to a CGI script.

        Returns True and updates the cgi_info attribute to the tuple
        (dir, rest) if self.path requires running a CGI script.
        Returns False otherwise.

        If any exception is raised, the caller should assume that
        self.path was rejected as invalid and act accordingly.

        The default implementation tests whether the normalized url
        path begins with one of the strings in self.cgi_directories
        (and the next character is a '/' or the end of the string).

        rr	NTF)r�r2�find�cgi_directories�cgi_info)rr�Zdir_sep�head�tailrrrr�s


zCGIHTTPRequestHandler.is_cgiz/cgi-binz/htbincCst|�S)z1Test whether argument path is an executable file.)r)rr2rrr�
is_executablesz#CGIHTTPRequestHandler.is_executablecCstj�|�\}}|��dkS)z.Test whether argument path is a Python script.)r�z.pyw)r�r2r�r:)rr2r
rrrr�	is_pythonszCGIHTTPRequestHandler.is_pythonc)	Cs�|j\}}|d|}|�dt|�d�}|dkr�|d|�}||dd�}|�|�}tj�|�r�||}}|�dt|�d�}q*q�q*|�d�\}}}	|�d�}|dkr�|d|�||d�}
}n
|d}
}|d|
}|�|�}tj�|��s
|�	t
jd|�dStj�|��s.|�	t
j
d|�dS|�|�}
|j�sF|
�sh|�|��sh|�	t
j
d	|�dSt�tj�}|��|d
<|jj|d<d|d
<|j|d<t|jj�|d<|j|d<tj�|�}||d<|�|�|d<||d<|	�r�|	|d<|jd|d<|j� d�}|�r�|�!�}t|�dk�r�ddl"}ddl#}|d|d<|d�$�dk�r�z"|d�%d�}|�&|��'d�}Wn|j(t)fk
�r�Yn&X|�!d�}t|�dk�r�|d|d<|j� d�dk�r�|j�*�|d<n|jd|d<|j� d�}|�r||d <|j� d!�}|�r||d"<g}|j�+d#�D]>}|dd�d$k�rR|�,|�-��n||d%d��!d&�}�q,d&�.|�|d'<|j� d(�}|�r�||d)<t/d|j�0d*g��}d+�.|�}|�r�||d,<d-D]}|�1|d��q�|�2t
j3d.�|�4�|	�5d/d0�}|j�r|
g}d1|k�r|�,|�t6�}|j7�8�t�9�}|dk�r�t�:|d�\}}t;�;|j<gggd�d�r~|j<�=d��sN�q~�qN|�r�|�>d2|�dSz\zt�?|�Wnt@k
�r�YnXt�A|j<�B�d�t�A|j7�B�d�t�C|||�Wn(|j�D|jE|j�t�Fd3�YnX�n�ddlG} |g}!|�|��rrtHjI}"|"�$��Jd4��rf|"dd5�|"d6d�}"|"d7g|!}!d1|	k�r�|!�,|	�|�Kd8| �L|!��ztM|�}#WntNtOfk
�r�d}#YnX| jP|!| jQ| jQ| jQ|d9�}$|j�$�d:k�r|#dk�r|j<�=|#�}%nd}%t;�;|j<jRgggd�d�r>|j<jR�Sd��s
�q>�q
|$�T|%�\}&}'|j7�U|&�|'�rj|�>d;|'�|$jV�W�|$jX�W�|$jY}(|(�r�|�>d2|(�n
|�Kd<�dS)=zExecute a CGI script.rr	rNr�rzNo such CGI script (%r)z#CGI script is not a plain file (%r)z!CGI script is not executable (%r)ZSERVER_SOFTWAREZSERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZSERVER_PROTOCOLZSERVER_PORTZREQUEST_METHODZ	PATH_INFOZPATH_TRANSLATEDZSCRIPT_NAME�QUERY_STRINGZREMOTE_ADDR�
authorizationr
Z	AUTH_TYPEZbasic�ascii�:ZREMOTE_USERzcontent-typeZCONTENT_TYPEzcontent-length�CONTENT_LENGTH�referer�HTTP_REFERER�acceptz	

 ��,ZHTTP_ACCEPTz
user-agent�HTTP_USER_AGENTZcookiez, �HTTP_COOKIE)rZREMOTE_HOSTrrrrzScript output follows�+r��=zCGI script exit status %#xryzw.exe������z-uzcommand: %s)�stdin�stdoutr}�envZpostz%szCGI script exited OK)Zr	rr+r�r�r2r�r�r�r0rr��isfileZ	FORBIDDENr
�	have_forkrr�Zdeepcopy�environrcZserverrr1r&rr"r�r�r�r�r8r9r*�base64�binasciir:r_Zdecodebytes�decode�Error�UnicodeErrorZget_content_typeZgetallmatchingheadersri�striprnr�Zget_all�
setdefaultrYr�rlrUr�rGrHr�waitpid�selectr6�readrI�setuidr��dup2r��execveZhandle_errorZrequest�_exit�
subprocessr|rr�rqZlist2cmdliner.r�r-�Popen�PIPEZ_sockZrecvZcommunicaterar}r r�
returncode))r�dir�restr2�iZnextdirZnextrestZ	scriptdirr�r�ZscriptZ
scriptnameZ
scriptfileZispyr Zuqrestrr$r%Zlengthrr�lineZua�coZ
cookie_str�kZ
decoded_queryrtr��pid�stsr2ZcmdlineZinterp�nbytes�p�datarr}Zstatusrrrrs<





��
�


�








�

zCGIHTTPRequestHandler.run_cgiN)rrrr�rDr�r"Zrbufsizerr�rrrr
rrrrrr�s	
cGs4tj|tjtjd��}tt|��\}}}}}||fS)N)�type�flags)rZgetaddrinfoZSOCK_STREAMZ
AI_PASSIVE�next�iter)ZaddressZinfosZfamilyrA�protoZ	canonnameZsockaddrrrr�_get_best_family�s�rFr�i@c	Cs�t||�\|_}||_|||���}|j��dd�\}}d|krLd|�d�n|}td|�d|�d|�d|�d	�	�z|��Wn&tk
r�td
�t�	d�YnXW5QRXdS)zmTest the HTTP request handler class.

    This runs an HTTP server on port 8000 (or the port argument).

    Nr
r�[�]zServing HTTP on z port z	 (http://z/) ...z&
Keyboard interrupt received, exiting.r)
rFZaddress_familyr1rZgetsockname�printZ
serve_forever�KeyboardInterruptr|�exit)	�HandlerClass�ServerClassZprotocolr�bindZaddrZhttpdrZurl_hostrrr�test�s�rO�__main__z--cgi�
store_truezRun as CGI Server)�action�helpz--bindz-bZADDRESSz8Specify alternate bind address [default: all interfaces])�metavarrSz--directoryz-dz9Specify alternative directory [default:current directory])�defaultrSrZstorer�z&Specify alternate port [default: 8000])rRrUrA�nargsrSr�cseZdZ�fdd�Z�ZS)�DualStackServerc	s4t�t��|j�tjtjd�W5QRXt���S)Nr)	�
contextlib�suppress�	ExceptionrZ
setsockoptZIPPROTO_IPV6ZIPV6_V6ONLYr�r
rBr�rrr
s�zDualStackServer.server_bind)rrrr
r�rrr�rrWsrW)rLrMrrN):r�r��__all__r�r�Zemail.utilsr�r]Zhttp.clientr4r�r�r�r�r�r,r�rrr|r�Zurllib.parser�rX�	functoolsrrr�r�rrZThreadingMixInrZStreamRequestHandlerrrr�r�r�rrrFrOr�argparse�ArgumentParser�parser�add_argumentr�r.�
parse_argsrtZcgiZ
handler_classr�rWrrNrrrr�<module>s�R�s
0
�

�
�����__pycache__/cookies.cpython-38.opt-1.pyc000064400000035566150532417300014016 0ustar00U

e5d�O�
@stdZddlZddlZdddgZdjZdjZdjZGd	d�de�Z	ej
ejd
ZedZ
dd
�eed��eeee
��D�Ze�ed�ded�di�e�de�e��jZdd�Ze�d�Ze�d�Zdd�Zddddddd gZdd!d"d#d$d%d&d'd(d)d*d+d,g
Zdeefd-d.�ZGd/d0�d0e�Z d1Z!e!d2Z"e�d3e!d4e"d5ej#ej$B�Z%Gd6d�de�Z&Gd7d�de&�Z'dS)8a.

Here's a sample session to show how to use this module.
At the moment, this is the only documentation.

The Basics
----------

Importing is easy...

   >>> from http import cookies

Most of the time you start by creating a cookie.

   >>> C = cookies.SimpleCookie()

Once you've created your Cookie, you can add values just as if it were
a dictionary.

   >>> C = cookies.SimpleCookie()
   >>> C["fig"] = "newton"
   >>> C["sugar"] = "wafer"
   >>> C.output()
   'Set-Cookie: fig=newton\r\nSet-Cookie: sugar=wafer'

Notice that the printable representation of a Cookie is the
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.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

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.SimpleCookie()
   >>> C.load("chips=ahoy; vienna=finger")
   >>> C.output()
   'Set-Cookie: chips=ahoy\r\nSet-Cookie: vienna=finger'

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.SimpleCookie()
   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
   >>> print(C)
   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"

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.SimpleCookie()
   >>> C["oreo"] = "doublestuff"
   >>> C["oreo"]["path"] = "/"
   >>> print(C)
   Set-Cookie: oreo=doublestuff; Path=/

Each dictionary element has a 'value' attribute, which gives you
back the value associated with the key.

   >>> C = cookies.SimpleCookie()
   >>> C["twix"] = "none for you"
   >>> C["twix"].value
   'none for you'

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.

   >>> C = cookies.SimpleCookie()
   >>> C["number"] = 7
   >>> C["string"] = "seven"
   >>> C["number"].value
   '7'
   >>> C["string"].value
   'seven'
   >>> C.output()
   'Set-Cookie: number=7\r\nSet-Cookie: string=seven'

Finis.
�N�CookieError�
BaseCookie�SimpleCookie�z; � c@seZdZdS)rN)�__name__�
__module__�__qualname__�r
r
�$/usr/lib64/python3.8/http/cookies.pyr�sz!#$%&'*+-.^_`|~:z
 ()/<=>?@[]{}cCsi|]}|d|�qS)z\%03or
)�.0�nr
r
r�
<dictcomp>�s�r��"�\"�\z\\z[%s]+cCs*|dkst|�r|Sd|�t�dSdS)z�Quote a string for use in a cookie header.

    If the string does not need to be double-quoted, then just return the
    string.  Otherwise, surround the string in doublequotes and quote
    (with a \) special characters.
    Nr)�
_is_legal_key�	translate�_Translator��strr
r
r�_quote�srz\\[0-3][0-7][0-7]z[\\].cCsN|dkst|�dkr|S|ddks0|ddkr4|S|dd�}d}t|�}g}d|krf|k�rFnn�t�||�}t�||�}|s�|s�|�||d���qFd}}|r�|�d�}|r�|�d�}|�r|r�||k�r|�|||��|�||d�|d}qP|�|||��|�tt||d|d�d���|d}qPt|�S)N�rr������)	�len�
_OctalPatt�search�
_QuotePatt�append�start�chr�int�	_nulljoin)r�ir
�resZo_matchZq_match�j�kr
r
r�_unquote�s6


$
r+ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc	CsRddlm}m}|�}|||�\	}}}}	}
}}}
}d|||||||	|
|fS)Nr)�gmtime�timez#%s, %02d %3s %4d %02d:%02d:%02d GMT)r-r,)ZfutureZweekdaynameZ	monthnamer,r-ZnowZyearZmonthZdayZhhZmmZssZwd�y�zr
r
r�_getdate�s�r0c
@s�eZdZdZdddddddd	d
d�	Zdd
hZdd�Zedd��Zedd��Z	edd��Z
dd�Zd2dd�Zdd�Z
ejZdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd3d*d+�ZeZd,d-�Zd4d.d/�Zd5d0d1�ZdS)6�MorselaCA class to hold ONE (key, value) pair.

    In a cookie, each such pair may have several attributes, so this class is
    used to keep the attributes associated with the appropriate key,value pair.
    This class also includes a coded_value attribute, which is used to hold
    the network representation of the value.
    �expires�Path�CommentZDomainzMax-AgeZSecureZHttpOnlyZVersionZSameSite)	r2�path�commentZdomain�max-age�secure�httponly�versionZsamesiter8r9cCs0d|_|_|_|jD]}t�||d�qdS)Nr)�_key�_value�_coded_value�	_reserved�dict�__setitem__)�self�keyr
r
r�__init__ s
zMorsel.__init__cCs|jS�N)r;�rAr
r
rrB(sz
Morsel.keycCs|jSrD)r<rEr
r
r�value,szMorsel.valuecCs|jSrD)r=rEr
r
r�coded_value0szMorsel.coded_valuecCs2|��}||jkr td|f��t�|||�dS�NzInvalid attribute %r)�lowerr>rr?r@)rA�K�Vr
r
rr@4s
zMorsel.__setitem__NcCs.|��}||jkr td|f��t�|||�SrH)rIr>rr?�
setdefault)rArB�valr
r
rrL:s
zMorsel.setdefaultcCs>t|t�stSt�||�o<|j|jko<|j|jko<|j|jkSrD)�
isinstancer1�NotImplementedr?�__eq__r<r;r=�rAZmorselr
r
rrP@s

�
�
�z
Morsel.__eq__cCs$t�}t�||�|j�|j�|SrD)r1r?�update�__dict__rQr
r
r�copyJszMorsel.copycCsRi}t|���D]0\}}|��}||jkr8td|f��|||<qt�||�dSrH)r?�itemsrIr>rrR)rA�values�datarBrMr
r
rrRPs

z
Morsel.updatecCs|��|jkSrD)rIr>)rArJr
r
r�
isReservedKeyYszMorsel.isReservedKeycCsH|��|jkrtd|f��t|�s2td|f��||_||_||_dS)Nz Attempt to set a reserved key %rzIllegal key %r)rIr>rrr;r<r=)rArBrMZ	coded_valr
r
r�set\sz
Morsel.setcCs|j|j|jd�S)N)rBrFrG�r;r<r=rEr
r
r�__getstate__gs�zMorsel.__getstate__cCs"|d|_|d|_|d|_dS)NrBrFrGrZ)rA�stater
r
r�__setstate__ns

zMorsel.__setstate__�Set-Cookie:cCsd||�|�fS)Nz%s %s)�OutputString)rA�attrs�headerr
r
r�outputssz
Morsel.outputcCsd|jj|��fS)N�<%s: %s>)�	__class__rr_rEr
r
r�__repr__xszMorsel.__repr__cCsd|�|��dd�S)Nz�
        <script type="text/javascript">
        <!-- begin hiding
        document.cookie = "%s";
        // end hiding -->
        </script>
        rr)r_�replace)rAr`r
r
r�	js_output{s�zMorsel.js_outputcCs$g}|j}|d|j|jf�|dkr,|j}t|���}|D]�\}}|dkrNq<||krXq<|dkr�t|t�r�|d|j|t|�f�q<|dkr�t|t�r�|d|j||f�q<|dkr�t|t	�r�|d|j|t
|�f�q<||jk�r|�r|t	|j|��q<|d|j||f�q<t|�S)N�%s=%srr2r7z%s=%dr6)
r"rBrGr>�sortedrUrNr%r0rr�_flags�_semispacejoin)rAr`�resultr"rUrBrFr
r
rr_�s,zMorsel.OutputString)N)Nr^)N)N)rrr	�__doc__r>rjrC�propertyrBrFrGr@rLrP�object�__ne__rTrRrXrYr[r]rb�__str__rergr_r
r
r
rr1�sD�



	


r1z,\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=z\[\]z�
    \s*                            # Optional whitespace at start of cookie
    (?P<key>                       # Start of group 'key'
    [a	]+?   # Any word of at least one letter
    )                              # End of group 'key'
    (                              # Optional group: there may not be a value.
    \s*=\s*                          # Equal Sign
    (?P<val>                         # Start of group 'val'
    "(?:[^\\"]|\\.)*"                  # Any doublequoted string
    |                                  # or
    \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT  # Special case for "expires" attr
    |                                  # or
    [a-]*      # Any word or empty string
    )                                # End of group 'val'
    )?                             # End of optional value group
    \s*                            # Any number of spaces.
    (\s+|;|$)                      # Ending either at space, semicolon, or EOS.
    c@sneZdZdZdd�Zdd�Zddd�Zd	d
�Zdd�Zddd�Z	e	Z
dd�Zddd�Zdd�Z
efdd�ZdS)rz'A container class for a set of Morsels.cCs||fS)a
real_value, coded_value = value_decode(STRING)
        Called prior to setting a cookie's value from the network
        representation.  The VALUE is the value read from HTTP
        header.
        Override this function to modify the behavior of cookies.
        r
�rArMr
r
r�value_decode�szBaseCookie.value_decodecCst|�}||fS)z�real_value, coded_value = value_encode(VALUE)
        Called prior to setting a cookie's value from the dictionary
        representation.  The VALUE is the value being assigned.
        Override this function to modify the behavior of cookies.
        r�rArMZstrvalr
r
r�value_encode�szBaseCookie.value_encodeNcCs|r|�|�dSrD)�load)rA�inputr
r
rrC�szBaseCookie.__init__cCs.|�|t��}|�|||�t�|||�dS)z+Private method for setting a cookie's valueN)�getr1rYr?r@)rArBZ
real_valuerG�Mr
r
rZ__set�szBaseCookie.__setcCs:t|t�rt�|||�n|�|�\}}|�|||�dS)zDictionary style assignment.N)rNr1r?r@ru�_BaseCookie__set)rArBrF�rval�cvalr
r
rr@�s
zBaseCookie.__setitem__r^�
cCs:g}t|���}|D]\}}|�|�||��q|�|�S)z"Return a string suitable for HTTP.)rirUr"rb�join)rAr`ra�seprlrUrBrFr
r
rrb�s
zBaseCookie.outputcCsJg}t|���}|D] \}}|�d|t|j�f�qd|jjt|�fS)Nrhrc)rirUr"�reprrFrdr�
_spacejoin)rA�lrUrBrFr
r
rre�s
zBaseCookie.__repr__cCs6g}t|���}|D]\}}|�|�|��qt|�S)z(Return a string suitable for JavaScript.)rirUr"rgr&)rAr`rlrUrBrFr
r
rrgs
zBaseCookie.js_outputcCs4t|t�r|�|�n|��D]\}}|||<qdS)z�Load cookies from a string (presumably HTTP_COOKIE) or
        from a dictionary.  Loading cookies from a dictionary 'd'
        is equivalent to calling:
            map(Cookie.__setitem__, d.keys(), d.values())
        N)rNr�_BaseCookie__parse_stringrU)rAZrawdatarBrFr
r
rrv
s


zBaseCookie.loadcCshd}t|�}g}d}d}d}d|kr2|k�rnn�|�||�}	|	sJ�q|	�d�|	�d�}
}|	�d�}|
ddkr�|s|q|�||
dd�|f�q|
��tjkr�|s�dS|dkr�|
��tjkr�|�||
df�q�dSn|�||
t	|�f�q|dk	�r|�||
|�
|�f�d}qdSqd}|D]>\}
}
}|
|k�rB|||
<n|\}}|�|
||�||
}�q$dS)	NrFrrrBrM�$T)r�match�group�endr"rIr1r>rjr+rsrz)rArZpattr'r
Zparsed_itemsZmorsel_seenZTYPE_ATTRIBUTEZ
TYPE_KEYVALUEr�rBrFry�tpr{r|r
r
rZ__parse_stringsF



zBaseCookie.__parse_string)N)Nr^r})N)rrr	rmrsrurCrzr@rbrqrergrv�_CookiePatternr�r
r
r
rr�s		
	

c@s eZdZdZdd�Zdd�ZdS)rz�
    SimpleCookie supports strings as cookie values.  When setting
    the value using the dictionary assignment notation, SimpleCookie
    calls the builtin str() to convert the value to a string.  Values
    received from HTTP are kept as strings.
    cCst|�|fSrD)r+rrr
r
rrs\szSimpleCookie.value_decodecCst|�}|t|�fSrD)rrrtr
r
rru_szSimpleCookie.value_encodeN)rrr	rmrsrur
r
r
rrUs)(rm�re�string�__all__r~r&rkr��	ExceptionrZ
ascii_lettersZdigitsZ_LegalCharsZ_UnescapedCharsrY�range�map�ordrrR�compile�escape�	fullmatchrrrr!r+Z_weekdaynameZ
_monthnamer0r?r1Z_LegalKeyCharsZ_LegalValueChars�ASCII�VERBOSEr�rrr
r
r
r�<module>'sr]
��

2�4����
�
__pycache__/cookiejar.cpython-38.pyc000064400000150614150532417300013361 0ustar00U

e5d#,�@sdZddddddddgZd	d
lZd	d
lZd	d
lZd	d
lZd	d
lZd	d
lZd	d
l	Zd	d
l
Zd	d
lZ
d	dlmZdZd
ad
d�Zee
jj�ZdZdd�ZdZdd�ZdddddddgZddddd d!d"d#d$d%d&d'gZgZeD]Ze�e� ��q�dud(d)�Z!dvd*d+�Z"d
d
d
d
d,�Z#e�$d-ej%�Z&d.d/�Z'd0d1�Z(e�$d2ej%�Z)e�$d3ej*ej%B�Z+e�$d4ej,ej%B�Z-d5d6�Z.e�$d7ej,ej%B�Z/d8d9�Z0d:d;�Z1e�$d<�Z2e�$d=�Z3e�$d>�Z4e�$d?�Z5d@dA�Z6e�$dB�Z7dCdD�Z8dEdF�Z9dGdH�Z:e�$dIej%�Z;dJdK�Z<dLdM�Z=dNdO�Z>dPdQ�Z?e�$dRej%�Z@dSdT�ZAdUdV�ZBdWdX�ZCdYdZ�ZDd[ZEe�$d\�ZFd]d^�ZGd_d`�ZHdadb�ZIdcdd�ZJGded�d�ZKGdfd�d�ZLGdgd�deL�ZMdhdi�ZNdjdk�ZOGdldm�dm�ZPGdnd�d�ZQGdod�deR�ZSGdpd�deQ�ZTdqdr�ZUGdsd�deT�ZVGdtd�deT�ZWd
S)wa�HTTP cookie handling for web clients.

This module has (now fairly distant) origins in Gisle Aas' Perl module
HTTP::Cookies, from the libwww-perl library.

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 BSDDBCookieJar and the MSIE* classes are not
distributed with the Python standard library, but are available from
http://wwwsearch.sf.net/):

                        CookieJar____
                        /     \      \
            FileCookieJar      \      \
             /    |   \         \      \
 MozillaCookieJar | LWPCookieJar \      \
                  |               |      \
                  |   ---MSIEBase |       \
                  |  /      |     |        \
                  | /   MSIEDBCookieJar BSDDBCookieJar
                  |/
               MSIECookieJar

�Cookie�	CookieJar�CookiePolicy�DefaultCookiePolicy�
FileCookieJar�LWPCookieJar�	LoadError�MozillaCookieJar�N)�timegmFcGs(tsdStsddl}|�d�atj|�S)Nr	zhttp.cookiejar)�debug�logger�loggingZ	getLogger)�argsr
�r�&/usr/lib64/python3.8/http/cookiejar.py�_debug,s
rzQa filename was not supplied (nor was the CookieJar instance initialised with one)cCsJddl}ddl}ddl}|��}|�d|�|��}|jd|dd�dS)Nr	zhttp.cookiejar bug!
%s�)�
stacklevel)�io�warnings�	traceback�StringIO�	print_exc�getvalue�warn)rrr�f�msgrrr�_warn_unhandled_exception:s
ri�cCs�|dd�\}}}}}}|tkr�d|kr4dkr�nnhd|krLdkr�nnPd|krddkr�nn8d|kr|dkr�nn d|kr�dkr�nnt|�SdSdS)	N����r	��;�=)�
EPOCH_YEARr
)�tt�year�monthZmday�hour�min�secrrr�_timegmIs&8��
��
��
r,ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs@|dkrtj��}ntj�|�}d|j|j|j|j|j|jfS)aHReturn a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like "YYYY-MM-DD hh:mm:ssZ",
    representing Universal Time (UTC, aka GMT).  An example of this format is:

    1994-11-24 08:49:37Z

    Nz%04d-%02d-%02d %02d:%02d:%02dZ)	�datetime�utcnow�utcfromtimestampr'r(�dayr)�minute�second��tZdtrrr�	time2isozWs�r5cCsR|dkrtj��}ntj�|�}dt|��|jt|jd|j|j	|j
|jfS)z�Return a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like this:

    Wed, DD-Mon-YYYY HH:MM:SS GMT

    Nz#%s, %02d-%s-%04d %02d:%02d:%02d GMTr)r-r.r/�DAYSZweekdayr0�MONTHSr(r'r)r1r2r3rrr�
time2netscapejs
�r8)ZGMT�UTCZUT�Zz^([-+])?(\d\d?):?(\d\d)?$cCsjd}|tkrd}nTt�|�}|rfdt|�d��}|�d�rR|dt|�d��}|�d�dkrf|}|S)Nr	ir��<r�-)�	UTC_ZONES�TIMEZONE_RE�search�int�group)�tz�offset�mrrr�offset_from_tz_string�s

rFc
Cs�t|�}|tjkrdSzt�|���d}Wn^tk
r�zt|�}Wntk
r`YYdSXd|krvdkr�nn|}nYdSYnX|dkr�d}|dkr�d}|dkr�d}t|�}t|�}t|�}t|�}|dk�r6t�t���d}|d}	|}
|||	}|	|
}	t	|	�dk�r6|	dk�r.|d}n|d}t
|||||||f�}|dk	�r�|dk�rdd}|��}t|�}|dk�r�dS||}|S)Nrr r	i��d�2r9)
rAr-ZMAXYEAR�MONTHS_LOWER�index�lower�
ValueError�time�	localtime�absr,�upperrF)
r0�mon�yr�hrr*r+rCZimonZcur_yrrEZtmpr4rDrrr�	_str2time�sV







rTzV^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$z+^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*a�^
    (\d\d?)            # day
       (?:\s+|[-\/])
    (\w+)              # month
        (?:\s+|[-\/])
    (\d+)              # year
    (?:
          (?:\s+|:)    # separator before clock
       (\d\d?):(\d\d)  # hour:min
       (?::(\d\d))?    # optional seconds
    )?                 # optional clock
       \s*
    (?:
       ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+) # timezone
       \s*
    )?
    (?:
       \(\w+\)         # ASCII representation of timezone in parens.
       \s*
    )?$cCs�t�|�}|rl|��}t�|d���d}t|d�|t|d�t|d�t|d�t|d�f}t|�S|�	�}t
�d|d�}dgd	\}}}}}}	}
t�|�}|dk	r�|��\}}}}}}	}
ndSt
||||||	|
�S)
a�Returns time in seconds since epoch of time represented by a string.

    Return value is an integer.

    None is returned if the format of str is unrecognized, the time is outside
    the representable range, or the timezone string is not recognized.  If the
    string contains no timezone, UTC is assumed.

    The timezone in the string may be numerical (like "-0800" or "+0100") or a
    string timezone (like "UTC", "GMT", "BST" or "EST").  Currently, only the
    timezone strings equivalent to UTC (zero offset) are known to the function.

    The function loosely parses the following formats:

    Wed, 09 Feb 1994 22:23:32 GMT       -- HTTP format
    Tuesday, 08-Feb-94 14:15:29 GMT     -- old rfc850 HTTP format
    Tuesday, 08-Feb-1994 14:15:29 GMT   -- broken rfc850 HTTP format
    09 Feb 1994 22:23:32 GMT            -- HTTP format (no weekday)
    08-Feb-94 14:15:29 GMT              -- rfc850 format (no weekday)
    08-Feb-1994 14:15:29 GMT            -- broken rfc850 format (no weekday)

    The parser ignores leading and trailing whitespace.  The time may be
    absent.

    If the year is given with only 2 digits, the function will select the
    century that makes the year closest to the current date.

    rrr	r;���N�)�STRICT_DATE_REr@�groupsrIrJrKrA�floatr,�lstrip�
WEEKDAY_RE�sub�LOOSE_HTTP_DATE_RErT)�textrE�grQr&r0rRrSr*r+rCrrr�	http2time�s$



�
rba�^
    (\d{4})              # year
       [-\/]?
    (\d\d?)              # numerical month
       [-\/]?
    (\d\d?)              # day
   (?:
         (?:\s+|[-:Tt])  # separator before clock
      (\d\d?):?(\d\d)    # hour:min
      (?::?(\d\d(?:\.\d*)?))?  # optional seconds (and fractional)
   )?                    # optional clock
      \s*
   (?:
      ([-+]?\d\d?:?(:?\d\d)?
       |Z|z)             # timezone  (Z is "zero meridian", i.e. GMT)
      \s*
   )?$c
Csd|��}dgd\}}}}}}}t�|�}|dk	rL|��\}}}}}}}}	ndSt|||||||�S)av
    As for http2time, but parses the ISO 8601 formats:

    1994-02-03 14:15:29 -0100    -- ISO 8601 format
    1994-02-03 14:15:29          -- zone is optional
    1994-02-03                   -- only date
    1994-02-03T14:15:29          -- Use T as separator
    19940203T141529Z             -- ISO 8601 compact format
    19940203                     -- only date

    NrX)r\�ISO_DATE_REr@rZrT)
r`r0rQrRrSr*r+rCrE�_rrr�iso2time+s

recCs*|�d�\}}|jd|�|j|d�S)z)Return unmatched part of re.Match object.r	N)�span�string)�match�start�endrrr�	unmatchedLsrkz^\s*([^=\s;,]+)z&^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"z^\s*=\s*([^\s;,]*)z\\(.)c
Cs0t|t�rt�g}|D�]}|}g}|�rt�|�}|r�t|�}|�d�}t�|�}|rxt|�}|�d�}t�	d|�}n.t
�|�}|r�t|�}|�d�}|��}nd}|�||f�q$|�
��d�r�|�
�dd�}|r�|�|�g}q$t�dd|�\}}	|	dk�std|||f��|}q$|r|�|�q|S)	amParse header values into a list of lists containing key,value pairs.

    The function knows how to deal with ",", ";" and "=" as well as quoted
    values after "=".  A list of space separated tokens are parsed as if they
    were separated by ";".

    If the header_values passed as argument contains multiple values, then they
    are treated as if they were a single value separated by comma ",".

    This means that this function is useful for parsing header fields that
    follow this syntax (BNF as from the HTTP/1.1 specification, but we relax
    the requirement for tokens).

      headers           = #header
      header            = (token | parameter) *( [";"] (token | parameter))

      token             = 1*<any CHAR except CTLs or separators>
      separators        = "(" | ")" | "<" | ">" | "@"
                        | "," | ";" | ":" | "\" | <">
                        | "/" | "[" | "]" | "?" | "="
                        | "{" | "}" | SP | HT

      quoted-string     = ( <"> *(qdtext | quoted-pair ) <"> )
      qdtext            = <any TEXT except <">>
      quoted-pair       = "\" CHAR

      parameter         = attribute "=" value
      attribute         = token
      value             = token | quoted-string

    Each header is represented by a list of key/value pairs.  The value for a
    simple token (not part of a parameter) is None.  Syntactically incorrect
    headers will not necessarily be parsed as you would want.

    This is easier to describe with some examples:

    >>> split_header_words(['foo="bar"; port="80,81"; discard, bar=baz'])
    [[('foo', 'bar'), ('port', '80,81'), ('discard', None)], [('bar', 'baz')]]
    >>> split_header_words(['text/html; charset="iso-8859-1"'])
    [[('text/html', None), ('charset', 'iso-8859-1')]]
    >>> split_header_words([r'Basic realm="\"foo\bar\""'])
    [[('Basic', None), ('realm', '"foobar"')]]

    rz\1N�,z^[=\s;]*rWr	z&split_header_words bug: '%s', '%s', %s)�
isinstance�str�AssertionError�HEADER_TOKEN_REr@rkrB�HEADER_QUOTED_VALUE_RE�HEADER_ESCAPE_REr^�HEADER_VALUE_RE�rstrip�appendr\�
startswith�re�subn)
Z
header_values�resultr`Z	orig_text�pairsrE�name�valueZnon_junkZ
nr_junk_charsrrr�split_header_wordsUsJ-








��r}�([\"\\])cCs|g}|D]h}g}|D]F\}}|dk	rPt�d|�sDt�d|�}d|}d||f}|�|�q|r|�d�|��qd�|�S)a�Do the inverse (almost) of the conversion done by split_header_words.

    Takes a list of lists of (key, value) pairs and produces a single header
    value.  Attribute values are quoted if needed.

    >>> join_header_words([[("text/plain", None), ("charset", "iso-8859-1")]])
    'text/plain; charset="iso-8859-1"'
    >>> join_header_words([[("text/plain", None)], [("charset", "iso-8859-1")]])
    'text/plain, charset="iso-8859-1"'

    Nz^\w+$�\\\1z"%s"�%s=%s�; �, )rwr@�HEADER_JOIN_ESCAPE_REr^ru�join)Zlists�headersrz�attr�k�vrrr�join_header_words�sr�cCs0|�d�r|dd�}|�d�r,|dd�}|S)N�"r���)rv�endswith�r`rrr�strip_quotes�s


r�cCs�d}g}|D]�}g}d}t|�d��D]�\}}|��}|�d�\}}	}
|��}|sb|dkr&q�nq&|	rn|
��nd}
|dkr�|��}||kr�|}|dkr�|
dk	r�t|
�}
d}n|d	kr�|
dk	r�tt|
��}
|�||
f�q&|r|s�|�d
�|�|�q|S)a5Ad-hoc parser for Netscape protocol cookie-attributes.

    The old Netscape cookie format for Set-Cookie can for instance contain
    an unquoted "," in the expires field, so we have to use this ad-hoc
    parser instead of split_header_words.

    XXX This may not make the best possible effort to parse all the crap
    that Netscape Cookie headers contain.  Ronald Tschalar's HTTPClient
    parser is probably better, so could do worse than following that if
    this ever gives any trouble.

    Currently, this is also used for parsing RFC 2109 cookies.

    )�expires�domain�path�secure�version�port�max-ageF�;�=r	Nr�Tr�)r��0)�	enumerate�split�strip�	partitionrKr�rbru)Z
ns_headersZknown_attrsryZ	ns_headerrz�version_setZiiZparam�key�sep�val�lcrrr�parse_ns_headers�s>
r�z\.\d+$cCs:t�|�rdS|dkrdS|ddks2|ddkr6dSdS)z*Return True if text is a host domain name.FrWr	�.r�T��IPV4_REr@r�rrr�is_HDNs
r�cCsl|��}|��}||krdSt|�s(dS|�|�}|dksB|dkrFdS|�d�sTdSt|dd��shdSdS)a�Return True if domain A domain-matches domain B, according to RFC 2965.

    A and B may be host domain names or IP addresses.

    RFC 2965, section 1:

    Host names can be specified either as an IP address or a HDN string.
    Sometimes we compare one host name with another.  (Such comparisons SHALL
    be case-insensitive.)  Host A's name domain-matches host B's if

         *  their host name strings string-compare equal; or

         * A is a HDN string and has the form NB, where N is a non-empty
            name string, B has the form .B', and B' is a HDN string.  (So,
            x.y.com domain-matches .Y.com but not Y.com.)

    Note that domain-match is not a commutative operation: a.b.c.com
    domain-matches .c.com, but not the reverse.

    TFr�r	r�rN)rKr��rfindrv)�A�B�irrr�domain_matchs

r�cCst�|�rdSdS)zdReturn True if text is a sort-of-like a host domain name.

    For accepting/blocking domains.

    FTr�r�rrr�liberal_is_HDNFs
r�cCs`|��}|��}t|�r t|�s0||kr,dSdS|�d�}|rL|�|�rLdS|s\||kr\dSdS)z\For blocking/accepting domains.

    A and B may be host domain names or IP addresses.

    TFr�)rKr�rvr�)r�r��initial_dotrrr�user_domain_matchPs
r�z:\d+$cCsB|��}tj�|�d}|dkr,|�dd�}t�d|d�}|��S)z�Return request-host, as defined by RFC 2965.

    Variation from RFC: returned value is lowercased, for convenient
    comparison.

    rrWZHost)�get_full_url�urllib�parseZurlparseZ
get_header�cut_port_rer^rK)�request�url�hostrrr�request_hostesr�cCs4t|�}}|�d�dkr,t�|�s,|d}||fS)zzReturn a tuple (request-host, effective request-host name).

    As defined by RFC 2965, except both are lowercased.

    r�r��.local)r��findr�r@)r��erhn�req_hostrrr�eff_request_hostusr�cCs4|��}tj�|�}t|j�}|�d�s0d|}|S)z6Path component of request-URI, as defined by RFC 2965.�/)r�r�r�Zurlsplit�escape_pathr�rv)r�r��partsr�rrr�request_path�s

r�cCs`|j}|�d�}|dkrX||dd�}zt|�Wq\tk
rTtd|�YdSXnt}|S)N�:r	rznonnumeric port: '%s')r�r�rArLr�DEFAULT_HTTP_PORT)r�r�r�r�rrr�request_port�s


r�z%/;:@&=+$,!~*'()z%([0-9a-fA-F][0-9a-fA-F])cCsd|�d���S)Nz%%%sr)rBrP)rhrrr�uppercase_escaped_char�sr�cCstj�|t�}t�t|�}|S)zEEscape any invalid characters in HTTP URL, and uppercase all escapes.)r�r�Zquote�HTTP_PATH_SAFE�ESCAPED_CHAR_REr^r�)r�rrrr��s
r�cCsP|�d�}|dkrL||dd�}|�d�}t|�rL|dksD|dkrLd|S|S)aBReturn reach of host h, as defined by RFC 2965, section 1.

    The reach R of a host name H is defined as follows:

       *  If

          -  H is the host domain name of a host; and,

          -  H has the form A.B; and

          -  A has no embedded (that is, interior) dots; and

          -  B has at least one embedded dot, or B is the string "local".
             then the reach of H is .B.

       *  Otherwise, the reach of H is H.

    >>> reach("www.acme.com")
    '.acme.com'
    >>> reach("acme.com")
    'acme.com'
    >>> reach("acme.local")
    '.local'

    r�r	rNZlocal)r�r�)�hr��brrr�reach�s

r�cCs$t|�}t|t|j��sdSdSdS)z�

    RFC 2965, section 3.3.6:

        An unverifiable transaction is to a third-party host if its request-
        host U does not domain-match the reach R of the request-host O in the
        origin transaction.

    TFN)r�r�r�Zorigin_req_host)r�r�rrr�is_third_party�s
r�c@sNeZdZdZddd�Zdd�Zddd	�Zd
d�Zddd
�Zdd�Z	dd�Z
dS)ra�HTTP Cookie.

    This class represents both Netscape and RFC 2965 cookies.

    This is deliberately a very simple class.  It just holds attributes.  It's
    possible to construct Cookie instances that don't comply with the cookie
    standards.  CookieJar.make_cookies is the factory function for Cookie
    objects -- it deals with cookie parsing, supplying defaults, and
    normalising to the representation used in this class.  CookiePolicy is
    responsible for checking them to see whether they should be accepted from
    and returned to the server.

    Note that the port may be present in the headers, but unspecified ("Port"
    rather than"Port=80", for example); if this is the case, port is None.

    FcCs�|dk	rt|�}|dk	r$tt|��}|dkr<|dkr<td��||_||_||_||_||_|��|_	||_
||_|	|_|
|_
||_||_|
|_||_||_||_t�|�|_dS)NTz-if port is None, port_specified must be false)rAr[rLr�r{r|r��port_specifiedrKr��domain_specified�domain_initial_dotr��path_specifiedr�r��discard�comment�comment_url�rfc2109�copy�_rest)�selfr�r{r|r�r�r�r�r�r�r�r�r�r�r�r��restr�rrr�__init__�s.

zCookie.__init__cCs
||jkS�N�r�)r�r{rrr�has_nonstandard_attrszCookie.has_nonstandard_attrNcCs|j�||�Sr�)r��get)r�r{�defaultrrr�get_nonstandard_attrszCookie.get_nonstandard_attrcCs||j|<dSr�r�)r�r{r|rrr�set_nonstandard_attr szCookie.set_nonstandard_attrcCs,|dkrt��}|jdk	r(|j|kr(dSdS�NTF)rMr�)r��nowrrr�
is_expired#s
zCookie.is_expiredcCsX|jdkrd}n
d|j}|j||j}|jdk	rFd|j|jf}n|j}d||fS)NrWr�r�z<Cookie %s for %s>)r�r�r�r|r{)r��p�limitZ	namevaluerrr�__str__)s


zCookie.__str__cCslg}dD]$}t||�}|�d|t|�f�q|�dt|j��|�dt|j��d|jjd�|�fS)N)r�r{r|r�r�r�r�r�r�r�r�r�r�r�r�r�zrest=%sz
rfc2109=%sz%s(%s)r�)�getattrru�reprr�r��	__class__�__name__r�)r�rr{r�rrr�__repr__3s
zCookie.__repr__)F)N)N)r��
__module__�__qualname__�__doc__r�r�r�r�r�r�r�rrrrr�s�
*


c@s0eZdZdZdd�Zdd�Zdd�Zdd	�Zd
S)ra Defines which cookies get accepted from and returned to server.

    May also modify cookies, though this is probably a bad idea.

    The subclass DefaultCookiePolicy defines the standard rules for Netscape
    and RFC 2965 cookies -- override that if you want a customized policy.

    cCs
t��dS)z�Return true if (and only if) cookie should be accepted from server.

        Currently, pre-expired cookies never get this far -- the CookieJar
        class deletes such cookies itself.

        N��NotImplementedError�r��cookier�rrr�set_okKszCookiePolicy.set_okcCs
t��dS)zAReturn true if (and only if) cookie should be returned to server.Nr�r�rrr�	return_okTszCookiePolicy.return_okcCsdS)zMReturn false if cookies should not be returned, given cookie domain.
        Tr)r�r�r�rrr�domain_return_okXszCookiePolicy.domain_return_okcCsdS)zKReturn false if cookies should not be returned, given cookie path.
        Tr)r�r�r�rrr�path_return_ok]szCookiePolicy.path_return_okN)r�r�r�r�r�r�r�r�rrrrrBs
	c
@s�eZdZdZdZdZdZdZeeBZdddddddddeddd	f
d
d�Z	dd
�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Zd2d3�Zd4d5�Zd6d7�ZdS)8rzBImplements the standard rules for accepting and returning cookies.rrrUr	NTF)ZhttpsZwsscCsv||_||_||_||_||_||_|	|_|
|_||_||_	|
|_
|dk	rVt|�|_nd|_|dk	rlt|�}||_
dS)zAConstructor arguments should be passed as keyword arguments only.Nr)�netscape�rfc2965�rfc2109_as_netscape�hide_cookie2�
strict_domain�strict_rfc2965_unverifiable�strict_ns_unverifiable�strict_ns_domain�strict_ns_set_initial_dollar�strict_ns_set_path�secure_protocols�tuple�_blocked_domains�_allowed_domains)r��blocked_domains�allowed_domainsr�r�r�r�r�r�r�r�r�r�r�rrrr�ms"zDefaultCookiePolicy.__init__cCs|jS)z4Return the sequence of blocked domains (as a tuple).)r�r�rrrr�sz#DefaultCookiePolicy.blocked_domainscCst|�|_dS)z$Set the sequence of blocked domains.N)r�r)r�rrrr�set_blocked_domains�sz'DefaultCookiePolicy.set_blocked_domainscCs |jD]}t||�rdSqdSr�)rr�)r�r�Zblocked_domainrrr�
is_blocked�s

zDefaultCookiePolicy.is_blockedcCs|jS)z=Return None, or the sequence of allowed domains (as a tuple).)rrrrrr�sz#DefaultCookiePolicy.allowed_domainscCs|dk	rt|�}||_dS)z-Set the sequence of allowed domains, or None.N)r�r)r�rrrr�set_allowed_domains�sz'DefaultCookiePolicy.set_allowed_domainscCs.|jdkrdS|jD]}t||�rdSqdS)NFT)rr�)r�r�Zallowed_domainrrr�is_not_allowed�s


z"DefaultCookiePolicy.is_not_allowedcCsNtd|j|j�|jdk	st�dD]&}d|}t||�}|||�s"dSq"dS)z�
        If you override .set_ok(), be sure to call this method.  If it returns
        false, so should your subclass (assuming your subclass wants to be more
        strict about which cookies to accept).

        � - checking cookie %s=%sN)r��
verifiabilityr{r�r�r�Zset_ok_FT)rr{r|ror��r�r�r��nZfn_name�fnrrrr��s

zDefaultCookiePolicy.set_okcCsZ|jdkrtd|j|j�dS|jdkr:|js:td�dS|jdkrV|jsVtd�dSdS)Nz0   Set-Cookie2 without version attribute (%s=%s)Fr	�$   RFC 2965 cookies are switched off�$   Netscape cookies are switched offT)r�rr{r|r�r�r�rrr�set_ok_version�s
�z"DefaultCookiePolicy.set_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS�Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT�Zunverifiabler�r�r�rr�r�rrr�set_ok_verifiability�sz(DefaultCookiePolicy.set_ok_verifiabilitycCs0|jdkr,|jr,|j�d�r,td|j�dSdS)Nr	�$z'   illegal name (starts with '$'): '%s'FT)r�r�r{rvrr�rrr�set_ok_name�s
�zDefaultCookiePolicy.set_ok_namecCsL|jrHt|�}|jdks(|jdkrH|jrH|�|j|�sHtd|j|�dSdS)Nr	z7   path attribute %s is not a prefix of request path %sFT)r�r�r�r�r�r�r)r�r�r��req_pathrrr�set_ok_path�s
����zDefaultCookiePolicy.set_ok_pathc
Cs�|�|j�rtd|j�dS|�|j�r8td|j�dS|j�r�t|�\}}|j}|jr�|�d�dkr�|�d�}|�dd|�}|dkr�||dd�}||d|�}	|	�	�dkr�t
|�dkr�td	|�dS|�d�r�|dd�}
n|}
|
�d�dk}|�s|d
k�rtd|�dS|j
dk�rX|�|��sX|�d��sXd|�|��sXtd||�dS|j
dk�sr|j|j@�r�t||��s�td
||�dS|j
dk�s�|j|j@�r�|dt
|��}|�d�dk�r�t�|��s�td||�dSdS)N�"   domain %s is in user block-listF�&   domain %s is not in user allow-listr�rr	r)�coZacZcomZeduZorgZnetZgovZmilrAZaeroZbiz�catZcoop�infoZjobsZmobiZmuseumr{ZproZtravelZeuz&   country-code second level domain %sr�z/   non-local domain %s contains no embedded dotzO   effective request-host %s (even with added initial dot) does not end with %sz5   effective request-host %s does not domain-match %sz.   host prefix %s for domain %s contains a dotT)rr�rrr�r�r��countr�rK�lenrvr�r�r�r��DomainRFC2965Matchr��DomainStrictNoDotsr�r@)
r�r�r�r�r�r�r��jZtldZsldZundotted_domainZ
embedded_dotsZhost_prefixrrr�
set_ok_domain�s|

�

����
��
���z!DefaultCookiePolicy.set_ok_domainc	Cs�|jr�t|�}|dkrd}nt|�}|j�d�D]@}zt|�Wn"tk
rbtd|�YdSX||kr0q�q0td||j�dSdS)N�80rlz   bad port %s (not numeric)Fz$   request port (%s) not found in %sT)r�r�rnr�r�rArLr�r�r�r�Zreq_portr�rrr�set_ok_port+s&

�zDefaultCookiePolicy.set_ok_portcCs@td|j|j�dD]&}d|}t||�}|||�sdSqdS)z�
        If you override .return_ok(), be sure to call this method.  If it
        returns false, so should your subclass (assuming your subclass wants to
        be more strict about which cookies to return).

        r	)r�r
r�r�r�r�Z
return_ok_FT)rr{r|r�rrrrr�@s	

zDefaultCookiePolicy.return_okcCs<|jdkr|jstd�dS|jdkr8|js8td�dSdS)Nr	rFrT)r�r�rr�r�rrr�return_ok_versionRsz%DefaultCookiePolicy.return_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdSrrr�rrr�return_ok_verifiability[sz+DefaultCookiePolicy.return_ok_verifiabilitycCs"|jr|j|jkrtd�dSdS)Nz(   secure cookie with non-secure requestFT)r��typer�rr�rrr�return_ok_securegsz$DefaultCookiePolicy.return_ok_securecCs|�|j�rtd�dSdS)Nz   cookie expiredFT)r��_nowrr�rrr�return_ok_expiresmsz%DefaultCookiePolicy.return_ok_expirescCsN|jrJt|�}|dkrd}|j�d�D]}||kr&qJq&td||j�dSdS)Nr#rlz0   request port %s does not match cookie port %sFT)r�r�r�rr$rrr�return_ok_portss�z"DefaultCookiePolicy.return_ok_portcCs�t|�\}}|j}|r*|�d�s*d|}n|}|jdkr^|j|j@r^|js^||kr^td�dS|jdkr�t||�s�td||�dS|jdkr�d|�	|�s�td||�dSdS)Nr�r	zQ   cookie with unspecified domain does not string-compare equal to request domainFzQ   effective request-host name %s does not domain-match RFC 2965 cookie domain %sz;   request-host %s does not match Netscape cookie domain %sT)
r�r�rvr�r��DomainStrictNonDomainr�rr�r�)r�r�r�r�r�r��	dotdomainrrr�return_ok_domain�s6


�����z$DefaultCookiePolicy.return_ok_domaincCs�t|�\}}|�d�sd|}|�d�s0d|}|rH|�d�sHd|}n|}|�|�sd|�|�sddS|�|�r|td|�dS|�|�r�td|�dSdS)Nr�FrrT)r�rvr�rrr)r�r�r�r�r�r.rrrr��s"






z$DefaultCookiePolicy.domain_return_okcCsbtd|�t|�}t|�}||kr&dS|�|�rR|�d�sN|||d�dkrRdStd||�dS)Nz- checking cookie path=%sTr�rz  %s does not path-match %sF)rr�rrvr�)r�r�r�rZpathlenrrrr��s

��z"DefaultCookiePolicy.path_return_ok) r�r�r�r�r r-rZ
DomainLiberalZDomainStrictr�rrrrrrr�rrrrr"r%r�r&r'r)r+r,r/r�r�rrrrrcsT�
#	;	cCst|���}t|j|�Sr�)�sorted�keys�mapr�)Zadictr1rrr�vals_sorted_by_key�sr3c	csVt|�}|D]D}d}z
|jWntk
r2YnXd}t|�EdH|s|VqdS)zBIterates over nested mapping, depth-first, in sorted order by key.FTN)r3�items�AttributeError�
deepvalues)�mapping�values�objrrrr6�s
r6c@seZdZdS)�AbsentN�r�r�r�rrrrr:�sr:c@s�eZdZdZe�d�Ze�d�Ze�d�Ze�d�Z	e�d�Z
e�dej�Zd3d	d
�Z
dd�Zd
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd4d%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Z d1d2�Z!dS)5rz�Collection of HTTP cookies.

    You may not need to know about this class: try
    urllib.request.build_opener(HTTPCookieProcessor).open(url).
    z\Wr~z\.?[^.]*z[^.]*z^\.+z^\#LWP-Cookies-(\d+\.\d+)NcCs(|dkrt�}||_t��|_i|_dSr�)r�_policy�
_threading�RLock�
_cookies_lock�_cookies�r��policyrrrr��s

zCookieJar.__init__cCs
||_dSr�)r<rArrr�
set_policy�szCookieJar.set_policycCs�g}|j�||�sgStd|�|j|}|��D]T}|j�||�sFq2||}|��D].}|j�||�srtd�qVtd�|�|�qVq2|S)Nz!Checking %s for cookies to returnz   not returning cookiez   it's a match)	r<r�rr@r1r�r8r�ru)r�r�r��cookiesZcookies_by_pathr�Zcookies_by_namer�rrr�_cookies_for_domain�s 

zCookieJar._cookies_for_domaincCs*g}|j��D]}|�|�||��q|S)z2Return a list of cookies to be returned to server.)r@r1�extendrE)r�r�rDr�rrr�_cookies_for_requestszCookieJar._cookies_for_requestc	Cs<|jdd�dd�d}g}|D�]}|j}|sHd}|dkrH|�d|�|jdk	rz|j�|j�rz|dkrz|j�d	|j�}n|j}|jdkr�|�|j�n|�d
|j|f�|dkr|j	r�|�d|j
�|j�d��r|j}|j
s�|�d�r�|d
d�}|�d|�|jdk	rd}|j�r,|d|j}|�|�q|S)z�Return a list of cookie-attributes to be returned to server.

        like ['foo="bar"; $Path="/"', ...]

        The $Version attribute is also added when appropriate (currently only
        once per request).

        cSs
t|j�Sr�)rr�)�arrr�<lambda>�z)CookieJar._cookie_attrs.<locals>.<lambda>T)r��reverseFr	z$Version=%sNrr�z
$Path="%s"r�rz$Domain="%s"z$Portz="%s")�sortr�rur|�non_word_rer@�quote_rer^r{r�r�r�rvr�r�r�)	r�rDr��attrsr�r�r|r�r�rrr�
_cookie_attrssF


��
�
zCookieJar._cookie_attrscCs�td�|j��z�tt���|j_|_|�|�}|�	|�}|r^|�
d�s^|�dd�|��|jj
r�|jjs�|�
d�s�|D]}|jdkr||�dd�q�q|W5|j��X|��dS)z�Add correct Cookie: header to request (urllib.request.Request object).

        The Cookie2 header is also added unless policy.hide_cookie2 is true.

        �add_cookie_headerrr�ZCookie2rz$Version="1"N)rr?�acquire�releaserArMr<r*rGrPZ
has_headerZadd_unredirected_headerr�r�r�r��clear_expired_cookies)r�r�rDrOr�rrrrQIs*



��

zCookieJar.add_cookie_headerc
Cs�g}d}d}|D�]z}|d\}}d}d}	i}
i}|dd�D�]0\}}
|��}||ks`||krd|}||krx|
dkrxd}
||
kr�q>|dkr�|
dkr�td	�d}	�qr|
��}
|d
kr�|r�q>|
dkr�td�q>|dk�r d}zt|
�}
Wn*tk
�rtd
�d}	Y�qrYnXd
}|j|
}
||k�s4||k�rh|
dk�r^|dk�r^td|�d}	�qr|
|
|<q>|
||<q>|	�rzq|�|||
|f�q|S)aReturn 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.

        )r�r�)r�r�r�r�r�r�r��
commenturlr	FrNTr�z%   missing value for domain attributer�zM   missing or invalid value for expires attribute: treating as session cookier�z?   missing or invalid (non-numeric) value for max-age attribute)r�r�rUz!   missing value for %s attribute)rKrrArLr*ru)r��	attrs_set�
cookie_tuples�
boolean_attrs�value_attrsZcookie_attrsr{r|Zmax_age_setZ
bad_cookie�standardr�r�r�r�rrr�_normalized_cookie_tuplesjsh





�

z#CookieJar._normalized_cookie_tuplescCs&|\}}}}|�dt�}|�dt�}|�dt�}	|�dt�}
|�dd�}|dk	rtzt|�}Wntk
rrYdSX|�dd�}|�dd�}
|�d	d�}|�d
d�}|tk	r�|dkr�d}t|�}nXd}t|�}|�d
�}|dk�r|dkr�|d|�}n|d|d�}t|�dk�rd
}|tk	}d}|�r:t|�	d��}|tk�rVt
|�\}}|}n|�	d��sjd|}d}|	tk	�r�|	dk�r�t|�}	nd}t�
dd|	�}	nd}	|
tk�r�d}
d}
nH|
|jk�rz|�|||�Wntk
�r�YnXtd|||�dSt||||	||||||||
|
|||�S)Nr�r�r�r�r�r�Fr�r�rUrWTr�r�r	rr�z\s+z2Expiring cookie, domain='%s', path='%s', name='%s')r�r:rArLr�r�r�r�boolrvr�r�rwr^r*�clear�KeyErrorrr)r��tupr�r{r|rZr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrr�_cookie_from_cookie_tuple�s�







��z#CookieJar._cookie_from_cookie_tuplecCs6|�|�}g}|D]}|�||�}|r|�|�q|Sr�)r[r`ru)r�rVr�rWrDr_r�rrr�_cookies_from_attrs_set's
z!CookieJar._cookies_from_attrs_setcCsHt|jdd�}|dkr |jj}|D]}|jdkr$d|_|r$d|_q$dS)Nr�rTr	)r�r<r�r�r�)r�rDZ
rfc2109_as_nsr�rrr�_process_rfc2109_cookies0s

z"CookieJar._process_rfc2109_cookiesc
Cs:|��}|�dg�}|�dg�}tt���|j_|_|jj}|jj}|sN|rf|sV|rf|s^|rf|sj|sjgSz|�t	|�|�}Wnt
k
r�t�g}YnX|�r6|�r6z|�t|�|�}	Wnt
k
r�t�g}	YnX|�
|	�|�r&i}
|D]}d|
|j|j|jf<q�|
fdd�}t||	�}	|	�r6|�|	�|S)zAReturn sequence of Cookie objects extracted from response object.zSet-Cookie2z
Set-CookieNcSs|j|j|jf}||kSr�)r�r�r{)Z	ns_cookie�lookupr�rrr�no_matching_rfc2965isz3CookieJar.make_cookies.<locals>.no_matching_rfc2965)rZget_allrArMr<r*r�r�rar}�	Exceptionrr�rbr�r�r{�filterrF)
r��responser�r�Zrfc2965_hdrsZns_hdrsr�r�rDZ
ns_cookiesrcr�rdrrr�make_cookies<s^�������
�



zCookieJar.make_cookiescCsN|j��z2tt���|j_|_|j�||�r:|�|�W5|j��XdS)z-Set a cookie if policy says it's OK to do so.N)	r?rRrSrArMr<r*r��
set_cookier�rrr�set_cookie_if_okss
zCookieJar.set_cookie_if_okcCsl|j}|j��zJ|j|kr&i||j<||j}|j|krDi||j<||j}|||j<W5|j��XdS)z?Set a cookie, without checking whether or not it should be set.N)r@r?rRrSr�r�r{)r�r��cZc2Zc3rrrri�s






zCookieJar.set_cookiecCsbtd|���|j��z8|�||�D]&}|j�||�r&td|�|�|�q&W5|j��XdS)zAExtract cookies from response, where allowable given the request.zextract_cookies: %sz setting cookie: %sN)	rrr?rRrSrhr<r�ri)r�rgr�r�rrr�extract_cookies�s

zCookieJar.extract_cookiescCst|dk	r2|dks|dkr td��|j|||=n>|dk	rX|dkrJtd��|j||=n|dk	rj|j|=ni|_dS)a�Clear some cookies.

        Invoking this method without arguments will clear all cookies.  If
        given a single argument, only cookies belonging to that domain will be
        removed.  If given two arguments, cookies belonging to the specified
        path within that domain are removed.  If given three arguments, then
        the cookie with the specified name, path and domain is removed.

        Raises KeyError if no matching cookie exists.

        Nz8domain and path must be given to remove a cookie by namez.domain must be given to remove cookies by path)rLr@)r�r�r�r{rrrr]�s��
zCookieJar.clearcCsD|j��z(|D]}|jr|�|j|j|j�qW5|j��XdS)z�Discard all session cookies.

        Note that the .save() method won't save session cookies anyway, unless
        you ask otherwise by passing a true ignore_discard argument.

        N)r?rRrSr�r]r�r�r{)r�r�rrr�clear_session_cookies�s
zCookieJar.clear_session_cookiescCsP|j��z4t��}|D]"}|�|�r|�|j|j|j�qW5|j��XdS)a�Discard all expired cookies.

        You probably don't need to call this method: expired cookies are never
        sent back to the server (provided you're using DefaultCookiePolicy),
        this method is called by CookieJar itself every so often, and the
        .save() method won't save expired cookies anyway (unless you ask
        otherwise by passing a true ignore_expires argument).

        N)	r?rRrSrMr�r]r�r�r{)r�r�r�rrrrT�s


zCookieJar.clear_expired_cookiescCs
t|j�Sr�)r6r@rrrr�__iter__�szCookieJar.__iter__cCsd}|D]}|d}q|S)z#Return number of contained cookies.r	rr)r�r�r�rrr�__len__�s
zCookieJar.__len__cCs2g}|D]}|�t|��qd|jjd�|�fS�Nz<%s[%s]>r�)rur�r�r�r��r��rr�rrrr��szCookieJar.__repr__cCs2g}|D]}|�t|��qd|jjd�|�fSrp)rurnr�r�r�rqrrrr��szCookieJar.__str__)N)NNN)"r�r�r�r�rw�compilerMrNZstrict_domain_reZ	domain_reZdots_re�ASCII�magic_rer�rCrErGrPrQr[r`rarbrhrjrirlr]rmrTrnror�r�rrrrr�s8





;!a\	7


c@seZdZdS)rNr;rrrrr�sc@s8eZdZdZddd�Zd
dd�Zddd	�Zdd
d�ZdS)rz6CookieJar that can be loaded from and saved to a file.NFcCs2t�||�|dk	rt�|�}||_t|�|_dS)z}
        Cookies are NOT loaded from the named file until either the .load() or
        .revert() method is called.

        N)rr��os�fspath�filenamer\�	delayload)r�rxryrBrrrr��s

zFileCookieJar.__init__cCs
t��dS)zSave cookies to a file.Nr�)r�rx�ignore_discard�ignore_expiresrrr�save�szFileCookieJar.savec	CsJ|dkr"|jdk	r|j}ntt��t|��}|�||||�W5QRXdS)zLoad cookies from a file.N)rxrL�MISSING_FILENAME_TEXT�open�_really_load�r�rxrzr{rrrr�loads

zFileCookieJar.loadcCs�|dkr"|jdk	r|j}ntt��|j��zFt�|j�}i|_z|�	|||�Wnt
k
rn||_�YnXW5|j��XdS)z�Clear all cookies and reload cookies from a saved file.

        Raises LoadError (or OSError) if reversion is not successful; the
        object's state will not be altered if this happens.

        N)rxrLr}r?rRrSr�Zdeepcopyr@r��OSError)r�rxrzr{Z	old_staterrr�revert	s

zFileCookieJar.revert)NFN)NFF)NFF)NFF)r�r�r�r�r�r|r�r�rrrrr�s


	�cCs |j|jfd|jfd|jfg}|jdk	r8|�d|jf�|jrH|�d�|jrX|�d�|jrh|�d�|j	rx|�d�|j
r�|�d	tt|j
��f�|j
r�|�d
�|jr�|�d|jf�|jr�|�d|jf�t|j���}|D]}|�|t|j|�f�q�|�d
t|j�f�t|g�S)z�Return string representation of Cookie in the LWP cookie file format.

    Actually, the format is extended a bit -- see module docstring.

    r�r�Nr�)�	path_specN)�	port_specN)�
domain_dotN)r�Nr�)r�Nr�rUr�)r{r|r�r�r�rur�r�r�r�r�r5r[r�r�r�r0r�r1rnr�r�)r�r�r1r�rrr�lwp_cookie_str$s:
�




�
r�c@s,eZdZdZddd�Zddd�Zd	d
�ZdS)
ra[
    The LWPCookieJar saves a sequence of "Set-Cookie3" lines.
    "Set-Cookie3" is the format used by the libwww-perl library, not known
    to be compatible with any browser, but which is easy to read and
    doesn't lose information about RFC 2965 cookies.

    Additional methods

    as_lwp_str(ignore_discard=True, ignore_expired=True)

    TcCsTt��}g}|D]2}|s |jr q|s0|�|�r0q|�dt|��qd�|dg�S)z�Return cookies as a string of "\n"-separated "Set-Cookie3" headers.

        ignore_discard and ignore_expires: see docstring for FileCookieJar.save

        zSet-Cookie3: %s�
rW)rMr�r�rur�r�)r�rzr{r�rrr�rrr�
as_lwp_strMs
zLWPCookieJar.as_lwp_strNFc	CsX|dkr"|jdk	r|j}ntt��t|d��"}|�d�|�|�||��W5QRXdS)N�wz#LWP-Cookies-2.0
)rxrLr}r~�writer�r�rrrr|]s

zLWPCookieJar.savecCs0|��}|j�|�s$d|}t|��t��}d}d}	d}
�z�|��}|dkrP�q�|�|�s\q<|t|�d���}t|g�D�]f}|d\}
}i}i}|	D]}d||<q�|dd�D]n\}}|dk	r�|�	�}nd}||
ks�||	kr�|}||	k�r|dkr�d	}|||<q�||
k�r|||<q�|||<q�|j
}|d
�}|d�}|dk	�rJt|�}|dk�rXd	}|d�}|�d
�}t|d�|
||d�|d�|||d�|d�|d�|d�|||d�|d�|�}|�s�|j
�r�qz|�s�|�|��r�qz|�|�qzq<WnBtk
�r�Yn,tk
�r*t�td||f��YnXdS)Nz5%r does not look like a Set-Cookie3 (LWP) format filezSet-Cookie3:)r�r�r�r�r�)r�r�r�r�r�r�rUrWr	FrTr�r�r�r�r�r�r�r�r�r�r�r�rUz&invalid Set-Cookie3 format file %r: %r)�readlinerur@rrMrvrr�r}rKr�rerr�r�rir�rer)r�rrxrzr{�magicrr��headerrXrY�line�datar{r|rZr�r�r�r�r�r�r�r�r�rkrrrris��










�
�zLWPCookieJar._really_load)TT)NFF)r�r�r�r�r�r|rrrrrr@s

c@s0eZdZdZe�d�ZdZdd�Zd
dd	�Z	dS)ra�

    WARNING: you may want to backup your browser's cookies file if you use
    this class to save cookies.  I *think* it works, but there have been
    bugs in the past!

    This class differs from CookieJar only in the format it uses to save and
    load cookies to and from a file.  This class uses the Mozilla/Netscape
    `cookies.txt' format.  lynx uses this file format, too.

    Don't expect cookies saved while the browser is running to be noticed by
    the browser (in fact, Mozilla on unix will overwrite your saved cookies if
    you change them on disk while it's running; on Windows, you probably can't
    save at all while the browser is running).

    Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
    Netscape cookies on saving.

    In particular, the cookie version and port number information is lost,
    together with information about whether or not Path, Port and Discard were
    specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
    domain as set in the HTTP header started with a dot (yes, I'm aware some
    domains in Netscape files start with a dot and some don't -- trust me, you
    really don't want to know any more about this).

    Note that though Mozilla and Netscape use the same format, they use
    slightly different headers.  The class saves cookies using the Netscape
    header by default (Mozilla can cope with that).

    z#( Netscape)? HTTP Cookie Filezr# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

cCstt��}|��}|j�|�s(td|���z|��}|dkr@�q*|�d�rV|dd�}|���d�s,|��dkrrq,|�d�\}}	}
}}}
}|dk}|	dk}	|
dkr�|}
d}|�d�}|	|ks�t	�d	}|dkr�d}d
}t
d|
|dd	||	||
d	|||ddi�}|�s
|j�r
q,|�s|�|��rq,|�
|�q,WnBtk
�rD�Yn,tk
�rnt�td||f��YnXdS)
Nz4%r does not look like a Netscape format cookies filerWr�r�)�#r�	�TRUEr�FTr	z+invalid Netscape format cookies file %r: %r)rMr�rur@rr�r�rvr�rorr�r�rir�rer)r�rrxrzr{r�r�r�r�r�r�r�r�r{r|r�r�rkrrrr�st��

��
�
�zMozillaCookieJar._really_loadNFc
Cs�|dkr"|jdk	r|j}ntt��t|d���}|�|j�t��}|D]�}|sV|jrVqF|sf|�|�rfqF|j	rrd}nd}|j
�d�r�d}nd}|jdk	r�t
|j�}	nd}	|jdkr�d}
|j}n|j}
|j}|�d�|j
||j||	|
|g�d�qFW5QRXdS)Nr�r�ZFALSEr�rWr�r�)rxrLr}r~r�r�rMr�r�r�r�rvr�rnr|r{r�r�)r�rxrzr{rr�r�r�r�r�r{r|rrrr| sH



���zMozillaCookieJar.save)NFF)
r�r�r�r�rwrsrur�rr|rrrrr�s

A)N)N)Xr��__all__rvr�r-rwrMZurllib.parser�Zurllib.requestZ	threadingr=Zhttp.clientZhttpZcalendarr
rrrrnZclientZ	HTTP_PORTr�r}rr%r,r6r7rIr(rurKr5r8r>rsrtr?rFrTrY�Ir]�Xr_rbrcrerkrprqrsrrr}r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrr3r6r:rr�rrr�rrrrrr�<module>s��
�

8�
�
�8
�!



U
D'


#b!b7x__pycache__/cookies.cpython-38.opt-2.pyc000064400000025111150532417300014000 0ustar00U

e5d�O�
@spddlZddlZdddgZdjZdjZdjZGdd�de�Zej	ej
d	Zed
Zdd�e
ed
��e
eee��D�Ze�ed�ded�di�e�de�e��jZdd�Ze�d�Ze�d�Zdd�ZdddddddgZdd d!d"d#d$d%d&d'd(d)d*d+g
Zdeefd,d-�ZGd.d/�d/e�Zd0Z e d1Z!e�d2e d3e!d4ej"ej#B�Z$Gd5d�de�Z%Gd6d�de%�Z&dS)7�N�CookieError�
BaseCookie�SimpleCookie�z; � c@seZdZdS)rN)�__name__�
__module__�__qualname__�r
r
�$/usr/lib64/python3.8/http/cookies.pyr�sz!#$%&'*+-.^_`|~:z
 ()/<=>?@[]{}cCsi|]}|d|�qS)z\%03or
)�.0�nr
r
r�
<dictcomp>�s�r��"�\"�\z\\z[%s]+cCs*|dkst|�r|Sd|�t�dSdS)Nr)�
_is_legal_key�	translate�_Translator��strr
r
r�_quote�srz\\[0-3][0-7][0-7]z[\\].cCsN|dkst|�dkr|S|ddks0|ddkr4|S|dd�}d}t|�}g}d|krf|k�rFnn�t�||�}t�||�}|s�|s�|�||d���qFd}}|r�|�d�}|r�|�d�}|�r|r�||k�r|�|||��|�||d�|d}qP|�|||��|�tt||d|d�d���|d}qPt|�S)N�rr������)	�len�
_OctalPatt�search�
_QuotePatt�append�start�chr�int�	_nulljoin)r�ir
�resZo_matchZq_match�j�kr
r
r�_unquote�s6


$
r+ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc	CsRddlm}m}|�}|||�\	}}}}	}
}}}
}d|||||||	|
|fS)Nr)�gmtime�timez#%s, %02d %3s %4d %02d:%02d:%02d GMT)r-r,)ZfutureZweekdaynameZ	monthnamer,r-ZnowZyearZmonthZdayZhhZmmZssZwd�y�zr
r
r�_getdate�s�r0c
@s�eZdZddddddddd	d
�	ZddhZd
d�Zedd��Zedd��Zedd��Z	dd�Z
d1dd�Zdd�Ze
jZdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd2d)d*�ZeZd+d,�Zd3d-d.�Zd4d/d0�ZdS)5�Morsel�expires�Path�CommentZDomainzMax-AgeZSecureZHttpOnlyZVersionZSameSite)	r2�path�commentZdomain�max-age�secure�httponly�versionZsamesiter8r9cCs0d|_|_|_|jD]}t�||d�qdS)Nr)�_key�_value�_coded_value�	_reserved�dict�__setitem__)�self�keyr
r
r�__init__ s
zMorsel.__init__cCs|jS�N)r;�rAr
r
rrB(sz
Morsel.keycCs|jSrD)r<rEr
r
r�value,szMorsel.valuecCs|jSrD)r=rEr
r
r�coded_value0szMorsel.coded_valuecCs2|��}||jkr td|f��t�|||�dS�NzInvalid attribute %r)�lowerr>rr?r@)rA�K�Vr
r
rr@4s
zMorsel.__setitem__NcCs.|��}||jkr td|f��t�|||�SrH)rIr>rr?�
setdefault)rArB�valr
r
rrL:s
zMorsel.setdefaultcCs>t|t�stSt�||�o<|j|jko<|j|jko<|j|jkSrD)�
isinstancer1�NotImplementedr?�__eq__r<r;r=�rAZmorselr
r
rrP@s

�
�
�z
Morsel.__eq__cCs$t�}t�||�|j�|j�|SrD)r1r?�update�__dict__rQr
r
r�copyJszMorsel.copycCsRi}t|���D]0\}}|��}||jkr8td|f��|||<qt�||�dSrH)r?�itemsrIr>rrR)rA�values�datarBrMr
r
rrRPs

z
Morsel.updatecCs|��|jkSrD)rIr>)rArJr
r
r�
isReservedKeyYszMorsel.isReservedKeycCsH|��|jkrtd|f��t|�s2td|f��||_||_||_dS)Nz Attempt to set a reserved key %rzIllegal key %r)rIr>rrr;r<r=)rArBrMZ	coded_valr
r
r�set\sz
Morsel.setcCs|j|j|jd�S)N)rBrFrG�r;r<r=rEr
r
r�__getstate__gs�zMorsel.__getstate__cCs"|d|_|d|_|d|_dS)NrBrFrGrZ)rA�stater
r
r�__setstate__ns

zMorsel.__setstate__�Set-Cookie:cCsd||�|�fS)Nz%s %s)�OutputString)rA�attrs�headerr
r
r�outputssz
Morsel.outputcCsd|jj|��fS)N�<%s: %s>)�	__class__rr_rEr
r
r�__repr__xszMorsel.__repr__cCsd|�|��dd�S)Nz�
        <script type="text/javascript">
        <!-- begin hiding
        document.cookie = "%s";
        // end hiding -->
        </script>
        rr)r_�replace)rAr`r
r
r�	js_output{s�zMorsel.js_outputcCs$g}|j}|d|j|jf�|dkr,|j}t|���}|D]�\}}|dkrNq<||krXq<|dkr�t|t�r�|d|j|t|�f�q<|dkr�t|t�r�|d|j||f�q<|dkr�t|t	�r�|d|j|t
|�f�q<||jk�r|�r|t	|j|��q<|d|j||f�q<t|�S)N�%s=%srr2r7z%s=%dr6)
r"rBrGr>�sortedrUrNr%r0rr�_flags�_semispacejoin)rAr`�resultr"rUrBrFr
r
rr_�s,zMorsel.OutputString)N)Nr^)N)N)rrr	r>rjrC�propertyrBrFrGr@rLrP�object�__ne__rTrRrXrYr[r]rb�__str__rergr_r
r
r
rr1�sB�



	


r1z,\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=z\[\]z�
    \s*                            # Optional whitespace at start of cookie
    (?P<key>                       # Start of group 'key'
    [a	]+?   # Any word of at least one letter
    )                              # End of group 'key'
    (                              # Optional group: there may not be a value.
    \s*=\s*                          # Equal Sign
    (?P<val>                         # Start of group 'val'
    "(?:[^\\"]|\\.)*"                  # Any doublequoted string
    |                                  # or
    \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT  # Special case for "expires" attr
    |                                  # or
    [a-]*      # Any word or empty string
    )                                # End of group 'val'
    )?                             # End of optional value group
    \s*                            # Any number of spaces.
    (\s+|;|$)                      # Ending either at space, semicolon, or EOS.
    c@sjeZdZdd�Zdd�Zddd�Zdd	�Zd
d�Zddd�ZeZ	dd�Z
ddd�Zdd�Ze
fdd�ZdS)rcCs||fSrDr
�rArMr
r
r�value_decode�szBaseCookie.value_decodecCst|�}||fSrDr�rArMZstrvalr
r
r�value_encode�szBaseCookie.value_encodeNcCs|r|�|�dSrD)�load)rA�inputr
r
rrC�szBaseCookie.__init__cCs.|�|t��}|�|||�t�|||�dSrD)�getr1rYr?r@)rArBZ
real_valuerG�Mr
r
rZ__set�szBaseCookie.__setcCs:t|t�rt�|||�n|�|�\}}|�|||�dSrD)rNr1r?r@rt�_BaseCookie__set)rArBrF�rval�cvalr
r
rr@�s
zBaseCookie.__setitem__r^�
cCs:g}t|���}|D]\}}|�|�||��q|�|�SrD)rirUr"rb�join)rAr`ra�seprlrUrBrFr
r
rrb�s
zBaseCookie.outputcCsJg}t|���}|D] \}}|�d|t|j�f�qd|jjt|�fS)Nrhrc)rirUr"�reprrFrdr�
_spacejoin)rA�lrUrBrFr
r
rre�s
zBaseCookie.__repr__cCs6g}t|���}|D]\}}|�|�|��qt|�SrD)rirUr"rgr&)rAr`rlrUrBrFr
r
rrgs
zBaseCookie.js_outputcCs4t|t�r|�|�n|��D]\}}|||<qdSrD)rNr�_BaseCookie__parse_stringrU)rAZrawdatarBrFr
r
rru
s


zBaseCookie.loadcCshd}t|�}g}d}d}d}d|kr2|k�rnn�|�||�}	|	sJ�q|	�d�|	�d�}
}|	�d�}|
ddkr�|s|q|�||
dd�|f�q|
��tjkr�|s�dS|dkr�|
��tjkr�|�||
df�q�dSn|�||
t	|�f�q|dk	�r|�||
|�
|�f�d}qdSqd}|D]>\}
}
}|
|k�rB|||
<n|\}}|�|
||�||
}�q$dS)	NrFrrrBrM�$T)r�match�group�endr"rIr1r>rjr+rrry)rArZpattr'r
Zparsed_itemsZmorsel_seenZTYPE_ATTRIBUTEZ
TYPE_KEYVALUEr�rBrFrx�tprzr{r
r
rZ__parse_stringsF



zBaseCookie.__parse_string)N)Nr^r|)N)rrr	rrrtrCryr@rbrprergru�_CookiePatternr�r
r
r
rr�s		
	

c@seZdZdd�Zdd�ZdS)rcCst|�|fSrD)r+rqr
r
rrr\szSimpleCookie.value_decodecCst|�}|t|�fSrD)rrrsr
r
rrt_szSimpleCookie.value_encodeN)rrr	rrrtr
r
r
rrUs)'�re�string�__all__r}r&rkr��	ExceptionrZ
ascii_lettersZdigitsZ_LegalCharsZ_UnescapedCharsrY�range�map�ordrrR�compile�escape�	fullmatchrrrr!r+Z_weekdaynameZ
_monthnamer0r?r1Z_LegalKeyCharsZ_LegalValueChars�ASCII�VERBOSEr�rrr
r
r
r�<module>�sp
��

2�4����
�
__pycache__/__init__.cpython-38.opt-1.pyc000064400000013662150532417300014112 0ustar00U

e5d��@s&ddlmZdgZGdd�de�ZdS)�)�IntEnum�
HTTPStatusc@seZdZdZdAdd�ZdZdZdZdZd	Z	d
Z
dZdZd
Z
dZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZd Z d!Z!d"Z"d#Z#d$Z$d%Z%d&Z&d'Z'd(Z(d)Z)d*Z*d+Z+d,Z,d-Z-d.Z.d/Z/d0Z0d1Z1d2Z2d3Z3d4Z4d5Z5d6Z6d7Z7d8Z8d9Z9d:Z:d;Z;d<Z<d=Z=d>Z>d?Z?d@S)Bra�HTTP status codes and reason phrases

    Status codes from the following RFCs are all observed:

        * RFC 7231: Hypertext Transfer Protocol (HTTP/1.1), obsoletes 2616
        * RFC 6585: Additional HTTP Status Codes
        * RFC 3229: Delta encoding in HTTP
        * RFC 4918: HTTP Extensions for WebDAV, obsoletes 2518
        * RFC 5842: Binding Extensions to WebDAV
        * RFC 7238: Permanent Redirect
        * RFC 2295: Transparent Content Negotiation in HTTP
        * RFC 2774: An HTTP Extension Framework
        * RFC 7725: An HTTP Status Code to Report Legal Obstacles
        * RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2)
    �cCs"t�||�}||_||_||_|S)N)�int�__new__�_value_�phrase�description)�cls�valuerr	�obj�r
�%/usr/lib64/python3.8/http/__init__.pyrs
zHTTPStatus.__new__)�dZContinuez!Request received, please continue)�ezSwitching Protocolsz.Switching to new protocol; obey Upgrade header)�fZ
Processing)���OKz#Request fulfilled, document follows)��ZCreatedzDocument created, URL follows)��ZAcceptedz/Request accepted, processing continues off-line)��zNon-Authoritative InformationzRequest fulfilled from cache)��z
No Contentz"Request fulfilled, nothing follows)��z
Reset Contentz"Clear input form for further input)��zPartial ContentzPartial content follows)��zMulti-Status)��zAlready Reported)��zIM Used)i,zMultiple Choicesz,Object has several resources -- see URI list)i-zMoved Permanently�(Object moved permanently -- see URI list)i.ZFound�(Object moved temporarily -- see URI list)i/z	See Otherz'Object moved -- see Method and URL list)i0zNot Modifiedz)Document has not changed since given time)i1z	Use Proxyz@You must use proxy specified in Location to access this resource)i3zTemporary Redirectr)i4zPermanent Redirectr)i�zBad Requestz(Bad request syntax or unsupported method)i�ZUnauthorizedz*No permission -- see authorization schemes)i�zPayment Requiredz"No payment -- see charging schemes)i�Z	Forbiddenz0Request forbidden -- authorization will not help)i�z	Not FoundzNothing matches the given URI)i�zMethod Not Allowedz-Specified method is invalid for this resource)i�zNot Acceptablez%URI not available in preferred format)i�zProxy Authentication Requiredz7You must authenticate with this proxy before proceeding)i�zRequest Timeoutz"Request timed out; try again later)i�ZConflictzRequest conflict)i�ZGonez5URI no longer exists and has been permanently removed)i�zLength Requiredz"Client must specify Content-Length)i�zPrecondition Failedz Precondition in headers is false)i�zRequest Entity Too LargezEntity is too large)i�zRequest-URI Too LongzURI is too long)i�zUnsupported Media Typez!Entity body in unsupported format)i�zRequested Range Not SatisfiablezCannot satisfy request range)i�zExpectation Failedz'Expect condition could not be satisfied)i�zMisdirected Requestz(Server is not able to produce a response)i�zUnprocessable Entity)i�ZLocked)i�zFailed Dependency)i�zUpgrade Required)i�zPrecondition Requiredz8The origin server requires the request to be conditional)i�zToo Many RequestszOThe user has sent too many requests in a given amount of time ("rate limiting"))i�zRequest Header Fields Too LargezVThe server is unwilling to process the request because its header fields are too large)i�zUnavailable For Legal ReasonszOThe server is denying access to the resource as a consequence of a legal demand)i�zInternal Server ErrorzServer got itself in trouble)i�zNot Implementedz&Server does not support this operation)i�zBad Gatewayz+Invalid responses from another server/proxy)i�zService Unavailablez8The server cannot process the request due to a high load)i�zGateway Timeoutz4The gateway server did not receive a timely response)i�zHTTP Version Not SupportedzCannot fulfill request)i�zVariant Also Negotiates)i�zInsufficient Storage)i�z
Loop Detected)i�zNot Extended)i�zNetwork Authentication Requiredz7The client needs to authenticate to gain network accessN)r)@�__name__�
__module__�__qualname__�__doc__rZCONTINUEZSWITCHING_PROTOCOLSZ
PROCESSINGrZCREATEDZACCEPTEDZNON_AUTHORITATIVE_INFORMATIONZ
NO_CONTENTZ
RESET_CONTENTZPARTIAL_CONTENTZMULTI_STATUSZALREADY_REPORTEDZIM_USEDZMULTIPLE_CHOICESZMOVED_PERMANENTLYZFOUNDZ	SEE_OTHERZNOT_MODIFIEDZ	USE_PROXYZTEMPORARY_REDIRECTZPERMANENT_REDIRECTZBAD_REQUESTZUNAUTHORIZEDZPAYMENT_REQUIREDZ	FORBIDDENZ	NOT_FOUNDZMETHOD_NOT_ALLOWEDZNOT_ACCEPTABLEZPROXY_AUTHENTICATION_REQUIREDZREQUEST_TIMEOUTZCONFLICTZGONEZLENGTH_REQUIREDZPRECONDITION_FAILEDZREQUEST_ENTITY_TOO_LARGEZREQUEST_URI_TOO_LONGZUNSUPPORTED_MEDIA_TYPEZREQUESTED_RANGE_NOT_SATISFIABLEZEXPECTATION_FAILEDZMISDIRECTED_REQUESTZUNPROCESSABLE_ENTITYZLOCKEDZFAILED_DEPENDENCYZUPGRADE_REQUIREDZPRECONDITION_REQUIREDZTOO_MANY_REQUESTSZREQUEST_HEADER_FIELDS_TOO_LARGEZUNAVAILABLE_FOR_LEGAL_REASONSZINTERNAL_SERVER_ERRORZNOT_IMPLEMENTEDZBAD_GATEWAYZSERVICE_UNAVAILABLEZGATEWAY_TIMEOUTZHTTP_VERSION_NOT_SUPPORTEDZVARIANT_ALSO_NEGOTIATESZINSUFFICIENT_STORAGEZ
LOOP_DETECTEDZNOT_EXTENDEDZNETWORK_AUTHENTICATION_REQUIREDr
r
r
rrsz
	N)�enumr�__all__rr
r
r
r�<module>s__pycache__/server.cpython-38.opt-1.pyc000064400000104101150532417300013646 0ustar00U

e5d��@s
dZdZdddddgZddlZddlZddlZddlZddlZ	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlZddlZddlZddlZddlZddlZdd	lmZdd
l	mZdZdZGd
d�dej�ZGdd�deje�Z Gdd�dej!�Z"Gdd�de"�Z#dd�Z$da%dd�Z&dd�Z'Gdd�de#�Z(dd�Z)e"e dddfdd�Z*e+dk�rddl,Z,e,�-�Z.e.j/dd d!d"�e.j/d#d$d%d&d'�e.j/d(d)e
�0�d*d+�e.j/d,d-de1d.d/d0�e.�2�Z3e3j4�r�e(Z5nee#e3j6d1�Z5Gd2d3�d3e �Z7e*e5e7e3j8e3j9d4�dS)5a@HTTP server classes.

Note: BaseHTTPRequestHandler doesn't implement any HTTP request; see
SimpleHTTPRequestHandler for simple implementations of GET, HEAD and POST,
and CGIHTTPRequestHandler for CGI scripts.

It does, however, optionally implement HTTP/1.1 persistent connections,
as of version 0.3.

Notes on CGIHTTPRequestHandler
------------------------------

This class implements GET and POST requests to cgi-bin scripts.

If the os.fork() function is not present (e.g. on Windows),
subprocess.Popen() is used as a fallback, with slightly altered semantics.

In all cases, the implementation is intentionally naive -- all
requests are executed synchronously.

SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
-- it may execute arbitrary Python code or external programs.

Note that status code 200 is sent prior to execution of a CGI script, so
scripts cannot send other status codes such as 302 (redirect).

XXX To do:

- log requests even later (to capture byte count)
- log user-agent header and other interesting goodies
- send error log to separate file
z0.6�
HTTPServer�ThreadingHTTPServer�BaseHTTPRequestHandler�SimpleHTTPRequestHandler�CGIHTTPRequestHandler�N)�partial)�
HTTPStatusa�<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: %(code)d</p>
        <p>Message: %(message)s.</p>
        <p>Error code explanation: %(code)s - %(explain)s.</p>
    </body>
</html>
ztext/html;charset=utf-8c@seZdZdZdd�ZdS)r�cCs4tj�|�|jdd�\}}t�|�|_||_dS)z.Override server_bind to store the server name.N�)�socketserver�	TCPServer�server_bindZserver_address�socketZgetfqdn�server_name�server_port)�self�host�port�r�#/usr/lib64/python3.8/http/server.pyr
�szHTTPServer.server_bindN)�__name__�
__module__�__qualname__Zallow_reuse_addressr
rrrrr�sc@seZdZdZdS)rTN)rrrZdaemon_threadsrrrrr�sc
@sJeZdZdZdej��dZdeZ	e
ZeZ
dZdd�Zdd	�Zd
d�Zdd
�ZdFdd�ZdGdd�ZdHdd�Zdd�Zdd�Zdd�ZdIdd�Zdd�Ze�d d!�e�ed"�ed#d$��D��Z d%e e!d&�<d'd(�Z"d)d*�Z#dJd+d,�Z$d-d.�Z%d/d0d1d2d3d4d5gZ&dd6d7d8d9d:d;d<d=d>d?d@dAg
Z'dBdC�Z(dDZ)e*j+j,Z-dEd!�e.j/�0�D�Z1dS)Kra�HTTP request handler base class.

    The following explanation of HTTP serves to guide you through the
    code as well as to expose any misunderstandings I may have about
    HTTP (so you don't need to read the code to figure out I'm wrong
    :-).

    HTTP (HyperText Transfer Protocol) is an extensible protocol on
    top of a reliable stream transport (e.g. TCP/IP).  The protocol
    recognizes three parts to a request:

    1. One line identifying the request type and path
    2. An optional set of RFC-822-style headers
    3. An optional data part

    The headers and data are separated by a blank line.

    The first line of the request has the form

    <command> <path> <version>

    where <command> is a (case-sensitive) keyword such as GET or POST,
    <path> is a string containing path information for the request,
    and <version> should be the string "HTTP/1.0" or "HTTP/1.1".
    <path> is encoded using the URL encoding scheme (using %xx to signify
    the ASCII character with hex code xx).

    The specification specifies that lines are separated by CRLF but
    for compatibility with the widest range of clients recommends
    servers also handle LF.  Similarly, whitespace in the request line
    is treated sensibly (allowing multiple spaces between components
    and allowing trailing whitespace).

    Similarly, for output, lines ought to be separated by CRLF pairs
    but most clients grok LF characters just fine.

    If the first line of the request has the form

    <command> <path>

    (i.e. <version> is left out) then this is assumed to be an HTTP
    0.9 request; this form has no optional headers and data part and
    the reply consists of just the data.

    The reply form of the HTTP 1.x protocol again has three parts:

    1. One line giving the response code
    2. An optional set of RFC-822-style headers
    3. The data

    Again, the headers and data are separated by a blank line.

    The response code line has the form

    <version> <responsecode> <responsestring>

    where <version> is the protocol version ("HTTP/1.0" or "HTTP/1.1"),
    <responsecode> is a 3-digit response code indicating success or
    failure of the request, and <responsestring> is an optional
    human-readable string explaining what the response code means.

    This server parses the request and the headers, and then calls a
    function specific to the request type (<command>).  Specifically,
    a request SPAM will be handled by a method do_SPAM().  If no
    such method exists the server sends an error response to the
    client.  If it exists, it is called with no arguments:

    do_SPAM()

    Note that the request name is case sensitive (i.e. SPAM and spam
    are different requests).

    The various request details are stored in instance variables:

    - client_address is the client IP address in the form (host,
    port);

    - command, path and version are the broken-down request line;

    - headers is an instance of email.message.Message (or a derived
    class) containing the header information;

    - rfile is a file object open for reading positioned at the
    start of the optional input data part;

    - wfile is a file object open for writing.

    IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!

    The first thing to be written must be the response line.  Then
    follow 0 or more header lines, then a blank line, and then the
    actual data (if any).  The meaning of the header lines depends on
    the command executed by the server; in most cases, when data is
    returned, there should be at least one header line of the form

    Content-type: <type>/<subtype>

    where <type> and <subtype> should be registered MIME types,
    e.g. "text/html" or "text/plain".

    zPython/rz	BaseHTTP/�HTTP/0.9c
Cs�d|_|j|_}d|_t|jd�}|�d�}||_|��}t	|�dkrLdSt	|�dk�r&|d}zT|�
d	�srt�|�d
d�d}|�d�}t	|�d
kr�t�t|d�t|d�f}Wn,tt
fk
r�|�tjd|�YdSX|dk�r|jdk�rd|_|dk�r |�tjd|�dS||_d
t	|�k�rBdk�sZn|�tjd|�dS|dd
�\}}t	|�d
k�r�d|_|dk�r�|�tjd|�dS|||_|_|j�
d��r�d
|j�d
�|_ztjj|j|jd�|_Wn�tjjk
�r(}z|�tjdt|��WY�dSd}~XYnBtjjk
�rh}z|�tjdt|��WY�dSd}~XYnX|j�dd�}	|	��dk�r�d|_n |	��dk�r�|jdk�r�d|_|j�dd�}
|
��dk�r�|jdk�r�|jdk�r�|� ��s�dSdS) aHParse a request (internal).

        The request should be stored in self.raw_requestline; the results
        are in self.command, self.path, self.request_version and
        self.headers.

        Return True for success, False for failure; on failure, any relevant
        error response has already been sent back.

        NTz
iso-8859-1z
rF����zHTTP/�/r	�.r
zBad request version (%r))r	r	zHTTP/1.1)r
rzInvalid HTTP version (%s)zBad request syntax (%r)ZGETzBad HTTP/0.9 request type (%r)z//)Z_classz
Line too longzToo many headers�
Connection��close�
keep-aliveZExpectz100-continue)!�command�default_request_version�request_version�close_connection�str�raw_requestline�rstrip�requestline�split�len�
startswith�
ValueError�int�
IndexError�
send_errorrZBAD_REQUEST�protocol_versionZHTTP_VERSION_NOT_SUPPORTED�path�lstrip�http�clientZ
parse_headers�rfile�MessageClass�headersZLineTooLongZREQUEST_HEADER_FIELDS_TOO_LARGEZ
HTTPException�get�lower�handle_expect_100)r�versionr)�wordsZbase_version_numberZversion_numberr"r2�errZconntypeZexpectrrr�
parse_requests�


�
��
�
������
z$BaseHTTPRequestHandler.parse_requestcCs|�tj�|��dS)a7Decide what to do with an "Expect: 100-continue" header.

        If the client is expecting a 100 Continue response, we must
        respond with either a 100 Continue or a final response before
        waiting for the request body. The default is to always respond
        with a 100 Continue. You can behave differently (for example,
        reject unauthorized requests) by overriding this method.

        This method should either return True (possibly after sending
        a 100 Continue response) or send an error response and return
        False.

        T)�send_response_onlyrZCONTINUE�end_headers�rrrrr;xsz(BaseHTTPRequestHandler.handle_expect_100c
Cs�z�|j�d�|_t|j�dkrBd|_d|_d|_|�tj	�WdS|jsTd|_
WdS|��sbWdSd|j}t||�s�|�tj
d|j�WdSt||�}|�|j��Wn<tjk
r�}z|�d|�d|_
WY�dSd}~XYnXdS)	z�Handle a single HTTP request.

        You normally don't need to override this method; see the class
        __doc__ string for information on how to handle specific HTTP
        commands such as GET and POST.

        iirNTZdo_zUnsupported method (%r)zRequest timed out: %r)r6�readliner'r+r)r$r"r0rZREQUEST_URI_TOO_LONGr%r?�hasattr�NOT_IMPLEMENTED�getattr�wfile�flushrZtimeout�	log_error)rZmname�method�errr�handle_one_request�s6

�
z)BaseHTTPRequestHandler.handle_one_requestcCs"d|_|��|js|��qdS)z&Handle multiple requests if necessary.TN)r%rLrBrrr�handle�szBaseHTTPRequestHandler.handleNcCsz|j|\}}Wntk
r.d\}}YnX|dkr<|}|dkrH|}|�d||�|�||�|�dd�d}|dkr�|tjtjtjfkr�|j	|t
j|dd�t
j|dd�d	�}|�d
d�}|�d|j
�|�d
tt|���|��|jdk�r|�r|j�|�dS)akSend and log an error reply.

        Arguments are
        * code:    an HTTP error code
                   3 digits
        * message: a simple optional 1 line reason phrase.
                   *( HTAB / SP / VCHAR / %x80-FF )
                   defaults to short entry matching the response code
        * explain: a detailed message defaults to the long entry
                   matching the response code.

        This sends an error response (so it must be called before any
        output has been generated), logs the error, and finally sends
        a piece of HTML explaining the error to the user.

        )�???rNNzcode %d, message %srr ��F��quote)�code�message�explainzUTF-8�replacezContent-Type�Content-LengthZHEAD)�	responses�KeyErrorrI�
send_response�send_headerrZ
NO_CONTENTZ
RESET_CONTENT�NOT_MODIFIED�error_message_format�html�escape�encode�error_content_typer&r+rAr"rG�write)rrRrSrTZshortmsgZlongmsgZbodyZcontentrrrr0�s:���z!BaseHTTPRequestHandler.send_errorcCs:|�|�|�||�|�d|���|�d|���dS)z�Add the response header to the headers buffer and log the
        response code.

        Also send two standard headers with the server software
        version and the current date.

        ZServerZDateN)�log_requestr@rZ�version_string�date_time_string�rrRrSrrrrY�s
z$BaseHTTPRequestHandler.send_responsecCsd|jdkr`|dkr0||jkr,|j|d}nd}t|d�s@g|_|j�d|j||f�dd��dS)	zSend the response header only.rNrr�_headers_bufferz
%s %d %s
�latin-1�strict)r$rWrDrf�appendr1r_rerrrr@�s



��z)BaseHTTPRequestHandler.send_response_onlycCsl|jdkr6t|d�sg|_|j�d||f�dd��|��dkrh|��dkrVd|_n|��d	krhd
|_dS)z)Send a MIME header to the headers buffer.rrfz%s: %s
rgrhZ
connectionr Tr!FN)r$rDrfrir_r:r%)r�keyword�valuerrrrZs

�z"BaseHTTPRequestHandler.send_headercCs"|jdkr|j�d�|��dS)z,Send the blank line ending the MIME headers.rs
N)r$rfri�
flush_headersrBrrrrAs
z"BaseHTTPRequestHandler.end_headerscCs(t|d�r$|j�d�|j��g|_dS)Nrf�)rDrGra�joinrfrBrrrrls
z$BaseHTTPRequestHandler.flush_headers�-cCs.t|t�r|j}|�d|jt|�t|��dS)zNLog an accepted request.

        This is called by send_response().

        z
"%s" %s %sN)�
isinstancerrk�log_messager)r&)rrR�sizerrrrb s
�z"BaseHTTPRequestHandler.log_requestcGs|j|f|��dS)z�Log an error.

        This is called when a request cannot be fulfilled.  By
        default it passes the message on to log_message().

        Arguments are the same as for log_message().

        XXX This should go to the separate error log.

        N)rq)r�format�argsrrrrI+sz BaseHTTPRequestHandler.log_errorcCsi|]}|d|d���qS)z\xZ02xr)�.0�crrr�
<dictcomp>;sz!BaseHTTPRequestHandler.<dictcomp>� ��z\\�\cGs2||}tj�d|��|��|�|j�f�dS)aZLog an arbitrary message.

        This is used by all other logging functions.  Override
        it if you have specific logging wishes.

        The first argument, FORMAT, is a format string for the
        message to be logged.  If the format string contains
        any % escapes requiring parameters, they should be
        specified as subsequent arguments (it's just like
        printf!).

        The client ip and current date/time are prefixed to
        every message.

        Unicode control characters are replaced with escaped hex
        before writing the output to stderr.

        z%s - - [%s] %s
N)�sys�stderrra�address_string�log_date_time_string�	translate�_control_char_table)rrsrtrSrrrrq>s
��z"BaseHTTPRequestHandler.log_messagecCs|jd|jS)z*Return the server software version string.� )�server_version�sys_versionrBrrrrcXsz%BaseHTTPRequestHandler.version_stringcCs |dkrt��}tjj|dd�S)z@Return the current date and time formatted for a message header.NT)Zusegmt)�time�email�utilsZ
formatdate)rZ	timestamprrrrd\sz'BaseHTTPRequestHandler.date_time_stringc	CsBt��}t�|�\	}}}}}}}}	}
d||j|||||f}|S)z.Return the current time formatted for logging.z%02d/%3s/%04d %02d:%02d:%02d)r��	localtime�	monthname)rZnowZyearZmonthZdayZhhZmmZss�x�y�z�srrrrbs�z+BaseHTTPRequestHandler.log_date_time_stringZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs
|jdS)zReturn the client address.r)�client_addressrBrrrr~psz%BaseHTTPRequestHandler.address_string�HTTP/1.0cCsi|]}||j|jf�qSr)�phraseZdescription)ru�vrrrrws�)NN)N)N)roro)N)2rrr�__doc__r|r<r*r��__version__r��DEFAULT_ERROR_MESSAGEr\�DEFAULT_ERROR_CONTENT_TYPEr`r#r?r;rLrMr0rYr@rZrArlrbrIr&�	maketrans�	itertools�chain�ranger��ordrqrcrdrZweekdaynamer�r~r1r4r5ZHTTPMessager7r�__members__�valuesrWrrrrr�s^gj%
5


�
�	�cs�eZdZdZdeZdd��fdd�
Zdd�Zd	d
�Zdd�Z	d
d�Z
dd�Zdd�Zdd�Z
ejsle��ej��Ze�ddddd���ZS)raWSimple HTTP request handler with GET and HEAD commands.

    This serves files from the current directory and any of its
    subdirectories.  The MIME type for files is determined by
    calling the .guess_type() method.

    The GET and HEAD requests are identical except that the HEAD
    request omits the actual contents of the file.

    zSimpleHTTP/N��	directorycs(|dkrt��}||_t�j||�dS�N)�os�getcwdr��super�__init__)rr�rt�kwargs��	__class__rrr��sz!SimpleHTTPRequestHandler.__init__cCs.|��}|r*z|�||j�W5|��XdS)zServe a GET request.N)�	send_headr �copyfilerG�r�frrr�do_GET�s
zSimpleHTTPRequestHandler.do_GETcCs|��}|r|��dS)zServe a HEAD request.N)r�r r�rrr�do_HEAD�sz SimpleHTTPRequestHandler.do_HEADcCs^|�|j�}d}tj�|�r�tj�|j�}|j�d�s�|�t	j
�|d|d|dd|d|df}tj�|�}|�d|�|�
�dSd	D]&}tj�||�}tj�|�r�|}q�q�|�|�S|�|�}|�d�r�|�t	jd
�dSzt|d�}Wn&tk
�r|�t	jd
�YdSX�z"t�|���}d|jk�r�d
|jk�r�ztj�|jd�}	Wnttttfk
�r|YnzX|	j dk�r�|	j!t"j#j$d�}	|	j t"j#j$k�r�t"j"�%|j&t"j#j$�}
|
j!dd�}
|
|	k�r�|�t	j'�|�
�|�(�WdS|�t	j)�|�d|�|�dt*|d��|�d|�+|j&��|�
�|WS|�(��YnXdS)a{Common code for GET and HEAD commands.

        This sends the response code and MIME headers.

        Return value is either a file object (which has to be copied
        to the outputfile by the caller unless the command was HEAD,
        and must be closed by the caller under all circumstances), or
        None, in which case the caller has nothing further to do.

        Nrrr	r
r�ZLocation)z
index.htmlz	index.htmzFile not found�rbzIf-Modified-Sincez
If-None-Match)�tzinfo)Zmicrosecond�Content-typerV�z
Last-Modified),�translate_pathr2r��isdir�urllib�parseZurlsplit�endswithrYrZMOVED_PERMANENTLYZ
urlunsplitrZrArn�exists�list_directory�
guess_typer0�	NOT_FOUND�open�OSError�fstat�filenor8r�r�Zparsedate_to_datetime�	TypeErrorr/�
OverflowErrorr-r�rU�datetime�timezoneZutcZ
fromtimestamp�st_mtimer[r �OKr&rd)rr2r��partsZ	new_partsZnew_url�indexZctypeZfsZimsZ
last_modifrrrr��s��


���

�z"SimpleHTTPRequestHandler.send_headc
	Cs�zt�|�}Wn$tk
r2|�tjd�YdSX|jdd�d�g}ztjj	|j
dd�}Wn"tk
r�tj�	|j
�}YnXtj
|dd	�}t��}d
|}|�d�|�d�|�d
|�|�d|�|�d|�|�d�|D]v}tj
�||�}|}	}
tj
�|��r$|d}	|d}
tj
�|��r:|d}	|�dtjj|
dd�tj
|	dd	�f�q�|�d�d�|��|d�}t��}|�|�|�d�|�tj�|�dd|�|�dtt|���|��|S)z�Helper to produce a directory listing (absent index.html).

        Return value is either a file object, or None (indicating an
        error).  In either case, the headers are sent, making the
        interface the same as for send_head().

        zNo permission to list directoryNcSs|��Sr�)r:)�arrr�<lambda>rmz9SimpleHTTPRequestHandler.list_directory.<locals>.<lambda>)�key�
surrogatepass��errorsFrPzDirectory listing for %szZ<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">z
<html>
<head>z@<meta http-equiv="Content-Type" content="text/html; charset=%s">z<title>%s</title>
</head>z<body>
<h1>%s</h1>z	<hr>
<ul>r�@z<li><a href="%s">%s</a></li>z</ul>
<hr>
</body>
</html>
�
�surrogateescaperr�ztext/html; charset=%srV) r��listdirr�r0rr��sortr�r��unquoter2�UnicodeDecodeErrorr]r^r|�getfilesystemencodingrirnr��islinkrQr_�io�BytesIOra�seekrYr�rZr&r+rA)
rr2�list�rZdisplaypath�enc�title�name�fullnameZdisplaynameZlinknameZencodedr�rrrr�sh�
�


�
���


z'SimpleHTTPRequestHandler.list_directorycCs�|�dd�d}|�dd�d}|���d�}ztjj|dd�}Wn tk
rbtj�|�}YnXt�|�}|�d�}t	d|�}|j
}|D]0}tj�
|�s�|tjtjfkr�q�tj�||�}q�|r�|d7}|S)	z�Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        �?r	r�#rr�r�N)r*r(r�r�r�r�r��	posixpath�normpath�filterr�r�r2�dirname�curdir�pardirrn)rr2Ztrailing_slashr=Zwordrrrr�:s$	


z'SimpleHTTPRequestHandler.translate_pathcCst�||�dS)a�Copy all data between two file objects.

        The SOURCE argument is a file object open for reading
        (or anything with a read() method) and the DESTINATION
        argument is a file object open for writing (or
        anything with a write() method).

        The only reason for overriding this would be to change
        the block size or perhaps to replace newlines by CRLF
        -- note however that this the default server uses this
        to copy binary data as well.

        N)�shutilZcopyfileobj)r�sourceZ
outputfilerrrr�Xsz!SimpleHTTPRequestHandler.copyfilecCsLt�|�\}}||jkr"|j|S|��}||jkr>|j|S|jdSdS)a�Guess the type of a file.

        Argument is a PATH (a filename).

        Return value is a string of the form type/subtype,
        usable for a MIME Content-type header.

        The default implementation looks the file's extension
        up in the table self.extensions_map, using application/octet-stream
        as a default; however it would be permissible (if
        slow) to look inside the data to make a better guess.

        rN)r��splitext�extensions_mapr:)rr2�baseZextrrrr�hs



z#SimpleHTTPRequestHandler.guess_typezapplication/octet-streamz
text/plain)r�.pyz.cz.h)rrrr�r�r�r�r�r�r�r�r�r�r��	mimetypesZinitedZinitZ	types_map�copyr��update�
__classcell__rrr�rr�s&	W:
�c	Cs�|�d�\}}}tj�|�}|�d�}g}|dd�D],}|dkrL|��q6|r6|dkr6|�|�q6|r�|��}|r�|dkr�|��d}q�|dkr�d}nd}|r�d�||f�}dd�|�|f}d�|�}|S)a�
    Given a URL path, remove extra '/'s and '.' path elements and collapse
    any '..' references and returns a collapsed path.

    Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
    The utility of this function is limited to is_cgi method and helps
    preventing some security attacks.

    Returns: The reconstituted URL, which will always start with a '/'.

    Raises: IndexError if too many '..' occur within the path.

    r�rNrz..rr)�	partitionr�r�r�r*�poprirn)	r2�_�query�
path_partsZ
head_parts�partZ	tail_partZ	splitpath�collapsed_pathrrr�_url_collapse_path�s.


r�cCsrtrtSzddl}Wntk
r*YdSXz|�d�daWn.tk
rldtdd�|��D��aYnXtS)	z$Internal routine to get nobody's uidrNr�nobodyr
r	css|]}|dVqdS)r
Nr)rur�rrr�	<genexpr>�sznobody_uid.<locals>.<genexpr>)r��pwd�ImportError�getpwnamrX�maxZgetpwall)r�rrr�
nobody_uid�s r�cCst�|tj�S)zTest for executable file.)r��access�X_OK)r2rrr�
executable�src@sVeZdZdZeed�ZdZdd�Zdd�Z	dd	�Z
d
dgZdd
�Zdd�Z
dd�ZdS)rz�Complete HTTP server with GET, HEAD and POST commands.

    GET and HEAD also support running CGI scripts.

    The POST command is *only* implemented for CGI scripts.

    �forkrcCs$|��r|��n|�tjd�dS)zRServe a POST request.

        This is only implemented for CGI scripts.

        zCan only POST to CGI scriptsN)�is_cgi�run_cgir0rrErBrrr�do_POST�s
�zCGIHTTPRequestHandler.do_POSTcCs|��r|��St�|�SdS)z-Version of send_head that support CGI scriptsN)rrrr�rBrrrr��szCGIHTTPRequestHandler.send_headcCsPt|j�}|�dd�}|d|�||dd�}}||jkrL||f|_dSdS)a3Test whether self.path corresponds to a CGI script.

        Returns True and updates the cgi_info attribute to the tuple
        (dir, rest) if self.path requires running a CGI script.
        Returns False otherwise.

        If any exception is raised, the caller should assume that
        self.path was rejected as invalid and act accordingly.

        The default implementation tests whether the normalized url
        path begins with one of the strings in self.cgi_directories
        (and the next character is a '/' or the end of the string).

        rr	NTF)r�r2�find�cgi_directories�cgi_info)rr�Zdir_sep�head�tailrrrr�s


zCGIHTTPRequestHandler.is_cgiz/cgi-binz/htbincCst|�S)z1Test whether argument path is an executable file.)r)rr2rrr�
is_executablesz#CGIHTTPRequestHandler.is_executablecCstj�|�\}}|��dkS)z.Test whether argument path is a Python script.)r�z.pyw)r�r2r�r:)rr2r
rrrr�	is_pythonszCGIHTTPRequestHandler.is_pythonc)	Cs�|j\}}|d|}|�dt|�d�}|dkr�|d|�}||dd�}|�|�}tj�|�r�||}}|�dt|�d�}q*q�q*|�d�\}}}	|�d�}|dkr�|d|�||d�}
}n
|d}
}|d|
}|�|�}tj�|��s
|�	t
jd|�dStj�|��s.|�	t
j
d|�dS|�|�}
|j�sF|
�sh|�|��sh|�	t
j
d	|�dSt�tj�}|��|d
<|jj|d<d|d
<|j|d<t|jj�|d<|j|d<tj�|�}||d<|�|�|d<||d<|	�r�|	|d<|jd|d<|j� d�}|�r�|�!�}t|�dk�r�ddl"}ddl#}|d|d<|d�$�dk�r�z"|d�%d�}|�&|��'d�}Wn|j(t)fk
�r�Yn&X|�!d�}t|�dk�r�|d|d<|j� d�dk�r�|j�*�|d<n|jd|d<|j� d�}|�r||d <|j� d!�}|�r||d"<g}|j�+d#�D]>}|dd�d$k�rR|�,|�-��n||d%d��!d&�}�q,d&�.|�|d'<|j� d(�}|�r�||d)<t/d|j�0d*g��}d+�.|�}|�r�||d,<d-D]}|�1|d��q�|�2t
j3d.�|�4�|	�5d/d0�}|j�r|
g}d1|k�r|�,|�t6�}|j7�8�t�9�}|dk�r�t�:|d�\}}t;�;|j<gggd�d�r~|j<�=d��sN�q~�qN|�r�|�>d2|�dSz\zt�?|�Wnt@k
�r�YnXt�A|j<�B�d�t�A|j7�B�d�t�C|||�Wn(|j�D|jE|j�t�Fd3�YnX�n�ddlG} |g}!|�|��rrtHjI}"|"�$��Jd4��rf|"dd5�|"d6d�}"|"d7g|!}!d1|	k�r�|!�,|	�|�Kd8| �L|!��ztM|�}#WntNtOfk
�r�d}#YnX| jP|!| jQ| jQ| jQ|d9�}$|j�$�d:k�r|#dk�r|j<�=|#�}%nd}%t;�;|j<jRgggd�d�r>|j<jR�Sd��s
�q>�q
|$�T|%�\}&}'|j7�U|&�|'�rj|�>d;|'�|$jV�W�|$jX�W�|$jY}(|(�r�|�>d2|(�n
|�Kd<�dS)=zExecute a CGI script.rr	rNr�rzNo such CGI script (%r)z#CGI script is not a plain file (%r)z!CGI script is not executable (%r)ZSERVER_SOFTWAREZSERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZSERVER_PROTOCOLZSERVER_PORTZREQUEST_METHODZ	PATH_INFOZPATH_TRANSLATEDZSCRIPT_NAME�QUERY_STRINGZREMOTE_ADDR�
authorizationr
Z	AUTH_TYPEZbasic�ascii�:ZREMOTE_USERzcontent-typeZCONTENT_TYPEzcontent-length�CONTENT_LENGTH�referer�HTTP_REFERER�acceptz	

 ��,ZHTTP_ACCEPTz
user-agent�HTTP_USER_AGENTZcookiez, �HTTP_COOKIE)rZREMOTE_HOSTrrrrzScript output follows�+r��=zCGI script exit status %#xryzw.exe������z-uzcommand: %s)�stdin�stdoutr}�envZpostz%szCGI script exited OK)Zr	rr+r�r�r2r�r�r�r0rr��isfileZ	FORBIDDENr
�	have_forkrr�Zdeepcopy�environrcZserverrr1r&rr"r�r�r�r�r8r9r*�base64�binasciir:r_Zdecodebytes�decode�Error�UnicodeErrorZget_content_typeZgetallmatchingheadersri�striprnr�Zget_all�
setdefaultrYr�rlrUr�rGrHr�waitpid�selectr6�readrI�setuidr��dup2r��execveZhandle_errorZrequest�_exit�
subprocessr|rr�rqZlist2cmdliner.r�r-�Popen�PIPEZ_sockZrecvZcommunicaterar}r r�
returncode))r�dir�restr2�iZnextdirZnextrestZ	scriptdirr�r�ZscriptZ
scriptnameZ
scriptfileZispyr Zuqrestrr$r%Zlengthrr�lineZua�coZ
cookie_str�kZ
decoded_queryrtr��pid�stsr2ZcmdlineZinterp�nbytes�p�datarr}Zstatusrrrrs<





��
�


�








�

zCGIHTTPRequestHandler.run_cgiN)rrrr�rDr�r"Zrbufsizerr�rrrr
rrrrrr�s	
cGs4tj|tjtjd��}tt|��\}}}}}||fS)N)�type�flags)rZgetaddrinfoZSOCK_STREAMZ
AI_PASSIVE�next�iter)ZaddressZinfosZfamilyrA�protoZ	canonnameZsockaddrrrr�_get_best_family�s�rFr�i@c	Cs�t||�\|_}||_|||���}|j��dd�\}}d|krLd|�d�n|}td|�d|�d|�d|�d	�	�z|��Wn&tk
r�td
�t�	d�YnXW5QRXdS)zmTest the HTTP request handler class.

    This runs an HTTP server on port 8000 (or the port argument).

    Nr
r�[�]zServing HTTP on z port z	 (http://z/) ...z&
Keyboard interrupt received, exiting.r)
rFZaddress_familyr1rZgetsockname�printZ
serve_forever�KeyboardInterruptr|�exit)	�HandlerClass�ServerClassZprotocolr�bindZaddrZhttpdrZurl_hostrrr�test�s�rO�__main__z--cgi�
store_truezRun as CGI Server)�action�helpz--bindz-bZADDRESSz8Specify alternate bind address [default: all interfaces])�metavarrSz--directoryz-dz9Specify alternative directory [default:current directory])�defaultrSrZstorer�z&Specify alternate port [default: 8000])rRrUrA�nargsrSr�cseZdZ�fdd�Z�ZS)�DualStackServerc	s4t�t��|j�tjtjd�W5QRXt���S)Nr)	�
contextlib�suppress�	ExceptionrZ
setsockoptZIPPROTO_IPV6ZIPV6_V6ONLYr�r
rBr�rrr
s�zDualStackServer.server_bind)rrrr
r�rrr�rrWsrW)rLrMrrN):r�r��__all__r�r�Zemail.utilsr�r]Zhttp.clientr4r�r�r�r�r�r,r�rrr|r�Zurllib.parser�rX�	functoolsrrr�r�rrZThreadingMixInrZStreamRequestHandlerrrr�r�r�rrrFrOr�argparse�ArgumentParser�parser�add_argumentr�r.�
parse_argsrtZcgiZ
handler_classr�rWrrNrrrr�<module>s�R�s
0
�

�
�����__pycache__/__init__.cpython-38.pyc000064400000013662150532417300013153 0ustar00U

e5d��@s&ddlmZdgZGdd�de�ZdS)�)�IntEnum�
HTTPStatusc@seZdZdZdAdd�ZdZdZdZdZd	Z	d
Z
dZdZd
Z
dZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZd Z d!Z!d"Z"d#Z#d$Z$d%Z%d&Z&d'Z'd(Z(d)Z)d*Z*d+Z+d,Z,d-Z-d.Z.d/Z/d0Z0d1Z1d2Z2d3Z3d4Z4d5Z5d6Z6d7Z7d8Z8d9Z9d:Z:d;Z;d<Z<d=Z=d>Z>d?Z?d@S)Bra�HTTP status codes and reason phrases

    Status codes from the following RFCs are all observed:

        * RFC 7231: Hypertext Transfer Protocol (HTTP/1.1), obsoletes 2616
        * RFC 6585: Additional HTTP Status Codes
        * RFC 3229: Delta encoding in HTTP
        * RFC 4918: HTTP Extensions for WebDAV, obsoletes 2518
        * RFC 5842: Binding Extensions to WebDAV
        * RFC 7238: Permanent Redirect
        * RFC 2295: Transparent Content Negotiation in HTTP
        * RFC 2774: An HTTP Extension Framework
        * RFC 7725: An HTTP Status Code to Report Legal Obstacles
        * RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2)
    �cCs"t�||�}||_||_||_|S)N)�int�__new__�_value_�phrase�description)�cls�valuerr	�obj�r
�%/usr/lib64/python3.8/http/__init__.pyrs
zHTTPStatus.__new__)�dZContinuez!Request received, please continue)�ezSwitching Protocolsz.Switching to new protocol; obey Upgrade header)�fZ
Processing)���OKz#Request fulfilled, document follows)��ZCreatedzDocument created, URL follows)��ZAcceptedz/Request accepted, processing continues off-line)��zNon-Authoritative InformationzRequest fulfilled from cache)��z
No Contentz"Request fulfilled, nothing follows)��z
Reset Contentz"Clear input form for further input)��zPartial ContentzPartial content follows)��zMulti-Status)��zAlready Reported)��zIM Used)i,zMultiple Choicesz,Object has several resources -- see URI list)i-zMoved Permanently�(Object moved permanently -- see URI list)i.ZFound�(Object moved temporarily -- see URI list)i/z	See Otherz'Object moved -- see Method and URL list)i0zNot Modifiedz)Document has not changed since given time)i1z	Use Proxyz@You must use proxy specified in Location to access this resource)i3zTemporary Redirectr)i4zPermanent Redirectr)i�zBad Requestz(Bad request syntax or unsupported method)i�ZUnauthorizedz*No permission -- see authorization schemes)i�zPayment Requiredz"No payment -- see charging schemes)i�Z	Forbiddenz0Request forbidden -- authorization will not help)i�z	Not FoundzNothing matches the given URI)i�zMethod Not Allowedz-Specified method is invalid for this resource)i�zNot Acceptablez%URI not available in preferred format)i�zProxy Authentication Requiredz7You must authenticate with this proxy before proceeding)i�zRequest Timeoutz"Request timed out; try again later)i�ZConflictzRequest conflict)i�ZGonez5URI no longer exists and has been permanently removed)i�zLength Requiredz"Client must specify Content-Length)i�zPrecondition Failedz Precondition in headers is false)i�zRequest Entity Too LargezEntity is too large)i�zRequest-URI Too LongzURI is too long)i�zUnsupported Media Typez!Entity body in unsupported format)i�zRequested Range Not SatisfiablezCannot satisfy request range)i�zExpectation Failedz'Expect condition could not be satisfied)i�zMisdirected Requestz(Server is not able to produce a response)i�zUnprocessable Entity)i�ZLocked)i�zFailed Dependency)i�zUpgrade Required)i�zPrecondition Requiredz8The origin server requires the request to be conditional)i�zToo Many RequestszOThe user has sent too many requests in a given amount of time ("rate limiting"))i�zRequest Header Fields Too LargezVThe server is unwilling to process the request because its header fields are too large)i�zUnavailable For Legal ReasonszOThe server is denying access to the resource as a consequence of a legal demand)i�zInternal Server ErrorzServer got itself in trouble)i�zNot Implementedz&Server does not support this operation)i�zBad Gatewayz+Invalid responses from another server/proxy)i�zService Unavailablez8The server cannot process the request due to a high load)i�zGateway Timeoutz4The gateway server did not receive a timely response)i�zHTTP Version Not SupportedzCannot fulfill request)i�zVariant Also Negotiates)i�zInsufficient Storage)i�z
Loop Detected)i�zNot Extended)i�zNetwork Authentication Requiredz7The client needs to authenticate to gain network accessN)r)@�__name__�
__module__�__qualname__�__doc__rZCONTINUEZSWITCHING_PROTOCOLSZ
PROCESSINGrZCREATEDZACCEPTEDZNON_AUTHORITATIVE_INFORMATIONZ
NO_CONTENTZ
RESET_CONTENTZPARTIAL_CONTENTZMULTI_STATUSZALREADY_REPORTEDZIM_USEDZMULTIPLE_CHOICESZMOVED_PERMANENTLYZFOUNDZ	SEE_OTHERZNOT_MODIFIEDZ	USE_PROXYZTEMPORARY_REDIRECTZPERMANENT_REDIRECTZBAD_REQUESTZUNAUTHORIZEDZPAYMENT_REQUIREDZ	FORBIDDENZ	NOT_FOUNDZMETHOD_NOT_ALLOWEDZNOT_ACCEPTABLEZPROXY_AUTHENTICATION_REQUIREDZREQUEST_TIMEOUTZCONFLICTZGONEZLENGTH_REQUIREDZPRECONDITION_FAILEDZREQUEST_ENTITY_TOO_LARGEZREQUEST_URI_TOO_LONGZUNSUPPORTED_MEDIA_TYPEZREQUESTED_RANGE_NOT_SATISFIABLEZEXPECTATION_FAILEDZMISDIRECTED_REQUESTZUNPROCESSABLE_ENTITYZLOCKEDZFAILED_DEPENDENCYZUPGRADE_REQUIREDZPRECONDITION_REQUIREDZTOO_MANY_REQUESTSZREQUEST_HEADER_FIELDS_TOO_LARGEZUNAVAILABLE_FOR_LEGAL_REASONSZINTERNAL_SERVER_ERRORZNOT_IMPLEMENTEDZBAD_GATEWAYZSERVICE_UNAVAILABLEZGATEWAY_TIMEOUTZHTTP_VERSION_NOT_SUPPORTEDZVARIANT_ALSO_NEGOTIATESZINSUFFICIENT_STORAGEZ
LOOP_DETECTEDZNOT_EXTENDEDZNETWORK_AUTHENTICATION_REQUIREDr
r
r
rrsz
	N)�enumr�__all__rr
r
r
r�<module>s__pycache__/client.cpython-38.opt-1.pyc000064400000103772150532417300013633 0ustar00U

e5d���@sfdZddlZddlZddlZddlZddlZddlZddlZ	ddl
mZdddddd	d
ddd
ddddddddgZdZ
dZdZdZdZdZe��ejj�dd�ejj��D�ZdZdZe�d �jZe�d!�jZe�d"�Z e�d#�Z!d$d%d&hZ"dBd(d)�Z#Gd*d+�d+ej$j%�Z&d,d-�Z'e&fd.d/�Z(Gd0d�dej)�Z*Gd1d�d�Z+zddl,Z,Wne-k
�r`YnXGd2d3�d3e+�Z.e�/d3�Gd4d�de0�Z1Gd5d�de1�Z2Gd6d�de1�Z3Gd7d�de1�Z4Gd8d	�d	e1�Z5Gd9d
�d
e1�Z6Gd:d�de1�Z7Gd;d
�d
e1�Z8Gd<d�de8�Z9Gd=d�de8�Z:Gd>d�de8�Z;Gd?d�de1�Z<Gd@d�de1�Z=GdAd�de>e<�Z?e1Z@dS)Ca�
HTTP/1.1 client library

<intro stuff goes here>
<other stuff, too>

HTTPConnection goes through a number of "states", which define when a client
may legally make another request or fetch the response for a particular
request. This diagram details these state transitions:

    (null)
      |
      | HTTPConnection()
      v
    Idle
      |
      | putrequest()
      v
    Request-started
      |
      | ( putheader() )*  endheaders()
      v
    Request-sent
      |\_____________________________
      |                              | getresponse() raises
      | response = getresponse()     | ConnectionError
      v                              v
    Unread-response                Idle
    [Response-headers-read]
      |\____________________
      |                     |
      | response.read()     | putrequest()
      v                     v
    Idle                  Req-started-unread-response
                     ______/|
                   /        |
   response.read() |        | ( putheader() )*  endheaders()
                   v        v
       Request-started    Req-sent-unread-response
                            |
                            | response.read()
                            v
                          Request-sent

This diagram presents the following rules:
  -- a second request may not be started until {response-headers-read}
  -- a response [object] cannot be retrieved until {request-sent}
  -- there is no differentiation between an unread response body and a
     partially read response body

Note: this enforcement is applied by the HTTPConnection class. The
      HTTPResponse class does not enforce this state machine, which
      implies sophisticated clients may accelerate the request/response
      pipeline. Caution should be taken, though: accelerating the states
      beyond the above pattern may imply knowledge of the server's
      connection-close behavior for certain requests. For example, it
      is impossible to tell whether the server will close the connection
      UNTIL the response headers have been read; this means that further
      requests cannot be placed into the pipeline until it is known that
      the server will NOT be closing the connection.

Logical State                  __state            __response
-------------                  -------            ----------
Idle                           _CS_IDLE           None
Request-started                _CS_REQ_STARTED    None
Request-sent                   _CS_REQ_SENT       None
Unread-response                _CS_IDLE           <response_class>
Req-started-unread-response    _CS_REQ_STARTED    <response_class>
Req-sent-unread-response       _CS_REQ_SENT       <response_class>
�N)�urlsplit�HTTPResponse�HTTPConnection�
HTTPException�NotConnected�UnknownProtocol�UnknownTransferEncoding�UnimplementedFileMode�IncompleteRead�
InvalidURL�ImproperConnectionState�CannotSendRequest�CannotSendHeader�ResponseNotReady�
BadStatusLine�LineTooLong�RemoteDisconnected�error�	responses�Pi�ZUNKNOWNZIdlezRequest-startedzRequest-sentcCsi|]}||j�qS�)�phrase)�.0�vrr�#/usr/lib64/python3.8/http/client.py�
<dictcomp>jsri�ds[^:\s][^:\r\n]*s\n(?![ \t])|\r(?![ \t\n])z[- ]z[-]ZPATCHZPOSTZPUT�datac
Cshz|�d�WStk
rb}z8t|j|j|j|jd|��||j|j�|f�d�W5d}~XYnXdS)z<Call data.encode("latin-1") but show a better error message.�latin-1z`%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') if you want to send it encoded in UTF-8.N)�encode�UnicodeEncodeError�encoding�object�start�end�title)r�name�errrrr�_encode�s���r(c@seZdZdd�ZdS)�HTTPMessagecCsj|��d}t|�}g}d}|��D]@}|d|���|krBd}n|dd���sVd}|r$|�|�q$|S)a�Find all header lines matching a given header name.

        Look through the list of headers and find all lines matching a given
        header name (and their continuation lines).  A list of the lines is
        returned, without interpretation.  If the header does not occur, an
        empty list is returned.  If the header occurs multiple times, all
        occurrences are returned.  Case is not important in the header name.

        �:rN�)�lower�len�keys�isspace�append)�selfr&�nZlstZhit�linerrr�getallmatchingheaders�s
z!HTTPMessage.getallmatchingheadersN)�__name__�
__module__�__qualname__r4rrrrr)�sr)cCsXg}|�td�}t|�tkr&td��|�|�t|�tkrHtdt��|dkrqTq|S)z�Reads potential header lines into a list from a file pointer.

    Length of line is limited by _MAXLINE, and number of
    headers is limited by _MAXHEADERS.
    r+�header linezgot more than %d headers��
�
�)�readline�_MAXLINEr-rr0�_MAXHEADERSr)�fp�headersr3rrr�
_read_headers�s
rBcCs,t|�}d�|��d�}tjj|d��|�S)aGParses only RFC2822 headers from a file pointer.

    email Parser wants to see strings rather than bytes.
    But a TextIOWrapper around self.rfile would buffer too many bytes
    from the stream, bytes which we later need to read as bytes.
    So we read the correct bytes here, as bytes, for email Parser
    to parse.

    r<�
iso-8859-1)�_class)rB�join�decode�email�parserZParserZparsestr)r@rDrAZhstringrrr�
parse_headers�s
rIcseZdZd@dd�Zdd�Zdd�Zd	d
�Zdd�Z�fd
d�Z�fdd�Z	dd�Z
dd�ZdAdd�Zdd�Z
dd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�ZdBd(d)�ZdCd*d+�ZdD�fd,d-�	Zd.d/�Zd0d1�Zd2d3�ZdEd4d5�Zd6d7�Zd8d9�Zd:d;�Zd<d=�Zd>d?�Z �Z!S)FrrNcCsR|�d�|_||_||_d|_|_t|_t|_t|_	t|_
t|_t|_t|_
dS)N�rb)Zmakefiler@�
debuglevel�_methodrA�msg�_UNKNOWN�version�status�reason�chunked�
chunk_left�length�
will_close)r1�sockrK�method�urlrrr�__init__�szHTTPResponse.__init__cCst|j�td�d�}t|�tkr*td��|jdkrBtdt|��|sNt	d��z|�
dd�\}}}WnFtk
r�z|�
dd�\}}d}Wntk
r�d}YnXYnX|�d	�s�|�
�t|��z$t|�}|d
ks�|dkr�t|��Wntk
�rt|��YnX|||fS)Nr+rCzstatus linerzreply:z-Remote end closed connection without response��zHTTP/ri�)�strr@r=r>r-rrK�print�reprr�split�
ValueError�
startswith�_close_connr�int)r1r3rOrPrQrrr�_read_statuss2

zHTTPResponse._read_statusc	Cs�|jdk	rdS|��\}}}|tkr&qHt|j�}|jdkrDtd|�~q||_|_|�	�|_
|dkrnd|_n|�d�r�d|_nt
|��t|j�|_|_|jdkr�|j��D]\}}td|d|�q�|j�d	�}|r�|��d
kr�d|_d|_nd|_|��|_d|_|j�d
�}|�rb|j�sbzt|�|_Wntk
�rLd|_YnX|jdk�rhd|_nd|_|tk�s�|tk�s�d|k�r�dk�s�n|jdk�r�d|_|j�s�|j�s�|jdk�r�d|_dS)Nrzheaders:)zHTTP/1.0zHTTP/0.9�
zHTTP/1.��header:r*�transfer-encodingrRTF�content-lengthr���HEAD)rArdZCONTINUErBr@rKr]�coderP�striprQrOrarrIrM�items�getr,rRrS�_check_closerUrTrcr`Z
NO_CONTENTZNOT_MODIFIEDrL)	r1rOrPrQZskipped_headers�hdr�valZtr_encrTrrr�begin5sf







�
�
���zHTTPResponse.begincCsv|j�d�}|jdkr.|r*d|��kr*dSdS|j�d�r>dS|rRd|��krRdS|j�d�}|rrd|��krrdSdS)NZ
connectionrf�closeTFz
keep-alivezproxy-connection)rArorOr,)r1ZconnZpconnrrrrp}s
zHTTPResponse._check_closecCs|j}d|_|��dS�N)r@rt)r1r@rrrrb�szHTTPResponse._close_conncs$zt���W5|jr|��XdSru)r@rb�superrt�r1��	__class__rrrt�szHTTPResponse.closecst���|jr|j��dSru)rv�flushr@rwrxrrrz�s
zHTTPResponse.flushcCsdS)zAlways returns TrueTrrwrrr�readable�szHTTPResponse.readablecCs
|jdkS)z!True if the connection is closed.N)r@rwrrr�isclosed�szHTTPResponse.isclosedcCs�|jdkrdS|jdkr$|��dS|dk	rRt|�}|�|�}t|�d|���S|jr`|��S|j	dkrv|j�
�}n6z|�|j	�}Wntk
r�|���YnXd|_	|��|SdS)Nr<rkr)
r@rLrb�	bytearray�readinto�
memoryview�tobytesrR�_readall_chunkedrT�read�
_safe_readr
)r1�amt�br2�srrrr��s*



zHTTPResponse.readcCs�|jdkrdS|jdkr$|��dS|jr4|�|�S|jdk	r^t|�|jkr^t|�d|j�}|j�|�}|s||r||��n&|jdk	r�|j|8_|js�|��|S)z^Read up to len(b) bytes into bytearray b and return the number
        of bytes read.
        Nrrk)	r@rLrbrR�_readinto_chunkedrTr-rr~)r1r�r2rrrr~�s$





zHTTPResponse.readintocCsr|j�td�}t|�tkr$td��|�d�}|dkrB|d|�}zt|d�WStk
rl|���YnXdS)Nr+z
chunk size�;r�)	r@r=r>r-r�findrcr`rb)r1r3�irrr�_read_next_chunk_sizes
z"HTTPResponse._read_next_chunk_sizecCs:|j�td�}t|�tkr$td��|s*q6|dkrq6qdS)Nr+ztrailer liner9)r@r=r>r-r�r1r3rrr�_read_and_discard_trailersz&HTTPResponse._read_and_discard_trailercCsl|j}|sh|dk	r|�d�z|��}Wntk
rDtd��YnX|dkrb|��|��d}||_|S)NrZr<r)rSr�r�r`r
r�rb)r1rSrrr�_get_chunk_left s
zHTTPResponse._get_chunk_leftcCsbg}z6|��}|dkrq0|�|�|��d|_qd�|�WStk
r\td�|���YnXdS�Nrr<)r�r0r�rSrEr
)r1�valuerSrrrr�8szHTTPResponse._readall_chunkedcCs�d}t|�}zv|��}|dkr$|WSt|�|krN|�|�}|||_||WS|d|�}|�|�}||d�}||7}d|_qWn(tk
r�tt|d|����YnXdS)Nr)rr�r-�_safe_readintorSr
�bytes)r1r�Ztotal_bytesZmvbrSr2Ztemp_mvbrrrr�Fs"



zHTTPResponse._readinto_chunkedcCs.|j�|�}t|�|kr*t||t|���|S)aRead the number of bytes requested.

        This function should be used when <amt> bytes "should" be present for
        reading. If the bytes are truly not available (due to EOF), then the
        IncompleteRead exception can be used to detect the problem.
        )r@r�r-r
)r1r�rrrrr�^szHTTPResponse._safe_readcCs:t|�}|j�|�}||kr6tt|d|��||��|S)z2Same as _safe_read, but for reading into a buffer.N)r-r@r~r
r�)r1r�r�r2rrrr�js
zHTTPResponse._safe_readinto���cCs�|jdks|jdkrdS|jr(|�|�S|jdk	rJ|dksD||jkrJ|j}|j�|�}|sh|rh|��n|jdk	r�|jt|�8_|S)zvRead with at most one underlying system call.  If at least one
        byte is buffered, return that instead.
        Nrkr<r)r@rLrR�_read1_chunkedrT�read1rbr-)r1r2�resultrrrr�rs


zHTTPResponse.read1cCs4|jdks|jdkrdS|jr(|�|�S|j�|�S)Nrkr<)r@rLrR�
_peek_chunked�peek)r1r2rrrr��s

zHTTPResponse.peekcs�|jdks|jdkrdS|jr*t��|�S|jdk	rL|dksF||jkrL|j}|j�|�}|sj|rj|��n|jdk	r�|jt|�8_|S)Nrkr<r)r@rLrRrvr=rTrbr-)r1�limitr�rxrrr=�s

zHTTPResponse.readlinecCsd|��}|dks|dkrdSd|kr0|ks6n|}|j�|�}|jt|�8_|s`td��|Sr�)r�r@r�rSr-r
)r1r2rSr�rrrr��szHTTPResponse._read1_chunkedcCsDz|��}Wntk
r"YdSX|dkr0dS|j�|�d|�S)Nr<)r�r
r@r�)r1r2rSrrrr��szHTTPResponse._peek_chunkedcCs
|j��Sru)r@�filenorwrrrr��szHTTPResponse.filenocCsF|jdkrt��|j�|�p|}t|t�s4t|d�s8|Sd�|�SdS)axReturns the value of the header matching *name*.

        If there are multiple matching headers, the values are
        combined into a single string separated by commas and spaces.

        If no matching header is found, returns *default* or None if
        the *default* is not specified.

        If the headers are unknown, raises http.client.ResponseNotReady.

        N�__iter__z, )rArZget_all�
isinstancer\�hasattrrE)r1r&�defaultrArrr�	getheader�s
zHTTPResponse.getheadercCs|jdkrt��t|j���S)z&Return list of (header, value) tuples.N)rAr�listrnrwrrr�
getheaders�s
zHTTPResponse.getheaderscCs|Srurrwrrrr��szHTTPResponse.__iter__cCs|jS)ajReturns an instance of the class mimetools.Message containing
        meta-information associated with the URL.

        When the method is HTTP, these headers are those returned by
        the server at the head of the retrieved HTML page (including
        Content-Length and Content-Type).

        When the method is FTP, a Content-Length header will be
        present if (as is now usual) the server passed back a file
        length in response to the FTP retrieval request. A
        Content-Type header will be present if the MIME type can be
        guessed.

        When the method is local-file, returned headers will include
        a Date representing the file's last-modified time, a
        Content-Length giving file size, and a Content-Type
        containing a guess at the file's type. See also the
        description of the mimetools module.

        )rArwrrr�info�szHTTPResponse.infocCs|jS)aZReturn the real URL of the page.

        In some cases, the HTTP server redirects a client to another
        URL. The urlopen() function handles this transparently, but in
        some cases the caller needs to know which URL the client was
        redirected to. The geturl() method can be used to get at this
        redirected URL.

        )rXrwrrr�geturl�s
zHTTPResponse.geturlcCs|jS)zuReturn the HTTP status code that was sent with the response,
        or None if the URL is not an HTTP URL.

        )rPrwrrr�getcode�szHTTPResponse.getcode)rNN)N)r�)r�)r�)N)"r5r6r7rYrdrsrprbrtrzr{r|r�r~r�r�r�r�r�r�r�r�r�r=r�r�r�r�r�r�r�r�r��
__classcell__rrrxrr�s<	
!H

 "

	

c@s
eZdZdZdZeZeZdZ	dZ
edd��Zedd��Z
d	ejd	d
fdd�Zd7d
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd8d d!�Zd9d"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Z d:dd.�d/d0�Z!d	ifdd.�d1d2�Z"d3d4�Z#d5d6�Z$d	S);rrfzHTTP/1.1r+rcCst|tj�S)zFTest whether a file-like object is a text or a binary stream.
        )r��io�
TextIOBase)�streamrrr�
_is_textIOszHTTPConnection._is_textIOcCsf|dkr|��tkrdSdSt|d�r*dSzt|�}|jWStk
rNYnXt|t�rbt|�SdS)aGet the content-length based on the body.

        If the body is None, we set Content-Length: 0 for methods that expect
        a body (RFC 7230, Section 3.3.2). We also set the Content-Length for
        any method if the body is a str or bytes-like object and not a file.
        Nrr�)	�upper�_METHODS_EXPECTING_BODYr�r�nbytes�	TypeErrorr�r\r-)�bodyrWZmvrrr�_get_content_lengths

z"HTTPConnection._get_content_lengthN� cCsn||_||_||_d|_g|_d|_t|_d|_d|_	d|_
i|_|�||�\|_
|_|�|j
�tj|_dSru)�timeout�source_address�	blocksizerV�_buffer�_HTTPConnection__response�_CS_IDLE�_HTTPConnection__staterL�_tunnel_host�_tunnel_port�_tunnel_headers�
_get_hostport�host�port�_validate_host�socketZcreate_connection�_create_connection)r1r�r�r�r�r�rrrrY4szHTTPConnection.__init__cCs<|jrtd��|�||�\|_|_|r.||_n
|j��dS)aDSet up host and port for HTTP CONNECT tunnelling.

        In a connection that uses HTTP CONNECT tunneling, the host passed to the
        constructor is used as a proxy server that relays all communication to
        the endpoint passed to `set_tunnel`. This done by sending an HTTP
        CONNECT request to the proxy server when the connection is established.

        This method must be called before the HTTP connection has been
        established.

        The headers argument should be a mapping of extra HTTP headers to send
        with the CONNECT request.
        z.Can't set up tunnel for established connectionN)rV�RuntimeErrorr�r�r�r��clear)r1r�r�rArrr�
set_tunnelJszHTTPConnection.set_tunnelcCs�|dkr�|�d�}|�d�}||kr�zt||dd��}WnHtk
r�||dd�dkrh|j}ntd||dd���YnX|d|�}n|j}|r�|ddkr�|ddkr�|dd�}||fS)	Nr*�]r+r[znonnumeric port: '%s'r�[r�)�rfindrcr`�default_portr)r1r�r�r��jrrrr�bs

zHTTPConnection._get_hostportcCs
||_dSru)rK)r1�levelrrr�set_debuglevelvszHTTPConnection.set_debuglevelcCs�d|j|jf}|�d�}|�|�|j��D](\}}d||f}|�d�}|�|�q.|�d�|j|j|jd�}|�	�\}}	}
|	t
jjkr�|�
�td|	|
��f��|j�td�}t|�tkr�td	��|s�q�|d
kr�q�|jdkr�td|���q�dS)
NzCONNECT %s:%d HTTP/1.0
�asciiz%s: %s
rr:�rWzTunnel connection failed: %d %sr+r8r9rrg)r�r�r�sendr�rn�response_classrVrLrd�http�
HTTPStatusZOKrt�OSErrorrmr@r=r>r-rrKr]rF)r1Zconnect_strZ
connect_bytes�headerr�Z
header_strZheader_bytes�responserOrl�messager3rrr�_tunnelys4�



�
zHTTPConnection._tunnelcCsB|�|j|jf|j|j�|_|j�tjtj	d�|j
r>|��dS)z3Connect to the host and port specified in __init__.r+N)r�r�r�r�r�rVZ
setsockoptr�ZIPPROTO_TCPZTCP_NODELAYr�r�rwrrr�connect�s
�zHTTPConnection.connectcCsBt|_z|j}|r d|_|��W5|j}|r<d|_|��XdS)z(Close the connection to the HTTP server.N)r�r�r�rtrV)r1r�rVrrrrt�szHTTPConnection.closecCs|jdkr |jr|��nt��|jdkr8tdt|��t|d�r�|jdkrTtd�|�|�}|rt|jdkrttd�|�	|j
�}|s�q�|r�|�d�}|j�|�qtdSz|j�|�WnLt
k
�rt|tjj�r�|D]}|j�|�q�nt
dt|���YnXdS)	z�Send `data' to the server.
        ``data`` can be a string object, a bytes object, an array object, a
        file-like object that supports a .read() method, or an iterable object.
        Nrzsend:r��sendIng a read()able�encoding file using iso-8859-1rCz9data should be a bytes-like object or an iterable, got %r)rV�	auto_openr�rrKr]r^r�r�r�r�rZsendallr�r��collections�abc�Iterable�type)r1rr�	datablock�drrrr��s8






�zHTTPConnection.sendcCs|j�|�dS)zuAdd a line of output to the current request buffer.

        Assumes that the line does *not* end with \r\n.
        N)r�r0)r1r�rrr�_output�szHTTPConnection._outputccs^|jdkrtd�|�|�}|r2|jdkr2td�|�|j�}|sDqZ|rR|�d�}|Vq2dS)Nrr�r�rC)rKr]r�r�r�r)r1r{rr�rrr�_read_readable�s


zHTTPConnection._read_readableFcCs |j�d�d�|j�}|jdd�=|�|�|dk	�rt|d�rN|�|�}nZzt|�WnFtk
r�zt|�}Wn$tk
r�tdt	|���YnXYnX|f}|D]R}|s�|j
dkr�td�q�|r�|jdkr�t
|�d	�d
��d�|d}|�|�q�|�r|jdk�r|�d�dS)
z�Send the currently buffered request and clear the buffer.

        Appends an extra \r\n to the buffer.
        A message_body may be specified, to be appended to the request.
        )r<r<r:Nr�zAmessage_body should be a bytes-like object or an iterable, got %rrzZero length chunk ignoredrf�Xz
r�s0

)r��extendrEr�r�r�rr��iterr�rKr]�	_http_vsnr-r)r1�message_body�encode_chunkedrMZchunks�chunkrrr�_send_output�s:


�
�zHTTPConnection._send_outputcCs�|jr|j��rd|_|jtkr(t|_n
t|j��|�|�||_|pHd}|�|�d|||j	f}|�
|�|��|jdk�r�|�s�d}|�
d�r�t|�\}}}}}|r�z|�d�}Wntk
r�|�d�}YnX|�d	|�n�|jr�|j}	|j}
n|j}	|j}
z|	�d�}Wn tk
�r4|	�d�}YnX|	�d
�dk�rRd|d
}|
|jk�rl|�d	|�n|�d�}|�d	d||
f�|�s�|�dd�ndS)a`Send a request to the server.

        `method' specifies an HTTP request method, e.g. 'GET'.
        `url' specifies the object being requested, e.g. '/index.html'.
        `skip_host' if True does not add automatically a 'Host:' header
        `skip_accept_encoding' if True does not add automatically an
           'Accept-Encoding:' header
        N�/z%s %s %srfr[r�r�ZidnaZHostr*r�[�]z%s:%szAccept-EncodingZidentity)r�r|r�r��_CS_REQ_STARTEDr
�_validate_methodrL�_validate_path�
_http_vsn_strr��_encode_requestr�rarrr �	putheaderr�r�r�r�r�r�rF)r1rWrX�	skip_host�skip_accept_encoding�requestZnetlocZnilZ
netloc_encr�r�Zhost_encrrr�
putrequest sP






zHTTPConnection.putrequestcCs
|�d�S)Nr�)r)r1r�rrrr��szHTTPConnection._encode_requestcCs,t�|�}|r(td|�d|���d���dS)z&Validate a method name for putrequest.z)method can't contain control characters. � (found at least �)N)�$_contains_disallowed_method_pchar_re�searchr`�group)r1rW�matchrrrr��s

�zHTTPConnection._validate_methodcCs,t�|�}|r(td|�d|���d���dS)zValidate a url for putrequest.�&URL can't contain control characters. r�r�N��!_contains_disallowed_url_pchar_rer�rr�)r1rXr�rrrr��s
zHTTPConnection._validate_pathcCs,t�|�}|r(td|�d|���d���dS)z9Validate a host so it doesn't contain control characters.r�r�r�Nr�)r1r�r�rrrr��s
zHTTPConnection._validate_hostcGs�|jtkrt��t|d�r$|�d�}t|�s:td|f��t|�}t|�D]\\}}t|d�rl|�d�||<nt	|t
�r�t|��d�||<t||�rJtd||f��qJd�
|�}|d|}|�|�dS)	zkSend a request header line to the server.

        For example: h.putheader('Accept', 'text/html')
        rr�zInvalid header name %rrzInvalid header value %rs
	s: N)r�r�rr�r�_is_legal_header_namer`r��	enumerater�rcr\�_is_illegal_header_valuerEr�)r1r��valuesr�Z	one_valuer�rrrr��s"





zHTTPConnection.putheader�r�cCs*|jtkrt|_nt��|j||d�dS)z�Indicate that the last header line has been sent to the server.

        This method sends the request to the server.  The optional message_body
        argument can be used to pass a message body associated with the
        request.
        rN)r�r��_CS_REQ_SENTrr�)r1r�r�rrr�
endheaders�s
zHTTPConnection.endheaderscCs|�|||||�dS)z&Send a complete request to the server.N)�
_send_request)r1rWrXr�rAr�rrrr��szHTTPConnection.requestcCs�tdd�|D��}i}d|kr&d|d<d|kr6d|d<|j||f|�d|kr�d	|kr�d
}|�||�}|dkr�|dk	r�|jdkr�td|�d
}|�dd�q�|�dt|��nd
}|��D]\}	}
|�|	|
�q�t|t�r�t	|d�}|j
||d�dS)Ncss|]}|��VqdSru)r,)r�krrr�	<genexpr>�sz/HTTPConnection._send_request.<locals>.<genexpr>r�r+r�zaccept-encodingr�rirhFrzUnable to determine size of %rTzTransfer-EncodingrRzContent-Lengthr�r)�	frozensetr�r�rKr]r�r\rnr�r(r)r1rWrXr�rAr�Zheader_namesZskipsZcontent_lengthrqr�rrrr�s0	


zHTTPConnection._send_requestcCs�|jr|j��rd|_|jtks&|jr0t|j��|jdkrR|j|j|j|jd�}n|j|j|jd�}zNz|�	�Wnt
k
r�|���YnXt|_|j
r�|��n||_|WS|���YnXdS)a)Get the response from the server.

        If the HTTPConnection is in the correct state, returns an
        instance of HTTPResponse or of whatever object is returned by
        the response_class variable.

        If a request has not been sent or if a previous response has
        not be handled, ResponseNotReady is raised.  If the HTTP
        response indicates that the connection should be closed, then
        it will be closed before the response is returned.  When the
        connection is closed, the underlying socket is closed.
        Nrr�)r�r|r�rrrKr�rVrLrs�ConnectionErrorrtr�rU)r1r�rrr�getresponses.

�
zHTTPConnection.getresponse)NN)NF)FF)N)%r5r6r7r�r�rr��	HTTP_PORTr�r�rK�staticmethodr�r�r��_GLOBAL_DEFAULT_TIMEOUTrYr�r�r�r�r�rtr�r�r�r�r�r�r�r�r�r�rr�rr
rrrrrsL

�

	&
6�
	
�.csHeZdZdZeZdddejdfdddd��fdd�Z�fdd�Z	�Z
S)	�HTTPSConnectionz(This class allows communication via SSL.Nr�)�context�check_hostnamer�cs�tt|�j|||||	d�|dk	s2|dk	s2|dk	rHddl}
|
�dtd�||_||_|dkrtt�	�}|j
dk	rtd|_
|jtjk}|dkr�|j
}|r�|s�td��|s�|r�|�||�|j
dk	r�d|_
||_|dk	r�||j_
dS)N)r�rzTkey_file, cert_file and check_hostname are deprecated, use a custom context instead.rZTzMcheck_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED)rvrrY�warnings�warn�DeprecationWarning�key_file�	cert_file�sslZ_create_default_https_contextZpost_handshake_authZverify_modeZ	CERT_NONErr`Zload_cert_chain�_context)r1r�r�rrr�r�rrr�rZwill_verifyrxrrrYcs<���

zHTTPSConnection.__init__cs6t���|jr|j}n|j}|jj|j|d�|_dS)z(Connect to a host on a given (SSL) port.)�server_hostnameN)rvr�r�r�rZwrap_socketrV)r1rrxrrr��s

�zHTTPSConnection.connect)r5r6r7�__doc__�
HTTPS_PORTr�r�rrYr�r�rrrxrr\s��$rc@seZdZdS)rN�r5r6r7rrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdd�ZdS)rcCs|f|_||_dSru)�argsrO)r1rOrrrrY�szUnknownProtocol.__init__N�r5r6r7rYrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)r	Nrrrrrr	�sc@s$eZdZddd�Zdd�ZejZdS)r
NcCs|f|_||_||_dSru)r�partial�expected)r1r!r"rrrrY�szIncompleteRead.__init__cCs2|jdk	rd|j}nd}d|jjt|j�|fS)Nz, %i more expectedr[z%s(%i bytes read%s))r"ryr5r-r!)r1�errr�__repr__�s
�zIncompleteRead.__repr__)N)r5r6r7rYr$r"�__str__rrrrr
�s
c@seZdZdS)rNrrrrrr�sc@seZdZdS)r
Nrrrrrr
�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdd�ZdS)rcCs|st|�}|f|_||_dSru)r^rr3r�rrrrY�szBadStatusLine.__init__Nr rrrrr�sc@seZdZdd�ZdS)rcCst�|dt|f�dS)Nz&got more than %d bytes when reading %s)rrYr>)r1Z	line_typerrrrY�s�zLineTooLong.__init__Nr rrrrr�sc@seZdZdd�ZdS)rcOs"t�|d�tj|f|�|�dS)Nr[)rrY�ConnectionResetError)r1�pos�kwrrrrY�szRemoteDisconnected.__init__Nr rrrrr�s)r)ArZemail.parserrGZ
email.messager�r��rer�Zcollections.abcr�Zurllib.parser�__all__rrrNr�r�r�globals�updater��__members__rrr>r?�compile�	fullmatchrr�rrr�r�r(r�ZMessager)rBrI�BufferedIOBaserrr�ImportErrorrr0�	Exceptionrrrrrr	r
rr
rrrrr&rrrrrr�<module>s�F�



W8
__pycache__/cookiejar.cpython-38.opt-2.pyc000064400000111657150532417300014325 0ustar00U

e5d#,�@sddddddddgZdd	lZdd	lZdd	lZdd	lZdd	lZdd	lZdd	lZdd	l	Z
dd	lZdd
l
mZdZd	add
�Zeejj�ZdZdd�ZdZdd�ZdddddddgZdddddd d!d"d#d$d%d&gZgZeD]Ze�e���q�dtd'd(�Z dud)d*�Z!d	d	d	d	d+�Z"e�#d,ej$�Z%d-d.�Z&d/d0�Z'e�#d1ej$�Z(e�#d2ej)ej$B�Z*e�#d3ej+ej$B�Z,d4d5�Z-e�#d6ej+ej$B�Z.d7d8�Z/d9d:�Z0e�#d;�Z1e�#d<�Z2e�#d=�Z3e�#d>�Z4d?d@�Z5e�#dA�Z6dBdC�Z7dDdE�Z8dFdG�Z9e�#dHej$�Z:dIdJ�Z;dKdL�Z<dMdN�Z=dOdP�Z>e�#dQej$�Z?dRdS�Z@dTdU�ZAdVdW�ZBdXdY�ZCdZZDe�#d[�ZEd\d]�ZFd^d_�ZGd`da�ZHdbdc�ZIGddd�d�ZJGded�d�ZKGdfd�deK�ZLdgdh�ZMdidj�ZNGdkdl�dl�ZOGdmd�d�ZPGdnd�deQ�ZRGdod�deP�ZSdpdq�ZTGdrd�deS�ZUGdsd�deS�ZVd	S)v�Cookie�	CookieJar�CookiePolicy�DefaultCookiePolicy�
FileCookieJar�LWPCookieJar�	LoadError�MozillaCookieJar�N)�timegmFcGs(tsdStsddl}|�d�atj|�S)Nr	zhttp.cookiejar)�debug�logger�loggingZ	getLogger)�argsr
�r�&/usr/lib64/python3.8/http/cookiejar.py�_debug,s
rzQa filename was not supplied (nor was the CookieJar instance initialised with one)cCsJddl}ddl}ddl}|��}|�d|�|��}|jd|dd�dS)Nr	zhttp.cookiejar bug!
%s�)�
stacklevel)�io�warnings�	traceback�StringIO�	print_exc�getvalue�warn)rrr�f�msgrrr�_warn_unhandled_exception:s
ri�cCs�|dd�\}}}}}}|tkr�d|kr4dkr�nnhd|krLdkr�nnPd|krddkr�nn8d|kr|dkr�nn d|kr�dkr�nnt|�SdSdS)	N����r	��;�=)�
EPOCH_YEARr
)�tt�year�monthZmday�hour�min�secrrr�_timegmIs&8��
��
��
r,ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs@|dkrtj��}ntj�|�}d|j|j|j|j|j|jfS)Nz%04d-%02d-%02d %02d:%02d:%02dZ)	�datetime�utcnow�utcfromtimestampr'r(�dayr)�minute�second��tZdtrrr�	time2isozWs�r5cCsR|dkrtj��}ntj�|�}dt|��|jt|jd|j|j	|j
|jfS)Nz#%s, %02d-%s-%04d %02d:%02d:%02d GMTr)r-r.r/�DAYSZweekdayr0�MONTHSr(r'r)r1r2r3rrr�
time2netscapejs
�r8)ZGMT�UTCZUT�Zz^([-+])?(\d\d?):?(\d\d)?$cCsjd}|tkrd}nTt�|�}|rfdt|�d��}|�d�rR|dt|�d��}|�d�dkrf|}|S)Nr	ir��<r�-)�	UTC_ZONES�TIMEZONE_RE�search�int�group)�tz�offset�mrrr�offset_from_tz_string�s

rFc
Cs�t|�}|tjkrdSzt�|���d}Wn^tk
r�zt|�}Wntk
r`YYdSXd|krvdkr�nn|}nYdSYnX|dkr�d}|dkr�d}|dkr�d}t|�}t|�}t|�}t|�}|dk�r6t�t���d}|d}	|}
|||	}|	|
}	t	|	�dk�r6|	dk�r.|d}n|d}t
|||||||f�}|dk	�r�|dk�rdd}|��}t|�}|dk�r�dS||}|S)Nrr r	i��d�2r9)
rAr-ZMAXYEAR�MONTHS_LOWER�index�lower�
ValueError�time�	localtime�absr,�upperrF)
r0�mon�yr�hrr*r+rCZimonZcur_yrrEZtmpr4rDrrr�	_str2time�sV







rTzV^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$z+^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*a�^
    (\d\d?)            # day
       (?:\s+|[-\/])
    (\w+)              # month
        (?:\s+|[-\/])
    (\d+)              # year
    (?:
          (?:\s+|:)    # separator before clock
       (\d\d?):(\d\d)  # hour:min
       (?::(\d\d))?    # optional seconds
    )?                 # optional clock
       \s*
    (?:
       ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+) # timezone
       \s*
    )?
    (?:
       \(\w+\)         # ASCII representation of timezone in parens.
       \s*
    )?$cCs�t�|�}|rl|��}t�|d���d}t|d�|t|d�t|d�t|d�t|d�f}t|�S|�	�}t
�d|d�}dgd\}}}}}}	}
t�|�}|dk	r�|��\}}}}}}	}
ndSt
||||||	|
�S)	Nrrr	r;����)�STRICT_DATE_REr@�groupsrIrJrKrA�floatr,�lstrip�
WEEKDAY_RE�sub�LOOSE_HTTP_DATE_RErT)�textrE�grQr&r0rRrSr*r+rCrrr�	http2time�s$



�
rba�^
    (\d{4})              # year
       [-\/]?
    (\d\d?)              # numerical month
       [-\/]?
    (\d\d?)              # day
   (?:
         (?:\s+|[-:Tt])  # separator before clock
      (\d\d?):?(\d\d)    # hour:min
      (?::?(\d\d(?:\.\d*)?))?  # optional seconds (and fractional)
   )?                    # optional clock
      \s*
   (?:
      ([-+]?\d\d?:?(:?\d\d)?
       |Z|z)             # timezone  (Z is "zero meridian", i.e. GMT)
      \s*
   )?$c
Csd|��}dgd\}}}}}}}t�|�}|dk	rL|��\}}}}}}}}	ndSt|||||||�S)NrX)r\�ISO_DATE_REr@rZrT)
r`r0rQrRrSr*r+rCrE�_rrr�iso2time+s

recCs*|�d�\}}|jd|�|j|d�S)Nr	)�span�string)�match�start�endrrr�	unmatchedLsrkz^\s*([^=\s;,]+)z&^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"z^\s*=\s*([^\s;,]*)z\\(.)c
Csg}|D]�}|}g}|r�t�|�}|r�t|�}|�d�}t�|�}|rft|�}|�d�}t�d|�}n.t�|�}|r�t|�}|�d�}|��}nd}|�	||f�q|�
��d�r�|�
�dd�}|r�|�	|�g}qt�
dd|�\}}	|}q|r|�	|�q|S)Nrz\1�,z^[=\s;]*rW)�HEADER_TOKEN_REr@rkrB�HEADER_QUOTED_VALUE_RE�HEADER_ESCAPE_REr^�HEADER_VALUE_RE�rstrip�appendr\�
startswith�re�subn)
Z
header_values�resultr`Z	orig_text�pairsrE�name�valueZnon_junkZ
nr_junk_charsrrr�split_header_wordsUs>.







rz�([\"\\])cCs|g}|D]h}g}|D]F\}}|dk	rPt�d|�sDt�d|�}d|}d||f}|�|�q|r|�d�|��qd�|�S)Nz^\w+$�\\\1z"%s"�%s=%s�; �, )rtr@�HEADER_JOIN_ESCAPE_REr^rr�join)Zlists�headersrw�attr�k�vrrr�join_header_words�sr�cCs0|�d�r|dd�}|�d�r,|dd�}|S)N�"r���)rs�endswith�r`rrr�strip_quotes�s


r�cCs�d}g}|D]�}g}d}t|�d��D]�\}}|��}|�d�\}}	}
|��}|sb|dkr&q�nq&|	rn|
��nd}
|dkr�|��}||kr�|}|dkr�|
dk	r�t|
�}
d}n|dkr�|
dk	r�tt|
��}
|�||
f�q&|r|s�|�d	�|�|�q|S)
N)�expires�domain�path�secure�version�port�max-ageF�;�=r	r�Tr�)r��0)�	enumerate�split�strip�	partitionrKr�rbrr)Z
ns_headersZknown_attrsrvZ	ns_headerrw�version_setZiiZparam�key�sep�val�lcrrr�parse_ns_headers�s>
r�z\.\d+$cCs:t�|�rdS|dkrdS|ddks2|ddkr6dSdS)NFrWr	�.r�T��IPV4_REr@r�rrr�is_HDNs
r�cCsl|��}|��}||krdSt|�s(dS|�|�}|dksB|dkrFdS|�d�sTdSt|dd��shdSdS)NTFr�r	r�r)rKr��rfindrs)�A�B�irrr�domain_matchs

r�cCst�|�rdSdS�NFTr�r�rrr�liberal_is_HDNFs
r�cCs`|��}|��}t|�r t|�s0||kr,dSdS|�d�}|rL|�|�rLdS|s\||kr\dSdS)NTFr�)rKr�rsr�)r�r��initial_dotrrr�user_domain_matchPs
r�z:\d+$cCsB|��}tj�|�d}|dkr,|�dd�}t�d|d�}|��S)NrrWZHost)�get_full_url�urllib�parseZurlparseZ
get_header�cut_port_rer^rK)�request�url�hostrrr�request_hostesr�cCs4t|�}}|�d�dkr,t�|�s,|d}||fS)Nr�r��.local)r��findr�r@)r��erhn�req_hostrrr�eff_request_hostusr�cCs4|��}tj�|�}t|j�}|�d�s0d|}|S)N�/)r�r�r�Zurlsplit�escape_pathr�rs)r�r��partsr�rrr�request_path�s

r�cCs`|j}|�d�}|dkrX||dd�}zt|�Wq\tk
rTtd|�YdSXnt}|S)N�:r	rznonnumeric port: '%s')r�r�rArLr�DEFAULT_HTTP_PORT)r�r�r�r�rrr�request_port�s


r�z%/;:@&=+$,!~*'()z%([0-9a-fA-F][0-9a-fA-F])cCsd|�d���S)Nz%%%sr)rBrP)rhrrr�uppercase_escaped_char�sr�cCstj�|t�}t�t|�}|S�N)r�r�Zquote�HTTP_PATH_SAFE�ESCAPED_CHAR_REr^r�)r�rrrr��s
r�cCsP|�d�}|dkrL||dd�}|�d�}t|�rL|dksD|dkrLd|S|S)Nr�r	rZlocal)r�r�)�hr��brrr�reach�s

r�cCs$t|�}t|t|j��sdSdSdS�NTF)r�r�r�Zorigin_req_host)r�r�rrr�is_third_party�s
r�c@sJeZdZddd�Zdd�Zddd�Zd	d
�Zddd�Zd
d�Zdd�Z	dS)rFcCs�|dk	rt|�}|dk	r$tt|��}|dkr<|dkr<td��||_||_||_||_||_|��|_	||_
||_|	|_|
|_
||_||_|
|_||_||_||_t�|�|_dS)NTz-if port is None, port_specified must be false)rAr[rLr�rxryr��port_specifiedrKr��domain_specified�domain_initial_dotr��path_specifiedr�r��discard�comment�comment_url�rfc2109�copy�_rest)�selfr�rxryr�r�r�r�r�r�r�r�r�r�r�r��restr�rrr�__init__�s.

zCookie.__init__cCs
||jkSr��r�)r�rxrrr�has_nonstandard_attrszCookie.has_nonstandard_attrNcCs|j�||�Sr�)r��get)r�rx�defaultrrr�get_nonstandard_attrszCookie.get_nonstandard_attrcCs||j|<dSr�r�)r�rxryrrr�set_nonstandard_attr szCookie.set_nonstandard_attrcCs,|dkrt��}|jdk	r(|j|kr(dSdSr�)rMr�)r��nowrrr�
is_expired#s
zCookie.is_expiredcCsX|jdkrd}n
d|j}|j||j}|jdk	rFd|j|jf}n|j}d||fS)NrWr�r}z<Cookie %s for %s>)r�r�r�ryrx)r��p�limitZ	namevaluerrr�__str__)s


zCookie.__str__cCslg}dD]$}t||�}|�d|t|�f�q|�dt|j��|�dt|j��d|jjd�|�fS)N)r�rxryr�r�r�r�r�r�r�r�r�r�r�r�r}zrest=%sz
rfc2109=%sz%s(%s)r)�getattrrr�reprr�r��	__class__�__name__r�)r�rrxr�rrr�__repr__3s
zCookie.__repr__)F)N)N)
r��
__module__�__qualname__r�r�r�r�r�r�r�rrrrr�s�
*


c@s,eZdZdd�Zdd�Zdd�Zdd�Zd	S)
rcCs
t��dSr���NotImplementedError�r��cookier�rrr�set_okKszCookiePolicy.set_okcCs
t��dSr�r�r�rrr�	return_okTszCookiePolicy.return_okcCsdS�NTr)r�r�r�rrr�domain_return_okXszCookiePolicy.domain_return_okcCsdSr�r)r�r�r�rrr�path_return_ok]szCookiePolicy.path_return_okN)r�r�r�r�r�r�r�rrrrrBs		c
@s�eZdZdZdZdZdZeeBZdddddddddedddf
d	d
�Zdd�Z	d
d�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Zd1d2�Zd3d4�Zd5d6�ZdS)7rrrrUr	NTF)ZhttpsZwsscCsv||_||_||_||_||_||_|	|_|
|_||_||_	|
|_
|dk	rVt|�|_nd|_|dk	rlt|�}||_
dS)Nr)�netscape�rfc2965�rfc2109_as_netscape�hide_cookie2�
strict_domain�strict_rfc2965_unverifiable�strict_ns_unverifiable�strict_ns_domain�strict_ns_set_initial_dollar�strict_ns_set_path�secure_protocols�tuple�_blocked_domains�_allowed_domains)r��blocked_domains�allowed_domainsr�r�r�r�r�r�r�r�r�r�r�rrrr�ms"zDefaultCookiePolicy.__init__cCs|jSr�)r��r�rrrr�sz#DefaultCookiePolicy.blocked_domainscCst|�|_dSr�)r�r�)r�rrrr�set_blocked_domains�sz'DefaultCookiePolicy.set_blocked_domainscCs |jD]}t||�rdSqdSr�)r�r�)r�r�Zblocked_domainrrr�
is_blocked�s

zDefaultCookiePolicy.is_blockedcCs|jSr�)r�rrrrr�sz#DefaultCookiePolicy.allowed_domainscCs|dk	rt|�}||_dSr�)r�r�)r�rrrr�set_allowed_domains�sz'DefaultCookiePolicy.set_allowed_domainscCs.|jdkrdS|jD]}t||�rdSqdSr�)r�r�)r�r�Zallowed_domainrrr�is_not_allowed�s


z"DefaultCookiePolicy.is_not_allowedcCs@td|j|j�dD]&}d|}t||�}|||�sdSqdS)N� - checking cookie %s=%s)r��
verifiabilityrxr�r�r�Zset_ok_FT�rrxryr��r�r�r��nZfn_name�fnrrrr��s

zDefaultCookiePolicy.set_okcCsZ|jdkrtd|j|j�dS|jdkr:|js:td�dS|jdkrV|jsVtd�dSdS)Nz0   Set-Cookie2 without version attribute (%s=%s)Fr	�$   RFC 2965 cookies are switched off�$   Netscape cookies are switched offT)r�rrxryr�r�r�rrr�set_ok_version�s
�z"DefaultCookiePolicy.set_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS�Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT�Zunverifiabler�r�r�rr�r�rrr�set_ok_verifiability�sz(DefaultCookiePolicy.set_ok_verifiabilitycCs0|jdkr,|jr,|j�d�r,td|j�dSdS)Nr	�$z'   illegal name (starts with '$'): '%s'FT)r�r�rxrsrr�rrr�set_ok_name�s
�zDefaultCookiePolicy.set_ok_namecCsL|jrHt|�}|jdks(|jdkrH|jrH|�|j|�sHtd|j|�dSdS)Nr	z7   path attribute %s is not a prefix of request path %sFT)r�r�r�r�r�r�r)r�r�r��req_pathrrr�set_ok_path�s
����zDefaultCookiePolicy.set_ok_pathc
Cs�|�|j�rtd|j�dS|�|j�r8td|j�dS|j�r�t|�\}}|j}|jr�|�d�dkr�|�d�}|�dd|�}|dkr�||dd�}||d|�}	|	�	�dkr�t
|�dkr�td	|�dS|�d�r�|dd�}
n|}
|
�d�dk}|�s|d
k�rtd|�dS|j
dk�rX|�|��sX|�d��sXd|�|��sXtd||�dS|j
dk�sr|j|j@�r�t||��s�td
||�dS|j
dk�s�|j|j@�r�|dt
|��}|�d�dk�r�t�|��s�td||�dSdS)N�"   domain %s is in user block-listF�&   domain %s is not in user allow-listr�rr	r)�coZacZcomZeduZorgZnetZgovZmilrAZaeroZbiz�catZcoop�infoZjobsZmobiZmuseumrxZproZtravelZeuz&   country-code second level domain %sr�z/   non-local domain %s contains no embedded dotzO   effective request-host %s (even with added initial dot) does not end with %sz5   effective request-host %s does not domain-match %sz.   host prefix %s for domain %s contains a dotT)rr�rrr�r�r��countr�rK�lenrsr�r�r�r��DomainRFC2965Matchr��DomainStrictNoDotsr�r@)
r�r�r�r�r�r�r��jZtldZsldZundotted_domainZ
embedded_dotsZhost_prefixrrr�
set_ok_domain�s|

�

����
��
���z!DefaultCookiePolicy.set_ok_domainc	Cs�|jr�t|�}|dkrd}nt|�}|j�d�D]@}zt|�Wn"tk
rbtd|�YdSX||kr0q�q0td||j�dSdS)N�80rlz   bad port %s (not numeric)Fz$   request port (%s) not found in %sT)r�r��strr�r�rArLr�r�r�r�Zreq_portr�rrr�set_ok_port+s&

�zDefaultCookiePolicy.set_ok_portcCs@td|j|j�dD]&}d|}t||�}|||�sdSqdS)Nr)r�rr�r�r�r�Z
return_ok_FTr	r
rrrr�@s	

zDefaultCookiePolicy.return_okcCs<|jdkr|jstd�dS|jdkr8|js8td�dSdS)Nr	r
FrT)r�r�rr�r�rrr�return_ok_versionRsz%DefaultCookiePolicy.return_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdSrrr�rrr�return_ok_verifiability[sz+DefaultCookiePolicy.return_ok_verifiabilitycCs"|jr|j|jkrtd�dSdS)Nz(   secure cookie with non-secure requestFT)r��typer�rr�rrr�return_ok_securegsz$DefaultCookiePolicy.return_ok_securecCs|�|j�rtd�dSdS)Nz   cookie expiredFT)r��_nowrr�rrr�return_ok_expiresmsz%DefaultCookiePolicy.return_ok_expirescCsN|jrJt|�}|dkrd}|j�d�D]}||kr&qJq&td||j�dSdS)Nr"rlz0   request port %s does not match cookie port %sFT)r�r�r�rr$rrr�return_ok_portss�z"DefaultCookiePolicy.return_ok_portcCs�t|�\}}|j}|r*|�d�s*d|}n|}|jdkr^|j|j@r^|js^||kr^td�dS|jdkr�t||�s�td||�dS|jdkr�d|�	|�s�td||�dSdS)Nr�r	zQ   cookie with unspecified domain does not string-compare equal to request domainFzQ   effective request-host name %s does not domain-match RFC 2965 cookie domain %sz;   request-host %s does not match Netscape cookie domain %sT)
r�r�rsr�r��DomainStrictNonDomainr�rr�r�)r�r�r�r�r�r��	dotdomainrrr�return_ok_domain�s6


�����z$DefaultCookiePolicy.return_ok_domaincCs�t|�\}}|�d�sd|}|�d�s0d|}|rH|�d�sHd|}n|}|�|�sd|�|�sddS|�|�r|td|�dS|�|�r�td|�dSdS)Nr�FrrT)r�rsr�rrr)r�r�r�r�r�r.rrrr��s"






z$DefaultCookiePolicy.domain_return_okcCsbtd|�t|�}t|�}||kr&dS|�|�rR|�d�sN|||d�dkrRdStd||�dS)Nz- checking cookie path=%sTr�rz  %s does not path-match %sF)rr�rrsr�)r�r�r�rZpathlenrrrr��s

��z"DefaultCookiePolicy.path_return_ok)r�r�r�rr-rZ
DomainLiberalZDomainStrictr�rrrrrrr�rrrrr!r%r�r&r'r)r+r,r/r�r�rrrrrcsR�
#	;	cCst|���}t|j|�Sr�)�sorted�keys�mapr�)Zadictr1rrr�vals_sorted_by_key�sr3c	csVt|�}|D]D}d}z
|jWntk
r2YnXd}t|�EdH|s|VqdSr�)r3�items�AttributeError�
deepvalues)�mapping�values�objrrrr6�s
r6c@seZdZdS)�AbsentN�r�r�r�rrrrr:�sr:c@s�eZdZe�d�Ze�d�Ze�d�Ze�d�Ze�d�Z	e�dej
�Zd2dd	�Zd
d�Z
dd
�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd3d$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Z dS)4rz\Wr{z\.?[^.]*z[^.]*z^\.+z^\#LWP-Cookies-(\d+\.\d+)NcCs(|dkrt�}||_t��|_i|_dSr�)r�_policy�
_threading�RLock�
_cookies_lock�_cookies�r��policyrrrr��s

zCookieJar.__init__cCs
||_dSr�)r<rArrr�
set_policy�szCookieJar.set_policycCs�g}|j�||�sgStd|�|j|}|��D]T}|j�||�sFq2||}|��D].}|j�||�srtd�qVtd�|�|�qVq2|S)Nz!Checking %s for cookies to returnz   not returning cookiez   it's a match)	r<r�rr@r1r�r8r�rr)r�r�r��cookiesZcookies_by_pathr�Zcookies_by_namer�rrr�_cookies_for_domain�s 

zCookieJar._cookies_for_domaincCs*g}|j��D]}|�|�||��q|Sr�)r@r1�extendrE)r�r�rDr�rrr�_cookies_for_requestszCookieJar._cookies_for_requestc	Cs<|jdd�dd�d}g}|D�]}|j}|sHd}|dkrH|�d|�|jdk	rz|j�|j�rz|dkrz|j�d|j�}n|j}|jdkr�|�|j�n|�d	|j|f�|dkr|j	r�|�d
|j
�|j�d��r|j}|j
s�|�d�r�|dd�}|�d
|�|jdk	rd}|j�r,|d|j}|�|�q|S)NcSs
t|j�Sr�)rr�)�arrr�<lambda>�z)CookieJar._cookie_attrs.<locals>.<lambda>T)r��reverseFr	z$Version=%sr|r}z
$Path="%s"r�rz$Domain="%s"z$Portz="%s")�sortr�rrry�non_word_rer@�quote_rer^rxr�r�r�rsr�r�r�)	r�rDr��attrsr�r�ryr�r�rrr�
_cookie_attrssF


��
�
zCookieJar._cookie_attrscCs�td�|j��z�tt���|j_|_|�|�}|�	|�}|r^|�
d�s^|�dd�|��|jj
r�|jjs�|�
d�s�|D]}|jdkr||�dd�q�q|W5|j��X|��dS)N�add_cookie_headerrr~ZCookie2rz$Version="1")rr?�acquire�releaserArMr<r*rGrPZ
has_headerZadd_unredirected_headerr�r�r�r��clear_expired_cookies)r�r�rDrOr�rrrrQIs*



��

zCookieJar.add_cookie_headerc
Cs�g}d}d}|D�]z}|d\}}d}d}	i}
i}|dd�D�]0\}}
|��}||ks`||krd|}||krx|
dkrxd}
||
kr�q>|dkr�|
dkr�td�d}	�qr|
��}
|d	kr�|r�q>|
dkr�td
�q>|dk�r d}zt|
�}
Wn*tk
�rtd�d}	Y�qrYnXd	}|j|
}
||k�s4||k�rh|
dk�r^|d
k�r^td|�d}	�qr|
|
|<q>|
||<q>|	�rzq|�|||
|f�q|S)N)r�r�)r�r�r�r�r�r�r��
commenturlr	FrTr�z%   missing value for domain attributer�zM   missing or invalid value for expires attribute: treating as session cookier�z?   missing or invalid (non-numeric) value for max-age attribute)r�r�rUz!   missing value for %s attribute)rKrrArLr*rr)r��	attrs_set�
cookie_tuples�
boolean_attrs�value_attrsZcookie_attrsrxryZmax_age_setZ
bad_cookie�standardr�r�r�r�rrr�_normalized_cookie_tuplesjsh





�

z#CookieJar._normalized_cookie_tuplescCs&|\}}}}|�dt�}|�dt�}|�dt�}	|�dt�}
|�dd�}|dk	rtzt|�}Wntk
rrYdSX|�dd�}|�dd�}
|�d	d�}|�d
d�}|tk	r�|dkr�d}t|�}nXd}t|�}|�d
�}|dk�r|dkr�|d|�}n|d|d�}t|�dk�rd
}|tk	}d}|�r:t|�	d��}|tk�rVt
|�\}}|}n|�	d��sjd|}d}|	tk	�r�|	dk�r�t|�}	nd}t�
dd|	�}	nd}	|
tk�r�d}
d}
nH|
|jk�rz|�|||�Wntk
�r�YnXtd|||�dSt||||	||||||||
|
|||�S)Nr�r�r�r�r�r�Fr�r�rUrWTr�r�r	rr�z\s+z2Expiring cookie, domain='%s', path='%s', name='%s')r�r:rArLr�r�r�r�boolrsr�r�rtr^r*�clear�KeyErrorrr)r��tupr�rxryrZr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrr�_cookie_from_cookie_tuple�s�







��z#CookieJar._cookie_from_cookie_tuplecCs6|�|�}g}|D]}|�||�}|r|�|�q|Sr�)r[r`rr)r�rVr�rWrDr_r�rrr�_cookies_from_attrs_set's
z!CookieJar._cookies_from_attrs_setcCsHt|jdd�}|dkr |jj}|D]}|jdkr$d|_|r$d|_q$dS)Nr�rTr	)r�r<r�r�r�)r�rDZ
rfc2109_as_nsr�rrr�_process_rfc2109_cookies0s

z"CookieJar._process_rfc2109_cookiesc
Cs:|��}|�dg�}|�dg�}tt���|j_|_|jj}|jj}|sN|rf|sV|rf|s^|rf|sj|sjgSz|�t	|�|�}Wnt
k
r�t�g}YnX|�r6|�r6z|�t|�|�}	Wnt
k
r�t�g}	YnX|�
|	�|�r&i}
|D]}d|
|j|j|jf<q�|
fdd�}t||	�}	|	�r6|�|	�|S)NzSet-Cookie2z
Set-CookiecSs|j|j|jf}||kSr�)r�r�rx)Z	ns_cookie�lookupr�rrr�no_matching_rfc2965isz3CookieJar.make_cookies.<locals>.no_matching_rfc2965)rZget_allrArMr<r*r�r�rarz�	Exceptionrr�rbr�r�rx�filterrF)
r��responser�r�Zrfc2965_hdrsZns_hdrsr�r�rDZ
ns_cookiesrcr�rdrrr�make_cookies<s^�������
�



zCookieJar.make_cookiescCsN|j��z2tt���|j_|_|j�||�r:|�|�W5|j��XdSr�)	r?rRrSrArMr<r*r��
set_cookier�rrr�set_cookie_if_okss
zCookieJar.set_cookie_if_okcCsl|j}|j��zJ|j|kr&i||j<||j}|j|krDi||j<||j}|||j<W5|j��XdSr�)r@r?rRrSr�r�rx)r�r��cZc2Zc3rrrri�s






zCookieJar.set_cookiecCsbtd|���|j��z8|�||�D]&}|j�||�r&td|�|�|�q&W5|j��XdS)Nzextract_cookies: %sz setting cookie: %s)	rrr?rRrSrhr<r�ri)r�rgr�r�rrr�extract_cookies�s

zCookieJar.extract_cookiescCst|dk	r2|dks|dkr td��|j|||=n>|dk	rX|dkrJtd��|j||=n|dk	rj|j|=ni|_dS)Nz8domain and path must be given to remove a cookie by namez.domain must be given to remove cookies by path)rLr@)r�r�r�rxrrrr]�s��
zCookieJar.clearcCsD|j��z(|D]}|jr|�|j|j|j�qW5|j��XdSr�)r?rRrSr�r]r�r�rx)r�r�rrr�clear_session_cookies�s
zCookieJar.clear_session_cookiescCsP|j��z4t��}|D]"}|�|�r|�|j|j|j�qW5|j��XdSr�)	r?rRrSrMr�r]r�r�rx)r�r�r�rrrrT�s


zCookieJar.clear_expired_cookiescCs
t|j�Sr�)r6r@rrrr�__iter__�szCookieJar.__iter__cCsd}|D]}|d}q|S)Nr	rr)r�r�r�rrr�__len__�s
zCookieJar.__len__cCs2g}|D]}|�t|��qd|jjd�|�fS�Nz<%s[%s]>r)rrr�r�r�r��r��rr�rrrr��szCookieJar.__repr__cCs2g}|D]}|�t|��qd|jjd�|�fSrp)rrr#r�r�r�rqrrrr��szCookieJar.__str__)N)NNN)!r�r�r�rt�compilerMrNZstrict_domain_reZ	domain_reZdots_re�ASCII�magic_rer�rCrErGrPrQr[r`rarbrhrjrirlr]rmrTrnror�r�rrrrr�s6





;!a\	7


c@seZdZdS)rNr;rrrrr�sc@s4eZdZddd�Zddd�Zd
dd�Zdd	d
�ZdS)rNFcCs2t�||�|dk	rt�|�}||_t|�|_dSr�)rr��os�fspath�filenamer\�	delayload)r�rxryrBrrrr��s

zFileCookieJar.__init__cCs
t��dSr�r�)r�rx�ignore_discard�ignore_expiresrrr�save�szFileCookieJar.savec	CsJ|dkr"|jdk	r|j}ntt��t|��}|�||||�W5QRXdSr�)rxrL�MISSING_FILENAME_TEXT�open�_really_load�r�rxrzr{rrrr�loads

zFileCookieJar.loadcCs�|dkr"|jdk	r|j}ntt��|j��zFt�|j�}i|_z|�	|||�Wnt
k
rn||_�YnXW5|j��XdSr�)rxrLr}r?rRrSr�Zdeepcopyr@r��OSError)r�rxrzr{Z	old_staterrr�revert	s

zFileCookieJar.revert)NFN)NFF)NFF)NFF)r�r�r�r�r|r�r�rrrrr�s


	�cCs |j|jfd|jfd|jfg}|jdk	r8|�d|jf�|jrH|�d�|jrX|�d�|jrh|�d�|j	rx|�d�|j
r�|�dtt|j
��f�|j
r�|�d	�|jr�|�d
|jf�|jr�|�d|jf�t|j���}|D]}|�|t|j|�f�q�|�dt|j�f�t|g�S)
Nr�r�r�)�	path_specN)�	port_specN)�
domain_dotN)r�Nr�)r�Nr�rUr�)rxryr�r�r�rrr�r�r�r�r�r5r[r�r�r�r0r�r1r#r�r�)r�r�r1r�rrr�lwp_cookie_str$s:
�




�
r�c@s(eZdZd
dd�Zddd�Zdd	�ZdS)rTcCsTt��}g}|D]2}|s |jr q|s0|�|�r0q|�dt|��qd�|dg�S)NzSet-Cookie3: %s�
rW)rMr�r�rrr�r�)r�rzr{r�rrr�rrr�
as_lwp_strMs
zLWPCookieJar.as_lwp_strNFc	CsX|dkr"|jdk	r|j}ntt��t|d��"}|�d�|�|�||��W5QRXdS)N�wz#LWP-Cookies-2.0
)rxrLr}r~�writer�r�rrrr|]s

zLWPCookieJar.savecCs0|��}|j�|�s$d|}t|��t��}d}d}	d}
�z�|��}|dkrP�q�|�|�s\q<|t|�d���}t|g�D�]f}|d\}
}i}i}|	D]}d||<q�|dd�D]n\}}|dk	r�|�	�}nd}||
ks�||	kr�|}||	k�r|dkr�d	}|||<q�||
k�r|||<q�|||<q�|j
}|d
�}|d�}|dk	�rJt|�}|dk�rXd	}|d�}|�d
�}t|d�|
||d�|d�|||d�|d�|d�|d�|||d�|d�|�}|�s�|j
�r�qz|�s�|�|��r�qz|�|�qzq<WnBtk
�r�Yn,tk
�r*t�td||f��YnXdS)Nz5%r does not look like a Set-Cookie3 (LWP) format filezSet-Cookie3:)r�r�r�r�r�)r�r�r�r�r�r�rUrWr	FrTr�r�r�r�r�r�r�r�r�r�r�r�rUz&invalid Set-Cookie3 format file %r: %r)�readlinerur@rrMrsrr�rzrKr�rerr�r�rir�rer)r�rrxrzr{�magicrr��headerrXrY�line�datarxryrZr�r�r�r�r�r�r�r�r�rkrrrris��










�
�zLWPCookieJar._really_load)TT)NFF)r�r�r�r�r|rrrrrr@s

c@s,eZdZe�d�ZdZdd�Zd	dd�ZdS)
rz#( Netscape)? HTTP Cookie Filezr# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

cCsbt��}|��}|j�|�s(td|��z�|��}|dkr>�q|�d�rT|dd�}|���d�s*|��dkrpq*|�d�\}}	}
}}}
}|dk}|	dk}	|
dkr�|}
d}|�d�}d	}|dkr�d}d
}t	d|
|dd	||	||
d	|||ddi�}|s�|j
r�q*|�s|�|��rq*|�|�q*WnBt
k
�r2�Yn,tk
�r\t�td||f��YnXdS)
Nz4%r does not look like a Netscape format cookies filerWr�r�)�#r�	�TRUEr�FTr	z+invalid Netscape format cookies file %r: %r)rMr�rur@rr�r�rsr�rr�r�rir�rer)r�rrxrzr{r�r�r�r�r�r�r�r�rxryr�r�rkrrrr�sr��

��
�

�zMozillaCookieJar._really_loadNFc
Cs�|dkr"|jdk	r|j}ntt��t|d���}|�|j�t��}|D]�}|sV|jrVqF|sf|�|�rfqF|j	rrd}nd}|j
�d�r�d}nd}|jdk	r�t
|j�}	nd}	|jdkr�d}
|j}n|j}
|j}|�d�|j
||j||	|
|g�d�qFW5QRXdS)Nr�r�ZFALSEr�rWr�r�)rxrLr}r~r�r�rMr�r�r�r�rsr�r#ryrxr�r�)r�rxrzr{rr�r�r�r�r�rxryrrrr| sH



���zMozillaCookieJar.save)NFF)	r�r�r�rtrsrur�rr|rrrrr�s
A)N)N)W�__all__rvr�r-rtrMZurllib.parser�Zurllib.requestZ	threadingr=Zhttp.clientZhttpZcalendarr
rrrr#ZclientZ	HTTP_PORTr�r}rr%r,r6r7rIr(rrrKr5r8r>rsrtr?rFrTrY�Ir]�Xr_rbrcrerkrmrnrprorzr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrr3r6r:rr�rrr�rrrrrr�<module>s��
�

8�
�
�8
�!



U
D'


#b!b7x__pycache__/client.cpython-38.pyc000064400000104135150532417300012666 0ustar00U

e5d���@sfdZddlZddlZddlZddlZddlZddlZddlZ	ddl
mZdddddd	d
ddd
ddddddddgZdZ
dZdZdZdZdZe��ejj�dd�ejj��D�ZdZdZe�d �jZe�d!�jZe�d"�Z e�d#�Z!d$d%d&hZ"dBd(d)�Z#Gd*d+�d+ej$j%�Z&d,d-�Z'e&fd.d/�Z(Gd0d�dej)�Z*Gd1d�d�Z+zddl,Z,Wne-k
�r`YnXGd2d3�d3e+�Z.e�/d3�Gd4d�de0�Z1Gd5d�de1�Z2Gd6d�de1�Z3Gd7d�de1�Z4Gd8d	�d	e1�Z5Gd9d
�d
e1�Z6Gd:d�de1�Z7Gd;d
�d
e1�Z8Gd<d�de8�Z9Gd=d�de8�Z:Gd>d�de8�Z;Gd?d�de1�Z<Gd@d�de1�Z=GdAd�de>e<�Z?e1Z@dS)Ca�
HTTP/1.1 client library

<intro stuff goes here>
<other stuff, too>

HTTPConnection goes through a number of "states", which define when a client
may legally make another request or fetch the response for a particular
request. This diagram details these state transitions:

    (null)
      |
      | HTTPConnection()
      v
    Idle
      |
      | putrequest()
      v
    Request-started
      |
      | ( putheader() )*  endheaders()
      v
    Request-sent
      |\_____________________________
      |                              | getresponse() raises
      | response = getresponse()     | ConnectionError
      v                              v
    Unread-response                Idle
    [Response-headers-read]
      |\____________________
      |                     |
      | response.read()     | putrequest()
      v                     v
    Idle                  Req-started-unread-response
                     ______/|
                   /        |
   response.read() |        | ( putheader() )*  endheaders()
                   v        v
       Request-started    Req-sent-unread-response
                            |
                            | response.read()
                            v
                          Request-sent

This diagram presents the following rules:
  -- a second request may not be started until {response-headers-read}
  -- a response [object] cannot be retrieved until {request-sent}
  -- there is no differentiation between an unread response body and a
     partially read response body

Note: this enforcement is applied by the HTTPConnection class. The
      HTTPResponse class does not enforce this state machine, which
      implies sophisticated clients may accelerate the request/response
      pipeline. Caution should be taken, though: accelerating the states
      beyond the above pattern may imply knowledge of the server's
      connection-close behavior for certain requests. For example, it
      is impossible to tell whether the server will close the connection
      UNTIL the response headers have been read; this means that further
      requests cannot be placed into the pipeline until it is known that
      the server will NOT be closing the connection.

Logical State                  __state            __response
-------------                  -------            ----------
Idle                           _CS_IDLE           None
Request-started                _CS_REQ_STARTED    None
Request-sent                   _CS_REQ_SENT       None
Unread-response                _CS_IDLE           <response_class>
Req-started-unread-response    _CS_REQ_STARTED    <response_class>
Req-sent-unread-response       _CS_REQ_SENT       <response_class>
�N)�urlsplit�HTTPResponse�HTTPConnection�
HTTPException�NotConnected�UnknownProtocol�UnknownTransferEncoding�UnimplementedFileMode�IncompleteRead�
InvalidURL�ImproperConnectionState�CannotSendRequest�CannotSendHeader�ResponseNotReady�
BadStatusLine�LineTooLong�RemoteDisconnected�error�	responses�Pi�ZUNKNOWNZIdlezRequest-startedzRequest-sentcCsi|]}||j�qS�)�phrase)�.0�vrr�#/usr/lib64/python3.8/http/client.py�
<dictcomp>jsri�ds[^:\s][^:\r\n]*s\n(?![ \t])|\r(?![ \t\n])z[- ]z[-]ZPATCHZPOSTZPUT�datac
Cshz|�d�WStk
rb}z8t|j|j|j|jd|��||j|j�|f�d�W5d}~XYnXdS)z<Call data.encode("latin-1") but show a better error message.�latin-1z`%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') if you want to send it encoded in UTF-8.N)�encode�UnicodeEncodeError�encoding�object�start�end�title)r�name�errrrr�_encode�s���r(c@seZdZdd�ZdS)�HTTPMessagecCsj|��d}t|�}g}d}|��D]@}|d|���|krBd}n|dd���sVd}|r$|�|�q$|S)a�Find all header lines matching a given header name.

        Look through the list of headers and find all lines matching a given
        header name (and their continuation lines).  A list of the lines is
        returned, without interpretation.  If the header does not occur, an
        empty list is returned.  If the header occurs multiple times, all
        occurrences are returned.  Case is not important in the header name.

        �:rN�)�lower�len�keys�isspace�append)�selfr&�nZlstZhit�linerrr�getallmatchingheaders�s
z!HTTPMessage.getallmatchingheadersN)�__name__�
__module__�__qualname__r4rrrrr)�sr)cCsXg}|�td�}t|�tkr&td��|�|�t|�tkrHtdt��|dkrqTq|S)z�Reads potential header lines into a list from a file pointer.

    Length of line is limited by _MAXLINE, and number of
    headers is limited by _MAXHEADERS.
    r+�header linezgot more than %d headers��
�
�)�readline�_MAXLINEr-rr0�_MAXHEADERSr)�fp�headersr3rrr�
_read_headers�s
rBcCs,t|�}d�|��d�}tjj|d��|�S)aGParses only RFC2822 headers from a file pointer.

    email Parser wants to see strings rather than bytes.
    But a TextIOWrapper around self.rfile would buffer too many bytes
    from the stream, bytes which we later need to read as bytes.
    So we read the correct bytes here, as bytes, for email Parser
    to parse.

    r<�
iso-8859-1)�_class)rB�join�decode�email�parserZParserZparsestr)r@rDrAZhstringrrr�
parse_headers�s
rIcseZdZd@dd�Zdd�Zdd�Zd	d
�Zdd�Z�fd
d�Z�fdd�Z	dd�Z
dd�ZdAdd�Zdd�Z
dd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�ZdBd(d)�ZdCd*d+�ZdD�fd,d-�	Zd.d/�Zd0d1�Zd2d3�ZdEd4d5�Zd6d7�Zd8d9�Zd:d;�Zd<d=�Zd>d?�Z �Z!S)FrrNcCsR|�d�|_||_||_d|_|_t|_t|_t|_	t|_
t|_t|_t|_
dS)N�rb)Zmakefiler@�
debuglevel�_methodrA�msg�_UNKNOWN�version�status�reason�chunked�
chunk_left�length�
will_close)r1�sockrK�method�urlrrr�__init__�szHTTPResponse.__init__cCst|j�td�d�}t|�tkr*td��|jdkrBtdt|��|sNt	d��z|�
dd�\}}}WnFtk
r�z|�
dd�\}}d}Wntk
r�d}YnXYnX|�d	�s�|�
�t|��z$t|�}|d
ks�|dkr�t|��Wntk
�rt|��YnX|||fS)Nr+rCzstatus linerzreply:z-Remote end closed connection without response��zHTTP/ri�)�strr@r=r>r-rrK�print�reprr�split�
ValueError�
startswith�_close_connr�int)r1r3rOrPrQrrr�_read_statuss2

zHTTPResponse._read_statusc	Cs�|jdk	rdS|��\}}}|tkr&qHt|j�}|jdkrDtd|�~q||_|_|�	�|_
|dkrnd|_n|�d�r�d|_nt
|��t|j�|_|_|jdkr�|j��D]\}}td|d|�q�|j�d	�}|r�|��d
kr�d|_d|_nd|_|��|_d|_|j�d
�}|�rb|j�sbzt|�|_Wntk
�rLd|_YnX|jdk�rhd|_nd|_|tk�s�|tk�s�d|k�r�dk�s�n|jdk�r�d|_|j�s�|j�s�|jdk�r�d|_dS)Nrzheaders:)zHTTP/1.0zHTTP/0.9�
zHTTP/1.��header:r*�transfer-encodingrRTF�content-lengthr���HEAD)rArdZCONTINUErBr@rKr]�coderP�striprQrOrarrIrM�items�getr,rRrS�_check_closerUrTrcr`Z
NO_CONTENTZNOT_MODIFIEDrL)	r1rOrPrQZskipped_headers�hdr�valZtr_encrTrrr�begin5sf







�
�
���zHTTPResponse.begincCsv|j�d�}|jdkr.|r*d|��kr*dSdS|j�d�r>dS|rRd|��krRdS|j�d�}|rrd|��krrdSdS)NZ
connectionrf�closeTFz
keep-alivezproxy-connection)rArorOr,)r1ZconnZpconnrrrrp}s
zHTTPResponse._check_closecCs|j}d|_|��dS�N)r@rt)r1r@rrrrb�szHTTPResponse._close_conncs$zt���W5|jr|��XdSru)r@rb�superrt�r1��	__class__rrrt�szHTTPResponse.closecst���|jr|j��dSru)rv�flushr@rwrxrrrz�s
zHTTPResponse.flushcCsdS)zAlways returns TrueTrrwrrr�readable�szHTTPResponse.readablecCs
|jdkS)z!True if the connection is closed.N)r@rwrrr�isclosed�szHTTPResponse.isclosedcCs�|jdkrdS|jdkr$|��dS|dk	rRt|�}|�|�}t|�d|���S|jr`|��S|j	dkrv|j�
�}n6z|�|j	�}Wntk
r�|���YnXd|_	|��|SdS)Nr<rkr)
r@rLrb�	bytearray�readinto�
memoryview�tobytesrR�_readall_chunkedrT�read�
_safe_readr
)r1�amt�br2�srrrr��s*



zHTTPResponse.readcCs�|jdkrdS|jdkr$|��dS|jr4|�|�S|jdk	r^t|�|jkr^t|�d|j�}|j�|�}|s||r||��n&|jdk	r�|j|8_|js�|��|S)z^Read up to len(b) bytes into bytearray b and return the number
        of bytes read.
        Nrrk)	r@rLrbrR�_readinto_chunkedrTr-rr~)r1r�r2rrrr~�s$





zHTTPResponse.readintocCsr|j�td�}t|�tkr$td��|�d�}|dkrB|d|�}zt|d�WStk
rl|���YnXdS)Nr+z
chunk size�;r�)	r@r=r>r-r�findrcr`rb)r1r3�irrr�_read_next_chunk_sizes
z"HTTPResponse._read_next_chunk_sizecCs:|j�td�}t|�tkr$td��|s*q6|dkrq6qdS)Nr+ztrailer liner9)r@r=r>r-r�r1r3rrr�_read_and_discard_trailersz&HTTPResponse._read_and_discard_trailercCsl|j}|sh|dk	r|�d�z|��}Wntk
rDtd��YnX|dkrb|��|��d}||_|S)NrZr<r)rSr�r�r`r
r�rb)r1rSrrr�_get_chunk_left s
zHTTPResponse._get_chunk_leftcCsp|jtkst�g}z6|��}|dkr&q>|�|�|��d|_qd�|�WStk
rjtd�|���YnXdS�Nrr<)	rRrN�AssertionErrorr�r0r�rSrEr
)r1�valuerSrrrr�8szHTTPResponse._readall_chunkedcCs�|jtkst�d}t|�}zv|��}|dkr2|WSt|�|kr\|�|�}|||_||WS|d|�}|�|�}||d�}||7}d|_qWn(tk
r�tt	|d|����YnXdS)Nr)
rRrNr�rr�r-�_safe_readintorSr
�bytes)r1r�Ztotal_bytesZmvbrSr2Ztemp_mvbrrrr�Fs$



zHTTPResponse._readinto_chunkedcCs.|j�|�}t|�|kr*t||t|���|S)aRead the number of bytes requested.

        This function should be used when <amt> bytes "should" be present for
        reading. If the bytes are truly not available (due to EOF), then the
        IncompleteRead exception can be used to detect the problem.
        )r@r�r-r
)r1r�rrrrr�^szHTTPResponse._safe_readcCs:t|�}|j�|�}||kr6tt|d|��||��|S)z2Same as _safe_read, but for reading into a buffer.N)r-r@r~r
r�)r1r�r�r2rrrr�js
zHTTPResponse._safe_readinto���cCs�|jdks|jdkrdS|jr(|�|�S|jdk	rJ|dksD||jkrJ|j}|j�|�}|sh|rh|��n|jdk	r�|jt|�8_|S)zvRead with at most one underlying system call.  If at least one
        byte is buffered, return that instead.
        Nrkr<r)r@rLrR�_read1_chunkedrT�read1rbr-)r1r2�resultrrrr�rs


zHTTPResponse.read1cCs4|jdks|jdkrdS|jr(|�|�S|j�|�S)Nrkr<)r@rLrR�
_peek_chunked�peek)r1r2rrrr��s

zHTTPResponse.peekcs�|jdks|jdkrdS|jr*t��|�S|jdk	rL|dksF||jkrL|j}|j�|�}|sj|rj|��n|jdk	r�|jt|�8_|S)Nrkr<r)r@rLrRrvr=rTrbr-)r1�limitr�rxrrr=�s

zHTTPResponse.readlinecCsd|��}|dks|dkrdSd|kr0|ks6n|}|j�|�}|jt|�8_|s`td��|Sr�)r�r@r�rSr-r
)r1r2rSr�rrrr��szHTTPResponse._read1_chunkedcCsDz|��}Wntk
r"YdSX|dkr0dS|j�|�d|�S)Nr<)r�r
r@r�)r1r2rSrrrr��szHTTPResponse._peek_chunkedcCs
|j��Sru)r@�filenorwrrrr��szHTTPResponse.filenocCsF|jdkrt��|j�|�p|}t|t�s4t|d�s8|Sd�|�SdS)axReturns the value of the header matching *name*.

        If there are multiple matching headers, the values are
        combined into a single string separated by commas and spaces.

        If no matching header is found, returns *default* or None if
        the *default* is not specified.

        If the headers are unknown, raises http.client.ResponseNotReady.

        N�__iter__z, )rArZget_all�
isinstancer\�hasattrrE)r1r&�defaultrArrr�	getheader�s
zHTTPResponse.getheadercCs|jdkrt��t|j���S)z&Return list of (header, value) tuples.N)rAr�listrnrwrrr�
getheaders�s
zHTTPResponse.getheaderscCs|Srurrwrrrr��szHTTPResponse.__iter__cCs|jS)ajReturns an instance of the class mimetools.Message containing
        meta-information associated with the URL.

        When the method is HTTP, these headers are those returned by
        the server at the head of the retrieved HTML page (including
        Content-Length and Content-Type).

        When the method is FTP, a Content-Length header will be
        present if (as is now usual) the server passed back a file
        length in response to the FTP retrieval request. A
        Content-Type header will be present if the MIME type can be
        guessed.

        When the method is local-file, returned headers will include
        a Date representing the file's last-modified time, a
        Content-Length giving file size, and a Content-Type
        containing a guess at the file's type. See also the
        description of the mimetools module.

        )rArwrrr�info�szHTTPResponse.infocCs|jS)aZReturn the real URL of the page.

        In some cases, the HTTP server redirects a client to another
        URL. The urlopen() function handles this transparently, but in
        some cases the caller needs to know which URL the client was
        redirected to. The geturl() method can be used to get at this
        redirected URL.

        )rXrwrrr�geturl�s
zHTTPResponse.geturlcCs|jS)zuReturn the HTTP status code that was sent with the response,
        or None if the URL is not an HTTP URL.

        )rPrwrrr�getcode�szHTTPResponse.getcode)rNN)N)r�)r�)r�)N)"r5r6r7rYrdrsrprbrtrzr{r|r�r~r�r�r�r�r�r�r�r�r�r=r�r�r�r�r�r�r�r�r��
__classcell__rrrxrr�s<	
!H

 "

	

c@s
eZdZdZdZeZeZdZ	dZ
edd��Zedd��Z
d	ejd	d
fdd�Zd7d
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd8d d!�Zd9d"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Z d:dd.�d/d0�Z!d	ifdd.�d1d2�Z"d3d4�Z#d5d6�Z$d	S);rrfzHTTP/1.1r+rcCst|tj�S)zFTest whether a file-like object is a text or a binary stream.
        )r��io�
TextIOBase)�streamrrr�
_is_textIOszHTTPConnection._is_textIOcCsf|dkr|��tkrdSdSt|d�r*dSzt|�}|jWStk
rNYnXt|t�rbt|�SdS)aGet the content-length based on the body.

        If the body is None, we set Content-Length: 0 for methods that expect
        a body (RFC 7230, Section 3.3.2). We also set the Content-Length for
        any method if the body is a str or bytes-like object and not a file.
        Nrr�)	�upper�_METHODS_EXPECTING_BODYr�r�nbytes�	TypeErrorr�r\r-)�bodyrWZmvrrr�_get_content_lengths

z"HTTPConnection._get_content_lengthN� cCsn||_||_||_d|_g|_d|_t|_d|_d|_	d|_
i|_|�||�\|_
|_|�|j
�tj|_dSru)�timeout�source_address�	blocksizerV�_buffer�_HTTPConnection__response�_CS_IDLE�_HTTPConnection__staterL�_tunnel_host�_tunnel_port�_tunnel_headers�
_get_hostport�host�port�_validate_host�socketZcreate_connection�_create_connection)r1r�r�r�r�r�rrrrY4szHTTPConnection.__init__cCs<|jrtd��|�||�\|_|_|r.||_n
|j��dS)aDSet up host and port for HTTP CONNECT tunnelling.

        In a connection that uses HTTP CONNECT tunneling, the host passed to the
        constructor is used as a proxy server that relays all communication to
        the endpoint passed to `set_tunnel`. This done by sending an HTTP
        CONNECT request to the proxy server when the connection is established.

        This method must be called before the HTTP connection has been
        established.

        The headers argument should be a mapping of extra HTTP headers to send
        with the CONNECT request.
        z.Can't set up tunnel for established connectionN)rV�RuntimeErrorr�r�r�r��clear)r1r�r�rArrr�
set_tunnelJszHTTPConnection.set_tunnelcCs�|dkr�|�d�}|�d�}||kr�zt||dd��}WnHtk
r�||dd�dkrh|j}ntd||dd���YnX|d|�}n|j}|r�|ddkr�|ddkr�|dd�}||fS)	Nr*�]r+r[znonnumeric port: '%s'r�[r�)�rfindrcr`�default_portr)r1r�r�r��jrrrr�bs

zHTTPConnection._get_hostportcCs
||_dSru)rK)r1�levelrrr�set_debuglevelvszHTTPConnection.set_debuglevelcCs�d|j|jf}|�d�}|�|�|j��D](\}}d||f}|�d�}|�|�q.|�d�|j|j|jd�}|�	�\}}	}
|	t
jjkr�|�
�td|	|
��f��|j�td�}t|�tkr�td	��|s�q�|d
kr�q�|jdkr�td|���q�dS)
NzCONNECT %s:%d HTTP/1.0
�asciiz%s: %s
rr:�rWzTunnel connection failed: %d %sr+r8r9rrg)r�r�r�sendr�rn�response_classrVrLrd�http�
HTTPStatusZOKrt�OSErrorrmr@r=r>r-rrKr]rF)r1Zconnect_strZ
connect_bytes�headerr�Z
header_strZheader_bytes�responserOrl�messager3rrr�_tunnelys4�



�
zHTTPConnection._tunnelcCsB|�|j|jf|j|j�|_|j�tjtj	d�|j
r>|��dS)z3Connect to the host and port specified in __init__.r+N)r�r�r�r�r�rVZ
setsockoptr�ZIPPROTO_TCPZTCP_NODELAYr�r�rwrrr�connect�s
�zHTTPConnection.connectcCsBt|_z|j}|r d|_|��W5|j}|r<d|_|��XdS)z(Close the connection to the HTTP server.N)r�r�r�rtrV)r1r�rVrrrrt�szHTTPConnection.closecCs|jdkr |jr|��nt��|jdkr8tdt|��t|d�r�|jdkrTtd�|�|�}|rt|jdkrttd�|�	|j
�}|s�q�|r�|�d�}|j�|�qtdSz|j�|�WnLt
k
�rt|tjj�r�|D]}|j�|�q�nt
dt|���YnXdS)	z�Send `data' to the server.
        ``data`` can be a string object, a bytes object, an array object, a
        file-like object that supports a .read() method, or an iterable object.
        Nrzsend:r��sendIng a read()able�encoding file using iso-8859-1rCz9data should be a bytes-like object or an iterable, got %r)rV�	auto_openr�rrKr]r^r�r�r�r�rZsendallr�r��collections�abc�Iterable�type)r1rr�	datablock�drrrr��s8






�zHTTPConnection.sendcCs|j�|�dS)zuAdd a line of output to the current request buffer.

        Assumes that the line does *not* end with \r\n.
        N)r�r0)r1r�rrr�_output�szHTTPConnection._outputccs^|jdkrtd�|�|�}|r2|jdkr2td�|�|j�}|sDqZ|rR|�d�}|Vq2dS)Nrr�r�rC)rKr]r�r�r�r)r1r{rr�rrr�_read_readable�s


zHTTPConnection._read_readableFcCs |j�d�d�|j�}|jdd�=|�|�|dk	�rt|d�rN|�|�}nZzt|�WnFtk
r�zt|�}Wn$tk
r�tdt	|���YnXYnX|f}|D]R}|s�|j
dkr�td�q�|r�|jdkr�t
|�d	�d
��d�|d}|�|�q�|�r|jdk�r|�d�dS)
z�Send the currently buffered request and clear the buffer.

        Appends an extra \r\n to the buffer.
        A message_body may be specified, to be appended to the request.
        )r<r<r:Nr�zAmessage_body should be a bytes-like object or an iterable, got %rrzZero length chunk ignoredrf�Xz
r�s0

)r��extendrEr�r�r�rr��iterr�rKr]�	_http_vsnr-r)r1�message_body�encode_chunkedrMZchunks�chunkrrr�_send_output�s:


�
�zHTTPConnection._send_outputcCs�|jr|j��rd|_|jtkr(t|_n
t|j��|�|�||_|pHd}|�|�d|||j	f}|�
|�|��|jdk�r�|�s�d}|�
d�r�t|�\}}}}}|r�z|�d�}Wntk
r�|�d�}YnX|�d	|�n�|jr�|j}	|j}
n|j}	|j}
z|	�d�}Wn tk
�r4|	�d�}YnX|	�d
�dk�rRd|d
}|
|jk�rl|�d	|�n|�d�}|�d	d||
f�|�s�|�dd�ndS)a`Send a request to the server.

        `method' specifies an HTTP request method, e.g. 'GET'.
        `url' specifies the object being requested, e.g. '/index.html'.
        `skip_host' if True does not add automatically a 'Host:' header
        `skip_accept_encoding' if True does not add automatically an
           'Accept-Encoding:' header
        N�/z%s %s %srfr[r�r�ZidnaZHostr*r�[�]z%s:%szAccept-EncodingZidentity)r�r|r�r��_CS_REQ_STARTEDr
�_validate_methodrL�_validate_path�
_http_vsn_strr��_encode_requestr�rarrr �	putheaderr�r�r�r�r�r�rF)r1rWrX�	skip_host�skip_accept_encoding�requestZnetlocZnilZ
netloc_encr�r�Zhost_encrrr�
putrequest sP






zHTTPConnection.putrequestcCs
|�d�S)Nr�)r)r1r�rrrr��szHTTPConnection._encode_requestcCs,t�|�}|r(td|�d|���d���dS)z&Validate a method name for putrequest.z)method can't contain control characters. � (found at least �)N)�$_contains_disallowed_method_pchar_re�searchr`�group)r1rW�matchrrrr��s

�zHTTPConnection._validate_methodcCs,t�|�}|r(td|�d|���d���dS)zValidate a url for putrequest.�&URL can't contain control characters. r�r�N��!_contains_disallowed_url_pchar_rer�rr�)r1rXr�rrrr��s
zHTTPConnection._validate_pathcCs,t�|�}|r(td|�d|���d���dS)z9Validate a host so it doesn't contain control characters.r�r�r�Nr)r1r�r�rrrr��s
zHTTPConnection._validate_hostcGs�|jtkrt��t|d�r$|�d�}t|�s:td|f��t|�}t|�D]\\}}t|d�rl|�d�||<nt	|t
�r�t|��d�||<t||�rJtd||f��qJd�
|�}|d|}|�|�dS)	zkSend a request header line to the server.

        For example: h.putheader('Accept', 'text/html')
        rr�zInvalid header name %rrzInvalid header value %rs
	s: N)r�r�rr�r�_is_legal_header_namer`r��	enumerater�rcr\�_is_illegal_header_valuerEr�)r1r��valuesr�Z	one_valuer�rrrr��s"





zHTTPConnection.putheader�r�cCs*|jtkrt|_nt��|j||d�dS)z�Indicate that the last header line has been sent to the server.

        This method sends the request to the server.  The optional message_body
        argument can be used to pass a message body associated with the
        request.
        rN)r�r��_CS_REQ_SENTrr�)r1r�r�rrr�
endheaders�s
zHTTPConnection.endheaderscCs|�|||||�dS)z&Send a complete request to the server.N)�
_send_request)r1rWrXr�rAr�rrrr��szHTTPConnection.requestcCs�tdd�|D��}i}d|kr&d|d<d|kr6d|d<|j||f|�d|kr�d	|kr�d
}|�||�}|dkr�|dk	r�|jdkr�td|�d
}|�dd�q�|�dt|��nd
}|��D]\}	}
|�|	|
�q�t|t�r�t	|d�}|j
||d�dS)Ncss|]}|��VqdSru)r,)r�krrr�	<genexpr>�sz/HTTPConnection._send_request.<locals>.<genexpr>r�r+r�zaccept-encodingr�rirhFrzUnable to determine size of %rTzTransfer-EncodingrRzContent-Lengthr�r)�	frozensetr�r�rKr]r�r\rnr�r(r)r1rWrXr�rAr�Zheader_namesZskipsZcontent_lengthrqr�rrrr	�s0	


zHTTPConnection._send_requestcCs�|jr|j��rd|_|jtks&|jr0t|j��|jdkrR|j|j|j|jd�}n|j|j|jd�}z\z|�	�Wnt
k
r�|���YnX|jt
ks�t�t|_|jr�|��n||_|WS|���YnXdS)a)Get the response from the server.

        If the HTTPConnection is in the correct state, returns an
        instance of HTTPResponse or of whatever object is returned by
        the response_class variable.

        If a request has not been sent or if a previous response has
        not be handled, ResponseNotReady is raised.  If the HTTP
        response indicates that the connection should be closed, then
        it will be closed before the response is returned.  When the
        connection is closed, the underlying socket is closed.
        Nrr�)r�r|r�rrrKr�rVrLrs�ConnectionErrorrtrUrNr�r�)r1r�rrr�getresponses0

�
zHTTPConnection.getresponse)NN)NF)FF)N)%r5r6r7r�r�rr��	HTTP_PORTr�r�rK�staticmethodr�r�r��_GLOBAL_DEFAULT_TIMEOUTrYr�r�r�r�r�rtr�r�r�r�r�r�r�r�r�r�rr�r	rrrrrrsL

�

	&
6�
	
�.csHeZdZdZeZdddejdfdddd��fdd�Z�fdd�Z	�Z
S)	�HTTPSConnectionz(This class allows communication via SSL.Nr�)�context�check_hostnamer�cs�tt|�j|||||	d�|dk	s2|dk	s2|dk	rHddl}
|
�dtd�||_||_|dkrtt�	�}|j
dk	rtd|_
|jtjk}|dkr�|j
}|r�|s�td��|s�|r�|�||�|j
dk	r�d|_
||_|dk	r�||j_
dS)N)r�rzTkey_file, cert_file and check_hostname are deprecated, use a custom context instead.rZTzMcheck_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED)rvrrY�warnings�warn�DeprecationWarning�key_file�	cert_file�sslZ_create_default_https_contextZpost_handshake_authZverify_modeZ	CERT_NONErr`Zload_cert_chain�_context)r1r�r�rrr�r�rrr�rZwill_verifyrxrrrYcs<���

zHTTPSConnection.__init__cs6t���|jr|j}n|j}|jj|j|d�|_dS)z(Connect to a host on a given (SSL) port.)�server_hostnameN)rvr�r�r�rZwrap_socketrV)r1rrxrrr��s

�zHTTPSConnection.connect)r5r6r7�__doc__�
HTTPS_PORTr�r�rrYr�r�rrrxrr\s��$rc@seZdZdS)rN�r5r6r7rrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdd�ZdS)rcCs|f|_||_dSru)�argsrO)r1rOrrrrY�szUnknownProtocol.__init__N�r5r6r7rYrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)r	Nrrrrrr	�sc@s$eZdZddd�Zdd�ZejZdS)r
NcCs|f|_||_||_dSru)r �partial�expected)r1r"r#rrrrY�szIncompleteRead.__init__cCs2|jdk	rd|j}nd}d|jjt|j�|fS)Nz, %i more expectedr[z%s(%i bytes read%s))r#ryr5r-r")r1�errr�__repr__�s
�zIncompleteRead.__repr__)N)r5r6r7rYr%r"�__str__rrrrr
�s
c@seZdZdS)rNrrrrrr�sc@seZdZdS)r
Nrrrrrr
�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdd�ZdS)rcCs|st|�}|f|_||_dSru)r^r r3r�rrrrY�szBadStatusLine.__init__Nr!rrrrr�sc@seZdZdd�ZdS)rcCst�|dt|f�dS)Nz&got more than %d bytes when reading %s)rrYr>)r1Z	line_typerrrrY�s�zLineTooLong.__init__Nr!rrrrr�sc@seZdZdd�ZdS)rcOs"t�|d�tj|f|�|�dS)Nr[)rrY�ConnectionResetError)r1�pos�kwrrrrY�szRemoteDisconnected.__init__Nr!rrrrr�s)r)ArZemail.parserrGZ
email.messager�r��rer�Zcollections.abcr�Zurllib.parser�__all__rrrNr�r�r�globals�updater��__members__rrr>r?�compile�	fullmatchrr�rrr�r�r(r�ZMessager)rBrI�BufferedIOBaserrr�ImportErrorrr0�	Exceptionrrrrrr	r
rr
rrrrr'rrrrrr�<module>s�F�



W8
__pycache__/client.cpython-38.opt-2.pyc000064400000062033150532417300013626 0ustar00U

e5d���@sbddlZddlZddlZddlZddlZddlZddlZddl	m
Z
ddddddd	d
ddd
dddddddgZdZdZ
dZdZdZdZe��ejj�dd�ejj��D�ZdZdZe�d�jZe�d �jZe�d!�Ze�d"�Z d#d$d%hZ!dAd'd(�Z"Gd)d*�d*ej#j$�Z%d+d,�Z&e%fd-d.�Z'Gd/d�dej(�Z)Gd0d�d�Z*zddl+Z+Wne,k
�r\YnXGd1d2�d2e*�Z-e�.d2�Gd3d�de/�Z0Gd4d�de0�Z1Gd5d�de0�Z2Gd6d�de0�Z3Gd7d�de0�Z4Gd8d	�d	e0�Z5Gd9d
�d
e0�Z6Gd:d�de0�Z7Gd;d
�d
e7�Z8Gd<d�de7�Z9Gd=d�de7�Z:Gd>d�de0�Z;Gd?d�de0�Z<Gd@d�de=e;�Z>e0Z?dS)B�N)�urlsplit�HTTPResponse�HTTPConnection�
HTTPException�NotConnected�UnknownProtocol�UnknownTransferEncoding�UnimplementedFileMode�IncompleteRead�
InvalidURL�ImproperConnectionState�CannotSendRequest�CannotSendHeader�ResponseNotReady�
BadStatusLine�LineTooLong�RemoteDisconnected�error�	responses�Pi�ZUNKNOWNZIdlezRequest-startedzRequest-sentcCsi|]}||j�qS�)�phrase)�.0�vrr�#/usr/lib64/python3.8/http/client.py�
<dictcomp>jsri�ds[^:\s][^:\r\n]*s\n(?![ \t])|\r(?![ \t\n])z[- ]z[-]ZPATCHZPOSTZPUT�datac
Cshz|�d�WStk
rb}z8t|j|j|j|jd|��||j|j�|f�d�W5d}~XYnXdS)N�latin-1z`%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') if you want to send it encoded in UTF-8.)�encode�UnicodeEncodeError�encoding�object�start�end�title)r�name�errrrr�_encode�s���r(c@seZdZdd�ZdS)�HTTPMessagecCsj|��d}t|�}g}d}|��D]@}|d|���|krBd}n|dd���sVd}|r$|�|�q$|S)N�:r�)�lower�len�keys�isspace�append)�selfr&�nZlstZhit�linerrr�getallmatchingheaders�s
z!HTTPMessage.getallmatchingheadersN)�__name__�
__module__�__qualname__r4rrrrr)�sr)cCsXg}|�td�}t|�tkr&td��|�|�t|�tkrHtdt��|dkrqTq|S)Nr+�header linezgot more than %d headers��
�
�)�readline�_MAXLINEr-rr0�_MAXHEADERSr)�fp�headersr3rrr�
_read_headers�s
rBcCs,t|�}d�|��d�}tjj|d��|�S)Nr<�
iso-8859-1)�_class)rB�join�decode�email�parserZParserZparsestr)r@rDrAZhstringrrr�
parse_headers�s
rIcseZdZd@dd�Zdd�Zdd�Zd	d
�Zdd�Z�fd
d�Z�fdd�Z	dd�Z
dd�ZdAdd�Zdd�Z
dd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�ZdBd(d)�ZdCd*d+�ZdD�fd,d-�	Zd.d/�Zd0d1�Zd2d3�ZdEd4d5�Zd6d7�Zd8d9�Zd:d;�Zd<d=�Zd>d?�Z �Z!S)FrrNcCsR|�d�|_||_||_d|_|_t|_t|_t|_	t|_
t|_t|_t|_
dS)N�rb)Zmakefiler@�
debuglevel�_methodrA�msg�_UNKNOWN�version�status�reason�chunked�
chunk_left�length�
will_close)r1�sockrK�method�urlrrr�__init__�szHTTPResponse.__init__cCst|j�td�d�}t|�tkr*td��|jdkrBtdt|��|sNt	d��z|�
dd�\}}}WnFtk
r�z|�
dd�\}}d}Wntk
r�d}YnXYnX|�d	�s�|�
�t|��z$t|�}|d
ks�|dkr�t|��Wntk
�rt|��YnX|||fS)Nr+rCzstatus linerzreply:z-Remote end closed connection without response��zHTTP/ri�)�strr@r=r>r-rrK�print�reprr�split�
ValueError�
startswith�_close_connr�int)r1r3rOrPrQrrr�_read_statuss2

zHTTPResponse._read_statusc	Cs�|jdk	rdS|��\}}}|tkr&qHt|j�}|jdkrDtd|�~q||_|_|�	�|_
|dkrnd|_n|�d�r�d|_nt
|��t|j�|_|_|jdkr�|j��D]\}}td|d|�q�|j�d	�}|r�|��d
kr�d|_d|_nd|_|��|_d|_|j�d
�}|�rb|j�sbzt|�|_Wntk
�rLd|_YnX|jdk�rhd|_nd|_|tk�s�|tk�s�d|k�r�dk�s�n|jdk�r�d|_|j�s�|j�s�|jdk�r�d|_dS)Nrzheaders:)zHTTP/1.0zHTTP/0.9�
zHTTP/1.��header:r*�transfer-encodingrRTF�content-lengthr���HEAD)rArdZCONTINUErBr@rKr]�coderP�striprQrOrarrIrM�items�getr,rRrS�_check_closerUrTrcr`Z
NO_CONTENTZNOT_MODIFIEDrL)	r1rOrPrQZskipped_headers�hdr�valZtr_encrTrrr�begin5sf







�
�
���zHTTPResponse.begincCsv|j�d�}|jdkr.|r*d|��kr*dSdS|j�d�r>dS|rRd|��krRdS|j�d�}|rrd|��krrdSdS)NZ
connectionrf�closeTFz
keep-alivezproxy-connection)rArorOr,)r1ZconnZpconnrrrrp}s
zHTTPResponse._check_closecCs|j}d|_|��dS�N)r@rt)r1r@rrrrb�szHTTPResponse._close_conncs$zt���W5|jr|��XdSru)r@rb�superrt�r1��	__class__rrrt�szHTTPResponse.closecst���|jr|j��dSru)rv�flushr@rwrxrrrz�s
zHTTPResponse.flushcCsdS)NTrrwrrr�readable�szHTTPResponse.readablecCs
|jdkSru)r@rwrrr�isclosed�szHTTPResponse.isclosedcCs�|jdkrdS|jdkr$|��dS|dk	rRt|�}|�|�}t|�d|���S|jr`|��S|j	dkrv|j�
�}n6z|�|j	�}Wntk
r�|���YnXd|_	|��|SdS)Nr<rkr)
r@rLrb�	bytearray�readinto�
memoryview�tobytesrR�_readall_chunkedrT�read�
_safe_readr
)r1�amt�br2�srrrr��s*



zHTTPResponse.readcCs�|jdkrdS|jdkr$|��dS|jr4|�|�S|jdk	r^t|�|jkr^t|�d|j�}|j�|�}|s||r||��n&|jdk	r�|j|8_|js�|��|S)Nrrk)	r@rLrbrR�_readinto_chunkedrTr-rr~)r1r�r2rrrr~�s$





zHTTPResponse.readintocCsr|j�td�}t|�tkr$td��|�d�}|dkrB|d|�}zt|d�WStk
rl|���YnXdS)Nr+z
chunk size�;r�)	r@r=r>r-r�findrcr`rb)r1r3�irrr�_read_next_chunk_sizes
z"HTTPResponse._read_next_chunk_sizecCs:|j�td�}t|�tkr$td��|s*q6|dkrq6qdS)Nr+ztrailer liner9)r@r=r>r-r�r1r3rrr�_read_and_discard_trailersz&HTTPResponse._read_and_discard_trailercCsl|j}|sh|dk	r|�d�z|��}Wntk
rDtd��YnX|dkrb|��|��d}||_|S)NrZr<r)rSr�r�r`r
r�rb)r1rSrrr�_get_chunk_left s
zHTTPResponse._get_chunk_leftcCsbg}z6|��}|dkrq0|�|�|��d|_qd�|�WStk
r\td�|���YnXdS�Nrr<)r�r0r�rSrEr
)r1�valuerSrrrr�8szHTTPResponse._readall_chunkedcCs�d}t|�}zv|��}|dkr$|WSt|�|krN|�|�}|||_||WS|d|�}|�|�}||d�}||7}d|_qWn(tk
r�tt|d|����YnXdS)Nr)rr�r-�_safe_readintorSr
�bytes)r1r�Ztotal_bytesZmvbrSr2Ztemp_mvbrrrr�Fs"



zHTTPResponse._readinto_chunkedcCs.|j�|�}t|�|kr*t||t|���|Sru)r@r�r-r
)r1r�rrrrr�^szHTTPResponse._safe_readcCs:t|�}|j�|�}||kr6tt|d|��||��|Sru)r-r@r~r
r�)r1r�r�r2rrrr�js
zHTTPResponse._safe_readinto���cCs�|jdks|jdkrdS|jr(|�|�S|jdk	rJ|dksD||jkrJ|j}|j�|�}|sh|rh|��n|jdk	r�|jt|�8_|S�Nrkr<r)r@rLrR�_read1_chunkedrT�read1rbr-)r1r2�resultrrrr�rs


zHTTPResponse.read1cCs4|jdks|jdkrdS|jr(|�|�S|j�|�S)Nrkr<)r@rLrR�
_peek_chunked�peek)r1r2rrrr��s

zHTTPResponse.peekcs�|jdks|jdkrdS|jr*t��|�S|jdk	rL|dksF||jkrL|j}|j�|�}|sj|rj|��n|jdk	r�|jt|�8_|Sr�)r@rLrRrvr=rTrbr-)r1�limitr�rxrrr=�s

zHTTPResponse.readlinecCsd|��}|dks|dkrdSd|kr0|ks6n|}|j�|�}|jt|�8_|s`td��|Sr�)r�r@r�rSr-r
)r1r2rSr�rrrr��szHTTPResponse._read1_chunkedcCsDz|��}Wntk
r"YdSX|dkr0dS|j�|�d|�S)Nr<)r�r
r@r�)r1r2rSrrrr��szHTTPResponse._peek_chunkedcCs
|j��Sru)r@�filenorwrrrr��szHTTPResponse.filenocCsF|jdkrt��|j�|�p|}t|t�s4t|d�s8|Sd�|�SdS)N�__iter__z, )rArZget_all�
isinstancer\�hasattrrE)r1r&�defaultrArrr�	getheader�s
zHTTPResponse.getheadercCs|jdkrt��t|j���Sru)rAr�listrnrwrrr�
getheaders�s
zHTTPResponse.getheaderscCs|Srurrwrrrr��szHTTPResponse.__iter__cCs|jSru)rArwrrr�info�szHTTPResponse.infocCs|jSru)rXrwrrr�geturl�s
zHTTPResponse.geturlcCs|jSru)rPrwrrr�getcode�szHTTPResponse.getcode)rNN)N)r�)r�)r�)N)"r5r6r7rYrdrsrprbrtrzr{r|r�r~r�r�r�r�r�r�r�r�r�r=r�r�r�r�r�r�r�r�r��
__classcell__rrrxrr�s<	
!H

 "

	

c@s
eZdZdZdZeZeZdZ	dZ
edd��Zedd��Z
d	ejd	d
fdd�Zd7d
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd8d d!�Zd9d"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Z d:dd.�d/d0�Z!d	ifdd.�d1d2�Z"d3d4�Z#d5d6�Z$d	S);rrfzHTTP/1.1r+rcCst|tj�Sru)r��io�
TextIOBase)�streamrrr�
_is_textIOszHTTPConnection._is_textIOcCsf|dkr|��tkrdSdSt|d�r*dSzt|�}|jWStk
rNYnXt|t�rbt|�SdS)Nrr�)	�upper�_METHODS_EXPECTING_BODYr�r�nbytes�	TypeErrorr�r\r-)�bodyrWZmvrrr�_get_content_lengths

z"HTTPConnection._get_content_lengthN� cCsn||_||_||_d|_g|_d|_t|_d|_d|_	d|_
i|_|�||�\|_
|_|�|j
�tj|_dSru)�timeout�source_address�	blocksizerV�_buffer�_HTTPConnection__response�_CS_IDLE�_HTTPConnection__staterL�_tunnel_host�_tunnel_port�_tunnel_headers�
_get_hostport�host�port�_validate_host�socketZcreate_connection�_create_connection)r1r�r�r�r�r�rrrrY4szHTTPConnection.__init__cCs<|jrtd��|�||�\|_|_|r.||_n
|j��dS)Nz.Can't set up tunnel for established connection)rV�RuntimeErrorr�r�r�r��clear)r1r�r�rArrr�
set_tunnelJszHTTPConnection.set_tunnelcCs�|dkr�|�d�}|�d�}||kr�zt||dd��}WnHtk
r�||dd�dkrh|j}ntd||dd���YnX|d|�}n|j}|r�|ddkr�|ddkr�|dd�}||fS)	Nr*�]r+r[znonnumeric port: '%s'r�[r�)�rfindrcr`�default_portr)r1r�r�r��jrrrr�bs

zHTTPConnection._get_hostportcCs
||_dSru)rK)r1�levelrrr�set_debuglevelvszHTTPConnection.set_debuglevelcCs�d|j|jf}|�d�}|�|�|j��D](\}}d||f}|�d�}|�|�q.|�d�|j|j|jd�}|�	�\}}	}
|	t
jjkr�|�
�td|	|
��f��|j�td�}t|�tkr�td	��|s�q�|d
kr�q�|jdkr�td|���q�dS)
NzCONNECT %s:%d HTTP/1.0
�asciiz%s: %s
rr:�rWzTunnel connection failed: %d %sr+r8r9rrg)r�r�r�sendr�rn�response_classrVrLrd�http�
HTTPStatusZOKrt�OSErrorrmr@r=r>r-rrKr]rF)r1Zconnect_strZ
connect_bytes�headerr�Z
header_strZheader_bytes�responserOrl�messager3rrr�_tunnelys4�



�
zHTTPConnection._tunnelcCsB|�|j|jf|j|j�|_|j�tjtj	d�|j
r>|��dS)Nr+)r�r�r�r�r�rVZ
setsockoptr�ZIPPROTO_TCPZTCP_NODELAYr�r�rwrrr�connect�s
�zHTTPConnection.connectcCsBt|_z|j}|r d|_|��W5|j}|r<d|_|��XdSru)r�r�r�rtrV)r1r�rVrrrrt�szHTTPConnection.closecCs|jdkr |jr|��nt��|jdkr8tdt|��t|d�r�|jdkrTtd�|�|�}|rt|jdkrttd�|�	|j
�}|s�q�|r�|�d�}|j�|�qtdSz|j�|�WnLt
k
�rt|tjj�r�|D]}|j�|�q�nt
dt|���YnXdS)Nrzsend:r��sendIng a read()able�encoding file using iso-8859-1rCz9data should be a bytes-like object or an iterable, got %r)rV�	auto_openr�rrKr]r^r�r�r�r�rZsendallr�r��collections�abc�Iterable�type)r1rr�	datablock�drrrr��s8






�zHTTPConnection.sendcCs|j�|�dSru)r�r0)r1r�rrr�_output�szHTTPConnection._outputccs^|jdkrtd�|�|�}|r2|jdkr2td�|�|j�}|sDqZ|rR|�d�}|Vq2dS)Nrr�r�rC)rKr]r�r�r�r)r1r{rr�rrr�_read_readable�s


zHTTPConnection._read_readableFcCs |j�d�d�|j�}|jdd�=|�|�|dk	�rt|d�rN|�|�}nZzt|�WnFtk
r�zt|�}Wn$tk
r�tdt	|���YnXYnX|f}|D]R}|s�|j
dkr�td�q�|r�|jdkr�t
|�d�d	��d
�|d}|�|�q�|�r|jdk�r|�d�dS)N)r<r<r:r�zAmessage_body should be a bytes-like object or an iterable, got %rrzZero length chunk ignoredrf�Xz
r�s0

)r��extendrEr�r�r�rr��iterr�rKr]�	_http_vsnr-r)r1�message_body�encode_chunkedrMZchunks�chunkrrr�_send_output�s:


�
�zHTTPConnection._send_outputcCs�|jr|j��rd|_|jtkr(t|_n
t|j��|�|�||_|pHd}|�|�d|||j	f}|�
|�|��|jdk�r�|�s�d}|�
d�r�t|�\}}}}}|r�z|�d�}Wntk
r�|�d�}YnX|�d|�n�|jr�|j}	|j}
n|j}	|j}
z|	�d�}Wn tk
�r4|	�d�}YnX|	�d	�d
k�rRd|d}|
|jk�rl|�d|�n|�d�}|�dd
||
f�|�s�|�dd�ndS)N�/z%s %s %srfr[r�r�ZidnaZHostr*r�[�]z%s:%szAccept-EncodingZidentity)r�r|r�r��_CS_REQ_STARTEDr
�_validate_methodrL�_validate_path�
_http_vsn_strr��_encode_requestr�rarrr �	putheaderr�r�r�r�r�r�rF)r1rWrX�	skip_host�skip_accept_encoding�requestZnetlocZnilZ
netloc_encr�r�Zhost_encrrr�
putrequest sP






zHTTPConnection.putrequestcCs
|�d�S)Nr�)r)r1r�rrrr��szHTTPConnection._encode_requestcCs,t�|�}|r(td|�d|���d���dS)Nz)method can't contain control characters. � (found at least �))�$_contains_disallowed_method_pchar_re�searchr`�group)r1rW�matchrrrr��s

�zHTTPConnection._validate_methodcCs,t�|�}|r(td|�d|���d���dS�Nz&URL can't contain control characters. r�r���!_contains_disallowed_url_pchar_rer�rr�)r1rXr�rrrr��s
zHTTPConnection._validate_pathcCs,t�|�}|r(td|�d|���d���dSr�r)r1r�r�rrrr��s
zHTTPConnection._validate_hostcGs�|jtkrt��t|d�r$|�d�}t|�s:td|f��t|�}t|�D]\\}}t|d�rl|�d�||<nt	|t
�r�t|��d�||<t||�rJtd||f��qJd�
|�}|d|}|�|�dS)Nrr�zInvalid header name %rrzInvalid header value %rs
	s: )r�r�rr�r�_is_legal_header_namer`r��	enumerater�rcr\�_is_illegal_header_valuerEr�)r1r��valuesr�Z	one_valuer�rrrr��s"





zHTTPConnection.putheader�r�cCs*|jtkrt|_nt��|j||d�dS)Nr)r�r��_CS_REQ_SENTrr�)r1r�r�rrr�
endheaders�s
zHTTPConnection.endheaderscCs|�|||||�dSru)�
_send_request)r1rWrXr�rAr�rrrr��szHTTPConnection.requestcCs�tdd�|D��}i}d|kr&d|d<d|kr6d|d<|j||f|�d|kr�d	|kr�d
}|�||�}|dkr�|dk	r�|jdkr�td|�d
}|�dd�q�|�dt|��nd
}|��D]\}	}
|�|	|
�q�t|t�r�t	|d�}|j
||d�dS)Ncss|]}|��VqdSru)r,)r�krrr�	<genexpr>�sz/HTTPConnection._send_request.<locals>.<genexpr>r�r+r�zaccept-encodingr�rirhFrzUnable to determine size of %rTzTransfer-EncodingrRzContent-Lengthr�r)�	frozensetr�r�rKr]r�r\rnr�r(r)r1rWrXr�rAr�Zheader_namesZskipsZcontent_lengthrqr�rrrr	�s0	


zHTTPConnection._send_requestcCs�|jr|j��rd|_|jtks&|jr0t|j��|jdkrR|j|j|j|jd�}n|j|j|jd�}zNz|�	�Wnt
k
r�|���YnXt|_|j
r�|��n||_|WS|���YnXdS)Nrr�)r�r|r�rrrKr�rVrLrs�ConnectionErrorrtr�rU)r1r�rrr�getresponses.

�
zHTTPConnection.getresponse)NN)NF)FF)N)%r5r6r7r�r�rr��	HTTP_PORTr�r�rK�staticmethodr�r�r��_GLOBAL_DEFAULT_TIMEOUTrYr�r�r�r�r�rtr�r�r�r�r�r�r�r�r�r�rr�r	rrrrrrsL

�

	&
6�
	
�.csDeZdZeZdddejdfdddd��fdd�Z�fdd�Z�Z	S)�HTTPSConnectionNr�)�context�check_hostnamer�cs�tt|�j|||||	d�|dk	s2|dk	s2|dk	rHddl}
|
�dtd�||_||_|dkrtt�	�}|j
dk	rtd|_
|jtjk}|dkr�|j
}|r�|s�td��|s�|r�|�||�|j
dk	r�d|_
||_|dk	r�||j_
dS)N)r�rzTkey_file, cert_file and check_hostname are deprecated, use a custom context instead.rZTzMcheck_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED)rvrrY�warnings�warn�DeprecationWarning�key_file�	cert_file�sslZ_create_default_https_contextZpost_handshake_authZverify_modeZ	CERT_NONErr`Zload_cert_chain�_context)r1r�r�rrr�r�rrr�rZwill_verifyrxrrrYcs<���

zHTTPSConnection.__init__cs6t���|jr|j}n|j}|jj|j|d�|_dS)N)�server_hostname)rvr�r�r�rZwrap_socketrV)r1rrxrrr��s

�zHTTPSConnection.connect)
r5r6r7�
HTTPS_PORTr�r�rrYr�r�rrrxrr\s��$rc@seZdZdS)rN�r5r6r7rrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdd�ZdS)rcCs|f|_||_dSru)�argsrO)r1rOrrrrY�szUnknownProtocol.__init__N�r5r6r7rYrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)r	Nrrrrrr	�sc@s$eZdZddd�Zdd�ZejZdS)r
NcCs|f|_||_||_dSru)r�partial�expected)r1r!r"rrrrY�szIncompleteRead.__init__cCs2|jdk	rd|j}nd}d|jjt|j�|fS)Nz, %i more expectedr[z%s(%i bytes read%s))r"ryr5r-r!)r1�errr�__repr__�s
�zIncompleteRead.__repr__)N)r5r6r7rYr$r"�__str__rrrrr
�s
c@seZdZdS)rNrrrrrr�sc@seZdZdS)r
Nrrrrrr
�sc@seZdZdS)rNrrrrrr�sc@seZdZdS)rNrrrrrr�sc@seZdZdd�ZdS)rcCs|st|�}|f|_||_dSru)r^rr3r�rrrrY�szBadStatusLine.__init__Nr rrrrr�sc@seZdZdd�ZdS)rcCst�|dt|f�dS)Nz&got more than %d bytes when reading %s)rrYr>)r1Z	line_typerrrrY�s�zLineTooLong.__init__Nr rrrrr�sc@seZdZdd�ZdS)rcOs"t�|d�tj|f|�|�dS)Nr[)rrY�ConnectionResetError)r1�pos�kwrrrrY�szRemoteDisconnected.__init__Nr rrrrr�s)r)@Zemail.parserrGZ
email.messager�r��rer�Zcollections.abcr�Zurllib.parser�__all__rrrNr�r�r�globals�updater��__members__rrr>r?�compile�	fullmatchrr�rrr�r�r(r�ZMessager)rBrI�BufferedIOBaserrr�ImportErrorrr0�	Exceptionrrrrrr	r
rr
rrrrr&rrrrrr�<module>Gs��



W8
__pycache__/server.cpython-38.opt-2.pyc000064400000054462150532417300013665 0ustar00U

e5d��@sdZdddddgZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlZddlZddlZddlZddlZddlmZdd	lmZd
ZdZGdd�dej�ZGd
d�deje�ZGdd�dej �Z!Gdd�de!�Z"dd�Z#da$dd�Z%dd�Z&Gdd�de"�Z'dd�Z(e!edddfdd�Z)e*dk�rddl+Z+e+�,�Z-e-j.ddd d!�e-j.d"d#d$d%d&�e-j.d'd(e�/�d)d*�e-j.d+d,de0d-d.d/�e-�1�Z2e2j3�r�e'Z4nee"e2j5d0�Z4Gd1d2�d2e�Z6e)e4e6e2j7e2j8d3�dS)4z0.6�
HTTPServer�ThreadingHTTPServer�BaseHTTPRequestHandler�SimpleHTTPRequestHandler�CGIHTTPRequestHandler�N)�partial)�
HTTPStatusa�<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: %(code)d</p>
        <p>Message: %(message)s.</p>
        <p>Error code explanation: %(code)s - %(explain)s.</p>
    </body>
</html>
ztext/html;charset=utf-8c@seZdZdZdd�ZdS)r�cCs4tj�|�|jdd�\}}t�|�|_||_dS)N�)�socketserver�	TCPServer�server_bindZserver_address�socketZgetfqdn�server_name�server_port)�self�host�port�r�#/usr/lib64/python3.8/http/server.pyr
�szHTTPServer.server_bindN)�__name__�
__module__�__qualname__Zallow_reuse_addressr
rrrrr�sc@seZdZdZdS)rTN)rrrZdaemon_threadsrrrrr�sc
@sFeZdZdej��dZdeZe	Z
eZdZ
dd�Zdd�Zd	d
�Zdd�ZdEdd�ZdFdd�ZdGdd�Zdd�Zdd�Zdd�ZdHdd�Zdd�Ze�dd �e�ed!�ed"d#��D��Zd$ee d%�<d&d'�Z!d(d)�Z"dId*d+�Z#d,d-�Z$d.d/d0d1d2d3d4gZ%d
d5d6d7d8d9d:d;d<d=d>d?d@g
Z&dAdB�Z'dCZ(e)j*j+Z,dDd �e-j.�/�D�Z0d
S)JrzPython/rz	BaseHTTP/�HTTP/0.9c
Cs�d|_|j|_}d|_t|jd�}|�d�}||_|��}t	|�dkrLdSt	|�dk�r&|d}zT|�
d�srt�|�d	d
�d
}|�d�}t	|�dkr�t�t|d�t|d
�f}Wn,tt
fk
r�|�tjd
|�YdSX|dk�r|jdk�rd|_|dk�r |�tjd|�dS||_dt	|�k�rBdk�sZn|�tjd|�dS|dd�\}}t	|�dk�r�d|_|dk�r�|�tjd|�dS|||_|_|j�
d��r�d	|j�d	�|_ztjj|j|jd�|_Wn�tjjk
�r(}z|�tjdt|��WY�dSd}~XYnBtjjk
�rh}z|�tjdt|��WY�dSd}~XYnX|j�dd�}	|	��dk�r�d|_n |	��dk�r�|jdk�r�d|_|j�dd�}
|
��dk�r�|jdk�r�|jdk�r�|� ��s�dSdS)NTz
iso-8859-1z
rF����zHTTP/�/r	�.r
zBad request version (%r))r	r	zHTTP/1.1)r
rzInvalid HTTP version (%s)zBad request syntax (%r)ZGETzBad HTTP/0.9 request type (%r)z//)Z_classz
Line too longzToo many headers�
Connection��close�
keep-aliveZExpectz100-continue)!�command�default_request_version�request_version�close_connection�str�raw_requestline�rstrip�requestline�split�len�
startswith�
ValueError�int�
IndexError�
send_errorrZBAD_REQUEST�protocol_versionZHTTP_VERSION_NOT_SUPPORTED�path�lstrip�http�clientZ
parse_headers�rfile�MessageClass�headersZLineTooLongZREQUEST_HEADER_FIELDS_TOO_LARGEZ
HTTPException�get�lower�handle_expect_100)r�versionr)�wordsZbase_version_numberZversion_numberr"r2�errZconntypeZexpectrrr�
parse_requests�


�
��
�
������
z$BaseHTTPRequestHandler.parse_requestcCs|�tj�|��dS�NT)�send_response_onlyrZCONTINUE�end_headers�rrrrr;xsz(BaseHTTPRequestHandler.handle_expect_100c
Cs�z�|j�d�|_t|j�dkrBd|_d|_d|_|�tj	�WdS|jsTd|_
WdS|��sbWdSd|j}t||�s�|�tj
d|j�WdSt||�}|�|j��Wn<tjk
r�}z|�d|�d|_
WY�dSd}~XYnXdS)NiirTZdo_zUnsupported method (%r)zRequest timed out: %r)r6�readliner'r+r)r$r"r0rZREQUEST_URI_TOO_LONGr%r?�hasattr�NOT_IMPLEMENTED�getattr�wfile�flushrZtimeout�	log_error)rZmname�method�errr�handle_one_request�s6

�
z)BaseHTTPRequestHandler.handle_one_requestcCs"d|_|��|js|��qdSr@)r%rMrCrrr�handle�szBaseHTTPRequestHandler.handleNcCsz|j|\}}Wntk
r.d\}}YnX|dkr<|}|dkrH|}|�d||�|�||�|�dd�d}|dkr�|tjtjtjfkr�|j	|t
j|dd�t
j|dd�d�}|�d	d
�}|�d|j
�|�dtt|���|��|jd
k�r|�r|j�|�dS)N)�???rOzcode %d, message %srr ��F��quote)�code�message�explainzUTF-8�replacezContent-Type�Content-LengthZHEAD)�	responses�KeyErrorrJ�
send_response�send_headerrZ
NO_CONTENTZ
RESET_CONTENT�NOT_MODIFIED�error_message_format�html�escape�encode�error_content_typer&r+rBr"rH�write)rrSrTrUZshortmsgZlongmsgZbodyZcontentrrrr0�s:���z!BaseHTTPRequestHandler.send_errorcCs:|�|�|�||�|�d|���|�d|���dS)NZServerZDate)�log_requestrAr[�version_string�date_time_string�rrSrTrrrrZ�s
z$BaseHTTPRequestHandler.send_responsecCsd|jdkr`|dkr0||jkr,|j|d}nd}t|d�s@g|_|j�d|j||f�dd��dS)Nrrr�_headers_bufferz
%s %d %s
�latin-1�strict)r$rXrErg�appendr1r`rfrrrrA�s



��z)BaseHTTPRequestHandler.send_response_onlycCsl|jdkr6t|d�sg|_|j�d||f�dd��|��dkrh|��dkrVd|_n|��d	krhd
|_dS)Nrrgz%s: %s
rhriZ
connectionr Tr!F)r$rErgrjr`r:r%)r�keyword�valuerrrr[s

�z"BaseHTTPRequestHandler.send_headercCs"|jdkr|j�d�|��dS)Nrs
)r$rgrj�
flush_headersrCrrrrBs
z"BaseHTTPRequestHandler.end_headerscCs(t|d�r$|j�d�|j��g|_dS)Nrg�)rErHrb�joinrgrCrrrrms
z$BaseHTTPRequestHandler.flush_headers�-cCs.t|t�r|j}|�d|jt|�t|��dS)Nz
"%s" %s %s)�
isinstancerrl�log_messager)r&)rrS�sizerrrrc s
�z"BaseHTTPRequestHandler.log_requestcGs|j|f|��dS�N)rr)r�format�argsrrrrJ+sz BaseHTTPRequestHandler.log_errorcCsi|]}|d|d���qS)z\xZ02xr)�.0�crrr�
<dictcomp>;sz!BaseHTTPRequestHandler.<dictcomp>� ��z\\�\cGs2||}tj�d|��|��|�|j�f�dS)Nz%s - - [%s] %s
)�sys�stderrrb�address_string�log_date_time_string�	translate�_control_char_table)rrurvrTrrrrr>s
��z"BaseHTTPRequestHandler.log_messagecCs|jd|jS)N� )�server_version�sys_versionrCrrrrdXsz%BaseHTTPRequestHandler.version_stringcCs |dkrt��}tjj|dd�S)NT)Zusegmt)�time�email�utilsZ
formatdate)rZ	timestamprrrre\sz'BaseHTTPRequestHandler.date_time_stringc	CsBt��}t�|�\	}}}}}}}}	}
d||j|||||f}|S)Nz%02d/%3s/%04d %02d:%02d:%02d)r��	localtime�	monthname)rZnowZyearZmonthZdayZhhZmmZss�x�y�z�srrrr�bs�z+BaseHTTPRequestHandler.log_date_time_stringZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs
|jdS�Nr)�client_addressrCrrrr�psz%BaseHTTPRequestHandler.address_string�HTTP/1.0cCsi|]}||j|jf�qSr)�phraseZdescription)rw�vrrrrys�)NN)N)N)rprp)N)1rrrr~r<r*r��__version__r��DEFAULT_ERROR_MESSAGEr]�DEFAULT_ERROR_CONTENT_TYPErar#r?r;rMrNr0rZrAr[rBrmrcrJr&�	maketrans�	itertools�chain�ranger��ordrrrdrer�Zweekdaynamer�r�r1r4r5ZHTTPMessager7r�__members__�valuesrXrrrrr�s\ij%
5


�
�	�cs�eZdZdeZdd��fdd�
Zdd�Zdd	�Zd
d�Zdd
�Z	dd�Z
dd�Zdd�Ze
jshe
��e
j��Ze�ddddd���ZS)rzSimpleHTTP/N��	directorycs(|dkrt��}||_t�j||�dSrt)�os�getcwdr��super�__init__)rr�rv�kwargs��	__class__rrr��sz!SimpleHTTPRequestHandler.__init__cCs.|��}|r*z|�||j�W5|��XdSrt)�	send_headr �copyfilerH�r�frrr�do_GET�s
zSimpleHTTPRequestHandler.do_GETcCs|��}|r|��dSrt)r�r r�rrr�do_HEAD�sz SimpleHTTPRequestHandler.do_HEADcCs^|�|j�}d}tj�|�r�tj�|j�}|j�d�s�|�t	j
�|d|d|dd|d|df}tj�|�}|�d|�|�
�dSdD]&}tj�||�}tj�|�r�|}q�q�|�|�S|�|�}|�d�r�|�t	jd	�dSzt|d
�}Wn&tk
�r|�t	jd	�YdSX�z"t�|���}d|jk�r�d|jk�r�ztj�|jd�}	Wnttttfk
�r|YnzX|	j dk�r�|	j!t"j#j$d
�}	|	j t"j#j$k�r�t"j"�%|j&t"j#j$�}
|
j!dd�}
|
|	k�r�|�t	j'�|�
�|�(�WdS|�t	j)�|�d|�|�dt*|d��|�d|�+|j&��|�
�|WS|�(��YnXdS)Nrrr	r
r�ZLocation)z
index.htmlz	index.htmzFile not found�rbzIf-Modified-Sincez
If-None-Match)�tzinfo)Zmicrosecond�Content-typerW�z
Last-Modified),�translate_pathr2r��isdir�urllib�parseZurlsplit�endswithrZrZMOVED_PERMANENTLYZ
urlunsplitr[rBro�exists�list_directory�
guess_typer0�	NOT_FOUND�open�OSError�fstat�filenor8r�r�Zparsedate_to_datetime�	TypeErrorr/�
OverflowErrorr-r�rV�datetime�timezoneZutcZ
fromtimestamp�st_mtimer\r �OKr&re)rr2r��partsZ	new_partsZnew_url�indexZctypeZfsZimsZ
last_modifrrrr��s��


���

�z"SimpleHTTPRequestHandler.send_headc
	Cs�zt�|�}Wn$tk
r2|�tjd�YdSX|jdd�d�g}ztjj	|j
dd�}Wn"tk
r�tj�	|j
�}YnXtj
|dd�}t��}d	|}|�d
�|�d�|�d|�|�d
|�|�d|�|�d�|D]v}tj
�||�}|}	}
tj
�|��r$|d}	|d}
tj
�|��r:|d}	|�dtjj|
dd�tj
|	dd�f�q�|�d�d�|��|d�}t��}|�|�|�d�|�tj�|�dd|�|�dtt|���|��|S)NzNo permission to list directorycSs|��Srt)r:)�arrr�<lambda>rnz9SimpleHTTPRequestHandler.list_directory.<locals>.<lambda>)�key�
surrogatepass��errorsFrQzDirectory listing for %szZ<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">z
<html>
<head>z@<meta http-equiv="Content-Type" content="text/html; charset=%s">z<title>%s</title>
</head>z<body>
<h1>%s</h1>z	<hr>
<ul>r�@z<li><a href="%s">%s</a></li>z</ul>
<hr>
</body>
</html>
�
�surrogateescaperr�ztext/html; charset=%srW) r��listdirr�r0rr��sortr�r��unquoter2�UnicodeDecodeErrorr^r_r~�getfilesystemencodingrjror��islinkrRr`�io�BytesIOrb�seekrZr�r[r&r+rB)
rr2�list�rZdisplaypath�enc�title�name�fullnameZdisplaynameZlinknameZencodedr�rrrr�sh�
�


�
���


z'SimpleHTTPRequestHandler.list_directorycCs�|�dd�d}|�dd�d}|���d�}ztjj|dd�}Wn tk
rbtj�|�}YnXt�|�}|�d�}t	d|�}|j
}|D]0}tj�
|�s�|tjtjfkr�q�tj�||�}q�|r�|d7}|S)N�?r	r�#rr�r�)r*r(r�r�r�r�r��	posixpath�normpath�filterr�r�r2�dirname�curdir�pardirro)rr2Ztrailing_slashr=Zwordrrrr�:s$	


z'SimpleHTTPRequestHandler.translate_pathcCst�||�dSrt)�shutilZcopyfileobj)r�sourceZ
outputfilerrrr�Xsz!SimpleHTTPRequestHandler.copyfilecCsLt�|�\}}||jkr"|j|S|��}||jkr>|j|S|jdSdS)Nr)r��splitext�extensions_mapr:)rr2�baseZextrrrr�hs



z#SimpleHTTPRequestHandler.guess_typezapplication/octet-streamz
text/plain)r�.pyz.cz.h)rrrr�r�r�r�r�r�r�r�r�r��	mimetypesZinitedZinitZ	types_map�copyr��update�
__classcell__rrr�rr�s$
	W:
�c	Cs�|�d�\}}}tj�|�}|�d�}g}|dd�D],}|dkrL|��q6|r6|dkr6|�|�q6|r�|��}|r�|dkr�|��d}q�|dkr�d}nd}|r�d�||f�}dd�|�|f}d�|�}|S)Nr�rrz..rr)�	partitionr�r�r�r*�poprjro)	r2�_�query�
path_partsZ
head_parts�partZ	tail_partZ	splitpath�collapsed_pathrrr�_url_collapse_path�s.


r�cCsrtrtSzddl}Wntk
r*YdSXz|�d�daWn.tk
rldtdd�|��D��aYnXtS)Nrr�nobodyr
r	css|]}|dVqdS)r
Nr)rwr�rrr�	<genexpr>�sznobody_uid.<locals>.<genexpr>)r��pwd�ImportError�getpwnamrY�maxZgetpwall)r�rrr�
nobody_uid�s rcCst�|tj�Srt)r��access�X_OK)r2rrr�
executable�src@sReZdZeed�ZdZdd�Zdd�Zdd�Z	d	d
gZ
dd�Zd
d�Zdd�Z
dS)r�forkrcCs$|��r|��n|�tjd�dS)NzCan only POST to CGI scripts)�is_cgi�run_cgir0rrFrCrrr�do_POST�s
�zCGIHTTPRequestHandler.do_POSTcCs|��r|��St�|�SdSrt)rrrr�rCrrrr��szCGIHTTPRequestHandler.send_headcCsPt|j�}|�dd�}|d|�||dd�}}||jkrL||f|_dSdS)Nrr	TF)r�r2�find�cgi_directories�cgi_info)rr�Zdir_sep�head�tailrrrr�s


zCGIHTTPRequestHandler.is_cgiz/cgi-binz/htbincCst|�Srt)r)rr2rrr�
is_executablesz#CGIHTTPRequestHandler.is_executablecCstj�|�\}}|��dkS)N)r�z.pyw)r�r2r�r:)rr2rrrrr�	is_pythonszCGIHTTPRequestHandler.is_pythonc)	Cs�|j\}}|d|}|�dt|�d�}|dkr�|d|�}||dd�}|�|�}tj�|�r�||}}|�dt|�d�}q*q�q*|�d�\}}}	|�d�}|dkr�|d|�||d�}
}n
|d}
}|d|
}|�|�}tj�|��s
|�	t
jd|�dStj�|��s.|�	t
j
d|�dS|�|�}
|j�sF|
�sh|�|��sh|�	t
j
d|�dSt�tj�}|��|d	<|jj|d
<d|d<|j|d
<t|jj�|d<|j|d<tj�|�}||d<|�|�|d<||d<|	�r�|	|d<|jd|d<|j� d�}|�r�|�!�}t|�dk�r�ddl"}ddl#}|d|d<|d�$�dk�r�z"|d�%d�}|�&|��'d�}Wn|j(t)fk
�r�Yn&X|�!d�}t|�dk�r�|d|d<|j� d�dk�r�|j�*�|d<n|jd|d<|j� d�}|�r||d<|j� d �}|�r||d!<g}|j�+d"�D]>}|dd�d#k�rR|�,|�-��n||d$d��!d%�}�q,d%�.|�|d&<|j� d'�}|�r�||d(<t/d|j�0d)g��}d*�.|�}|�r�||d+<d,D]}|�1|d��q�|�2t
j3d-�|�4�|	�5d.d/�}|j�r|
g}d0|k�r|�,|�t6�}|j7�8�t�9�}|dk�r�t�:|d�\}}t;�;|j<gggd�d�r~|j<�=d��sN�q~�qN|�r�|�>d1|�dSz\zt�?|�Wnt@k
�r�YnXt�A|j<�B�d�t�A|j7�B�d�t�C|||�Wn(|j�D|jE|j�t�Fd2�YnX�n�ddlG} |g}!|�|��rrtHjI}"|"�$��Jd3��rf|"dd4�|"d5d�}"|"d6g|!}!d0|	k�r�|!�,|	�|�Kd7| �L|!��ztM|�}#WntNtOfk
�r�d}#YnX| jP|!| jQ| jQ| jQ|d8�}$|j�$�d9k�r|#dk�r|j<�=|#�}%nd}%t;�;|j<jRgggd�d�r>|j<jR�Sd��s
�q>�q
|$�T|%�\}&}'|j7�U|&�|'�rj|�>d:|'�|$jV�W�|$jX�W�|$jY}(|(�r�|�>d1|(�n
|�Kd;�dS)<Nrr	rr�rzNo such CGI script (%r)z#CGI script is not a plain file (%r)z!CGI script is not executable (%r)ZSERVER_SOFTWAREZSERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZSERVER_PROTOCOLZSERVER_PORTZREQUEST_METHODZ	PATH_INFOZPATH_TRANSLATEDZSCRIPT_NAME�QUERY_STRINGZREMOTE_ADDR�
authorizationr
Z	AUTH_TYPEZbasic�ascii�:ZREMOTE_USERzcontent-typeZCONTENT_TYPEzcontent-length�CONTENT_LENGTH�referer�HTTP_REFERER�acceptz	

 ��,ZHTTP_ACCEPTz
user-agent�HTTP_USER_AGENTZcookiez, �HTTP_COOKIE)rZREMOTE_HOSTrrrrzScript output follows�+r��=zCGI script exit status %#xr{zw.exe������z-uzcommand: %s)�stdin�stdoutr�envZpostz%szCGI script exited OK)Zr
rr+r�r�r2r�r�r�r0rr��isfileZ	FORBIDDENr�	have_forkr
r�Zdeepcopy�environrdZserverrr1r&rr"r�r�r�r�r8r9r*�base64�binasciir:r`Zdecodebytes�decode�Error�UnicodeErrorZget_content_typeZgetallmatchingheadersrj�stripror�Zget_all�
setdefaultrZr�rmrVrrHrIr�waitpid�selectr6�readrJ�setuidr��dup2r��execveZhandle_errorZrequest�_exit�
subprocessr~rr�rrZlist2cmdliner.r�r-�Popen�PIPEZ_sockZrecvZcommunicaterbrr r �
returncode))r�dir�restr2�iZnextdirZnextrestZ	scriptdirr�r�ZscriptZ
scriptnameZ
scriptfileZispyr!Zuqrestrr%r&Zlengthrr�lineZua�coZ
cookie_str�kZ
decoded_queryrvr��pid�stsr3ZcmdlineZinterp�nbytes�p�datar rZstatusrrrrs<





��
�


�








�

zCGIHTTPRequestHandler.run_cgiN)rrrrEr�r#Zrbufsizerr�rr	r
rrrrrrr�s
cGs4tj|tjtjd��}tt|��\}}}}}||fS)N)�type�flags)rZgetaddrinfoZSOCK_STREAMZ
AI_PASSIVE�next�iter)ZaddressZinfosZfamilyrB�protoZ	canonnameZsockaddrrrr�_get_best_family�s�rGr�i@c	Cs�t||�\|_}||_|||���}|j��dd�\}}d|krLd|�d�n|}td|�d|�d|�d|�d�	�z|��Wn&tk
r�td	�t�	d
�YnXW5QRXdS)Nr
r�[�]zServing HTTP on z port z	 (http://z/) ...z&
Keyboard interrupt received, exiting.r)
rGZaddress_familyr1rZgetsockname�printZ
serve_forever�KeyboardInterruptr~�exit)	�HandlerClass�ServerClassZprotocolr�bindZaddrZhttpdrZurl_hostrrr�test�s�rP�__main__z--cgi�
store_truezRun as CGI Server)�action�helpz--bindz-bZADDRESSz8Specify alternate bind address [default: all interfaces])�metavarrTz--directoryz-dz9Specify alternative directory [default:current directory])�defaultrTrZstorer�z&Specify alternate port [default: 8000])rSrVrB�nargsrTr�cseZdZ�fdd�Z�ZS)�DualStackServerc	s4t�t��|j�tjtjd�W5QRXt���Sr�)	�
contextlib�suppress�	ExceptionrZ
setsockoptZIPPROTO_IPV6ZIPV6_V6ONLYr�r
rCr�rrr
s�zDualStackServer.server_bind)rrrr
r�rrr�rrXsrX)rMrNrrO)9r��__all__r�r�Zemail.utilsr�r^Zhttp.clientr4r�r�r�r�r�r-r�rrr~r�Zurllib.parser�rY�	functoolsrrr�r�rrZThreadingMixInrZStreamRequestHandlerrrr�r�rrrrGrPr�argparse�ArgumentParser�parser�add_argumentr�r.�
parse_argsrvZcgiZ
handler_classr�rXrrOrrrr�<module>Ss��s
0
�

�
�����cookies.py000064400000047674150532417300006574 0ustar00####
# Copyright 2000 by Timothy O'Malley <timo@alum.mit.edu>
#
#                All Rights Reserved
#
# Permission to use, copy, modify, and distribute this software
# and its documentation for any purpose and without fee is hereby
# granted, provided that the above copyright notice appear in all
# copies and that both that copyright notice and this permission
# notice appear in supporting documentation, and that the name of
# Timothy O'Malley  not be used in advertising or publicity
# pertaining to distribution of the software without specific, written
# prior permission.
#
# Timothy O'Malley DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS, IN NO EVENT SHALL Timothy O'Malley BE LIABLE FOR
# ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
# PERFORMANCE OF THIS SOFTWARE.
#
####
#
# Id: Cookie.py,v 2.29 2000/08/23 05:28:49 timo Exp
#   by Timothy O'Malley <timo@alum.mit.edu>
#
#  Cookie.py is a Python module for the handling of HTTP
#  cookies as a Python dictionary.  See RFC 2109 for more
#  information on cookies.
#
#  The original idea to treat Cookies as a dictionary came from
#  Dave Mitchell (davem@magnet.com) in 1995, when he released the
#  first version of nscookie.py.
#
####

r"""
Here's a sample session to show how to use this module.
At the moment, this is the only documentation.

The Basics
----------

Importing is easy...

   >>> from http import cookies

Most of the time you start by creating a cookie.

   >>> C = cookies.SimpleCookie()

Once you've created your Cookie, you can add values just as if it were
a dictionary.

   >>> C = cookies.SimpleCookie()
   >>> C["fig"] = "newton"
   >>> C["sugar"] = "wafer"
   >>> C.output()
   'Set-Cookie: fig=newton\r\nSet-Cookie: sugar=wafer'

Notice that the printable representation of a Cookie is the
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.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

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.SimpleCookie()
   >>> C.load("chips=ahoy; vienna=finger")
   >>> C.output()
   'Set-Cookie: chips=ahoy\r\nSet-Cookie: vienna=finger'

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.SimpleCookie()
   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
   >>> print(C)
   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"

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.SimpleCookie()
   >>> C["oreo"] = "doublestuff"
   >>> C["oreo"]["path"] = "/"
   >>> print(C)
   Set-Cookie: oreo=doublestuff; Path=/

Each dictionary element has a 'value' attribute, which gives you
back the value associated with the key.

   >>> C = cookies.SimpleCookie()
   >>> C["twix"] = "none for you"
   >>> C["twix"].value
   'none for you'

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.

   >>> C = cookies.SimpleCookie()
   >>> C["number"] = 7
   >>> C["string"] = "seven"
   >>> C["number"].value
   '7'
   >>> C["string"].value
   'seven'
   >>> C.output()
   'Set-Cookie: number=7\r\nSet-Cookie: string=seven'

Finis.
"""

#
# Import our required modules
#
import re
import string

__all__ = ["CookieError", "BaseCookie", "SimpleCookie"]

_nulljoin = ''.join
_semispacejoin = '; '.join
_spacejoin = ' '.join

#
# Define an exception visible to External modules
#
class CookieError(Exception):
    pass


# These quoting routines conform to the RFC2109 specification, which in
# turn references the character definitions from RFC2068.  They provide
# a two-way quoting algorithm.  Any non-text character is translated
# into a 4 character sequence: a forward-slash followed by the
# three-digit octal equivalent of the character.  Any '\' or '"' is
# quoted with a preceding '\' slash.
# Because of the way browsers really handle cookies (as opposed to what
# the RFC says) we also encode "," and ";".
#
# These are taken from RFC2068 and RFC2109.
#       _LegalChars       is the list of chars which don't require "'s
#       _Translator       hash-table for fast quoting
#
_LegalChars = string.ascii_letters + string.digits + "!#$%&'*+-.^_`|~:"
_UnescapedChars = _LegalChars + ' ()/<=>?@[]{}'

_Translator = {n: '\\%03o' % n
               for n in set(range(256)) - set(map(ord, _UnescapedChars))}
_Translator.update({
    ord('"'): '\\"',
    ord('\\'): '\\\\',
})

_is_legal_key = re.compile('[%s]+' % re.escape(_LegalChars)).fullmatch

def _quote(str):
    r"""Quote a string for use in a cookie header.

    If the string does not need to be double-quoted, then just return the
    string.  Otherwise, surround the string in doublequotes and quote
    (with a \) special characters.
    """
    if str is None or _is_legal_key(str):
        return str
    else:
        return '"' + str.translate(_Translator) + '"'


_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]")
_QuotePatt = re.compile(r"[\\].")

def _unquote(str):
    # If there aren't any doublequotes,
    # then there can't be any special characters.  See RFC 2109.
    if str is None or len(str) < 2:
        return str
    if str[0] != '"' or str[-1] != '"':
        return str

    # We have to assume that we must decode this string.
    # Down to work.

    # Remove the "s
    str = str[1:-1]

    # Check for special sequences.  Examples:
    #    \012 --> \n
    #    \"   --> "
    #
    i = 0
    n = len(str)
    res = []
    while 0 <= i < n:
        o_match = _OctalPatt.search(str, i)
        q_match = _QuotePatt.search(str, i)
        if not o_match and not q_match:              # Neither matched
            res.append(str[i:])
            break
        # else:
        j = k = -1
        if o_match:
            j = o_match.start(0)
        if q_match:
            k = q_match.start(0)
        if q_match and (not o_match or k < j):     # QuotePatt matched
            res.append(str[i:k])
            res.append(str[k+1])
            i = k + 2
        else:                                      # OctalPatt matched
            res.append(str[i:j])
            res.append(chr(int(str[j+1:j+4], 8)))
            i = j + 4
    return _nulljoin(res)

# The _getdate() routine is used to set the expiration time in the cookie's HTTP
# header.  By default, _getdate() returns the current time in the appropriate
# "expires" format for a Set-Cookie header.  The one optional argument is an
# offset from now, in seconds.  For example, an offset of -3600 means "one hour
# ago".  The offset may be a floating point number.
#

_weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

_monthname = [None,
              'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
              'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

def _getdate(future=0, weekdayname=_weekdayname, monthname=_monthname):
    from time import gmtime, time
    now = time()
    year, month, day, hh, mm, ss, wd, y, z = gmtime(now + future)
    return "%s, %02d %3s %4d %02d:%02d:%02d GMT" % \
           (weekdayname[wd], day, monthname[month], year, hh, mm, ss)


class Morsel(dict):
    """A class to hold ONE (key, value) pair.

    In a cookie, each such pair may have several attributes, so this class is
    used to keep the attributes associated with the appropriate key,value pair.
    This class also includes a coded_value attribute, which is used to hold
    the network representation of the value.
    """
    # RFC 2109 lists these attributes as reserved:
    #   path       comment         domain
    #   max-age    secure      version
    #
    # For historical reasons, these attributes are also reserved:
    #   expires
    #
    # This is an extension from Microsoft:
    #   httponly
    #
    # This dictionary provides a mapping from the lowercase
    # variant on the left to the appropriate traditional
    # formatting on the right.
    _reserved = {
        "expires"  : "expires",
        "path"     : "Path",
        "comment"  : "Comment",
        "domain"   : "Domain",
        "max-age"  : "Max-Age",
        "secure"   : "Secure",
        "httponly" : "HttpOnly",
        "version"  : "Version",
        "samesite" : "SameSite",
    }

    _flags = {'secure', 'httponly'}

    def __init__(self):
        # Set defaults
        self._key = self._value = self._coded_value = None

        # Set default attributes
        for key in self._reserved:
            dict.__setitem__(self, key, "")

    @property
    def key(self):
        return self._key

    @property
    def value(self):
        return self._value

    @property
    def coded_value(self):
        return self._coded_value

    def __setitem__(self, K, V):
        K = K.lower()
        if not K in self._reserved:
            raise CookieError("Invalid attribute %r" % (K,))
        dict.__setitem__(self, K, V)

    def setdefault(self, key, val=None):
        key = key.lower()
        if key not in self._reserved:
            raise CookieError("Invalid attribute %r" % (key,))
        return dict.setdefault(self, key, val)

    def __eq__(self, morsel):
        if not isinstance(morsel, Morsel):
            return NotImplemented
        return (dict.__eq__(self, morsel) and
                self._value == morsel._value and
                self._key == morsel._key and
                self._coded_value == morsel._coded_value)

    __ne__ = object.__ne__

    def copy(self):
        morsel = Morsel()
        dict.update(morsel, self)
        morsel.__dict__.update(self.__dict__)
        return morsel

    def update(self, values):
        data = {}
        for key, val in dict(values).items():
            key = key.lower()
            if key not in self._reserved:
                raise CookieError("Invalid attribute %r" % (key,))
            data[key] = val
        dict.update(self, data)

    def isReservedKey(self, K):
        return K.lower() in self._reserved

    def set(self, key, val, coded_val):
        if key.lower() in self._reserved:
            raise CookieError('Attempt to set a reserved key %r' % (key,))
        if not _is_legal_key(key):
            raise CookieError('Illegal key %r' % (key,))

        # It's a good key, so save it.
        self._key = key
        self._value = val
        self._coded_value = coded_val

    def __getstate__(self):
        return {
            'key': self._key,
            'value': self._value,
            'coded_value': self._coded_value,
        }

    def __setstate__(self, state):
        self._key = state['key']
        self._value = state['value']
        self._coded_value = state['coded_value']

    def output(self, attrs=None, header="Set-Cookie:"):
        return "%s %s" % (header, self.OutputString(attrs))

    __str__ = output

    def __repr__(self):
        return '<%s: %s>' % (self.__class__.__name__, self.OutputString())

    def js_output(self, attrs=None):
        # Print javascript
        return """
        <script type="text/javascript">
        <!-- begin hiding
        document.cookie = \"%s\";
        // end hiding -->
        </script>
        """ % (self.OutputString(attrs).replace('"', r'\"'))

    def OutputString(self, attrs=None):
        # Build up our result
        #
        result = []
        append = result.append

        # First, the key=value pair
        append("%s=%s" % (self.key, self.coded_value))

        # Now add any defined attributes
        if attrs is None:
            attrs = self._reserved
        items = sorted(self.items())
        for key, value in items:
            if value == "":
                continue
            if key not in attrs:
                continue
            if key == "expires" and isinstance(value, int):
                append("%s=%s" % (self._reserved[key], _getdate(value)))
            elif key == "max-age" and isinstance(value, int):
                append("%s=%d" % (self._reserved[key], value))
            elif key == "comment" and isinstance(value, str):
                append("%s=%s" % (self._reserved[key], _quote(value)))
            elif key in self._flags:
                if value:
                    append(str(self._reserved[key]))
            else:
                append("%s=%s" % (self._reserved[key], value))

        # Return the result
        return _semispacejoin(result)


#
# Pattern for finding cookie
#
# This used to be strict parsing based on the RFC2109 and RFC2068
# specifications.  I have since discovered that MSIE 3.0x doesn't
# follow the character rules outlined in those specs.  As a
# result, the parsing rules here are less strict.
#

_LegalKeyChars  = r"\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\="
_LegalValueChars = _LegalKeyChars + r'\[\]'
_CookiePattern = re.compile(r"""
    \s*                            # Optional whitespace at start of cookie
    (?P<key>                       # Start of group 'key'
    [""" + _LegalKeyChars + r"""]+?   # Any word of at least one letter
    )                              # End of group 'key'
    (                              # Optional group: there may not be a value.
    \s*=\s*                          # Equal Sign
    (?P<val>                         # Start of group 'val'
    "(?:[^\\"]|\\.)*"                  # Any doublequoted string
    |                                  # or
    \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT  # Special case for "expires" attr
    |                                  # or
    [""" + _LegalValueChars + r"""]*      # Any word or empty string
    )                                # End of group 'val'
    )?                             # End of optional value group
    \s*                            # Any number of spaces.
    (\s+|;|$)                      # Ending either at space, semicolon, or EOS.
    """, re.ASCII | re.VERBOSE)    # re.ASCII may be removed if safe.


# At long last, here is the cookie class.  Using this class is almost just like
# using a dictionary.  See this module's docstring for example usage.
#
class BaseCookie(dict):
    """A container class for a set of Morsels."""

    def value_decode(self, val):
        """real_value, coded_value = value_decode(STRING)
        Called prior to setting a cookie's value from the network
        representation.  The VALUE is the value read from HTTP
        header.
        Override this function to modify the behavior of cookies.
        """
        return val, val

    def value_encode(self, val):
        """real_value, coded_value = value_encode(VALUE)
        Called prior to setting a cookie's value from the dictionary
        representation.  The VALUE is the value being assigned.
        Override this function to modify the behavior of cookies.
        """
        strval = str(val)
        return strval, strval

    def __init__(self, input=None):
        if input:
            self.load(input)

    def __set(self, key, real_value, coded_value):
        """Private method for setting a cookie's value"""
        M = self.get(key, Morsel())
        M.set(key, real_value, coded_value)
        dict.__setitem__(self, key, M)

    def __setitem__(self, key, value):
        """Dictionary style assignment."""
        if isinstance(value, Morsel):
            # allow assignment of constructed Morsels (e.g. for pickling)
            dict.__setitem__(self, key, value)
        else:
            rval, cval = self.value_encode(value)
            self.__set(key, rval, cval)

    def output(self, attrs=None, header="Set-Cookie:", sep="\015\012"):
        """Return a string suitable for HTTP."""
        result = []
        items = sorted(self.items())
        for key, value in items:
            result.append(value.output(attrs, header))
        return sep.join(result)

    __str__ = output

    def __repr__(self):
        l = []
        items = sorted(self.items())
        for key, value in items:
            l.append('%s=%s' % (key, repr(value.value)))
        return '<%s: %s>' % (self.__class__.__name__, _spacejoin(l))

    def js_output(self, attrs=None):
        """Return a string suitable for JavaScript."""
        result = []
        items = sorted(self.items())
        for key, value in items:
            result.append(value.js_output(attrs))
        return _nulljoin(result)

    def load(self, rawdata):
        """Load cookies from a string (presumably HTTP_COOKIE) or
        from a dictionary.  Loading cookies from a dictionary 'd'
        is equivalent to calling:
            map(Cookie.__setitem__, d.keys(), d.values())
        """
        if isinstance(rawdata, str):
            self.__parse_string(rawdata)
        else:
            # self.update() wouldn't call our custom __setitem__
            for key, value in rawdata.items():
                self[key] = value
        return

    def __parse_string(self, str, patt=_CookiePattern):
        i = 0                 # Our starting point
        n = len(str)          # Length of string
        parsed_items = []     # Parsed (type, key, value) triples
        morsel_seen = False   # A key=value pair was previously encountered

        TYPE_ATTRIBUTE = 1
        TYPE_KEYVALUE = 2

        # We first parse the whole cookie string and reject it if it's
        # syntactically invalid (this helps avoid some classes of injection
        # attacks).
        while 0 <= i < n:
            # Start looking for a cookie
            match = patt.match(str, i)
            if not match:
                # No more cookies
                break

            key, value = match.group("key"), match.group("val")
            i = match.end(0)

            if key[0] == "$":
                if not morsel_seen:
                    # We ignore attributes which pertain to the cookie
                    # mechanism as a whole, such as "$Version".
                    # See RFC 2965. (Does anyone care?)
                    continue
                parsed_items.append((TYPE_ATTRIBUTE, key[1:], value))
            elif key.lower() in Morsel._reserved:
                if not morsel_seen:
                    # Invalid cookie string
                    return
                if value is None:
                    if key.lower() in Morsel._flags:
                        parsed_items.append((TYPE_ATTRIBUTE, key, True))
                    else:
                        # Invalid cookie string
                        return
                else:
                    parsed_items.append((TYPE_ATTRIBUTE, key, _unquote(value)))
            elif value is not None:
                parsed_items.append((TYPE_KEYVALUE, key, self.value_decode(value)))
                morsel_seen = True
            else:
                # Invalid cookie string
                return

        # The cookie string is valid, apply it.
        M = None         # current morsel
        for tp, key, value in parsed_items:
            if tp == TYPE_ATTRIBUTE:
                assert M is not None
                M[key] = value
            else:
                assert tp == TYPE_KEYVALUE
                rval, cval = value
                self.__set(key, rval, cval)
                M = self[key]


class SimpleCookie(BaseCookie):
    """
    SimpleCookie supports strings as cookie values.  When setting
    the value using the dictionary assignment notation, SimpleCookie
    calls the builtin str() to convert the value to a string.  Values
    received from HTTP are kept as strings.
    """
    def value_decode(self, val):
        return _unquote(val), val

    def value_encode(self, val):
        strval = str(val)
        return strval, _quote(strval)
server.py000064400000135757150532417300006446 0ustar00"""HTTP server classes.

Note: BaseHTTPRequestHandler doesn't implement any HTTP request; see
SimpleHTTPRequestHandler for simple implementations of GET, HEAD and POST,
and CGIHTTPRequestHandler for CGI scripts.

It does, however, optionally implement HTTP/1.1 persistent connections,
as of version 0.3.

Notes on CGIHTTPRequestHandler
------------------------------

This class implements GET and POST requests to cgi-bin scripts.

If the os.fork() function is not present (e.g. on Windows),
subprocess.Popen() is used as a fallback, with slightly altered semantics.

In all cases, the implementation is intentionally naive -- all
requests are executed synchronously.

SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
-- it may execute arbitrary Python code or external programs.

Note that status code 200 is sent prior to execution of a CGI script, so
scripts cannot send other status codes such as 302 (redirect).

XXX To do:

- log requests even later (to capture byte count)
- log user-agent header and other interesting goodies
- send error log to separate file
"""


# See also:
#
# HTTP Working Group                                        T. Berners-Lee
# INTERNET-DRAFT                                            R. T. Fielding
# <draft-ietf-http-v10-spec-00.txt>                     H. Frystyk Nielsen
# Expires September 8, 1995                                  March 8, 1995
#
# URL: http://www.ics.uci.edu/pub/ietf/http/draft-ietf-http-v10-spec-00.txt
#
# and
#
# Network Working Group                                      R. Fielding
# Request for Comments: 2616                                       et al
# Obsoletes: 2068                                              June 1999
# Category: Standards Track
#
# URL: http://www.faqs.org/rfcs/rfc2616.html

# Log files
# ---------
#
# Here's a quote from the NCSA httpd docs about log file format.
#
# | The logfile format is as follows. Each line consists of:
# |
# | host rfc931 authuser [DD/Mon/YYYY:hh:mm:ss] "request" ddd bbbb
# |
# |        host: Either the DNS name or the IP number of the remote client
# |        rfc931: Any information returned by identd for this person,
# |                - otherwise.
# |        authuser: If user sent a userid for authentication, the user name,
# |                  - otherwise.
# |        DD: Day
# |        Mon: Month (calendar name)
# |        YYYY: Year
# |        hh: hour (24-hour format, the machine's timezone)
# |        mm: minutes
# |        ss: seconds
# |        request: The first line of the HTTP request as sent by the client.
# |        ddd: the status code returned by the server, - if not available.
# |        bbbb: the total number of bytes sent,
# |              *not including the HTTP/1.0 header*, - if not available
# |
# | You can determine the name of the file accessed through request.
#
# (Actually, the latter is only true if you know the server configuration
# at the time the request was made!)

__version__ = "0.6"

__all__ = [
    "HTTPServer", "ThreadingHTTPServer", "BaseHTTPRequestHandler",
    "SimpleHTTPRequestHandler", "CGIHTTPRequestHandler",
]

import copy
import datetime
import email.utils
import html
import http.client
import io
import itertools
import mimetypes
import os
import posixpath
import select
import shutil
import socket # For gethostbyaddr()
import socketserver
import sys
import time
import urllib.parse
import contextlib
from functools import partial

from http import HTTPStatus


# Default error message template
DEFAULT_ERROR_MESSAGE = """\
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: %(code)d</p>
        <p>Message: %(message)s.</p>
        <p>Error code explanation: %(code)s - %(explain)s.</p>
    </body>
</html>
"""

DEFAULT_ERROR_CONTENT_TYPE = "text/html;charset=utf-8"

class HTTPServer(socketserver.TCPServer):

    allow_reuse_address = 1    # Seems to make sense in testing environment

    def server_bind(self):
        """Override server_bind to store the server name."""
        socketserver.TCPServer.server_bind(self)
        host, port = self.server_address[:2]
        self.server_name = socket.getfqdn(host)
        self.server_port = port


class ThreadingHTTPServer(socketserver.ThreadingMixIn, HTTPServer):
    daemon_threads = True


class BaseHTTPRequestHandler(socketserver.StreamRequestHandler):

    """HTTP request handler base class.

    The following explanation of HTTP serves to guide you through the
    code as well as to expose any misunderstandings I may have about
    HTTP (so you don't need to read the code to figure out I'm wrong
    :-).

    HTTP (HyperText Transfer Protocol) is an extensible protocol on
    top of a reliable stream transport (e.g. TCP/IP).  The protocol
    recognizes three parts to a request:

    1. One line identifying the request type and path
    2. An optional set of RFC-822-style headers
    3. An optional data part

    The headers and data are separated by a blank line.

    The first line of the request has the form

    <command> <path> <version>

    where <command> is a (case-sensitive) keyword such as GET or POST,
    <path> is a string containing path information for the request,
    and <version> should be the string "HTTP/1.0" or "HTTP/1.1".
    <path> is encoded using the URL encoding scheme (using %xx to signify
    the ASCII character with hex code xx).

    The specification specifies that lines are separated by CRLF but
    for compatibility with the widest range of clients recommends
    servers also handle LF.  Similarly, whitespace in the request line
    is treated sensibly (allowing multiple spaces between components
    and allowing trailing whitespace).

    Similarly, for output, lines ought to be separated by CRLF pairs
    but most clients grok LF characters just fine.

    If the first line of the request has the form

    <command> <path>

    (i.e. <version> is left out) then this is assumed to be an HTTP
    0.9 request; this form has no optional headers and data part and
    the reply consists of just the data.

    The reply form of the HTTP 1.x protocol again has three parts:

    1. One line giving the response code
    2. An optional set of RFC-822-style headers
    3. The data

    Again, the headers and data are separated by a blank line.

    The response code line has the form

    <version> <responsecode> <responsestring>

    where <version> is the protocol version ("HTTP/1.0" or "HTTP/1.1"),
    <responsecode> is a 3-digit response code indicating success or
    failure of the request, and <responsestring> is an optional
    human-readable string explaining what the response code means.

    This server parses the request and the headers, and then calls a
    function specific to the request type (<command>).  Specifically,
    a request SPAM will be handled by a method do_SPAM().  If no
    such method exists the server sends an error response to the
    client.  If it exists, it is called with no arguments:

    do_SPAM()

    Note that the request name is case sensitive (i.e. SPAM and spam
    are different requests).

    The various request details are stored in instance variables:

    - client_address is the client IP address in the form (host,
    port);

    - command, path and version are the broken-down request line;

    - headers is an instance of email.message.Message (or a derived
    class) containing the header information;

    - rfile is a file object open for reading positioned at the
    start of the optional input data part;

    - wfile is a file object open for writing.

    IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!

    The first thing to be written must be the response line.  Then
    follow 0 or more header lines, then a blank line, and then the
    actual data (if any).  The meaning of the header lines depends on
    the command executed by the server; in most cases, when data is
    returned, there should be at least one header line of the form

    Content-type: <type>/<subtype>

    where <type> and <subtype> should be registered MIME types,
    e.g. "text/html" or "text/plain".

    """

    # The Python system version, truncated to its first component.
    sys_version = "Python/" + sys.version.split()[0]

    # The server software version.  You may want to override this.
    # The format is multiple whitespace-separated strings,
    # where each string is of the form name[/version].
    server_version = "BaseHTTP/" + __version__

    error_message_format = DEFAULT_ERROR_MESSAGE
    error_content_type = DEFAULT_ERROR_CONTENT_TYPE

    # The default request version.  This only affects responses up until
    # the point where the request line is parsed, so it mainly decides what
    # the client gets back when sending a malformed request line.
    # Most web servers default to HTTP 0.9, i.e. don't send a status line.
    default_request_version = "HTTP/0.9"

    def parse_request(self):
        """Parse a request (internal).

        The request should be stored in self.raw_requestline; the results
        are in self.command, self.path, self.request_version and
        self.headers.

        Return True for success, False for failure; on failure, any relevant
        error response has already been sent back.

        """
        self.command = None  # set in case of error on the first line
        self.request_version = version = self.default_request_version
        self.close_connection = True
        requestline = str(self.raw_requestline, 'iso-8859-1')
        requestline = requestline.rstrip('\r\n')
        self.requestline = requestline
        words = requestline.split()
        if len(words) == 0:
            return False

        if len(words) >= 3:  # Enough to determine protocol version
            version = words[-1]
            try:
                if not version.startswith('HTTP/'):
                    raise ValueError
                base_version_number = version.split('/', 1)[1]
                version_number = base_version_number.split(".")
                # RFC 2145 section 3.1 says there can be only one "." and
                #   - major and minor numbers MUST be treated as
                #      separate integers;
                #   - HTTP/2.4 is a lower version than HTTP/2.13, which in
                #      turn is lower than HTTP/12.3;
                #   - Leading zeros MUST be ignored by recipients.
                if len(version_number) != 2:
                    raise ValueError
                version_number = int(version_number[0]), int(version_number[1])
            except (ValueError, IndexError):
                self.send_error(
                    HTTPStatus.BAD_REQUEST,
                    "Bad request version (%r)" % version)
                return False
            if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1":
                self.close_connection = False
            if version_number >= (2, 0):
                self.send_error(
                    HTTPStatus.HTTP_VERSION_NOT_SUPPORTED,
                    "Invalid HTTP version (%s)" % base_version_number)
                return False
            self.request_version = version

        if not 2 <= len(words) <= 3:
            self.send_error(
                HTTPStatus.BAD_REQUEST,
                "Bad request syntax (%r)" % requestline)
            return False
        command, path = words[:2]
        if len(words) == 2:
            self.close_connection = True
            if command != 'GET':
                self.send_error(
                    HTTPStatus.BAD_REQUEST,
                    "Bad HTTP/0.9 request type (%r)" % command)
                return False
        self.command, self.path = command, path

        # gh-87389: The purpose of replacing '//' with '/' is to protect
        # against open redirect attacks possibly triggered if the path starts
        # with '//' because http clients treat //path as an absolute URI
        # without scheme (similar to http://path) rather than a path.
        if self.path.startswith('//'):
            self.path = '/' + self.path.lstrip('/')  # Reduce to a single /

        # Examine the headers and look for a Connection directive.
        try:
            self.headers = http.client.parse_headers(self.rfile,
                                                     _class=self.MessageClass)
        except http.client.LineTooLong as err:
            self.send_error(
                HTTPStatus.REQUEST_HEADER_FIELDS_TOO_LARGE,
                "Line too long",
                str(err))
            return False
        except http.client.HTTPException as err:
            self.send_error(
                HTTPStatus.REQUEST_HEADER_FIELDS_TOO_LARGE,
                "Too many headers",
                str(err)
            )
            return False

        conntype = self.headers.get('Connection', "")
        if conntype.lower() == 'close':
            self.close_connection = True
        elif (conntype.lower() == 'keep-alive' and
              self.protocol_version >= "HTTP/1.1"):
            self.close_connection = False
        # Examine the headers and look for an Expect directive
        expect = self.headers.get('Expect', "")
        if (expect.lower() == "100-continue" and
                self.protocol_version >= "HTTP/1.1" and
                self.request_version >= "HTTP/1.1"):
            if not self.handle_expect_100():
                return False
        return True

    def handle_expect_100(self):
        """Decide what to do with an "Expect: 100-continue" header.

        If the client is expecting a 100 Continue response, we must
        respond with either a 100 Continue or a final response before
        waiting for the request body. The default is to always respond
        with a 100 Continue. You can behave differently (for example,
        reject unauthorized requests) by overriding this method.

        This method should either return True (possibly after sending
        a 100 Continue response) or send an error response and return
        False.

        """
        self.send_response_only(HTTPStatus.CONTINUE)
        self.end_headers()
        return True

    def handle_one_request(self):
        """Handle a single HTTP request.

        You normally don't need to override this method; see the class
        __doc__ string for information on how to handle specific HTTP
        commands such as GET and POST.

        """
        try:
            self.raw_requestline = self.rfile.readline(65537)
            if len(self.raw_requestline) > 65536:
                self.requestline = ''
                self.request_version = ''
                self.command = ''
                self.send_error(HTTPStatus.REQUEST_URI_TOO_LONG)
                return
            if not self.raw_requestline:
                self.close_connection = True
                return
            if not self.parse_request():
                # An error code has been sent, just exit
                return
            mname = 'do_' + self.command
            if not hasattr(self, mname):
                self.send_error(
                    HTTPStatus.NOT_IMPLEMENTED,
                    "Unsupported method (%r)" % self.command)
                return
            method = getattr(self, mname)
            method()
            self.wfile.flush() #actually send the response if not already done.
        except socket.timeout as e:
            #a read or a write timed out.  Discard this connection
            self.log_error("Request timed out: %r", e)
            self.close_connection = True
            return

    def handle(self):
        """Handle multiple requests if necessary."""
        self.close_connection = True

        self.handle_one_request()
        while not self.close_connection:
            self.handle_one_request()

    def send_error(self, code, message=None, explain=None):
        """Send and log an error reply.

        Arguments are
        * code:    an HTTP error code
                   3 digits
        * message: a simple optional 1 line reason phrase.
                   *( HTAB / SP / VCHAR / %x80-FF )
                   defaults to short entry matching the response code
        * explain: a detailed message defaults to the long entry
                   matching the response code.

        This sends an error response (so it must be called before any
        output has been generated), logs the error, and finally sends
        a piece of HTML explaining the error to the user.

        """

        try:
            shortmsg, longmsg = self.responses[code]
        except KeyError:
            shortmsg, longmsg = '???', '???'
        if message is None:
            message = shortmsg
        if explain is None:
            explain = longmsg
        self.log_error("code %d, message %s", code, message)
        self.send_response(code, message)
        self.send_header('Connection', 'close')

        # Message body is omitted for cases described in:
        #  - RFC7230: 3.3. 1xx, 204(No Content), 304(Not Modified)
        #  - RFC7231: 6.3.6. 205(Reset Content)
        body = None
        if (code >= 200 and
            code not in (HTTPStatus.NO_CONTENT,
                         HTTPStatus.RESET_CONTENT,
                         HTTPStatus.NOT_MODIFIED)):
            # HTML encode to prevent Cross Site Scripting attacks
            # (see bug #1100201)
            content = (self.error_message_format % {
                'code': code,
                'message': html.escape(message, quote=False),
                'explain': html.escape(explain, quote=False)
            })
            body = content.encode('UTF-8', 'replace')
            self.send_header("Content-Type", self.error_content_type)
            self.send_header('Content-Length', str(len(body)))
        self.end_headers()

        if self.command != 'HEAD' and body:
            self.wfile.write(body)

    def send_response(self, code, message=None):
        """Add the response header to the headers buffer and log the
        response code.

        Also send two standard headers with the server software
        version and the current date.

        """
        self.log_request(code)
        self.send_response_only(code, message)
        self.send_header('Server', self.version_string())
        self.send_header('Date', self.date_time_string())

    def send_response_only(self, code, message=None):
        """Send the response header only."""
        if self.request_version != 'HTTP/0.9':
            if message is None:
                if code in self.responses:
                    message = self.responses[code][0]
                else:
                    message = ''
            if not hasattr(self, '_headers_buffer'):
                self._headers_buffer = []
            self._headers_buffer.append(("%s %d %s\r\n" %
                    (self.protocol_version, code, message)).encode(
                        'latin-1', 'strict'))

    def send_header(self, keyword, value):
        """Send a MIME header to the headers buffer."""
        if self.request_version != 'HTTP/0.9':
            if not hasattr(self, '_headers_buffer'):
                self._headers_buffer = []
            self._headers_buffer.append(
                ("%s: %s\r\n" % (keyword, value)).encode('latin-1', 'strict'))

        if keyword.lower() == 'connection':
            if value.lower() == 'close':
                self.close_connection = True
            elif value.lower() == 'keep-alive':
                self.close_connection = False

    def end_headers(self):
        """Send the blank line ending the MIME headers."""
        if self.request_version != 'HTTP/0.9':
            self._headers_buffer.append(b"\r\n")
            self.flush_headers()

    def flush_headers(self):
        if hasattr(self, '_headers_buffer'):
            self.wfile.write(b"".join(self._headers_buffer))
            self._headers_buffer = []

    def log_request(self, code='-', size='-'):
        """Log an accepted request.

        This is called by send_response().

        """
        if isinstance(code, HTTPStatus):
            code = code.value
        self.log_message('"%s" %s %s',
                         self.requestline, str(code), str(size))

    def log_error(self, format, *args):
        """Log an error.

        This is called when a request cannot be fulfilled.  By
        default it passes the message on to log_message().

        Arguments are the same as for log_message().

        XXX This should go to the separate error log.

        """

        self.log_message(format, *args)

    # https://en.wikipedia.org/wiki/List_of_Unicode_characters#Control_codes
    _control_char_table = str.maketrans(
            {c: fr'\x{c:02x}' for c in itertools.chain(range(0x20), range(0x7f,0xa0))})
    _control_char_table[ord('\\')] = r'\\'

    def log_message(self, format, *args):
        """Log an arbitrary message.

        This is used by all other logging functions.  Override
        it if you have specific logging wishes.

        The first argument, FORMAT, is a format string for the
        message to be logged.  If the format string contains
        any % escapes requiring parameters, they should be
        specified as subsequent arguments (it's just like
        printf!).

        The client ip and current date/time are prefixed to
        every message.

        Unicode control characters are replaced with escaped hex
        before writing the output to stderr.

        """

        message = format % args
        sys.stderr.write("%s - - [%s] %s\n" %
                         (self.address_string(),
                          self.log_date_time_string(),
                          message.translate(self._control_char_table)))

    def version_string(self):
        """Return the server software version string."""
        return self.server_version + ' ' + self.sys_version

    def date_time_string(self, timestamp=None):
        """Return the current date and time formatted for a message header."""
        if timestamp is None:
            timestamp = time.time()
        return email.utils.formatdate(timestamp, usegmt=True)

    def log_date_time_string(self):
        """Return the current time formatted for logging."""
        now = time.time()
        year, month, day, hh, mm, ss, x, y, z = time.localtime(now)
        s = "%02d/%3s/%04d %02d:%02d:%02d" % (
                day, self.monthname[month], year, hh, mm, ss)
        return s

    weekdayname = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

    monthname = [None,
                 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

    def address_string(self):
        """Return the client address."""

        return self.client_address[0]

    # Essentially static class variables

    # The version of the HTTP protocol we support.
    # Set this to HTTP/1.1 to enable automatic keepalive
    protocol_version = "HTTP/1.0"

    # MessageClass used to parse headers
    MessageClass = http.client.HTTPMessage

    # hack to maintain backwards compatibility
    responses = {
        v: (v.phrase, v.description)
        for v in HTTPStatus.__members__.values()
    }


class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

    """Simple HTTP request handler with GET and HEAD commands.

    This serves files from the current directory and any of its
    subdirectories.  The MIME type for files is determined by
    calling the .guess_type() method.

    The GET and HEAD requests are identical except that the HEAD
    request omits the actual contents of the file.

    """

    server_version = "SimpleHTTP/" + __version__

    def __init__(self, *args, directory=None, **kwargs):
        if directory is None:
            directory = os.getcwd()
        self.directory = directory
        super().__init__(*args, **kwargs)

    def do_GET(self):
        """Serve a GET request."""
        f = self.send_head()
        if f:
            try:
                self.copyfile(f, self.wfile)
            finally:
                f.close()

    def do_HEAD(self):
        """Serve a HEAD request."""
        f = self.send_head()
        if f:
            f.close()

    def send_head(self):
        """Common code for GET and HEAD commands.

        This sends the response code and MIME headers.

        Return value is either a file object (which has to be copied
        to the outputfile by the caller unless the command was HEAD,
        and must be closed by the caller under all circumstances), or
        None, in which case the caller has nothing further to do.

        """
        path = self.translate_path(self.path)
        f = None
        if os.path.isdir(path):
            parts = urllib.parse.urlsplit(self.path)
            if not parts.path.endswith('/'):
                # redirect browser - doing basically what apache does
                self.send_response(HTTPStatus.MOVED_PERMANENTLY)
                new_parts = (parts[0], parts[1], parts[2] + '/',
                             parts[3], parts[4])
                new_url = urllib.parse.urlunsplit(new_parts)
                self.send_header("Location", new_url)
                self.end_headers()
                return None
            for index in "index.html", "index.htm":
                index = os.path.join(path, index)
                if os.path.exists(index):
                    path = index
                    break
            else:
                return self.list_directory(path)
        ctype = self.guess_type(path)
        # check for trailing "/" which should return 404. See Issue17324
        # The test for this was added in test_httpserver.py
        # However, some OS platforms accept a trailingSlash as a filename
        # See discussion on python-dev and Issue34711 regarding
        # parseing and rejection of filenames with a trailing slash
        if path.endswith("/"):
            self.send_error(HTTPStatus.NOT_FOUND, "File not found")
            return None
        try:
            f = open(path, 'rb')
        except OSError:
            self.send_error(HTTPStatus.NOT_FOUND, "File not found")
            return None

        try:
            fs = os.fstat(f.fileno())
            # Use browser cache if possible
            if ("If-Modified-Since" in self.headers
                    and "If-None-Match" not in self.headers):
                # compare If-Modified-Since and time of last file modification
                try:
                    ims = email.utils.parsedate_to_datetime(
                        self.headers["If-Modified-Since"])
                except (TypeError, IndexError, OverflowError, ValueError):
                    # ignore ill-formed values
                    pass
                else:
                    if ims.tzinfo is None:
                        # obsolete format with no timezone, cf.
                        # https://tools.ietf.org/html/rfc7231#section-7.1.1.1
                        ims = ims.replace(tzinfo=datetime.timezone.utc)
                    if ims.tzinfo is datetime.timezone.utc:
                        # compare to UTC datetime of last modification
                        last_modif = datetime.datetime.fromtimestamp(
                            fs.st_mtime, datetime.timezone.utc)
                        # remove microseconds, like in If-Modified-Since
                        last_modif = last_modif.replace(microsecond=0)

                        if last_modif <= ims:
                            self.send_response(HTTPStatus.NOT_MODIFIED)
                            self.end_headers()
                            f.close()
                            return None

            self.send_response(HTTPStatus.OK)
            self.send_header("Content-type", ctype)
            self.send_header("Content-Length", str(fs[6]))
            self.send_header("Last-Modified",
                self.date_time_string(fs.st_mtime))
            self.end_headers()
            return f
        except:
            f.close()
            raise

    def list_directory(self, path):
        """Helper to produce a directory listing (absent index.html).

        Return value is either a file object, or None (indicating an
        error).  In either case, the headers are sent, making the
        interface the same as for send_head().

        """
        try:
            list = os.listdir(path)
        except OSError:
            self.send_error(
                HTTPStatus.NOT_FOUND,
                "No permission to list directory")
            return None
        list.sort(key=lambda a: a.lower())
        r = []
        try:
            displaypath = urllib.parse.unquote(self.path,
                                               errors='surrogatepass')
        except UnicodeDecodeError:
            displaypath = urllib.parse.unquote(self.path)
        displaypath = html.escape(displaypath, quote=False)
        enc = sys.getfilesystemencoding()
        title = 'Directory listing for %s' % displaypath
        r.append('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" '
                 '"http://www.w3.org/TR/html4/strict.dtd">')
        r.append('<html>\n<head>')
        r.append('<meta http-equiv="Content-Type" '
                 'content="text/html; charset=%s">' % enc)
        r.append('<title>%s</title>\n</head>' % title)
        r.append('<body>\n<h1>%s</h1>' % title)
        r.append('<hr>\n<ul>')
        for name in list:
            fullname = os.path.join(path, name)
            displayname = linkname = name
            # Append / for directories or @ for symbolic links
            if os.path.isdir(fullname):
                displayname = name + "/"
                linkname = name + "/"
            if os.path.islink(fullname):
                displayname = name + "@"
                # Note: a link to a directory displays with @ and links with /
            r.append('<li><a href="%s">%s</a></li>'
                    % (urllib.parse.quote(linkname,
                                          errors='surrogatepass'),
                       html.escape(displayname, quote=False)))
        r.append('</ul>\n<hr>\n</body>\n</html>\n')
        encoded = '\n'.join(r).encode(enc, 'surrogateescape')
        f = io.BytesIO()
        f.write(encoded)
        f.seek(0)
        self.send_response(HTTPStatus.OK)
        self.send_header("Content-type", "text/html; charset=%s" % enc)
        self.send_header("Content-Length", str(len(encoded)))
        self.end_headers()
        return f

    def translate_path(self, path):
        """Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        """
        # abandon query parameters
        path = path.split('?',1)[0]
        path = path.split('#',1)[0]
        # Don't forget explicit trailing slash when normalizing. Issue17324
        trailing_slash = path.rstrip().endswith('/')
        try:
            path = urllib.parse.unquote(path, errors='surrogatepass')
        except UnicodeDecodeError:
            path = urllib.parse.unquote(path)
        path = posixpath.normpath(path)
        words = path.split('/')
        words = filter(None, words)
        path = self.directory
        for word in words:
            if os.path.dirname(word) or word in (os.curdir, os.pardir):
                # Ignore components that are not a simple file/directory name
                continue
            path = os.path.join(path, word)
        if trailing_slash:
            path += '/'
        return path

    def copyfile(self, source, outputfile):
        """Copy all data between two file objects.

        The SOURCE argument is a file object open for reading
        (or anything with a read() method) and the DESTINATION
        argument is a file object open for writing (or
        anything with a write() method).

        The only reason for overriding this would be to change
        the block size or perhaps to replace newlines by CRLF
        -- note however that this the default server uses this
        to copy binary data as well.

        """
        shutil.copyfileobj(source, outputfile)

    def guess_type(self, path):
        """Guess the type of a file.

        Argument is a PATH (a filename).

        Return value is a string of the form type/subtype,
        usable for a MIME Content-type header.

        The default implementation looks the file's extension
        up in the table self.extensions_map, using application/octet-stream
        as a default; however it would be permissible (if
        slow) to look inside the data to make a better guess.

        """

        base, ext = posixpath.splitext(path)
        if ext in self.extensions_map:
            return self.extensions_map[ext]
        ext = ext.lower()
        if ext in self.extensions_map:
            return self.extensions_map[ext]
        else:
            return self.extensions_map['']

    if not mimetypes.inited:
        mimetypes.init() # try to read system mime.types
    extensions_map = mimetypes.types_map.copy()
    extensions_map.update({
        '': 'application/octet-stream', # Default
        '.py': 'text/plain',
        '.c': 'text/plain',
        '.h': 'text/plain',
        })


# Utilities for CGIHTTPRequestHandler

def _url_collapse_path(path):
    """
    Given a URL path, remove extra '/'s and '.' path elements and collapse
    any '..' references and returns a collapsed path.

    Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
    The utility of this function is limited to is_cgi method and helps
    preventing some security attacks.

    Returns: The reconstituted URL, which will always start with a '/'.

    Raises: IndexError if too many '..' occur within the path.

    """
    # Query component should not be involved.
    path, _, query = path.partition('?')
    path = urllib.parse.unquote(path)

    # Similar to os.path.split(os.path.normpath(path)) but specific to URL
    # path semantics rather than local operating system semantics.
    path_parts = path.split('/')
    head_parts = []
    for part in path_parts[:-1]:
        if part == '..':
            head_parts.pop() # IndexError if more '..' than prior parts
        elif part and part != '.':
            head_parts.append( part )
    if path_parts:
        tail_part = path_parts.pop()
        if tail_part:
            if tail_part == '..':
                head_parts.pop()
                tail_part = ''
            elif tail_part == '.':
                tail_part = ''
    else:
        tail_part = ''

    if query:
        tail_part = '?'.join((tail_part, query))

    splitpath = ('/' + '/'.join(head_parts), tail_part)
    collapsed_path = "/".join(splitpath)

    return collapsed_path



nobody = None

def nobody_uid():
    """Internal routine to get nobody's uid"""
    global nobody
    if nobody:
        return nobody
    try:
        import pwd
    except ImportError:
        return -1
    try:
        nobody = pwd.getpwnam('nobody')[2]
    except KeyError:
        nobody = 1 + max(x[2] for x in pwd.getpwall())
    return nobody


def executable(path):
    """Test for executable file."""
    return os.access(path, os.X_OK)


class CGIHTTPRequestHandler(SimpleHTTPRequestHandler):

    """Complete HTTP server with GET, HEAD and POST commands.

    GET and HEAD also support running CGI scripts.

    The POST command is *only* implemented for CGI scripts.

    """

    # Determine platform specifics
    have_fork = hasattr(os, 'fork')

    # Make rfile unbuffered -- we need to read one line and then pass
    # the rest to a subprocess, so we can't use buffered input.
    rbufsize = 0

    def do_POST(self):
        """Serve a POST request.

        This is only implemented for CGI scripts.

        """

        if self.is_cgi():
            self.run_cgi()
        else:
            self.send_error(
                HTTPStatus.NOT_IMPLEMENTED,
                "Can only POST to CGI scripts")

    def send_head(self):
        """Version of send_head that support CGI scripts"""
        if self.is_cgi():
            return self.run_cgi()
        else:
            return SimpleHTTPRequestHandler.send_head(self)

    def is_cgi(self):
        """Test whether self.path corresponds to a CGI script.

        Returns True and updates the cgi_info attribute to the tuple
        (dir, rest) if self.path requires running a CGI script.
        Returns False otherwise.

        If any exception is raised, the caller should assume that
        self.path was rejected as invalid and act accordingly.

        The default implementation tests whether the normalized url
        path begins with one of the strings in self.cgi_directories
        (and the next character is a '/' or the end of the string).

        """
        collapsed_path = _url_collapse_path(self.path)
        dir_sep = collapsed_path.find('/', 1)
        head, tail = collapsed_path[:dir_sep], collapsed_path[dir_sep+1:]
        if head in self.cgi_directories:
            self.cgi_info = head, tail
            return True
        return False


    cgi_directories = ['/cgi-bin', '/htbin']

    def is_executable(self, path):
        """Test whether argument path is an executable file."""
        return executable(path)

    def is_python(self, path):
        """Test whether argument path is a Python script."""
        head, tail = os.path.splitext(path)
        return tail.lower() in (".py", ".pyw")

    def run_cgi(self):
        """Execute a CGI script."""
        dir, rest = self.cgi_info
        path = dir + '/' + rest
        i = path.find('/', len(dir)+1)
        while i >= 0:
            nextdir = path[:i]
            nextrest = path[i+1:]

            scriptdir = self.translate_path(nextdir)
            if os.path.isdir(scriptdir):
                dir, rest = nextdir, nextrest
                i = path.find('/', len(dir)+1)
            else:
                break

        # find an explicit query string, if present.
        rest, _, query = rest.partition('?')

        # dissect the part after the directory name into a script name &
        # a possible additional path, to be stored in PATH_INFO.
        i = rest.find('/')
        if i >= 0:
            script, rest = rest[:i], rest[i:]
        else:
            script, rest = rest, ''

        scriptname = dir + '/' + script
        scriptfile = self.translate_path(scriptname)
        if not os.path.exists(scriptfile):
            self.send_error(
                HTTPStatus.NOT_FOUND,
                "No such CGI script (%r)" % scriptname)
            return
        if not os.path.isfile(scriptfile):
            self.send_error(
                HTTPStatus.FORBIDDEN,
                "CGI script is not a plain file (%r)" % scriptname)
            return
        ispy = self.is_python(scriptname)
        if self.have_fork or not ispy:
            if not self.is_executable(scriptfile):
                self.send_error(
                    HTTPStatus.FORBIDDEN,
                    "CGI script is not executable (%r)" % scriptname)
                return

        # Reference: http://hoohoo.ncsa.uiuc.edu/cgi/env.html
        # XXX Much of the following could be prepared ahead of time!
        env = copy.deepcopy(os.environ)
        env['SERVER_SOFTWARE'] = self.version_string()
        env['SERVER_NAME'] = self.server.server_name
        env['GATEWAY_INTERFACE'] = 'CGI/1.1'
        env['SERVER_PROTOCOL'] = self.protocol_version
        env['SERVER_PORT'] = str(self.server.server_port)
        env['REQUEST_METHOD'] = self.command
        uqrest = urllib.parse.unquote(rest)
        env['PATH_INFO'] = uqrest
        env['PATH_TRANSLATED'] = self.translate_path(uqrest)
        env['SCRIPT_NAME'] = scriptname
        if query:
            env['QUERY_STRING'] = query
        env['REMOTE_ADDR'] = self.client_address[0]
        authorization = self.headers.get("authorization")
        if authorization:
            authorization = authorization.split()
            if len(authorization) == 2:
                import base64, binascii
                env['AUTH_TYPE'] = authorization[0]
                if authorization[0].lower() == "basic":
                    try:
                        authorization = authorization[1].encode('ascii')
                        authorization = base64.decodebytes(authorization).\
                                        decode('ascii')
                    except (binascii.Error, UnicodeError):
                        pass
                    else:
                        authorization = authorization.split(':')
                        if len(authorization) == 2:
                            env['REMOTE_USER'] = authorization[0]
        # XXX REMOTE_IDENT
        if self.headers.get('content-type') is None:
            env['CONTENT_TYPE'] = self.headers.get_content_type()
        else:
            env['CONTENT_TYPE'] = self.headers['content-type']
        length = self.headers.get('content-length')
        if length:
            env['CONTENT_LENGTH'] = length
        referer = self.headers.get('referer')
        if referer:
            env['HTTP_REFERER'] = referer
        accept = []
        for line in self.headers.getallmatchingheaders('accept'):
            if line[:1] in "\t\n\r ":
                accept.append(line.strip())
            else:
                accept = accept + line[7:].split(',')
        env['HTTP_ACCEPT'] = ','.join(accept)
        ua = self.headers.get('user-agent')
        if ua:
            env['HTTP_USER_AGENT'] = ua
        co = filter(None, self.headers.get_all('cookie', []))
        cookie_str = ', '.join(co)
        if cookie_str:
            env['HTTP_COOKIE'] = cookie_str
        # XXX Other HTTP_* headers
        # Since we're setting the env in the parent, provide empty
        # values to override previously set values
        for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH',
                  'HTTP_USER_AGENT', 'HTTP_COOKIE', 'HTTP_REFERER'):
            env.setdefault(k, "")

        self.send_response(HTTPStatus.OK, "Script output follows")
        self.flush_headers()

        decoded_query = query.replace('+', ' ')

        if self.have_fork:
            # Unix -- fork as we should
            args = [script]
            if '=' not in decoded_query:
                args.append(decoded_query)
            nobody = nobody_uid()
            self.wfile.flush() # Always flush before forking
            pid = os.fork()
            if pid != 0:
                # Parent
                pid, sts = os.waitpid(pid, 0)
                # throw away additional data [see bug #427345]
                while select.select([self.rfile], [], [], 0)[0]:
                    if not self.rfile.read(1):
                        break
                if sts:
                    self.log_error("CGI script exit status %#x", sts)
                return
            # Child
            try:
                try:
                    os.setuid(nobody)
                except OSError:
                    pass
                os.dup2(self.rfile.fileno(), 0)
                os.dup2(self.wfile.fileno(), 1)
                os.execve(scriptfile, args, env)
            except:
                self.server.handle_error(self.request, self.client_address)
                os._exit(127)

        else:
            # Non-Unix -- use subprocess
            import subprocess
            cmdline = [scriptfile]
            if self.is_python(scriptfile):
                interp = sys.executable
                if interp.lower().endswith("w.exe"):
                    # On Windows, use python.exe, not pythonw.exe
                    interp = interp[:-5] + interp[-4:]
                cmdline = [interp, '-u'] + cmdline
            if '=' not in query:
                cmdline.append(query)
            self.log_message("command: %s", subprocess.list2cmdline(cmdline))
            try:
                nbytes = int(length)
            except (TypeError, ValueError):
                nbytes = 0
            p = subprocess.Popen(cmdline,
                                 stdin=subprocess.PIPE,
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE,
                                 env = env
                                 )
            if self.command.lower() == "post" and nbytes > 0:
                data = self.rfile.read(nbytes)
            else:
                data = None
            # throw away additional data [see bug #427345]
            while select.select([self.rfile._sock], [], [], 0)[0]:
                if not self.rfile._sock.recv(1):
                    break
            stdout, stderr = p.communicate(data)
            self.wfile.write(stdout)
            if stderr:
                self.log_error('%s', stderr)
            p.stderr.close()
            p.stdout.close()
            status = p.returncode
            if status:
                self.log_error("CGI script exit status %#x", status)
            else:
                self.log_message("CGI script exited OK")


def _get_best_family(*address):
    infos = socket.getaddrinfo(
        *address,
        type=socket.SOCK_STREAM,
        flags=socket.AI_PASSIVE,
    )
    family, type, proto, canonname, sockaddr = next(iter(infos))
    return family, sockaddr


def test(HandlerClass=BaseHTTPRequestHandler,
         ServerClass=ThreadingHTTPServer,
         protocol="HTTP/1.0", port=8000, bind=None):
    """Test the HTTP request handler class.

    This runs an HTTP server on port 8000 (or the port argument).

    """
    ServerClass.address_family, addr = _get_best_family(bind, port)

    HandlerClass.protocol_version = protocol
    with ServerClass(addr, HandlerClass) as httpd:
        host, port = httpd.socket.getsockname()[:2]
        url_host = f'[{host}]' if ':' in host else host
        print(
            f"Serving HTTP on {host} port {port} "
            f"(http://{url_host}:{port}/) ..."
        )
        try:
            httpd.serve_forever()
        except KeyboardInterrupt:
            print("\nKeyboard interrupt received, exiting.")
            sys.exit(0)

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument('--cgi', action='store_true',
                       help='Run as CGI Server')
    parser.add_argument('--bind', '-b', metavar='ADDRESS',
                        help='Specify alternate bind address '
                             '[default: all interfaces]')
    parser.add_argument('--directory', '-d', default=os.getcwd(),
                        help='Specify alternative directory '
                        '[default:current directory]')
    parser.add_argument('port', action='store',
                        default=8000, type=int,
                        nargs='?',
                        help='Specify alternate port [default: 8000]')
    args = parser.parse_args()
    if args.cgi:
        handler_class = CGIHTTPRequestHandler
    else:
        handler_class = partial(SimpleHTTPRequestHandler,
                                directory=args.directory)

    # ensure dual-stack is not disabled; ref #38907
    class DualStackServer(ThreadingHTTPServer):
        def server_bind(self):
            # suppress exception when protocol is IPv4
            with contextlib.suppress(Exception):
                self.socket.setsockopt(
                    socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
            return super().server_bind()

    test(
        HandlerClass=handler_class,
        ServerClass=DualStackServer,
        port=args.port,
        bind=args.bind,
    )
__init__.py000064400000014352150532417300006662 0ustar00from enum import IntEnum

__all__ = ['HTTPStatus']

class HTTPStatus(IntEnum):
    """HTTP status codes and reason phrases

    Status codes from the following RFCs are all observed:

        * RFC 7231: Hypertext Transfer Protocol (HTTP/1.1), obsoletes 2616
        * RFC 6585: Additional HTTP Status Codes
        * RFC 3229: Delta encoding in HTTP
        * RFC 4918: HTTP Extensions for WebDAV, obsoletes 2518
        * RFC 5842: Binding Extensions to WebDAV
        * RFC 7238: Permanent Redirect
        * RFC 2295: Transparent Content Negotiation in HTTP
        * RFC 2774: An HTTP Extension Framework
        * RFC 7725: An HTTP Status Code to Report Legal Obstacles
        * RFC 7540: Hypertext Transfer Protocol Version 2 (HTTP/2)
    """
    def __new__(cls, value, phrase, description=''):
        obj = int.__new__(cls, value)
        obj._value_ = value

        obj.phrase = phrase
        obj.description = description
        return obj

    # informational
    CONTINUE = 100, 'Continue', 'Request received, please continue'
    SWITCHING_PROTOCOLS = (101, 'Switching Protocols',
            'Switching to new protocol; obey Upgrade header')
    PROCESSING = 102, 'Processing'

    # success
    OK = 200, 'OK', 'Request fulfilled, document follows'
    CREATED = 201, 'Created', 'Document created, URL follows'
    ACCEPTED = (202, 'Accepted',
        'Request accepted, processing continues off-line')
    NON_AUTHORITATIVE_INFORMATION = (203,
        'Non-Authoritative Information', 'Request fulfilled from cache')
    NO_CONTENT = 204, 'No Content', 'Request fulfilled, nothing follows'
    RESET_CONTENT = 205, 'Reset Content', 'Clear input form for further input'
    PARTIAL_CONTENT = 206, 'Partial Content', 'Partial content follows'
    MULTI_STATUS = 207, 'Multi-Status'
    ALREADY_REPORTED = 208, 'Already Reported'
    IM_USED = 226, 'IM Used'

    # redirection
    MULTIPLE_CHOICES = (300, 'Multiple Choices',
        'Object has several resources -- see URI list')
    MOVED_PERMANENTLY = (301, 'Moved Permanently',
        'Object moved permanently -- see URI list')
    FOUND = 302, 'Found', 'Object moved temporarily -- see URI list'
    SEE_OTHER = 303, 'See Other', 'Object moved -- see Method and URL list'
    NOT_MODIFIED = (304, 'Not Modified',
        'Document has not changed since given time')
    USE_PROXY = (305, 'Use Proxy',
        'You must use proxy specified in Location to access this resource')
    TEMPORARY_REDIRECT = (307, 'Temporary Redirect',
        'Object moved temporarily -- see URI list')
    PERMANENT_REDIRECT = (308, 'Permanent Redirect',
        'Object moved permanently -- see URI list')

    # client error
    BAD_REQUEST = (400, 'Bad Request',
        'Bad request syntax or unsupported method')
    UNAUTHORIZED = (401, 'Unauthorized',
        'No permission -- see authorization schemes')
    PAYMENT_REQUIRED = (402, 'Payment Required',
        'No payment -- see charging schemes')
    FORBIDDEN = (403, 'Forbidden',
        'Request forbidden -- authorization will not help')
    NOT_FOUND = (404, 'Not Found',
        'Nothing matches the given URI')
    METHOD_NOT_ALLOWED = (405, 'Method Not Allowed',
        'Specified method is invalid for this resource')
    NOT_ACCEPTABLE = (406, 'Not Acceptable',
        'URI not available in preferred format')
    PROXY_AUTHENTICATION_REQUIRED = (407,
        'Proxy Authentication Required',
        'You must authenticate with this proxy before proceeding')
    REQUEST_TIMEOUT = (408, 'Request Timeout',
        'Request timed out; try again later')
    CONFLICT = 409, 'Conflict', 'Request conflict'
    GONE = (410, 'Gone',
        'URI no longer exists and has been permanently removed')
    LENGTH_REQUIRED = (411, 'Length Required',
        'Client must specify Content-Length')
    PRECONDITION_FAILED = (412, 'Precondition Failed',
        'Precondition in headers is false')
    REQUEST_ENTITY_TOO_LARGE = (413, 'Request Entity Too Large',
        'Entity is too large')
    REQUEST_URI_TOO_LONG = (414, 'Request-URI Too Long',
        'URI is too long')
    UNSUPPORTED_MEDIA_TYPE = (415, 'Unsupported Media Type',
        'Entity body in unsupported format')
    REQUESTED_RANGE_NOT_SATISFIABLE = (416,
        'Requested Range Not Satisfiable',
        'Cannot satisfy request range')
    EXPECTATION_FAILED = (417, 'Expectation Failed',
        'Expect condition could not be satisfied')
    MISDIRECTED_REQUEST = (421, 'Misdirected Request',
        'Server is not able to produce a response')
    UNPROCESSABLE_ENTITY = 422, 'Unprocessable Entity'
    LOCKED = 423, 'Locked'
    FAILED_DEPENDENCY = 424, 'Failed Dependency'
    UPGRADE_REQUIRED = 426, 'Upgrade Required'
    PRECONDITION_REQUIRED = (428, 'Precondition Required',
        'The origin server requires the request to be conditional')
    TOO_MANY_REQUESTS = (429, 'Too Many Requests',
        'The user has sent too many requests in '
        'a given amount of time ("rate limiting")')
    REQUEST_HEADER_FIELDS_TOO_LARGE = (431,
        'Request Header Fields Too Large',
        'The server is unwilling to process the request because its header '
        'fields are too large')
    UNAVAILABLE_FOR_LEGAL_REASONS = (451,
        'Unavailable For Legal Reasons',
        'The server is denying access to the '
        'resource as a consequence of a legal demand')

    # server errors
    INTERNAL_SERVER_ERROR = (500, 'Internal Server Error',
        'Server got itself in trouble')
    NOT_IMPLEMENTED = (501, 'Not Implemented',
        'Server does not support this operation')
    BAD_GATEWAY = (502, 'Bad Gateway',
        'Invalid responses from another server/proxy')
    SERVICE_UNAVAILABLE = (503, 'Service Unavailable',
        'The server cannot process the request due to a high load')
    GATEWAY_TIMEOUT = (504, 'Gateway Timeout',
        'The gateway server did not receive a timely response')
    HTTP_VERSION_NOT_SUPPORTED = (505, 'HTTP Version Not Supported',
        'Cannot fulfill request')
    VARIANT_ALSO_NEGOTIATES = 506, 'Variant Also Negotiates'
    INSUFFICIENT_STORAGE = 507, 'Insufficient Storage'
    LOOP_DETECTED = 508, 'Loop Detected'
    NOT_EXTENDED = 510, 'Not Extended'
    NETWORK_AUTHENTICATION_REQUIRED = (511,
        'Network Authentication Required',
        'The client needs to authenticate to gain network access')
__pycache__/__init__.cpython-36.opt-1.pyc000064400000014601150532432170014104 0ustar003


 \A�@s&ddlmZdgZGdd�de�ZdS)�)�IntEnum�
HTTPStatusc@s�eZdZdZd�dd�Zd�Zd�Zd�Zd�Zd�Z	d�Z
d�Zd�Zd�Z
d�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Z d�Z!d�Z"d�Z#d�Z$d�Z%d�Z&d�Z'd�Z(d�Z)d�Z*d�Z+d�Z,d�Z-d�Z.d�Z/d�Z0d�Z1d�Z2d�Z3d�Z4d�Z5d�Z6d�Z7d�Z8d�Z9d�Z:d�Z;d�Z<d�Z=d�S)�raHTTP status codes and reason phrases

    Status codes from the following RFCs are all observed:

        * RFC 7231: Hypertext Transfer Protocol (HTTP/1.1), obsoletes 2616
        * RFC 6585: Additional HTTP Status Codes
        * RFC 3229: Delta encoding in HTTP
        * RFC 4918: HTTP Extensions for WebDAV, obsoletes 2518
        * RFC 5842: Binding Extensions to WebDAV
        * RFC 7238: Permanent Redirect
        * RFC 2295: Transparent Content Negotiation in HTTP
        * RFC 2774: An HTTP Extension Framework
    �cCs"tj||�}||_||_||_|S)N)�int�__new__�_value_�phrase�description)�cls�valuerr	�obj�r
�%/usr/lib64/python3.6/http/__init__.pyrs
zHTTPStatus.__new__�d�Continue�!Request received, please continue�e�Switching Protocols�.Switching to new protocol; obey Upgrade header�f�
Processing���OK�#Request fulfilled, document follows���Created�Document created, URL follows���Accepted�/Request accepted, processing continues off-line���Non-Authoritative Information�Request fulfilled from cache���
No Content�"Request fulfilled, nothing follows���
Reset Content�"Clear input form for further input���Partial Content�Partial content follows���Multi-Status���Already Reported���IM Used�,�Multiple Choices�,Object has several resources -- see URI list�-�Moved Permanently�(Object moved permanently -- see URI list�.�Found�(Object moved temporarily -- see URI list�/�	See Other�'Object moved -- see Method and URL list�0�Not Modified�)Document has not changed since given time�1�	Use Proxy�@You must use proxy specified in Location to access this resource�3�Temporary Redirect�4�Permanent Redirect��Bad Request�(Bad request syntax or unsupported method��Unauthorized�*No permission -- see authorization schemes��Payment Required�"No payment -- see charging schemes��	Forbidden�0Request forbidden -- authorization will not help��	Not Found�Nothing matches the given URI��Method Not Allowed�-Specified method is invalid for this resource��Not Acceptable�%URI not available in preferred format��Proxy Authentication Required�7You must authenticate with this proxy before proceeding��Request Timeout�"Request timed out; try again later��Conflict�Request conflict��Gone�5URI no longer exists and has been permanently removed��Length Required�"Client must specify Content-Length��Precondition Failed� Precondition in headers is false��Request Entity Too Large�Entity is too large��Request-URI Too Long�URI is too long��Unsupported Media Type�!Entity body in unsupported format��Requested Range Not Satisfiable�Cannot satisfy request range��Expectation Failed�'Expect condition could not be satisfied��Unprocessable Entity��Locked��Failed Dependency��Upgrade Required��Precondition Required�8The origin server requires the request to be conditional��Too Many Requests�OThe user has sent too many requests in a given amount of time ("rate limiting")��Request Header Fields Too Large�VThe server is unwilling to process the request because its header fields are too large���Internal Server Error�Server got itself in trouble��Not Implemented�&Server does not support this operation��Bad Gateway�+Invalid responses from another server/proxy��Service Unavailable�8The server cannot process the request due to a high load��Gateway Timeout�4The gateway server did not receive a timely response��HTTP Version Not Supported�Cannot fulfill request��Variant Also Negotiates��Insufficient Storage��
Loop Detected��Not Extended��Network Authentication Required�7The client needs to authenticate to gain network accessN)r)rrr)rrr)rr)rrr)rrr)rrr)r r!r")r#r$r%)r&r'r()r)r*r+)r,r-)r.r/)r0r1)r2r3r4)r5r6r7)r8r9r:)r;r<r=)r>r?r@)rArBrC)rDrEr:)rFrGr:)rHrIrJ)rKrLrM)rNrOrP)rQrRrS)rTrUrV)rWrXrY)rZr[r\)r]r^r_)r`rarb)rcrdre)rfrgrh)rirjrk)rlrmrn)rorprq)rrrsrt)rurvrw)rxryrz)r{r|r})r~r)r�r�)r�r�)r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�)r�r�)r�r�)r�r�)r�r�r�)>�__name__�
__module__�__qualname__�__doc__rZCONTINUEZSWITCHING_PROTOCOLSZ
PROCESSINGrZCREATEDZACCEPTEDZNON_AUTHORITATIVE_INFORMATIONZ
NO_CONTENTZ
RESET_CONTENTZPARTIAL_CONTENTZMULTI_STATUSZALREADY_REPORTEDZIM_USEDZMULTIPLE_CHOICESZMOVED_PERMANENTLYZFOUNDZ	SEE_OTHERZNOT_MODIFIEDZ	USE_PROXYZTEMPORARY_REDIRECTZPERMANENT_REDIRECTZBAD_REQUESTZUNAUTHORIZEDZPAYMENT_REQUIREDZ	FORBIDDENZ	NOT_FOUNDZMETHOD_NOT_ALLOWEDZNOT_ACCEPTABLEZPROXY_AUTHENTICATION_REQUIREDZREQUEST_TIMEOUTZCONFLICTZGONEZLENGTH_REQUIREDZPRECONDITION_FAILEDZREQUEST_ENTITY_TOO_LARGEZREQUEST_URI_TOO_LONGZUNSUPPORTED_MEDIA_TYPEZREQUESTED_RANGE_NOT_SATISFIABLEZEXPECTATION_FAILEDZUNPROCESSABLE_ENTITYZLOCKEDZFAILED_DEPENDENCYZUPGRADE_REQUIREDZPRECONDITION_REQUIREDZTOO_MANY_REQUESTSZREQUEST_HEADER_FIELDS_TOO_LARGEZINTERNAL_SERVER_ERRORZNOT_IMPLEMENTEDZBAD_GATEWAYZSERVICE_UNAVAILABLEZGATEWAY_TIMEOUTZHTTP_VERSION_NOT_SUPPORTEDZVARIANT_ALSO_NEGOTIATESZINSUFFICIENT_STORAGEZ
LOOP_DETECTEDZNOT_EXTENDEDZNETWORK_AUTHENTICATION_REQUIREDr
r
r
rrs�

	N)�enumr�__all__rr
r
r
r�<module>s__pycache__/cookiejar.cpython-36.opt-1.pyc000064400000151077150532432170014324 0ustar003

Ow�hr+�@s*dZddddddddgZd	d
lZd	d
lZd	d
lZd	d
lZd	d
lZd	d
lZyd	d
l	Z
Wnek
rpd	d
lZ
YnXd	d
l
Zd	dlmZdZd
ad
d�Zeejj�ZdZdd�ZdZdd�ZdddddddgZddddd d!d"d#d$d%d&d'gZgZxeD]Zej ej!��q�Wdud(d)�Z"dvd*d+�Z#d
d
d
d
d,�Z$ej%d-ej&�Z'd.d/�Z(d0d1�Z)ej%d2ej&�Z*ej%d3ej+ej&B�Z,ej%d4ej-ej&B�Z.d5d6�Z/ej%d7ej-ej&B�Z0d8d9�Z1d:d;�Z2ej%d<�Z3ej%d=�Z4ej%d>�Z5ej%d?�Z6d@dA�Z7ej%dB�Z8dCdD�Z9dEdF�Z:dGdH�Z;ej%dIej&�Z<dJdK�Z=dLdM�Z>dNdO�Z?dPdQ�Z@ej%dRej&�ZAdSdT�ZBdUdV�ZCdWdX�ZDdYdZ�ZEd[ZFej%d\�ZGd]d^�ZHd_d`�ZIdadb�ZJdcdd�ZKGded�d�ZLGdfd�d�ZMGdgd�deM�ZNdhdi�ZOdjdk�ZPGdldm�dm�ZQGdnd�d�ZRGdod�deS�ZTGdpd�deR�ZUdqdr�ZVGdsd�deU�ZWGdtd�deU�ZXd
S)wa�HTTP cookie handling for web clients.

This module has (now fairly distant) origins in Gisle Aas' Perl module
HTTP::Cookies, from the libwww-perl library.

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 BSDDBCookieJar and the MSIE* classes are not
distributed with the Python standard library, but are available from
http://wwwsearch.sf.net/):

                        CookieJar____
                        /     \      \
            FileCookieJar      \      \
             /    |   \         \      \
 MozillaCookieJar | LWPCookieJar \      \
                  |               |      \
                  |   ---MSIEBase |       \
                  |  /      |     |        \
                  | /   MSIEDBCookieJar BSDDBCookieJar
                  |/
               MSIECookieJar

�Cookie�	CookieJar�CookiePolicy�DefaultCookiePolicy�
FileCookieJar�LWPCookieJar�	LoadError�MozillaCookieJar�N)�timegmFcGs(tsdStsddl}|jd�atj|�S)Nr	zhttp.cookiejar)�debug�logger�loggingZ	getLogger)�argsr
�r�&/usr/lib64/python3.6/http/cookiejar.py�_debug.s
rzQa filename was not supplied (nor was the CookieJar instance initialised with one)cCsJddl}ddl}ddl}|j�}|jd|�|j�}|jd|dd�dS)Nr	zhttp.cookiejar bug!
%s�)�
stacklevel)�io�warnings�	traceback�StringIO�	print_exc�getvalue�warn)rrr�f�msgrrr�_warn_unhandled_exception<s
ri�cCs�|dd�\}}}}}}|tkr�d|ko2dknr�d|koJdknr�d|kobdknr�d|kozdknr�d|ko�dknr�t|�SdSdS)	N����r	��;�=)�
EPOCH_YEARr
)�tt�year�monthZmday�hour�min�secrrr�_timegmKs
8Hr,ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs@|dkrtjj�}ntjj|�}d|j|j|j|j|j|jfS)aHReturn a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like "YYYY-MM-DD hh:mm:ssZ",
    representing Universal Time (UTC, aka GMT).  An example of this format is:

    1994-11-24 08:49:37Z

    Nz%04d-%02d-%02d %02d:%02d:%02dZ)	�datetime�utcnow�utcfromtimestampr'r(�dayr)�minute�second)�t�dtrrr�	time2isozYs
r5cCsR|dkrtjj�}ntjj|�}dt|j�|jt|jd|j|j	|j
|jfS)z�Return a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like this:

    Wed, DD-Mon-YYYY HH:MM:SS GMT

    Nz#%s, %02d-%s-%04d %02d:%02d:%02d GMTr)r-r.r/�DAYSZweekdayr0�MONTHSr(r'r)r1r2)r3r4rrr�
time2netscapelsr8)ZGMT�UTCZUT�Zz^([-+])?(\d\d?):?(\d\d)?$cCsjd}|tkrd}nTtj|�}|rfdt|jd��}|jd�rR|dt|jd��}|jd�dkrf|}|S)Nr	ir��<r�-)�	UTC_ZONES�TIMEZONE_RE�search�int�group)�tz�offset�mrrr�offset_from_tz_string�s

rFc
Cs�t|�}|tjkrdSytj|j��d}WnXtk
r�yt|�}Wntk
r\dSXd|kopdknr||}ndSYnX|dkr�d}|dkr�d}|dkr�d}t|�}t|�}t|�}t|�}|dk�r0tjtj��d}|d}	|}
|||	}|	|
}	t	|	�dk�r0|	dk�r(|d}n|d}t
|||||||f�}|dk	�r�|dk�r^d}|j�}t|�}|dk�r|dS||}|S)Nrr r	i��d�2r9)
rAr-ZMAXYEAR�MONTHS_LOWER�index�lower�
ValueError�timeZ	localtime�absr,�upperrF)
r0�mon�yr�hrr*r+rCZimonZcur_yrrEZtmpr3rDrrr�	_str2time�sV







rSzV^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$z+^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*a�^
    (\d\d?)            # day
       (?:\s+|[-\/])
    (\w+)              # month
        (?:\s+|[-\/])
    (\d+)              # year
    (?:
          (?:\s+|:)    # separator before clock
       (\d\d?):(\d\d)  # hour:min
       (?::(\d\d))?    # optional seconds
    )?                 # optional clock
       \s*
    ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone
       \s*
    (?:\(\w+\))?       # ASCII representation of timezone in parens.
       \s*$cCs�tj|�}|rl|j�}tj|dj��d}t|d�|t|d�t|d�t|d�t|d�f}t|�S|j	�}t
jd|d�}dgd	\}}}}}}	}
tj|�}|dk	r�|j�\}}}}}}	}
ndSt
||||||	|
�S)
a�Returns time in seconds since epoch of time represented by a string.

    Return value is an integer.

    None is returned if the format of str is unrecognized, the time is outside
    the representable range, or the timezone string is not recognized.  If the
    string contains no timezone, UTC is assumed.

    The timezone in the string may be numerical (like "-0800" or "+0100") or a
    string timezone (like "UTC", "GMT", "BST" or "EST").  Currently, only the
    timezone strings equivalent to UTC (zero offset) are known to the function.

    The function loosely parses the following formats:

    Wed, 09 Feb 1994 22:23:32 GMT       -- HTTP format
    Tuesday, 08-Feb-94 14:15:29 GMT     -- old rfc850 HTTP format
    Tuesday, 08-Feb-1994 14:15:29 GMT   -- broken rfc850 HTTP format
    09 Feb 1994 22:23:32 GMT            -- HTTP format (no weekday)
    08-Feb-94 14:15:29 GMT              -- rfc850 format (no weekday)
    08-Feb-1994 14:15:29 GMT            -- broken rfc850 format (no weekday)

    The parser ignores leading and trailing whitespace.  The time may be
    absent.

    If the year is given with only 2 digits, the function will select the
    century that makes the year closest to the current date.

    rrr	r;���N�)�STRICT_DATE_REr@�groupsrIrJrKrA�floatr,�lstrip�
WEEKDAY_RE�sub�LOOSE_HTTP_DATE_RErS)�textrE�grPr&r0rQrRr*r+rCrrr�	http2time�s
"
raa�^
    (\d{4})              # year
       [-\/]?
    (\d\d?)              # numerical month
       [-\/]?
    (\d\d?)              # day
   (?:
         (?:\s+|[-:Tt])  # separator before clock
      (\d\d?):?(\d\d)    # hour:min
      (?::?(\d\d(?:\.\d*)?))?  # optional seconds (and fractional)
   )?                    # optional clock
      \s*
   ([-+]?\d\d?:?(:?\d\d)?
    |Z|z)?               # timezone  (Z is "zero meridian", i.e. GMT)
      \s*$c
Csd|j�}dgd\}}}}}}}tj|�}|dk	rL|j�\}}}}}}}}	ndSt|||||||�S)av
    As for http2time, but parses the ISO 8601 formats:

    1994-02-03 14:15:29 -0100    -- ISO 8601 format
    1994-02-03 14:15:29          -- zone is optional
    1994-02-03                   -- only date
    1994-02-03T14:15:29          -- Use T as separator
    19940203T141529Z             -- ISO 8601 compact format
    19940203                     -- only date

    NrW)r[�ISO_DATE_REr@rYrS)
r_r0rPrQrRr*r+rCrE�_rrr�iso2time's

rdcCs*|jd�\}}|jd|�|j|d�S)z)Return unmatched part of re.Match object.r	N)�span�string)�match�start�endrrr�	unmatchedHsrjz^\s*([^=\s;,]+)z&^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"z^\s*=\s*([^\s;,]*)z\\(.)c
Csg}�x|D]�}|}g}x�|r�tj|�}|r�t|�}|jd�}tj|�}|rlt|�}|jd�}tjd|�}n.tj|�}|r�t|�}|jd�}|j�}nd}|j	||f�q|j
�jd�r�|j
�dd�}|r�|j	|�g}qtj
dd|�\}}	|}qW|r|j	|�qW|S)amParse header values into a list of lists containing key,value pairs.

    The function knows how to deal with ",", ";" and "=" as well as quoted
    values after "=".  A list of space separated tokens are parsed as if they
    were separated by ";".

    If the header_values passed as argument contains multiple values, then they
    are treated as if they were a single value separated by comma ",".

    This means that this function is useful for parsing header fields that
    follow this syntax (BNF as from the HTTP/1.1 specification, but we relax
    the requirement for tokens).

      headers           = #header
      header            = (token | parameter) *( [";"] (token | parameter))

      token             = 1*<any CHAR except CTLs or separators>
      separators        = "(" | ")" | "<" | ">" | "@"
                        | "," | ";" | ":" | "\" | <">
                        | "/" | "[" | "]" | "?" | "="
                        | "{" | "}" | SP | HT

      quoted-string     = ( <"> *(qdtext | quoted-pair ) <"> )
      qdtext            = <any TEXT except <">>
      quoted-pair       = "\" CHAR

      parameter         = attribute "=" value
      attribute         = token
      value             = token | quoted-string

    Each header is represented by a list of key/value pairs.  The value for a
    simple token (not part of a parameter) is None.  Syntactically incorrect
    headers will not necessarily be parsed as you would want.

    This is easier to describe with some examples:

    >>> split_header_words(['foo="bar"; port="80,81"; discard, bar=baz'])
    [[('foo', 'bar'), ('port', '80,81'), ('discard', None)], [('bar', 'baz')]]
    >>> split_header_words(['text/html; charset="iso-8859-1"'])
    [[('text/html', None), ('charset', 'iso-8859-1')]]
    >>> split_header_words([r'Basic realm="\"foo\bar\""'])
    [[('Basic', None), ('realm', '"foobar"')]]

    rz\1N�,z^[=\s;]*rV)�HEADER_TOKEN_REr@rjrB�HEADER_QUOTED_VALUE_RE�HEADER_ESCAPE_REr]�HEADER_VALUE_RE�rstrip�appendr[�
startswith�re�subn)
Z
header_values�resultr_Z	orig_text�pairsrE�name�valueZnon_junkZ
nr_junk_charsrrr�split_header_wordsQs>.







ryz([\"\\])cCs�g}xt|D]l}g}xN|D]F\}}|dk	rTtjd|�sHtjd|�}d|}d||f}|j|�qW|r
|jdj|��q
Wdj|�S)a�Do the inverse (almost) of the conversion done by split_header_words.

    Takes a list of lists of (key, value) pairs and produces a single header
    value.  Attribute values are quoted if needed.

    >>> join_header_words([[("text/plain", None), ("charset", "iso-8859-1")]])
    'text/plain; charset="iso-8859-1"'
    >>> join_header_words([[("text/plain", None)], [("charset", "iso-8859-1")]])
    'text/plain, charset="iso-8859-1"'

    Nz^\w+$z\\\1z"%s"z%s=%sz; z, )rsr@�HEADER_JOIN_ESCAPE_REr]rq�join)Zlists�headersrv�attr�k�vrrr�join_header_words�s
r�cCs0|jd�r|dd�}|jd�r,|dd�}|S)N�"r���)rr�endswith)r_rrr�strip_quotes�s


r�cCsd}g}x�|D]�}g}d}x�t|jd	��D]�\}}|j�}|jd
�\}}	}
|j�}|sd|dkr*Pnq*|	rp|
j�nd}
|dkr�|j�}||kr�|}|dkr�|
dk	r�t|
�}
d
}n|dkr�|
dk	r�tt|
��}
|j||
f�q*W|r|�s�|jd�|j|�qW|S)a5Ad-hoc parser for Netscape protocol cookie-attributes.

    The old Netscape cookie format for Set-Cookie can for instance contain
    an unquoted "," in the expires field, so we have to use this ad-hoc
    parser instead of split_header_words.

    XXX This may not make the best possible effort to parse all the crap
    that Netscape Cookie headers contain.  Ronald Tschalar's HTTPClient
    parser is probably better, so could do worse than following that if
    this ever gives any trouble.

    Currently, this is also used for parsing RFC 2109 cookies.

    �expires�domain�path�secure�version�port�max-ageF�;�=r	NT�0)r�r�r�r�r�r�r�)r�r�)�	enumerate�split�strip�	partitionrKr�rarq)Z
ns_headersZknown_attrsruZ	ns_headerrv�version_setZiiZparam�key�sep�val�lcrrr�parse_ns_headers�s@

r�z\.\d+$cCs:tj|�rdS|dkrdS|ddks2|ddkr6dSdS)z*Return True if text is a host domain name.FrVr	�.rTr�)�IPV4_REr@)r_rrr�is_HDNs
r�cCsl|j�}|j�}||krdSt|�s(dS|j|�}|dksB|dkrFdS|jd�sTdSt|dd��shdSdS)a�Return True if domain A domain-matches domain B, according to RFC 2965.

    A and B may be host domain names or IP addresses.

    RFC 2965, section 1:

    Host names can be specified either as an IP address or a HDN string.
    Sometimes we compare one host name with another.  (Such comparisons SHALL
    be case-insensitive.)  Host A's name domain-matches host B's if

         *  their host name strings string-compare equal; or

         * A is a HDN string and has the form NB, where N is a non-empty
            name string, B has the form .B', and B' is a HDN string.  (So,
            x.y.com domain-matches .Y.com but not Y.com.)

    Note that domain-match is not a commutative operation: a.b.c.com
    domain-matches .c.com, but not the reverse.

    TFrr	r�Nr�)rKr��rfindrr)�A�B�irrr�domain_matchs

r�cCstj|�rdSdS)zdReturn True if text is a sort-of-like a host domain name.

    For accepting/blocking domains.

    FT)r�r@)r_rrr�liberal_is_HDNBs
r�cCsb|j�}|j�}t|�ot|�s0||kr,dSdS|jd�}|rL|j|�rLdS|r^||kr^dSdS)z\For blocking/accepting domains.

    A and B may be host domain names or IP addresses.

    TFr�)rKr�rrr�)r�r��initial_dotrrr�user_domain_matchLs
r�z:\d+$cCsB|j�}tjj|�d}|dkr,|jdd�}tjd|d�}|j�S)z�Return request-host, as defined by RFC 2965.

    Variation from RFC: returned value is lowercased, for convenient
    comparison.

    rrVZHost)�get_full_url�urllib�parseZurlparseZ
get_header�cut_port_rer]rK)�request�url�hostrrr�request_hostasr�cCs6t|�}}|jd�dkr.tj|�r.|d}||fS)zzReturn a tuple (request-host, effective request-host name).

    As defined by RFC 2965, except both are lowercased.

    r�rz.localr�)r��findr�r@)r��erhn�req_hostrrr�eff_request_hostqsr�cCs4|j�}tjj|�}t|j�}|jd�s0d|}|S)z6Path component of request-URI, as defined by RFC 2965.�/)r�r�r�Zurlsplit�escape_pathr�rr)r�r��partsr�rrr�request_path|s

r�cCs^|j}|jd�}|dkrV||dd�}yt|�WqZtk
rRtd|�dSXnt}|S)N�:r	rznonnumeric port: '%s')r�r�rArLr�DEFAULT_HTTP_PORT)r�r�r�r�rrr�request_port�s

r�z%/;:@&=+$,!~*'()z%([0-9a-fA-F][0-9a-fA-F])cCsd|jd�j�S)Nz%%%sr)rBrO)rgrrr�uppercase_escaped_char�sr�cCstjj|t�}tjt|�}|S)zEEscape any invalid characters in HTTP URL, and uppercase all escapes.)r�r�Zquote�HTTP_PATH_SAFE�ESCAPED_CHAR_REr]r�)r�rrrr��s
r�cCsP|jd�}|dkrL||dd�}|jd�}t|�rL|dksD|dkrLd|S|S)aBReturn reach of host h, as defined by RFC 2965, section 1.

    The reach R of a host name H is defined as follows:

       *  If

          -  H is the host domain name of a host; and,

          -  H has the form A.B; and

          -  A has no embedded (that is, interior) dots; and

          -  B has at least one embedded dot, or B is the string "local".
             then the reach of H is .B.

       *  Otherwise, the reach of H is H.

    >>> reach("www.acme.com")
    '.acme.com'
    >>> reach("acme.com")
    'acme.com'
    >>> reach("acme.local")
    '.local'

    r�r	rNZlocal)r�r�)�hr��brrr�reach�s

r�cCs$t|�}t|t|j��sdSdSdS)z�

    RFC 2965, section 3.3.6:

        An unverifiable transaction is to a third-party host if its request-
        host U does not domain-match the reach R of the request-host O in the
        origin transaction.

    TFN)r�r�r�Zorigin_req_host)r�r�rrr�is_third_party�s
r�c@sNeZdZdZddd�Zdd�Zddd	�Zd
d�Zddd
�Zdd�Z	dd�Z
dS)ra�HTTP Cookie.

    This class represents both Netscape and RFC 2965 cookies.

    This is deliberately a very simple class.  It just holds attributes.  It's
    possible to construct Cookie instances that don't comply with the cookie
    standards.  CookieJar.make_cookies is the factory function for Cookie
    objects -- it deals with cookie parsing, supplying defaults, and
    normalising to the representation used in this class.  CookiePolicy is
    responsible for checking them to see whether they should be accepted from
    and returned to the server.

    Note that the port may be present in the headers, but unspecified ("Port"
    rather than"Port=80", for example); if this is the case, port is None.

    FcCs�|dk	rt|�}|dk	r$tt|��}|dkr<|dkr<td��||_||_||_||_||_|j�|_	||_
||_|	|_|
|_
||_||_|
|_||_||_||_tj|�|_dS)NTz-if port is None, port_specified must be false)rArZrLr�rwrxr��port_specifiedrKr��domain_specified�domain_initial_dotr��path_specifiedr�r��discard�comment�comment_url�rfc2109�copy�_rest)�selfr�rwrxr�r�r�r�r�r�r�r�r�r�r�r��restr�rrr�__init__�s.

zCookie.__init__cCs
||jkS)N)r�)r�rwrrr�has_nonstandard_attrszCookie.has_nonstandard_attrNcCs|jj||�S)N)r��get)r�rw�defaultrrr�get_nonstandard_attrszCookie.get_nonstandard_attrcCs||j|<dS)N)r�)r�rwrxrrr�set_nonstandard_attrszCookie.set_nonstandard_attrcCs,|dkrtj�}|jdk	r(|j|kr(dSdS)NTF)rMr�)r��nowrrr�
is_expireds
zCookie.is_expiredcCsX|jdkrd}n
d|j}|j||j}|jdk	rFd|j|jf}n|j}d||fS)NrVr�z%s=%sz<Cookie %s for %s>)r�r�r�rxrw)r��p�limitZ	namevaluerrr�__str__%s


zCookie.__str__cCspg}x,dD]$}t||�}|jd|t|�f�q
W|jdt|j��|jdt|j��d|jjdj|�fS)Nr�rwrxr�r�r�r�r�r�r�r�r�r�r�r�z%s=%szrest=%sz
rfc2109=%sz%s(%s)z, )r�rwrxr�r�r�r�r�r�r�r�r�r�r�r�)�getattrrq�reprr�r��	__class__�__name__r{)r�rrwr}rrr�__repr__/s
zCookie.__repr__)F)N)N)r��
__module__�__qualname__�__doc__r�r�r�r�r�r�r�rrrrr�s
 


c@s0eZdZdZdd�Zdd�Zdd�Zdd	�Zd
S)ra Defines which cookies get accepted from and returned to server.

    May also modify cookies, though this is probably a bad idea.

    The subclass DefaultCookiePolicy defines the standard rules for Netscape
    and RFC 2965 cookies -- override that if you want a customized policy.

    cCs
t��dS)z�Return true if (and only if) cookie should be accepted from server.

        Currently, pre-expired cookies never get this far -- the CookieJar
        class deletes such cookies itself.

        N)�NotImplementedError)r��cookier�rrr�set_okGszCookiePolicy.set_okcCs
t��dS)zAReturn true if (and only if) cookie should be returned to server.N)r�)r�r�r�rrr�	return_okPszCookiePolicy.return_okcCsdS)zMReturn false if cookies should not be returned, given cookie domain.
        Tr)r�r�r�rrr�domain_return_okTszCookiePolicy.domain_return_okcCsdS)zKReturn false if cookies should not be returned, given cookie path.
        Tr)r�r�r�rrr�path_return_okYszCookiePolicy.path_return_okN)r�r�r�r�r�r�r�r�rrrrr>s
	c@s�eZdZdZdZdZdZdZeeBZdddddddddeddfd	d
�Z	dd�Z
d
d�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Zd1d2�Zd3d4�Zd5d6�ZdS)7rzBImplements the standard rules for accepting and returning cookies.rrrTr	NTFc

Csp||_||_||_||_||_||_|	|_|
|_||_||_	|dk	rPt
|�|_nf|_|dk	rft
|�}||_dS)zAConstructor arguments should be passed as keyword arguments only.N)
�netscape�rfc2965�rfc2109_as_netscape�hide_cookie2�
strict_domain�strict_rfc2965_unverifiable�strict_ns_unverifiable�strict_ns_domain�strict_ns_set_initial_dollar�strict_ns_set_path�tuple�_blocked_domains�_allowed_domains)
r��blocked_domains�allowed_domainsr�r�r�r�r�r�r�r�r�r�rrrr�is 
zDefaultCookiePolicy.__init__cCs|jS)z4Return the sequence of blocked domains (as a tuple).)r�)r�rrrr��sz#DefaultCookiePolicy.blocked_domainscCst|�|_dS)z$Set the sequence of blocked domains.N)r�r�)r�r�rrr�set_blocked_domains�sz'DefaultCookiePolicy.set_blocked_domainscCs"x|jD]}t||�rdSqWdS)NTF)r�r�)r�r�Zblocked_domainrrr�
is_blocked�s
zDefaultCookiePolicy.is_blockedcCs|jS)z=Return None, or the sequence of allowed domains (as a tuple).)r�)r�rrrr��sz#DefaultCookiePolicy.allowed_domainscCs|dk	rt|�}||_dS)z-Set the sequence of allowed domains, or None.N)r�r�)r�r�rrr�set_allowed_domains�sz'DefaultCookiePolicy.set_allowed_domainscCs0|jdkrdSx|jD]}t||�rdSqWdS)NFT)r�r�)r�r�Zallowed_domainrrr�is_not_allowed�s

z"DefaultCookiePolicy.is_not_allowedcCsBtd|j|j�x,dD]$}d|}t||�}|||�sd	SqWd
S)z�
        If you override .set_ok(), be sure to call this method.  If it returns
        false, so should your subclass (assuming your subclass wants to be more
        strict about which cookies to accept).

        z - checking cookie %s=%sr��
verifiabilityrwr�r�r�Zset_ok_FT)r�r�rwr�r�r�)rrwrxr�)r�r�r��n�fn_name�fnrrrr��s


zDefaultCookiePolicy.set_okcCs^|jdkrtd|j|j�dS|jdkr<|jr<td�dS|jdkrZ|jrZtd�dSdS)Nz0   Set-Cookie2 without version attribute (%s=%s)Fr	z$   RFC 2965 cookies are switched offz$   Netscape cookies are switched offT)r�rrwrxr�r�)r�r�r�rrr�set_ok_version�s
z"DefaultCookiePolicy.set_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS)Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT)�unverifiabler�r�r�rr�)r�r�r�rrr�set_ok_verifiability�sz(DefaultCookiePolicy.set_ok_verifiabilitycCs0|jdkr,|jr,|jjd�r,td|j�dSdS)Nr	�$z'   illegal name (starts with '$'): '%s'FT)r�r�rwrrr)r�r�r�rrr�set_ok_name�s
zDefaultCookiePolicy.set_ok_namecCsL|jrHt|�}|jdks(|jdkrH|jrH|j|j�rHtd|j|�dSdS)Nr	z7   path attribute %s is not a prefix of request path %sFT)r�r�r�r�rrr�r)r�r�r��req_pathrrr�set_ok_path�s

zDefaultCookiePolicy.set_ok_pathc
Cs�|j|j�rtd|j�dS|j|j�r8td|j�dS|j�r�t|�\}}|j}|jr�|jd�dkr�|jd�}|jdd|�}|dkr�||dd�}||d|�}	|	j	�d$kr�t
|�dkr�td|�dS|jd��r�|dd�}
n|}
|
jd�dk}|�r|dk�rtd|�dS|j
dk�rb|j|��rb|jd��rbd|j|��rbtd ||�dS|j
dk�s||j|j@�r�t||��s�td!||�dS|j
dk�s�|j|j@�r�|dt
|��}|jd�dk�r�tj|��r�td"||�dSd#S)%Nz"   domain %s is in user block-listFz&   domain %s is not in user allow-listr�rr	r�co�ac�com�edu�org�net�gov�milrA�aero�biz�cat�coop�info�jobs�mobi�museumrw�pro�travel�euz&   country-code second level domain %sz.localz/   non-local domain %s contains no embedded dotzO   effective request-host %s (even with added initial dot) does not end with %sz5   effective request-host %s does not domain-match %sz.   host prefix %s for domain %s contains a dotT)rrrrrrrrrAr	r
rrr
rrrrwrrr)r�r�rr�r�r�r��countr�rK�lenrrr�r�r�r��DomainRFC2965Matchr��DomainStrictNoDotsr�r@)
r�r�r�r�r�r�r��jZtldZsldZundotted_domainZ
embedded_dotsZhost_prefixrrr�
set_ok_domain�sf

z!DefaultCookiePolicy.set_ok_domaincCs�|jr�t|�}|dkrd}nt|�}x\|jjd�D]:}yt|�Wntk
r`td|�dSX||kr2Pq2Wtd||j�dSdS)N�80rkz   bad port %s (not numeric)Fz$   request port (%s) not found in %sT)r�r��strr�r�rArLr)r�r�r��req_portr�rrr�set_ok_port%s"

zDefaultCookiePolicy.set_ok_portcCsBtd|j|j�x,dD]$}d|}t||�}|||�sd	SqWd
S)z�
        If you override .return_ok(), be sure to call this method.  If it
        returns false, so should your subclass (assuming your subclass wants to
        be more strict about which cookies to return).

        z - checking cookie %s=%sr�r�r�r�r�r�Z
return_ok_FT)r�r�r�r�r�r�)rrwrxr�)r�r�r�r�r�r�rrrr�:s	


zDefaultCookiePolicy.return_okcCs@|jdkr|jrtd�dS|jdkr<|jr<td�dSdS)Nr	z$   RFC 2965 cookies are switched offFz$   Netscape cookies are switched offT)r�r�rr�)r�r�r�rrr�return_ok_versionLsz%DefaultCookiePolicy.return_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS)Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT)r�r�r�r�rr�)r�r�r�rrr�return_ok_verifiabilityUsz+DefaultCookiePolicy.return_ok_verifiabilitycCs |jr|jdkrtd�dSdS)NZhttpsz(   secure cookie with non-secure requestFT)r��typer)r�r�r�rrr�return_ok_secureasz$DefaultCookiePolicy.return_ok_securecCs|j|j�rtd�dSdS)Nz   cookie expiredFT)r��_nowr)r�r�r�rrr�return_ok_expiresgsz%DefaultCookiePolicy.return_ok_expirescCsP|jrLt|�}|dkrd}x0|jjd�D]}||kr(Pq(Wtd||j�dSdS)Nrrkz0   request port %s does not match cookie port %sFT)r�r�r�r)r�r�r�rr�rrr�return_ok_portms
z"DefaultCookiePolicy.return_ok_portcCs�t|�\}}|j}|r,|jd�r,d|}n|}|jdkrb|j|j@rb|jrb||krbtd�dS|jdkr�t||�r�td||�dS|jdkr�d|j	|�r�td||�dSdS)Nr�r	zQ   cookie with unspecified domain does not string-compare equal to request domainFzQ   effective request-host name %s does not domain-match RFC 2965 cookie domain %sz;   request-host %s does not match Netscape cookie domain %sT)
r�r�rrr�r��DomainStrictNonDomainr�rr�r�)r�r�r�r�r�r��	dotdomainrrr�return_ok_domain{s&

z$DefaultCookiePolicy.return_ok_domaincCs�t|�\}}|jd�sd|}|jd�s0d|}|rJ|jd�rJd|}n|}|j|�p`|j|�sfdS|j|�r~td|�dS|j|�r�td|�dSdS)Nr�Fz"   domain %s is in user block-listz&   domain %s is not in user allow-listT)r�rrr�r�rr�)r�r�r�r�r�r&rrrr��s"






z$DefaultCookiePolicy.domain_return_okcCs0td|�t|�}|j|�s,td||�dSdS)Nz- checking cookie path=%sz  %s does not path-match %sFT)rr�rr)r�r�r�r�rrrr��s

z"DefaultCookiePolicy.path_return_ok) r�r�r�r�rr%rZ
DomainLiberalZDomainStrictr�r�r�r�r�r�r�r�r�r�r�rrrr�rrr!r#r$r'r�r�rrrrr_sL	;	cCst|j��}t|j|�S)N)�sorted�keys�mapr�)Zadictr)rrr�vals_sorted_by_key�sr+ccsZt|�}xL|D]D}d}y
|jWntk
r4YnXd}t|�EdH|s|VqWdS)zBIterates over nested mapping, depth-first, in sorted order by key.FTN)r+�items�AttributeError�
deepvalues)�mapping�values�objrrrr.�s

r.c@seZdZdS)�AbsentN)r�r�r�rrrrr2�sr2c@s�eZdZdZejd�Zejd�Zejd�Zejd�Z	ejd�Z
ejdej�Zd3d	d
�Z
dd�Zd
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd4d%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Z d1d2�Z!dS)5rz�Collection of HTTP cookies.

    You may not need to know about this class: try
    urllib.request.build_opener(HTTPCookieProcessor).open(url).
    z\Wz([\"\\])z\.?[^.]*z[^.]*z^\.+z^\#LWP-Cookies-(\d+\.\d+)NcCs(|dkrt�}||_tj�|_i|_dS)N)r�_policy�
_threading�RLock�
_cookies_lock�_cookies)r��policyrrrr��s

zCookieJar.__init__cCs
||_dS)N)r3)r�r8rrr�
set_policy�szCookieJar.set_policycCs�g}|jj||�sgStd|�|j|}xd|j�D]X}|jj||�sHq4||}x:|j�D].}|jj||�svtd�qZtd�|j|�qZWq4W|S)Nz!Checking %s for cookies to returnz   not returning cookiez   it's a match)	r3r�rr7r)r�r0r�rq)r�r�r��cookiesZcookies_by_pathr�Zcookies_by_namer�rrr�_cookies_for_domain�s 

zCookieJar._cookies_for_domaincCs.g}x$|jj�D]}|j|j||��qW|S)z2Return a list of cookies to be returned to server.)r7r)�extendr;)r�r�r:r�rrr�_cookies_for_request�szCookieJar._cookies_for_requestc	CsF|jdd�dd�d}g}�x$|D�]}|j}|sLd}|dkrL|jd|�|jdk	r~|jj|j�r~|dkr~|jjd	|j�}n|j}|jdkr�|j|j�n|jd
|j|f�|dkr"|j	r�|jd|j
�|jjd��r|j}|j
o�|jd��r|d
d�}|jd|�|jdk	r"d}|j�r4|d|j}|j|�q"W|S)z�Return a list of cookie-attributes to be returned to server.

        like ['foo="bar"; $Path="/"', ...]

        The $Version attribute is also added when appropriate (currently only
        once per request).

        cSs
t|j�S)N)rr�)�arrr�<lambda>sz)CookieJar._cookie_attrs.<locals>.<lambda>T)r��reverseFr	z$Version=%sNz\\\1z%s=%sz
$Path="%s"r�rz$Domain="%s"z$Portz="%s")�sortr�rqrx�non_word_rer@�quote_rer]rwr�r�r�rrr�r�r�)	r�r:r��attrsr�r�rxr�r�rrr�
_cookie_attrss>



zCookieJar._cookie_attrsc
Cs�td�|jj�z�ttj��|j_|_|j|�}|j|�}|r^|j	d�s^|j
ddj|��|jjr�|jj
r�|j	d�r�x$|D]}|jdkr�|j
dd�Pq�WWd|jj�X|j�dS)z�Add correct Cookie: header to request (urllib.request.Request object).

        The Cookie2 header is also added unless policy.hide_cookie2 is true.

        �add_cookie_headerrz; ZCookie2rz$Version="1"N)rr6�acquirerArMr3r"r=rEZ
has_headerZadd_unredirected_headerr{r�r�r��release�clear_expired_cookies)r�r�r:rDr�rrrrF?s$






zCookieJar.add_cookie_headercCs�g}d}d}�x||D�]r}|d\}}d}d}	i}
i}�x4|d
d�D�]"\}}
|j�}||ksh||krl|}||kr�|
dkr�d}
||
kr�qF|dkr�|
dkr�td�d}	P|
j�}
|dkr�|r�qF|
dkr�td�qF|dk�rd}yt|
�}
Wn$tk
�rtd�d}	PYnXd}|j|
}
||k�s2||k�rb|
dk�rX|dk�rXtd|�d}	P|
|
|<qF|
||<qFW|	�rvq|j|||
|f�qW|S)aReturn 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.

        r�r�r�r��max-ager�r�r�r��
commenturlr	FrNTz%   missing value for domain attributezM   missing or invalid value for expires attribute: treating as session cookiez?   missing or invalid (non-numeric) value for max-age attributez!   missing value for %s attribute)r�r�)r�r�rJr�r�r�r�rK)r�r�rK)rKrrArLr"rq)r��	attrs_set�
cookie_tuples�
boolean_attrs�value_attrsZcookie_attrsrwrxZmax_age_setZ
bad_cookie�standardr�r~rr�rrr�_normalized_cookie_tuples`sl






z#CookieJar._normalized_cookie_tuplesc!Cs$|\}}}}|jdt�}|jdt�}|jdt�}	|jdt�}
|jdd�}|dk	rryt|�}Wntk
rpdSX|jdd�}|jdd�}
|jd	d�}|jd
d�}|tk	r�|dkr�d}t|�}nXd}t|�}|jd
�}|dk�r|dkr�|d|�}n|d|d�}t|�dk�rd
}|tk	}d}|�r8t|j	d��}|tk�rTt
|�\}}|}n|j	d��shd|}d}|	tk	�r�|	dk�r�t|�}	nd}tj
dd|	�}	nd}	|
tk�r�d}
d}
nH|
|jk�r�y|j|||�Wntk
�r�YnXtd|||�dSt||||	||||||||
|
|||�S)Nr�r�r�r�r�r�Fr�r�rKrVTr�rr	r�z\s+z2Expiring cookie, domain='%s', path='%s', name='%s'r�)r�r2rArLr�r�r�r�boolrrr�r�rsr]r"�clear�KeyErrorrr)r��tupr�rwrxrPr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrr�_cookie_from_cookie_tuple�s�








z#CookieJar._cookie_from_cookie_tuplecCs:|j|�}g}x&|D]}|j||�}|r|j|�qW|S)N)rQrVrq)r�rLr�rMr:rUr�rrr�_cookies_from_attrs_sets

z!CookieJar._cookies_from_attrs_setcCsLt|jdd�}|dkr |jj}x&|D]}|jdkr&d|_|r&d|_q&WdS)Nr�rTr	)r�r3r�r�r�)r�r:Z
rfc2109_as_nsr�rrr�_process_rfc2109_cookies&s


z"CookieJar._process_rfc2109_cookiesc
Cs6|j�}|jdg�}|jdg�}|jj}|jj}|r<|s`|rH|s`|rT|s`|rd|rdgSy|jt|�|�}Wntk
r�t�g}YnX|o�|�r2y|jt	|�|�}	Wntk
r�t�g}	YnX|j
|	�|�r"i}
x |D]}d|
|j|j|j
f<q�W|
fdd�}t||	�}	|	�r2|j|	�|S)zAReturn sequence of Cookie objects extracted from response object.zSet-Cookie2z
Set-CookieNcSs|j|j|jf}||kS)N)r�r�rw)Z	ns_cookie�lookupr�rrr�no_matching_rfc2965^sz3CookieJar.make_cookies.<locals>.no_matching_rfc2965)r
Zget_allr3r�r�rWry�	Exceptionrr�rXr�r�rw�filterr<)
r��responser�r|Zrfc2965_hdrsZns_hdrsr�r�r:Z
ns_cookiesrYr�rZrrr�make_cookies2sB






zCookieJar.make_cookiesc
CsN|jj�z2ttj��|j_|_|jj||�r:|j|�Wd|jj�XdS)z-Set a cookie if policy says it's OK to do so.N)	r6rGrArMr3r"r��
set_cookierH)r�r�r�rrr�set_cookie_if_okhs
zCookieJar.set_cookie_if_okc
Csl|j}|jj�zJ|j|kr&i||j<||j}|j|krDi||j<||j}|||j<Wd|jj�XdS)z?Set a cookie, without checking whether or not it should be set.N)r7r6rGr�r�rwrH)r�r��cZc2Zc3rrrr_us






zCookieJar.set_cookiec
Cs|td|j��|jj�zRttj��|j_|_x6|j||�D]&}|jj	||�r>td|�|j
|�q>WWd|jj�XdS)zAExtract cookies from response, where allowable given the request.zextract_cookies: %sz setting cookie: %sN)rr
r6rGrArMr3r"r^r�r_rH)r�r]r�r�rrr�extract_cookies�s

zCookieJar.extract_cookiescCst|dk	r2|dks|dkr td��|j|||=n>|dk	rX|dkrJtd��|j||=n|dk	rj|j|=ni|_dS)a�Clear some cookies.

        Invoking this method without arguments will clear all cookies.  If
        given a single argument, only cookies belonging to that domain will be
        removed.  If given two arguments, cookies belonging to the specified
        path within that domain are removed.  If given three arguments, then
        the cookie with the specified name, path and domain is removed.

        Raises KeyError if no matching cookie exists.

        Nz8domain and path must be given to remove a cookie by namez.domain must be given to remove cookies by path)rLr7)r�r�r�rwrrrrS�s
zCookieJar.clearcCsH|jj�z,x&|D]}|jr|j|j|j|j�qWWd|jj�XdS)z�Discard all session cookies.

        Note that the .save() method won't save session cookies anyway, unless
        you ask otherwise by passing a true ignore_discard argument.

        N)r6rGr�rSr�r�rwrH)r�r�rrr�clear_session_cookies�s

zCookieJar.clear_session_cookiescCsT|jj�z8tj�}x*|D]"}|j|�r|j|j|j|j�qWWd|jj�XdS)a�Discard all expired cookies.

        You probably don't need to call this method: expired cookies are never
        sent back to the server (provided you're using DefaultCookiePolicy),
        this method is called by CookieJar itself every so often, and the
        .save() method won't save expired cookies anyway (unless you ask
        otherwise by passing a true ignore_expires argument).

        N)	r6rGrMr�rSr�r�rwrH)r�r�r�rrrrI�s



zCookieJar.clear_expired_cookiescCs
t|j�S)N)r.r7)r�rrr�__iter__�szCookieJar.__iter__cCsd}x|D]}|d}q
W|S)z#Return number of contained cookies.r	rr)r�r�r�rrr�__len__�s
zCookieJar.__len__cCs6g}x|D]}|jt|��q
Wd|jjdj|�fS)Nz<%s[%s]>z, )rqr�r�r�r{)r��rr�rrrr��s
zCookieJar.__repr__cCs6g}x|D]}|jt|��q
Wd|jjdj|�fS)Nz<%s[%s]>z, )rqrr�r�r{)r�rfr�rrrr��s
zCookieJar.__str__)N)NNN)"r�r�r�r�rs�compilerBrCZstrict_domain_reZ	domain_reZdots_re�ASCII�magic_rer�r9r;r=rErFrQrVrWrXr^r`r_rbrSrcrIrdrer�r�rrrrr�s8





;!a\	6


c@seZdZdS)rN)r�r�r�rrrrr�sc@s8eZdZdZddd�Zd
dd�Zddd	�Zdd
d�ZdS)rz6CookieJar that can be loaded from and saved to a file.NFc	CsJtj||�|dk	r6y|dWntd��YnX||_t|�|_dS)z}
        Cookies are NOT loaded from the named file until either the .load() or
        .revert() method is called.

        NrVzfilename must be string-like)rr�rL�filenamerR�	delayload)r�rjrkr8rrrr��szFileCookieJar.__init__cCs
t��dS)zSave cookies to a file.N)r�)r�rj�ignore_discard�ignore_expiresrrr�save�szFileCookieJar.savecCsJ|dkr"|jdk	r|j}ntt��t|��}|j||||�WdQRXdS)zLoad cookies from a file.N)rjrL�MISSING_FILENAME_TEXT�open�_really_load)r�rjrlrmrrrr�load�s

zFileCookieJar.loadcCs�|dkr"|jdk	r|j}ntt��|jj�zFtj|j�}i|_y|j|||�Wnt	k
rn||_�YnXWd|jj
�XdS)z�Clear all cookies and reload cookies from a saved file.

        Raises LoadError (or OSError) if reversion is not successful; the
        object's state will not be altered if this happens.

        N)rjrLror6rGr��deepcopyr7rr�OSErrorrH)r�rjrlrmZ	old_staterrr�reverts

zFileCookieJar.revert)NFN)NFF)NFF)NFF)r�r�r�r�r�rnrrrurrrrr�s


	cCs$|j|jfd|jfd|jfg}|jdk	r8|jd|jf�|jrH|jd�|jrX|jd�|jrh|jd�|j	rx|jd�|j
r�|jd	tt|j
��f�|j
r�|jd�|jr�|jd|jf�|jr�|jd|jf�t|jj��}x$|D]}|j|t|j|�f�q�W|jd
t|j�f�t|g�S)z�Return string representation of Cookie in the LWP cookie file format.

    Actually, the format is extended a bit -- see module docstring.

    r�r�Nr��	path_spec�	port_spec�
domain_dotr�r�r�r�rKr�)rvN)rwN)rxN)r�N)r�N)rwrxr�r�r�rqr�r�r�r�r�r5rZr�r�r�r(r�r)rr�r�)r�r�r)r~rrr�lwp_cookie_strs6







ryc@s,eZdZdZddd�Zddd�Zd	d
�ZdS)
ra[
    The LWPCookieJar saves a sequence of "Set-Cookie3" lines.
    "Set-Cookie3" is the format used by the libwww-perl library, not known
    to be compatible with any browser, but which is easy to read and
    doesn't lose information about RFC 2965 cookies.

    Additional methods

    as_lwp_str(ignore_discard=True, ignore_expired=True)

    TcCs\tj�}g}x>|D]6}|r$|jr$q|r6|j|�r6q|jdt|��qWdj|dg�S)z�Return cookies as a string of "\n"-separated "Set-Cookie3" headers.

        ignore_discard and ignore_expires: see docstring for FileCookieJar.save

        zSet-Cookie3: %s�
rV)rMr�r�rqryr{)r�rlrmr�rfr�rrr�
as_lwp_strGs
zLWPCookieJar.as_lwp_strNFcCsX|dkr"|jdk	r|j}ntt��t|d��"}|jd�|j|j||��WdQRXdS)N�wz#LWP-Cookies-2.0
)rjrLrorp�writer{)r�rjrlrmrrrrrnWs

zLWPCookieJar.savecCsL|j�}|jj|�s$d|}t|��tj�}d}d}	d}
�yʐx�|j�}|dkrRP|j|�s^q@|t|�d�j�}�x�t|g�D�]x}|d\}
}i}i}x|	D]}d||<q�Wx�|dd�D]t\}}|dk	r�|j	�}nd}||
k�s�||	k�r�|}||	k�r|dk�rd}|||<q�||
k�r*|||<q�|||<q�W|j
}|d�}|d�}|dk	�r^t|�}|dk�rld}|d�}|jd�}t|d�|
||d	�|d�|||d�|d
�|d�|d�|||d
�|d�|�}|�r�|j
�r�q�|�r�|j|��r�q�|j|�q�Wq@WWnBtk
�r�Yn,tk
�rFt�td||f��YnXdS)Nz5%r does not look like a Set-Cookie3 (LWP) format filezSet-Cookie3:rwrvrxr�r�r�r�r�r�r�r�rKrVr	FrTr�z&invalid Set-Cookie3 format file %r: %r)rwrvrxr�r�)r�r�r�r�r�r�rK)�readlinerir@rrMrrrr�ryrKr�rdrr�r�r_rtr[r)r�rrjrlrm�magicrr��headerrNrO�line�datarwrxrPr�r~rr�r�r�r�r�r�rarrrrqcs�











zLWPCookieJar._really_load)TT)NFF)r�r�r�r�r{rnrqrrrrr:s

c@s0eZdZdZejd�ZdZdd�Zd
dd	�Z	dS)ra�

    WARNING: you may want to backup your browser's cookies file if you use
    this class to save cookies.  I *think* it works, but there have been
    bugs in the past!

    This class differs from CookieJar only in the format it uses to save and
    load cookies to and from a file.  This class uses the Mozilla/Netscape
    `cookies.txt' format.  lynx uses this file format, too.

    Don't expect cookies saved while the browser is running to be noticed by
    the browser (in fact, Mozilla on unix will overwrite your saved cookies if
    you change them on disk while it's running; on Windows, you probably can't
    save at all while the browser is running).

    Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
    Netscape cookies on saving.

    In particular, the cookie version and port number information is lost,
    together with information about whether or not Path, Port and Discard were
    specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
    domain as set in the HTTP header started with a dot (yes, I'm aware some
    domains in Netscape files start with a dot and some don't -- trust me, you
    really don't want to know any more about this).

    Note that though Mozilla and Netscape use the same format, they use
    slightly different headers.  The class saves cookies using the Netscape
    header by default (Mozilla can cope with that).

    z#( Netscape)? HTTP Cookie Filezr# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

cCsntj�}|j�}|jj|�s(td|���y�x�|j�}|dkr@P|jd�rV|dd�}|j�jd�s.|j�dkrrq.|jd�\}}	}
}}}
}|dk}|	dk}	|
dkr�|}
d}|jd	�}d
}|dkr�d}d}t	d|
|dd
||	||
d
|||ddi�}|�r|j
�rq.|�r|j|��rq.|j|�q.WWnBt
k
�r>�Yn,tk
�rht�td
||f��YnXdS)Nz4%r does not look like a Netscape format cookies filerVrzr�#r��	�TRUEr�FTr	z+invalid Netscape format cookies file %r: %rr�)r�r�)rMr~rir@rr�r�rrr�rr�r�r_rtr[r)r�rrjrlrmr�rr�r�r�r�r�r�rwrxr�r�rarrrrq�s`

zMozillaCookieJar._really_loadNFcCs|dkr"|jdk	r|j}ntt��t|d���}|j|j�tj�}x�|D]�}|rZ|jrZqH|rl|j|�rlqH|j	rxd}nd}|j
jd�r�d}nd}|jdk	r�t
|j�}	nd}	|jdkr�d}
|j}n|j}
|j}|jdj|j
||j||	|
|g�d�qHWWdQRXdS)Nr|r�ZFALSEr�rVr�rz)rjrLrorpr}r�rMr�r�r�r�rrr�rrxrwr{r�)r�rjrlrmrr�r�r�r�r�rwrxrrrrns<



zMozillaCookieJar.save)NFF)
r�r�r�r�rsrgrir�rqrnrrrrr�s

A)N)N)Yr��__all__r�r-rsrMZurllib.parser�Zurllib.requestZ	threadingr4�ImportErrorZdummy_threadingZhttp.clientZhttpZcalendarr
rrrrZclientZ	HTTP_PORTr�rorr%r,r6r7rIr(rqrKr5r8r>rgrhr?rFrSrX�Ir\�Xr^rarbrdrjrlrmrornryrzr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrr+r.r2rrtrrryrrrrrr�<module>s�



88!



U
D'


#b!\:x__pycache__/server.cpython-36.pyc000064400000077030150532432170012721 0ustar003

Ow�h���@s�dZdZddddgZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlZddlZddlZddlZddlmZd	Zd
ZGdd�dej�ZGdd�dej�ZGd
d�de�Zdd�Zdadd�Z dd�Z!Gdd�de�Z"eedddfdd�Z#e$dk�r�ej%�Z&e&j'dddd�e&j'dd dd!d"d#�e&j'd$d%de(d&d'd(�e&j)�Z*e*j+�r~e"Z,neZ,e#e,e*j-e*j.d)�dS)*a@HTTP server classes.

Note: BaseHTTPRequestHandler doesn't implement any HTTP request; see
SimpleHTTPRequestHandler for simple implementations of GET, HEAD and POST,
and CGIHTTPRequestHandler for CGI scripts.

It does, however, optionally implement HTTP/1.1 persistent connections,
as of version 0.3.

Notes on CGIHTTPRequestHandler
------------------------------

This class implements GET and POST requests to cgi-bin scripts.

If the os.fork() function is not present (e.g. on Windows),
subprocess.Popen() is used as a fallback, with slightly altered semantics.

In all cases, the implementation is intentionally naive -- all
requests are executed synchronously.

SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
-- it may execute arbitrary Python code or external programs.

Note that status code 200 is sent prior to execution of a CGI script, so
scripts cannot send other status codes such as 302 (redirect).

XXX To do:

- log requests even later (to capture byte count)
- log user-agent header and other interesting goodies
- send error log to separate file
z0.6�
HTTPServer�BaseHTTPRequestHandler�SimpleHTTPRequestHandler�CGIHTTPRequestHandler�N)�
HTTPStatusa�<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: %(code)d</p>
        <p>Message: %(message)s.</p>
        <p>Error code explanation: %(code)s - %(explain)s.</p>
    </body>
</html>
ztext/html;charset=utf-8c@seZdZdZdd�ZdS)r�cCs4tjj|�|jdd�\}}tj|�|_||_dS)z.Override server_bind to store the server name.N�)�socketserver�	TCPServer�server_bind�server_address�socketZgetfqdn�server_name�server_port)�self�host�port�r�#/usr/lib64/python3.6/http/server.pyr�szHTTPServer.server_bindN)�__name__�
__module__�__qualname__Zallow_reuse_addressrrrrrr�sc
@seZdZdZdejj�dZdeZ	e
ZeZ
dZdd�Zdd	�Zd
d�Zdd
�Zd@dd�ZdAdd�ZdBdd�Zdd�Zdd�Zdd�ZdCdd�Zdd�Zd d!�Zd"d#�ZdDd$d%�Zd&d'�Zd(d)d*d+d,d-d.gZdd/d0d1d2d3d4d5d6d7d8d9d:g
Z d;d<�Z!d=Z"e#j$j%Z&d>d?�e'j(j)�D�Z*dS)Era�HTTP request handler base class.

    The following explanation of HTTP serves to guide you through the
    code as well as to expose any misunderstandings I may have about
    HTTP (so you don't need to read the code to figure out I'm wrong
    :-).

    HTTP (HyperText Transfer Protocol) is an extensible protocol on
    top of a reliable stream transport (e.g. TCP/IP).  The protocol
    recognizes three parts to a request:

    1. One line identifying the request type and path
    2. An optional set of RFC-822-style headers
    3. An optional data part

    The headers and data are separated by a blank line.

    The first line of the request has the form

    <command> <path> <version>

    where <command> is a (case-sensitive) keyword such as GET or POST,
    <path> is a string containing path information for the request,
    and <version> should be the string "HTTP/1.0" or "HTTP/1.1".
    <path> is encoded using the URL encoding scheme (using %xx to signify
    the ASCII character with hex code xx).

    The specification specifies that lines are separated by CRLF but
    for compatibility with the widest range of clients recommends
    servers also handle LF.  Similarly, whitespace in the request line
    is treated sensibly (allowing multiple spaces between components
    and allowing trailing whitespace).

    Similarly, for output, lines ought to be separated by CRLF pairs
    but most clients grok LF characters just fine.

    If the first line of the request has the form

    <command> <path>

    (i.e. <version> is left out) then this is assumed to be an HTTP
    0.9 request; this form has no optional headers and data part and
    the reply consists of just the data.

    The reply form of the HTTP 1.x protocol again has three parts:

    1. One line giving the response code
    2. An optional set of RFC-822-style headers
    3. The data

    Again, the headers and data are separated by a blank line.

    The response code line has the form

    <version> <responsecode> <responsestring>

    where <version> is the protocol version ("HTTP/1.0" or "HTTP/1.1"),
    <responsecode> is a 3-digit response code indicating success or
    failure of the request, and <responsestring> is an optional
    human-readable string explaining what the response code means.

    This server parses the request and the headers, and then calls a
    function specific to the request type (<command>).  Specifically,
    a request SPAM will be handled by a method do_SPAM().  If no
    such method exists the server sends an error response to the
    client.  If it exists, it is called with no arguments:

    do_SPAM()

    Note that the request name is case sensitive (i.e. SPAM and spam
    are different requests).

    The various request details are stored in instance variables:

    - client_address is the client IP address in the form (host,
    port);

    - command, path and version are the broken-down request line;

    - headers is an instance of email.message.Message (or a derived
    class) containing the header information;

    - rfile is a file object open for reading positioned at the
    start of the optional input data part;

    - wfile is a file object open for writing.

    IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!

    The first thing to be written must be the response line.  Then
    follow 0 or more header lines, then a blank line, and then the
    actual data (if any).  The meaning of the header lines depends on
    the command executed by the server; in most cases, when data is
    returned, there should be at least one header line of the form

    Content-type: <type>/<subtype>

    where <type> and <subtype> should be registered MIME types,
    e.g. "text/html" or "text/plain".

    zPython/rz	BaseHTTP/zHTTP/0.9cCs�d|_|j|_}d|_t|jd�}|jd�}||_|j�}t	|�dk�r|\}}}yZ|dd�dkrjt
�|jdd	�d	}|jd
�}t	|�dkr�t
�t|d�t|d	�f}Wn*t
tfk
r�|j
tjd
|�dSX|dkr�|jdkr�d|_|dk�rr|j
tjd|�dSn^t	|�dk�rR|\}}d|_|dk�rr|j
tjd|�dSn |�s\dS|j
tjd|�dS||||_|_|_|jjd��r�d|jjd�|_ytjj|j|jd�|_Wnrtjjk
�r�}z|j
tjdt|��dSd}~Xn:tjjk
�r4}z|j
tjdt|��dSd}~XnX|jjdd�}	|	j�dk�rZd|_n |	j�dk�rz|jdk�rzd|_|jjdd�}
|
j�dk�r�|jdk�r�|jdk�r�|j ��s�dSdS) a'Parse a request (internal).

        The request should be stored in self.raw_requestline; the results
        are in self.command, self.path, self.request_version and
        self.headers.

        Return True for success, False for failure; on failure, an
        error is sent back.

        NTz
iso-8859-1z
��zHTTP/�/r�.rrzBad request version (%r)FzHTTP/1.1zInvalid HTTP version (%s)ZGETzBad HTTP/0.9 request type (%r)zBad request syntax (%r)z//)Z_classz
Line too longzToo many headers�
Connection��closez
keep-aliveZExpectz100-continue)rr)rr)!�command�default_request_version�request_version�close_connection�str�raw_requestline�rstrip�requestline�split�len�
ValueError�int�
IndexError�
send_errorrZBAD_REQUEST�protocol_versionZHTTP_VERSION_NOT_SUPPORTED�path�
startswith�lstrip�http�clientZ
parse_headers�rfile�MessageClass�headersZLineTooLongZREQUEST_HEADER_FIELDS_TOO_LARGEZ
HTTPException�get�lower�handle_expect_100)r�versionr&�wordsrr.Zbase_version_numberZversion_number�errZconntypeZexpectrrr�
parse_requests�












z$BaseHTTPRequestHandler.parse_requestcCs|jtj�|j�dS)a7Decide what to do with an "Expect: 100-continue" header.

        If the client is expecting a 100 Continue response, we must
        respond with either a 100 Continue or a final response before
        waiting for the request body. The default is to always respond
        with a 100 Continue. You can behave differently (for example,
        reject unauthorized requests) by overriding this method.

        This method should either return True (possibly after sending
        a 100 Continue response) or send an error response and return
        False.

        T)�send_response_onlyrZCONTINUE�end_headers)rrrrr8nsz(BaseHTTPRequestHandler.handle_expect_100cCs�y�|jjd�|_t|j�dkr@d|_d|_d|_|jtj	�dS|jsPd|_
dS|j�s\dSd|j}t||�s�|jtj
d|j�dSt||�}|�|jj�Wn4tjk
r�}z|jd|�d|_
dSd}~XnXdS)	z�Handle a single HTTP request.

        You normally don't need to override this method; see the class
        __doc__ string for information on how to handle specific HTTP
        commands such as GET and POST.

        iirNTZdo_zUnsupported method (%r)zRequest timed out: %r)r3�readliner$r(r&r!rr,rZREQUEST_URI_TOO_LONGr"r<�hasattr�NOT_IMPLEMENTED�getattr�wfile�flushr
Ztimeout�	log_error)rZmname�method�errr�handle_one_request�s4


z)BaseHTTPRequestHandler.handle_one_requestcCs&d|_|j�x|js |j�qWdS)z&Handle multiple requests if necessary.TN)r"rH)rrrr�handle�szBaseHTTPRequestHandler.handleNcCs
y|j|\}}Wntk
r.d\}}YnX|dkr<|}|dkrH|}|jd||�|j||�|jdd�d}|dkr�|tjtjtjfkr�|j	|t
j|dd�t
j|dd�d	�}|jd
d�}|jd|j
�|jd
tt|���|j�|jdko�|�r|jj|�dS)akSend and log an error reply.

        Arguments are
        * code:    an HTTP error code
                   3 digits
        * message: a simple optional 1 line reason phrase.
                   *( HTAB / SP / VCHAR / %x80-FF )
                   defaults to short entry matching the response code
        * explain: a detailed message defaults to the long entry
                   matching the response code.

        This sends an error response (so it must be called before any
        output has been generated), logs the error, and finally sends
        a piece of HTML explaining the error to the user.

        �???Nzcode %d, message %srr��F)�quote)�code�message�explainzUTF-8�replacezContent-TypezContent-LengthZHEAD)rJrJ)�	responses�KeyErrorrE�
send_response�send_headerrZ
NO_CONTENTZ
RESET_CONTENTZNOT_MODIFIED�error_message_format�html�escape�encode�error_content_typer#r(r>rrC�write)rrMrNrOZshortmsgZlongmsgZbodyZcontentrrrr,�s4
z!BaseHTTPRequestHandler.send_errorcCs:|j|�|j||�|jd|j��|jd|j��dS)z�Add the response header to the headers buffer and log the
        response code.

        Also send two standard headers with the server software
        version and the current date.

        ZServerZDateN)�log_requestr=rT�version_string�date_time_string)rrMrNrrrrS�s
z$BaseHTTPRequestHandler.send_responsecCsd|jdkr`|dkr0||jkr,|j|d}nd}t|d�s@g|_|jjd|j||fjdd��dS)	zSend the response header only.zHTTP/0.9Nrr�_headers_bufferz
%s %d %s
zlatin-1�strict)r!rQr@r^�appendr-rX)rrMrNrrrr=�s


z)BaseHTTPRequestHandler.send_response_onlycCsl|jdkr6t|d�sg|_|jjd||fjdd��|j�dkrh|j�dkrVd|_n|j�d	krhd
|_dS)z)Send a MIME header to the headers buffer.zHTTP/0.9r^z%s: %s
zlatin-1r_Z
connectionrTz
keep-aliveFN)r!r@r^r`rXr7r")r�keyword�valuerrrrT�s

z"BaseHTTPRequestHandler.send_headercCs"|jdkr|jjd�|j�dS)z,Send the blank line ending the MIME headers.zHTTP/0.9s
N)r!r^r`�
flush_headers)rrrrr>s
z"BaseHTTPRequestHandler.end_headerscCs(t|d�r$|jjdj|j��g|_dS)Nr^�)r@rCrZ�joinr^)rrrrrcs
z$BaseHTTPRequestHandler.flush_headers�-cCs.t|t�r|j}|jd|jt|�t|��dS)zNLog an accepted request.

        This is called by send_response().

        z
"%s" %s %sN)�
isinstancerrb�log_messager&r#)rrM�sizerrrr[s
z"BaseHTTPRequestHandler.log_requestcGs|j|f|��dS)z�Log an error.

        This is called when a request cannot be fulfilled.  By
        default it passes the message on to log_message().

        Arguments are the same as for log_message().

        XXX This should go to the separate error log.

        N)rh)r�format�argsrrrrE!sz BaseHTTPRequestHandler.log_errorcGs&tjjd|j�|j�||f�dS)a�Log an arbitrary message.

        This is used by all other logging functions.  Override
        it if you have specific logging wishes.

        The first argument, FORMAT, is a format string for the
        message to be logged.  If the format string contains
        any % escapes requiring parameters, they should be
        specified as subsequent arguments (it's just like
        printf!).

        The client ip and current date/time are prefixed to
        every message.

        z%s - - [%s] %s
N)�sys�stderrrZ�address_string�log_date_time_string)rrjrkrrrrh/sz"BaseHTTPRequestHandler.log_messagecCs|jd|jS)z*Return the server software version string.� )�server_version�sys_version)rrrrr\Esz%BaseHTTPRequestHandler.version_stringcCs |dkrtj�}tjj|dd�S)z@Return the current date and time formatted for a message header.NT)Zusegmt)�time�emailZutilsZ
formatdate)rZ	timestamprrrr]Isz'BaseHTTPRequestHandler.date_time_stringc	CsBtj�}tj|�\	}}}}}}}}	}
d||j|||||f}|S)z.Return the current time formatted for logging.z%02d/%3s/%04d %02d:%02d:%02d)rsZ	localtime�	monthname)rZnowZyearZmonthZdayZhhZmmZss�x�y�z�srrrroOs
z+BaseHTTPRequestHandler.log_date_time_stringZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs
|jdS)zReturn the client address.r)�client_address)rrrrrn]sz%BaseHTTPRequestHandler.address_stringzHTTP/1.0cCsi|]}|j|jf|�qSr)�phraseZdescription)�.0�vrrr�
<dictcomp>lsz!BaseHTTPRequestHandler.<dictcomp>)NN)N)N)rfrf)N)+rrr�__doc__rlr9r'rr�__version__rq�DEFAULT_ERROR_MESSAGErU�DEFAULT_ERROR_CONTENT_TYPErYr r<r8rHrIr,rSr=rTr>rcr[rErhr\r]roZweekdaynamerurnr-r1r2ZHTTPMessager4r�__members__�valuesrQrrrrr�s>fg%
5



	c@s|eZdZdZdeZdd�Zdd�Zdd�Zd	d
�Z	dd�Z
d
d�Zdd�Ze
jsZe
j�e
jj�Zejddddd��dS)raWSimple HTTP request handler with GET and HEAD commands.

    This serves files from the current directory and any of its
    subdirectories.  The MIME type for files is determined by
    calling the .guess_type() method.

    The GET and HEAD requests are identical except that the HEAD
    request omits the actual contents of the file.

    zSimpleHTTP/c
Cs.|j�}|r*z|j||j�Wd|j�XdS)zServe a GET request.N)�	send_head�copyfilerCr)r�frrr�do_GET�s
zSimpleHTTPRequestHandler.do_GETcCs|j�}|r|j�dS)zServe a HEAD request.N)r�r)rr�rrr�do_HEAD�sz SimpleHTTPRequestHandler.do_HEADc	Csx|j|j�}d}tjj|�r�tjj|j�}|jjd�s�|jt	j
�|d|d|dd|d|df}tjj|�}|jd|�|j
�dSx6dD]$}tjj||�}tjj|�r�|}Pq�W|j|�S|j|�}yt|d�}Wn$tk
�r|jt	jd�dSXyZ|jt	j�|jd
|�tj|j��}|jdt|d��|jd|j|j��|j
�|S|j��YnXdS)a{Common code for GET and HEAD commands.

        This sends the response code and MIME headers.

        Return value is either a file object (which has to be copied
        to the outputfile by the caller unless the command was HEAD,
        and must be closed by the caller under all circumstances), or
        None, in which case the caller has nothing further to do.

        Nrrrrr�ZLocation�
index.html�	index.htm�rbzFile not foundzContent-typezContent-Length�z
Last-Modified)r�r�)�translate_pathr.�os�isdir�urllib�parseZurlsplit�endswithrSrZMOVED_PERMANENTLYZ
urlunsplitrTr>re�exists�list_directory�
guess_type�open�OSErrorr,�	NOT_FOUND�OK�fstat�filenor#r]�st_mtimer)	rr.r��partsZ	new_partsZnew_url�indexZctypeZfsrrrr��sF


z"SimpleHTTPRequestHandler.send_headc
Cs�ytj|�}Wn"tk
r0|jtjd�dSX|jdd�d�g}ytjj	|j
dd�}Wn tk
r|tjj	|�}YnXtj
|dd	�}tj�}d
|}|jd�|jd�|jd
|�|jd|�|jd|�|jd�x~|D]v}tj
j||�}|}	}
tj
j|��r"|d}	|d}
tj
j|��r8|d}	|jdtjj|
dd�tj
|	dd	�f�q�W|jd�dj|�j|d�}tj�}|j|�|jd�|jtj�|jdd|�|jdtt|���|j�|S)z�Helper to produce a directory listing (absent index.html).

        Return value is either a file object, or None (indicating an
        error).  In either case, the headers are sent, making the
        interface the same as for send_head().

        zNo permission to list directoryNcSs|j�S)N)r7)�arrr�<lambda>�sz9SimpleHTTPRequestHandler.list_directory.<locals>.<lambda>)�key�
surrogatepass)�errorsF)rLzDirectory listing for %szZ<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">z
<html>
<head>z@<meta http-equiv="Content-Type" content="text/html; charset=%s">z<title>%s</title>
</head>z<body>
<h1>%s</h1>z	<hr>
<ul>r�@z<li><a href="%s">%s</a></li>z</ul>
<hr>
</body>
</html>
�
�surrogateescaperzContent-typeztext/html; charset=%szContent-Length) r��listdirr�r,rr��sortr�r��unquoter.�UnicodeDecodeErrorrVrWrl�getfilesystemencodingr`rer��islinkrLrX�io�BytesIOrZ�seekrSr�rTr#r(r>)
rr.�list�rZdisplaypath�enc�title�name�fullnameZdisplaynameZlinknameZencodedr�rrrr��s\







z'SimpleHTTPRequestHandler.list_directorycCs�|jdd�d}|jdd�d}|j�jd�}ytjj|dd�}Wn tk
rbtjj|�}YnXtj|�}|jd�}t	d|�}t
j�}x8|D]0}t
jj
|�s�|t
jt
jfkr�q�t
jj||�}q�W|r�|d7}|S)	z�Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        �?rr�#rr�)r�N)r'r%r�r�r�r�r��	posixpath�normpath�filterr��getcwdr.�dirname�curdir�pardirre)rr.Ztrailing_slashr:Zwordrrrr��s$	



z'SimpleHTTPRequestHandler.translate_pathcCstj||�dS)a�Copy all data between two file objects.

        The SOURCE argument is a file object open for reading
        (or anything with a read() method) and the DESTINATION
        argument is a file object open for writing (or
        anything with a write() method).

        The only reason for overriding this would be to change
        the block size or perhaps to replace newlines by CRLF
        -- note however that this the default server uses this
        to copy binary data as well.

        N)�shutilZcopyfileobj)r�sourceZ
outputfilerrrr�sz!SimpleHTTPRequestHandler.copyfilecCsLtj|�\}}||jkr"|j|S|j�}||jkr>|j|S|jdSdS)a�Guess the type of a file.

        Argument is a PATH (a filename).

        Return value is a string of the form type/subtype,
        usable for a MIME Content-type header.

        The default implementation looks the file's extension
        up in the table self.extensions_map, using application/octet-stream
        as a default; however it would be permissible (if
        slow) to look inside the data to make a better guess.

        rN)r��splitext�extensions_mapr7)rr.�baseZextrrrr�)s



z#SimpleHTTPRequestHandler.guess_typezapplication/octet-streamz
text/plain)rz.pyz.cz.hN)rrrrr�rqr�r�r�r�r�r�r��	mimetypesZinitedZinitZ	types_map�copyr��updaterrrrrrs"	1:
c	Cs�|jd�\}}}tjj|�}|jd�}g}x<|dd�D],}|dkrN|j�q8|r8|dkr8|j|�q8W|r�|j�}|r�|dkr�|j�d}q�|dkr�d}nd}|r�dj||f�}ddj|�|f}dj|�}|S)	a�
    Given a URL path, remove extra '/'s and '.' path elements and collapse
    any '..' references and returns a collapsed path.

    Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
    The utility of this function is limited to is_cgi method and helps
    preventing some security attacks.

    Returns: The reconstituted URL, which will always start with a '/'.

    Raises: IndexError if too many '..' occur within the path.

    r�rNrz..rr���)�	partitionr�r�r�r'�popr`re)	r.�_�query�
path_partsZ
head_parts�partZ	tail_partZ	splitpath�collapsed_pathrrr�_url_collapse_pathNs.


r�cCsptrtSyddl}Wntk
r(dSXy|jd�daWn.tk
rjdtdd�|j�D��aYnXtS)	z$Internal routine to get nobody's uidrNr�nobodyrcss|]}|dVqdS)rNr)r|rvrrr�	<genexpr>�sznobody_uid.<locals>.<genexpr>r�)r��pwd�ImportError�getpwnamrR�maxZgetpwall)r�rrr�
nobody_uid�s r�cCstj|tj�S)zTest for executable file.)r��access�X_OK)r.rrr�
executable�sr�c@sVeZdZdZeed�ZdZdd�Zdd�Z	dd	�Z
d
dgZdd
�Zdd�Z
dd�ZdS)rz�Complete HTTP server with GET, HEAD and POST commands.

    GET and HEAD also support running CGI scripts.

    The POST command is *only* implemented for CGI scripts.

    �forkrcCs$|j�r|j�n|jtjd�dS)zRServe a POST request.

        This is only implemented for CGI scripts.

        zCan only POST to CGI scriptsN)�is_cgi�run_cgir,rrA)rrrr�do_POST�s

zCGIHTTPRequestHandler.do_POSTcCs|j�r|j�Stj|�SdS)z-Version of send_head that support CGI scriptsN)r�r�rr�)rrrrr��szCGIHTTPRequestHandler.send_headcCsPt|j�}|jdd�}|d|�||dd�}}||jkrL||f|_dSdS)a3Test whether self.path corresponds to a CGI script.

        Returns True and updates the cgi_info attribute to the tuple
        (dir, rest) if self.path requires running a CGI script.
        Returns False otherwise.

        If any exception is raised, the caller should assume that
        self.path was rejected as invalid and act accordingly.

        The default implementation tests whether the normalized url
        path begins with one of the strings in self.cgi_directories
        (and the next character is a '/' or the end of the string).

        rrNTF)r�r.�find�cgi_directories�cgi_info)rr�Zdir_sep�head�tailrrrr��s


zCGIHTTPRequestHandler.is_cgiz/cgi-binz/htbincCst|�S)z1Test whether argument path is an executable file.)r�)rr.rrr�
is_executable�sz#CGIHTTPRequestHandler.is_executablecCstjj|�\}}|j�dkS)z.Test whether argument path is a Python script.�.py�.pyw)r�r�)r�r.r�r7)rr.r�r�rrr�	is_python�szCGIHTTPRequestHandler.is_pythonc)Cs�|j\}}|d|}|jdt|�d�}x`|dkr�|d|�}||dd�}|j|�}tjj|�r�||}}|jdt|�d�}q,Pq,W|jd�\}}}	|jd�}|dkr�|d|�||d�}
}n
|d}
}|d|
}|j|�}tjj|��s|j	t
jd|�dStjj|��s2|j	t
j
d|�dS|j|�}
|j�sL|
�rn|j|��sn|j	t
j
d	|�dStjtj�}|j�|d
<|jj|d<d|d
<|j|d<t|jj�|d<|j|d<tjj|�}||d<|j|�|d<||d<|	�r�|	|d<|jd|d<|jj d�}|�r�|j!�}t|�dk�r�ddl"}ddl#}|d|d<|dj$�dk�r�y"|dj%d�}|j&|�j'd�}Wn|j(t)fk
�r�Yn&X|j!d�}t|�dk�r�|d|d<|jj d�dk�r�|jj*�|d<n|jd|d<|jj d�}|�r||d <|jj d!�}|�r"||d"<g}xN|jj+d#�D]>}|dd�d$k�rZ|j,|j-��n||d%d�j!d&�}�q4Wd&j.|�|d'<|jj d(�}|�r�||d)<t/d|jj0d*g��}d+j.|�}|�r�||d,<xd=D]}|j1|d��q�W|j2t
j3d.�|j4�|	j5d/d0�}|j�r.|
g}d1|k�r*|j,|�t6�}|j7j8�tj9�}|dk�r�tj:|d�\}}x0t;j;|j<gggd�d�r�|j<j=d��s^P�q^W|�r�|j>d2|�dSy\ytj?|�Wnt@k
�r�YnXtjA|j<jB�d�tjA|j7jB�d�tjC|||�Wn(|jjD|jE|j�tjFd3�YnX�n�ddlG} |g}!|j|��r�tHjI}"|"j$�jJd4��rv|"dd>�|"d?d�}"|"d7g|!}!d1|	k�r�|!j,|	�|jKd8| jL|!��ytM|�}#WntNtOfk
�r�d}#YnX| jP|!| jQ| jQ| jQ|d9�}$|jj$�d:k�r|#dk�r|j<j=|#�}%nd}%x4t;j;|j<jRgggd�d�rN|j<jRjSd��sP�qW|$jT|%�\}&}'|j7jU|&�|'�r||j>d;|'�|$jVjW�|$jXjW�|$jY}(|(�r�|j>d2|(�n
|jKd<�dS)@zExecute a CGI script.rrrNr�rzNo such CGI script (%r)z#CGI script is not a plain file (%r)z!CGI script is not executable (%r)ZSERVER_SOFTWAREZSERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZSERVER_PROTOCOLZSERVER_PORTZREQUEST_METHODZ	PATH_INFOZPATH_TRANSLATEDZSCRIPT_NAME�QUERY_STRINGZREMOTE_ADDR�
authorizationrZ	AUTH_TYPEZbasic�ascii�:ZREMOTE_USERzcontent-typeZCONTENT_TYPEzcontent-length�CONTENT_LENGTH�referer�HTTP_REFERER�acceptz	

 ��,ZHTTP_ACCEPTz
user-agent�HTTP_USER_AGENTZcookiez, �HTTP_COOKIE�REMOTE_HOSTzScript output follows�+rp�=zCGI script exit status %#x�zw.exerr�z-uzcommand: %s)�stdin�stdoutrm�envZpostz%szCGI script exited OK)r�r�r�r�r�r�������)Zr�r�r(r�r�r.r�r�r�r,rr��isfileZ	FORBIDDENr��	have_forkr�r��deepcopy�environr\Zserverrr-r#rrr�r�r�rzr5r6r'�base64�binasciir7rXZdecodebytes�decode�Error�UnicodeErrorZget_content_typeZgetallmatchingheadersr`�striprer�Zget_all�
setdefaultrSr�rcrPr�rCrDr��waitpid�selectr3�readrE�setuidr��dup2r��execveZhandle_errorZrequest�_exit�
subprocessrlr�r�rhZlist2cmdliner*�	TypeErrorr)�Popen�PIPEZ_sockZrecvZcommunicaterZrmrr��
returncode))r�dir�restr.�iZnextdirZnextrestZ	scriptdirr�r�ZscriptZ
scriptnameZ
scriptfileZispyr�Zuqrestr�rrZlengthr�r��lineZua�coZ
cookie_str�kZ
decoded_queryrkr��pid�stsrZcmdlineZinterp�nbytes�p�datar�rmZstatusrrrr��s4

























zCGIHTTPRequestHandler.run_cgiN)rrrrr@r�r�Zrbufsizer�r�r�r�r�r�r�rrrrr�s
zHTTP/1.0i@rc	Cs�||f}||_|||��b}|jj�}d}t|j|d|dd��y|j�Wn&tk
rttd�tjd�YnXWdQRXdS)zmTest the HTTP request handler class.

    This runs an HTTP server on port 8000 (or the port argument).

    z>Serving HTTP on {host} port {port} (http://{host}:{port}/) ...rr)rrz&
Keyboard interrupt received, exiting.N)	r-r
Zgetsockname�printrjZ
serve_forever�KeyboardInterruptrl�exit)	�HandlerClassZServerClassZprotocolr�bindrZhttpdZsaZ
serve_messagerrr�test�s
r%�__main__z--cgi�
store_truezRun as CGI Server)�action�helpz--bindz-bZADDRESSz8Specify alternate bind address [default: all interfaces])�default�metavarr)rZstorer�z&Specify alternate port [default: 8000])r(r*�type�nargsr))r#rr$)/rr��__all__Zemail.utilsrtrVZhttp.clientr1r�r�r�r�r
r�r
r	rlrsZurllib.parser�r��argparserr�r�r
rZStreamRequestHandlerrrr�r�r�r�rr%r�ArgumentParser�parser�add_argumentr*�
parse_argsrkZcgiZ
handler_classrr$rrrr�<module> sj3g]0
__pycache__/client.cpython-36.opt-1.pyc000064400000104460150532432170013626 0ustar003

Ow�h*��@srdZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
mZdddddd	d
ddd
ddddddddgZdZ
dZdZdZdZdZe�jejj�dd�ejjj�D�ZdZdZd Zejd!�jZejd"�jZ ejd#�Z!ejd$�Z"d%d&d'hZ#dCd)d*�Z$Gd+d,�d,ej%j&�Z'd-d.�Z(e'fd/d0�Z)Gd1d�dej*�Z+Gd2d�d�Z,yddl-Z-Wne.k
�rlYnXGd3d4�d4e,�Z/ej0d4�Gd5d�de1�Z2Gd6d�de2�Z3Gd7d�de2�Z4Gd8d�de2�Z5Gd9d	�d	e2�Z6Gd:d
�d
e2�Z7Gd;d�de2�Z8Gd<d
�d
e2�Z9Gd=d�de9�Z:Gd>d�de9�Z;Gd?d�de9�Z<Gd@d�de2�Z=GdAd�de2�Z>GdBd�de?e=�Z@e2ZAdS)Da�
HTTP/1.1 client library

<intro stuff goes here>
<other stuff, too>

HTTPConnection goes through a number of "states", which define when a client
may legally make another request or fetch the response for a particular
request. This diagram details these state transitions:

    (null)
      |
      | HTTPConnection()
      v
    Idle
      |
      | putrequest()
      v
    Request-started
      |
      | ( putheader() )*  endheaders()
      v
    Request-sent
      |\_____________________________
      |                              | getresponse() raises
      | response = getresponse()     | ConnectionError
      v                              v
    Unread-response                Idle
    [Response-headers-read]
      |\____________________
      |                     |
      | response.read()     | putrequest()
      v                     v
    Idle                  Req-started-unread-response
                     ______/|
                   /        |
   response.read() |        | ( putheader() )*  endheaders()
                   v        v
       Request-started    Req-sent-unread-response
                            |
                            | response.read()
                            v
                          Request-sent

This diagram presents the following rules:
  -- a second request may not be started until {response-headers-read}
  -- a response [object] cannot be retrieved until {request-sent}
  -- there is no differentiation between an unread response body and a
     partially read response body

Note: this enforcement is applied by the HTTPConnection class. The
      HTTPResponse class does not enforce this state machine, which
      implies sophisticated clients may accelerate the request/response
      pipeline. Caution should be taken, though: accelerating the states
      beyond the above pattern may imply knowledge of the server's
      connection-close behavior for certain requests. For example, it
      is impossible to tell whether the server will close the connection
      UNTIL the response headers have been read; this means that further
      requests cannot be placed into the pipeline until it is known that
      the server will NOT be closing the connection.

Logical State                  __state            __response
-------------                  -------            ----------
Idle                           _CS_IDLE           None
Request-started                _CS_REQ_STARTED    None
Request-sent                   _CS_REQ_SENT       None
Unread-response                _CS_IDLE           <response_class>
Req-started-unread-response    _CS_REQ_STARTED    <response_class>
Req-sent-unread-response       _CS_REQ_SENT       <response_class>
�N)�urlsplit�HTTPResponse�HTTPConnection�
HTTPException�NotConnected�UnknownProtocol�UnknownTransferEncoding�UnimplementedFileMode�IncompleteRead�
InvalidURL�ImproperConnectionState�CannotSendRequest�CannotSendHeader�ResponseNotReady�
BadStatusLine�LineTooLong�RemoteDisconnected�error�	responses�Pi�ZUNKNOWNZIdlezRequest-startedzRequest-sentcCsi|]}|j|�qS�)�phrase)�.0�vrr�#/usr/lib64/python3.6/http/client.py�
<dictcomp>ksrii�ds[^:\s][^:\r\n]*s\n(?![ \t])|\r(?![ \t\n])z[- ]z[-]ZPATCHZPOSTZPUT�datacCsfy
|jd�Stk
r`}z:t|j|j|j|jd|j�||j|j�|f�d�WYdd}~XnXdS)z<Call data.encode("latin-1") but show a better error message.zlatin-1z`%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') if you want to send it encoded in UTF-8.N)�encode�UnicodeEncodeError�encoding�object�start�end�title)r�name�errrrr�_encode�s
r'c@seZdZdd�ZdS)�HTTPMessagecCsn|j�d}t|�}g}d}xL|j�D]@}|d|�j�|krDd}n|dd�j�sXd}|r&|j|�q&W|S)a�Find all header lines matching a given header name.

        Look through the list of headers and find all lines matching a given
        header name (and their continuation lines).  A list of the lines is
        returned, without interpretation.  If the header does not occur, an
        empty list is returned.  If the header occurs multiple times, all
        occurrences are returned.  Case is not important in the header name.

        �:rN�)�lower�len�keys�isspace�append)�selfr%�nZlstZhit�linerrr�getallmatchingheaders�s
z!HTTPMessage.getallmatchingheadersN)�__name__�
__module__�__qualname__r3rrrrr(�sr(cCs\g}xR|jtd�}t|�tkr(td��|j|�t|�tkrJtdt��|dkrPqW|S)z�Reads potential header lines into a list from a file pointer.

    Length of line is limited by _MAXLINE, and number of
    headers is limited by _MAXHEADERS.
    r*zheader linezgot more than %d headers�
�
�)r7r8r9)�readline�_MAXLINEr,rr/�_MAXHEADERSr)�fp�headersr2rrr�
_read_headers�s
r?cCs,t|�}dj|�jd�}tjj|d�j|�S)aGParses only RFC2822 headers from a file pointer.

    email Parser wants to see strings rather than bytes.
    But a TextIOWrapper around self.rfile would buffer too many bytes
    from the stream, bytes which we later need to read as bytes.
    So we read the correct bytes here, as bytes, for email Parser
    to parse.

    r9z
iso-8859-1)�_class)r?�join�decode�email�parserZParserZparsestr)r=r@r>Zhstringrrr�
parse_headers�s
rEcseZdZd@dd�Zdd�Zdd�Zd	d
�Zdd�Z�fd
d�Z�fdd�Z	dd�Z
dd�ZdAdd�Zdd�Z
dd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�ZdCd(d)�ZdEd*d+�ZdG�fd,d-�	Zd.d/�Zd0d1�Zd2d3�ZdHd4d5�Zd6d7�Zd8d9�Zd:d;�Zd<d=�Zd>d?�Z �Z!S)IrrNcCsR|jd�|_||_||_d|_|_t|_t|_t|_	t|_
t|_t|_t|_
dS)N�rb)�makefiler=�
debuglevel�_methodr>�msg�_UNKNOWN�version�status�reason�chunked�
chunk_left�length�
will_close)r0�sockrH�method�urlrrr�__init__�szHTTPResponse.__init__cCst|jjtd�d�}t|�tkr*td��|jdkrBtdt|��|sNt	d��y|j
dd�\}}}WnFtk
r�y|j
dd�\}}d}Wntk
r�d}YnXYnX|jd	�s�|j
�t|��y$t|�}|d
ks�|dkr�t|��Wntk
�rt|��YnX|||fS)Nr*z
iso-8859-1zstatus linerzreply:z-Remote end closed connection without response��zHTTP/ri�)�strr=r:r;r,rrH�print�reprr�split�
ValueError�
startswith�_close_connr�int)r0r2rLrMrNrrr�_read_statuss2

zHTTPResponse._read_statuscCs�|jdk	rdSx<|j�\}}}|tkr(Pt|j�}|jdkrFtd|�~qW||_|_|j	�|_
|dkrrd|_n|jd�r�d|_nt
|��t|j�|_|_|jdkr�x&|jD]}td|d	|jj|��q�W|jjd
�}|r�|j�dkr�d|_d|_nd
|_|j�|_d|_|jjd�}|jjd
�}|�rx|j�rxyt|�|_Wntk
�rbd|_YnX|jdk�r~d|_nd|_|tk�s�|tk�s�d|k�o�dkn�s�|jdk�r�d|_|j�r�|j�r�|jdk�r�d|_dS)Nrzheaders:�HTTP/1.0�HTTP/0.9�
zHTTP/1.�zheader:r)ztransfer-encodingrOTFzcontent-lengthr���HEAD)rbrc)r>raZCONTINUEr?r=rHrZ�coderM�striprNrLr^rrErJ�getr+rOrP�_check_closerRrQr`r]Z
NO_CONTENTZNOT_MODIFIEDrI)r0rLrMrNZskipped_headers�hdrZtr_encrQrrr�begin9s\









zHTTPResponse.begincCs�|jjd�}|jdkr:|jjd�}|r6d|j�kr6dSdS|jjd�rJdS|r^d|j�kr^dS|jjd�}|r~d|j�kr~dSdS)NZ
connectionre�closeTFz
keep-alivezproxy-connection)r>rjrLr+)r0ZconnZpconnrrrrk�s
zHTTPResponse._check_closecCs|j}d|_|j�dS)N)r=rn)r0r=rrrr_�szHTTPResponse._close_connc
s$zt�j�Wd|jr|j�XdS)N)�superrnr=r_)r0)�	__class__rrrn�szHTTPResponse.closecst�j�|jr|jj�dS)N)ro�flushr=)r0)rprrrq�s
zHTTPResponse.flushcCsdS)zAlways returns TrueTr)r0rrr�readable�szHTTPResponse.readablecCs
|jdkS)z!True if the connection is closed.N)r=)r0rrr�isclosed�szHTTPResponse.isclosedcCs�|jdkrdS|jdkr$|j�dS|dk	rRt|�}|j|�}t|�d|�j�S|jr`|j�S|j	dkrv|jj
�}n6y|j|j	�}Wntk
r�|j��YnXd|_	|j�|SdS)Nr9rgr)
r=rIr_�	bytearray�readinto�
memoryview�tobytesrO�_readall_chunkedrQ�read�
_safe_readr
)r0�amt�br1�srrrry�s*



zHTTPResponse.readcCs�|jdkrdS|jdkr$|j�dS|jr4|j|�S|jdk	r^t|�|jkr^t|�d|j�}|jj|�}|r~|r~|j�n&|jdk	r�|j|8_|js�|j�|S)z^Read up to len(b) bytes into bytearray b and return the number
        of bytes read.
        Nrrg)	r=rIr_rO�_readinto_chunkedrQr,rvru)r0r|r1rrrru�s$






zHTTPResponse.readintocCsp|jjtd�}t|�tkr$td��|jd�}|dkrB|d|�}y
t|d�Stk
rj|j��YnXdS)Nr*z
chunk size�;r�)	r=r:r;r,r�findr`r]r_)r0r2�irrr�_read_next_chunk_size
s

z"HTTPResponse._read_next_chunk_sizecCs>x8|jjtd�}t|�tkr&td��|s,P|dkrPqWdS)Nr*ztrailer line�
r8r9)r�r8r9)r=r:r;r,r)r0r2rrr�_read_and_discard_trailersz&HTTPResponse._read_and_discard_trailercCsl|j}|sh|dk	r|jd�y|j�}Wntk
rDtd��YnX|dkrb|j�|j�d}||_|S)NrWr9r)rPrzr�r]r
r�r_)r0rPrrr�_get_chunk_left(s
zHTTPResponse._get_chunk_leftcCsdg}y8x,|j�}|dkrP|j|j|��d|_qWdj|�Stk
r^tdj|���YnXdS)Nrr9)r�r/rzrPrAr
)r0�valuerPrrrrx@s

zHTTPResponse._readall_chunkedcCs�d}t|�}yvxp|j�}|dkr$|St|�|krL|j|�}|||_||S|d|�}|j|�}||d�}||7}d|_qWWn(tk
r�tt|d|����YnXdS)Nr)rvr�r,�_safe_readintorPr
�bytes)r0r|�total_bytes�mvbrPr1�temp_mvbrrrr~Ns$


zHTTPResponse._readinto_chunkedcCsXg}xH|dkrL|jjt|t��}|s4tdj|�|��|j|�|t|�8}qWdj|�S)aVRead the number of bytes requested, compensating for partial reads.

        Normally, we have a blocking socket, but a read() can be interrupted
        by a signal (resulting in a partial read).

        Note that we cannot distinguish between EOF and an interrupt when zero
        bytes have been read. IncompleteRead() will be raised in this
        situation.

        This function should be used when <amt> bytes "should" be present for
        reading. If the bytes are truly not available (due to EOF), then the
        IncompleteRead exception can be used to detect the problem.
        rr9)r=ry�min�	MAXAMOUNTr
rAr/r,)r0r{r}�chunkrrrrzfs

zHTTPResponse._safe_readcCs�d}t|�}xt|t|�kr�tt|�kr@|dt�}|jj|�}n|jj|�}|sjtt|d|��t|���||d�}||7}qW|S)z2Same as _safe_read, but for reading into a buffer.rN)rvr,r�r=rur
r�)r0r|r�r�r�r1rrrr�}szHTTPResponse._safe_readintor*cCs�|jdks|jdkrdS|jr(|j|�S|jdk	rJ|dksD||jkrJ|j}y|jj|�}Wn*tk
r�|dkrt�|jjd�}YnX|r�|r�|j�n|jdk	r�|jt|�8_|S)zvRead with at most one underlying system call.  If at least one
        byte is buffered, return that instead.
        Nrgr9rr�ii@)	r=rIrO�_read1_chunkedrQ�read1r]r_r,)r0r1�resultrrrr��s"



zHTTPResponse.read1cCs4|jdks|jdkrdS|jr(|j|�S|jj|�S)Nrgr9)r=rIrO�
_peek_chunked�peek)r0r1rrrr��s

zHTTPResponse.peekcs�|jdks|jdkrdS|jr*t�j|�S|jdk	rL|dksF||jkrL|j}|jj|�}|rl|rl|j�n|jdk	r�|jt|�8_|S)Nrgr9r)r=rIrOror:rQr_r,)r0�limitr�)rprrr:�s


zHTTPResponse.readlinecCsf|j�}|dks|dkrdSd|ko.|kns8|}|jj|�}|jt|�8_|sbtd��|S)Nrr9)r�r=r�rPr,r
)r0r1rPryrrrr��szHTTPResponse._read1_chunkedcCsBy|j�}Wntk
r dSX|dkr.dS|jj|�d|�S)Nr9)r�r
r=r�)r0r1rPrrrr��szHTTPResponse._peek_chunkedcCs
|jj�S)N)r=�fileno)r0rrrr��szHTTPResponse.filenocCsH|jdkrt��|jj|�p|}t|t�s6t|d�r:|Sdj|�SdS)axReturns the value of the header matching *name*.

        If there are multiple matching headers, the values are
        combined into a single string separated by commas and spaces.

        If no matching header is found, returns *default* or None if
        the *default* is not specified.

        If the headers are unknown, raises http.client.ResponseNotReady.

        N�__iter__z, )r>rZget_all�
isinstancerY�hasattrrA)r0r%�defaultr>rrr�	getheader�s
zHTTPResponse.getheadercCs|jdkrt��t|jj��S)z&Return list of (header, value) tuples.N)r>r�list�items)r0rrr�
getheaders�s
zHTTPResponse.getheaderscCs|S)Nr)r0rrrr��szHTTPResponse.__iter__cCs|jS)ajReturns an instance of the class mimetools.Message containing
        meta-information associated with the URL.

        When the method is HTTP, these headers are those returned by
        the server at the head of the retrieved HTML page (including
        Content-Length and Content-Type).

        When the method is FTP, a Content-Length header will be
        present if (as is now usual) the server passed back a file
        length in response to the FTP retrieval request. A
        Content-Type header will be present if the MIME type can be
        guessed.

        When the method is local-file, returned headers will include
        a Date representing the file's last-modified time, a
        Content-Length giving file size, and a Content-Type
        containing a guess at the file's type. See also the
        description of the mimetools module.

        )r>)r0rrr�info�szHTTPResponse.infocCs|jS)aZReturn the real URL of the page.

        In some cases, the HTTP server redirects a client to another
        URL. The urlopen() function handles this transparently, but in
        some cases the caller needs to know which URL the client was
        redirected to. The geturl() method can be used to get at this
        redirected URL.

        )rU)r0rrr�geturls
zHTTPResponse.geturlcCs|jS)zuReturn the HTTP status code that was sent with the response,
        or None if the URL is not an HTTP URL.

        )rM)r0rrr�getcodeszHTTPResponse.getcode)rNN)N���)r�r�)r�r�)r�)N)"r4r5r6rVrarmrkr_rnrqrrrsryrur�r�r�rxr~rzr�r�r�r:r�r�r�r�r�r�r�r�r��
__classcell__rr)rprr�s<	
!K

 "

	

c@s�eZdZdZdZeZeZdZ	dZ
edd��Zedd��Z
d	ejd	fd
d�Zd0dd
�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd1dd �Zd2d!d"�Zd#d$�Zd%d&�Zd3dd'�d(d)�Zd	ifdd'�d*d+�Zd,d-�Z d.d/�Z!d	S)4rrezHTTP/1.1r*rcCst|tj�S)zFTest whether a file-like object is a text or a binary stream.
        )r��io�
TextIOBase)�streamrrr�
_is_textIO0szHTTPConnection._is_textIOcCsd|dkr|j�tkrdSdSt|d�r*dSyt|�}|jStk
rLYnXt|t�r`t|�SdS)aGet the content-length based on the body.

        If the body is None, we set Content-Length: 0 for methods that expect
        a body (RFC 7230, Section 3.3.2). We also set the Content-Length for
        any method if the body is a str or bytes-like object and not a file.
        Nrry)	�upper�_METHODS_EXPECTING_BODYr�rv�nbytes�	TypeErrorr�rYr,)�bodyrTZmvrrr�_get_content_length6s

z"HTTPConnection._get_content_lengthNcCs\||_||_d|_g|_d|_t|_d|_d|_d|_	i|_
|j||�\|_|_
tj|_dS)N)�timeout�source_addressrS�_buffer�_HTTPConnection__response�_CS_IDLE�_HTTPConnection__staterI�_tunnel_host�_tunnel_port�_tunnel_headers�
_get_hostport�host�port�socketZcreate_connection�_create_connection)r0r�r�r�r�rrrrVVszHTTPConnection.__init__cCs<|jrtd��|j||�\|_|_|r.||_n
|jj�dS)aDSet up host and port for HTTP CONNECT tunnelling.

        In a connection that uses HTTP CONNECT tunneling, the host passed to the
        constructor is used as a proxy server that relays all communication to
        the endpoint passed to `set_tunnel`. This done by sending an HTTP
        CONNECT request to the proxy server when the connection is established.

        This method must be called before the HTML connection has been
        established.

        The headers argument should be a mapping of extra HTTP headers to send
        with the CONNECT request.
        z.Can't set up tunnel for established connectionN)rS�RuntimeErrorr�r�r�r��clear)r0r�r�r>rrr�
set_tunneliszHTTPConnection.set_tunnelcCs�|dkr�|jd�}|jd�}||kr�yt||dd��}WnHtk
r�||dd�dkrh|j}ntd||dd���YnX|d|�}n|j}|r�|ddkr�|ddkr�|dd	�}||fS)
Nr)�]r*rXznonnumeric port: '%s'r�[r�r�)�rfindr`r]�default_portr)r0r�r�r��jrrrr��s

zHTTPConnection._get_hostportcCs
||_dS)N)rH)r0�levelrrr�set_debuglevel�szHTTPConnection.set_debuglevelcCsd|j|jf}|jd�}|j|�x6|jj�D](\}}d||f}|jd�}|j|�q0W|jd�|j|j|jd�}|j	�\}}	}
|	t
jjkr�|j
�td|	|
j�f��xP|jjtd�}t|�tkr�td	��|s�P|dkr�P|jdkr�td
|j��q�WdS)NzCONNECT %s:%d HTTP/1.0
�asciiz%s: %s
zlatin-1�
)rTzTunnel connection failed: %d %sr*zheader liner8r9rzheader:)r�r8r9)r�r�r�sendr�r��response_classrSrIra�http�
HTTPStatusZOKrn�OSErrorrir=r:r;r,rrHrZrB)r0Zconnect_strZ
connect_bytes�headerr�Z
header_strZheader_bytes�responserLrh�messager2rrr�_tunnel�s2





zHTTPConnection._tunnelcCsB|j|j|jf|j|j�|_|jjtjtj	d�|j
r>|j�dS)z3Connect to the host and port specified in __init__.r*N)r�r�r�r�r�rSZ
setsockoptr�ZIPPROTO_TCPZTCP_NODELAYr�r�)r0rrr�connect�s
zHTTPConnection.connectcCsBt|_z|j}|r d|_|j�Wd|j}|r<d|_|j�XdS)z(Close the connection to the HTTP server.N)r�r�rSrnr�)r0rSr�rrrrn�szHTTPConnection.closecCs|jdkr |jr|j�nt��|jdkr8tdt|��d}t|d�r�|jdkrXtd�|j|�}|rx|jdkrxtd�x.|j	|�}|s�P|r�|j
d�}|jj|�qzWdSy|jj|�WnNtk
�r
t
|tj�r�x*|D]}|jj|�q�Wntd	t|���YnXdS)
z�Send `data' to the server.
        ``data`` can be a string object, a bytes object, an array object, a
        file-like object that supports a .read() method, or an iterable object.
        Nrzsend:i ryzsendIng a read()ablezencoding file using iso-8859-1z
iso-8859-1z9data should be a bytes-like object or an iterable, got %r)rS�	auto_openr�rrHrZr[r�r�ryrZsendallr�r��collections�Iterable�type)r0r�	blocksizer�	datablock�drrrr��s:








zHTTPConnection.sendcCs|jj|�dS)zuAdd a line of output to the current request buffer.

        Assumes that the line does *not* end with \r\n.
        N)r�r/)r0r}rrr�_output�szHTTPConnection._outputccsdd}|jdkrtd�|j|�}|r6|jdkr6td�x(|j|�}|sHP|rV|jd�}|Vq8WdS)Ni rzsendIng a read()ablezencoding file using iso-8859-1z
iso-8859-1)rHrZr�ryr)r0rrr�rr�rrr�_read_readable�s



zHTTPConnection._read_readableFcCs$|jjd
�dj|j�}|jdd�=|j|�|dk	�r t|d�rN|j|�}nZyt|�WnFtk
r�yt|�}Wn$tk
r�tdt	|���YnXYnX|f}xZ|D]R}|s�|j
dkr�td�q�|r�|jdkr�t
|�d	�d
�jd�|d}|j|�q�W|�r |jdk�r |jd�dS)z�Send the currently buffered request and clear the buffer.

        Appends an extra \r\n to the buffer.
        A message_body may be specified, to be appended to the request.
        r9s
NryzAmessage_body should be a bytes-like object or an iterable, got %rrzZero length chunk ignoredre�Xz
r�s0

)r9r9)r��extendrAr�r�r�rvr��iterr�rHrZ�	_http_vsnr,r)r0�message_body�encode_chunkedrJZchunksr�rrr�_send_outputs4




zHTTPConnection._send_outputc

Cs�|jr|jj�rd|_|jtkr(t|_n
t|j��|j|�||_|sJd}tj	|�}|rrt
d|�d|j��d���d|||jf}|j
|jd��|jdk�r�|�s�d	}|jd
�r�t|�\}}}}}|�ry|jd�}	Wntk
r�|jd�}	YnX|jd|	�n�|j�r|j}
|j}n|j}
|j}y|
jd�}Wn tk
�rV|
jd�}YnX|
jd
�dk�rtd|d}||jk�r�|jd|�n|jd�}|jdd||f�|�s�|jdd�ndS)a`Send a request to the server.

        `method' specifies an HTTP request method, e.g. 'GET'.
        `url' specifies the object being requested, e.g. '/index.html'.
        `skip_host' if True does not add automatically a 'Host:' header
        `skip_accept_encoding' if True does not add automatically an
           'Accept-Encoding:' header
        N�/z&URL can't contain control characters. z (found at least �)z%s %s %sr�rerXr�ZidnaZHostr)r�[�]z%s:%szAccept-EncodingZidentity)r�rsr�r��_CS_REQ_STARTEDr
�_validate_methodrI�!_contains_disallowed_url_pchar_re�searchr�group�
_http_vsn_strr�rr�r^rr�	putheaderr�r�r�r�r�r�rB)
r0rTrU�	skip_host�skip_accept_encoding�match�requestZnetlocZnilZ
netloc_encr�r�Zhost_encrrr�
putrequestAsV






zHTTPConnection.putrequestcCs,tj|�}|r(td|�d|j��d���dS)z&Validate a method name for putrequest.z)method can't contain control characters. z (found at least r�N)�$_contains_disallowed_method_pchar_rer�r]r�)r0rTr�rrrr��s
zHTTPConnection._validate_methodcGs�|jtkrt��t|d�r$|jd�}t|�s:td|f��t|�}xht|�D]\\}}t|d�rn|jd�||<nt	|t
�r�t|�jd�||<t||�rLtd||f��qLWdj
|�}|d|}|j|�dS)	zkSend a request header line to the server.

        For example: h.putheader('Accept', 'text/html')
        rr�zInvalid header name %rzlatin-1zInvalid header value %rs
	s: N)r�r�rr�r�_is_legal_header_namer]r��	enumerater�r`rY�_is_illegal_header_valuerAr�)r0r��valuesr�Z	one_valuer�rrrr��s"





zHTTPConnection.putheader)r�cCs*|jtkrt|_nt��|j||d�dS)z�Indicate that the last header line has been sent to the server.

        This method sends the request to the server.  The optional message_body
        argument can be used to pass a message body associated with the
        request.
        )r�N)r�r��_CS_REQ_SENTrr�)r0r�r�rrr�
endheaders�s
zHTTPConnection.endheaderscCs|j|||||�dS)z&Send a complete request to the server.N)�
_send_request)r0rTrUr�r>r�rrrr��szHTTPConnection.requestcCs�tdd�|D��}i}d|kr&d|d<d|kr6d|d<|j||f|�d|kr�d	|kr�d
}|j||�}|dkr�|dk	r�|jdkr�td|�d
}|jdd�q�|jdt|��nd
}x |j�D]\}	}
|j|	|
�q�Wt|t�r�t	|d�}|j
||d�dS)Ncss|]}|j�VqdS)N)r+)r�krrr�	<genexpr>�sz/HTTPConnection._send_request.<locals>.<genexpr>r�r*r�zaccept-encodingr�zcontent-lengthztransfer-encodingFrzUnable to determine size of %rTzTransfer-EncodingrOzContent-Lengthr�)r�)�	frozensetr�r�rHrZr�rYr�r�r'r�)r0rTrUr�r>r�Zheader_namesZskipsZcontent_lengthrlr�rrrr��s0	


zHTTPConnection._send_requestcCs�|jr|jj�rd|_|jtks&|jr0t|j��|jdkrR|j|j|j|jd�}n|j|j|jd�}yLy|j	�Wnt
k
r�|j��YnXt|_|j
r�|j�n||_|S|j��YnXdS)a)Get the response from the server.

        If the HTTPConnection is in the correct state, returns an
        instance of HTTPResponse or of whatever object is returned by
        the response_class variable.

        If a request has not been sent or if a previous response has
        not be handled, ResponseNotReady is raised.  If the HTTP
        response indicates that the connection should be closed, then
        it will be closed before the response is returned.  When the
        connection is closed, the underlying socket is closed.
        Nr)rT)r�rsr�r�rrHr�rSrIrm�ConnectionErrorrnr�rR)r0r�rrr�getresponse)s,


zHTTPConnection.getresponse)NN)NF)FF)N)"r4r5r6r�r�rr��	HTTP_PORTr�r�rH�staticmethodr�r�r��_GLOBAL_DEFAULT_TIMEOUTrVr�r�r�r�r�rnr�r�r�r�r�r�r�r�r�r�r�rrrrr&s< 
	'
6
	
.csFeZdZdZeZdddejdfddd��fdd�Z�fdd�Z	�Z
S)�HTTPSConnectionz(This class allows communication via SSL.N)�context�check_hostnamecs�tt|�j||||�|dk	s.|dk	s.|dk	rDddl}	|	jdtd�||_||_|dkrptj	�}|j
dk	rpd|_
|jtjk}
|dkr�|j
}|r�|
r�td��|s�|r�|j||�|j
dk	r�d|_
||_||_dS)NrzTkey_file, cert_file and check_hostname are deprecated, use a custom context instead.rWTzMcheck_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED)rorrV�warnings�warn�DeprecationWarning�key_file�	cert_file�sslZ_create_default_https_contextZpost_handshake_authZverify_modeZ	CERT_NONErr]Zload_cert_chain�_context�_check_hostname)r0r�r�rr	r�r�rrrZwill_verify)rprrrVts0


zHTTPSConnection.__init__cs�t�j�|jr|j}n|j}|jj|j|d�|_|jjr�|jr�yt	j
|jj�|�Wn.tk
r�|jj
tj�|jj��YnXdS)z(Connect to a host on a given (SSL) port.)�server_hostnameN)ror�r�r�rZwrap_socketrSrrr
Zmatch_hostnameZgetpeercert�	ExceptionZshutdownr�Z	SHUT_RDWRrn)r0r
)rprrr��s



zHTTPSConnection.connect)r4r5r6�__doc__�
HTTPS_PORTr�r�rrVr�r�rr)rprrmsrc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdd�ZdS)rcCs|f|_||_dS)N)�argsrL)r0rLrrrrV�szUnknownProtocol.__init__N)r4r5r6rVrrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)r	N)r4r5r6rrrrr	�sc@s&eZdZddd�Zdd�Zdd�ZdS)	r
NcCs|f|_||_||_dS)N)r�partial�expected)r0rrrrrrV�szIncompleteRead.__init__cCs2|jdk	rd|j}nd}d|jjt|j�|fS)Nz, %i more expectedrXz%s(%i bytes read%s))rrpr4r,r)r0�errr�__repr__�s

zIncompleteRead.__repr__cCst|�S)N)r[)r0rrr�__str__�szIncompleteRead.__str__)N)r4r5r6rVrrrrrrr
�s
c@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)r
N)r4r5r6rrrrr
�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdd�ZdS)rcCs|st|�}|f|_||_dS)N)r[rr2)r0r2rrrrV�szBadStatusLine.__init__N)r4r5r6rVrrrrr�sc@seZdZdd�ZdS)rcCstj|dt|f�dS)Nz&got more than %d bytes when reading %s)rrVr;)r0Z	line_typerrrrV�szLineTooLong.__init__N)r4r5r6rVrrrrr�sc@seZdZdd�ZdS)rcOs"tj|d�tj|f|�|�dS)NrX)rrV�ConnectionResetError)r0�pos�kwrrrrV�szRemoteDisconnected.__init__N)r4r5r6rVrrrrr�s)r)BrZemail.parserrCZ
email.messager�r��os�rer�r�Zurllib.parser�__all__r�rrKr�r�r��globals�updater��__members__r�rr�r;r<�compile�	fullmatchr�r�r�r�r�r�r'r�ZMessager(r?rE�BufferedIOBaserrr
�ImportErrorrr/rrrrrrr	r
rr
rrrrrrrrrrr�<module>Es�



9F=
__pycache__/client.cpython-36.opt-2.pyc000064400000062146150532432170013633 0ustar003

Ow�h*��@snddlZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
ddddddd	d
ddd
dddddddgZdZdZ
dZdZdZdZe�jejj�dd�ejjj�D�ZdZdZdZejd �jZejd!�jZejd"�Z ejd#�Z!d$d%d&hZ"dBd(d)�Z#Gd*d+�d+ej$j%�Z&d,d-�Z'e&fd.d/�Z(Gd0d�dej)�Z*Gd1d�d�Z+yddl,Z,Wne-k
�rhYnXGd2d3�d3e+�Z.ej/d3�Gd4d�de0�Z1Gd5d�de1�Z2Gd6d�de1�Z3Gd7d�de1�Z4Gd8d�de1�Z5Gd9d	�d	e1�Z6Gd:d
�d
e1�Z7Gd;d�de1�Z8Gd<d
�d
e8�Z9Gd=d�de8�Z:Gd>d�de8�Z;Gd?d�de1�Z<Gd@d�de1�Z=GdAd�de>e<�Z?e1Z@dS)C�N)�urlsplit�HTTPResponse�HTTPConnection�
HTTPException�NotConnected�UnknownProtocol�UnknownTransferEncoding�UnimplementedFileMode�IncompleteRead�
InvalidURL�ImproperConnectionState�CannotSendRequest�CannotSendHeader�ResponseNotReady�
BadStatusLine�LineTooLong�RemoteDisconnected�error�	responses�Pi�ZUNKNOWNZIdlezRequest-startedzRequest-sentcCsi|]}|j|�qS�)�phrase)�.0�vrr�#/usr/lib64/python3.6/http/client.py�
<dictcomp>ksrii�ds[^:\s][^:\r\n]*s\n(?![ \t])|\r(?![ \t\n])z[- ]z[-]ZPATCHZPOSTZPUT�datacCsfy
|jd�Stk
r`}z:t|j|j|j|jd|j�||j|j�|f�d�WYdd}~XnXdS)Nzlatin-1z`%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') if you want to send it encoded in UTF-8.)�encode�UnicodeEncodeError�encoding�object�start�end�title)r�name�errrrr�_encode�s
r'c@seZdZdd�ZdS)�HTTPMessagecCsn|j�d}t|�}g}d}xL|j�D]@}|d|�j�|krDd}n|dd�j�sXd}|r&|j|�q&W|S)N�:r�)�lower�len�keys�isspace�append)�selfr%�nZlstZhit�linerrr�getallmatchingheaders�s
z!HTTPMessage.getallmatchingheadersN)�__name__�
__module__�__qualname__r3rrrrr(�sr(cCs\g}xR|jtd�}t|�tkr(td��|j|�t|�tkrJtdt��|dkrPqW|S)Nr*zheader linezgot more than %d headers�
�
�)r7r8r9)�readline�_MAXLINEr,rr/�_MAXHEADERSr)�fp�headersr2rrr�
_read_headers�s
r?cCs,t|�}dj|�jd�}tjj|d�j|�S)Nr9z
iso-8859-1)�_class)r?�join�decode�email�parserZParserZparsestr)r=r@r>Zhstringrrr�
parse_headers�s
rEcseZdZd@dd�Zdd�Zdd�Zd	d
�Zdd�Z�fd
d�Z�fdd�Z	dd�Z
dd�ZdAdd�Zdd�Z
dd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�ZdCd(d)�ZdEd*d+�ZdG�fd,d-�	Zd.d/�Zd0d1�Zd2d3�ZdHd4d5�Zd6d7�Zd8d9�Zd:d;�Zd<d=�Zd>d?�Z �Z!S)IrrNcCsR|jd�|_||_||_d|_|_t|_t|_t|_	t|_
t|_t|_t|_
dS)N�rb)�makefiler=�
debuglevel�_methodr>�msg�_UNKNOWN�version�status�reason�chunked�
chunk_left�length�
will_close)r0�sockrH�method�urlrrr�__init__�szHTTPResponse.__init__cCst|jjtd�d�}t|�tkr*td��|jdkrBtdt|��|sNt	d��y|j
dd�\}}}WnFtk
r�y|j
dd�\}}d}Wntk
r�d}YnXYnX|jd	�s�|j
�t|��y$t|�}|d
ks�|dkr�t|��Wntk
�rt|��YnX|||fS)Nr*z
iso-8859-1zstatus linerzreply:z-Remote end closed connection without response��zHTTP/ri�)�strr=r:r;r,rrH�print�reprr�split�
ValueError�
startswith�_close_connr�int)r0r2rLrMrNrrr�_read_statuss2

zHTTPResponse._read_statuscCs�|jdk	rdSx<|j�\}}}|tkr(Pt|j�}|jdkrFtd|�~qW||_|_|j	�|_
|dkrrd|_n|jd�r�d|_nt
|��t|j�|_|_|jdkr�x&|jD]}td|d	|jj|��q�W|jjd
�}|r�|j�dkr�d|_d|_nd
|_|j�|_d|_|jjd�}|jjd
�}|�rx|j�rxyt|�|_Wntk
�rbd|_YnX|jdk�r~d|_nd|_|tk�s�|tk�s�d|k�o�dkn�s�|jdk�r�d|_|j�r�|j�r�|jdk�r�d|_dS)Nrzheaders:�HTTP/1.0�HTTP/0.9�
zHTTP/1.�zheader:r)ztransfer-encodingrOTFzcontent-lengthr���HEAD)rbrc)r>raZCONTINUEr?r=rHrZ�coderM�striprNrLr^rrErJ�getr+rOrP�_check_closerRrQr`r]Z
NO_CONTENTZNOT_MODIFIEDrI)r0rLrMrNZskipped_headers�hdrZtr_encrQrrr�begin9s\









zHTTPResponse.begincCs�|jjd�}|jdkr:|jjd�}|r6d|j�kr6dSdS|jjd�rJdS|r^d|j�kr^dS|jjd�}|r~d|j�kr~dSdS)NZ
connectionre�closeTFz
keep-alivezproxy-connection)r>rjrLr+)r0ZconnZpconnrrrrk�s
zHTTPResponse._check_closecCs|j}d|_|j�dS)N)r=rn)r0r=rrrr_�szHTTPResponse._close_connc
s$zt�j�Wd|jr|j�XdS)N)�superrnr=r_)r0)�	__class__rrrn�szHTTPResponse.closecst�j�|jr|jj�dS)N)ro�flushr=)r0)rprrrq�s
zHTTPResponse.flushcCsdS)NTr)r0rrr�readable�szHTTPResponse.readablecCs
|jdkS)N)r=)r0rrr�isclosed�szHTTPResponse.isclosedcCs�|jdkrdS|jdkr$|j�dS|dk	rRt|�}|j|�}t|�d|�j�S|jr`|j�S|j	dkrv|jj
�}n6y|j|j	�}Wntk
r�|j��YnXd|_	|j�|SdS)Nr9rgr)
r=rIr_�	bytearray�readinto�
memoryview�tobytesrO�_readall_chunkedrQ�read�
_safe_readr
)r0�amt�br1�srrrry�s*



zHTTPResponse.readcCs�|jdkrdS|jdkr$|j�dS|jr4|j|�S|jdk	r^t|�|jkr^t|�d|j�}|jj|�}|r~|r~|j�n&|jdk	r�|j|8_|js�|j�|S)Nrrg)	r=rIr_rO�_readinto_chunkedrQr,rvru)r0r|r1rrrru�s$






zHTTPResponse.readintocCsp|jjtd�}t|�tkr$td��|jd�}|dkrB|d|�}y
t|d�Stk
rj|j��YnXdS)Nr*z
chunk size�;r�)	r=r:r;r,r�findr`r]r_)r0r2�irrr�_read_next_chunk_size
s

z"HTTPResponse._read_next_chunk_sizecCs>x8|jjtd�}t|�tkr&td��|s,P|dkrPqWdS)Nr*ztrailer line�
r8r9)r�r8r9)r=r:r;r,r)r0r2rrr�_read_and_discard_trailersz&HTTPResponse._read_and_discard_trailercCsl|j}|sh|dk	r|jd�y|j�}Wntk
rDtd��YnX|dkrb|j�|j�d}||_|S)NrWr9r)rPrzr�r]r
r�r_)r0rPrrr�_get_chunk_left(s
zHTTPResponse._get_chunk_leftcCsdg}y8x,|j�}|dkrP|j|j|��d|_qWdj|�Stk
r^tdj|���YnXdS)Nrr9)r�r/rzrPrAr
)r0�valuerPrrrrx@s

zHTTPResponse._readall_chunkedcCs�d}t|�}yvxp|j�}|dkr$|St|�|krL|j|�}|||_||S|d|�}|j|�}||d�}||7}d|_qWWn(tk
r�tt|d|����YnXdS)Nr)rvr�r,�_safe_readintorPr
�bytes)r0r|�total_bytes�mvbrPr1�temp_mvbrrrr~Ns$


zHTTPResponse._readinto_chunkedcCsXg}xH|dkrL|jjt|t��}|s4tdj|�|��|j|�|t|�8}qWdj|�S)Nrr9)r=ry�min�	MAXAMOUNTr
rAr/r,)r0r{r}�chunkrrrrzfs

zHTTPResponse._safe_readcCs�d}t|�}xt|t|�kr�tt|�kr@|dt�}|jj|�}n|jj|�}|sjtt|d|��t|���||d�}||7}qW|S)Nr)rvr,r�r=rur
r�)r0r|r�r�r�r1rrrr�}szHTTPResponse._safe_readintor*cCs�|jdks|jdkrdS|jr(|j|�S|jdk	rJ|dksD||jkrJ|j}y|jj|�}Wn*tk
r�|dkrt�|jjd�}YnX|r�|r�|j�n|jdk	r�|jt|�8_|S)Nrgr9rr�ii@)	r=rIrO�_read1_chunkedrQ�read1r]r_r,)r0r1�resultrrrr��s"



zHTTPResponse.read1cCs4|jdks|jdkrdS|jr(|j|�S|jj|�S)Nrgr9)r=rIrO�
_peek_chunked�peek)r0r1rrrr��s

zHTTPResponse.peekcs�|jdks|jdkrdS|jr*t�j|�S|jdk	rL|dksF||jkrL|j}|jj|�}|rl|rl|j�n|jdk	r�|jt|�8_|S)Nrgr9r)r=rIrOror:rQr_r,)r0�limitr�)rprrr:�s


zHTTPResponse.readlinecCsf|j�}|dks|dkrdSd|ko.|kns8|}|jj|�}|jt|�8_|sbtd��|S)Nrr9)r�r=r�rPr,r
)r0r1rPryrrrr��szHTTPResponse._read1_chunkedcCsBy|j�}Wntk
r dSX|dkr.dS|jj|�d|�S)Nr9)r�r
r=r�)r0r1rPrrrr��szHTTPResponse._peek_chunkedcCs
|jj�S)N)r=�fileno)r0rrrr��szHTTPResponse.filenocCsH|jdkrt��|jj|�p|}t|t�s6t|d�r:|Sdj|�SdS)N�__iter__z, )r>rZget_all�
isinstancerY�hasattrrA)r0r%�defaultr>rrr�	getheader�s
zHTTPResponse.getheadercCs|jdkrt��t|jj��S)N)r>r�list�items)r0rrr�
getheaders�s
zHTTPResponse.getheaderscCs|S)Nr)r0rrrr��szHTTPResponse.__iter__cCs|jS)N)r>)r0rrr�info�szHTTPResponse.infocCs|jS)N)rU)r0rrr�geturls
zHTTPResponse.geturlcCs|jS)N)rM)r0rrr�getcodeszHTTPResponse.getcode)rNN)N���)r�r�)r�r�)r�)N)"r4r5r6rVrarmrkr_rnrqrrrsryrur�r�r�rxr~rzr�r�r�r:r�r�r�r�r�r�r�r�r��
__classcell__rr)rprr�s<	
!K

 "

	

c@s�eZdZdZdZeZeZdZ	dZ
edd��Zedd��Z
d	ejd	fd
d�Zd0dd
�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd1dd �Zd2d!d"�Zd#d$�Zd%d&�Zd3dd'�d(d)�Zd	ifdd'�d*d+�Zd,d-�Z d.d/�Z!d	S)4rrezHTTP/1.1r*rcCst|tj�S)N)r��io�
TextIOBase)�streamrrr�
_is_textIO0szHTTPConnection._is_textIOcCsd|dkr|j�tkrdSdSt|d�r*dSyt|�}|jStk
rLYnXt|t�r`t|�SdS)Nrry)	�upper�_METHODS_EXPECTING_BODYr�rv�nbytes�	TypeErrorr�rYr,)�bodyrTZmvrrr�_get_content_length6s

z"HTTPConnection._get_content_lengthNcCs\||_||_d|_g|_d|_t|_d|_d|_d|_	i|_
|j||�\|_|_
tj|_dS)N)�timeout�source_addressrS�_buffer�_HTTPConnection__response�_CS_IDLE�_HTTPConnection__staterI�_tunnel_host�_tunnel_port�_tunnel_headers�
_get_hostport�host�port�socketZcreate_connection�_create_connection)r0r�r�r�r�rrrrVVszHTTPConnection.__init__cCs<|jrtd��|j||�\|_|_|r.||_n
|jj�dS)Nz.Can't set up tunnel for established connection)rS�RuntimeErrorr�r�r�r��clear)r0r�r�r>rrr�
set_tunneliszHTTPConnection.set_tunnelcCs�|dkr�|jd�}|jd�}||kr�yt||dd��}WnHtk
r�||dd�dkrh|j}ntd||dd���YnX|d|�}n|j}|r�|ddkr�|ddkr�|dd	�}||fS)
Nr)�]r*rXznonnumeric port: '%s'r�[r�r�)�rfindr`r]�default_portr)r0r�r�r��jrrrr��s

zHTTPConnection._get_hostportcCs
||_dS)N)rH)r0�levelrrr�set_debuglevel�szHTTPConnection.set_debuglevelcCsd|j|jf}|jd�}|j|�x6|jj�D](\}}d||f}|jd�}|j|�q0W|jd�|j|j|jd�}|j	�\}}	}
|	t
jjkr�|j
�td|	|
j�f��xP|jjtd�}t|�tkr�td	��|s�P|dkr�P|jdkr�td
|j��q�WdS)NzCONNECT %s:%d HTTP/1.0
�asciiz%s: %s
zlatin-1�
)rTzTunnel connection failed: %d %sr*zheader liner8r9rzheader:)r�r8r9)r�r�r�sendr�r��response_classrSrIra�http�
HTTPStatusZOKrn�OSErrorrir=r:r;r,rrHrZrB)r0Zconnect_strZ
connect_bytes�headerr�Z
header_strZheader_bytes�responserLrh�messager2rrr�_tunnel�s2





zHTTPConnection._tunnelcCsB|j|j|jf|j|j�|_|jjtjtj	d�|j
r>|j�dS)Nr*)r�r�r�r�r�rSZ
setsockoptr�ZIPPROTO_TCPZTCP_NODELAYr�r�)r0rrr�connect�s
zHTTPConnection.connectcCsBt|_z|j}|r d|_|j�Wd|j}|r<d|_|j�XdS)N)r�r�rSrnr�)r0rSr�rrrrn�szHTTPConnection.closecCs|jdkr |jr|j�nt��|jdkr8tdt|��d}t|d�r�|jdkrXtd�|j|�}|rx|jdkrxtd�x.|j	|�}|s�P|r�|j
d�}|jj|�qzWdSy|jj|�WnNtk
�r
t
|tj�r�x*|D]}|jj|�q�Wntdt|���YnXdS)	Nrzsend:i ryzsendIng a read()ablezencoding file using iso-8859-1z
iso-8859-1z9data should be a bytes-like object or an iterable, got %r)rS�	auto_openr�rrHrZr[r�r�ryrZsendallr�r��collections�Iterable�type)r0r�	blocksizer�	datablock�drrrr��s:








zHTTPConnection.sendcCs|jj|�dS)N)r�r/)r0r}rrr�_output�szHTTPConnection._outputccsdd}|jdkrtd�|j|�}|r6|jdkr6td�x(|j|�}|sHP|rV|jd�}|Vq8WdS)Ni rzsendIng a read()ablezencoding file using iso-8859-1z
iso-8859-1)rHrZr�ryr)r0rrr�rr�rrr�_read_readable�s



zHTTPConnection._read_readableFcCs$|jjd�dj|j�}|jdd�=|j|�|dk	�r t|d�rN|j|�}nZyt|�WnFtk
r�yt|�}Wn$tk
r�tdt	|���YnXYnX|f}xZ|D]R}|s�|j
dkr�td�q�|r�|jdkr�t
|�d�d	�jd
�|d}|j|�q�W|�r |jdk�r |jd�dS)
Nr9s
ryzAmessage_body should be a bytes-like object or an iterable, got %rrzZero length chunk ignoredre�Xz
r�s0

)r9r9)r��extendrAr�r�r�rvr��iterr�rHrZ�	_http_vsnr,r)r0�message_body�encode_chunkedrJZchunksr�rrr�_send_outputs4




zHTTPConnection._send_outputc

Cs�|jr|jj�rd|_|jtkr(t|_n
t|j��|j|�||_|sJd}tj	|�}|rrt
d|�d|j��d���d|||jf}|j
|jd��|jdk�r�|�s�d}|jd	�r�t|�\}}}}}|�ry|jd�}	Wntk
r�|jd
�}	YnX|jd|	�n�|j�r|j}
|j}n|j}
|j}y|
jd�}Wn tk
�rV|
jd
�}YnX|
jd�d
k�rtd|d}||jk�r�|jd|�n|jd�}|jdd||f�|�s�|jdd�ndS)N�/z&URL can't contain control characters. z (found at least �)z%s %s %sr�rerXr�ZidnaZHostr)r�[�]z%s:%szAccept-EncodingZidentity)r�rsr�r��_CS_REQ_STARTEDr
�_validate_methodrI�!_contains_disallowed_url_pchar_re�searchr�group�
_http_vsn_strr�rr�r^rr�	putheaderr�r�r�r�r�r�rB)
r0rTrU�	skip_host�skip_accept_encoding�match�requestZnetlocZnilZ
netloc_encr�r�Zhost_encrrr�
putrequestAsV






zHTTPConnection.putrequestcCs,tj|�}|r(td|�d|j��d���dS)Nz)method can't contain control characters. z (found at least r�)�$_contains_disallowed_method_pchar_rer�r]r�)r0rTr�rrrr��s
zHTTPConnection._validate_methodcGs�|jtkrt��t|d�r$|jd�}t|�s:td|f��t|�}xht|�D]\\}}t|d�rn|jd�||<nt	|t
�r�t|�jd�||<t||�rLtd||f��qLWdj
|�}|d|}|j|�dS)Nrr�zInvalid header name %rzlatin-1zInvalid header value %rs
	s: )r�r�rr�r�_is_legal_header_namer]r��	enumerater�r`rY�_is_illegal_header_valuerAr�)r0r��valuesr�Z	one_valuer�rrrr��s"





zHTTPConnection.putheader)r�cCs*|jtkrt|_nt��|j||d�dS)N)r�)r�r��_CS_REQ_SENTrr�)r0r�r�rrr�
endheaders�s
zHTTPConnection.endheaderscCs|j|||||�dS)N)�
_send_request)r0rTrUr�r>r�rrrr��szHTTPConnection.requestcCs�tdd�|D��}i}d|kr&d|d<d|kr6d|d<|j||f|�d|kr�d	|kr�d
}|j||�}|dkr�|dk	r�|jdkr�td|�d
}|jdd�q�|jdt|��nd
}x |j�D]\}	}
|j|	|
�q�Wt|t�r�t	|d�}|j
||d�dS)Ncss|]}|j�VqdS)N)r+)r�krrr�	<genexpr>�sz/HTTPConnection._send_request.<locals>.<genexpr>r�r*r�zaccept-encodingr�zcontent-lengthztransfer-encodingFrzUnable to determine size of %rTzTransfer-EncodingrOzContent-Lengthr�)r�)�	frozensetr�r�rHrZr�rYr�r�r'r�)r0rTrUr�r>r�Zheader_namesZskipsZcontent_lengthrlr�rrrr��s0	


zHTTPConnection._send_requestcCs�|jr|jj�rd|_|jtks&|jr0t|j��|jdkrR|j|j|j|jd�}n|j|j|jd�}yLy|j	�Wnt
k
r�|j��YnXt|_|j
r�|j�n||_|S|j��YnXdS)Nr)rT)r�rsr�r�rrHr�rSrIrm�ConnectionErrorrnr�rR)r0r�rrr�getresponse)s,


zHTTPConnection.getresponse)NN)NF)FF)N)"r4r5r6r�r�rr��	HTTP_PORTr�r�rH�staticmethodr�r�r��_GLOBAL_DEFAULT_TIMEOUTrVr�r�r�r�r�rnr�r�r�r�r�r�r�r�r�r�r�rrrrr&s< 
	'
6
	
.csBeZdZeZdddejdfddd��fdd�Z�fdd�Z�Z	S)�HTTPSConnectionN)�context�check_hostnamecs�tt|�j||||�|dk	s.|dk	s.|dk	rDddl}	|	jdtd�||_||_|dkrptj	�}|j
dk	rpd|_
|jtjk}
|dkr�|j
}|r�|
r�td��|s�|r�|j||�|j
dk	r�d|_
||_||_dS)NrzTkey_file, cert_file and check_hostname are deprecated, use a custom context instead.rWTzMcheck_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED)rorrV�warnings�warn�DeprecationWarning�key_file�	cert_file�sslZ_create_default_https_contextZpost_handshake_authZverify_modeZ	CERT_NONErr]Zload_cert_chain�_context�_check_hostname)r0r�r�rr	r�r�rrrZwill_verify)rprrrVts0


zHTTPSConnection.__init__cs�t�j�|jr|j}n|j}|jj|j|d�|_|jjr�|jr�yt	j
|jj�|�Wn.tk
r�|jj
tj�|jj��YnXdS)N)�server_hostname)ror�r�r�rZwrap_socketrSrrr
Zmatch_hostnameZgetpeercert�	ExceptionZshutdownr�Z	SHUT_RDWRrn)r0r
)rprrr��s



zHTTPSConnection.connect)
r4r5r6�
HTTPS_PORTr�r�rrVr�r�rr)rprrmsrc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdd�ZdS)rcCs|f|_||_dS)N)�argsrL)r0rLrrrrV�szUnknownProtocol.__init__N)r4r5r6rVrrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)r	N)r4r5r6rrrrr	�sc@s&eZdZddd�Zdd�Zdd�ZdS)	r
NcCs|f|_||_||_dS)N)r�partial�expected)r0rrrrrrV�szIncompleteRead.__init__cCs2|jdk	rd|j}nd}d|jjt|j�|fS)Nz, %i more expectedrXz%s(%i bytes read%s))rrpr4r,r)r0�errr�__repr__�s

zIncompleteRead.__repr__cCst|�S)N)r[)r0rrr�__str__�szIncompleteRead.__str__)N)r4r5r6rVrrrrrrr
�s
c@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)r
N)r4r5r6rrrrr
�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdd�ZdS)rcCs|st|�}|f|_||_dS)N)r[rr2)r0r2rrrrV�szBadStatusLine.__init__N)r4r5r6rVrrrrr�sc@seZdZdd�ZdS)rcCstj|dt|f�dS)Nz&got more than %d bytes when reading %s)rrVr;)r0Z	line_typerrrrV�szLineTooLong.__init__N)r4r5r6rVrrrrr�sc@seZdZdd�ZdS)rcOs"tj|d�tj|f|�|�dS)NrX)rrV�ConnectionResetError)r0�pos�kwrrrrV�szRemoteDisconnected.__init__N)r4r5r6rVrrrrr�s)r)AZemail.parserrCZ
email.messager�r��os�rer�r�Zurllib.parser�__all__r�rrKr�r�r��globals�updater��__members__r�rr�r;r<�compile�	fullmatchr�r�r�r�r�r�r'r�ZMessager(r?rE�BufferedIOBaserrr
�ImportErrorrr/rrrrrrr	r
rr
rrrrrrrrrrr�<module>Gs�



9F=
__pycache__/__init__.cpython-36.opt-2.pyc000064400000013535150532432170014112 0ustar003


 \A�@s&ddlmZdgZGdd�de�ZdS)�)�IntEnum�
HTTPStatusc@s�eZdZd�dd�Zd�Zd�Zd�Zd�Zd�Zd�Z	d�Z
d�Zd�Zd�Z
d�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Z d�Z!d�Z"d�Z#d�Z$d�Z%d�Z&d�Z'd�Z(d�Z)d�Z*d�Z+d�Z,d�Z-d�Z.d�Z/d�Z0d�Z1d�Z2d�Z3d�Z4d�Z5d�Z6d�Z7d�Z8d�Z9d�Z:d�Z;d�Z<d�S)�r�cCs"tj||�}||_||_||_|S)N)�int�__new__�_value_�phrase�description)�cls�valuerr	�obj�r
�%/usr/lib64/python3.6/http/__init__.pyrs
zHTTPStatus.__new__�d�Continue�!Request received, please continue�e�Switching Protocols�.Switching to new protocol; obey Upgrade header�f�
Processing���OK�#Request fulfilled, document follows���Created�Document created, URL follows���Accepted�/Request accepted, processing continues off-line���Non-Authoritative Information�Request fulfilled from cache���
No Content�"Request fulfilled, nothing follows���
Reset Content�"Clear input form for further input���Partial Content�Partial content follows���Multi-Status���Already Reported���IM Used�,�Multiple Choices�,Object has several resources -- see URI list�-�Moved Permanently�(Object moved permanently -- see URI list�.�Found�(Object moved temporarily -- see URI list�/�	See Other�'Object moved -- see Method and URL list�0�Not Modified�)Document has not changed since given time�1�	Use Proxy�@You must use proxy specified in Location to access this resource�3�Temporary Redirect�4�Permanent Redirect��Bad Request�(Bad request syntax or unsupported method��Unauthorized�*No permission -- see authorization schemes��Payment Required�"No payment -- see charging schemes��	Forbidden�0Request forbidden -- authorization will not help��	Not Found�Nothing matches the given URI��Method Not Allowed�-Specified method is invalid for this resource��Not Acceptable�%URI not available in preferred format��Proxy Authentication Required�7You must authenticate with this proxy before proceeding��Request Timeout�"Request timed out; try again later��Conflict�Request conflict��Gone�5URI no longer exists and has been permanently removed��Length Required�"Client must specify Content-Length��Precondition Failed� Precondition in headers is false��Request Entity Too Large�Entity is too large��Request-URI Too Long�URI is too long��Unsupported Media Type�!Entity body in unsupported format��Requested Range Not Satisfiable�Cannot satisfy request range��Expectation Failed�'Expect condition could not be satisfied��Unprocessable Entity��Locked��Failed Dependency��Upgrade Required��Precondition Required�8The origin server requires the request to be conditional��Too Many Requests�OThe user has sent too many requests in a given amount of time ("rate limiting")��Request Header Fields Too Large�VThe server is unwilling to process the request because its header fields are too large���Internal Server Error�Server got itself in trouble��Not Implemented�&Server does not support this operation��Bad Gateway�+Invalid responses from another server/proxy��Service Unavailable�8The server cannot process the request due to a high load��Gateway Timeout�4The gateway server did not receive a timely response��HTTP Version Not Supported�Cannot fulfill request��Variant Also Negotiates��Insufficient Storage��
Loop Detected��Not Extended��Network Authentication Required�7The client needs to authenticate to gain network accessN)r)rrr)rrr)rr)rrr)rrr)rrr)r r!r")r#r$r%)r&r'r()r)r*r+)r,r-)r.r/)r0r1)r2r3r4)r5r6r7)r8r9r:)r;r<r=)r>r?r@)rArBrC)rDrEr:)rFrGr:)rHrIrJ)rKrLrM)rNrOrP)rQrRrS)rTrUrV)rWrXrY)rZr[r\)r]r^r_)r`rarb)rcrdre)rfrgrh)rirjrk)rlrmrn)rorprq)rrrsrt)rurvrw)rxryrz)r{r|r})r~r)r�r�)r�r�)r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�)r�r�)r�r�)r�r�)r�r�r�)=�__name__�
__module__�__qualname__rZCONTINUEZSWITCHING_PROTOCOLSZ
PROCESSINGrZCREATEDZACCEPTEDZNON_AUTHORITATIVE_INFORMATIONZ
NO_CONTENTZ
RESET_CONTENTZPARTIAL_CONTENTZMULTI_STATUSZALREADY_REPORTEDZIM_USEDZMULTIPLE_CHOICESZMOVED_PERMANENTLYZFOUNDZ	SEE_OTHERZNOT_MODIFIEDZ	USE_PROXYZTEMPORARY_REDIRECTZPERMANENT_REDIRECTZBAD_REQUESTZUNAUTHORIZEDZPAYMENT_REQUIREDZ	FORBIDDENZ	NOT_FOUNDZMETHOD_NOT_ALLOWEDZNOT_ACCEPTABLEZPROXY_AUTHENTICATION_REQUIREDZREQUEST_TIMEOUTZCONFLICTZGONEZLENGTH_REQUIREDZPRECONDITION_FAILEDZREQUEST_ENTITY_TOO_LARGEZREQUEST_URI_TOO_LONGZUNSUPPORTED_MEDIA_TYPEZREQUESTED_RANGE_NOT_SATISFIABLEZEXPECTATION_FAILEDZUNPROCESSABLE_ENTITYZLOCKEDZFAILED_DEPENDENCYZUPGRADE_REQUIREDZPRECONDITION_REQUIREDZTOO_MANY_REQUESTSZREQUEST_HEADER_FIELDS_TOO_LARGEZINTERNAL_SERVER_ERRORZNOT_IMPLEMENTEDZBAD_GATEWAYZSERVICE_UNAVAILABLEZGATEWAY_TIMEOUTZHTTP_VERSION_NOT_SUPPORTEDZVARIANT_ALSO_NEGOTIATESZINSUFFICIENT_STORAGEZ
LOOP_DETECTEDZNOT_EXTENDEDZNETWORK_AUTHENTICATION_REQUIREDr
r
r
rrs�
	N)�enumr�__all__rr
r
r
r�<module>s__pycache__/__init__.cpython-36.pyc000064400000014601150532432170013145 0ustar003


 \A�@s&ddlmZdgZGdd�de�ZdS)�)�IntEnum�
HTTPStatusc@s�eZdZdZd�dd�Zd�Zd�Zd�Zd�Zd�Z	d�Z
d�Zd�Zd�Z
d�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Zd�Z d�Z!d�Z"d�Z#d�Z$d�Z%d�Z&d�Z'd�Z(d�Z)d�Z*d�Z+d�Z,d�Z-d�Z.d�Z/d�Z0d�Z1d�Z2d�Z3d�Z4d�Z5d�Z6d�Z7d�Z8d�Z9d�Z:d�Z;d�Z<d�Z=d�S)�raHTTP status codes and reason phrases

    Status codes from the following RFCs are all observed:

        * RFC 7231: Hypertext Transfer Protocol (HTTP/1.1), obsoletes 2616
        * RFC 6585: Additional HTTP Status Codes
        * RFC 3229: Delta encoding in HTTP
        * RFC 4918: HTTP Extensions for WebDAV, obsoletes 2518
        * RFC 5842: Binding Extensions to WebDAV
        * RFC 7238: Permanent Redirect
        * RFC 2295: Transparent Content Negotiation in HTTP
        * RFC 2774: An HTTP Extension Framework
    �cCs"tj||�}||_||_||_|S)N)�int�__new__�_value_�phrase�description)�cls�valuerr	�obj�r
�%/usr/lib64/python3.6/http/__init__.pyrs
zHTTPStatus.__new__�d�Continue�!Request received, please continue�e�Switching Protocols�.Switching to new protocol; obey Upgrade header�f�
Processing���OK�#Request fulfilled, document follows���Created�Document created, URL follows���Accepted�/Request accepted, processing continues off-line���Non-Authoritative Information�Request fulfilled from cache���
No Content�"Request fulfilled, nothing follows���
Reset Content�"Clear input form for further input���Partial Content�Partial content follows���Multi-Status���Already Reported���IM Used�,�Multiple Choices�,Object has several resources -- see URI list�-�Moved Permanently�(Object moved permanently -- see URI list�.�Found�(Object moved temporarily -- see URI list�/�	See Other�'Object moved -- see Method and URL list�0�Not Modified�)Document has not changed since given time�1�	Use Proxy�@You must use proxy specified in Location to access this resource�3�Temporary Redirect�4�Permanent Redirect��Bad Request�(Bad request syntax or unsupported method��Unauthorized�*No permission -- see authorization schemes��Payment Required�"No payment -- see charging schemes��	Forbidden�0Request forbidden -- authorization will not help��	Not Found�Nothing matches the given URI��Method Not Allowed�-Specified method is invalid for this resource��Not Acceptable�%URI not available in preferred format��Proxy Authentication Required�7You must authenticate with this proxy before proceeding��Request Timeout�"Request timed out; try again later��Conflict�Request conflict��Gone�5URI no longer exists and has been permanently removed��Length Required�"Client must specify Content-Length��Precondition Failed� Precondition in headers is false��Request Entity Too Large�Entity is too large��Request-URI Too Long�URI is too long��Unsupported Media Type�!Entity body in unsupported format��Requested Range Not Satisfiable�Cannot satisfy request range��Expectation Failed�'Expect condition could not be satisfied��Unprocessable Entity��Locked��Failed Dependency��Upgrade Required��Precondition Required�8The origin server requires the request to be conditional��Too Many Requests�OThe user has sent too many requests in a given amount of time ("rate limiting")��Request Header Fields Too Large�VThe server is unwilling to process the request because its header fields are too large���Internal Server Error�Server got itself in trouble��Not Implemented�&Server does not support this operation��Bad Gateway�+Invalid responses from another server/proxy��Service Unavailable�8The server cannot process the request due to a high load��Gateway Timeout�4The gateway server did not receive a timely response��HTTP Version Not Supported�Cannot fulfill request��Variant Also Negotiates��Insufficient Storage��
Loop Detected��Not Extended��Network Authentication Required�7The client needs to authenticate to gain network accessN)r)rrr)rrr)rr)rrr)rrr)rrr)r r!r")r#r$r%)r&r'r()r)r*r+)r,r-)r.r/)r0r1)r2r3r4)r5r6r7)r8r9r:)r;r<r=)r>r?r@)rArBrC)rDrEr:)rFrGr:)rHrIrJ)rKrLrM)rNrOrP)rQrRrS)rTrUrV)rWrXrY)rZr[r\)r]r^r_)r`rarb)rcrdre)rfrgrh)rirjrk)rlrmrn)rorprq)rrrsrt)rurvrw)rxryrz)r{r|r})r~r)r�r�)r�r�)r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�r�)r�r�)r�r�)r�r�)r�r�)r�r�r�)>�__name__�
__module__�__qualname__�__doc__rZCONTINUEZSWITCHING_PROTOCOLSZ
PROCESSINGrZCREATEDZACCEPTEDZNON_AUTHORITATIVE_INFORMATIONZ
NO_CONTENTZ
RESET_CONTENTZPARTIAL_CONTENTZMULTI_STATUSZALREADY_REPORTEDZIM_USEDZMULTIPLE_CHOICESZMOVED_PERMANENTLYZFOUNDZ	SEE_OTHERZNOT_MODIFIEDZ	USE_PROXYZTEMPORARY_REDIRECTZPERMANENT_REDIRECTZBAD_REQUESTZUNAUTHORIZEDZPAYMENT_REQUIREDZ	FORBIDDENZ	NOT_FOUNDZMETHOD_NOT_ALLOWEDZNOT_ACCEPTABLEZPROXY_AUTHENTICATION_REQUIREDZREQUEST_TIMEOUTZCONFLICTZGONEZLENGTH_REQUIREDZPRECONDITION_FAILEDZREQUEST_ENTITY_TOO_LARGEZREQUEST_URI_TOO_LONGZUNSUPPORTED_MEDIA_TYPEZREQUESTED_RANGE_NOT_SATISFIABLEZEXPECTATION_FAILEDZUNPROCESSABLE_ENTITYZLOCKEDZFAILED_DEPENDENCYZUPGRADE_REQUIREDZPRECONDITION_REQUIREDZTOO_MANY_REQUESTSZREQUEST_HEADER_FIELDS_TOO_LARGEZINTERNAL_SERVER_ERRORZNOT_IMPLEMENTEDZBAD_GATEWAYZSERVICE_UNAVAILABLEZGATEWAY_TIMEOUTZHTTP_VERSION_NOT_SUPPORTEDZVARIANT_ALSO_NEGOTIATESZINSUFFICIENT_STORAGEZ
LOOP_DETECTEDZNOT_EXTENDEDZNETWORK_AUTHENTICATION_REQUIREDr
r
r
rrs�

	N)�enumr�__all__rr
r
r
r�<module>s__pycache__/cookies.cpython-36.opt-2.pyc000064400000026541150532432170014010 0ustar003


 \�S�
@sxddlZddlZdddgZdjZdjZdjZdd	�ZGd
d�de�Z	ej
ejdZedZ
d
d�eed��eeee
��D�Zejed�ded�di�ejdeje��jZdd�Zejd�Zejd�Zdd�Zdddddd d!gZdd"d#d$d%d&d'd(d)d*d+d,d-g
Zdeefd.d/�ZGd0d1�d1e�Z d2Z!e!d3Z"ejd4e!d5e"d6ej#ej$B�Z%Gd7d�de�Z&Gd8d�de&�Z'dS)9�N�CookieError�
BaseCookie�SimpleCookie�z; � cCs$ddl}d|}|j|tdd�dS)NrzvThe .%s setter is deprecated. The attribute will be read-only in future releases. Please use the set() method instead.�)�
stacklevel)�warnings�warn�DeprecationWarning)�setterr	�msg�r�$/usr/lib64/python3.6/http/cookies.py�_warn_deprecated_setter�src@seZdZdS)rN)�__name__�
__module__�__qualname__rrrrr�sz!#$%&'*+-.^_`|~:z
 ()/<=>?@[]{}cCsi|]}d||�qS)z\%03or)�.0�nrrr�
<dictcomp>�sr��"z\"�\z\\z[%s]+cCs*|dkst|�r|Sd|jt�dSdS)Nr)�
_is_legal_key�	translate�_Translator)�strrrr�_quote�srz\\[0-3][0-7][0-7]z[\\].cCsT|dkst|�dkr|S|ddks0|ddkr4|S|dd�}d}t|�}g}x�d|kod|kn�rJtj||�}tj||�}|r�|r�|j||d��Pd	}}|r�|jd�}|r�|jd�}|o�|s�||k�r
|j|||��|j||d�|d}qR|j|||��|jtt||d|d�d���|d}qRWt|�S)
N�rr������r#r#)	�len�
_OctalPatt�search�
_QuotePatt�append�start�chr�int�	_nulljoin)r�ir�resZo_matchZq_match�j�krrr�_unquote�s6


$r1ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc	CsRddlm}m}|�}|||�\	}}}}	}
}}}
}d|||||||	|
|fS)Nr)�gmtime�timez#%s, %02d %3s %4d %02d:%02d:%02d GMT)r3r2)ZfutureZweekdaynameZ	monthnamer2r3ZnowZyearZmonthZdayZhhZmmZssZwd�y�zrrr�_getdate�s
r6c	@s�eZdZddddddddd	�Zd
dhZdd
�Zedd��Zejdd��Zedd��Z	e	jdd��Z	edd��Z
e
jdd��Z
dd�Zd3dd�Zdd�Z
ejZdd�Zd d!�Zd"d#�Zefd$d%�Zd&d'�Zd(d)�Zd4d+d,�ZeZd-d.�Zd5d/d0�Zd6d1d2�ZdS)7�Morsel�expiresZPath�CommentZDomainzMax-AgeZSecureZHttpOnlyZVersion)r8�path�commentZdomainzmax-age�secure�httponly�versionr<r=cCs4d|_|_|_x|jD]}tj||d�qWdS)Nr)�_key�_value�_coded_value�	_reserved�dict�__setitem__)�self�keyrrr�__init__&szMorsel.__init__cCs|jS)N)r?)rErrrrF.sz
Morsel.keycCstd�||_dS)NrF)rr?)rErFrrrrF2scCs|jS)N)r@)rErrr�value7szMorsel.valuecCstd�||_dS)NrH)rr@)rErHrrrrH;scCs|jS)N)rA)rErrr�coded_value@szMorsel.coded_valuecCstd�||_dS)NrI)rrA)rErIrrrrIDscCs2|j�}||jkr td|f��tj|||�dS)NzInvalid attribute %r)�lowerrBrrCrD)rE�K�VrrrrDIs
zMorsel.__setitem__NcCs.|j�}||jkr td|f��tj|||�S)NzInvalid attribute %r)rJrBrrC�
setdefault)rErF�valrrrrMOs
zMorsel.setdefaultcCs>t|t�stStj||�o<|j|jko<|j|jko<|j|jkS)N)�
isinstancer7�NotImplementedrC�__eq__r@r?rA)rE�morselrrrrQUs
z
Morsel.__eq__cCs$t�}tj||�|jj|j�|S)N)r7rC�update�__dict__)rErRrrr�copy_szMorsel.copycCsVi}x@t|�j�D]0\}}|j�}||jkr:td|f��|||<qWtj||�dS)NzInvalid attribute %r)rC�itemsrJrBrrS)rE�values�datarFrNrrrrSes
z
Morsel.updatecCs|j�|jkS)N)rJrB)rErKrrr�
isReservedKeynszMorsel.isReservedKeycCsh|tkr ddl}|jdtdd�|j�|jkr<td|f��t|�sRtd|f��||_||_	||_
dS)NrzSLegalChars parameter is deprecated, ignored and will be removed in future versions.r)rz Attempt to set a reserved key %rzIllegal key %r)�_LegalCharsr	r
rrJrBrrr?r@rA)rErFrNZ	coded_valZ
LegalCharsr	rrr�setqsz
Morsel.setcCs|j|j|jd�S)N)rFrHrI)r?r@rA)rErrr�__getstate__�szMorsel.__getstate__cCs"|d|_|d|_|d|_dS)NrFrHrI)r?r@rA)rE�staterrr�__setstate__�s

zMorsel.__setstate__�Set-Cookie:cCsd||j|�fS)Nz%s %s)�OutputString)rE�attrs�headerrrr�output�sz
Morsel.outputcCsd|jj|j�fS)Nz<%s: %s>)�	__class__rr`)rErrr�__repr__�szMorsel.__repr__cCsd|j|�jdd�S)Nz�
        <script type="text/javascript">
        <!-- begin hiding
        document.cookie = "%s";
        // end hiding -->
        </script>
        rz\")r`�replace)rErarrr�	js_output�szMorsel.js_outputcCs(g}|j}|d|j|jf�|dkr,|j}t|j��}x�|D]�\}}|dkrPq>||krZq>|dkr�t|t�r�|d|j|t|�f�q>|dkr�t|t�r�|d|j||f�q>|dkr�t|t	�r�|d|j|t
|�f�q>||jk�r|�r|t	|j|��q>|d|j||f�q>Wt|�S)Nz%s=%srr8zmax-agez%s=%dr;)
r(rFrIrB�sortedrVrOr+r6rr�_flags�_semispacejoin)rEra�resultr(rVrFrHrrrr`�s,zMorsel.OutputString)N)Nr_)N)N)rrrrBrirG�propertyrFrrHrIrDrMrQ�object�__ne__rUrSrYrZr[r\r^rc�__str__rergr`rrrrr7s>
	


r7z,\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=z\[\]z�
    \s*                            # Optional whitespace at start of cookie
    (?P<key>                       # Start of group 'key'
    [a	]+?   # Any word of at least one letter
    )                              # End of group 'key'
    (                              # Optional group: there may not be a value.
    \s*=\s*                          # Equal Sign
    (?P<val>                         # Start of group 'val'
    "(?:[^\\"]|\\.)*"                  # Any doublequoted string
    |                                  # or
    \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT  # Special case for "expires" attr
    |                                  # or
    [a-]*      # Any word or empty string
    )                                # End of group 'val'
    )?                             # End of optional value group
    \s*                            # Any number of spaces.
    (\s+|;|$)                      # Ending either at space, semicolon, or EOS.
    c@sjeZdZdd�Zdd�Zddd�Zdd	�Zd
d�Zddd�ZeZ	dd�Z
ddd�Zdd�Ze
fdd�ZdS)rcCs||fS)Nr)rErNrrr�value_decode�szBaseCookie.value_decodecCst|�}||fS)N)r)rErN�strvalrrr�value_encode�szBaseCookie.value_encodeNcCs|r|j|�dS)N)�load)rE�inputrrrrG�szBaseCookie.__init__cCs.|j|t��}|j|||�tj|||�dS)N)�getr7r[rCrD)rErFZ
real_valuerI�MrrrZ__set�szBaseCookie.__setcCs:t|t�rtj|||�n|j|�\}}|j|||�dS)N)rOr7rCrDrr�_BaseCookie__set)rErFrH�rval�cvalrrrrDs
zBaseCookie.__setitem__�Set-Cookie:�
cCs>g}t|j��}x"|D]\}}|j|j||��qW|j|�S)N)rhrVr(rc�join)rErarb�seprkrVrFrHrrrrc
s
zBaseCookie.outputcCsNg}t|j��}x(|D] \}}|jd|t|j�f�qWd|jjt|�fS)Nz%s=%sz<%s: %s>)rhrVr(�reprrHrdr�
_spacejoin)rE�lrVrFrHrrrres
zBaseCookie.__repr__cCs:g}t|j��}x |D]\}}|j|j|��qWt|�S)N)rhrVr(rgr,)rErarkrVrFrHrrrrgs
zBaseCookie.js_outputcCs8t|t�r|j|�nx|j�D]\}}|||<q WdS)N)rOr�_BaseCookie__parse_stringrV)rEZrawdatarFrHrrrrs&s

zBaseCookie.loadcCspd}t|�}g}d}d}d}�xd|ko2|kn�r|j||�}	|	sLP|	jd�|	jd�}
}|	jd�}|
ddkr�|s~q |j||
dd�|f�q |
j�tjkr�|s�dS|dkr�|
j�tjkr�|j||
df�q�dSn|j||
t	|�f�q |dk	�r|j||
|j
|�f�d}q dSq Wd}xF|D]>\}
}
}|
|k�rH|||
<n|\}}|j|
||�||
}�q*WdS)	NrFr rrFrN�$T)r$�match�group�endr(rJr7rBrir1rprw)rErZpattr-rZparsed_itemsZmorsel_seenZTYPE_ATTRIBUTEZ
TYPE_KEYVALUEr�rFrHrv�tprxryrrrZ__parse_string4sF



zBaseCookie.__parse_string)N)Nrzr{)N)rrrrprrrGrwrDrcrorergrs�_CookiePatternr�rrrrr�s		
	

c@seZdZdd�Zdd�ZdS)rcCst|�|fS)N)r1)rErNrrrrpxszSimpleCookie.value_decodecCst|�}|t|�fS)N)rr)rErNrqrrrrr{szSimpleCookie.value_encodeN)rrrrprrrrrrrqs)(�re�string�__all__r|r,rjrr�	ExceptionrZ
ascii_lettersZdigitsrZZ_UnescapedCharsr[�range�map�ordrrS�compile�escape�	fullmatchrrr%r'r1Z_weekdaynameZ
_monthnamer6rCr7Z_LegalKeyCharsZ_LegalValueChars�ASCII�VERBOSEr�rrrrrr�<module>�sD
	

2J
__pycache__/cookies.cpython-36.pyc000064400000037432150532432170013051 0ustar003


 \�S�
@s|dZddlZddlZdddgZdjZdjZdjZd	d
�ZGdd�de	�Z
ejejdZ
e
d
Zdd�eed��eeee��D�Zejed�ded�di�ejdeje
��jZdd�Zejd�Zejd�Zdd�Zddddd d!d"gZdd#d$d%d&d'd(d)d*d+d,d-d.g
Zdeefd/d0�ZGd1d2�d2e �Z!d3Z"e"d4Z#ejd5e"d6e#d7ej$ej%B�Z&Gd8d�de �Z'Gd9d�de'�Z(dS):a.

Here's a sample session to show how to use this module.
At the moment, this is the only documentation.

The Basics
----------

Importing is easy...

   >>> from http import cookies

Most of the time you start by creating a cookie.

   >>> C = cookies.SimpleCookie()

Once you've created your Cookie, you can add values just as if it were
a dictionary.

   >>> C = cookies.SimpleCookie()
   >>> C["fig"] = "newton"
   >>> C["sugar"] = "wafer"
   >>> C.output()
   'Set-Cookie: fig=newton\r\nSet-Cookie: sugar=wafer'

Notice that the printable representation of a Cookie is the
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.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

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.SimpleCookie()
   >>> C.load("chips=ahoy; vienna=finger")
   >>> C.output()
   'Set-Cookie: chips=ahoy\r\nSet-Cookie: vienna=finger'

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.SimpleCookie()
   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
   >>> print(C)
   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"

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.SimpleCookie()
   >>> C["oreo"] = "doublestuff"
   >>> C["oreo"]["path"] = "/"
   >>> print(C)
   Set-Cookie: oreo=doublestuff; Path=/

Each dictionary element has a 'value' attribute, which gives you
back the value associated with the key.

   >>> C = cookies.SimpleCookie()
   >>> C["twix"] = "none for you"
   >>> C["twix"].value
   'none for you'

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.

   >>> C = cookies.SimpleCookie()
   >>> C["number"] = 7
   >>> C["string"] = "seven"
   >>> C["number"].value
   '7'
   >>> C["string"].value
   'seven'
   >>> C.output()
   'Set-Cookie: number=7\r\nSet-Cookie: string=seven'

Finis.
�N�CookieError�
BaseCookie�SimpleCookie�z; � cCs$ddl}d|}|j|tdd�dS)NrzvThe .%s setter is deprecated. The attribute will be read-only in future releases. Please use the set() method instead.�)�
stacklevel)�warnings�warn�DeprecationWarning)�setterr	�msg�r�$/usr/lib64/python3.6/http/cookies.py�_warn_deprecated_setter�src@seZdZdS)rN)�__name__�
__module__�__qualname__rrrrr�sz!#$%&'*+-.^_`|~:z
 ()/<=>?@[]{}cCsi|]}d||�qS)z\%03or)�.0�nrrr�
<dictcomp>�sr��"z\"�\z\\z[%s]+cCs*|dkst|�r|Sd|jt�dSdS)z�Quote a string for use in a cookie header.

    If the string does not need to be double-quoted, then just return the
    string.  Otherwise, surround the string in doublequotes and quote
    (with a \) special characters.
    Nr)�
_is_legal_key�	translate�_Translator)�strrrr�_quote�srz\\[0-3][0-7][0-7]z[\\].cCsT|dkst|�dkr|S|ddks0|ddkr4|S|dd�}d}t|�}g}x�d|kod|kn�rJtj||�}tj||�}|r�|r�|j||d��Pd	}}|r�|jd�}|r�|jd�}|o�|s�||k�r
|j|||��|j||d�|d}qR|j|||��|jtt||d|d�d���|d}qRWt|�S)
N�rr������r#r#)	�len�
_OctalPatt�search�
_QuotePatt�append�start�chr�int�	_nulljoin)r�ir�resZo_matchZq_match�j�krrr�_unquote�s6


$r1ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc	CsRddlm}m}|�}|||�\	}}}}	}
}}}
}d|||||||	|
|fS)Nr)�gmtime�timez#%s, %02d %3s %4d %02d:%02d:%02d GMT)r3r2)ZfutureZweekdaynameZ	monthnamer2r3ZnowZyearZmonthZdayZhhZmmZssZwd�y�zrrr�_getdate�s
r6c	@seZdZdZdddddddd	d
�ZddhZd
d�Zedd��Zej	dd��Zedd��Z
e
j	dd��Z
edd��Zej	dd��Zdd�Zd4dd�Z
dd�ZejZdd �Zd!d"�Zd#d$�Zefd%d&�Zd'd(�Zd)d*�Zd5d,d-�ZeZd.d/�Zd6d0d1�Zd7d2d3�ZdS)8�Morsela�A class to hold ONE (key, value) pair.

    In a cookie, each such pair may have several attributes, so this class is
    used to keep the attributes associated with the appropriate key,value pair.
    This class also includes a coded_value attribute, which is used to hold
    the network representation of the value.  This is most useful when Python
    objects are pickled for network transit.
    �expiresZPath�CommentZDomainzMax-AgeZSecureZHttpOnlyZVersion)r8�path�commentZdomainzmax-age�secure�httponly�versionr<r=cCs4d|_|_|_x|jD]}tj||d�qWdS)Nr)�_key�_value�_coded_value�	_reserved�dict�__setitem__)�self�keyrrr�__init__&szMorsel.__init__cCs|jS)N)r?)rErrrrF.sz
Morsel.keycCstd�||_dS)NrF)rr?)rErFrrrrF2scCs|jS)N)r@)rErrr�value7szMorsel.valuecCstd�||_dS)NrH)rr@)rErHrrrrH;scCs|jS)N)rA)rErrr�coded_value@szMorsel.coded_valuecCstd�||_dS)NrI)rrA)rErIrrrrIDscCs2|j�}||jkr td|f��tj|||�dS)NzInvalid attribute %r)�lowerrBrrCrD)rE�K�VrrrrDIs
zMorsel.__setitem__NcCs.|j�}||jkr td|f��tj|||�S)NzInvalid attribute %r)rJrBrrC�
setdefault)rErF�valrrrrMOs
zMorsel.setdefaultcCs>t|t�stStj||�o<|j|jko<|j|jko<|j|jkS)N)�
isinstancer7�NotImplementedrC�__eq__r@r?rA)rE�morselrrrrQUs
z
Morsel.__eq__cCs$t�}tj||�|jj|j�|S)N)r7rC�update�__dict__)rErRrrr�copy_szMorsel.copycCsVi}x@t|�j�D]0\}}|j�}||jkr:td|f��|||<qWtj||�dS)NzInvalid attribute %r)rC�itemsrJrBrrS)rE�values�datarFrNrrrrSes
z
Morsel.updatecCs|j�|jkS)N)rJrB)rErKrrr�
isReservedKeynszMorsel.isReservedKeycCsh|tkr ddl}|jdtdd�|j�|jkr<td|f��t|�sRtd|f��||_||_	||_
dS)NrzSLegalChars parameter is deprecated, ignored and will be removed in future versions.r)rz Attempt to set a reserved key %rzIllegal key %r)�_LegalCharsr	r
rrJrBrrr?r@rA)rErFrNZ	coded_valZ
LegalCharsr	rrr�setqsz
Morsel.setcCs|j|j|jd�S)N)rFrHrI)r?r@rA)rErrr�__getstate__�szMorsel.__getstate__cCs"|d|_|d|_|d|_dS)NrFrHrI)r?r@rA)rE�staterrr�__setstate__�s

zMorsel.__setstate__�Set-Cookie:cCsd||j|�fS)Nz%s %s)�OutputString)rE�attrs�headerrrr�output�sz
Morsel.outputcCsd|jj|j�fS)Nz<%s: %s>)�	__class__rr`)rErrr�__repr__�szMorsel.__repr__cCsd|j|�jdd�S)Nz�
        <script type="text/javascript">
        <!-- begin hiding
        document.cookie = "%s";
        // end hiding -->
        </script>
        rz\")r`�replace)rErarrr�	js_output�szMorsel.js_outputcCs(g}|j}|d|j|jf�|dkr,|j}t|j��}x�|D]�\}}|dkrPq>||krZq>|dkr�t|t�r�|d|j|t|�f�q>|dkr�t|t�r�|d|j||f�q>|dkr�t|t	�r�|d|j|t
|�f�q>||jk�r|�r|t	|j|��q>|d|j||f�q>Wt|�S)Nz%s=%srr8zmax-agez%s=%dr;)
r(rFrIrB�sortedrVrOr+r6rr�_flags�_semispacejoin)rEra�resultr(rVrFrHrrrr`�s,zMorsel.OutputString)N)Nr_)N)N)rrr�__doc__rBrirG�propertyrFrrHrIrDrMrQ�object�__ne__rUrSrYrZr[r\r^rc�__str__rergr`rrrrr7s@
	


r7z,\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=z\[\]z�
    \s*                            # Optional whitespace at start of cookie
    (?P<key>                       # Start of group 'key'
    [a	]+?   # Any word of at least one letter
    )                              # End of group 'key'
    (                              # Optional group: there may not be a value.
    \s*=\s*                          # Equal Sign
    (?P<val>                         # Start of group 'val'
    "(?:[^\\"]|\\.)*"                  # Any doublequoted string
    |                                  # or
    \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT  # Special case for "expires" attr
    |                                  # or
    [a-]*      # Any word or empty string
    )                                # End of group 'val'
    )?                             # End of optional value group
    \s*                            # Any number of spaces.
    (\s+|;|$)                      # Ending either at space, semicolon, or EOS.
    c@sneZdZdZdd�Zdd�Zddd�Zd	d
�Zdd�Zddd�Z	e	Z
dd�Zddd�Zdd�Z
efdd�ZdS)rz'A container class for a set of Morsels.cCs||fS)a
real_value, coded_value = value_decode(STRING)
        Called prior to setting a cookie's value from the network
        representation.  The VALUE is the value read from HTTP
        header.
        Override this function to modify the behavior of cookies.
        r)rErNrrr�value_decode�szBaseCookie.value_decodecCst|�}||fS)z�real_value, coded_value = value_encode(VALUE)
        Called prior to setting a cookie's value from the dictionary
        representation.  The VALUE is the value being assigned.
        Override this function to modify the behavior of cookies.
        )r)rErN�strvalrrr�value_encode�szBaseCookie.value_encodeNcCs|r|j|�dS)N)�load)rE�inputrrrrG�szBaseCookie.__init__cCs.|j|t��}|j|||�tj|||�dS)z+Private method for setting a cookie's valueN)�getr7r[rCrD)rErFZ
real_valuerI�MrrrZ__set�szBaseCookie.__setcCs:t|t�rtj|||�n|j|�\}}|j|||�dS)zDictionary style assignment.N)rOr7rCrDrs�_BaseCookie__set)rErFrH�rval�cvalrrrrDs
zBaseCookie.__setitem__�Set-Cookie:�
cCs>g}t|j��}x"|D]\}}|j|j||��qW|j|�S)z"Return a string suitable for HTTP.)rhrVr(rc�join)rErarb�seprkrVrFrHrrrrc
s
zBaseCookie.outputcCsNg}t|j��}x(|D] \}}|jd|t|j�f�qWd|jjt|�fS)Nz%s=%sz<%s: %s>)rhrVr(�reprrHrdr�
_spacejoin)rE�lrVrFrHrrrres
zBaseCookie.__repr__cCs:g}t|j��}x |D]\}}|j|j|��qWt|�S)z(Return a string suitable for JavaScript.)rhrVr(rgr,)rErarkrVrFrHrrrrgs
zBaseCookie.js_outputcCs8t|t�r|j|�nx|j�D]\}}|||<q WdS)z�Load cookies from a string (presumably HTTP_COOKIE) or
        from a dictionary.  Loading cookies from a dictionary 'd'
        is equivalent to calling:
            map(Cookie.__setitem__, d.keys(), d.values())
        N)rOr�_BaseCookie__parse_stringrV)rEZrawdatarFrHrrrrt&s

zBaseCookie.loadcCs�d}t|�}g}d}d}d}�xd|ko2|kn�r|j||�}	|	sLP|	jd�|	jd�}
}|	jd�}|
ddkr�|s~q |j||
dd�|f�q |
j�tjkr�|s�dS|dkr�|
j�tjkr�|j||
df�q�dSn|j||
t	|�f�q |dk	�r|j||
|j
|�f�d}q dSq Wd}xb|D]Z\}
}
}|
|k�rV|dk	�sLt�|||
<n,|
|k�sdt�|\}}|j|
||�||
}�q*WdS)	NrFr rrFrN�$T)
r$�match�group�endr(rJr7rBrir1rq�AssertionErrorrx)rErZpattr-rZparsed_itemsZmorsel_seenZTYPE_ATTRIBUTEZ
TYPE_KEYVALUEr�rFrHrw�tpryrzrrrZ__parse_string4sJ



zBaseCookie.__parse_string)N)Nr{r|)N)rrrrlrqrsrGrxrDrcrprergrt�_CookiePatternr�rrrrr�s		
	

c@s eZdZdZdd�Zdd�ZdS)rz�
    SimpleCookie supports strings as cookie values.  When setting
    the value using the dictionary assignment notation, SimpleCookie
    calls the builtin str() to convert the value to a string.  Values
    received from HTTP are kept as strings.
    cCst|�|fS)N)r1)rErNrrrrqxszSimpleCookie.value_decodecCst|�}|t|�fS)N)rr)rErNrrrrrrs{szSimpleCookie.value_encodeN)rrrrlrqrsrrrrrqs))rl�re�string�__all__r}r,rjr�r�	ExceptionrZ
ascii_lettersZdigitsrZZ_UnescapedCharsr[�range�map�ordrrS�compile�escape�	fullmatchrrr%r'r1Z_weekdaynameZ
_monthnamer6rCr7Z_LegalKeyCharsZ_LegalValueChars�ASCII�VERBOSEr�rrrrrr�<module>sF
	

2J
__pycache__/cookiejar.cpython-36.pyc000064400000151360150532432170013360 0ustar003

Ow�hr+�@s*dZddddddddgZd	d
lZd	d
lZd	d
lZd	d
lZd	d
lZd	d
lZyd	d
l	Z
Wnek
rpd	d
lZ
YnXd	d
l
Zd	dlmZdZd
ad
d�Zeejj�ZdZdd�ZdZdd�ZdddddddgZddddd d!d"d#d$d%d&d'gZgZxeD]Zej ej!��q�Wdud(d)�Z"dvd*d+�Z#d
d
d
d
d,�Z$ej%d-ej&�Z'd.d/�Z(d0d1�Z)ej%d2ej&�Z*ej%d3ej+ej&B�Z,ej%d4ej-ej&B�Z.d5d6�Z/ej%d7ej-ej&B�Z0d8d9�Z1d:d;�Z2ej%d<�Z3ej%d=�Z4ej%d>�Z5ej%d?�Z6d@dA�Z7ej%dB�Z8dCdD�Z9dEdF�Z:dGdH�Z;ej%dIej&�Z<dJdK�Z=dLdM�Z>dNdO�Z?dPdQ�Z@ej%dRej&�ZAdSdT�ZBdUdV�ZCdWdX�ZDdYdZ�ZEd[ZFej%d\�ZGd]d^�ZHd_d`�ZIdadb�ZJdcdd�ZKGded�d�ZLGdfd�d�ZMGdgd�deM�ZNdhdi�ZOdjdk�ZPGdldm�dm�ZQGdnd�d�ZRGdod�deS�ZTGdpd�deR�ZUdqdr�ZVGdsd�deU�ZWGdtd�deU�ZXd
S)wa�HTTP cookie handling for web clients.

This module has (now fairly distant) origins in Gisle Aas' Perl module
HTTP::Cookies, from the libwww-perl library.

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 BSDDBCookieJar and the MSIE* classes are not
distributed with the Python standard library, but are available from
http://wwwsearch.sf.net/):

                        CookieJar____
                        /     \      \
            FileCookieJar      \      \
             /    |   \         \      \
 MozillaCookieJar | LWPCookieJar \      \
                  |               |      \
                  |   ---MSIEBase |       \
                  |  /      |     |        \
                  | /   MSIEDBCookieJar BSDDBCookieJar
                  |/
               MSIECookieJar

�Cookie�	CookieJar�CookiePolicy�DefaultCookiePolicy�
FileCookieJar�LWPCookieJar�	LoadError�MozillaCookieJar�N)�timegmFcGs(tsdStsddl}|jd�atj|�S)Nr	zhttp.cookiejar)�debug�logger�loggingZ	getLogger)�argsr
�r�&/usr/lib64/python3.6/http/cookiejar.py�_debug.s
rzQa filename was not supplied (nor was the CookieJar instance initialised with one)cCsJddl}ddl}ddl}|j�}|jd|�|j�}|jd|dd�dS)Nr	zhttp.cookiejar bug!
%s�)�
stacklevel)�io�warnings�	traceback�StringIO�	print_exc�getvalue�warn)rrr�f�msgrrr�_warn_unhandled_exception<s
ri�cCs�|dd�\}}}}}}|tkr�d|ko2dknr�d|koJdknr�d|kobdknr�d|kozdknr�d|ko�dknr�t|�SdSdS)	N����r	��;�=)�
EPOCH_YEARr
)�tt�year�monthZmday�hour�min�secrrr�_timegmKs
8Hr,ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs@|dkrtjj�}ntjj|�}d|j|j|j|j|j|jfS)aHReturn a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like "YYYY-MM-DD hh:mm:ssZ",
    representing Universal Time (UTC, aka GMT).  An example of this format is:

    1994-11-24 08:49:37Z

    Nz%04d-%02d-%02d %02d:%02d:%02dZ)	�datetime�utcnow�utcfromtimestampr'r(�dayr)�minute�second)�t�dtrrr�	time2isozYs
r5cCsR|dkrtjj�}ntjj|�}dt|j�|jt|jd|j|j	|j
|jfS)z�Return a string representing time in seconds since epoch, t.

    If the function is called without an argument, it will use the current
    time.

    The format of the returned string is like this:

    Wed, DD-Mon-YYYY HH:MM:SS GMT

    Nz#%s, %02d-%s-%04d %02d:%02d:%02d GMTr)r-r.r/�DAYSZweekdayr0�MONTHSr(r'r)r1r2)r3r4rrr�
time2netscapelsr8)ZGMT�UTCZUT�Zz^([-+])?(\d\d?):?(\d\d)?$cCsjd}|tkrd}nTtj|�}|rfdt|jd��}|jd�rR|dt|jd��}|jd�dkrf|}|S)Nr	ir��<r�-)�	UTC_ZONES�TIMEZONE_RE�search�int�group)�tz�offset�mrrr�offset_from_tz_string�s

rFc
Cs�t|�}|tjkrdSytj|j��d}WnXtk
r�yt|�}Wntk
r\dSXd|kopdknr||}ndSYnX|dkr�d}|dkr�d}|dkr�d}t|�}t|�}t|�}t|�}|dk�r0tjtj��d}|d}	|}
|||	}|	|
}	t	|	�dk�r0|	dk�r(|d}n|d}t
|||||||f�}|dk	�r�|dk�r^d}|j�}t|�}|dk�r|dS||}|S)Nrr r	i��d�2r9)
rAr-ZMAXYEAR�MONTHS_LOWER�index�lower�
ValueError�timeZ	localtime�absr,�upperrF)
r0�mon�yr�hrr*r+rCZimonZcur_yrrEZtmpr3rDrrr�	_str2time�sV







rSzV^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$z+^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*a�^
    (\d\d?)            # day
       (?:\s+|[-\/])
    (\w+)              # month
        (?:\s+|[-\/])
    (\d+)              # year
    (?:
          (?:\s+|:)    # separator before clock
       (\d\d?):(\d\d)  # hour:min
       (?::(\d\d))?    # optional seconds
    )?                 # optional clock
       \s*
    ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone
       \s*
    (?:\(\w+\))?       # ASCII representation of timezone in parens.
       \s*$cCs�tj|�}|rl|j�}tj|dj��d}t|d�|t|d�t|d�t|d�t|d�f}t|�S|j	�}t
jd|d�}dgd	\}}}}}}	}
tj|�}|dk	r�|j�\}}}}}}	}
ndSt
||||||	|
�S)
a�Returns time in seconds since epoch of time represented by a string.

    Return value is an integer.

    None is returned if the format of str is unrecognized, the time is outside
    the representable range, or the timezone string is not recognized.  If the
    string contains no timezone, UTC is assumed.

    The timezone in the string may be numerical (like "-0800" or "+0100") or a
    string timezone (like "UTC", "GMT", "BST" or "EST").  Currently, only the
    timezone strings equivalent to UTC (zero offset) are known to the function.

    The function loosely parses the following formats:

    Wed, 09 Feb 1994 22:23:32 GMT       -- HTTP format
    Tuesday, 08-Feb-94 14:15:29 GMT     -- old rfc850 HTTP format
    Tuesday, 08-Feb-1994 14:15:29 GMT   -- broken rfc850 HTTP format
    09 Feb 1994 22:23:32 GMT            -- HTTP format (no weekday)
    08-Feb-94 14:15:29 GMT              -- rfc850 format (no weekday)
    08-Feb-1994 14:15:29 GMT            -- broken rfc850 format (no weekday)

    The parser ignores leading and trailing whitespace.  The time may be
    absent.

    If the year is given with only 2 digits, the function will select the
    century that makes the year closest to the current date.

    rrr	r;���N�)�STRICT_DATE_REr@�groupsrIrJrKrA�floatr,�lstrip�
WEEKDAY_RE�sub�LOOSE_HTTP_DATE_RErS)�textrE�grPr&r0rQrRr*r+rCrrr�	http2time�s
"
raa�^
    (\d{4})              # year
       [-\/]?
    (\d\d?)              # numerical month
       [-\/]?
    (\d\d?)              # day
   (?:
         (?:\s+|[-:Tt])  # separator before clock
      (\d\d?):?(\d\d)    # hour:min
      (?::?(\d\d(?:\.\d*)?))?  # optional seconds (and fractional)
   )?                    # optional clock
      \s*
   ([-+]?\d\d?:?(:?\d\d)?
    |Z|z)?               # timezone  (Z is "zero meridian", i.e. GMT)
      \s*$c
Csd|j�}dgd\}}}}}}}tj|�}|dk	rL|j�\}}}}}}}}	ndSt|||||||�S)av
    As for http2time, but parses the ISO 8601 formats:

    1994-02-03 14:15:29 -0100    -- ISO 8601 format
    1994-02-03 14:15:29          -- zone is optional
    1994-02-03                   -- only date
    1994-02-03T14:15:29          -- Use T as separator
    19940203T141529Z             -- ISO 8601 compact format
    19940203                     -- only date

    NrW)r[�ISO_DATE_REr@rYrS)
r_r0rPrQrRr*r+rCrE�_rrr�iso2time's

rdcCs*|jd�\}}|jd|�|j|d�S)z)Return unmatched part of re.Match object.r	N)�span�string)�match�start�endrrr�	unmatchedHsrjz^\s*([^=\s;,]+)z&^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"z^\s*=\s*([^\s;,]*)z\\(.)c
Cs<t|t�st�g}�x |D�]}|}g}x�|�r$tj|�}|r�t|�}|jd�}tj|�}|r�t|�}|jd�}tj	d|�}n.t
j|�}|r�t|�}|jd�}|j�}nd}|j||f�q,|j
�jd�r�|j
�dd�}|r�|j|�g}q,tjdd|�\}}	|	dk�std|||f��|}q,W|r|j|�qW|S)	amParse header values into a list of lists containing key,value pairs.

    The function knows how to deal with ",", ";" and "=" as well as quoted
    values after "=".  A list of space separated tokens are parsed as if they
    were separated by ";".

    If the header_values passed as argument contains multiple values, then they
    are treated as if they were a single value separated by comma ",".

    This means that this function is useful for parsing header fields that
    follow this syntax (BNF as from the HTTP/1.1 specification, but we relax
    the requirement for tokens).

      headers           = #header
      header            = (token | parameter) *( [";"] (token | parameter))

      token             = 1*<any CHAR except CTLs or separators>
      separators        = "(" | ")" | "<" | ">" | "@"
                        | "," | ";" | ":" | "\" | <">
                        | "/" | "[" | "]" | "?" | "="
                        | "{" | "}" | SP | HT

      quoted-string     = ( <"> *(qdtext | quoted-pair ) <"> )
      qdtext            = <any TEXT except <">>
      quoted-pair       = "\" CHAR

      parameter         = attribute "=" value
      attribute         = token
      value             = token | quoted-string

    Each header is represented by a list of key/value pairs.  The value for a
    simple token (not part of a parameter) is None.  Syntactically incorrect
    headers will not necessarily be parsed as you would want.

    This is easier to describe with some examples:

    >>> split_header_words(['foo="bar"; port="80,81"; discard, bar=baz'])
    [[('foo', 'bar'), ('port', '80,81'), ('discard', None)], [('bar', 'baz')]]
    >>> split_header_words(['text/html; charset="iso-8859-1"'])
    [[('text/html', None), ('charset', 'iso-8859-1')]]
    >>> split_header_words([r'Basic realm="\"foo\bar\""'])
    [[('Basic', None), ('realm', '"foobar"')]]

    rz\1N�,z^[=\s;]*rVr	z&split_header_words bug: '%s', '%s', %s)�
isinstance�str�AssertionError�HEADER_TOKEN_REr@rjrB�HEADER_QUOTED_VALUE_RE�HEADER_ESCAPE_REr]�HEADER_VALUE_RE�rstrip�appendr[�
startswith�re�subn)
Z
header_values�resultr_Z	orig_text�pairsrE�name�valueZnon_junkZ
nr_junk_charsrrr�split_header_wordsQsF-







r|z([\"\\])cCs�g}xt|D]l}g}xN|D]F\}}|dk	rTtjd|�sHtjd|�}d|}d||f}|j|�qW|r
|jdj|��q
Wdj|�S)a�Do the inverse (almost) of the conversion done by split_header_words.

    Takes a list of lists of (key, value) pairs and produces a single header
    value.  Attribute values are quoted if needed.

    >>> join_header_words([[("text/plain", None), ("charset", "iso-8859-1")]])
    'text/plain; charset="iso-8859-1"'
    >>> join_header_words([[("text/plain", None)], [("charset", "iso-8859-1")]])
    'text/plain, charset="iso-8859-1"'

    Nz^\w+$z\\\1z"%s"z%s=%sz; z, )rvr@�HEADER_JOIN_ESCAPE_REr]rt�join)Zlists�headersry�attr�k�vrrr�join_header_words�s
r�cCs0|jd�r|dd�}|jd�r,|dd�}|S)N�"r���)ru�endswith)r_rrr�strip_quotes�s


r�cCsd}g}x�|D]�}g}d}x�t|jd	��D]�\}}|j�}|jd
�\}}	}
|j�}|sd|dkr*Pnq*|	rp|
j�nd}
|dkr�|j�}||kr�|}|dkr�|
dk	r�t|
�}
d
}n|dkr�|
dk	r�tt|
��}
|j||
f�q*W|r|�s�|jd�|j|�qW|S)a5Ad-hoc parser for Netscape protocol cookie-attributes.

    The old Netscape cookie format for Set-Cookie can for instance contain
    an unquoted "," in the expires field, so we have to use this ad-hoc
    parser instead of split_header_words.

    XXX This may not make the best possible effort to parse all the crap
    that Netscape Cookie headers contain.  Ronald Tschalar's HTTPClient
    parser is probably better, so could do worse than following that if
    this ever gives any trouble.

    Currently, this is also used for parsing RFC 2109 cookies.

    �expires�domain�path�secure�version�port�max-ageF�;�=r	NT�0)r�r�r�r�r�r�r�)r�r�)�	enumerate�split�strip�	partitionrKr�rart)Z
ns_headersZknown_attrsrxZ	ns_headerry�version_setZiiZparam�key�sep�val�lcrrr�parse_ns_headers�s@

r�z\.\d+$cCs:tj|�rdS|dkrdS|ddks2|ddkr6dSdS)z*Return True if text is a host domain name.FrVr	�.rTr�)�IPV4_REr@)r_rrr�is_HDNs
r�cCsl|j�}|j�}||krdSt|�s(dS|j|�}|dksB|dkrFdS|jd�sTdSt|dd��shdSdS)a�Return True if domain A domain-matches domain B, according to RFC 2965.

    A and B may be host domain names or IP addresses.

    RFC 2965, section 1:

    Host names can be specified either as an IP address or a HDN string.
    Sometimes we compare one host name with another.  (Such comparisons SHALL
    be case-insensitive.)  Host A's name domain-matches host B's if

         *  their host name strings string-compare equal; or

         * A is a HDN string and has the form NB, where N is a non-empty
            name string, B has the form .B', and B' is a HDN string.  (So,
            x.y.com domain-matches .Y.com but not Y.com.)

    Note that domain-match is not a commutative operation: a.b.c.com
    domain-matches .c.com, but not the reverse.

    TFrr	r�Nr�)rKr��rfindru)�A�B�irrr�domain_matchs

r�cCstj|�rdSdS)zdReturn True if text is a sort-of-like a host domain name.

    For accepting/blocking domains.

    FT)r�r@)r_rrr�liberal_is_HDNBs
r�cCsb|j�}|j�}t|�ot|�s0||kr,dSdS|jd�}|rL|j|�rLdS|r^||kr^dSdS)z\For blocking/accepting domains.

    A and B may be host domain names or IP addresses.

    TFr�)rKr�rur�)r�r��initial_dotrrr�user_domain_matchLs
r�z:\d+$cCsB|j�}tjj|�d}|dkr,|jdd�}tjd|d�}|j�S)z�Return request-host, as defined by RFC 2965.

    Variation from RFC: returned value is lowercased, for convenient
    comparison.

    rrVZHost)�get_full_url�urllib�parseZurlparseZ
get_header�cut_port_rer]rK)�request�url�hostrrr�request_hostasr�cCs6t|�}}|jd�dkr.tj|�r.|d}||fS)zzReturn a tuple (request-host, effective request-host name).

    As defined by RFC 2965, except both are lowercased.

    r�rz.localr�)r��findr�r@)r��erhn�req_hostrrr�eff_request_hostqsr�cCs4|j�}tjj|�}t|j�}|jd�s0d|}|S)z6Path component of request-URI, as defined by RFC 2965.�/)r�r�r�Zurlsplit�escape_pathr�ru)r�r��partsr�rrr�request_path|s

r�cCs^|j}|jd�}|dkrV||dd�}yt|�WqZtk
rRtd|�dSXnt}|S)N�:r	rznonnumeric port: '%s')r�r�rArLr�DEFAULT_HTTP_PORT)r�r�r�r�rrr�request_port�s

r�z%/;:@&=+$,!~*'()z%([0-9a-fA-F][0-9a-fA-F])cCsd|jd�j�S)Nz%%%sr)rBrO)rgrrr�uppercase_escaped_char�sr�cCstjj|t�}tjt|�}|S)zEEscape any invalid characters in HTTP URL, and uppercase all escapes.)r�r�Zquote�HTTP_PATH_SAFE�ESCAPED_CHAR_REr]r�)r�rrrr��s
r�cCsP|jd�}|dkrL||dd�}|jd�}t|�rL|dksD|dkrLd|S|S)aBReturn reach of host h, as defined by RFC 2965, section 1.

    The reach R of a host name H is defined as follows:

       *  If

          -  H is the host domain name of a host; and,

          -  H has the form A.B; and

          -  A has no embedded (that is, interior) dots; and

          -  B has at least one embedded dot, or B is the string "local".
             then the reach of H is .B.

       *  Otherwise, the reach of H is H.

    >>> reach("www.acme.com")
    '.acme.com'
    >>> reach("acme.com")
    'acme.com'
    >>> reach("acme.local")
    '.local'

    r�r	rNZlocal)r�r�)�hr��brrr�reach�s

r�cCs$t|�}t|t|j��sdSdSdS)z�

    RFC 2965, section 3.3.6:

        An unverifiable transaction is to a third-party host if its request-
        host U does not domain-match the reach R of the request-host O in the
        origin transaction.

    TFN)r�r�r�Zorigin_req_host)r�r�rrr�is_third_party�s
r�c@sNeZdZdZddd�Zdd�Zddd	�Zd
d�Zddd
�Zdd�Z	dd�Z
dS)ra�HTTP Cookie.

    This class represents both Netscape and RFC 2965 cookies.

    This is deliberately a very simple class.  It just holds attributes.  It's
    possible to construct Cookie instances that don't comply with the cookie
    standards.  CookieJar.make_cookies is the factory function for Cookie
    objects -- it deals with cookie parsing, supplying defaults, and
    normalising to the representation used in this class.  CookiePolicy is
    responsible for checking them to see whether they should be accepted from
    and returned to the server.

    Note that the port may be present in the headers, but unspecified ("Port"
    rather than"Port=80", for example); if this is the case, port is None.

    FcCs�|dk	rt|�}|dk	r$tt|��}|dkr<|dkr<td��||_||_||_||_||_|j�|_	||_
||_|	|_|
|_
||_||_|
|_||_||_||_tj|�|_dS)NTz-if port is None, port_specified must be false)rArZrLr�rzr{r��port_specifiedrKr��domain_specified�domain_initial_dotr��path_specifiedr�r��discard�comment�comment_url�rfc2109�copy�_rest)�selfr�rzr{r�r�r�r�r�r�r�r�r�r�r�r��restr�rrr�__init__�s.

zCookie.__init__cCs
||jkS)N)r�)r�rzrrr�has_nonstandard_attrszCookie.has_nonstandard_attrNcCs|jj||�S)N)r��get)r�rz�defaultrrr�get_nonstandard_attrszCookie.get_nonstandard_attrcCs||j|<dS)N)r�)r�rzr{rrr�set_nonstandard_attrszCookie.set_nonstandard_attrcCs,|dkrtj�}|jdk	r(|j|kr(dSdS)NTF)rMr�)r��nowrrr�
is_expireds
zCookie.is_expiredcCsX|jdkrd}n
d|j}|j||j}|jdk	rFd|j|jf}n|j}d||fS)NrVr�z%s=%sz<Cookie %s for %s>)r�r�r�r{rz)r��p�limitZ	namevaluerrr�__str__%s


zCookie.__str__cCspg}x,dD]$}t||�}|jd|t|�f�q
W|jdt|j��|jdt|j��d|jjdj|�fS)Nr�rzr{r�r�r�r�r�r�r�r�r�r�r�r�z%s=%szrest=%sz
rfc2109=%sz%s(%s)z, )r�rzr{r�r�r�r�r�r�r�r�r�r�r�r�)�getattrrt�reprr�r��	__class__�__name__r~)r�rrzr�rrr�__repr__/s
zCookie.__repr__)F)N)N)r��
__module__�__qualname__�__doc__r�r�r�r�r�r�r�rrrrr�s
 


c@s0eZdZdZdd�Zdd�Zdd�Zdd	�Zd
S)ra Defines which cookies get accepted from and returned to server.

    May also modify cookies, though this is probably a bad idea.

    The subclass DefaultCookiePolicy defines the standard rules for Netscape
    and RFC 2965 cookies -- override that if you want a customized policy.

    cCs
t��dS)z�Return true if (and only if) cookie should be accepted from server.

        Currently, pre-expired cookies never get this far -- the CookieJar
        class deletes such cookies itself.

        N)�NotImplementedError)r��cookier�rrr�set_okGszCookiePolicy.set_okcCs
t��dS)zAReturn true if (and only if) cookie should be returned to server.N)r�)r�r�r�rrr�	return_okPszCookiePolicy.return_okcCsdS)zMReturn false if cookies should not be returned, given cookie domain.
        Tr)r�r�r�rrr�domain_return_okTszCookiePolicy.domain_return_okcCsdS)zKReturn false if cookies should not be returned, given cookie path.
        Tr)r�r�r�rrr�path_return_okYszCookiePolicy.path_return_okN)r�r�r�r�r�r�r�r�rrrrr>s
	c@s�eZdZdZdZdZdZdZeeBZdddddddddeddfd	d
�Z	dd�Z
d
d�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Zd1d2�Zd3d4�Zd5d6�ZdS)7rzBImplements the standard rules for accepting and returning cookies.rrrTr	NTFc

Csp||_||_||_||_||_||_|	|_|
|_||_||_	|dk	rPt
|�|_nf|_|dk	rft
|�}||_dS)zAConstructor arguments should be passed as keyword arguments only.N)
�netscape�rfc2965�rfc2109_as_netscape�hide_cookie2�
strict_domain�strict_rfc2965_unverifiable�strict_ns_unverifiable�strict_ns_domain�strict_ns_set_initial_dollar�strict_ns_set_path�tuple�_blocked_domains�_allowed_domains)
r��blocked_domains�allowed_domainsr�r�r�r�r�r�r�r�r�r�rrrr�is 
zDefaultCookiePolicy.__init__cCs|jS)z4Return the sequence of blocked domains (as a tuple).)r�)r�rrrr��sz#DefaultCookiePolicy.blocked_domainscCst|�|_dS)z$Set the sequence of blocked domains.N)r�r�)r�r�rrr�set_blocked_domains�sz'DefaultCookiePolicy.set_blocked_domainscCs"x|jD]}t||�rdSqWdS)NTF)r�r�)r�r�Zblocked_domainrrr�
is_blocked�s
zDefaultCookiePolicy.is_blockedcCs|jS)z=Return None, or the sequence of allowed domains (as a tuple).)r�)r�rrrr��sz#DefaultCookiePolicy.allowed_domainscCs|dk	rt|�}||_dS)z-Set the sequence of allowed domains, or None.N)r�r�)r�r�rrr�set_allowed_domains�sz'DefaultCookiePolicy.set_allowed_domainscCs0|jdkrdSx|jD]}t||�rdSqWdS)NFT)r�r�)r�r�Zallowed_domainrrr�is_not_allowed�s

z"DefaultCookiePolicy.is_not_allowedcCsPtd|j|j�|jdk	st�x,dD]$}d	|}t||�}|||�s$d
Sq$WdS)
z�
        If you override .set_ok(), be sure to call this method.  If it returns
        false, so should your subclass (assuming your subclass wants to be more
        strict about which cookies to accept).

        z - checking cookie %s=%sNr��
verifiabilityrzr�r�r�Zset_ok_FT)r�r�rzr�r�r�)rrzr{rnr�)r�r�r��n�fn_name�fnrrrr��s


zDefaultCookiePolicy.set_okcCs^|jdkrtd|j|j�dS|jdkr<|jr<td�dS|jdkrZ|jrZtd�dSdS)Nz0   Set-Cookie2 without version attribute (%s=%s)Fr	z$   RFC 2965 cookies are switched offz$   Netscape cookies are switched offT)r�rrzr{r�r�)r�r�r�rrr�set_ok_version�s
z"DefaultCookiePolicy.set_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS)Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT)�unverifiabler�r�r�rr�)r�r�r�rrr�set_ok_verifiability�sz(DefaultCookiePolicy.set_ok_verifiabilitycCs0|jdkr,|jr,|jjd�r,td|j�dSdS)Nr	�$z'   illegal name (starts with '$'): '%s'FT)r�r�rzrur)r�r�r�rrr�set_ok_name�s
zDefaultCookiePolicy.set_ok_namecCsL|jrHt|�}|jdks(|jdkrH|jrH|j|j�rHtd|j|�dSdS)Nr	z7   path attribute %s is not a prefix of request path %sFT)r�r�r�r�rur�r)r�r�r��req_pathrrr�set_ok_path�s

zDefaultCookiePolicy.set_ok_pathc
Cs�|j|j�rtd|j�dS|j|j�r8td|j�dS|j�r�t|�\}}|j}|jr�|jd�dkr�|jd�}|jdd|�}|dkr�||dd�}||d|�}	|	j	�d$kr�t
|�dkr�td|�dS|jd��r�|dd�}
n|}
|
jd�dk}|�r|dk�rtd|�dS|j
dk�rb|j|��rb|jd��rbd|j|��rbtd ||�dS|j
dk�s||j|j@�r�t||��s�td!||�dS|j
dk�s�|j|j@�r�|dt
|��}|jd�dk�r�tj|��r�td"||�dSd#S)%Nz"   domain %s is in user block-listFz&   domain %s is not in user allow-listr�rr	r�co�ac�com�edu�org�net�gov�milrA�aero�biz�cat�coop�info�jobs�mobi�museumrz�pro�travel�euz&   country-code second level domain %sz.localz/   non-local domain %s contains no embedded dotzO   effective request-host %s (even with added initial dot) does not end with %sz5   effective request-host %s does not domain-match %sz.   host prefix %s for domain %s contains a dotT)rrrrrr	r
rrArr
rrrrrrrzrrr)r�r�rr�r�r�r��countr�rK�lenrur�r�r�r��DomainRFC2965Matchr��DomainStrictNoDotsr�r@)
r�r�r�r�r�r�r��jZtldZsldZundotted_domainZ
embedded_dotsZhost_prefixrrr�
set_ok_domain�sf

z!DefaultCookiePolicy.set_ok_domaincCs�|jr�t|�}|dkrd}nt|�}x\|jjd�D]:}yt|�Wntk
r`td|�dSX||kr2Pq2Wtd||j�dSdS)N�80rkz   bad port %s (not numeric)Fz$   request port (%s) not found in %sT)r�r�rmr�r�rArLr)r�r�r��req_portr�rrr�set_ok_port%s"

zDefaultCookiePolicy.set_ok_portcCsBtd|j|j�x,dD]$}d|}t||�}|||�sd	SqWd
S)z�
        If you override .return_ok(), be sure to call this method.  If it
        returns false, so should your subclass (assuming your subclass wants to
        be more strict about which cookies to return).

        z - checking cookie %s=%sr�r�r�r�r�r�Z
return_ok_FT)r�r�r�r�r�r�)rrzr{r�)r�r�r�r�r�r�rrrr�:s	


zDefaultCookiePolicy.return_okcCs@|jdkr|jrtd�dS|jdkr<|jr<td�dSdS)Nr	z$   RFC 2965 cookies are switched offFz$   Netscape cookies are switched offT)r�r�rr�)r�r�r�rrr�return_ok_versionLsz%DefaultCookiePolicy.return_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS)Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT)r�r�r�r�rr�)r�r�r�rrr�return_ok_verifiabilityUsz+DefaultCookiePolicy.return_ok_verifiabilitycCs |jr|jdkrtd�dSdS)NZhttpsz(   secure cookie with non-secure requestFT)r��typer)r�r�r�rrr�return_ok_secureasz$DefaultCookiePolicy.return_ok_securecCs|j|j�rtd�dSdS)Nz   cookie expiredFT)r��_nowr)r�r�r�rrr�return_ok_expiresgsz%DefaultCookiePolicy.return_ok_expirescCsP|jrLt|�}|dkrd}x0|jjd�D]}||kr(Pq(Wtd||j�dSdS)Nrrkz0   request port %s does not match cookie port %sFT)r�r�r�r)r�r�r�rr�rrr�return_ok_portms
z"DefaultCookiePolicy.return_ok_portcCs�t|�\}}|j}|r,|jd�r,d|}n|}|jdkrb|j|j@rb|jrb||krbtd�dS|jdkr�t||�r�td||�dS|jdkr�d|j	|�r�td||�dSdS)Nr�r	zQ   cookie with unspecified domain does not string-compare equal to request domainFzQ   effective request-host name %s does not domain-match RFC 2965 cookie domain %sz;   request-host %s does not match Netscape cookie domain %sT)
r�r�rur�r��DomainStrictNonDomainr�rr�r�)r�r�r�r�r�r��	dotdomainrrr�return_ok_domain{s&

z$DefaultCookiePolicy.return_ok_domaincCs�t|�\}}|jd�sd|}|jd�s0d|}|rJ|jd�rJd|}n|}|j|�p`|j|�sfdS|j|�r~td|�dS|j|�r�td|�dSdS)Nr�Fz"   domain %s is in user block-listz&   domain %s is not in user allow-listT)r�rur�r�rr�)r�r�r�r�r�r(rrrr��s"






z$DefaultCookiePolicy.domain_return_okcCs0td|�t|�}|j|�s,td||�dSdS)Nz- checking cookie path=%sz  %s does not path-match %sFT)rr�ru)r�r�r�rrrrr��s

z"DefaultCookiePolicy.path_return_ok) r�r�r�r�rr'rZ
DomainLiberalZDomainStrictr�r�r�r�r�r�r�r�r�r�rrrrr�r r!r#r%r&r)r�r�rrrrr_sL	;	cCst|j��}t|j|�S)N)�sorted�keys�mapr�)Zadictr+rrr�vals_sorted_by_key�sr-ccsZt|�}xL|D]D}d}y
|jWntk
r4YnXd}t|�EdH|s|VqWdS)zBIterates over nested mapping, depth-first, in sorted order by key.FTN)r-�items�AttributeError�
deepvalues)�mapping�values�objrrrr0�s

r0c@seZdZdS)�AbsentN)r�r�r�rrrrr4�sr4c@s�eZdZdZejd�Zejd�Zejd�Zejd�Z	ejd�Z
ejdej�Zd3d	d
�Z
dd�Zd
d�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd4d%d&�Zd'd(�Zd)d*�Zd+d,�Zd-d.�Zd/d0�Z d1d2�Z!dS)5rz�Collection of HTTP cookies.

    You may not need to know about this class: try
    urllib.request.build_opener(HTTPCookieProcessor).open(url).
    z\Wz([\"\\])z\.?[^.]*z[^.]*z^\.+z^\#LWP-Cookies-(\d+\.\d+)NcCs(|dkrt�}||_tj�|_i|_dS)N)r�_policy�
_threading�RLock�
_cookies_lock�_cookies)r��policyrrrr��s

zCookieJar.__init__cCs
||_dS)N)r5)r�r:rrr�
set_policy�szCookieJar.set_policycCs�g}|jj||�sgStd|�|j|}xd|j�D]X}|jj||�sHq4||}x:|j�D].}|jj||�svtd�qZtd�|j|�qZWq4W|S)Nz!Checking %s for cookies to returnz   not returning cookiez   it's a match)	r5r�rr9r+r�r2r�rt)r�r�r��cookiesZcookies_by_pathr�Zcookies_by_namer�rrr�_cookies_for_domain�s 

zCookieJar._cookies_for_domaincCs.g}x$|jj�D]}|j|j||��qW|S)z2Return a list of cookies to be returned to server.)r9r+�extendr=)r�r�r<r�rrr�_cookies_for_request�szCookieJar._cookies_for_requestc	CsF|jdd�dd�d}g}�x$|D�]}|j}|sLd}|dkrL|jd|�|jdk	r~|jj|j�r~|dkr~|jjd	|j�}n|j}|jdkr�|j|j�n|jd
|j|f�|dkr"|j	r�|jd|j
�|jjd��r|j}|j
o�|jd��r|d
d�}|jd|�|jdk	r"d}|j�r4|d|j}|j|�q"W|S)z�Return a list of cookie-attributes to be returned to server.

        like ['foo="bar"; $Path="/"', ...]

        The $Version attribute is also added when appropriate (currently only
        once per request).

        cSs
t|j�S)N)rr�)�arrr�<lambda>sz)CookieJar._cookie_attrs.<locals>.<lambda>T)r��reverseFr	z$Version=%sNz\\\1z%s=%sz
$Path="%s"r�rz$Domain="%s"z$Portz="%s")�sortr�rtr{�non_word_rer@�quote_rer]rzr�r�r�rur�r�r�)	r�r<r��attrsr�r�r{r�r�rrr�
_cookie_attrss>



zCookieJar._cookie_attrsc
Cs�td�|jj�z�ttj��|j_|_|j|�}|j|�}|r^|j	d�s^|j
ddj|��|jjr�|jj
r�|j	d�r�x$|D]}|jdkr�|j
dd�Pq�WWd|jj�X|j�dS)z�Add correct Cookie: header to request (urllib.request.Request object).

        The Cookie2 header is also added unless policy.hide_cookie2 is true.

        �add_cookie_headerrz; ZCookie2rz$Version="1"N)rr8�acquirerArMr5r$r?rGZ
has_headerZadd_unredirected_headerr~r�r�r��release�clear_expired_cookies)r�r�r<rFr�rrrrH?s$






zCookieJar.add_cookie_headercCs�g}d}d}�x||D�]r}|d\}}d}d}	i}
i}�x4|d
d�D�]"\}}
|j�}||ksh||krl|}||kr�|
dkr�d}
||
kr�qF|dkr�|
dkr�td�d}	P|
j�}
|dkr�|r�qF|
dkr�td�qF|dk�rd}yt|
�}
Wn$tk
�rtd�d}	PYnXd}|j|
}
||k�s2||k�rb|
dk�rX|dk�rXtd|�d}	P|
|
|<qF|
||<qFW|	�rvq|j|||
|f�qW|S)aReturn 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.

        r�r�r�r��max-ager�r�r�r��
commenturlr	FrNTz%   missing value for domain attributezM   missing or invalid value for expires attribute: treating as session cookiez?   missing or invalid (non-numeric) value for max-age attributez!   missing value for %s attribute)r�r�)r�r�rLr�r�r�r�rM)r�r�rM)rKrrArLr$rt)r��	attrs_set�
cookie_tuples�
boolean_attrs�value_attrsZcookie_attrsrzr{Zmax_age_setZ
bad_cookie�standardr�r�r�r�rrr�_normalized_cookie_tuples`sl






z#CookieJar._normalized_cookie_tuplesc!Cs$|\}}}}|jdt�}|jdt�}|jdt�}	|jdt�}
|jdd�}|dk	rryt|�}Wntk
rpdSX|jdd�}|jdd�}
|jd	d�}|jd
d�}|tk	r�|dkr�d}t|�}nXd}t|�}|jd
�}|dk�r|dkr�|d|�}n|d|d�}t|�dk�rd
}|tk	}d}|�r8t|j	d��}|tk�rTt
|�\}}|}n|j	d��shd|}d}|	tk	�r�|	dk�r�t|�}	nd}tj
dd|	�}	nd}	|
tk�r�d}
d}
nH|
|jk�r�y|j|||�Wntk
�r�YnXtd|||�dSt||||	||||||||
|
|||�S)Nr�r�r�r�r�r�Fr�r�rMrVTr�rr	r�z\s+z2Expiring cookie, domain='%s', path='%s', name='%s'r�)r�r4rArLr�r�r�r�boolrur�r�rvr]r$�clear�KeyErrorrr)r��tupr�rzr{rRr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrr�_cookie_from_cookie_tuple�s�








z#CookieJar._cookie_from_cookie_tuplecCs:|j|�}g}x&|D]}|j||�}|r|j|�qW|S)N)rSrXrt)r�rNr�rOr<rWr�rrr�_cookies_from_attrs_sets

z!CookieJar._cookies_from_attrs_setcCsLt|jdd�}|dkr |jj}x&|D]}|jdkr&d|_|r&d|_q&WdS)Nr�rTr	)r�r5r�r�r�)r�r<Z
rfc2109_as_nsr�rrr�_process_rfc2109_cookies&s


z"CookieJar._process_rfc2109_cookiesc
Cs6|j�}|jdg�}|jdg�}|jj}|jj}|r<|s`|rH|s`|rT|s`|rd|rdgSy|jt|�|�}Wntk
r�t�g}YnX|o�|�r2y|jt	|�|�}	Wntk
r�t�g}	YnX|j
|	�|�r"i}
x |D]}d|
|j|j|j
f<q�W|
fdd�}t||	�}	|	�r2|j|	�|S)zAReturn sequence of Cookie objects extracted from response object.zSet-Cookie2z
Set-CookieNcSs|j|j|jf}||kS)N)r�r�rz)Z	ns_cookie�lookupr�rrr�no_matching_rfc2965^sz3CookieJar.make_cookies.<locals>.no_matching_rfc2965)rZget_allr5r�r�rYr|�	Exceptionrr�rZr�r�rz�filterr>)
r��responser�rZrfc2965_hdrsZns_hdrsr�r�r<Z
ns_cookiesr[r�r\rrr�make_cookies2sB






zCookieJar.make_cookiesc
CsN|jj�z2ttj��|j_|_|jj||�r:|j|�Wd|jj�XdS)z-Set a cookie if policy says it's OK to do so.N)	r8rIrArMr5r$r��
set_cookierJ)r�r�r�rrr�set_cookie_if_okhs
zCookieJar.set_cookie_if_okc
Csl|j}|jj�zJ|j|kr&i||j<||j}|j|krDi||j<||j}|||j<Wd|jj�XdS)z?Set a cookie, without checking whether or not it should be set.N)r9r8rIr�r�rzrJ)r�r��cZc2Zc3rrrraus






zCookieJar.set_cookiec
Cs|td|j��|jj�zRttj��|j_|_x6|j||�D]&}|jj	||�r>td|�|j
|�q>WWd|jj�XdS)zAExtract cookies from response, where allowable given the request.zextract_cookies: %sz setting cookie: %sN)rrr8rIrArMr5r$r`r�rarJ)r�r_r�r�rrr�extract_cookies�s

zCookieJar.extract_cookiescCst|dk	r2|dks|dkr td��|j|||=n>|dk	rX|dkrJtd��|j||=n|dk	rj|j|=ni|_dS)a�Clear some cookies.

        Invoking this method without arguments will clear all cookies.  If
        given a single argument, only cookies belonging to that domain will be
        removed.  If given two arguments, cookies belonging to the specified
        path within that domain are removed.  If given three arguments, then
        the cookie with the specified name, path and domain is removed.

        Raises KeyError if no matching cookie exists.

        Nz8domain and path must be given to remove a cookie by namez.domain must be given to remove cookies by path)rLr9)r�r�r�rzrrrrU�s
zCookieJar.clearcCsH|jj�z,x&|D]}|jr|j|j|j|j�qWWd|jj�XdS)z�Discard all session cookies.

        Note that the .save() method won't save session cookies anyway, unless
        you ask otherwise by passing a true ignore_discard argument.

        N)r8rIr�rUr�r�rzrJ)r�r�rrr�clear_session_cookies�s

zCookieJar.clear_session_cookiescCsT|jj�z8tj�}x*|D]"}|j|�r|j|j|j|j�qWWd|jj�XdS)a�Discard all expired cookies.

        You probably don't need to call this method: expired cookies are never
        sent back to the server (provided you're using DefaultCookiePolicy),
        this method is called by CookieJar itself every so often, and the
        .save() method won't save expired cookies anyway (unless you ask
        otherwise by passing a true ignore_expires argument).

        N)	r8rIrMr�rUr�r�rzrJ)r�r�r�rrrrK�s



zCookieJar.clear_expired_cookiescCs
t|j�S)N)r0r9)r�rrr�__iter__�szCookieJar.__iter__cCsd}x|D]}|d}q
W|S)z#Return number of contained cookies.r	rr)r�r�r�rrr�__len__�s
zCookieJar.__len__cCs6g}x|D]}|jt|��q
Wd|jjdj|�fS)Nz<%s[%s]>z, )rtr�r�r�r~)r��rr�rrrr��s
zCookieJar.__repr__cCs6g}x|D]}|jt|��q
Wd|jjdj|�fS)Nz<%s[%s]>z, )rtrmr�r�r~)r�rhr�rrrr��s
zCookieJar.__str__)N)NNN)"r�r�r�r�rv�compilerDrEZstrict_domain_reZ	domain_reZdots_re�ASCII�magic_rer�r;r=r?rGrHrSrXrYrZr`rbrardrUrerKrfrgr�r�rrrrr�s8





;!a\	6


c@seZdZdS)rN)r�r�r�rrrrr�sc@s8eZdZdZddd�Zd
dd�Zddd	�Zdd
d�ZdS)rz6CookieJar that can be loaded from and saved to a file.NFc	CsJtj||�|dk	r6y|dWntd��YnX||_t|�|_dS)z}
        Cookies are NOT loaded from the named file until either the .load() or
        .revert() method is called.

        NrVzfilename must be string-like)rr�rL�filenamerT�	delayload)r�rlrmr:rrrr��szFileCookieJar.__init__cCs
t��dS)zSave cookies to a file.N)r�)r�rl�ignore_discard�ignore_expiresrrr�save�szFileCookieJar.savecCsJ|dkr"|jdk	r|j}ntt��t|��}|j||||�WdQRXdS)zLoad cookies from a file.N)rlrL�MISSING_FILENAME_TEXT�open�_really_load)r�rlrnrorrrr�load�s

zFileCookieJar.loadcCs�|dkr"|jdk	r|j}ntt��|jj�zFtj|j�}i|_y|j|||�Wnt	k
rn||_�YnXWd|jj
�XdS)z�Clear all cookies and reload cookies from a saved file.

        Raises LoadError (or OSError) if reversion is not successful; the
        object's state will not be altered if this happens.

        N)rlrLrqr8rIr��deepcopyr9rt�OSErrorrJ)r�rlrnroZ	old_staterrr�reverts

zFileCookieJar.revert)NFN)NFF)NFF)NFF)r�r�r�r�r�rprtrwrrrrr�s


	cCs$|j|jfd|jfd|jfg}|jdk	r8|jd|jf�|jrH|jd�|jrX|jd�|jrh|jd�|j	rx|jd�|j
r�|jd	tt|j
��f�|j
r�|jd�|jr�|jd|jf�|jr�|jd|jf�t|jj��}x$|D]}|j|t|j|�f�q�W|jd
t|j�f�t|g�S)z�Return string representation of Cookie in the LWP cookie file format.

    Actually, the format is extended a bit -- see module docstring.

    r�r�Nr��	path_spec�	port_spec�
domain_dotr�r�r�r�rMr�)rxN)ryN)rzN)r�N)r�N)rzr{r�r�r�rtr�r�r�r�r�r5rZr�r�r�r*r�r+rmr�r�)r�r�r+r�rrr�lwp_cookie_strs6







r{c@s,eZdZdZddd�Zddd�Zd	d
�ZdS)
ra[
    The LWPCookieJar saves a sequence of "Set-Cookie3" lines.
    "Set-Cookie3" is the format used by the libwww-perl library, not known
    to be compatible with any browser, but which is easy to read and
    doesn't lose information about RFC 2965 cookies.

    Additional methods

    as_lwp_str(ignore_discard=True, ignore_expired=True)

    TcCs\tj�}g}x>|D]6}|r$|jr$q|r6|j|�r6q|jdt|��qWdj|dg�S)z�Return cookies as a string of "\n"-separated "Set-Cookie3" headers.

        ignore_discard and ignore_expires: see docstring for FileCookieJar.save

        zSet-Cookie3: %s�
rV)rMr�r�rtr{r~)r�rnror�rhr�rrr�
as_lwp_strGs
zLWPCookieJar.as_lwp_strNFcCsX|dkr"|jdk	r|j}ntt��t|d��"}|jd�|j|j||��WdQRXdS)N�wz#LWP-Cookies-2.0
)rlrLrqrr�writer})r�rlrnrorrrrrpWs

zLWPCookieJar.savecCsL|j�}|jj|�s$d|}t|��tj�}d}d}	d}
�yʐx�|j�}|dkrRP|j|�s^q@|t|�d�j�}�x�t|g�D�]x}|d\}
}i}i}x|	D]}d||<q�Wx�|dd�D]t\}}|dk	r�|j	�}nd}||
k�s�||	k�r�|}||	k�r|dk�rd}|||<q�||
k�r*|||<q�|||<q�W|j
}|d�}|d�}|dk	�r^t|�}|dk�rld}|d�}|jd�}t|d�|
||d	�|d�|||d�|d
�|d�|d�|||d
�|d�|�}|�r�|j
�r�q�|�r�|j|��r�q�|j|�q�Wq@WWnBtk
�r�Yn,tk
�rFt�td||f��YnXdS)Nz5%r does not look like a Set-Cookie3 (LWP) format filezSet-Cookie3:ryrxrzr�r�r�r�r�r�r�r�rMrVr	FrTr�z&invalid Set-Cookie3 format file %r: %r)ryrxrzr�r�)r�r�r�r�r�r�rM)�readlinerkr@rrMrurr�r|rKr�rdrr�r�rarvr]r)r�rrlrnro�magicrr��headerrPrQ�line�datarzr{rRr�r�r�r�r�r�r�r�r�rcrrrrscs�











zLWPCookieJar._really_load)TT)NFF)r�r�r�r�r}rprsrrrrr:s

c@s0eZdZdZejd�ZdZdd�Zd
dd	�Z	dS)ra�

    WARNING: you may want to backup your browser's cookies file if you use
    this class to save cookies.  I *think* it works, but there have been
    bugs in the past!

    This class differs from CookieJar only in the format it uses to save and
    load cookies to and from a file.  This class uses the Mozilla/Netscape
    `cookies.txt' format.  lynx uses this file format, too.

    Don't expect cookies saved while the browser is running to be noticed by
    the browser (in fact, Mozilla on unix will overwrite your saved cookies if
    you change them on disk while it's running; on Windows, you probably can't
    save at all while the browser is running).

    Note that the Mozilla/Netscape format will downgrade RFC2965 cookies to
    Netscape cookies on saving.

    In particular, the cookie version and port number information is lost,
    together with information about whether or not Path, Port and Discard were
    specified by the Set-Cookie2 (or Set-Cookie) header, and whether or not the
    domain as set in the HTTP header started with a dot (yes, I'm aware some
    domains in Netscape files start with a dot and some don't -- trust me, you
    really don't want to know any more about this).

    Note that though Mozilla and Netscape use the same format, they use
    slightly different headers.  The class saves cookies using the Netscape
    header by default (Mozilla can cope with that).

    z#( Netscape)? HTTP Cookie Filezr# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

cCs|tj�}|j�}|jj|�s(td|���y
�x|j�}|dkrBP|jd�rX|dd�}|j�jd�s0|j�dkrtq0|jd�\}}	}
}}}
}|dk}|	dk}	|
dkr�|}
d}|jd	�}|	|ks�t	�d
}|dkr�d}d}t
d|
|dd
||	||
d
|||ddi�}|�r|j�rq0|�r$|j|��r$q0|j
|�q0WWnBtk
�rL�Yn,tk
�rvt�td
||f��YnXdS)Nz4%r does not look like a Netscape format cookies filerVr|r�#r�	�TRUEr�FTr	z+invalid Netscape format cookies file %r: %rr�)r�r)rMr�rkr@rr�r�rur�rnrr�r�rarvr]r)r�rrlrnror�r�r�r�r�r�r�r�rzr{r�r�rcrrrrs�sb

zMozillaCookieJar._really_loadNFcCs|dkr"|jdk	r|j}ntt��t|d���}|j|j�tj�}x�|D]�}|rZ|jrZqH|rl|j|�rlqH|j	rxd}nd}|j
jd�r�d}nd}|jdk	r�t
|j�}	nd}	|jdkr�d}
|j}n|j}
|j}|jdj|j
||j||	|
|g�d�qHWWdQRXdS)Nr~r�ZFALSEr�rVr�r|)rlrLrqrrrr�rMr�r�r�r�rur�rmr{rzr~r�)r�rlrnrorr�r�r�r�r�rzr{rrrrps<



zMozillaCookieJar.save)NFF)
r�r�r�r�rvrirkr�rsrprrrrr�s

A)N)N)Yr��__all__r�r-rvrMZurllib.parser�Zurllib.requestZ	threadingr6�ImportErrorZdummy_threadingZhttp.clientZhttpZcalendarr
rrrrmZclientZ	HTTP_PORTr�rqrr%r,r6r7rIr(rtrKr5r8r>rirjr?rFrSrX�Ir\�Xr^rarbrdrjrorprrrqr|r}r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrr-r0r4rrvrrr{rrrrrr�<module>s�



88!



U
D'


#b!\:x__pycache__/cookies.cpython-36.opt-1.pyc000064400000037352150532432170014011 0ustar003


 \�S�
@s|dZddlZddlZdddgZdjZdjZdjZd	d
�ZGdd�de	�Z
ejejdZ
e
d
Zdd�eed��eeee��D�Zejed�ded�di�ejdeje
��jZdd�Zejd�Zejd�Zdd�Zddddd d!d"gZdd#d$d%d&d'd(d)d*d+d,d-d.g
Zdeefd/d0�ZGd1d2�d2e �Z!d3Z"e"d4Z#ejd5e"d6e#d7ej$ej%B�Z&Gd8d�de �Z'Gd9d�de'�Z(dS):a.

Here's a sample session to show how to use this module.
At the moment, this is the only documentation.

The Basics
----------

Importing is easy...

   >>> from http import cookies

Most of the time you start by creating a cookie.

   >>> C = cookies.SimpleCookie()

Once you've created your Cookie, you can add values just as if it were
a dictionary.

   >>> C = cookies.SimpleCookie()
   >>> C["fig"] = "newton"
   >>> C["sugar"] = "wafer"
   >>> C.output()
   'Set-Cookie: fig=newton\r\nSet-Cookie: sugar=wafer'

Notice that the printable representation of a Cookie is the
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.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

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.SimpleCookie()
   >>> C.load("chips=ahoy; vienna=finger")
   >>> C.output()
   'Set-Cookie: chips=ahoy\r\nSet-Cookie: vienna=finger'

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.SimpleCookie()
   >>> C.load('keebler="E=everybody; L=\\"Loves\\"; fudge=\\012;";')
   >>> print(C)
   Set-Cookie: keebler="E=everybody; L=\"Loves\"; fudge=\012;"

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.SimpleCookie()
   >>> C["oreo"] = "doublestuff"
   >>> C["oreo"]["path"] = "/"
   >>> print(C)
   Set-Cookie: oreo=doublestuff; Path=/

Each dictionary element has a 'value' attribute, which gives you
back the value associated with the key.

   >>> C = cookies.SimpleCookie()
   >>> C["twix"] = "none for you"
   >>> C["twix"].value
   'none for you'

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.

   >>> C = cookies.SimpleCookie()
   >>> C["number"] = 7
   >>> C["string"] = "seven"
   >>> C["number"].value
   '7'
   >>> C["string"].value
   'seven'
   >>> C.output()
   'Set-Cookie: number=7\r\nSet-Cookie: string=seven'

Finis.
�N�CookieError�
BaseCookie�SimpleCookie�z; � cCs$ddl}d|}|j|tdd�dS)NrzvThe .%s setter is deprecated. The attribute will be read-only in future releases. Please use the set() method instead.�)�
stacklevel)�warnings�warn�DeprecationWarning)�setterr	�msg�r�$/usr/lib64/python3.6/http/cookies.py�_warn_deprecated_setter�src@seZdZdS)rN)�__name__�
__module__�__qualname__rrrrr�sz!#$%&'*+-.^_`|~:z
 ()/<=>?@[]{}cCsi|]}d||�qS)z\%03or)�.0�nrrr�
<dictcomp>�sr��"z\"�\z\\z[%s]+cCs*|dkst|�r|Sd|jt�dSdS)z�Quote a string for use in a cookie header.

    If the string does not need to be double-quoted, then just return the
    string.  Otherwise, surround the string in doublequotes and quote
    (with a \) special characters.
    Nr)�
_is_legal_key�	translate�_Translator)�strrrr�_quote�srz\\[0-3][0-7][0-7]z[\\].cCsT|dkst|�dkr|S|ddks0|ddkr4|S|dd�}d}t|�}g}x�d|kod|kn�rJtj||�}tj||�}|r�|r�|j||d��Pd	}}|r�|jd�}|r�|jd�}|o�|s�||k�r
|j|||��|j||d�|d}qR|j|||��|jtt||d|d�d���|d}qRWt|�S)
N�rr������r#r#)	�len�
_OctalPatt�search�
_QuotePatt�append�start�chr�int�	_nulljoin)r�ir�resZo_matchZq_match�j�krrr�_unquote�s6


$r1ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDecc	CsRddlm}m}|�}|||�\	}}}}	}
}}}
}d|||||||	|
|fS)Nr)�gmtime�timez#%s, %02d %3s %4d %02d:%02d:%02d GMT)r3r2)ZfutureZweekdaynameZ	monthnamer2r3ZnowZyearZmonthZdayZhhZmmZssZwd�y�zrrr�_getdate�s
r6c	@seZdZdZdddddddd	d
�ZddhZd
d�Zedd��Zej	dd��Zedd��Z
e
j	dd��Z
edd��Zej	dd��Zdd�Zd4dd�Z
dd�ZejZdd �Zd!d"�Zd#d$�Zefd%d&�Zd'd(�Zd)d*�Zd5d,d-�ZeZd.d/�Zd6d0d1�Zd7d2d3�ZdS)8�Morsela�A class to hold ONE (key, value) pair.

    In a cookie, each such pair may have several attributes, so this class is
    used to keep the attributes associated with the appropriate key,value pair.
    This class also includes a coded_value attribute, which is used to hold
    the network representation of the value.  This is most useful when Python
    objects are pickled for network transit.
    �expiresZPath�CommentZDomainzMax-AgeZSecureZHttpOnlyZVersion)r8�path�commentZdomainzmax-age�secure�httponly�versionr<r=cCs4d|_|_|_x|jD]}tj||d�qWdS)Nr)�_key�_value�_coded_value�	_reserved�dict�__setitem__)�self�keyrrr�__init__&szMorsel.__init__cCs|jS)N)r?)rErrrrF.sz
Morsel.keycCstd�||_dS)NrF)rr?)rErFrrrrF2scCs|jS)N)r@)rErrr�value7szMorsel.valuecCstd�||_dS)NrH)rr@)rErHrrrrH;scCs|jS)N)rA)rErrr�coded_value@szMorsel.coded_valuecCstd�||_dS)NrI)rrA)rErIrrrrIDscCs2|j�}||jkr td|f��tj|||�dS)NzInvalid attribute %r)�lowerrBrrCrD)rE�K�VrrrrDIs
zMorsel.__setitem__NcCs.|j�}||jkr td|f��tj|||�S)NzInvalid attribute %r)rJrBrrC�
setdefault)rErF�valrrrrMOs
zMorsel.setdefaultcCs>t|t�stStj||�o<|j|jko<|j|jko<|j|jkS)N)�
isinstancer7�NotImplementedrC�__eq__r@r?rA)rE�morselrrrrQUs
z
Morsel.__eq__cCs$t�}tj||�|jj|j�|S)N)r7rC�update�__dict__)rErRrrr�copy_szMorsel.copycCsVi}x@t|�j�D]0\}}|j�}||jkr:td|f��|||<qWtj||�dS)NzInvalid attribute %r)rC�itemsrJrBrrS)rE�values�datarFrNrrrrSes
z
Morsel.updatecCs|j�|jkS)N)rJrB)rErKrrr�
isReservedKeynszMorsel.isReservedKeycCsh|tkr ddl}|jdtdd�|j�|jkr<td|f��t|�sRtd|f��||_||_	||_
dS)NrzSLegalChars parameter is deprecated, ignored and will be removed in future versions.r)rz Attempt to set a reserved key %rzIllegal key %r)�_LegalCharsr	r
rrJrBrrr?r@rA)rErFrNZ	coded_valZ
LegalCharsr	rrr�setqsz
Morsel.setcCs|j|j|jd�S)N)rFrHrI)r?r@rA)rErrr�__getstate__�szMorsel.__getstate__cCs"|d|_|d|_|d|_dS)NrFrHrI)r?r@rA)rE�staterrr�__setstate__�s

zMorsel.__setstate__�Set-Cookie:cCsd||j|�fS)Nz%s %s)�OutputString)rE�attrs�headerrrr�output�sz
Morsel.outputcCsd|jj|j�fS)Nz<%s: %s>)�	__class__rr`)rErrr�__repr__�szMorsel.__repr__cCsd|j|�jdd�S)Nz�
        <script type="text/javascript">
        <!-- begin hiding
        document.cookie = "%s";
        // end hiding -->
        </script>
        rz\")r`�replace)rErarrr�	js_output�szMorsel.js_outputcCs(g}|j}|d|j|jf�|dkr,|j}t|j��}x�|D]�\}}|dkrPq>||krZq>|dkr�t|t�r�|d|j|t|�f�q>|dkr�t|t�r�|d|j||f�q>|dkr�t|t	�r�|d|j|t
|�f�q>||jk�r|�r|t	|j|��q>|d|j||f�q>Wt|�S)Nz%s=%srr8zmax-agez%s=%dr;)
r(rFrIrB�sortedrVrOr+r6rr�_flags�_semispacejoin)rEra�resultr(rVrFrHrrrr`�s,zMorsel.OutputString)N)Nr_)N)N)rrr�__doc__rBrirG�propertyrFrrHrIrDrMrQ�object�__ne__rUrSrYrZr[r\r^rc�__str__rergr`rrrrr7s@
	


r7z,\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=z\[\]z�
    \s*                            # Optional whitespace at start of cookie
    (?P<key>                       # Start of group 'key'
    [a	]+?   # Any word of at least one letter
    )                              # End of group 'key'
    (                              # Optional group: there may not be a value.
    \s*=\s*                          # Equal Sign
    (?P<val>                         # Start of group 'val'
    "(?:[^\\"]|\\.)*"                  # Any doublequoted string
    |                                  # or
    \w{3},\s[\w\d\s-]{9,11}\s[\d:]{8}\sGMT  # Special case for "expires" attr
    |                                  # or
    [a-]*      # Any word or empty string
    )                                # End of group 'val'
    )?                             # End of optional value group
    \s*                            # Any number of spaces.
    (\s+|;|$)                      # Ending either at space, semicolon, or EOS.
    c@sneZdZdZdd�Zdd�Zddd�Zd	d
�Zdd�Zddd�Z	e	Z
dd�Zddd�Zdd�Z
efdd�ZdS)rz'A container class for a set of Morsels.cCs||fS)a
real_value, coded_value = value_decode(STRING)
        Called prior to setting a cookie's value from the network
        representation.  The VALUE is the value read from HTTP
        header.
        Override this function to modify the behavior of cookies.
        r)rErNrrr�value_decode�szBaseCookie.value_decodecCst|�}||fS)z�real_value, coded_value = value_encode(VALUE)
        Called prior to setting a cookie's value from the dictionary
        representation.  The VALUE is the value being assigned.
        Override this function to modify the behavior of cookies.
        )r)rErN�strvalrrr�value_encode�szBaseCookie.value_encodeNcCs|r|j|�dS)N)�load)rE�inputrrrrG�szBaseCookie.__init__cCs.|j|t��}|j|||�tj|||�dS)z+Private method for setting a cookie's valueN)�getr7r[rCrD)rErFZ
real_valuerI�MrrrZ__set�szBaseCookie.__setcCs:t|t�rtj|||�n|j|�\}}|j|||�dS)zDictionary style assignment.N)rOr7rCrDrs�_BaseCookie__set)rErFrH�rval�cvalrrrrDs
zBaseCookie.__setitem__�Set-Cookie:�
cCs>g}t|j��}x"|D]\}}|j|j||��qW|j|�S)z"Return a string suitable for HTTP.)rhrVr(rc�join)rErarb�seprkrVrFrHrrrrc
s
zBaseCookie.outputcCsNg}t|j��}x(|D] \}}|jd|t|j�f�qWd|jjt|�fS)Nz%s=%sz<%s: %s>)rhrVr(�reprrHrdr�
_spacejoin)rE�lrVrFrHrrrres
zBaseCookie.__repr__cCs:g}t|j��}x |D]\}}|j|j|��qWt|�S)z(Return a string suitable for JavaScript.)rhrVr(rgr,)rErarkrVrFrHrrrrgs
zBaseCookie.js_outputcCs8t|t�r|j|�nx|j�D]\}}|||<q WdS)z�Load cookies from a string (presumably HTTP_COOKIE) or
        from a dictionary.  Loading cookies from a dictionary 'd'
        is equivalent to calling:
            map(Cookie.__setitem__, d.keys(), d.values())
        N)rOr�_BaseCookie__parse_stringrV)rEZrawdatarFrHrrrrt&s

zBaseCookie.loadcCspd}t|�}g}d}d}d}�xd|ko2|kn�r|j||�}	|	sLP|	jd�|	jd�}
}|	jd�}|
ddkr�|s~q |j||
dd�|f�q |
j�tjkr�|s�dS|dkr�|
j�tjkr�|j||
df�q�dSn|j||
t	|�f�q |dk	�r|j||
|j
|�f�d}q dSq Wd}xF|D]>\}
}
}|
|k�rH|||
<n|\}}|j|
||�||
}�q*WdS)	NrFr rrFrN�$T)r$�match�group�endr(rJr7rBrir1rqrx)rErZpattr-rZparsed_itemsZmorsel_seenZTYPE_ATTRIBUTEZ
TYPE_KEYVALUEr�rFrHrw�tpryrzrrrZ__parse_string4sF



zBaseCookie.__parse_string)N)Nr{r|)N)rrrrlrqrsrGrxrDrcrprergrt�_CookiePatternr�rrrrr�s		
	

c@s eZdZdZdd�Zdd�ZdS)rz�
    SimpleCookie supports strings as cookie values.  When setting
    the value using the dictionary assignment notation, SimpleCookie
    calls the builtin str() to convert the value to a string.  Values
    received from HTTP are kept as strings.
    cCst|�|fS)N)r1)rErNrrrrqxszSimpleCookie.value_decodecCst|�}|t|�fS)N)rr)rErNrrrrrrs{szSimpleCookie.value_encodeN)rrrrlrqrsrrrrrqs))rl�re�string�__all__r}r,rjr�r�	ExceptionrZ
ascii_lettersZdigitsrZZ_UnescapedCharsr[�range�map�ordrrS�compile�escape�	fullmatchrrr%r'r1Z_weekdaynameZ
_monthnamer6rCr7Z_LegalKeyCharsZ_LegalValueChars�ASCII�VERBOSEr�rrrrrr�<module>sF
	

2J
__pycache__/client.cpython-36.pyc000064400000104623150532432170012670 0ustar003

Ow�h*��@srdZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
mZdddddd	d
ddd
ddddddddgZdZ
dZdZdZdZdZe�jejj�dd�ejjj�D�ZdZdZd Zejd!�jZejd"�jZ ejd#�Z!ejd$�Z"d%d&d'hZ#dCd)d*�Z$Gd+d,�d,ej%j&�Z'd-d.�Z(e'fd/d0�Z)Gd1d�dej*�Z+Gd2d�d�Z,yddl-Z-Wne.k
�rlYnXGd3d4�d4e,�Z/ej0d4�Gd5d�de1�Z2Gd6d�de2�Z3Gd7d�de2�Z4Gd8d�de2�Z5Gd9d	�d	e2�Z6Gd:d
�d
e2�Z7Gd;d�de2�Z8Gd<d
�d
e2�Z9Gd=d�de9�Z:Gd>d�de9�Z;Gd?d�de9�Z<Gd@d�de2�Z=GdAd�de2�Z>GdBd�de?e=�Z@e2ZAdS)Da�
HTTP/1.1 client library

<intro stuff goes here>
<other stuff, too>

HTTPConnection goes through a number of "states", which define when a client
may legally make another request or fetch the response for a particular
request. This diagram details these state transitions:

    (null)
      |
      | HTTPConnection()
      v
    Idle
      |
      | putrequest()
      v
    Request-started
      |
      | ( putheader() )*  endheaders()
      v
    Request-sent
      |\_____________________________
      |                              | getresponse() raises
      | response = getresponse()     | ConnectionError
      v                              v
    Unread-response                Idle
    [Response-headers-read]
      |\____________________
      |                     |
      | response.read()     | putrequest()
      v                     v
    Idle                  Req-started-unread-response
                     ______/|
                   /        |
   response.read() |        | ( putheader() )*  endheaders()
                   v        v
       Request-started    Req-sent-unread-response
                            |
                            | response.read()
                            v
                          Request-sent

This diagram presents the following rules:
  -- a second request may not be started until {response-headers-read}
  -- a response [object] cannot be retrieved until {request-sent}
  -- there is no differentiation between an unread response body and a
     partially read response body

Note: this enforcement is applied by the HTTPConnection class. The
      HTTPResponse class does not enforce this state machine, which
      implies sophisticated clients may accelerate the request/response
      pipeline. Caution should be taken, though: accelerating the states
      beyond the above pattern may imply knowledge of the server's
      connection-close behavior for certain requests. For example, it
      is impossible to tell whether the server will close the connection
      UNTIL the response headers have been read; this means that further
      requests cannot be placed into the pipeline until it is known that
      the server will NOT be closing the connection.

Logical State                  __state            __response
-------------                  -------            ----------
Idle                           _CS_IDLE           None
Request-started                _CS_REQ_STARTED    None
Request-sent                   _CS_REQ_SENT       None
Unread-response                _CS_IDLE           <response_class>
Req-started-unread-response    _CS_REQ_STARTED    <response_class>
Req-sent-unread-response       _CS_REQ_SENT       <response_class>
�N)�urlsplit�HTTPResponse�HTTPConnection�
HTTPException�NotConnected�UnknownProtocol�UnknownTransferEncoding�UnimplementedFileMode�IncompleteRead�
InvalidURL�ImproperConnectionState�CannotSendRequest�CannotSendHeader�ResponseNotReady�
BadStatusLine�LineTooLong�RemoteDisconnected�error�	responses�Pi�ZUNKNOWNZIdlezRequest-startedzRequest-sentcCsi|]}|j|�qS�)�phrase)�.0�vrr�#/usr/lib64/python3.6/http/client.py�
<dictcomp>ksrii�ds[^:\s][^:\r\n]*s\n(?![ \t])|\r(?![ \t\n])z[- ]z[-]ZPATCHZPOSTZPUT�datacCsfy
|jd�Stk
r`}z:t|j|j|j|jd|j�||j|j�|f�d�WYdd}~XnXdS)z<Call data.encode("latin-1") but show a better error message.zlatin-1z`%s (%.20r) is not valid Latin-1. Use %s.encode('utf-8') if you want to send it encoded in UTF-8.N)�encode�UnicodeEncodeError�encoding�object�start�end�title)r�name�errrrr�_encode�s
r'c@seZdZdd�ZdS)�HTTPMessagecCsn|j�d}t|�}g}d}xL|j�D]@}|d|�j�|krDd}n|dd�j�sXd}|r&|j|�q&W|S)a�Find all header lines matching a given header name.

        Look through the list of headers and find all lines matching a given
        header name (and their continuation lines).  A list of the lines is
        returned, without interpretation.  If the header does not occur, an
        empty list is returned.  If the header occurs multiple times, all
        occurrences are returned.  Case is not important in the header name.

        �:rN�)�lower�len�keys�isspace�append)�selfr%�nZlstZhit�linerrr�getallmatchingheaders�s
z!HTTPMessage.getallmatchingheadersN)�__name__�
__module__�__qualname__r3rrrrr(�sr(cCs\g}xR|jtd�}t|�tkr(td��|j|�t|�tkrJtdt��|dkrPqW|S)z�Reads potential header lines into a list from a file pointer.

    Length of line is limited by _MAXLINE, and number of
    headers is limited by _MAXHEADERS.
    r*zheader linezgot more than %d headers�
�
�)r7r8r9)�readline�_MAXLINEr,rr/�_MAXHEADERSr)�fp�headersr2rrr�
_read_headers�s
r?cCs,t|�}dj|�jd�}tjj|d�j|�S)aGParses only RFC2822 headers from a file pointer.

    email Parser wants to see strings rather than bytes.
    But a TextIOWrapper around self.rfile would buffer too many bytes
    from the stream, bytes which we later need to read as bytes.
    So we read the correct bytes here, as bytes, for email Parser
    to parse.

    r9z
iso-8859-1)�_class)r?�join�decode�email�parserZParserZparsestr)r=r@r>Zhstringrrr�
parse_headers�s
rEcseZdZd@dd�Zdd�Zdd�Zd	d
�Zdd�Z�fd
d�Z�fdd�Z	dd�Z
dd�ZdAdd�Zdd�Z
dd�Zdd�Zdd�Zdd �Zd!d"�Zd#d$�Zd%d&�ZdCd(d)�ZdEd*d+�ZdG�fd,d-�	Zd.d/�Zd0d1�Zd2d3�ZdHd4d5�Zd6d7�Zd8d9�Zd:d;�Zd<d=�Zd>d?�Z �Z!S)IrrNcCsR|jd�|_||_||_d|_|_t|_t|_t|_	t|_
t|_t|_t|_
dS)N�rb)�makefiler=�
debuglevel�_methodr>�msg�_UNKNOWN�version�status�reason�chunked�
chunk_left�length�
will_close)r0�sockrH�method�urlrrr�__init__�szHTTPResponse.__init__cCst|jjtd�d�}t|�tkr*td��|jdkrBtdt|��|sNt	d��y|j
dd�\}}}WnFtk
r�y|j
dd�\}}d}Wntk
r�d}YnXYnX|jd	�s�|j
�t|��y$t|�}|d
ks�|dkr�t|��Wntk
�rt|��YnX|||fS)Nr*z
iso-8859-1zstatus linerzreply:z-Remote end closed connection without response��zHTTP/ri�)�strr=r:r;r,rrH�print�reprr�split�
ValueError�
startswith�_close_connr�int)r0r2rLrMrNrrr�_read_statuss2

zHTTPResponse._read_statuscCs�|jdk	rdSx<|j�\}}}|tkr(Pt|j�}|jdkrFtd|�~qW||_|_|j	�|_
|dkrrd|_n|jd�r�d|_nt
|��t|j�|_|_|jdkr�x&|jD]}td|d	|jj|��q�W|jjd
�}|r�|j�dkr�d|_d|_nd
|_|j�|_d|_|jjd�}|jjd
�}|�rx|j�rxyt|�|_Wntk
�rbd|_YnX|jdk�r~d|_nd|_|tk�s�|tk�s�d|k�o�dkn�s�|jdk�r�d|_|j�r�|j�r�|jdk�r�d|_dS)Nrzheaders:�HTTP/1.0�HTTP/0.9�
zHTTP/1.�zheader:r)ztransfer-encodingrOTFzcontent-lengthr���HEAD)rbrc)r>raZCONTINUEr?r=rHrZ�coderM�striprNrLr^rrErJ�getr+rOrP�_check_closerRrQr`r]Z
NO_CONTENTZNOT_MODIFIEDrI)r0rLrMrNZskipped_headers�hdrZtr_encrQrrr�begin9s\









zHTTPResponse.begincCs�|jjd�}|jdkr:|jjd�}|r6d|j�kr6dSdS|jjd�rJdS|r^d|j�kr^dS|jjd�}|r~d|j�kr~dSdS)NZ
connectionre�closeTFz
keep-alivezproxy-connection)r>rjrLr+)r0ZconnZpconnrrrrk�s
zHTTPResponse._check_closecCs|j}d|_|j�dS)N)r=rn)r0r=rrrr_�szHTTPResponse._close_connc
s$zt�j�Wd|jr|j�XdS)N)�superrnr=r_)r0)�	__class__rrrn�szHTTPResponse.closecst�j�|jr|jj�dS)N)ro�flushr=)r0)rprrrq�s
zHTTPResponse.flushcCsdS)zAlways returns TrueTr)r0rrr�readable�szHTTPResponse.readablecCs
|jdkS)z!True if the connection is closed.N)r=)r0rrr�isclosed�szHTTPResponse.isclosedcCs�|jdkrdS|jdkr$|j�dS|dk	rRt|�}|j|�}t|�d|�j�S|jr`|j�S|j	dkrv|jj
�}n6y|j|j	�}Wntk
r�|j��YnXd|_	|j�|SdS)Nr9rgr)
r=rIr_�	bytearray�readinto�
memoryview�tobytesrO�_readall_chunkedrQ�read�
_safe_readr
)r0�amt�br1�srrrry�s*



zHTTPResponse.readcCs�|jdkrdS|jdkr$|j�dS|jr4|j|�S|jdk	r^t|�|jkr^t|�d|j�}|jj|�}|r~|r~|j�n&|jdk	r�|j|8_|js�|j�|S)z^Read up to len(b) bytes into bytearray b and return the number
        of bytes read.
        Nrrg)	r=rIr_rO�_readinto_chunkedrQr,rvru)r0r|r1rrrru�s$






zHTTPResponse.readintocCsp|jjtd�}t|�tkr$td��|jd�}|dkrB|d|�}y
t|d�Stk
rj|j��YnXdS)Nr*z
chunk size�;r�)	r=r:r;r,r�findr`r]r_)r0r2�irrr�_read_next_chunk_size
s

z"HTTPResponse._read_next_chunk_sizecCs>x8|jjtd�}t|�tkr&td��|s,P|dkrPqWdS)Nr*ztrailer line�
r8r9)r�r8r9)r=r:r;r,r)r0r2rrr�_read_and_discard_trailersz&HTTPResponse._read_and_discard_trailercCsl|j}|sh|dk	r|jd�y|j�}Wntk
rDtd��YnX|dkrb|j�|j�d}||_|S)NrWr9r)rPrzr�r]r
r�r_)r0rPrrr�_get_chunk_left(s
zHTTPResponse._get_chunk_leftcCsr|jtkst�g}y8x,|j�}|dkr(P|j|j|��d|_qWdj|�Stk
rltdj|���YnXdS)Nrr9)	rOrK�AssertionErrorr�r/rzrPrAr
)r0�valuerPrrrrx@s

zHTTPResponse._readall_chunkedcCs�|jtkst�d}t|�}yvxp|j�}|dkr2|St|�|krZ|j|�}|||_||S|d|�}|j|�}||d�}||7}d|_qWWn(tk
r�tt	|d|����YnXdS)Nr)
rOrKr�rvr�r,�_safe_readintorPr
�bytes)r0r|�total_bytes�mvbrPr1�temp_mvbrrrr~Ns&


zHTTPResponse._readinto_chunkedcCsXg}xH|dkrL|jjt|t��}|s4tdj|�|��|j|�|t|�8}qWdj|�S)aVRead the number of bytes requested, compensating for partial reads.

        Normally, we have a blocking socket, but a read() can be interrupted
        by a signal (resulting in a partial read).

        Note that we cannot distinguish between EOF and an interrupt when zero
        bytes have been read. IncompleteRead() will be raised in this
        situation.

        This function should be used when <amt> bytes "should" be present for
        reading. If the bytes are truly not available (due to EOF), then the
        IncompleteRead exception can be used to detect the problem.
        rr9)r=ry�min�	MAXAMOUNTr
rAr/r,)r0r{r}�chunkrrrrzfs

zHTTPResponse._safe_readcCs�d}t|�}xt|t|�kr�tt|�kr@|dt�}|jj|�}n|jj|�}|sjtt|d|��t|���||d�}||7}qW|S)z2Same as _safe_read, but for reading into a buffer.rN)rvr,r�r=rur
r�)r0r|r�r�r�r1rrrr�}szHTTPResponse._safe_readintor*cCs�|jdks|jdkrdS|jr(|j|�S|jdk	rJ|dksD||jkrJ|j}y|jj|�}Wn*tk
r�|dkrt�|jjd�}YnX|r�|r�|j�n|jdk	r�|jt|�8_|S)zvRead with at most one underlying system call.  If at least one
        byte is buffered, return that instead.
        Nrgr9rr�ii@)	r=rIrO�_read1_chunkedrQ�read1r]r_r,)r0r1�resultrrrr��s"



zHTTPResponse.read1cCs4|jdks|jdkrdS|jr(|j|�S|jj|�S)Nrgr9)r=rIrO�
_peek_chunked�peek)r0r1rrrr��s

zHTTPResponse.peekcs�|jdks|jdkrdS|jr*t�j|�S|jdk	rL|dksF||jkrL|j}|jj|�}|rl|rl|j�n|jdk	r�|jt|�8_|S)Nrgr9r)r=rIrOror:rQr_r,)r0�limitr�)rprrr:�s


zHTTPResponse.readlinecCsf|j�}|dks|dkrdSd|ko.|kns8|}|jj|�}|jt|�8_|sbtd��|S)Nrr9)r�r=r�rPr,r
)r0r1rPryrrrr��szHTTPResponse._read1_chunkedcCsBy|j�}Wntk
r dSX|dkr.dS|jj|�d|�S)Nr9)r�r
r=r�)r0r1rPrrrr��szHTTPResponse._peek_chunkedcCs
|jj�S)N)r=�fileno)r0rrrr��szHTTPResponse.filenocCsH|jdkrt��|jj|�p|}t|t�s6t|d�r:|Sdj|�SdS)axReturns the value of the header matching *name*.

        If there are multiple matching headers, the values are
        combined into a single string separated by commas and spaces.

        If no matching header is found, returns *default* or None if
        the *default* is not specified.

        If the headers are unknown, raises http.client.ResponseNotReady.

        N�__iter__z, )r>rZget_all�
isinstancerY�hasattrrA)r0r%�defaultr>rrr�	getheader�s
zHTTPResponse.getheadercCs|jdkrt��t|jj��S)z&Return list of (header, value) tuples.N)r>r�list�items)r0rrr�
getheaders�s
zHTTPResponse.getheaderscCs|S)Nr)r0rrrr��szHTTPResponse.__iter__cCs|jS)ajReturns an instance of the class mimetools.Message containing
        meta-information associated with the URL.

        When the method is HTTP, these headers are those returned by
        the server at the head of the retrieved HTML page (including
        Content-Length and Content-Type).

        When the method is FTP, a Content-Length header will be
        present if (as is now usual) the server passed back a file
        length in response to the FTP retrieval request. A
        Content-Type header will be present if the MIME type can be
        guessed.

        When the method is local-file, returned headers will include
        a Date representing the file's last-modified time, a
        Content-Length giving file size, and a Content-Type
        containing a guess at the file's type. See also the
        description of the mimetools module.

        )r>)r0rrr�info�szHTTPResponse.infocCs|jS)aZReturn the real URL of the page.

        In some cases, the HTTP server redirects a client to another
        URL. The urlopen() function handles this transparently, but in
        some cases the caller needs to know which URL the client was
        redirected to. The geturl() method can be used to get at this
        redirected URL.

        )rU)r0rrr�geturls
zHTTPResponse.geturlcCs|jS)zuReturn the HTTP status code that was sent with the response,
        or None if the URL is not an HTTP URL.

        )rM)r0rrr�getcodeszHTTPResponse.getcode)rNN)N���)r�r�)r�r�)r�)N)"r4r5r6rVrarmrkr_rnrqrrrsryrur�r�r�rxr~rzr�r�r�r:r�r�r�r�r�r�r�r�r��
__classcell__rr)rprr�s<	
!K

 "

	

c@s�eZdZdZdZeZeZdZ	dZ
edd��Zedd��Z
d	ejd	fd
d�Zd0dd
�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd1dd �Zd2d!d"�Zd#d$�Zd%d&�Zd3dd'�d(d)�Zd	ifdd'�d*d+�Zd,d-�Z d.d/�Z!d	S)4rrezHTTP/1.1r*rcCst|tj�S)zFTest whether a file-like object is a text or a binary stream.
        )r��io�
TextIOBase)�streamrrr�
_is_textIO0szHTTPConnection._is_textIOcCsd|dkr|j�tkrdSdSt|d�r*dSyt|�}|jStk
rLYnXt|t�r`t|�SdS)aGet the content-length based on the body.

        If the body is None, we set Content-Length: 0 for methods that expect
        a body (RFC 7230, Section 3.3.2). We also set the Content-Length for
        any method if the body is a str or bytes-like object and not a file.
        Nrry)	�upper�_METHODS_EXPECTING_BODYr�rv�nbytes�	TypeErrorr�rYr,)�bodyrTZmvrrr�_get_content_length6s

z"HTTPConnection._get_content_lengthNcCs\||_||_d|_g|_d|_t|_d|_d|_d|_	i|_
|j||�\|_|_
tj|_dS)N)�timeout�source_addressrS�_buffer�_HTTPConnection__response�_CS_IDLE�_HTTPConnection__staterI�_tunnel_host�_tunnel_port�_tunnel_headers�
_get_hostport�host�port�socketZcreate_connection�_create_connection)r0r�r�r�r�rrrrVVszHTTPConnection.__init__cCs<|jrtd��|j||�\|_|_|r.||_n
|jj�dS)aDSet up host and port for HTTP CONNECT tunnelling.

        In a connection that uses HTTP CONNECT tunneling, the host passed to the
        constructor is used as a proxy server that relays all communication to
        the endpoint passed to `set_tunnel`. This done by sending an HTTP
        CONNECT request to the proxy server when the connection is established.

        This method must be called before the HTML connection has been
        established.

        The headers argument should be a mapping of extra HTTP headers to send
        with the CONNECT request.
        z.Can't set up tunnel for established connectionN)rS�RuntimeErrorr�r�r�r��clear)r0r�r�r>rrr�
set_tunneliszHTTPConnection.set_tunnelcCs�|dkr�|jd�}|jd�}||kr�yt||dd��}WnHtk
r�||dd�dkrh|j}ntd||dd���YnX|d|�}n|j}|r�|ddkr�|ddkr�|dd	�}||fS)
Nr)�]r*rXznonnumeric port: '%s'r�[r�r�)�rfindr`r]�default_portr)r0r�r�r��jrrrr��s

zHTTPConnection._get_hostportcCs
||_dS)N)rH)r0�levelrrr�set_debuglevel�szHTTPConnection.set_debuglevelcCsd|j|jf}|jd�}|j|�x6|jj�D](\}}d||f}|jd�}|j|�q0W|jd�|j|j|jd�}|j	�\}}	}
|	t
jjkr�|j
�td|	|
j�f��xP|jjtd�}t|�tkr�td	��|s�P|dkr�P|jdkr�td
|j��q�WdS)NzCONNECT %s:%d HTTP/1.0
�asciiz%s: %s
zlatin-1�
)rTzTunnel connection failed: %d %sr*zheader liner8r9rzheader:)r�r8r9)r�r�r�sendr�r��response_classrSrIra�http�
HTTPStatusZOKrn�OSErrorrir=r:r;r,rrHrZrB)r0Zconnect_strZ
connect_bytes�headerr�Z
header_strZheader_bytes�responserLrh�messager2rrr�_tunnel�s2





zHTTPConnection._tunnelcCsB|j|j|jf|j|j�|_|jjtjtj	d�|j
r>|j�dS)z3Connect to the host and port specified in __init__.r*N)r�r�r�r�r�rSZ
setsockoptr�ZIPPROTO_TCPZTCP_NODELAYr�r�)r0rrr�connect�s
zHTTPConnection.connectcCsBt|_z|j}|r d|_|j�Wd|j}|r<d|_|j�XdS)z(Close the connection to the HTTP server.N)r�r�rSrnr�)r0rSr�rrrrn�szHTTPConnection.closecCs|jdkr |jr|j�nt��|jdkr8tdt|��d}t|d�r�|jdkrXtd�|j|�}|rx|jdkrxtd�x.|j	|�}|s�P|r�|j
d�}|jj|�qzWdSy|jj|�WnNtk
�r
t
|tj�r�x*|D]}|jj|�q�Wntd	t|���YnXdS)
z�Send `data' to the server.
        ``data`` can be a string object, a bytes object, an array object, a
        file-like object that supports a .read() method, or an iterable object.
        Nrzsend:i ryzsendIng a read()ablezencoding file using iso-8859-1z
iso-8859-1z9data should be a bytes-like object or an iterable, got %r)rS�	auto_openr�rrHrZr[r�r�ryrZsendallr�r��collections�Iterable�type)r0r�	blocksizer�	datablock�drrrr��s:








zHTTPConnection.sendcCs|jj|�dS)zuAdd a line of output to the current request buffer.

        Assumes that the line does *not* end with \r\n.
        N)r�r/)r0r}rrr�_output�szHTTPConnection._outputccsdd}|jdkrtd�|j|�}|r6|jdkr6td�x(|j|�}|sHP|rV|jd�}|Vq8WdS)Ni rzsendIng a read()ablezencoding file using iso-8859-1z
iso-8859-1)rHrZr�ryr)r0rrr�rr�rrr�_read_readable�s



zHTTPConnection._read_readableFcCs$|jjd
�dj|j�}|jdd�=|j|�|dk	�r t|d�rN|j|�}nZyt|�WnFtk
r�yt|�}Wn$tk
r�tdt	|���YnXYnX|f}xZ|D]R}|s�|j
dkr�td�q�|r�|jdkr�t
|�d	�d
�jd�|d}|j|�q�W|�r |jdk�r |jd�dS)z�Send the currently buffered request and clear the buffer.

        Appends an extra \r\n to the buffer.
        A message_body may be specified, to be appended to the request.
        r9s
NryzAmessage_body should be a bytes-like object or an iterable, got %rrzZero length chunk ignoredre�Xz
r�s0

)r9r9)r��extendrAr�r�r�rvr��iterr�rHrZ�	_http_vsnr,r)r0�message_body�encode_chunkedrJZchunksr�rrr�_send_outputs4




zHTTPConnection._send_outputc

Cs�|jr|jj�rd|_|jtkr(t|_n
t|j��|j|�||_|sJd}tj	|�}|rrt
d|�d|j��d���d|||jf}|j
|jd��|jdk�r�|�s�d	}|jd
�r�t|�\}}}}}|�ry|jd�}	Wntk
r�|jd�}	YnX|jd|	�n�|j�r|j}
|j}n|j}
|j}y|
jd�}Wn tk
�rV|
jd�}YnX|
jd
�dk�rtd|d}||jk�r�|jd|�n|jd�}|jdd||f�|�s�|jdd�ndS)a`Send a request to the server.

        `method' specifies an HTTP request method, e.g. 'GET'.
        `url' specifies the object being requested, e.g. '/index.html'.
        `skip_host' if True does not add automatically a 'Host:' header
        `skip_accept_encoding' if True does not add automatically an
           'Accept-Encoding:' header
        N�/z&URL can't contain control characters. z (found at least �)z%s %s %sr�rerXr�ZidnaZHostr)r�[�]z%s:%szAccept-EncodingZidentity)r�rsr�r��_CS_REQ_STARTEDr
�_validate_methodrI�!_contains_disallowed_url_pchar_re�searchr�group�
_http_vsn_strr�rr�r^rr�	putheaderr�r�r�r�r�r�rB)
r0rTrU�	skip_host�skip_accept_encoding�match�requestZnetlocZnilZ
netloc_encr�r�Zhost_encrrr�
putrequestAsV






zHTTPConnection.putrequestcCs,tj|�}|r(td|�d|j��d���dS)z&Validate a method name for putrequest.z)method can't contain control characters. z (found at least r�N)�$_contains_disallowed_method_pchar_rer�r]r�)r0rTr�rrrr��s
zHTTPConnection._validate_methodcGs�|jtkrt��t|d�r$|jd�}t|�s:td|f��t|�}xht|�D]\\}}t|d�rn|jd�||<nt	|t
�r�t|�jd�||<t||�rLtd||f��qLWdj
|�}|d|}|j|�dS)	zkSend a request header line to the server.

        For example: h.putheader('Accept', 'text/html')
        rr�zInvalid header name %rzlatin-1zInvalid header value %rs
	s: N)r�r�rr�r�_is_legal_header_namer]r��	enumerater�r`rY�_is_illegal_header_valuerAr�)r0r��valuesr�Z	one_valuer�rrrr��s"





zHTTPConnection.putheader)r�cCs*|jtkrt|_nt��|j||d�dS)z�Indicate that the last header line has been sent to the server.

        This method sends the request to the server.  The optional message_body
        argument can be used to pass a message body associated with the
        request.
        )r�N)r�r��_CS_REQ_SENTrr�)r0r�r�rrr�
endheaders�s
zHTTPConnection.endheaderscCs|j|||||�dS)z&Send a complete request to the server.N)�
_send_request)r0rTrUr�r>r�rrrr��szHTTPConnection.requestcCs�tdd�|D��}i}d|kr&d|d<d|kr6d|d<|j||f|�d|kr�d	|kr�d
}|j||�}|dkr�|dk	r�|jdkr�td|�d
}|jdd�q�|jdt|��nd
}x |j�D]\}	}
|j|	|
�q�Wt|t�r�t	|d�}|j
||d�dS)Ncss|]}|j�VqdS)N)r+)r�krrr�	<genexpr>�sz/HTTPConnection._send_request.<locals>.<genexpr>r�r*r�zaccept-encodingr�zcontent-lengthztransfer-encodingFrzUnable to determine size of %rTzTransfer-EncodingrOzContent-Lengthr�)r�)�	frozensetr�r�rHrZr�rYr�r�r'r�)r0rTrUr�r>r�Zheader_namesZskipsZcontent_lengthrlr�rrrr��s0	


zHTTPConnection._send_requestcCs�|jr|jj�rd|_|jtks&|jr0t|j��|jdkrR|j|j|j|jd�}n|j|j|jd�}yZy|j	�Wnt
k
r�|j��YnX|jt
ks�t�t|_|jr�|j�n||_|S|j��YnXdS)a)Get the response from the server.

        If the HTTPConnection is in the correct state, returns an
        instance of HTTPResponse or of whatever object is returned by
        the response_class variable.

        If a request has not been sent or if a previous response has
        not be handled, ResponseNotReady is raised.  If the HTTP
        response indicates that the connection should be closed, then
        it will be closed before the response is returned.  When the
        connection is closed, the underlying socket is closed.
        Nr)rT)r�rsr�r�rrHr�rSrIrm�ConnectionErrorrnrRrKr�r�)r0r�rrr�getresponse)s.


zHTTPConnection.getresponse)NN)NF)FF)N)"r4r5r6r�r�rr��	HTTP_PORTr�r�rH�staticmethodr�r�r��_GLOBAL_DEFAULT_TIMEOUTrVr�r�r�r�r�rnr�r�r�r�r�r�r�r�r�r�r�rrrrr&s< 
	'
6
	
.csFeZdZdZeZdddejdfddd��fdd�Z�fdd�Z	�Z
S)�HTTPSConnectionz(This class allows communication via SSL.N)�context�check_hostnamecs�tt|�j||||�|dk	s.|dk	s.|dk	rDddl}	|	jdtd�||_||_|dkrptj	�}|j
dk	rpd|_
|jtjk}
|dkr�|j
}|r�|
r�td��|s�|r�|j||�|j
dk	r�d|_
||_||_dS)NrzTkey_file, cert_file and check_hostname are deprecated, use a custom context instead.rWTzMcheck_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED)rorrV�warnings�warn�DeprecationWarning�key_file�	cert_file�sslZ_create_default_https_contextZpost_handshake_authZverify_modeZ	CERT_NONErr]Zload_cert_chain�_context�_check_hostname)r0r�r�r	r
r�r�rrrZwill_verify)rprrrVts0


zHTTPSConnection.__init__cs�t�j�|jr|j}n|j}|jj|j|d�|_|jjr�|jr�yt	j
|jj�|�Wn.tk
r�|jj
tj�|jj��YnXdS)z(Connect to a host on a given (SSL) port.)�server_hostnameN)ror�r�r�rZwrap_socketrSrr
rZmatch_hostnameZgetpeercert�	ExceptionZshutdownr�Z	SHUT_RDWRrn)r0r)rprrr��s



zHTTPSConnection.connect)r4r5r6�__doc__�
HTTPS_PORTr�r�rrVr�r�rr)rprrmsrc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdd�ZdS)rcCs|f|_||_dS)N)�argsrL)r0rLrrrrV�szUnknownProtocol.__init__N)r4r5r6rVrrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)r	N)r4r5r6rrrrr	�sc@s&eZdZddd�Zdd�Zdd�ZdS)	r
NcCs|f|_||_||_dS)N)r�partial�expected)r0rrrrrrV�szIncompleteRead.__init__cCs2|jdk	rd|j}nd}d|jjt|j�|fS)Nz, %i more expectedrXz%s(%i bytes read%s))rrpr4r,r)r0�errr�__repr__�s

zIncompleteRead.__repr__cCst|�S)N)r[)r0rrr�__str__�szIncompleteRead.__str__)N)r4r5r6rVrrrrrrr
�s
c@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)r
N)r4r5r6rrrrr
�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdS)rN)r4r5r6rrrrr�sc@seZdZdd�ZdS)rcCs|st|�}|f|_||_dS)N)r[rr2)r0r2rrrrV�szBadStatusLine.__init__N)r4r5r6rVrrrrr�sc@seZdZdd�ZdS)rcCstj|dt|f�dS)Nz&got more than %d bytes when reading %s)rrVr;)r0Z	line_typerrrrV�szLineTooLong.__init__N)r4r5r6rVrrrrr�sc@seZdZdd�ZdS)rcOs"tj|d�tj|f|�|�dS)NrX)rrV�ConnectionResetError)r0�pos�kwrrrrV�szRemoteDisconnected.__init__N)r4r5r6rVrrrrr�s)r)BrZemail.parserrCZ
email.messager�r��os�rer�r�Zurllib.parser�__all__rrrKr�r�r��globals�updater��__members__r�rr�r;r<�compile�	fullmatchr�r�r�r�r�r�r'r�ZMessager(r?rE�BufferedIOBaserrr�ImportErrorrr/rrrrrrr	r
rr
rrrrrrrrrrr�<module>Es�



9F=
__pycache__/cookiejar.cpython-36.opt-2.pyc000064400000112411150532432170014312 0ustar003

Ow�hr+�@s&ddddddddgZdd	lZdd	lZdd	lZdd	lZdd	lZdd	lZydd	lZ	Wne
k
rldd	lZ	YnXdd	lZ
dd
lmZdZd	add
�Zee
jj�ZdZdd�ZdZdd�ZdddddddgZdddddd d!d"d#d$d%d&gZgZxeD]Zejej ��q�Wdtd'd(�Z!dud)d*�Z"d	d	d	d	d+�Z#ej$d,ej%�Z&d-d.�Z'd/d0�Z(ej$d1ej%�Z)ej$d2ej*ej%B�Z+ej$d3ej,ej%B�Z-d4d5�Z.ej$d6ej,ej%B�Z/d7d8�Z0d9d:�Z1ej$d;�Z2ej$d<�Z3ej$d=�Z4ej$d>�Z5d?d@�Z6ej$dA�Z7dBdC�Z8dDdE�Z9dFdG�Z:ej$dHej%�Z;dIdJ�Z<dKdL�Z=dMdN�Z>dOdP�Z?ej$dQej%�Z@dRdS�ZAdTdU�ZBdVdW�ZCdXdY�ZDdZZEej$d[�ZFd\d]�ZGd^d_�ZHd`da�ZIdbdc�ZJGddd�d�ZKGded�d�ZLGdfd�deL�ZMdgdh�ZNdidj�ZOGdkdl�dl�ZPGdmd�d�ZQGdnd�deR�ZSGdod�deQ�ZTdpdq�ZUGdrd�deT�ZVGdsd�deT�ZWd	S)v�Cookie�	CookieJar�CookiePolicy�DefaultCookiePolicy�
FileCookieJar�LWPCookieJar�	LoadError�MozillaCookieJar�N)�timegmFcGs(tsdStsddl}|jd�atj|�S)Nr	zhttp.cookiejar)�debug�logger�loggingZ	getLogger)�argsr
�r�&/usr/lib64/python3.6/http/cookiejar.py�_debug.s
rzQa filename was not supplied (nor was the CookieJar instance initialised with one)cCsJddl}ddl}ddl}|j�}|jd|�|j�}|jd|dd�dS)Nr	zhttp.cookiejar bug!
%s�)�
stacklevel)�io�warnings�	traceback�StringIO�	print_exc�getvalue�warn)rrr�f�msgrrr�_warn_unhandled_exception<s
ri�cCs�|dd�\}}}}}}|tkr�d|ko2dknr�d|koJdknr�d|kobdknr�d|kozdknr�d|ko�dknr�t|�SdSdS)	N����r	��;�=)�
EPOCH_YEARr
)�tt�year�monthZmday�hour�min�secrrr�_timegmKs
8Hr,ZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs@|dkrtjj�}ntjj|�}d|j|j|j|j|j|jfS)Nz%04d-%02d-%02d %02d:%02d:%02dZ)	�datetime�utcnow�utcfromtimestampr'r(�dayr)�minute�second)�t�dtrrr�	time2isozYs
r5cCsR|dkrtjj�}ntjj|�}dt|j�|jt|jd|j|j	|j
|jfS)Nz#%s, %02d-%s-%04d %02d:%02d:%02d GMTr)r-r.r/�DAYSZweekdayr0�MONTHSr(r'r)r1r2)r3r4rrr�
time2netscapelsr8)ZGMT�UTCZUT�Zz^([-+])?(\d\d?):?(\d\d)?$cCsjd}|tkrd}nTtj|�}|rfdt|jd��}|jd�rR|dt|jd��}|jd�dkrf|}|S)Nr	ir��<r�-)�	UTC_ZONES�TIMEZONE_RE�search�int�group)�tz�offset�mrrr�offset_from_tz_string�s

rFc
Cs�t|�}|tjkrdSytj|j��d}WnXtk
r�yt|�}Wntk
r\dSXd|kopdknr||}ndSYnX|dkr�d}|dkr�d}|dkr�d}t|�}t|�}t|�}t|�}|dk�r0tjtj��d}|d}	|}
|||	}|	|
}	t	|	�dk�r0|	dk�r(|d}n|d}t
|||||||f�}|dk	�r�|dk�r^d}|j�}t|�}|dk�r|dS||}|S)Nrr r	i��d�2r9)
rAr-ZMAXYEAR�MONTHS_LOWER�index�lower�
ValueError�timeZ	localtime�absr,�upperrF)
r0�mon�yr�hrr*r+rCZimonZcur_yrrEZtmpr3rDrrr�	_str2time�sV







rSzV^[SMTWF][a-z][a-z], (\d\d) ([JFMASOND][a-z][a-z]) (\d\d\d\d) (\d\d):(\d\d):(\d\d) GMT$z+^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\s*a�^
    (\d\d?)            # day
       (?:\s+|[-\/])
    (\w+)              # month
        (?:\s+|[-\/])
    (\d+)              # year
    (?:
          (?:\s+|:)    # separator before clock
       (\d\d?):(\d\d)  # hour:min
       (?::(\d\d))?    # optional seconds
    )?                 # optional clock
       \s*
    ([-+]?\d{2,4}|(?![APap][Mm]\b)[A-Za-z]+)? # timezone
       \s*
    (?:\(\w+\))?       # ASCII representation of timezone in parens.
       \s*$cCs�tj|�}|rl|j�}tj|dj��d}t|d�|t|d�t|d�t|d�t|d�f}t|�S|j	�}t
jd|d�}dgd\}}}}}}	}
tj|�}|dk	r�|j�\}}}}}}	}
ndSt
||||||	|
�S)	Nrrr	r;����)�STRICT_DATE_REr@�groupsrIrJrKrA�floatr,�lstrip�
WEEKDAY_RE�sub�LOOSE_HTTP_DATE_RErS)�textrE�grPr&r0rQrRr*r+rCrrr�	http2time�s
"
raa�^
    (\d{4})              # year
       [-\/]?
    (\d\d?)              # numerical month
       [-\/]?
    (\d\d?)              # day
   (?:
         (?:\s+|[-:Tt])  # separator before clock
      (\d\d?):?(\d\d)    # hour:min
      (?::?(\d\d(?:\.\d*)?))?  # optional seconds (and fractional)
   )?                    # optional clock
      \s*
   ([-+]?\d\d?:?(:?\d\d)?
    |Z|z)?               # timezone  (Z is "zero meridian", i.e. GMT)
      \s*$c
Csd|j�}dgd\}}}}}}}tj|�}|dk	rL|j�\}}}}}}}}	ndSt|||||||�S)NrW)r[�ISO_DATE_REr@rYrS)
r_r0rPrQrRr*r+rCrE�_rrr�iso2time's

rdcCs*|jd�\}}|jd|�|j|d�S)Nr	)�span�string)�match�start�endrrr�	unmatchedHsrjz^\s*([^=\s;,]+)z&^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"z^\s*=\s*([^\s;,]*)z\\(.)c
Csg}�x|D]�}|}g}x�|r�tj|�}|r�t|�}|jd�}tj|�}|rlt|�}|jd�}tjd|�}n.tj|�}|r�t|�}|jd�}|j�}nd}|j	||f�q|j
�jd�r�|j
�dd�}|r�|j	|�g}qtj
dd|�\}}	|}qW|r|j	|�qW|S)Nrz\1�,z^[=\s;]*rV)�HEADER_TOKEN_REr@rjrB�HEADER_QUOTED_VALUE_RE�HEADER_ESCAPE_REr]�HEADER_VALUE_RE�rstrip�appendr[�
startswith�re�subn)
Z
header_values�resultr_Z	orig_text�pairsrE�name�valueZnon_junkZ
nr_junk_charsrrr�split_header_wordsQs>.







ryz([\"\\])cCs�g}xt|D]l}g}xN|D]F\}}|dk	rTtjd|�sHtjd|�}d|}d||f}|j|�qW|r
|jdj|��q
Wdj|�S)Nz^\w+$z\\\1z"%s"z%s=%sz; z, )rsr@�HEADER_JOIN_ESCAPE_REr]rq�join)Zlists�headersrv�attr�k�vrrr�join_header_words�s
r�cCs0|jd�r|dd�}|jd�r,|dd�}|S)N�"r���)rr�endswith)r_rrr�strip_quotes�s


r�cCsd}g}x�|D]�}g}d}x�t|jd	��D]�\}}|j�}|jd
�\}}	}
|j�}|sd|dkr*Pnq*|	rp|
j�nd}
|dkr�|j�}||kr�|}|dkr�|
dk	r�t|
�}
d}n|dkr�|
dk	r�tt|
��}
|j||
f�q*W|r|�s�|jd�|j|�qW|S)N�expires�domain�path�secure�version�port�max-ageF�;�=r	T�0)r�r�r�r�r�r�r�)r�r�)�	enumerate�split�strip�	partitionrKr�rarq)Z
ns_headersZknown_attrsruZ	ns_headerrv�version_setZiiZparam�key�sep�val�lcrrr�parse_ns_headers�s@

r�z\.\d+$cCs:tj|�rdS|dkrdS|ddks2|ddkr6dSdS)NFrVr	�.rTr�)�IPV4_REr@)r_rrr�is_HDNs
r�cCsl|j�}|j�}||krdSt|�s(dS|j|�}|dksB|dkrFdS|jd�sTdSt|dd��shdSdS)NTFrr	r�r�)rKr��rfindrr)�A�B�irrr�domain_matchs

r�cCstj|�rdSdS)NFT)r�r@)r_rrr�liberal_is_HDNBs
r�cCsb|j�}|j�}t|�ot|�s0||kr,dSdS|jd�}|rL|j|�rLdS|r^||kr^dSdS)NTFr�)rKr�rrr�)r�r��initial_dotrrr�user_domain_matchLs
r�z:\d+$cCsB|j�}tjj|�d}|dkr,|jdd�}tjd|d�}|j�S)NrrVZHost)�get_full_url�urllib�parseZurlparseZ
get_header�cut_port_rer]rK)�request�url�hostrrr�request_hostasr�cCs6t|�}}|jd�dkr.tj|�r.|d}||fS)Nr�rz.localr�)r��findr�r@)r��erhn�req_hostrrr�eff_request_hostqsr�cCs4|j�}tjj|�}t|j�}|jd�s0d|}|S)N�/)r�r�r�Zurlsplit�escape_pathr�rr)r�r��partsr�rrr�request_path|s

r�cCs^|j}|jd�}|dkrV||dd�}yt|�WqZtk
rRtd|�dSXnt}|S)N�:r	rznonnumeric port: '%s')r�r�rArLr�DEFAULT_HTTP_PORT)r�r�r�r�rrr�request_port�s

r�z%/;:@&=+$,!~*'()z%([0-9a-fA-F][0-9a-fA-F])cCsd|jd�j�S)Nz%%%sr)rBrO)rgrrr�uppercase_escaped_char�sr�cCstjj|t�}tjt|�}|S)N)r�r�Zquote�HTTP_PATH_SAFE�ESCAPED_CHAR_REr]r�)r�rrrr��s
r�cCsP|jd�}|dkrL||dd�}|jd�}t|�rL|dksD|dkrLd|S|S)Nr�r	rZlocal)r�r�)�hr��brrr�reach�s

r�cCs$t|�}t|t|j��sdSdSdS)NTF)r�r�r�Zorigin_req_host)r�r�rrr�is_third_party�s
r�c@sJeZdZddd�Zdd�Zddd�Zd	d
�Zddd�Zd
d�Zdd�Z	dS)rFcCs�|dk	rt|�}|dk	r$tt|��}|dkr<|dkr<td��||_||_||_||_||_|j�|_	||_
||_|	|_|
|_
||_||_|
|_||_||_||_tj|�|_dS)NTz-if port is None, port_specified must be false)rArZrLr�rwrxr��port_specifiedrKr��domain_specified�domain_initial_dotr��path_specifiedr�r��discard�comment�comment_url�rfc2109�copy�_rest)�selfr�rwrxr�r�r�r�r�r�r�r�r�r�r�r��restr�rrr�__init__�s.

zCookie.__init__cCs
||jkS)N)r�)r�rwrrr�has_nonstandard_attrszCookie.has_nonstandard_attrNcCs|jj||�S)N)r��get)r�rw�defaultrrr�get_nonstandard_attrszCookie.get_nonstandard_attrcCs||j|<dS)N)r�)r�rwrxrrr�set_nonstandard_attrszCookie.set_nonstandard_attrcCs,|dkrtj�}|jdk	r(|j|kr(dSdS)NTF)rMr�)r��nowrrr�
is_expireds
zCookie.is_expiredcCsX|jdkrd}n
d|j}|j||j}|jdk	rFd|j|jf}n|j}d||fS)NrVr�z%s=%sz<Cookie %s for %s>)r�r�r�rxrw)r��p�limitZ	namevaluerrr�__str__%s


zCookie.__str__cCspg}x,dD]$}t||�}|jd|t|�f�q
W|jdt|j��|jdt|j��d|jjdj|�fS)Nr�rwrxr�r�r�r�r�r�r�r�r�r�r�r�z%s=%szrest=%sz
rfc2109=%sz%s(%s)z, )r�rwrxr�r�r�r�r�r�r�r�r�r�r�r�)�getattrrq�reprr�r��	__class__�__name__r{)r�rrwr}rrr�__repr__/s
zCookie.__repr__)F)N)N)
r��
__module__�__qualname__r�r�r�r�r�r�r�rrrrr�s
 


c@s,eZdZdd�Zdd�Zdd�Zdd�Zd	S)
rcCs
t��dS)N)�NotImplementedError)r��cookier�rrr�set_okGszCookiePolicy.set_okcCs
t��dS)N)r�)r�r�r�rrr�	return_okPszCookiePolicy.return_okcCsdS)NTr)r�r�r�rrr�domain_return_okTszCookiePolicy.domain_return_okcCsdS)NTr)r�r�r�rrr�path_return_okYszCookiePolicy.path_return_okN)r�r�r�r�r�r�r�rrrrr>s		c@s�eZdZdZdZdZdZeeBZdddddddddeddfdd	�Zd
d�Z	dd
�Z
dd�Zdd�Zdd�Z
dd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Zd2d3�Zd4d5�ZdS)6rrrrTr	NTFc

Csp||_||_||_||_||_||_|	|_|
|_||_||_	|dk	rPt
|�|_nf|_|dk	rft
|�}||_dS)N)
�netscape�rfc2965�rfc2109_as_netscape�hide_cookie2�
strict_domain�strict_rfc2965_unverifiable�strict_ns_unverifiable�strict_ns_domain�strict_ns_set_initial_dollar�strict_ns_set_path�tuple�_blocked_domains�_allowed_domains)
r��blocked_domains�allowed_domainsr�r�r�r�r�r�r�r�r�r�rrrr�is 
zDefaultCookiePolicy.__init__cCs|jS)N)r�)r�rrrr��sz#DefaultCookiePolicy.blocked_domainscCst|�|_dS)N)r�r�)r�r�rrr�set_blocked_domains�sz'DefaultCookiePolicy.set_blocked_domainscCs"x|jD]}t||�rdSqWdS)NTF)r�r�)r�r�Zblocked_domainrrr�
is_blocked�s
zDefaultCookiePolicy.is_blockedcCs|jS)N)r�)r�rrrr��sz#DefaultCookiePolicy.allowed_domainscCs|dk	rt|�}||_dS)N)r�r�)r�r�rrr�set_allowed_domains�sz'DefaultCookiePolicy.set_allowed_domainscCs0|jdkrdSx|jD]}t||�rdSqWdS)NFT)r�r�)r�r�Zallowed_domainrrr�is_not_allowed�s

z"DefaultCookiePolicy.is_not_allowedcCsBtd|j|j�x,dD]$}d|}t||�}|||�sd	SqWd
S)Nz - checking cookie %s=%sr��
verifiabilityrwr�r�r�Zset_ok_FT)r�r�rwr�r�r�)rrwrxr�)r�r�r��n�fn_name�fnrrrr��s


zDefaultCookiePolicy.set_okcCs^|jdkrtd|j|j�dS|jdkr<|jr<td�dS|jdkrZ|jrZtd�dSdS)Nz0   Set-Cookie2 without version attribute (%s=%s)Fr	z$   RFC 2965 cookies are switched offz$   Netscape cookies are switched offT)r�rrwrxr�r�)r�r�r�rrr�set_ok_version�s
z"DefaultCookiePolicy.set_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS)Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT)�unverifiabler�r�r�rr�)r�r�r�rrr�set_ok_verifiability�sz(DefaultCookiePolicy.set_ok_verifiabilitycCs0|jdkr,|jr,|jjd�r,td|j�dSdS)Nr	�$z'   illegal name (starts with '$'): '%s'FT)r�r�rwrrr)r�r�r�rrr�set_ok_name�s
zDefaultCookiePolicy.set_ok_namecCsL|jrHt|�}|jdks(|jdkrH|jrH|j|j�rHtd|j|�dSdS)Nr	z7   path attribute %s is not a prefix of request path %sFT)r�r�r�r�rrr�r)r�r�r��req_pathrrr�set_ok_path�s

zDefaultCookiePolicy.set_ok_pathc
Cs�|j|j�rtd|j�dS|j|j�r8td|j�dS|j�r�t|�\}}|j}|jr�|jd�dkr�|jd�}|jdd|�}|dkr�||dd�}||d|�}	|	j	�d$kr�t
|�dkr�td|�dS|jd��r�|dd�}
n|}
|
jd�dk}|�r|dk�rtd|�dS|j
dk�rb|j|��rb|jd��rbd|j|��rbtd ||�dS|j
dk�s||j|j@�r�t||��s�td!||�dS|j
dk�s�|j|j@�r�|dt
|��}|jd�dk�r�tj|��r�td"||�dSd#S)%Nz"   domain %s is in user block-listFz&   domain %s is not in user allow-listr�rr	r�co�ac�com�edu�org�net�gov�milrA�aero�biz�cat�coop�info�jobs�mobi�museumrw�pro�travel�euz&   country-code second level domain %sz.localz/   non-local domain %s contains no embedded dotzO   effective request-host %s (even with added initial dot) does not end with %sz5   effective request-host %s does not domain-match %sz.   host prefix %s for domain %s contains a dotT)rrrrrrrrrArr	r
rrr
rrrwrrr)r�r�rr�r�r�r��countr�rK�lenrrr�r�r�r��DomainRFC2965Matchr��DomainStrictNoDotsr�r@)
r�r�r�r�r�r�r��jZtldZsldZundotted_domainZ
embedded_dotsZhost_prefixrrr�
set_ok_domain�sf

z!DefaultCookiePolicy.set_ok_domaincCs�|jr�t|�}|dkrd}nt|�}x\|jjd�D]:}yt|�Wntk
r`td|�dSX||kr2Pq2Wtd||j�dSdS)N�80rkz   bad port %s (not numeric)Fz$   request port (%s) not found in %sT)r�r��strr�r�rArLr)r�r�r��req_portr�rrr�set_ok_port%s"

zDefaultCookiePolicy.set_ok_portcCsBtd|j|j�x,dD]$}d|}t||�}|||�sd	SqWd
S)Nz - checking cookie %s=%sr�r�r�r�r�r�Z
return_ok_FT)r�r�r�r�r�r�)rrwrxr�)r�r�r�r�r�r�rrrr�:s	


zDefaultCookiePolicy.return_okcCs@|jdkr|jrtd�dS|jdkr<|jr<td�dSdS)Nr	z$   RFC 2965 cookies are switched offFz$   Netscape cookies are switched offT)r�r�rr�)r�r�r�rrr�return_ok_versionLsz%DefaultCookiePolicy.return_ok_versioncCsJ|jrFt|�rF|jdkr*|jr*td�dS|jdkrF|jrFtd�dSdS)Nr	z>   third-party RFC 2965 cookie during unverifiable transactionFz>   third-party Netscape cookie during unverifiable transactionT)r�r�r�r�rr�)r�r�r�rrr�return_ok_verifiabilityUsz+DefaultCookiePolicy.return_ok_verifiabilitycCs |jr|jdkrtd�dSdS)NZhttpsz(   secure cookie with non-secure requestFT)r��typer)r�r�r�rrr�return_ok_secureasz$DefaultCookiePolicy.return_ok_securecCs|j|j�rtd�dSdS)Nz   cookie expiredFT)r��_nowr)r�r�r�rrr�return_ok_expiresgsz%DefaultCookiePolicy.return_ok_expirescCsP|jrLt|�}|dkrd}x0|jjd�D]}||kr(Pq(Wtd||j�dSdS)Nrrkz0   request port %s does not match cookie port %sFT)r�r�r�r)r�r�r�rr�rrr�return_ok_portms
z"DefaultCookiePolicy.return_ok_portcCs�t|�\}}|j}|r,|jd�r,d|}n|}|jdkrb|j|j@rb|jrb||krbtd�dS|jdkr�t||�r�td||�dS|jdkr�d|j	|�r�td||�dSdS)Nr�r	zQ   cookie with unspecified domain does not string-compare equal to request domainFzQ   effective request-host name %s does not domain-match RFC 2965 cookie domain %sz;   request-host %s does not match Netscape cookie domain %sT)
r�r�rrr�r��DomainStrictNonDomainr�rr�r�)r�r�r�r�r�r��	dotdomainrrr�return_ok_domain{s&

z$DefaultCookiePolicy.return_ok_domaincCs�t|�\}}|jd�sd|}|jd�s0d|}|rJ|jd�rJd|}n|}|j|�p`|j|�sfdS|j|�r~td|�dS|j|�r�td|�dSdS)Nr�Fz"   domain %s is in user block-listz&   domain %s is not in user allow-listT)r�rrr�r�rr�)r�r�r�r�r�r%rrrr��s"






z$DefaultCookiePolicy.domain_return_okcCs0td|�t|�}|j|�s,td||�dSdS)Nz- checking cookie path=%sz  %s does not path-match %sFT)rr�rr)r�r�r�r�rrrr��s

z"DefaultCookiePolicy.path_return_ok)r�r�r�rr$rZ
DomainLiberalZDomainStrictr�r�r�r�r�r�r�r�r�r�r�r�rrr�rrr r"r#r&r�r�rrrrr_sJ	;	cCst|j��}t|j|�S)N)�sorted�keys�mapr�)Zadictr(rrr�vals_sorted_by_key�sr*ccsZt|�}xL|D]D}d}y
|jWntk
r4YnXd}t|�EdH|s|VqWdS)NFT)r*�items�AttributeError�
deepvalues)�mapping�values�objrrrr-�s

r-c@seZdZdS)�AbsentN)r�r�r�rrrrr1�sr1c@s�eZdZejd�Zejd�Zejd�Zejd�Zejd�Z	ejdej
�Zd2dd	�Zd
d�Z
dd
�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zdd�Zd d!�Zd"d#�Zd3d$d%�Zd&d'�Zd(d)�Zd*d+�Zd,d-�Zd.d/�Zd0d1�Z dS)4rz\Wz([\"\\])z\.?[^.]*z[^.]*z^\.+z^\#LWP-Cookies-(\d+\.\d+)NcCs(|dkrt�}||_tj�|_i|_dS)N)r�_policy�
_threading�RLock�
_cookies_lock�_cookies)r��policyrrrr��s

zCookieJar.__init__cCs
||_dS)N)r2)r�r7rrr�
set_policy�szCookieJar.set_policycCs�g}|jj||�sgStd|�|j|}xd|j�D]X}|jj||�sHq4||}x:|j�D].}|jj||�svtd�qZtd�|j|�qZWq4W|S)Nz!Checking %s for cookies to returnz   not returning cookiez   it's a match)	r2r�rr6r(r�r/r�rq)r�r�r��cookiesZcookies_by_pathr�Zcookies_by_namer�rrr�_cookies_for_domain�s 

zCookieJar._cookies_for_domaincCs.g}x$|jj�D]}|j|j||��qW|S)N)r6r(�extendr:)r�r�r9r�rrr�_cookies_for_request�szCookieJar._cookies_for_requestc	CsF|jdd�dd�d}g}�x$|D�]}|j}|sLd}|dkrL|jd|�|jdk	r~|jj|j�r~|dkr~|jjd|j�}n|j}|jdkr�|j|j�n|jd	|j|f�|dkr"|j	r�|jd
|j
�|jjd��r|j}|j
o�|jd��r|dd�}|jd
|�|jdk	r"d}|j�r4|d|j}|j|�q"W|S)NcSs
t|j�S)N)rr�)�arrr�<lambda>sz)CookieJar._cookie_attrs.<locals>.<lambda>T)r��reverseFr	z$Version=%sz\\\1z%s=%sz
$Path="%s"r�rz$Domain="%s"z$Portz="%s")�sortr�rqrx�non_word_rer@�quote_rer]rwr�r�r�rrr�r�r�)	r�r9r��attrsr�r�rxr�r�rrr�
_cookie_attrss>



zCookieJar._cookie_attrsc
Cs�td�|jj�z�ttj��|j_|_|j|�}|j|�}|r^|j	d�s^|j
ddj|��|jjr�|jj
r�|j	d�r�x$|D]}|jdkr�|j
dd�Pq�WWd|jj�X|j�dS)N�add_cookie_headerrz; ZCookie2rz$Version="1")rr5�acquirerArMr2r!r<rDZ
has_headerZadd_unredirected_headerr{r�r�r��release�clear_expired_cookies)r�r�r9rCr�rrrrE?s$






zCookieJar.add_cookie_headercCs�g}d}d}�x||D�]r}|d\}}d}d}	i}
i}�x4|d
d�D�]"\}}
|j�}||ksh||krl|}||kr�|
dkr�d}
||
kr�qF|dkr�|
dkr�td�d}	P|
j�}
|dkr�|r�qF|
dkr�td�qF|dk�rd}yt|
�}
Wn$tk
�rtd�d}	PYnXd}|j|
}
||k�s2||k�rb|
dk�rX|dk�rXtd|�d}	P|
|
|<qF|
||<qFW|	�rvq|j|||
|f�qW|S)Nr�r�r�r��max-ager�r�r�r��
commenturlr	FrTz%   missing value for domain attributezM   missing or invalid value for expires attribute: treating as session cookiez?   missing or invalid (non-numeric) value for max-age attributez!   missing value for %s attribute)r�r�)r�r�rIr�r�r�r�rJ)r�r�rJ)rKrrArLr!rq)r��	attrs_set�
cookie_tuples�
boolean_attrs�value_attrsZcookie_attrsrwrxZmax_age_setZ
bad_cookie�standardr�r~rr�rrr�_normalized_cookie_tuples`sl






z#CookieJar._normalized_cookie_tuplesc!Cs$|\}}}}|jdt�}|jdt�}|jdt�}	|jdt�}
|jdd�}|dk	rryt|�}Wntk
rpdSX|jdd�}|jdd�}
|jd	d�}|jd
d�}|tk	r�|dkr�d}t|�}nXd}t|�}|jd
�}|dk�r|dkr�|d|�}n|d|d�}t|�dk�rd
}|tk	}d}|�r8t|j	d��}|tk�rTt
|�\}}|}n|j	d��shd|}d}|	tk	�r�|	dk�r�t|�}	nd}tj
dd|	�}	nd}	|
tk�r�d}
d}
nH|
|jk�r�y|j|||�Wntk
�r�YnXtd|||�dSt||||	||||||||
|
|||�S)Nr�r�r�r�r�r�Fr�r�rJrVTr�rr	r�z\s+z2Expiring cookie, domain='%s', path='%s', name='%s'r�)r�r1rArLr�r�r�r�boolrrr�r�rsr]r!�clear�KeyErrorrr)r��tupr�rwrxrOr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrr�_cookie_from_cookie_tuple�s�








z#CookieJar._cookie_from_cookie_tuplecCs:|j|�}g}x&|D]}|j||�}|r|j|�qW|S)N)rPrUrq)r�rKr�rLr9rTr�rrr�_cookies_from_attrs_sets

z!CookieJar._cookies_from_attrs_setcCsLt|jdd�}|dkr |jj}x&|D]}|jdkr&d|_|r&d|_q&WdS)Nr�rTr	)r�r2r�r�r�)r�r9Z
rfc2109_as_nsr�rrr�_process_rfc2109_cookies&s


z"CookieJar._process_rfc2109_cookiesc
Cs6|j�}|jdg�}|jdg�}|jj}|jj}|r<|s`|rH|s`|rT|s`|rd|rdgSy|jt|�|�}Wntk
r�t�g}YnX|o�|�r2y|jt	|�|�}	Wntk
r�t�g}	YnX|j
|	�|�r"i}
x |D]}d|
|j|j|j
f<q�W|
fdd�}t||	�}	|	�r2|j|	�|S)NzSet-Cookie2z
Set-CookiecSs|j|j|jf}||kS)N)r�r�rw)Z	ns_cookie�lookupr�rrr�no_matching_rfc2965^sz3CookieJar.make_cookies.<locals>.no_matching_rfc2965)rZget_allr2r�r�rVry�	Exceptionrr�rWr�r�rw�filterr;)
r��responser�r|Zrfc2965_hdrsZns_hdrsr�r�r9Z
ns_cookiesrXr�rYrrr�make_cookies2sB






zCookieJar.make_cookiesc
CsN|jj�z2ttj��|j_|_|jj||�r:|j|�Wd|jj�XdS)N)	r5rFrArMr2r!r��
set_cookierG)r�r�r�rrr�set_cookie_if_okhs
zCookieJar.set_cookie_if_okc
Csl|j}|jj�zJ|j|kr&i||j<||j}|j|krDi||j<||j}|||j<Wd|jj�XdS)N)r6r5rFr�r�rwrG)r�r��cZc2Zc3rrrr^us






zCookieJar.set_cookiec
Cs|td|j��|jj�zRttj��|j_|_x6|j||�D]&}|jj	||�r>td|�|j
|�q>WWd|jj�XdS)Nzextract_cookies: %sz setting cookie: %s)rrr5rFrArMr2r!r]r�r^rG)r�r\r�r�rrr�extract_cookies�s

zCookieJar.extract_cookiescCst|dk	r2|dks|dkr td��|j|||=n>|dk	rX|dkrJtd��|j||=n|dk	rj|j|=ni|_dS)Nz8domain and path must be given to remove a cookie by namez.domain must be given to remove cookies by path)rLr6)r�r�r�rwrrrrR�s
zCookieJar.clearcCsH|jj�z,x&|D]}|jr|j|j|j|j�qWWd|jj�XdS)N)r5rFr�rRr�r�rwrG)r�r�rrr�clear_session_cookies�s

zCookieJar.clear_session_cookiescCsT|jj�z8tj�}x*|D]"}|j|�r|j|j|j|j�qWWd|jj�XdS)N)	r5rFrMr�rRr�r�rwrG)r�r�r�rrrrH�s



zCookieJar.clear_expired_cookiescCs
t|j�S)N)r-r6)r�rrr�__iter__�szCookieJar.__iter__cCsd}x|D]}|d}q
W|S)Nr	rr)r�r�r�rrr�__len__�s
zCookieJar.__len__cCs6g}x|D]}|jt|��q
Wd|jjdj|�fS)Nz<%s[%s]>z, )rqr�r�r�r{)r��rr�rrrr��s
zCookieJar.__repr__cCs6g}x|D]}|jt|��q
Wd|jjdj|�fS)Nz<%s[%s]>z, )rqrr�r�r{)r�rer�rrrr��s
zCookieJar.__str__)N)NNN)!r�r�r�rs�compilerArBZstrict_domain_reZ	domain_reZdots_re�ASCII�magic_rer�r8r:r<rDrErPrUrVrWr]r_r^rarRrbrHrcrdr�r�rrrrr�s6





;!a\	6


c@seZdZdS)rN)r�r�r�rrrrr�sc@s4eZdZddd�Zddd�Zd
dd�Zdd	d
�ZdS)rNFc	CsJtj||�|dk	r6y|dWntd��YnX||_t|�|_dS)NrVzfilename must be string-like)rr�rL�filenamerQ�	delayload)r�rirjr7rrrr��szFileCookieJar.__init__cCs
t��dS)N)r�)r�ri�ignore_discard�ignore_expiresrrr�save�szFileCookieJar.savecCsJ|dkr"|jdk	r|j}ntt��t|��}|j||||�WdQRXdS)N)rirL�MISSING_FILENAME_TEXT�open�_really_load)r�rirkrlrrrr�load�s

zFileCookieJar.loadcCs�|dkr"|jdk	r|j}ntt��|jj�zFtj|j�}i|_y|j|||�Wnt	k
rn||_�YnXWd|jj
�XdS)N)rirLrnr5rFr��deepcopyr6rq�OSErrorrG)r�rirkrlZ	old_staterrr�reverts

zFileCookieJar.revert)NFN)NFF)NFF)NFF)r�r�r�r�rmrqrtrrrrr�s



	cCs$|j|jfd|jfd|jfg}|jdk	r8|jd|jf�|jrH|jd
�|jrX|jd�|jrh|jd�|j	rx|jd�|j
r�|jdtt|j
��f�|j
r�|jd�|jr�|jd
|jf�|jr�|jd|jf�t|jj��}x$|D]}|j|t|j|�f�q�W|jdt|j�f�t|g�S)Nr�r�r��	path_spec�	port_spec�
domain_dotr�r�r�r�rJr�)ruN)rvN)rwN)r�N)r�N)rwrxr�r�r�rqr�r�r�r�r�r5rZr�r�r�r'r�r(rr�r�)r�r�r(r~rrr�lwp_cookie_strs6







rxc@s(eZdZd
dd�Zddd�Zdd	�ZdS)rTcCs\tj�}g}x>|D]6}|r$|jr$q|r6|j|�r6q|jdt|��qWdj|dg�S)NzSet-Cookie3: %s�
rV)rMr�r�rqrxr{)r�rkrlr�rer�rrr�
as_lwp_strGs
zLWPCookieJar.as_lwp_strNFcCsX|dkr"|jdk	r|j}ntt��t|d��"}|jd�|j|j||��WdQRXdS)N�wz#LWP-Cookies-2.0
)rirLrnro�writerz)r�rirkrlrrrrrmWs

zLWPCookieJar.savecCsL|j�}|jj|�s$d|}t|��tj�}d}d}	d}
�yʐx�|j�}|dkrRP|j|�s^q@|t|�d�j�}�x�t|g�D�]x}|d\}
}i}i}x|	D]}d||<q�Wx�|dd�D]t\}}|dk	r�|j	�}nd}||
k�s�||	k�r�|}||	k�r|dk�rd}|||<q�||
k�r*|||<q�|||<q�W|j
}|d�}|d�}|dk	�r^t|�}|dk�rld}|d�}|jd�}t|d�|
||d	�|d�|||d�|d
�|d�|d�|||d
�|d�|�}|�r�|j
�r�q�|�r�|j|��r�q�|j|�q�Wq@WWnBtk
�r�Yn,tk
�rFt�td||f��YnXdS)Nz5%r does not look like a Set-Cookie3 (LWP) format filezSet-Cookie3:rvrurwr�r�r�r�r�r�r�r�rJrVr	FrTr�z&invalid Set-Cookie3 format file %r: %r)rvrurwr�r�)r�r�r�r�r�r�rJ)�readlinerhr@rrMrrrr�ryrKr�rdrr�r�r^rsrZr)r�rrirkrl�magicrr��headerrMrN�line�datarwrxrOr�r~rr�r�r�r�r�r�r`rrrrpcs�











zLWPCookieJar._really_load)TT)NFF)r�r�r�rzrmrprrrrr:s

c@s,eZdZejd�ZdZdd�Zd	dd�ZdS)
rz#( Netscape)? HTTP Cookie Filezr# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

cCsntj�}|j�}|jj|�s(td|���y�x�|j�}|dkr@P|jd�rV|dd�}|j�jd�s.|j�dkrrq.|jd�\}}	}
}}}
}|dk}|	dk}	|
dkr�|}
d}|jd	�}d
}|dkr�d}d}t	d|
|dd
||	||
d
|||ddi�}|�r|j
�rq.|�r|j|��rq.|j|�q.WWnBt
k
�r>�Yn,tk
�rht�td
||f��YnXdS)Nz4%r does not look like a Netscape format cookies filerVryr�#r��	�TRUEr�FTr	z+invalid Netscape format cookies file %r: %rr�)r�r�)rMr}rhr@rr�r�rrr�rr�r�r^rsrZr)r�rrirkrlr�r~r�r�r�r�r�r�rwrxr�r�r`rrrrp�s`

zMozillaCookieJar._really_loadNFcCs|dkr"|jdk	r|j}ntt��t|d���}|j|j�tj�}x�|D]�}|rZ|jrZqH|rl|j|�rlqH|j	rxd}nd}|j
jd�r�d}nd}|jdk	r�t
|j�}	nd}	|jdkr�d}
|j}n|j}
|j}|jdj|j
||j||	|
|g�d�qHWWdQRXdS)Nr{r�ZFALSEr�rVr�ry)rirLrnror|rrMr�r�r�r�rrr�rrxrwr{r�)r�rirkrlrr�r�r�r�r�rwrxrrrrms<



zMozillaCookieJar.save)NFF)	r�r�r�rsrfrhrrprmrrrrr�s
A)N)N)X�__all__r�r-rsrMZurllib.parser�Zurllib.requestZ	threadingr3�ImportErrorZdummy_threadingZhttp.clientZhttpZcalendarr
rrrrZclientZ	HTTP_PORTr�rnrr%r,r6r7rIr(rqrKr5r8r>rfrgr?rFrSrX�Ir\�Xr^rarbrdrjrlrmrornryrzr�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�r�rrrr*r-r1rrsrrrxrrrrrr�<module>s�



88!



U
D'


#b!\:x__pycache__/server.cpython-36.opt-2.pyc000064400000047615150532432170013667 0ustar003

Ow�h���@s�dZddddgZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlZddlZddlZddlmZdZd	ZGd
d�dej�ZGdd�dej�ZGdd�de�Zd
d�Zdadd�Zdd�Z Gdd�de�Z!eedddfdd�Z"e#dk�r�ej$�Z%e%j&dddd�e%j&dddd d!d"�e%j&d#d$de'd%d&d'�e%j(�Z)e)j*�rze!Z+neZ+e"e+e)j,e)j-d(�dS))z0.6�
HTTPServer�BaseHTTPRequestHandler�SimpleHTTPRequestHandler�CGIHTTPRequestHandler�N)�
HTTPStatusa�<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: %(code)d</p>
        <p>Message: %(message)s.</p>
        <p>Error code explanation: %(code)s - %(explain)s.</p>
    </body>
</html>
ztext/html;charset=utf-8c@seZdZdZdd�ZdS)r�cCs4tjj|�|jdd�\}}tj|�|_||_dS)N�)�socketserver�	TCPServer�server_bind�server_address�socketZgetfqdn�server_name�server_port)�self�host�port�r�#/usr/lib64/python3.6/http/server.pyr�szHTTPServer.server_bindN)�__name__�
__module__�__qualname__Zallow_reuse_addressrrrrrr�sc
@seZdZdejj�dZdeZe	Z
eZdZ
dd�Zdd�Zd	d
�Zdd�Zd?dd�Zd@dd�ZdAdd�Zdd�Zdd�Zdd�ZdBdd�Zdd�Zdd �Zd!d"�ZdCd#d$�Zd%d&�Zd'd(d)d*d+d,d-gZd
d.d/d0d1d2d3d4d5d6d7d8d9g
Zd:d;�Z d<Z!e"j#j$Z%d=d>�e&j'j(�D�Z)d
S)DrzPython/rz	BaseHTTP/zHTTP/0.9cCs�d|_|j|_}d|_t|jd�}|jd�}||_|j�}t	|�dk�r|\}}}yZ|dd�dkrjt
�|jdd�d}|jd	�}t	|�d
kr�t
�t|d�t|d�f}Wn*t
tfk
r�|j
tjd|�d
SX|dkr�|jdkr�d
|_|dk�rr|j
tjd|�d
Sn^t	|�d
k�rR|\}}d|_|dk�rr|j
tjd|�d
Sn |�s\d
S|j
tjd|�d
S||||_|_|_|jjd��r�d|jjd�|_ytjj|j|jd�|_Wnrtjjk
�r�}z|j
tjdt|��d
Sd}~Xn:tjjk
�r4}z|j
tjdt|��d
Sd}~XnX|jjdd�}	|	j�dk�rZd|_n |	j�dk�rz|jdk�rzd
|_|jjdd�}
|
j�dk�r�|jdk�r�|jdk�r�|j ��s�d
SdS)NTz
iso-8859-1z
��zHTTP/�/r�.rrzBad request version (%r)FzHTTP/1.1zInvalid HTTP version (%s)ZGETzBad HTTP/0.9 request type (%r)zBad request syntax (%r)z//)Z_classz
Line too longzToo many headers�
Connection��closez
keep-aliveZExpectz100-continue)rr)rr)!�command�default_request_version�request_version�close_connection�str�raw_requestline�rstrip�requestline�split�len�
ValueError�int�
IndexError�
send_errorrZBAD_REQUEST�protocol_versionZHTTP_VERSION_NOT_SUPPORTED�path�
startswith�lstrip�http�clientZ
parse_headers�rfile�MessageClass�headersZLineTooLongZREQUEST_HEADER_FIELDS_TOO_LARGEZ
HTTPException�get�lower�handle_expect_100)r�versionr&�wordsrr.Zbase_version_numberZversion_number�errZconntypeZexpectrrr�
parse_requests�












z$BaseHTTPRequestHandler.parse_requestcCs|jtj�|j�dS)NT)�send_response_onlyrZCONTINUE�end_headers)rrrrr8nsz(BaseHTTPRequestHandler.handle_expect_100cCs�y�|jjd�|_t|j�dkr@d|_d|_d|_|jtj	�dS|jsPd|_
dS|j�s\dSd|j}t||�s�|jtj
d|j�dSt||�}|�|jj�Wn4tjk
r�}z|jd|�d|_
dSd}~XnXdS)NiirTZdo_zUnsupported method (%r)zRequest timed out: %r)r3�readliner$r(r&r!rr,rZREQUEST_URI_TOO_LONGr"r<�hasattr�NOT_IMPLEMENTED�getattr�wfile�flushr
Ztimeout�	log_error)rZmname�method�errr�handle_one_request�s4


z)BaseHTTPRequestHandler.handle_one_requestcCs&d|_|j�x|js |j�qWdS)NT)r"rH)rrrr�handle�szBaseHTTPRequestHandler.handleNcCs
y|j|\}}Wntk
r.d\}}YnX|dkr<|}|dkrH|}|jd||�|j||�|jdd�d}|dkr�|tjtjtjfkr�|j	|t
j|dd�t
j|dd�d�}|jd	d
�}|jd|j
�|jdtt|���|j�|jd
ko�|�r|jj|�dS)N�???zcode %d, message %srr��F)�quote)�code�message�explainzUTF-8�replacezContent-TypezContent-LengthZHEAD)rJrJ)�	responses�KeyErrorrE�
send_response�send_headerrZ
NO_CONTENTZ
RESET_CONTENTZNOT_MODIFIED�error_message_format�html�escape�encode�error_content_typer#r(r>rrC�write)rrMrNrOZshortmsgZlongmsgZbodyZcontentrrrr,�s4
z!BaseHTTPRequestHandler.send_errorcCs:|j|�|j||�|jd|j��|jd|j��dS)NZServerZDate)�log_requestr=rT�version_string�date_time_string)rrMrNrrrrS�s
z$BaseHTTPRequestHandler.send_responsecCsd|jdkr`|dkr0||jkr,|j|d}nd}t|d�s@g|_|jjd|j||fjdd��dS)NzHTTP/0.9rr�_headers_bufferz
%s %d %s
zlatin-1�strict)r!rQr@r^�appendr-rX)rrMrNrrrr=�s


z)BaseHTTPRequestHandler.send_response_onlycCsl|jdkr6t|d�sg|_|jjd||fjdd��|j�dkrh|j�dkrVd|_n|j�d	krhd
|_dS)NzHTTP/0.9r^z%s: %s
zlatin-1r_Z
connectionrTz
keep-aliveF)r!r@r^r`rXr7r")r�keyword�valuerrrrT�s

z"BaseHTTPRequestHandler.send_headercCs"|jdkr|jjd�|j�dS)NzHTTP/0.9s
)r!r^r`�
flush_headers)rrrrr>s
z"BaseHTTPRequestHandler.end_headerscCs(t|d�r$|jjdj|j��g|_dS)Nr^�)r@rCrZ�joinr^)rrrrrcs
z$BaseHTTPRequestHandler.flush_headers�-cCs.t|t�r|j}|jd|jt|�t|��dS)Nz
"%s" %s %s)�
isinstancerrb�log_messager&r#)rrM�sizerrrr[s
z"BaseHTTPRequestHandler.log_requestcGs|j|f|��dS)N)rh)r�format�argsrrrrE!sz BaseHTTPRequestHandler.log_errorcGs&tjjd|j�|j�||f�dS)Nz%s - - [%s] %s
)�sys�stderrrZ�address_string�log_date_time_string)rrjrkrrrrh/sz"BaseHTTPRequestHandler.log_messagecCs|jd|jS)N� )�server_version�sys_version)rrrrr\Esz%BaseHTTPRequestHandler.version_stringcCs |dkrtj�}tjj|dd�S)NT)Zusegmt)�time�emailZutilsZ
formatdate)rZ	timestamprrrr]Isz'BaseHTTPRequestHandler.date_time_stringc	CsBtj�}tj|�\	}}}}}}}}	}
d||j|||||f}|S)Nz%02d/%3s/%04d %02d:%02d:%02d)rsZ	localtime�	monthname)rZnowZyearZmonthZdayZhhZmmZss�x�y�z�srrrroOs
z+BaseHTTPRequestHandler.log_date_time_stringZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs
|jdS)Nr)�client_address)rrrrrn]sz%BaseHTTPRequestHandler.address_stringzHTTP/1.0cCsi|]}|j|jf|�qSr)�phraseZdescription)�.0�vrrr�
<dictcomp>lsz!BaseHTTPRequestHandler.<dictcomp>)NN)N)N)rfrf)N)*rrrrlr9r'rr�__version__rq�DEFAULT_ERROR_MESSAGErU�DEFAULT_ERROR_CONTENT_TYPErYr r<r8rHrIr,rSr=rTr>rcr[rErhr\r]roZweekdaynamerurnr-r1r2ZHTTPMessager4r�__members__�valuesrQrrrrr�s<ig%
5



	c@sxeZdZdeZdd�Zdd�Zdd�Zdd	�Zd
d�Z	dd
�Z
dd�Zej
sVej�ejj�Zejddddd��dS)rzSimpleHTTP/c
Cs.|j�}|r*z|j||j�Wd|j�XdS)N)�	send_head�copyfilerCr)r�frrr�do_GET�s
zSimpleHTTPRequestHandler.do_GETcCs|j�}|r|j�dS)N)r�r)rr�rrr�do_HEAD�sz SimpleHTTPRequestHandler.do_HEADc	Csx|j|j�}d}tjj|�r�tjj|j�}|jjd�s�|jt	j
�|d|d|dd|d|df}tjj|�}|jd|�|j
�dSx6dD]$}tjj||�}tjj|�r�|}Pq�W|j|�S|j|�}yt|d
�}Wn$tk
�r|jt	jd�dSXyZ|jt	j�|jd|�tj|j��}|jd
t|d��|jd|j|j��|j
�|S|j��YnXdS)Nrrrrr�ZLocation�
index.html�	index.htm�rbzFile not foundzContent-typezContent-Length�z
Last-Modified)r�r�)�translate_pathr.�os�isdir�urllib�parseZurlsplit�endswithrSrZMOVED_PERMANENTLYZ
urlunsplitrTr>re�exists�list_directory�
guess_type�open�OSErrorr,�	NOT_FOUND�OK�fstat�filenor#r]�st_mtimer)	rr.r��partsZ	new_partsZnew_url�indexZctypeZfsrrrr��sF


z"SimpleHTTPRequestHandler.send_headc
Cs�ytj|�}Wn"tk
r0|jtjd�dSX|jdd�d�g}ytjj	|j
dd�}Wn tk
r|tjj	|�}YnXtj
|dd�}tj�}d	|}|jd
�|jd�|jd|�|jd
|�|jd|�|jd�x~|D]v}tj
j||�}|}	}
tj
j|��r"|d}	|d}
tj
j|��r8|d}	|jdtjj|
dd�tj
|	dd�f�q�W|jd�dj|�j|d�}tj�}|j|�|jd�|jtj�|jdd|�|jdtt|���|j�|S)NzNo permission to list directorycSs|j�S)N)r7)�arrr�<lambda>�sz9SimpleHTTPRequestHandler.list_directory.<locals>.<lambda>)�key�
surrogatepass)�errorsF)rLzDirectory listing for %szZ<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">z
<html>
<head>z@<meta http-equiv="Content-Type" content="text/html; charset=%s">z<title>%s</title>
</head>z<body>
<h1>%s</h1>z	<hr>
<ul>r�@z<li><a href="%s">%s</a></li>z</ul>
<hr>
</body>
</html>
�
�surrogateescaperzContent-typeztext/html; charset=%szContent-Length) r��listdirr�r,rr��sortr�r��unquoter.�UnicodeDecodeErrorrVrWrl�getfilesystemencodingr`rer��islinkrLrX�io�BytesIOrZ�seekrSr�rTr#r(r>)
rr.�list�rZdisplaypath�enc�title�name�fullnameZdisplaynameZlinknameZencodedr�rrrr��s\







z'SimpleHTTPRequestHandler.list_directorycCs�|jdd�d}|jdd�d}|j�jd�}ytjj|dd�}Wn tk
rbtjj|�}YnXtj|�}|jd�}t	d|�}t
j�}x8|D]0}t
jj
|�s�|t
jt
jfkr�q�t
jj||�}q�W|r�|d7}|S)N�?rr�#rr�)r�)r'r%r�r�r�r�r��	posixpath�normpath�filterr��getcwdr.�dirname�curdir�pardirre)rr.Ztrailing_slashr:Zwordrrrr��s$	



z'SimpleHTTPRequestHandler.translate_pathcCstj||�dS)N)�shutilZcopyfileobj)r�sourceZ
outputfilerrrr�sz!SimpleHTTPRequestHandler.copyfilecCsLtj|�\}}||jkr"|j|S|j�}||jkr>|j|S|jdSdS)Nr)r��splitext�extensions_mapr7)rr.�baseZextrrrr�)s



z#SimpleHTTPRequestHandler.guess_typezapplication/octet-streamz
text/plain)rz.pyz.cz.hN)rrrrrqr�r�r�r�r�r�r��	mimetypesZinitedZinitZ	types_map�copyr��updaterrrrrrs 
	1:
c	Cs�|jd�\}}}tjj|�}|jd�}g}x<|dd�D],}|dkrN|j�q8|r8|dkr8|j|�q8W|r�|j�}|r�|dkr�|j�d}q�|dkr�d}nd}|r�dj||f�}ddj|�|f}dj|�}|S)Nr�rrz..rr���)�	partitionr�r�r�r'�popr`re)	r.�_�query�
path_partsZ
head_parts�partZ	tail_partZ	splitpath�collapsed_pathrrr�_url_collapse_pathNs.


r�cCsptrtSyddl}Wntk
r(dSXy|jd�daWn.tk
rjdtdd�|j�D��aYnXtS)Nrr�nobodyrcss|]}|dVqdS)rNr)r|rvrrr�	<genexpr>�sznobody_uid.<locals>.<genexpr>r�)r��pwd�ImportError�getpwnamrR�maxZgetpwall)r�rrr�
nobody_uid�s r�cCstj|tj�S)N)r��access�X_OK)r.rrr�
executable�sr�c@sReZdZeed�ZdZdd�Zdd�Zdd�Z	d	d
gZ
dd�Zd
d�Zdd�Z
dS)r�forkrcCs$|j�r|j�n|jtjd�dS)NzCan only POST to CGI scripts)�is_cgi�run_cgir,rrA)rrrr�do_POST�s

zCGIHTTPRequestHandler.do_POSTcCs|j�r|j�Stj|�SdS)N)r�r�rr�)rrrrr��szCGIHTTPRequestHandler.send_headcCsPt|j�}|jdd�}|d|�||dd�}}||jkrL||f|_dSdS)NrrTF)r�r.�find�cgi_directories�cgi_info)rr�Zdir_sep�head�tailrrrr��s


zCGIHTTPRequestHandler.is_cgiz/cgi-binz/htbincCst|�S)N)r�)rr.rrr�
is_executable�sz#CGIHTTPRequestHandler.is_executablecCstjj|�\}}|j�dkS)N�.py�.pyw)r�r�)r�r.r�r7)rr.r�r�rrr�	is_python�szCGIHTTPRequestHandler.is_pythonc)Cs�|j\}}|d|}|jdt|�d�}x`|dkr�|d|�}||dd�}|j|�}tjj|�r�||}}|jdt|�d�}q,Pq,W|jd�\}}}	|jd�}|dkr�|d|�||d�}
}n
|d}
}|d|
}|j|�}tjj|��s|j	t
jd|�dStjj|��s2|j	t
j
d|�dS|j|�}
|j�sL|
�rn|j|��sn|j	t
j
d|�dStjtj�}|j�|d	<|jj|d
<d|d<|j|d
<t|jj�|d<|j|d<tjj|�}||d<|j|�|d<||d<|	�r�|	|d<|jd|d<|jj d�}|�r�|j!�}t|�dk�r�ddl"}ddl#}|d|d<|dj$�dk�r�y"|dj%d�}|j&|�j'd�}Wn|j(t)fk
�r�Yn&X|j!d�}t|�dk�r�|d|d<|jj d�dk�r�|jj*�|d<n|jd|d<|jj d�}|�r||d<|jj d �}|�r"||d!<g}xN|jj+d"�D]>}|dd�d#k�rZ|j,|j-��n||d$d�j!d%�}�q4Wd%j.|�|d&<|jj d'�}|�r�||d(<t/d|jj0d)g��}d*j.|�}|�r�||d+<xd<D]}|j1|d��q�W|j2t
j3d-�|j4�|	j5d.d/�}|j�r.|
g}d0|k�r*|j,|�t6�}|j7j8�tj9�}|dk�r�tj:|d�\}}x0t;j;|j<gggd�d�r�|j<j=d��s^P�q^W|�r�|j>d1|�dSy\ytj?|�Wnt@k
�r�YnXtjA|j<jB�d�tjA|j7jB�d�tjC|||�Wn(|jjD|jE|j�tjFd2�YnX�n�ddlG} |g}!|j|��r�tHjI}"|"j$�jJd3��rv|"dd=�|"d>d�}"|"d6g|!}!d0|	k�r�|!j,|	�|jKd7| jL|!��ytM|�}#WntNtOfk
�r�d}#YnX| jP|!| jQ| jQ| jQ|d8�}$|jj$�d9k�r|#dk�r|j<j=|#�}%nd}%x4t;j;|j<jRgggd�d�rN|j<jRjSd��sP�qW|$jT|%�\}&}'|j7jU|&�|'�r||j>d:|'�|$jVjW�|$jXjW�|$jY}(|(�r�|j>d1|(�n
|jKd;�dS)?Nrrrr�rzNo such CGI script (%r)z#CGI script is not a plain file (%r)z!CGI script is not executable (%r)ZSERVER_SOFTWAREZSERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZSERVER_PROTOCOLZSERVER_PORTZREQUEST_METHODZ	PATH_INFOZPATH_TRANSLATEDZSCRIPT_NAME�QUERY_STRINGZREMOTE_ADDR�
authorizationrZ	AUTH_TYPEZbasic�ascii�:ZREMOTE_USERzcontent-typeZCONTENT_TYPEzcontent-length�CONTENT_LENGTH�referer�HTTP_REFERER�acceptz	

 ��,ZHTTP_ACCEPTz
user-agent�HTTP_USER_AGENTZcookiez, �HTTP_COOKIE�REMOTE_HOSTzScript output follows�+rp�=zCGI script exit status %#x�zw.exerr�z-uzcommand: %s)�stdin�stdoutrm�envZpostz%szCGI script exited OK)r�r�r�r�r�r�������)Zr�r�r(r�r�r.r�r�r�r,rr��isfileZ	FORBIDDENr��	have_forkr�r��deepcopy�environr\Zserverrr-r#rrr�r�r�rzr5r6r'�base64�binasciir7rXZdecodebytes�decode�Error�UnicodeErrorZget_content_typeZgetallmatchingheadersr`�striprer�Zget_all�
setdefaultrSr�rcrPr�rCrDr��waitpid�selectr3�readrE�setuidr��dup2r��execveZhandle_errorZrequest�_exit�
subprocessrlr�r�rhZlist2cmdliner*�	TypeErrorr)�Popen�PIPEZ_sockZrecvZcommunicaterZrmrr��
returncode))r�dir�restr.�iZnextdirZnextrestZ	scriptdirr�r�ZscriptZ
scriptnameZ
scriptfileZispyr�Zuqrestr�rrZlengthr�r��lineZua�coZ
cookie_str�kZ
decoded_queryrkr��pid�stsrZcmdlineZinterp�nbytes�p�datar�rmZstatusrrrr��s4

























zCGIHTTPRequestHandler.run_cgiN)rrrr@r�r�Zrbufsizer�r�r�r�r�r�r�rrrrr�s
zHTTP/1.0i@rc	Cs�||f}||_|||��b}|jj�}d}t|j|d|dd��y|j�Wn&tk
rttd�tjd�YnXWdQRXdS)Nz>Serving HTTP on {host} port {port} (http://{host}:{port}/) ...rr)rrz&
Keyboard interrupt received, exiting.)	r-r
Zgetsockname�printrjZ
serve_forever�KeyboardInterruptrl�exit)	�HandlerClassZServerClassZprotocolr�bindrZhttpdZsaZ
serve_messagerrr�test�s
r$�__main__z--cgi�
store_truezRun as CGI Server)�action�helpz--bindz-bZADDRESSz8Specify alternate bind address [default: all interfaces])�default�metavarr(rZstorer�z&Specify alternate port [default: 8000])r'r)�type�nargsr()r"rr#).r�__all__Zemail.utilsrtrVZhttp.clientr1r�r�r�r�r	r�r
r	rlrsZurllib.parser�r��argparserr�r�r
rZStreamRequestHandlerrrr�r�r�r�rr$r�ArgumentParser�parser�add_argumentr*�
parse_argsrkZcgiZ
handler_classrr#rrrr�<module>Sshg]0
__pycache__/server.cpython-36.opt-1.pyc000064400000077030150532432170013660 0ustar003

Ow�h���@s�dZdZddddgZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddl
Z
ddlZddlZddlZddlZddlZddlZddlZddlmZd	Zd
ZGdd�dej�ZGdd�dej�ZGd
d�de�Zdd�Zdadd�Z dd�Z!Gdd�de�Z"eedddfdd�Z#e$dk�r�ej%�Z&e&j'dddd�e&j'dd dd!d"d#�e&j'd$d%de(d&d'd(�e&j)�Z*e*j+�r~e"Z,neZ,e#e,e*j-e*j.d)�dS)*a@HTTP server classes.

Note: BaseHTTPRequestHandler doesn't implement any HTTP request; see
SimpleHTTPRequestHandler for simple implementations of GET, HEAD and POST,
and CGIHTTPRequestHandler for CGI scripts.

It does, however, optionally implement HTTP/1.1 persistent connections,
as of version 0.3.

Notes on CGIHTTPRequestHandler
------------------------------

This class implements GET and POST requests to cgi-bin scripts.

If the os.fork() function is not present (e.g. on Windows),
subprocess.Popen() is used as a fallback, with slightly altered semantics.

In all cases, the implementation is intentionally naive -- all
requests are executed synchronously.

SECURITY WARNING: DON'T USE THIS CODE UNLESS YOU ARE INSIDE A FIREWALL
-- it may execute arbitrary Python code or external programs.

Note that status code 200 is sent prior to execution of a CGI script, so
scripts cannot send other status codes such as 302 (redirect).

XXX To do:

- log requests even later (to capture byte count)
- log user-agent header and other interesting goodies
- send error log to separate file
z0.6�
HTTPServer�BaseHTTPRequestHandler�SimpleHTTPRequestHandler�CGIHTTPRequestHandler�N)�
HTTPStatusa�<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
        <title>Error response</title>
    </head>
    <body>
        <h1>Error response</h1>
        <p>Error code: %(code)d</p>
        <p>Message: %(message)s.</p>
        <p>Error code explanation: %(code)s - %(explain)s.</p>
    </body>
</html>
ztext/html;charset=utf-8c@seZdZdZdd�ZdS)r�cCs4tjj|�|jdd�\}}tj|�|_||_dS)z.Override server_bind to store the server name.N�)�socketserver�	TCPServer�server_bind�server_address�socketZgetfqdn�server_name�server_port)�self�host�port�r�#/usr/lib64/python3.6/http/server.pyr�szHTTPServer.server_bindN)�__name__�
__module__�__qualname__Zallow_reuse_addressrrrrrr�sc
@seZdZdZdejj�dZdeZ	e
ZeZ
dZdd�Zdd	�Zd
d�Zdd
�Zd@dd�ZdAdd�ZdBdd�Zdd�Zdd�Zdd�ZdCdd�Zdd�Zd d!�Zd"d#�ZdDd$d%�Zd&d'�Zd(d)d*d+d,d-d.gZdd/d0d1d2d3d4d5d6d7d8d9d:g
Z d;d<�Z!d=Z"e#j$j%Z&d>d?�e'j(j)�D�Z*dS)Era�HTTP request handler base class.

    The following explanation of HTTP serves to guide you through the
    code as well as to expose any misunderstandings I may have about
    HTTP (so you don't need to read the code to figure out I'm wrong
    :-).

    HTTP (HyperText Transfer Protocol) is an extensible protocol on
    top of a reliable stream transport (e.g. TCP/IP).  The protocol
    recognizes three parts to a request:

    1. One line identifying the request type and path
    2. An optional set of RFC-822-style headers
    3. An optional data part

    The headers and data are separated by a blank line.

    The first line of the request has the form

    <command> <path> <version>

    where <command> is a (case-sensitive) keyword such as GET or POST,
    <path> is a string containing path information for the request,
    and <version> should be the string "HTTP/1.0" or "HTTP/1.1".
    <path> is encoded using the URL encoding scheme (using %xx to signify
    the ASCII character with hex code xx).

    The specification specifies that lines are separated by CRLF but
    for compatibility with the widest range of clients recommends
    servers also handle LF.  Similarly, whitespace in the request line
    is treated sensibly (allowing multiple spaces between components
    and allowing trailing whitespace).

    Similarly, for output, lines ought to be separated by CRLF pairs
    but most clients grok LF characters just fine.

    If the first line of the request has the form

    <command> <path>

    (i.e. <version> is left out) then this is assumed to be an HTTP
    0.9 request; this form has no optional headers and data part and
    the reply consists of just the data.

    The reply form of the HTTP 1.x protocol again has three parts:

    1. One line giving the response code
    2. An optional set of RFC-822-style headers
    3. The data

    Again, the headers and data are separated by a blank line.

    The response code line has the form

    <version> <responsecode> <responsestring>

    where <version> is the protocol version ("HTTP/1.0" or "HTTP/1.1"),
    <responsecode> is a 3-digit response code indicating success or
    failure of the request, and <responsestring> is an optional
    human-readable string explaining what the response code means.

    This server parses the request and the headers, and then calls a
    function specific to the request type (<command>).  Specifically,
    a request SPAM will be handled by a method do_SPAM().  If no
    such method exists the server sends an error response to the
    client.  If it exists, it is called with no arguments:

    do_SPAM()

    Note that the request name is case sensitive (i.e. SPAM and spam
    are different requests).

    The various request details are stored in instance variables:

    - client_address is the client IP address in the form (host,
    port);

    - command, path and version are the broken-down request line;

    - headers is an instance of email.message.Message (or a derived
    class) containing the header information;

    - rfile is a file object open for reading positioned at the
    start of the optional input data part;

    - wfile is a file object open for writing.

    IT IS IMPORTANT TO ADHERE TO THE PROTOCOL FOR WRITING!

    The first thing to be written must be the response line.  Then
    follow 0 or more header lines, then a blank line, and then the
    actual data (if any).  The meaning of the header lines depends on
    the command executed by the server; in most cases, when data is
    returned, there should be at least one header line of the form

    Content-type: <type>/<subtype>

    where <type> and <subtype> should be registered MIME types,
    e.g. "text/html" or "text/plain".

    zPython/rz	BaseHTTP/zHTTP/0.9cCs�d|_|j|_}d|_t|jd�}|jd�}||_|j�}t	|�dk�r|\}}}yZ|dd�dkrjt
�|jdd	�d	}|jd
�}t	|�dkr�t
�t|d�t|d	�f}Wn*t
tfk
r�|j
tjd
|�dSX|dkr�|jdkr�d|_|dk�rr|j
tjd|�dSn^t	|�dk�rR|\}}d|_|dk�rr|j
tjd|�dSn |�s\dS|j
tjd|�dS||||_|_|_|jjd��r�d|jjd�|_ytjj|j|jd�|_Wnrtjjk
�r�}z|j
tjdt|��dSd}~Xn:tjjk
�r4}z|j
tjdt|��dSd}~XnX|jjdd�}	|	j�dk�rZd|_n |	j�dk�rz|jdk�rzd|_|jjdd�}
|
j�dk�r�|jdk�r�|jdk�r�|j ��s�dSdS) a'Parse a request (internal).

        The request should be stored in self.raw_requestline; the results
        are in self.command, self.path, self.request_version and
        self.headers.

        Return True for success, False for failure; on failure, an
        error is sent back.

        NTz
iso-8859-1z
��zHTTP/�/r�.rrzBad request version (%r)FzHTTP/1.1zInvalid HTTP version (%s)ZGETzBad HTTP/0.9 request type (%r)zBad request syntax (%r)z//)Z_classz
Line too longzToo many headers�
Connection��closez
keep-aliveZExpectz100-continue)rr)rr)!�command�default_request_version�request_version�close_connection�str�raw_requestline�rstrip�requestline�split�len�
ValueError�int�
IndexError�
send_errorrZBAD_REQUEST�protocol_versionZHTTP_VERSION_NOT_SUPPORTED�path�
startswith�lstrip�http�clientZ
parse_headers�rfile�MessageClass�headersZLineTooLongZREQUEST_HEADER_FIELDS_TOO_LARGEZ
HTTPException�get�lower�handle_expect_100)r�versionr&�wordsrr.Zbase_version_numberZversion_number�errZconntypeZexpectrrr�
parse_requests�












z$BaseHTTPRequestHandler.parse_requestcCs|jtj�|j�dS)a7Decide what to do with an "Expect: 100-continue" header.

        If the client is expecting a 100 Continue response, we must
        respond with either a 100 Continue or a final response before
        waiting for the request body. The default is to always respond
        with a 100 Continue. You can behave differently (for example,
        reject unauthorized requests) by overriding this method.

        This method should either return True (possibly after sending
        a 100 Continue response) or send an error response and return
        False.

        T)�send_response_onlyrZCONTINUE�end_headers)rrrrr8nsz(BaseHTTPRequestHandler.handle_expect_100cCs�y�|jjd�|_t|j�dkr@d|_d|_d|_|jtj	�dS|jsPd|_
dS|j�s\dSd|j}t||�s�|jtj
d|j�dSt||�}|�|jj�Wn4tjk
r�}z|jd|�d|_
dSd}~XnXdS)	z�Handle a single HTTP request.

        You normally don't need to override this method; see the class
        __doc__ string for information on how to handle specific HTTP
        commands such as GET and POST.

        iirNTZdo_zUnsupported method (%r)zRequest timed out: %r)r3�readliner$r(r&r!rr,rZREQUEST_URI_TOO_LONGr"r<�hasattr�NOT_IMPLEMENTED�getattr�wfile�flushr
Ztimeout�	log_error)rZmname�method�errr�handle_one_request�s4


z)BaseHTTPRequestHandler.handle_one_requestcCs&d|_|j�x|js |j�qWdS)z&Handle multiple requests if necessary.TN)r"rH)rrrr�handle�szBaseHTTPRequestHandler.handleNcCs
y|j|\}}Wntk
r.d\}}YnX|dkr<|}|dkrH|}|jd||�|j||�|jdd�d}|dkr�|tjtjtjfkr�|j	|t
j|dd�t
j|dd�d	�}|jd
d�}|jd|j
�|jd
tt|���|j�|jdko�|�r|jj|�dS)akSend and log an error reply.

        Arguments are
        * code:    an HTTP error code
                   3 digits
        * message: a simple optional 1 line reason phrase.
                   *( HTAB / SP / VCHAR / %x80-FF )
                   defaults to short entry matching the response code
        * explain: a detailed message defaults to the long entry
                   matching the response code.

        This sends an error response (so it must be called before any
        output has been generated), logs the error, and finally sends
        a piece of HTML explaining the error to the user.

        �???Nzcode %d, message %srr��F)�quote)�code�message�explainzUTF-8�replacezContent-TypezContent-LengthZHEAD)rJrJ)�	responses�KeyErrorrE�
send_response�send_headerrZ
NO_CONTENTZ
RESET_CONTENTZNOT_MODIFIED�error_message_format�html�escape�encode�error_content_typer#r(r>rrC�write)rrMrNrOZshortmsgZlongmsgZbodyZcontentrrrr,�s4
z!BaseHTTPRequestHandler.send_errorcCs:|j|�|j||�|jd|j��|jd|j��dS)z�Add the response header to the headers buffer and log the
        response code.

        Also send two standard headers with the server software
        version and the current date.

        ZServerZDateN)�log_requestr=rT�version_string�date_time_string)rrMrNrrrrS�s
z$BaseHTTPRequestHandler.send_responsecCsd|jdkr`|dkr0||jkr,|j|d}nd}t|d�s@g|_|jjd|j||fjdd��dS)	zSend the response header only.zHTTP/0.9Nrr�_headers_bufferz
%s %d %s
zlatin-1�strict)r!rQr@r^�appendr-rX)rrMrNrrrr=�s


z)BaseHTTPRequestHandler.send_response_onlycCsl|jdkr6t|d�sg|_|jjd||fjdd��|j�dkrh|j�dkrVd|_n|j�d	krhd
|_dS)z)Send a MIME header to the headers buffer.zHTTP/0.9r^z%s: %s
zlatin-1r_Z
connectionrTz
keep-aliveFN)r!r@r^r`rXr7r")r�keyword�valuerrrrT�s

z"BaseHTTPRequestHandler.send_headercCs"|jdkr|jjd�|j�dS)z,Send the blank line ending the MIME headers.zHTTP/0.9s
N)r!r^r`�
flush_headers)rrrrr>s
z"BaseHTTPRequestHandler.end_headerscCs(t|d�r$|jjdj|j��g|_dS)Nr^�)r@rCrZ�joinr^)rrrrrcs
z$BaseHTTPRequestHandler.flush_headers�-cCs.t|t�r|j}|jd|jt|�t|��dS)zNLog an accepted request.

        This is called by send_response().

        z
"%s" %s %sN)�
isinstancerrb�log_messager&r#)rrM�sizerrrr[s
z"BaseHTTPRequestHandler.log_requestcGs|j|f|��dS)z�Log an error.

        This is called when a request cannot be fulfilled.  By
        default it passes the message on to log_message().

        Arguments are the same as for log_message().

        XXX This should go to the separate error log.

        N)rh)r�format�argsrrrrE!sz BaseHTTPRequestHandler.log_errorcGs&tjjd|j�|j�||f�dS)a�Log an arbitrary message.

        This is used by all other logging functions.  Override
        it if you have specific logging wishes.

        The first argument, FORMAT, is a format string for the
        message to be logged.  If the format string contains
        any % escapes requiring parameters, they should be
        specified as subsequent arguments (it's just like
        printf!).

        The client ip and current date/time are prefixed to
        every message.

        z%s - - [%s] %s
N)�sys�stderrrZ�address_string�log_date_time_string)rrjrkrrrrh/sz"BaseHTTPRequestHandler.log_messagecCs|jd|jS)z*Return the server software version string.� )�server_version�sys_version)rrrrr\Esz%BaseHTTPRequestHandler.version_stringcCs |dkrtj�}tjj|dd�S)z@Return the current date and time formatted for a message header.NT)Zusegmt)�time�emailZutilsZ
formatdate)rZ	timestamprrrr]Isz'BaseHTTPRequestHandler.date_time_stringc	CsBtj�}tj|�\	}}}}}}}}	}
d||j|||||f}|S)z.Return the current time formatted for logging.z%02d/%3s/%04d %02d:%02d:%02d)rsZ	localtime�	monthname)rZnowZyearZmonthZdayZhhZmmZss�x�y�z�srrrroOs
z+BaseHTTPRequestHandler.log_date_time_stringZMonZTueZWedZThuZFriZSatZSunZJanZFebZMarZAprZMayZJunZJulZAugZSepZOctZNovZDeccCs
|jdS)zReturn the client address.r)�client_address)rrrrrn]sz%BaseHTTPRequestHandler.address_stringzHTTP/1.0cCsi|]}|j|jf|�qSr)�phraseZdescription)�.0�vrrr�
<dictcomp>lsz!BaseHTTPRequestHandler.<dictcomp>)NN)N)N)rfrf)N)+rrr�__doc__rlr9r'rr�__version__rq�DEFAULT_ERROR_MESSAGErU�DEFAULT_ERROR_CONTENT_TYPErYr r<r8rHrIr,rSr=rTr>rcr[rErhr\r]roZweekdaynamerurnr-r1r2ZHTTPMessager4r�__members__�valuesrQrrrrr�s>fg%
5



	c@s|eZdZdZdeZdd�Zdd�Zdd�Zd	d
�Z	dd�Z
d
d�Zdd�Ze
jsZe
j�e
jj�Zejddddd��dS)raWSimple HTTP request handler with GET and HEAD commands.

    This serves files from the current directory and any of its
    subdirectories.  The MIME type for files is determined by
    calling the .guess_type() method.

    The GET and HEAD requests are identical except that the HEAD
    request omits the actual contents of the file.

    zSimpleHTTP/c
Cs.|j�}|r*z|j||j�Wd|j�XdS)zServe a GET request.N)�	send_head�copyfilerCr)r�frrr�do_GET�s
zSimpleHTTPRequestHandler.do_GETcCs|j�}|r|j�dS)zServe a HEAD request.N)r�r)rr�rrr�do_HEAD�sz SimpleHTTPRequestHandler.do_HEADc	Csx|j|j�}d}tjj|�r�tjj|j�}|jjd�s�|jt	j
�|d|d|dd|d|df}tjj|�}|jd|�|j
�dSx6dD]$}tjj||�}tjj|�r�|}Pq�W|j|�S|j|�}yt|d�}Wn$tk
�r|jt	jd�dSXyZ|jt	j�|jd
|�tj|j��}|jdt|d��|jd|j|j��|j
�|S|j��YnXdS)a{Common code for GET and HEAD commands.

        This sends the response code and MIME headers.

        Return value is either a file object (which has to be copied
        to the outputfile by the caller unless the command was HEAD,
        and must be closed by the caller under all circumstances), or
        None, in which case the caller has nothing further to do.

        Nrrrrr�ZLocation�
index.html�	index.htm�rbzFile not foundzContent-typezContent-Length�z
Last-Modified)r�r�)�translate_pathr.�os�isdir�urllib�parseZurlsplit�endswithrSrZMOVED_PERMANENTLYZ
urlunsplitrTr>re�exists�list_directory�
guess_type�open�OSErrorr,�	NOT_FOUND�OK�fstat�filenor#r]�st_mtimer)	rr.r��partsZ	new_partsZnew_url�indexZctypeZfsrrrr��sF


z"SimpleHTTPRequestHandler.send_headc
Cs�ytj|�}Wn"tk
r0|jtjd�dSX|jdd�d�g}ytjj	|j
dd�}Wn tk
r|tjj	|�}YnXtj
|dd	�}tj�}d
|}|jd�|jd�|jd
|�|jd|�|jd|�|jd�x~|D]v}tj
j||�}|}	}
tj
j|��r"|d}	|d}
tj
j|��r8|d}	|jdtjj|
dd�tj
|	dd	�f�q�W|jd�dj|�j|d�}tj�}|j|�|jd�|jtj�|jdd|�|jdtt|���|j�|S)z�Helper to produce a directory listing (absent index.html).

        Return value is either a file object, or None (indicating an
        error).  In either case, the headers are sent, making the
        interface the same as for send_head().

        zNo permission to list directoryNcSs|j�S)N)r7)�arrr�<lambda>�sz9SimpleHTTPRequestHandler.list_directory.<locals>.<lambda>)�key�
surrogatepass)�errorsF)rLzDirectory listing for %szZ<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">z
<html>
<head>z@<meta http-equiv="Content-Type" content="text/html; charset=%s">z<title>%s</title>
</head>z<body>
<h1>%s</h1>z	<hr>
<ul>r�@z<li><a href="%s">%s</a></li>z</ul>
<hr>
</body>
</html>
�
�surrogateescaperzContent-typeztext/html; charset=%szContent-Length) r��listdirr�r,rr��sortr�r��unquoter.�UnicodeDecodeErrorrVrWrl�getfilesystemencodingr`rer��islinkrLrX�io�BytesIOrZ�seekrSr�rTr#r(r>)
rr.�list�rZdisplaypath�enc�title�name�fullnameZdisplaynameZlinknameZencodedr�rrrr��s\







z'SimpleHTTPRequestHandler.list_directorycCs�|jdd�d}|jdd�d}|j�jd�}ytjj|dd�}Wn tk
rbtjj|�}YnXtj|�}|jd�}t	d|�}t
j�}x8|D]0}t
jj
|�s�|t
jt
jfkr�q�t
jj||�}q�W|r�|d7}|S)	z�Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        �?rr�#rr�)r�N)r'r%r�r�r�r�r��	posixpath�normpath�filterr��getcwdr.�dirname�curdir�pardirre)rr.Ztrailing_slashr:Zwordrrrr��s$	



z'SimpleHTTPRequestHandler.translate_pathcCstj||�dS)a�Copy all data between two file objects.

        The SOURCE argument is a file object open for reading
        (or anything with a read() method) and the DESTINATION
        argument is a file object open for writing (or
        anything with a write() method).

        The only reason for overriding this would be to change
        the block size or perhaps to replace newlines by CRLF
        -- note however that this the default server uses this
        to copy binary data as well.

        N)�shutilZcopyfileobj)r�sourceZ
outputfilerrrr�sz!SimpleHTTPRequestHandler.copyfilecCsLtj|�\}}||jkr"|j|S|j�}||jkr>|j|S|jdSdS)a�Guess the type of a file.

        Argument is a PATH (a filename).

        Return value is a string of the form type/subtype,
        usable for a MIME Content-type header.

        The default implementation looks the file's extension
        up in the table self.extensions_map, using application/octet-stream
        as a default; however it would be permissible (if
        slow) to look inside the data to make a better guess.

        rN)r��splitext�extensions_mapr7)rr.�baseZextrrrr�)s



z#SimpleHTTPRequestHandler.guess_typezapplication/octet-streamz
text/plain)rz.pyz.cz.hN)rrrrr�rqr�r�r�r�r�r�r��	mimetypesZinitedZinitZ	types_map�copyr��updaterrrrrrs"	1:
c	Cs�|jd�\}}}tjj|�}|jd�}g}x<|dd�D],}|dkrN|j�q8|r8|dkr8|j|�q8W|r�|j�}|r�|dkr�|j�d}q�|dkr�d}nd}|r�dj||f�}ddj|�|f}dj|�}|S)	a�
    Given a URL path, remove extra '/'s and '.' path elements and collapse
    any '..' references and returns a collapsed path.

    Implements something akin to RFC-2396 5.2 step 6 to parse relative paths.
    The utility of this function is limited to is_cgi method and helps
    preventing some security attacks.

    Returns: The reconstituted URL, which will always start with a '/'.

    Raises: IndexError if too many '..' occur within the path.

    r�rNrz..rr���)�	partitionr�r�r�r'�popr`re)	r.�_�query�
path_partsZ
head_parts�partZ	tail_partZ	splitpath�collapsed_pathrrr�_url_collapse_pathNs.


r�cCsptrtSyddl}Wntk
r(dSXy|jd�daWn.tk
rjdtdd�|j�D��aYnXtS)	z$Internal routine to get nobody's uidrNr�nobodyrcss|]}|dVqdS)rNr)r|rvrrr�	<genexpr>�sznobody_uid.<locals>.<genexpr>r�)r��pwd�ImportError�getpwnamrR�maxZgetpwall)r�rrr�
nobody_uid�s r�cCstj|tj�S)zTest for executable file.)r��access�X_OK)r.rrr�
executable�sr�c@sVeZdZdZeed�ZdZdd�Zdd�Z	dd	�Z
d
dgZdd
�Zdd�Z
dd�ZdS)rz�Complete HTTP server with GET, HEAD and POST commands.

    GET and HEAD also support running CGI scripts.

    The POST command is *only* implemented for CGI scripts.

    �forkrcCs$|j�r|j�n|jtjd�dS)zRServe a POST request.

        This is only implemented for CGI scripts.

        zCan only POST to CGI scriptsN)�is_cgi�run_cgir,rrA)rrrr�do_POST�s

zCGIHTTPRequestHandler.do_POSTcCs|j�r|j�Stj|�SdS)z-Version of send_head that support CGI scriptsN)r�r�rr�)rrrrr��szCGIHTTPRequestHandler.send_headcCsPt|j�}|jdd�}|d|�||dd�}}||jkrL||f|_dSdS)a3Test whether self.path corresponds to a CGI script.

        Returns True and updates the cgi_info attribute to the tuple
        (dir, rest) if self.path requires running a CGI script.
        Returns False otherwise.

        If any exception is raised, the caller should assume that
        self.path was rejected as invalid and act accordingly.

        The default implementation tests whether the normalized url
        path begins with one of the strings in self.cgi_directories
        (and the next character is a '/' or the end of the string).

        rrNTF)r�r.�find�cgi_directories�cgi_info)rr�Zdir_sep�head�tailrrrr��s


zCGIHTTPRequestHandler.is_cgiz/cgi-binz/htbincCst|�S)z1Test whether argument path is an executable file.)r�)rr.rrr�
is_executable�sz#CGIHTTPRequestHandler.is_executablecCstjj|�\}}|j�dkS)z.Test whether argument path is a Python script.�.py�.pyw)r�r�)r�r.r�r7)rr.r�r�rrr�	is_python�szCGIHTTPRequestHandler.is_pythonc)Cs�|j\}}|d|}|jdt|�d�}x`|dkr�|d|�}||dd�}|j|�}tjj|�r�||}}|jdt|�d�}q,Pq,W|jd�\}}}	|jd�}|dkr�|d|�||d�}
}n
|d}
}|d|
}|j|�}tjj|��s|j	t
jd|�dStjj|��s2|j	t
j
d|�dS|j|�}
|j�sL|
�rn|j|��sn|j	t
j
d	|�dStjtj�}|j�|d
<|jj|d<d|d
<|j|d<t|jj�|d<|j|d<tjj|�}||d<|j|�|d<||d<|	�r�|	|d<|jd|d<|jj d�}|�r�|j!�}t|�dk�r�ddl"}ddl#}|d|d<|dj$�dk�r�y"|dj%d�}|j&|�j'd�}Wn|j(t)fk
�r�Yn&X|j!d�}t|�dk�r�|d|d<|jj d�dk�r�|jj*�|d<n|jd|d<|jj d�}|�r||d <|jj d!�}|�r"||d"<g}xN|jj+d#�D]>}|dd�d$k�rZ|j,|j-��n||d%d�j!d&�}�q4Wd&j.|�|d'<|jj d(�}|�r�||d)<t/d|jj0d*g��}d+j.|�}|�r�||d,<xd=D]}|j1|d��q�W|j2t
j3d.�|j4�|	j5d/d0�}|j�r.|
g}d1|k�r*|j,|�t6�}|j7j8�tj9�}|dk�r�tj:|d�\}}x0t;j;|j<gggd�d�r�|j<j=d��s^P�q^W|�r�|j>d2|�dSy\ytj?|�Wnt@k
�r�YnXtjA|j<jB�d�tjA|j7jB�d�tjC|||�Wn(|jjD|jE|j�tjFd3�YnX�n�ddlG} |g}!|j|��r�tHjI}"|"j$�jJd4��rv|"dd>�|"d?d�}"|"d7g|!}!d1|	k�r�|!j,|	�|jKd8| jL|!��ytM|�}#WntNtOfk
�r�d}#YnX| jP|!| jQ| jQ| jQ|d9�}$|jj$�d:k�r|#dk�r|j<j=|#�}%nd}%x4t;j;|j<jRgggd�d�rN|j<jRjSd��sP�qW|$jT|%�\}&}'|j7jU|&�|'�r||j>d;|'�|$jVjW�|$jXjW�|$jY}(|(�r�|j>d2|(�n
|jKd<�dS)@zExecute a CGI script.rrrNr�rzNo such CGI script (%r)z#CGI script is not a plain file (%r)z!CGI script is not executable (%r)ZSERVER_SOFTWAREZSERVER_NAMEzCGI/1.1ZGATEWAY_INTERFACEZSERVER_PROTOCOLZSERVER_PORTZREQUEST_METHODZ	PATH_INFOZPATH_TRANSLATEDZSCRIPT_NAME�QUERY_STRINGZREMOTE_ADDR�
authorizationrZ	AUTH_TYPEZbasic�ascii�:ZREMOTE_USERzcontent-typeZCONTENT_TYPEzcontent-length�CONTENT_LENGTH�referer�HTTP_REFERER�acceptz	

 ��,ZHTTP_ACCEPTz
user-agent�HTTP_USER_AGENTZcookiez, �HTTP_COOKIE�REMOTE_HOSTzScript output follows�+rp�=zCGI script exit status %#x�zw.exerr�z-uzcommand: %s)�stdin�stdoutrm�envZpostz%szCGI script exited OK)r�r�r�r�r�r�������)Zr�r�r(r�r�r.r�r�r�r,rr��isfileZ	FORBIDDENr��	have_forkr�r��deepcopy�environr\Zserverrr-r#rrr�r�r�rzr5r6r'�base64�binasciir7rXZdecodebytes�decode�Error�UnicodeErrorZget_content_typeZgetallmatchingheadersr`�striprer�Zget_all�
setdefaultrSr�rcrPr�rCrDr��waitpid�selectr3�readrE�setuidr��dup2r��execveZhandle_errorZrequest�_exit�
subprocessrlr�r�rhZlist2cmdliner*�	TypeErrorr)�Popen�PIPEZ_sockZrecvZcommunicaterZrmrr��
returncode))r�dir�restr.�iZnextdirZnextrestZ	scriptdirr�r�ZscriptZ
scriptnameZ
scriptfileZispyr�Zuqrestr�rrZlengthr�r��lineZua�coZ
cookie_str�kZ
decoded_queryrkr��pid�stsrZcmdlineZinterp�nbytes�p�datar�rmZstatusrrrr��s4

























zCGIHTTPRequestHandler.run_cgiN)rrrrr@r�r�Zrbufsizer�r�r�r�r�r�r�rrrrr�s
zHTTP/1.0i@rc	Cs�||f}||_|||��b}|jj�}d}t|j|d|dd��y|j�Wn&tk
rttd�tjd�YnXWdQRXdS)zmTest the HTTP request handler class.

    This runs an HTTP server on port 8000 (or the port argument).

    z>Serving HTTP on {host} port {port} (http://{host}:{port}/) ...rr)rrz&
Keyboard interrupt received, exiting.N)	r-r
Zgetsockname�printrjZ
serve_forever�KeyboardInterruptrl�exit)	�HandlerClassZServerClassZprotocolr�bindrZhttpdZsaZ
serve_messagerrr�test�s
r%�__main__z--cgi�
store_truezRun as CGI Server)�action�helpz--bindz-bZADDRESSz8Specify alternate bind address [default: all interfaces])�default�metavarr)rZstorer�z&Specify alternate port [default: 8000])r(r*�type�nargsr))r#rr$)/rr��__all__Zemail.utilsrtrVZhttp.clientr1r�r�r�r�r
r�r
r	rlrsZurllib.parser�r��argparserr�r�r
rZStreamRequestHandlerrrr�r�r�r�rr%r�ArgumentParser�parser�add_argumentr*�
parse_argsrkZcgiZ
handler_classrr$rrrr�<module> sj3g]0