�ɲɾ�����ӯ�����һ��ˣ��������С���˴��ͣ�������P���ҹ��ñ˽��ά�Բ��������˸߸ԣ�������ơ��ҹ��ñ�����ά�Բ���ˡ���˳^�ӣ������ӡ� ���ͯj�ӣ��ƺ���ӣ� ? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!? PNG ?%k25u25%fgd5n!client.py000064400000156052152527315050006412 0ustar00r"""HTTP/1.1 client library 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 Req-started-unread-response _CS_REQ_STARTED Req-sent-unread-response _CS_REQ_SENT """ import email.parser import email.message import http import io import os import re import socket import collections 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 amount of data to read at one time in _safe_read MAXAMOUNT = 1048576 # 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 in self.headers: print("header:", hdr + ":", self.headers.get(hdr)) # 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") # are we using the chunked-style of transfer encoding? tr_enc = self.headers.get("transfer-encoding") 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. conn = self.headers.get("connection") 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, 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 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. """ s = [] while amt > 0: chunk = self.fp.read(min(amt, MAXAMOUNT)) if not chunk: raise IncompleteRead(b''.join(s), amt) s.append(chunk) amt -= len(chunk) return b"".join(s) def _safe_readinto(self, b): """Same as _safe_read, but for reading into a buffer.""" total_bytes = 0 mvb = memoryview(b) while total_bytes < len(b): if MAXAMOUNT < len(mvb): temp_mvb = mvb[0:MAXAMOUNT] n = self.fp.readinto(temp_mvb) else: n = self.fp.readinto(mvb) if not n: raise IncompleteRead(bytes(mvb[0:total_bytes]), len(b)) mvb = mvb[n:] total_bytes += n return total_bytes 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 try: result = self.fp.read1(n) except ValueError: if n >= 0: raise # some implementations, like BufferedReader, don't support -1 # Read an arbitrarily selected largeish chunk. result = self.fp.read1(16*1024) 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): self.timeout = timeout self.source_address = source_address 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) # 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 HTML 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)) blocksize = 8192 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(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.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): blocksize = 8192 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(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 we use, we need it later in the response phase self._method = method if not url: url = '/' # 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})") request = '%s %s %s' % (method, url, self._http_vsn_str) # Non-ASCII characters should have been eliminated earlier self._output(request.encode('ascii')) 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 _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 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): super(HTTPSConnection, self).__init__(host, port, timeout, source_address) 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 self._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) if not self._context.check_hostname and self._check_hostname: try: ssl.match_hostname(self.sock.getpeercert(), server_hostname) except Exception: self.sock.shutdown(socket.SHUT_RDWR) self.sock.close() raise __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) def __str__(self): return repr(self) 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__/client.cpython-312.opt-1.pyc000064400000162214152527315050013707 0ustar00 {|jjdZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl m Z gdZdZdZdZdZd Zd Zej-ej.j0ej.j0j3Dcic]}||j4c}Zd Zd Zd Zd Zej@djBZ"ej@djFZ$ej@dZ%ej@dZ&hdZ'd?dZ(de)de)fdZ*GddejVjXZ-dZ.e-fdZ/e-fdZ0GddejbZ2dZ3Gdd Z4 ddl5Z5Gd!d"e4Z6ejod"Gd#d$e9Z:Gd%d&e:Z;Gd'd(e:Z<Gd)d*e:Z=Gd+d,e:Z>Gd-d.e:Z?Gd/d0e:Z@Gd1d2e:ZAGd3d4eAZBGd5d6eAZCGd7d8eAZDGd9d:e:ZEGd;deGeEZHe:ZIycc}w#e8$rYwxYw)@a HTTP/1.1 client library 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 Req-started-unread-response _CS_REQ_STARTED Req-sent-unread-response _CS_REQ_SENT N)urlsplit) HTTPResponseHTTPConnection HTTPException NotConnectedUnknownProtocolUnknownTransferEncodingUnimplementedFileModeIncompleteRead InvalidURLImproperConnectionStateCannotSendRequestCannotSendHeaderResponseNotReady BadStatusLine LineTooLongRemoteDisconnectederror responsesPiUNKNOWNIdlezRequest-startedz Request-sentidis[^:\s][^:\r\n]*s\n(?![ \t])|\r(?![ \t\n])z[- ]z[-]>PUTPOSTPATCHc  |jdS#t$rl}t|j|j|j|j |j d||j|j dd|ddd}~wwxYw)z|jd\}}}|r|dz }|S)z)Remove interface scope from IPv6 address.%]) partition)r+percent_s r)_strip_ipv6_ifacer3s+#--d3HgqD OceZdZdZy) HTTPMessagec|jdz}t|}g}d}|jD]D}|d|j|k(rd}n|ddjsd}|s4|j |F|S)aFind 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)lowerlenkeysisspaceappend)selfr'nlsthitlines r)getallmatchingheadersz!HTTPMessage.getallmatchingheaderss~zz|c! IIIKDBQx~~4'"1X%%' 4   r4N)__name__ __module__ __qualname__rDr4r)r6r6sr4r6cg} |jtdz}t|tkDr td|j |t|t kDrt dt z|dvr |Sr)zReads 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. r9z header linezgot more than %d headers  r4)readline_MAXLINEr;rr> _MAXHEADERSr)fpheadersrCs r) _read_headersrRst G {{8a<( t9x m, ,t w<+ % :[ HI I ( (  N r4cdj|jd}tjj |j |S)aJ Parses only RFC2822 headers from header lines. 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. r4 iso-8859-1)_class)joindecodeemailparserParserparsestr) header_linesrUhstrings r)_parse_header_linesr^s@hh|$++L9G <<  f  - 6 6w ??r4c0t|}t||S)z0Parses only RFC2822 headers from a file pointer.)rRr^)rPrUrQs r) parse_headersr`sBG w //r4ceZdZddZdZdZdZdZfdZfdZ dZ d Z d d Z d Z d Zd ZdZd dZdZdZdZd!dZd!dZd!fd ZdZdZdZd dZdZdZdZdZdZ xZ!S)"rc|jd|_||_||_dx|_|_t |_t |_t |_ t |_ t |_ t |_ t |_ y)Nrb)makefilerP debuglevel_methodrQmsg_UNKNOWNversionstatusreasonchunked chunk_leftlength will_close)r?sockremethodurls r)__init__zHTTPResponse.__init__se--%$ #'& tx     " "r4clt|jjtdzd}t |tkDr t d|j dkDrtdt||s td |jdd\}}}|jd s|jt| t}|d ks|d kDr t| ||fS#t$r- |jdd\}}d}n#t$rd}YnwxYwYwxYw#t$r t|wxYw) Nr9rTz status linerzreply:z-Remote end closed connection without responsezHTTP/ri)strrPrMrNr;rreprintreprrsplit ValueError startswith _close_connrint)r?rCrirjrks r) _read_statuszHTTPResponse._read_status/sD477##HqL1<@ t9x m, , ??Q  (DJ '%&12 2 &*jjq&9 #GVV!!'*    % % &[F|v|#D)) ,&&%  "&**T1"5      &% % &sB<C%? D% D/DD DDDDDD3c|jyttD]R}|j\}}}|tk7rnFt |j }|jdkDr td|~Ttdtd|x|_ |_ |j|_ |dvrd|_n$|jdrd|_n t!|t#|j x|_|_|jdkDr2|jj'D]\}}td |d z||jj)d }|r"|j+d k(rd |_d|_nd|_|j1|_d|_|jj)d} | r4|j,s( t7| |_|j4dkrd|_nd|_|t:k(s%|t<k(sd|cxkrdksn|j>dk(rd|_|j2s"|j,s|j4d |_yyyy#t8$r d|_YvwxYw)Nrzheaders:got more than z interim responses)zHTTP/1.0zHTTP/0.9 zHTTP/1. header:r8transfer-encodingrlTFcontent-lengthrHEAD) rQrange_MAXINTERIMRESPONSESrCONTINUErRrPrerxrcoderjstriprkrir|rr`rgitemsgetr:rlrm _check_closerornr~r{ NO_CONTENT NOT_MODIFIEDrf) r?r2rirjrkskipped_headershdrvaltr_encrns r)beginzHTTPResponse.beginPs< << # +,A&*&7&7&9 #GVV!+DGG4O"j/2-  !5 66HIK K#)( DKlln . .DL    *DL!'* *"/"88 tx ??Q  LL..0SisC01!!"56 flln 1DL"DO DL++- !!"23 $,, '!&k ;;?"&DKDK j Fl$: 6 C  LLF "DK  KK "DO  # #"  #sII+*I+cF|jjd}|jdk(r|rd|jvryy|jjdry|rd|jvry|jjd}|rd|jvryy)N connectionrcloseTFz keep-alivezproxy-connection)rQrrir:)r?connpconns r)rzHTTPResponse._check_closes|| - <<2 4::</ <<  L ) LDJJL0   !34 \U[[]2r4cJ|j}d|_|jyN)rPr)r?rPs r)r}zHTTPResponse._close_conns WW  r4c t||jr|jyy#|jr|jwwxYwr)superrrPr}r? __class__s r)rzHTTPResponse.closesB # GMOww  "tww  "s /Acpt||jr|jjyyr)rflushrPrs r)rzHTTPResponse.flushs%   77 GGMMO r4cy)zAlways returns TrueTrHr?s r)readablezHTTPResponse.readablesr4c|jduS)z!True if the connection is closed.N)rPrs r)isclosedzHTTPResponse.isclosedsww$r4c|jy|jdk(r|jy|jr|j |S||dk\r|j ||j kDr |j }|jj |}|s|r|j|S|j :|xj t|zc_|j s|j|S|j |jj }n# |j|j }d|_|j|S#t$r|jwxYw)z?Read and return the response body, or up to the next amt bytes.r4rr) rPrfr}rl _read_chunkedrnreadr; _safe_readr )r?amtss r)rzHTTPResponse.reads8 77? <<6 !     <<%%c* * ?sax{{&3+<kk S!A  " H ( s1v% {{$$&H{{"GGLLN 4A     H &$$&s EE)c|jy|jdk(r|jy|jr|j |S|j 0t ||j kDrt|d|j }|jj|}|s|r|j|S|j 1|xj |zc_|j s|j|S)z^Read up to len(b) bytes into bytearray b and return the number of bytes read. rr) rPrfr}rl_readinto_chunkedrnr; memoryviewreadinto)r?br@s r)rzHTTPResponse.readintos 77? <<6 !     <<))!, , ;; "1v #qM!DKK0 GG  Q Q      [[ $ KK1 K;;  "r4c |jjtdz}t|tkDr t d|j d}|dk\r|d|} t |dS#t$r|jwxYw)Nr9z chunk size;r) rPrMrNr;rfindr~r{r})r?rCis r)_read_next_chunk_sizez"HTTPResponse._read_next_chunk_size(sww1 - t9x l+ + IIdO 68D tR=         s  A((Bcd} |jjtdz}t|tkDr t d|sy|dvry|dz }|t kDrt dt di)Nrr9z trailer linerJrz trailers)rPrMrNr;rrOr)r? trailers_readrCs r)_read_and_discard_trailerz&HTTPResponse._read_and_discard_trailer8s 77##HqL1D4y8#!.11,, Q M{*#$[M;==!r4c|j}|sR||jd |j}|dk(r"|j |j d}||_|S#t$r t dwxYw)Nrur4r)rmrrr{r rr})r?rms r)_get_chunk_leftzHTTPResponse._get_chunk_leftOs __ %" *!779 Q..0  "! (DO *$S)) *s A##A8c||dkrd}g} |jx}s|0||kr+|j|j|||z |_nA|j|j||||z}d|_|jx}sdj |S#t $r }t dj ||d}~wwxYwNrr4)rr>rrmrVr )r?rvaluermexcs r)rzHTTPResponse._read_chunkedgs ?sQwC ;!%!5!5!77:D?sj'8LL!56&03&6DO T__Z89?:%C"#"&!5!5!77:D88E? " ; %1s : ;sBB#B## C ,CC c<d}t|} |j}||St||kr |j|}||z |_||zS|d|}|j|}||d}||z }d|_j#t $rt t |d|wxYw)Nr)rrr;_safe_readintormr bytes)r?r total_bytesmvbrmr@temp_mvbs r)rzHTTPResponse._readinto_chunked{s m :!113 %&&s8z)++C0A&01nDO&?*{ +''1!"gq "#  : q;'7!89 9 :sA:-A:(A::!BcTt|t}|jj|}t ||k\r|St ||krt ||t |z t j|}|jdd t|||z }|j|jj||j|k\r|jS||z }|j|kr+t |j||jz )a Read the number of bytes requested. This function should be used when 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. rru) min_MIN_READ_BUF_SIZErPrr;r ioBytesIOseekwritetellgetvalue)r?rcursizer&deltas r)rzHTTPResponse._safe_readsc-.ww||G$ t9 K t9w  sSY7 7zz$ !Qw/E JJtww||E* +yy{c!}}& u Gyy{W$$T]]_cDIIK6GHHr4ct|}|jj|}||krtt |d|||z |S)z2Same as _safe_read, but for reading into a buffer.N)r;rPrr r)r?rrr@s r)rzHTTPResponse._safe_readintosF!f GG  Q  s7 q!us1u5 5r4c|j|jdk(ry|jr|j|S|j |dks||jkDr |j}|jj |}|s|r|j |S|j:|xjt|zc_|js|j |S)zvRead with at most one underlying system call. If at least one byte is buffered, return that instead. rr4r)rPrfrl_read1_chunkedrnread1r}r;)r?r@results r)rzHTTPResponse.read1s 77?dllf4 <<&&q) ) ;; "AT[[ Aq!!      [[ $ KK3v; &K;;  " r4c|j|jdk(ry|jr|j|S|jj |S)Nrr4)rPrfrl _peek_chunkedpeek)r?r@s r)rzHTTPResponse.peeksE 77?dllf4 <<%%a( (ww||Ar4c|j|jdk(ry|jrt||S|j |dks||j kDr |j }|jj |}|s|r|j |S|j :|xj t|zc_|j s|j |S)Nrr4r)rPrfrlrrMrnr}r;)r?limitrrs r)rMzHTTPResponse.readlines 77?dllf4 <<7#E* * ;; " UT[[5HKKE!!%(%      [[ $ KK3v; &K;;  " r4c|j}||dk(ryd|cxkr|ksn|}|jj|}|xjt |zc_|s t d|Sr)rrPrrmr;r )r?r@rmrs r)rzHTTPResponse._read1_chunkedsj))+  aQ$*$Aww}}Q 3t9$ % % r4c |j}|y|jj|d|S#t$rYywxYw)Nr4)rr rPr)r?r@rms r)rzHTTPResponse._peek_chunkedsP --/J  ww||J' 44   s 3 ??c6|jjSr)rPfilenors r)rzHTTPResponse.filenosww~~r4c|j t|jj|xs|}t|ts t |ds|Sdj |S)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. __iter__z, )rQrget_all isinstancerwhasattrrV)r?r'defaultrQs r) getheaderzHTTPResponse.getheadersW << "$ $,,&&t,7 gs #77J+GN99W% %r4ct|j tt|jjS)z&Return list of (header, value) tuples.)rQrlistrrs r) getheaderszHTTPResponse.getheaderss- << "$ $DLL&&())r4c|SrrHrs r)rzHTTPResponse.__iter__s r4c|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. )rQrs r)infozHTTPResponse.info"s*||r4c|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. )rrrs r)geturlzHTTPResponse.geturl9s xxr4c|jS)zuReturn the HTTP status code that was sent with the response, or None if the URL is not an HTTP URL. )rjrs r)getcodezHTTPResponse.getcodeEs {{r4)rNNr))"rErFrGrsrrrr}rrrrrrrrrrrrrrrrMrrrrrrrrr __classcell__rs@r)rrs#<'BI#V: #  &P D =.0;(:0I6&"  5 &(* . r4rctj}|dk(r|jdg|jd|_|S)Nrzhttp/1.1T)ssl_create_default_https_contextset_alpn_protocolspost_handshake_auth) http_versioncontexts r)_create_https_contextrMsC//1Gr""J<0"".&*# Nr4c eZdZdZdZeZeZdZ dZ e dZ e dZ dejddfd Zd"d Zd Zd Zd ZdZdZdZdZdZdZdZd#dZ d$dZdZdZdZ dZ!dZ"d%dddZ#difdddZ$d Z%d!Z&y)&rrzHTTP/1.1r9rc6t|tjS)zFTest whether a file-like object is a text or a binary stream. )rr TextIOBase)streams r) _is_textIOzHTTPConnection._is_textIOds&"--00r4c||jtvryyt|dry t|}|jS#t $rYnwxYwt |tr t|Sy)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_BODYrrnbytes TypeErrorrrwr;)bodyrqmvs r)_get_content_lengthz"HTTPConnection._get_content_lengthjsq <||~!88 4  D!B99     dC t9 sA A  A N cR||_||_||_d|_g|_d|_t |_d|_d|_ d|_ i|_ d|_ |j||\|_|_|j!|jt"j$|_yr)timeoutsource_address blocksizerp_buffer_HTTPConnection__response_CS_IDLE_HTTPConnection__staterf _tunnel_host _tunnel_port_tunnel_headers_raw_proxy_headers _get_hostporthostport_validate_hostsocketcreate_connection_create_connection)r?rrrrrs r)rszHTTPConnection.__init__s ,"      !"&!%!3!3D$!?DI DII&#)":":r4c|jr td|j||\|_|_|r|j |_n|j jtd|j DsI|jjdjd}d||jfz|j d<yy)aSet up host and port for HTTP CONNECT tunnelling. In a connection that uses HTTP CONNECT tunnelling, 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. As HTTP/1.1 is used for HTTP CONNECT tunnelling request, as per the RFC (https://tools.ietf.org/html/rfc7231#section-4.3.6), a HTTP Host: header must be provided, matching the authority-form of the request target provided as the destination for the CONNECT request. If a HTTP Host: header is not provided via the headers argument, one is generated and transmitted automatically. z.Can't set up tunnel for established connectionc3BK|]}|jdk(yw)rNr:).0headers r) z,HTTPConnection.set_tunnel..sO:N6<<>V+:Nsidnaasciiz%s:%dHostN) rp RuntimeErrorrrrcopyrclearanyrrW)r?rrrQ encoded_hosts r) set_tunnelzHTTPConnection.set_tunnels, 99OP P/3/A/A$/M,4, #*<<>D  & & (O$:N:NOO,,33F;BB7KL+2d//61,1D  (Pr4cH|K|jd}|jd}||kDr t||dzd}|d|}n |j}|r|ddk(r |ddk(r|dd}||fS#t$r/||dzddk(r |j}nt d||dzdzYdwxYw) Nr8]r9rvznonnumeric port: '%s'r[r)rfindr~r{ default_portr )r?rrrjs r)rzHTTPConnection._get_hostports < 3A 3A1uOtAaCDz?D BQx(( DGsNtBx3":Dd|"OAaCDzR'#00()@4!:)MNNOsA))5B! B!c||_yr)re)r?levels r)set_debuglevelzHTTPConnection.set_debuglevels r4c.d|vr|ddk7rd|zdzS|S)N:r[[r/rH)r?ips r) _wrap_ipv6zHTTPConnection._wrap_ipv6s( 2:"Q%7*"9t# # r4ctj|jrtd|jd|j |jj d|j |jj dfz}|g}|jjD]o\}}|j d}|j d}t|std|t|rtd||jd||fzq|jd |jd j|~|j|j |j" } |j%\}} } t'|j(|_|j,d kDr+|j*D]}t/d |j1| t2j4j6k7r/|j9t;d| d| j= |j9y#|j9wxYw)Nz-Tunnel host can't contain control characters sCONNECT %s:%d %s r&r'rInvalid header name Invalid header value s%s: %s rKr4rqrrzTunnel connection failed:  )!_contains_disallowed_url_pchar_researchrr{r=rr _http_vsn_strrr_is_legal_header_name_is_illegal_header_valuer>sendrVresponse_classrprfrrRrPrrerxrWhttp HTTPStatusOKrOSErrorr) r?connectrQr$r header_bytes value_bytesresponserirmessages r)_tunnelzHTTPConnection._tunnels , 3 3D4E4E F $ 1 145 5) OOD--44V< =       % %g .-00)!11779MFE!==3L,,y1K(6 \!KLL' 4 k!KLL NN=L++FF G: w #((7#$ &&tyy&F '/'<'<'> $WdG&3HKK&@D #""55F)V]]_56t)))  :4&'--/ARSTT* NN HNN s 4B4H::I cH|jt|jSdS)z Returns a dictionary with the headers of the response received from the proxy server to the CONNECT request sent to set the tunnel. If the CONNECT request was not sent, the method returns None. N)rr^rs r)get_proxy_response_headersz)HTTPConnection.get_proxy_response_headers s/&&2  7 7 8  r4ctjd||j|j|j |j|jf|j |j |_ |jjtjtjd|jr|j!yy#t$r(}|jtjk7rYd}~Jd}~wwxYw)z3Connect to the host and port specified in __init__.zhttp.client.connectr9N)sysauditrrrrrrp setsockoptr IPPROTO_TCP TCP_NODELAYrMerrno ENOPROTOOPTrrSr?es r)rNzHTTPConnection.connects 'tyy$))D++ YYtyy !4<<1D1DF   II !3!3V5G5G K    LLN   ww%+++, s09C C8C33C8ct|_ |j}|rd|_|j|j}|rd|_|jyy#|j}|rd|_|jwwxYw)z(Close the connection to the HTTP server.N)rrrprr)r?rprQs r)rzHTTPConnection.close'sr  !99D   H"& H"& s %A(Bc|j'|jr|jn t|jdkDrt dt |t|dr|jdkDr t d|j|}|r|jdkDr t d|j|jx}rc|r|jd}tjd|||jj||j|jx}rcytjd|| |jj|y#t$r`t!|t"j$j&r$|D]}|jj|Yytd t)|zwxYw) zSend `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:rzsending a readableencoding file using iso-8859-1rTzhttp.client.sendz9data should be a bytes-like object or an iterable, got %r)rp auto_openrNrrerxryrrrrrrWrXsendallrr collectionsabcIterabletype)r?r&r datablockds r)rHzHTTPConnection.send5s~ 99 ~~ "n$ ??Q  '4: & 4 "*+__T*F$//A-67#yy88)8 ) 0 0 >I ,dI> !!), $yy88)8  $dD1 G II  d # G$  8 89AII%%a( !9;?:!FGG  GsE AG 1G c:|jj|y)zuAdd a line of output to the current request buffer. Assumes that the line does *not* end with \r\n. N)rr>)r?rs r)_outputzHTTPConnection._outputZs Ar4c#@K|jdkDr td|j|}|r|jdkDr td|j|jx}r6|r|j d}||j|jx}r5yyw)Nrzreading a readablerbrT)rerxrrrr)r?rrris r)_read_readablezHTTPConnection._read_readableas ??Q  & '* doo) 2 3#==88i8%,,\: O$==88i8s BBBFc|jjddj|j}|jdd=|j||t |dr|j |}n t ||f}|D]e}|s|jdkDr td |r3|jdk(r$t|d d jd |zdz}|j|g|r"|jdk(r|jd yyyy#t$r4 t|}n$#t$rtdt|zwxYwYwxYw) zSend 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. )r4r4rKNrzAmessage_body should be a bytes-like object or an iterable, got %rrzZero length chunk ignoredrXz r's0 )rextendrVrHrrnrriterrhrerx _http_vsnr;r)r? message_bodyencode_chunkedrgchunkschunks r) _send_outputzHTTPConnection._send_outputls` J'll4<<( LLO #  #|V,,,\:- |,+_F*9:!dnn&:"5z!nD188AEI!"E %  $..B"6 ,'#7~O $!>>!%l!3$>')H*.|*<)=>>>>s*8 D E D,+E,!E  EEcz|jr!|jjrd|_|jtk(r t|_nt |j|j |||_|xsd}|j||d|d|j}|j|j||jdk(r&|s d}|jdrt|\}}}}}|r. |jd}|j#d t%|n|j&r|j&} |j(} n|j*} |j,} | jd} |j/| } d | vr t%| } | |j0k(r|j#d | n(| j3d} |j#d | d | |s|j#d d yyy#t $r|jd}Y wxYw#t $r| jd} YwxYw) 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/rBrrvrJr'r&r(r8zAccept-Encodingidentity)rrrr_CS_REQ_STARTEDr_validate_methodrf_validate_pathrErl_encode_requestrsr|rrr putheaderr3rrrrr=r3rW) r?rqrr skip_hostskip_accept_encodingrequestnetlocnil netloc_encrrhost_encs r) putrequestzHTTPConnection.putrequests ??t779"DO* <<8 #*DL#DLL1 1 f% jS C &T-?-?@ T))'23 >>R >>&)19#.Cc3;%+]]7%; NN6+t000vx8#+??7#;v(D/IJ(0*=( c.;%+]]6%: ;.7#';;v#67s$?G<*H<HHH:9H:c$|jdS)Nr')r)r?rs r)rzHTTPConnection._encode_request!s~~g&&r4crtj|}|r td|d|jdy)z&Validate a method name for putrequest.z)method can't contain control characters.  (found at least )N)$_contains_disallowed_method_pchar_rerDr{group)r?rqmatchs r)r}zHTTPConnection._validate_method%sI5;;FC ?zJ'',{{}&7q:; ; r4crtj|}|r td|d|jdy)zValidate a url for putrequest.&URL can't contain control characters. rrNrCrDr r)r?rrrs r)r~zHTTPConnection._validate_path.sL288= EcWM005 /@CD D r4crtj|}|r td|d|jdy)z9Validate a host so it doesn't contain control characters.rrrNr)r?rrs r)rzHTTPConnection._validate_host6sL288> EdXN005 /@CD D r4c|jtk7r tt|dr|j d}t |st d|t|}t|D]r\}}t|dr|j d||<n-t|trt|j d||<t||sct d||dj|}|dz|z}|j|y) zkSend a request header line to the server. For example: h.putheader('Accept', 'text/html') rr'r?rr@s s: N)rr|rrrrFr{r enumeraterr~rwrGrVrl)r?r$valuesr one_valuers r)rzHTTPConnection.putheader>s <.ns #'0N0N $;."1H(  'R    !#GJ 4(l16(-}~';DD8 Ge G)-bG$G ,=\=r4rcReZdZdZeZdejddddfd ZfdZ xZ S)HTTPSConnectionz(This class allows communication via SSL.Nr )rrrrcrtt| ||||||t|j}||_y)N)r)rrrsrrs_context)r?rrrrrrrs r)rszHTTPSConnection.__init__sB /4 1$g2@ >$($$ $ S Sr4rc eZdZy)rNrErFrGrHr4r)rrs r4rc eZdZy)rNrrHr4r)rrr4rc eZdZy)r NrrHr4r)r r rr4r ceZdZdZy)rc"|f|_||_yr)argsri)r?ris r)rszUnknownProtocol.__init__sH  r4NrErFrGrsrHr4r)rrsr4rc eZdZy)r NrrHr4r)r r rr4r c eZdZy)r NrrHr4r)r r rr4r c2eZdZddZdZej Zy)r Nc0|f|_||_||_yr)rpartialexpected)r?rrs r)rszIncompleteRead.__init__sH    r4c|jd|jz}nd}d|jjt|j|fzS)Nz, %i more expectedrvz%s(%i bytes read%s))rrrEr;rr^s r)__repr__zIncompleteRead.__repr__sK == $$t}}4AA$(?(?(+DLL(91(>> >r4r)rErFrGrsrr"__str__rHr4r)r r s!>nnGr4r c eZdZy)r NrrHr4r)r r rr4r c eZdZy)rNrrHr4r)rr#rr4rc eZdZy)rNrrHr4r)rr&rr4rc eZdZy)rNrrHr4r)rr)rr4rceZdZdZy)rc<|s t|}|f|_||_yr)ryrrC)r?rCs r)rszBadStatusLine.__init__-s:DE  r4NrrHr4r)rr,sr4rceZdZdZy)rcBtj|dt|fzy)Nz&got more than %d bytes when reading %s)rrsrN)r? line_types r)rszLineTooLong.__init__4s"t%M(0)'<&= >r4NrrHr4r)rr3s>r4rceZdZdZy)rcbtj|dtj|g|i|y)Nrv)rrsConnectionResetError)r?poskws r)rszRemoteDisconnected.__init__9s*tR(%%d7S7B7r4NrrHr4r)rr8s8r4r)r&)Jr email.parserrX email.messager\rJrrerrWcollections.abcre urllib.parser__all__rrrhrr|rglobalsupdaterK __members__rphraserrNrOrrcompile fullmatchrFrDrGrCrrr*rr3rRMessager6rRr^r`BufferedIOBaserrrrrr> ImportError Exceptionrrr rr r r r rrrrrrrr)vs0r)rsDL !     #  ,,-#'//"="="D"D"F G"FQQ["F G   8# #67AA%2::&CDKK%/BJJ/@$A!(2rzz-'@$3 E%%--''<$.9 @)0B 2$$B J } } ~!&S.S8 NN$% I  =   m  m  M  ]  m  /  .  . M>-> 8-}8 e. H^+  s H%'H**H21H2__pycache__/__init__.cpython-312.pyc000064400000022421152527315050013224 0ustar00 {|jt tddlmZmZmZddgZeeGddZeeGddZy))StrEnumIntEnum _simple_enum HTTPStatus HTTPMethodc`eZdZdZdGdZedZedZedZedZ edZ dZ d Z d Z d Zd Zd ZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZ dZ!dZ"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/Z2d0Z3d1Z4d2Z5d3Z6d4Z7d5Z8d6Z9d7Z:d8Z;d9ZdZAd?ZBd@ZCdAZDdBZEdCZFdDZGdEZHyF)HraGHTTP 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) * RFC 2324: Hyper Text Coffee Pot Control Protocol (HTCPCP/1.0) * RFC 8297: An HTTP Status Code for Indicating Hints * RFC 8470: Using Early Data in HTTP c\tj||}||_||_||_|SN)int__new___value_phrase description)clsvaluerrobjs &/usr/lib64/python3.12/http/__init__.pyr zHTTPStatus.__new__s,kk#u%  % c"d|cxkxrdkScS)Ndselfs ris_informationalzHTTPStatus.is_informational"d!c!!!!rc"d|cxkxrdkScS)Ni+rrs r is_successzHTTPStatus.is_success&rrc"d|cxkxrdkScS)N,irrs ris_redirectionzHTTPStatus.is_redirection*rrc"d|cxkxrdkScS)Nirrs ris_client_errorzHTTPStatus.is_client_error.rrc"d|cxkxrdkScS)NiWrrs ris_server_errorzHTTPStatus.is_server_error2rr)rContinuez!Request received, please continue)ezSwitching Protocolsz.Switching to new protocol; obey Upgrade header)f Processing)gz Early Hints)rOKz#Request fulfilled, document follows)CreatedzDocument created, URL follows)Acceptedz/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)r!zMultiple Choicesz,Object has several resources -- see URI list)i-zMoved Permanently(Object moved permanently -- see URI list)i.Found(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:)r$z Bad Requestz(Bad request syntax or unsupported method)i Unauthorizedz*No permission -- see authorization schemes)izPayment Requiredz"No payment -- see charging schemes)i Forbiddenz0Request forbidden -- authorization will not help)iz Not FoundzNothing matches the given URI)izMethod Not Allowedz-Specified method is invalid for this resource)izNot Acceptablez%URI not available in preferred format)izProxy Authentication Requiredz7You must authenticate with this proxy before proceeding)izRequest Timeoutz"Request timed out; try again later)iConflictzRequest conflict)iGonez5URI no longer exists and has been permanently removed)izLength Requiredz"Client must specify Content-Length)izPrecondition Failedz Precondition in headers is false)izRequest Entity Too LargezEntity is too large)izRequest-URI Too LongzURI is too long)izUnsupported Media Typez!Entity body in unsupported format)izRequested Range Not SatisfiablezCannot satisfy request range)izExpectation Failedz'Expect condition could not be satisfied)iz I'm a Teapotz5Server refuses to brew coffee because it is a teapot.)izMisdirected Requestz(Server is not able to produce a response)izUnprocessable Entity)iLocked)izFailed Dependency)iz Too Early)izUpgrade Required)izPrecondition Requiredz8The origin server requires the request to be conditional)izToo Many RequestszOThe user has sent too many requests in a given amount of time ("rate limiting"))izRequest Header Fields Too LargezVThe server is unwilling to process the request because its header fields are too large)izUnavailable For Legal ReasonszOThe server is denying access to the resource as a consequence of a legal demand)r'zInternal Server ErrorzServer got itself in trouble)izNot Implementedz&Server does not support this operation)iz Bad Gatewayz+Invalid responses from another server/proxy)izService Unavailablez8The server cannot process the request due to a high load)izGateway Timeoutz4The gateway server did not receive a timely response)izHTTP Version Not SupportedzCannot fulfill request)izVariant Also Negotiates)izInsufficient Storage)iz Loop Detected)iz Not Extended)izNetwork Authentication Requiredz7The client needs to authenticate to gain network accessN))I__name__ __module__ __qualname____doc__r propertyrrr"r%r(CONTINUESWITCHING_PROTOCOLS PROCESSING EARLY_HINTSr.CREATEDACCEPTEDNON_AUTHORITATIVE_INFORMATION NO_CONTENT RESET_CONTENTPARTIAL_CONTENT MULTI_STATUSALREADY_REPORTEDIM_USEDMULTIPLE_CHOICESMOVED_PERMANENTLYFOUND SEE_OTHER NOT_MODIFIED USE_PROXYTEMPORARY_REDIRECTPERMANENT_REDIRECT BAD_REQUEST UNAUTHORIZEDPAYMENT_REQUIRED FORBIDDEN NOT_FOUNDMETHOD_NOT_ALLOWEDNOT_ACCEPTABLEPROXY_AUTHENTICATION_REQUIREDREQUEST_TIMEOUTCONFLICTGONELENGTH_REQUIREDPRECONDITION_FAILEDREQUEST_ENTITY_TOO_LARGEREQUEST_URI_TOO_LONGUNSUPPORTED_MEDIA_TYPEREQUESTED_RANGE_NOT_SATISFIABLEEXPECTATION_FAILED IM_A_TEAPOTMISDIRECTED_REQUESTUNPROCESSABLE_ENTITYLOCKEDFAILED_DEPENDENCY TOO_EARLYUPGRADE_REQUIREDPRECONDITION_REQUIREDTOO_MANY_REQUESTSREQUEST_HEADER_FIELDS_TOO_LARGEUNAVAILABLE_FOR_LEGAL_REASONSINTERNAL_SERVER_ERRORNOT_IMPLEMENTED BAD_GATEWAYSERVICE_UNAVAILABLEGATEWAY_TIMEOUTHTTP_VERSION_NOT_SUPPORTEDVARIANT_ALSO_NEGOTIATESINSUFFICIENT_STORAGE LOOP_DETECTED NOT_EXTENDEDNETWORK_AUTHENTICATION_REQUIREDrrrrrs $""""""""""DH>"J$K :B=G;H%I!HJNMGO&L.G84 DEKI5LLI444K6L.) __class__rC_name_rs r__repr__zHTTPMethod.__repr__s NN33T[[AAr)CONNECTz%Establish a connection to the server.)DELETEzRemove the target.)GETzRetrieve the target.)HEADzBSame as GET, but only retrieve the status line and header section.)OPTIONSz2Describe the communication options for the target.)PATCHz(Apply partial modifications to a target.)POSTzPerform a message loop-back test along the path to the target.N)rCrDrErFr rrrrrrrrrrrrrrrsB BAG +F 'C WDMG ?E QD ?C UErN)enumrrr__all__rrrrrrs[//  &gdCdCdCNgVVVr__pycache__/cookiejar.cpython-312.pyc000064400000237012152527315050013437 0ustar00 {|j~.jdZgdZddlZddlZddlZddlZddlZddlZddl Zddl Z ddl Z ddlmZdZdadZdZdZee j,j.Zej2d Zd Zd Zd Zd ZdZgdZ gdZ!e!Dcgc]}|jEc}Z#dKdZ$dKdZ%dddddZ&ej2dejNZ(dZ)dZ*ej2dejNZ+ej2dejXejNzZ-ej2dej\ejNzZ/dZ0ej2dej\ejNzZ1dZ2dZ3ej2dZ4ej2dZ5ej2d Z6ej2d!Z7d"Z8ej2d#Z9d$Z:d%Z;d&Z<ej2d'ejNZ=d(Z>d)Z?d*Z@d+ZAej2d,ejNZBd-ZCd.ZDd/ZEd0ZFd1ZGej2d2ZHd3ZId4ZJd5ZKd6ZLGd7d8ZMGd9d:ZNGd;dd?ZQGd@dAZRGdBdCeSZTGdDdEeRZUdFZVGdGdHeUZWGdIdJeUZXycc}w)LaHTTP 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 CookiePolicyDefaultCookiePolicy FileCookieJar LWPCookieJar LoadErrorMozillaCookieJarN)timegmFcjtsytsddl}|jdatj|S)Nr zhttp.cookiejar)debugloggerlogging getLogger)argsrs '/usr/lib64/python3.12/http/cookiejar.py_debugr,s.  ""#34 << HTTPOnlyz #HttpOnly_z#( Netscape)? HTTP Cookie FilezQa filename was not supplied (nor was the CookieJar instance initialised with one)zr# Netscape HTTP Cookie File # http://curl.haxx.se/rfc/cookie_spec.html # This is a generated file! Do not edit. cddl}ddl}ddl}|j}|j d||j }|j d|zdy)Nr zhttp.cookiejar bug! %s) stacklevel)iowarnings tracebackStringIO print_excgetvaluewarn)rrrfmsgs r_warn_unhandled_exceptionr"BsF#" A a **,C MM+c1aM@ric|dd\}}}}}}|tk\rPd|cxkrdkrEnyd|cxkrdkr7nyd|cxkrdkr)nyd|cxkrdkrnyd|cxkrdkr t|Syy) N r ;=) EPOCH_YEARr )ttyearmonthmdayhourminsecs r_timegmr3Qs(*2A%D%tS#  !u"2"2 :;db db !C~2~56NNbz5Cr)MonTueWedThuFriSatSun) JanFebMarAprMayJunJulAugSepOctNovDeccP|/tjjtj}n/tjj|tj}d|j|j |j |j|j|jfzS)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 tzz%04d-%02d-%02d %02d:%02d:%02dZ) datetimenowUTC fromtimestampr-r.dayr0minutesecondtdts r time2isozrT^s y    " "hll " 3    , ,Q8<< , @ + 266277BIIryy/B BBrc|/tjjtj}n/tjj|tj}dt|j |j t|jdz |j|j|j|jfzS)zReturn 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 rHz#%s, %02d-%s-%04d %02d:%02d:%02d GMTr%) rJrKrLrMDAYSweekdayrNMONTHSr.r-r0rOrPrQs r time2netscaperYqs y    " "hll " 3    , ,Q8<< , @ 0 RZZ\BFFF288A:$6 "))RYY40 00r)GMTrLUTZz^([-+])?(\d\d?):?(\d\d)?$cd}|tvrd}|Stj|}|redt|j dz}|j dr |dt|j dzz}|j ddk(r| }|S)Nr ir<r%-) UTC_ZONES TIMEZONE_REsearchintgroup)rIoffsetms roffset_from_tz_stringrhs F Y M   r " C O+Fwwqz"s1771:"66wwqzS   Mrc t|}|tjkDry tj |j dz}|d}|d}|d}t|}t|}t|}t|}|dkr\tjtjd}|dz} |} ||z| z }| | z } t| dkDr| dkDr|dz}n|dz }t|||||||f} | '|d}|j}t|} | y| | z } | S#t $r5 t|}n#t $rYYywxYwd|cxkrdkrnYy|}nYyYwxYw)Nr%r&r id2rL) rdrJMAXYEAR MONTHS_LOWERindexlower ValueErrortime localtimeabsr3upperrh) rNmonyrhrr1r2rIimoncur_yrrgtmprRrfs r _str2timer{s RB H     -a/ z2 {!C {!C c(C RB c(C c(C Dy ,Q/ SL &[1_ G q6B;1u28bCx" S#r3R01A} :B XXZ&r* > J H[   s8D   ??C  s;&D E' D32E3 E<E?EEEEzV^[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* )?$c .tj|}|r|j}tj |dj dz}t |d|t |dt |dt |dt|df}t|S|j}tjd|d}dgd z\}}}}}} } tj|}||j\}}}}}} } nyt|||||| | S) aReturns 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. r%rr r^N)STRICT_DATE_RErcgroupsrmrnrordfloatr3lstrip WEEKDAY_REsubLOOSE_HTTP_DATE_REr{) textrggrur,rNrvrwr1r2rIs r http2timers< d#A HHJ  1.2!A$ic!A$i!A$iQqTE!A$K1r{ ;;=D >>"dA &D'+VAX"Cb"c3 !!$'A})*&S"b#sB S#r2sC 44ra^ (\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 |j}dgdz\}}}}}}}tj|}||j\}}}}}}}} nyt |||||||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 Nr)r ISO_DATE_RErcrr{) rrNrurvrwr1r2rIrg_s riso2timer2sz ;;=D'+VAX"Cb"c3 4 A}-.HHJ)Cb#sB S#r2sC 44rch|jd\}}|jd||j|dzS)z)Return unmatched part of re.Match object.r N)spanstring)matchstartends r unmatchedrSs4AJE3 <<  ST 2 22rz^\s*([^=\s;,]+)z&^\s*=\s*\"([^\"\\]*(?:\\.[^\"\\]*)*)\"z^\s*=\s*([^\s;,]*)z\\(.)c t|trJg}|D]s}|}g}|rTtj|}|rt |}|j d}t j|}|r3t |}|j d}tjd|}nFtj|}|r-t |}|j d}|j}nd}|j||fny|jjdr)|jdd}|r|j|g}n1tjdd|\}} | dkDsJd|d |d ||}|rT|sc|j|v|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* separators = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT quoted-string = ( <"> *(qdtext | quoted-pair ) <"> ) qdtext = > 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"')]] r%z\1N,z^[=\s;]*rr zsplit_header_words bug: 'z', 'z', ) isinstancestrHEADER_TOKEN_RErcrreHEADER_QUOTED_VALUE_REHEADER_ESCAPE_RErHEADER_VALUE_RErstripappendr startswithresubn) header_valuesresultr orig_textpairsrgnamevaluenon_junk nr_junk_charss rsplit_header_wordsr\syZ--- - F &&t,A |wwqz*11$7$QE'..t4A(| !  % !% dE]+))#.{{}QR(&--.+-''+r4*H'-$q(.e-.( ?@ &--&GH Mr([\"\\])c*g}|D]|}g}|D]P\}}|8tjd|stjd|}d|z}|d|}|j |R|s]|j dj |~dj |S)aDo 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"' z^\w+$\\\1z"%s"=; , )rrcHEADER_JOIN_ESCAPE_RErrjoin)listsheadersrattrkvs rjoin_header_wordsrsGDAq}yy1--11'1=A A !$ KKN   $0 99W rc^|jdr|dd}|jdr|dd}|S)N"r%)rendswithrs r strip_quotesrs5 sABx }}SCRy Krcd}g}|D]}g}d}t|jdD]\}}|j}|jd\}} } |j}|s|dk(rnuE| r| jnd} |dk7rF|j } | |vr| }|dk(r| t | } d}n|d k(r| t t | } |j|| f|s|s|jd |j||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. )expiresdomainpathsecureversionportmax-ageF;rr NrTr)r0) enumeratesplitstrip partitionrorrr) ns_headers known_attrsr ns_headerr version_setiiparamkeysepvallcs rparse_ns_headersrs1KF  #9??3#78IBKKME!OOC0MCc))+C7"%#))+$CQwYY[$C)#*3/"&KI%' S(9: LL#s $=9@  -. MM% W Z Mrz\.\d+$c^tj|ry|dk(ry|ddk(s|ddk(ryy)z*Return True if text is a host domain name.Frr .rTIPV4_RErcrs ris_HDNrs8~~d rz Aw#~bS rc|j}|j}||k(ryt|sy|j|}|dk(s|dk(ry|jdsyt|ddsyy)aReturn 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 rr%N)rorrfindr)ABis r domain_matchr&sm.  A  AAv !9  ABw!q& <<  !AB%= rc0tj|ryy)zdReturn True if text is a sort-of-like a host domain name. For accepting/blocking domains. FTrrs rliberal_is_HDNrMs ~~d rc|j}|j}t|r t|s||k(ryy|jd}|r|j|ry|s||k(ryy)z\For blocking/accepting domains. A and B may be host domain names or IP addresses. TFr)rorrr)rr initial_dots ruser_domain_matchrWsc  A  A 1 ."3 6,,s#Kqzz!} 16 rz:\d+$c|j}tjj|d}|dk(r|j dd}t j d|d}|jS)zReturn request-host, as defined by RFC 2965. Variation from RFC: returned value is lowercased, for convenient comparison. r%rHost) get_full_urlurllibparseurlparse get_header cut_port_rerro)requesturlhosts r request_hostrlsd    C <<  %a (D rz!!&"- ??2tQ 'D ::<rc6t|x}}d|vr|dz}||fS)zzReturn a tuple (request-host, effective request-host name). As defined by RFC 2965, except both are lowercased. r.local)r)rerhnreq_hosts reff_request_hostr|s/ #7++D8 ((" T>rc|j}tjj|}t |j }|j dsd|z}|S)z6Path component of request-URI, as defined by RFC 2965./)rrrurlsplit escape_pathrr)rrpartsrs r request_pathrsL    C LL ! !# &E uzz "D ??3 Tz Krc|j}|jd}|dk\r||dzd} t||St }|S#t$rt d|YywxYw)N:r r%znonnumeric port: '%s')rfindrdrprDEFAULT_HTTP_PORT)rrrrs r request_portrsl <>> reach("www.acme.com") '.acme.com' >>> reach("acme.com") 'acme.com' >>> reach("acme.local") '.local' rr r%Nlocal)rr)hrbs rreachrsU4 s AAv acdG FF3K !9!q&ALq5L HrcZt|}t|t|jsyy)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. TF)rrrorigin_req_host)rrs ris_third_partyrs)G$H %(?(?"@ ArcBeZdZdZ d dZdZd dZdZd dZdZ d Z y) raHTTP 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. c| t|}| tt| } ||dur td||_||_||_||_||_|j|_ ||_ ||_ | |_ | |_ | |_| |_| |_||_||_||_t)j(||_y)NTz-if port is None, port_specified must be false)rdrrprrrrport_specifiedrordomain_specifieddomain_initial_dotrpath_specifiedrrdiscardcomment comment_urlrfc2109copy_rest)selfrrrrrrrrrrrrrrrrestrs r__init__zCookie.__init__s  #g,  #eGn*= rc|jd}nd|jz}|j|z|jz}|j|jd|j}n |j}d|d|dS)Nrrrz)rrrrr)rplimit namevalues r__str__zCookie.__str__0sd 99 "adii-a a$))+ :: !#'99djj9I I'0%88rc\g}dD]-}t||}|j|dt|/|jdt|jz|jdt|jz|j j ddj|dS)N)rrrrrrrrrrrrrrrrzrest=%sz rfc2109=%s(r))getattrrreprrr __class____name__r)rrrrs r__repr__zCookie.__repr__:sD 4&D KK4d4 5 ITZZ 001 L4 #556>>22DIIdODDr)Fr#) r; __module__ __qualname____doc__r!r%r)r+r.r4r<rrrrs16(%T"-! 9 Errc(eZdZdZdZdZdZdZy)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. ct)zReturn 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. NotImplementedErrorrcookiers rset_okzCookiePolicy.set_okRs "##rct)zAReturn true if (and only if) cookie should be returned to server.rCrEs r return_okzCookiePolicy.return_ok[ !##rcy)zMReturn false if cookies should not be returned, given cookie domain. Tr@)rrrs rdomain_return_okzCookiePolicy.domain_return_ok_rcy)zKReturn false if cookies should not be returned, given cookie path. Tr@)rrrs rpath_return_okzCookiePolicy.path_return_okdrMrN)r;r=r>r?rGrIrLrOr@rrrrIs$$ rrc eZdZdZdZdZdZdZeezZdddddddddeddd f d Z d Z d Z d Z dZ dZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZdZd Zy)!rzBImplements the standard rules for accepting and returning cookies.r%rr}r NTF)httpswssc||_||_||_||_||_||_| |_| |_| |_| |_ | |_ |t||_ nd|_ | t|}||_ y)zAConstructor arguments should be passed as keyword arguments only.Nr@)netscaperfc2965rfc2109_as_netscape hide_cookie2 strict_domainstrict_rfc2965_unverifiablestrict_ns_unverifiablestrict_ns_domainstrict_ns_set_initial_dollarstrict_ns_set_pathsecure_protocolstuple_blocked_domains_allowed_domains)rblocked_domainsallowed_domainsrTrUrVrWrXrYrZr[r\r]r^s rr!zDefaultCookiePolicy.__init__ts!  #6 (*+F(&<# 0,H)"4 0  &$)/$:D !$&D !  &#O4O /rc|jS)z4Return the sequence of blocked domains (as a tuple).)r`rs rrbz#DefaultCookiePolicy.blocked_domains$$$rc$t||_y)z$Set the sequence of blocked domains.N)r_r`)rrbs rset_blocked_domainsz'DefaultCookiePolicy.set_blocked_domainss %o 6rcB|jD]}t||syyr-)r`r)rrblocked_domains r is_blockedzDefaultCookiePolicy.is_blockeds$"33N 84rc|jS)z=Return None, or the sequence of allowed domains (as a tuple).)rares rrcz#DefaultCookiePolicy.allowed_domainsrfrc,| t|}||_y)z-Set the sequence of allowed domains, or None.N)r_ra)rrcs rset_allowed_domainsz'DefaultCookiePolicy.set_allowed_domainss  &#O4O /rc\|jy|jD]}t||syy)NFT)rar)rrallowed_domains ris_not_allowedz"DefaultCookiePolicy.is_not_alloweds3  ("33N 84rctd|j|j|jJdD]}d|z}t||}|||ryy)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 verifiabilityrrrrset_ok_FTrrrr8rrFrnfn_namefns rrGzDefaultCookiePolicy.set_oks[ )6;; E{{&&&MAkGw'Bfg& N rc|j"td|j|jy|jdkDr|js tdy|jdk(r|j s tdyy)Nz0 Set-Cookie2 without version attribute (%s=%s)Fr $ RFC 2965 cookies are switched off$ Netscape cookies are switched offT)rrrrrUrTrEs rset_ok_versionz"DefaultCookiePolicy.set_ok_versionsh >> ! E;;  . >>A dll 9 : ^^q  9 :rc|jrYt|rN|jdkDr|jr t dy|jdk(r|j r t dyyNr z> third-party RFC 2965 cookie during unverifiable transactionFz> third-party Netscape cookie during unverifiable transactionT unverifiablerrrYrrZrEs rset_ok_verifiabilityz(DefaultCookiePolicy.set_ok_verifiabilitys]   N7$;~~!d&F&F891$)D)D89rc|jdk(r>|jr2|jjdrt d|jyy)Nr $z' illegal name (starts with '$'): '%s'FT)rr\rrrrEs r set_ok_namezDefaultCookiePolicy.set_ok_names? NNa D$E$E KK " "3 ' >A dll 9 : ^^q  9 :rc|jrYt|rN|jdkDr|jr t dy|jdk(r|j r t dyyrrrEs rreturn_ok_verifiabilityz+DefaultCookiePolicy.return_ok_verifiabilitycs]   N7$;~~!d&F&F%&1$)D)D%&rcd|jr$|j|jvr tdyy)Nz( secure cookie with non-secure requestFT)rtyper^rrEs rreturn_ok_securez$DefaultCookiePolicy.return_ok_secureos) ==W\\1F1FF = >rcR|j|jr tdyy)Nz cookie expiredFT)r._nowrrEs rreturn_ok_expiresz%DefaultCookiePolicy.return_ok_expiresus#   TYY ' & 'rc|jrNt|}|d}|jjdD] }||k(s ytd||jyy)Nrrz0 request port %s does not match cookie port %sFT)rrrrrs rreturn_ok_portz"DefaultCookiePolicy.return_ok_port{sb ;;#G,H[[&&s+= ,I.rct|\}}|j}|r|jdsd|z}n|}|jdk(r6|j|j zr|j s||k7r tdy|jdkDrt||std||y|jdk(r"d|zj|std||yy)Nrr 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) rrrrr[DomainStrictNonDomainrrrr)rrFrrrr dotdomains rreturn_ok_domainz$DefaultCookiePolicy.return_ok_domains)'2$ &++C0f II NNa   " "T%?%? ?''FdN - . >>A l4&@ /04f > >>Q D':':9'E !6 +rclt|\}}|jdsd|z}|jdsd|z}|r|jdsd|z}n|}|j|s|j|sy|j|r t d|y|j |r t d|yy)NrFrrT)rrrrkrrq)rrrrrrs rrLz$DefaultCookiePolicy.domain_return_oks*'2$""3'8|Hs#t8D &++C0f II!!), i0H ??6 " 7 @   v & ;V Drctd|t|}t|}||k(ry|j|r|j ds |||dzdk(rytd||y)Nz- checking cookie path=%sTrr%z %s does not path-match %sF)rrrrr)rrrrpathlens rrOz"DefaultCookiePolicy.path_return_oksj*D1(d) t !!$'}}S!Xggai%@C%G,h=r) r;r=r>r?rrr DomainLiberal DomainStrictr!rbrhrkrcrnrqrGr~rrrrrrIrrrrrrrLrOr@rrrrjsLM%&;;L"&t%)#$-1(-"/.3$)"2!0F%7 %0 &   :x*$   64 rrc#Kt|jD]-}d} |jd}t|Ed{|r*|/y7#t$rYwxYww)z)Iterates over nested mapping, depth-firstFTN)listvaluesitems deepvaluesAttributeError)mappingobjs rrrsaGNN$% ' IIG!# & &I& '    s7A AAA AA AAAAc eZdZy)AbsentNr;r=r>r@rrrrrrceZdZdZej dZej dZej dZej dZ ej dZ ej dejZ dd Z d Zd Zd Zd ZdZdZdZdZdZdZdZdZdZddZdZdZdZdZdZ dZ!y) rzCollection of HTTP cookies. You may not need to know about this class: try urllib.request.build_opener(HTTPCookieProcessor).open(url). z\Wrz\.?[^.]*z[^.]*z^\.+z^\#LWP-Cookies-(\d+\.\d+)Ncj| t}||_tj|_i|_yr#)r_policy _threadingRLock _cookies_lock_cookiesrpolicys rr!zCookieJar.__init__s. >(*F '--/ rc||_yr#)rrs r set_policyzCookieJar.set_policys  rcg}|jj||sgStd||j|}|j D]}}|jj ||s ||}|j D]F}|jj||s td+td|j|H|S)Nz!Checking %s for cookies to returnz not returning cookiez it's a match) rrLrrkeysrOrrIr)rrrcookiescookies_by_pathrcookies_by_namerFs r_cookies_for_domainzCookieJar._cookies_for_domains||,,VW=I2F;--/#((*D<<..tW=-d3O)002||--fg>45()v& 3 +rcg}|jjD]#}|j|j||%|S)z2Return a list of cookies to be returned to server.)rrextendr)rrrrs r_cookies_for_requestzCookieJar._cookies_for_request s<mm((*F NN433FGD E+rc|jddd}g}|D]}|j}|sd}|dkDr|jd|z|jQ|jj |jr,|dkDr'|j jd|j}n |j}|j|j|jn |j|jd ||dkDs|jr|jd |jz|jjd rB|j}|js|jd r|d d}|jd |z|jyd}|jr|d|jzz}|j||S)zReturn 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). c,t|jSr#)rr)as rz)CookieJar._cookie_attrs..s 3qvv;rT)rreverseFr z $Version=%sNrrz $Path="%s"rr%z $Domain="%s"z$Portz="%s")sortrrr non_word_rercquote_rerrrrrrrrr) rrrattrsrFrrrr1s r _cookie_attrszCookieJar._cookie_attrss  . = FnnG" Q;LL!89 )  '' 5'A+ ))'6<<@ ||# V[[)  U;<{((LL !;<==++C0#]]F"55))#.!'LL&!89;;*A,,6;;!67LLOQT rctd|jj tt jx|j _|_|j|}|j|}|r2|jds!|jddj||j jrQ|j js;|jds*|D]%}|jdk7s|jddn|jj|j!y#|jjwxYw)zAdd correct Cookie: header to request (urllib.request.Request object). The Cookie2 header is also added unless policy.hide_cookie2 is true. add_cookie_headerrrCookie2r%z $Version="1"N)rracquirerdrqrrrr has_headeradd_unredirected_headerrrUrWrreleaseclear_expired_cookies)rrrrrFs rrzCookieJar.add_cookie_headerLs "# ""$ ),/ ,< R&    & & ( ""$    & & (sCEEEc(g}d}d}|D]}|d\}}d}d} i} i} |ddD]\} } | j}||vs||vr|} | |vr| d} | | vr-| dk(r!| td d} nw| j} | d k(r|r[| td i| d k(rd} t| } d } |j| z} | |vs| |vr| | dvrtd| zd} n | | | <| | | <| r|j ||| | f|S#t$rtd d} Y5wxYw)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. )rr)rrrrrrr commenturlr Fr%NTrz% missing value for domain attributerzM missing or invalid value for expires attribute: treating as session cookierz? missing or invalid (non-numeric) value for max-age attribute)rrrz! missing value for %s attribute)rorrdrprr)r attrs_set cookie_tuples boolean_attrs value_attrs cookie_attrsrr max_age_set bad_cookiestandardr rrrs r_normalized_cookie_tuplesz#CookieJar._normalized_cookie_tuplesms + 0 &L&q/KD% KJHD$QR(1WWY$m(;A %!)A==yFG%)  A >" y FG  >"&KF"A A A$!}*< !BBBQFG%) "#HQKDGe)h  $x!> ?Q&T5& 23%)  s C77DDcR|\}}}}|jdt}|jdt}|jdt} |jdt} |jdd} | t| } |jdd} |jdd} |jd d}|jd d}|tur|d k7rd }t |}nFd}t |}|j d }|dk7r| dk(r|d|}n|d|dz}t|dk(rd }|tu}d}|rt|jd}|turt|\}}|}n|jdsd|z}d}| tur(| t|} nd }tjdd | } nd} | turd} d } n2| |jkr# |j|||t#d|||yt%| ||| ||||||| | | |||S#t$rYywxYw#t $rYCwxYw)NrrrrrrFrrrrTrrr r%rz\s+z2Expiring cookie, domain='%s', path='%s', name='%s')r'rrdrprrrrboolrrrrrrclearKeyErrorrr)rtuprrrrr rrrrrrrrrrrrrrrrs r_cookie_from_cookie_tuplez#CookieJar._cookie_from_cookie_tuplesv'*#eXth/||FF+||FF+,,y&1,,y$/   g,h.,,y%0,,y$/ll<6  v $"*!Nt$D"N(D 3ABwa<8D1:D4yA~ct"/" !%f&7&7&.no_matching_rfc2965ls'#**INNINNJCf,,r)rget_allrdrqrrrUrTr r Exceptionr"rrrrrfilterr) rresponserr rfc2965_hdrsns_hdrsrUrTr ns_cookiesrrFrs r make_cookieszCookieJar.make_cookies?sp--/}b9 //,3(+DIIK(88 DI,,&&<<((gh'I 22"<0';G x !99$W-w8  ) )* 5%FHLFFMM6;; DE&;A-$$7D z*C  % 'G  )+  s$'E E% E"!E"%E=<E=cl|jj ttjx|j_|_|jj ||r|j||jjy#|jjwxYw)z-Set a cookie if policy says it's OK to do so.N) rrrdrqrrrG set_cookierrEs rset_cookie_if_okzCookieJar.set_cookie_if_okvs~ ""$ ),/ ,<  |jjy#|jjwxYw)zAExtract cookies from response, where allowable given the request.zextract_cookies: %sz setting cookie: %sN) rrrrrrrGrr)rrrrFs rextract_cookieszCookieJar.extract_cookiess$hmmo6 ""$ )++Hg><<&&vw70&9OOF+?    & & (D   & & (s1B#(B##B?c|#|| td|j|||=y|| td|j||=y||j|=yi|_y)aClear 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)rpr)rrrrs rrzCookieJar.clears  DL NPP f%d+D1  ~ DFF f%d+   f%DMrc8|jj |D]@}|js|j|j|j |j B |jjy#|jjwxYw)zDiscard 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)rrrrrrrr)rrFs rclear_session_cookieszCookieJar.clear_session_cookiesso ""$ )>>JJv}}fkk6;;G    & & (D   & & (sA=3A==Bcj|jj tj}|D]E}|j|s|j |j |j |jG |jjy#|jjwxYw)aDiscard 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) rrrqr.rrrrr)rrKrFs rrzCookieJar.clear_expired_cookiess ""$ )))+C$$S)JJv}}fkk6;;G    & & (D   & & (s*B3BB2c,t|jSr#)rrres r__iter__zCookieJar.__iter__s$--((rc"d}|D]}|dz} |S)z#Return number of contained cookies.r r%r@)rrrFs r__len__zCookieJar.__len__s FAAdrcg}|D]}|jt|d|jjddj |dSN<[rz]>)rr9r:r;rrrrFs rr<zCookieJar.__repr__s: FAHHT&\2d!^^44diilCCrcg}|D]}|jt|d|jjddj |dSr.)rrr:r;rr1s rr4zCookieJar.__str__s: FAHHS[1d!^^44diilCCrr#)NNN)"r;r=r>r?rcompilerrstrict_domain_re domain_redots_reASCIImagic_rer!rrrrrrr r rrrrr$rr'rr*r,r<r4r@rrrrs "**U#Krzz+&H!rzz+. 8$Ibjj!Grzz6AH$9v%B_BZx '5n ) ) )6 ))&) D Drrc eZdZy)rNrr@rrrrrrrc4eZdZdZddZddZddZ ddZy) rz6CookieJar that can be loaded from and saved to a file.Nctj|||tj|}||_t ||_y)z} Cookies are NOT loaded from the named file until either the .load() or .revert() method is called. N)rr!osfspathfilenamer delayload)rr?r@rs rr!zFileCookieJar.__init__s: 4(  yy*H  irct)zSave cookies to a file.rC)rr?ignore_discardignore_expiress rsavezFileCookieJar.saverJrc|(|j |j}nttt|5}|j ||||dddy#1swYyxYw)zLoad cookies from a file.N)r?rpMISSING_FILENAME_TEXTopen _really_loadrr?rBrCr s rloadzFileCookieJar.loadsM  }}(T]]("#899 (^q   a>> J^^s AAc|(|j |j}ntt|jj  t j |j}i|_ |j||| |jjy#t$r ||_wxYw#|jjwxYw)zClear 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) r?rprFrrrdeepcopyrrJOSErrorr)rr?rBrC old_states rrevertzFileCookieJar.revert s  }}(T]]("#899 ""$ ) dmm4IDM  (NNC    & & (   )      & & (s&B1-BB..B11C )NFNNFF)r;r=r>r?r!rDrJrOr@rrrrs"@ )$K#49)rrc|j|jfd|jfd|jfg}|j|j d|jf|j r|j d|jr|j d|jr|j d|jr|j d|jr/|j dtt|jf|jr|j d |jr|j d |jf|jr|j d |jft!|j"j%}|D]+}|j |t'|j"|f-|j d t'|j(ft+|gS) zReturn string representation of Cookie in the LWP cookie file format. Actually, the format is extended a bit -- see module docstring. rrr) path_specN) port_specN) domain_dotN)rNr)rNrrr)rrrrrrrrrrrrTrrrrsortedrrrrr)rFr rrs rlwp_cookie_strrV's ++v|| $ &++  FMM " $A{{&&++)> ? ahh':; ahh':;   !((+?"@ }}ahh/0 ~~qxx(v~~)>?!AB ~~qxx 12 ~~qxxFNN ;< 188\63E3E$FG &,,##% &D  !Sa)*+HHiV^^, -. aS !!rc&eZdZdZddZddZdZy)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) ctj}g}|D]B}|s |jr|s|j|r&|jdt |zDdj |dgzS)zReturn cookies as a string of "\n"-separated "Set-Cookie3" headers. ignore_discard and ignore_expires: see docstring for FileCookieJar.save zSet-Cookie3: %s r)rqrr.rrVr)rrBrCrKr2rFs r as_lwp_strzLWPCookieJar.as_lwp_strPsk iik F!fnn!f&7&7&< HH&)?? @  yyB4  rNc|(|j |j}ntttjtj |tj tjztjzdd5}|jd|j|j||dddy#1swYyxYw)Nwz#LWP-Cookies-2.0 ) r?rprFr=fdopenrGO_CREATO_WRONLYO_TRUNCwriterZrIs rrDzLWPCookieJar.save`s  }}(T]]("#899 YY GGHbjj2;;6CU K   GG( ) GGDOONNC D   s 3CC cJ|j}|jj|sd|z}t|t j}d}d} d} |jx} dk7r| j |s(| t |dj} t| gD]0} | d\} }i}i}| D]}d||< | ddD]A\}}||j}nd}|| vs|| vr|}|| vr |d }|||<3|| vr|||<=|||<C|j}|d }|d }| t|}|d }|d }|j d }t|d| ||d|d|||d|d|d|d|||d|d|}|s|jr |s|j|r |j|3|jx} dk7ryy#t $rt"$rt%td|d wxYw)Nz5%r does not look like a Set-Cookie3 (LWP) format filez Set-Cookie3:)rSrRrTrr)rrrrrrrrr Fr%TrrrrrrrSrTrrRrrrz invalid Set-Cookie3 format file : )readliner9rcrrqrrrrror'rrrr.rrMrr")rr r?rBrCmagicr!rKheaderrrlinedatarrrr rrrr rrrrr s rrHzLWPCookieJar._really_loadosf }}##E*$%CC. iik. 0 9 .::<'4B.v.CKL)//1.v6D"&q'KD%!HD*&+ + $QR1=!"B!%B+-23F "A - yd!*+HQK+-*+HQK&'DG!) ! A lG lG*"*7"3"&x[F'-'8'8'=$q|T5 y!K.%'7< y!K. {&& | # %A*aii )all3.? OOA&[7 ::<'4B.f   . % '%t-. . .s FG44.H")TTrP)r;r=r>r?rZrDrHr@rrrrCs ! EJ.rrceZdZdZdZddZy)r a 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. curl and lynx use 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). ctj}tj|jst d|z |jx}dk7r2i}|j t rd|t<|tt d}|jdr|dd}|jj ds|jdk(r|jd\}} } } } } }| dk(} | dk(} | dk(r|} d}|j d}| |k(sJd }| dk(rd} d }td | |dd || || d | | |dd|}|s|jr |s|j|r|j||jx}dk7r1yy#t $rt"$rt%t d |d wxYw)Nz4%r does not look like a Netscape format cookies filerrYr)#r TRUErFTr z%invalid Netscape format cookies file rd)rqNETSCAPE_MAGIC_RGXrrerrHTTPONLY_PREFIX HTTPONLY_ATTRrrrrrrr.rrMrr")rr r?rBrCrKrhr rrrrrrrrrr s rrHzMozillaCookieJar._really_loadsiik!'' 5F < .::<'4B. ???3*,D'O 4 56D==&tCRyJJL++J7JJLB& 4(M($u F*$4$> 2:!D E$//4 ';666b="G"G1dE!#3[!"" !&!))%!,,s*;"i::<'4B.l   . % '%t-. . .s EF.F>Nc |(|j |j}ntttjtj |tj tjztjzdd5}|jttj}|D]}|j}|s |jr|s|j|r3|jrd}nd}|j!drd} nd} |j"t%|j"} nd} |j&d} |j(} n|j(} |j&} |j+t,r t.|z}|jdj1|| |j2|| | | gdz dddy#1swYyxYw) Nr\r]rnFALSErrrmrY)r?rprFr=r^rGr_r`rarbNETSCAPE_HEADER_TEXTrqrrr.rrrrrrr%rqrprr) rr?rBrCr rKrFrrrrrrs rrDzMozillaCookieJar.save"sz  }}(T]]("#899 YY GGHbjj2;;6CU K   GG( )))+C%&..%&*;*;C*@==6&&f$$S);$+k>>-!&..1G G<<'D"KKE!;;D"LLE..}=,v5FIIv{FKK%we=>3    s D2GG rP)r;r=r>r?rHrDr@rrr r s>D.L'rr r#)Yr?__all__r=rrJrrq urllib.parserurllib.request threadingr http.clienthttpcalendarr r rrrqrprclient HTTP_PORTrr4rorFrtr"r+r3rVrXrormrTrYrar8rbrhr{rIrXrrrrrrrrrrrrrrrrrrrrrrrrr r rrrrrrrrrrrMrrrVrr )r.s0rrs6 M  #    --.RZZ @A:A 9 4+126% 62 B&0(T = bjj5rxx@  6 p,-/XX7RZZ2BDD288OE RZZ & DD288O)*65pbjj 44")) # $5B3 $$67#$MN#$9:2::h'Sj# ;/2AH "**Y ) %N(bjj288,    $"**9:+ ! F"_E_EDB_,_B "LDLD`4)I4)n"8v.=v.rM}MA;3sJ0__pycache__/client.cpython-312.pyc000064400000162656152527315050012762 0ustar00 {|jjdZddlZddlZddlZddlZddlZddlZddlZddl Z ddl Z ddl m Z gdZdZdZdZdZd Zd Zej-ej.j0ej.j0j3Dcic]}||j4c}Zd Zd Zd Zd Zej@djBZ"ej@djFZ$ej@dZ%ej@dZ&hdZ'd?dZ(de)de)fdZ*GddejVjXZ-dZ.e-fdZ/e-fdZ0GddejbZ2dZ3Gdd Z4 ddl5Z5Gd!d"e4Z6ejod"Gd#d$e9Z:Gd%d&e:Z;Gd'd(e:Z<Gd)d*e:Z=Gd+d,e:Z>Gd-d.e:Z?Gd/d0e:Z@Gd1d2e:ZAGd3d4eAZBGd5d6eAZCGd7d8eAZDGd9d:e:ZEGd;deGeEZHe:ZIycc}w#e8$rYwxYw)@a HTTP/1.1 client library 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 Req-started-unread-response _CS_REQ_STARTED Req-sent-unread-response _CS_REQ_SENT N)urlsplit) HTTPResponseHTTPConnection HTTPException NotConnectedUnknownProtocolUnknownTransferEncodingUnimplementedFileModeIncompleteRead InvalidURLImproperConnectionStateCannotSendRequestCannotSendHeaderResponseNotReady BadStatusLine LineTooLongRemoteDisconnectederror responsesPiUNKNOWNIdlezRequest-startedz Request-sentidis[^:\s][^:\r\n]*s\n(?![ \t])|\r(?![ \t\n])z[- ]z[-]>PUTPOSTPATCHc  |jdS#t$rl}t|j|j|j|j |j d||j|j dd|ddd}~wwxYw)zdk(rd|_|j2s"|j,s|j4d |_yyyy#t8$r d|_YvwxYw)Nrzheaders:got more than z interim responses)zHTTP/1.0zHTTP/0.9 zHTTP/1. header:r:transfer-encodingrnTFcontent-lengthrHEAD) rSrange_MAXINTERIMRESPONSESrCONTINUErTrRrgrzrcoderlstriprmrkr2rrbriitemsgetr<rnro _check_closerqrprr} NO_CONTENT NOT_MODIFIEDrh) rAr4rkrlrmskipped_headershdrvaltr_encrps r)beginzHTTPResponse.beginPs< << # +,A&*&7&7&9 #GVV!+DGG4O"j/2-  !5 66HIK K#)( DKlln . .DL    *DL!'* *"/"88 tx ??Q  LL..0SisC01!!"56 flln 1DL"DO DL++- !!"23 $,, '!&k ;;?"&DKDK j Fl$: 6 C  LLF "DK  KK "DO  # #"  #sII+*I+cF|jjd}|jdk(r|rd|jvryy|jjdry|rd|jvry|jjd}|rd|jvryy)N connectionrcloseTFz keep-alivezproxy-connection)rSrrkr<)rAconnpconns r)rzHTTPResponse._check_closes|| - <<2 4::</ <<  L ) LDJJL0   !34 \U[[]2r6cJ|j}d|_|jyN)rRr)rArRs r)r~zHTTPResponse._close_conns WW  r6c t||jr|jyy#|jr|jwwxYwr)superrrRr~rA __class__s r)rzHTTPResponse.closesB # GMOww  "tww  "s /Acpt||jr|jjyyr)rflushrRrs r)rzHTTPResponse.flushs%   77 GGMMO r6cy)zAlways returns TrueTrJrAs r)readablezHTTPResponse.readablesr6c|jduS)z!True if the connection is closed.N)rRrs r)isclosedzHTTPResponse.isclosedsww$r6c|jy|jdk(r|jy|jr|j |S||dk\r|j ||j kDr |j }|jj |}|s|r|j|S|j :|xj t|zc_|j s|j|S|j |jj }n# |j|j }d|_|j|S#t$r|jwxYw)z?Read and return the response body, or up to the next amt bytes.r6rr) rRrhr~rn _read_chunkedrpreadr= _safe_readr )rAamtss r)rzHTTPResponse.reads8 77? <<6 !     <<%%c* * ?sax{{&3+<kk S!A  " H ( s1v% {{$$&H{{"GGLLN 4A     H &$$&s EE)c|jy|jdk(r|jy|jr|j |S|j 0t ||j kDrt|d|j }|jj|}|s|r|j|S|j 1|xj |zc_|j s|j|S)z^Read up to len(b) bytes into bytearray b and return the number of bytes read. rr) rRrhr~rn_readinto_chunkedrpr= memoryviewreadinto)rAbrBs r)rzHTTPResponse.readintos 77? <<6 !     <<))!, , ;; "1v #qM!DKK0 GG  Q Q      [[ $ KK1 K;;  "r6c |jjtdz}t|tkDr t d|j d}|dk\r|d|} t |dS#t$r|jwxYw)Nr;z chunk size;r) rRrOrPr=rfindrr}r~)rArEis r)_read_next_chunk_sizez"HTTPResponse._read_next_chunk_size(sww1 - t9x l+ + IIdO 68D tR=         s  A((Bcd} |jjtdz}t|tkDr t d|sy|dvry|dz }|t kDrt dt di)Nrr;z trailer linerLrz trailers)rRrOrPr=rrQr)rA trailers_readrEs r)_read_and_discard_trailerz&HTTPResponse._read_and_discard_trailer8s 77##HqL1D4y8#!.11,, Q M{*#$[M;==!r6c|j}|sR||jd |j}|dk(r"|j |j d}||_|S#t$r t dwxYw)Nrwr6r)rorrr}r rr~)rAros r)_get_chunk_leftzHTTPResponse._get_chunk_leftOs __ %" *!779 Q..0  "! (DO *$S)) *s A##A8c|jtk7sJ||dkrd}g} |jx}s|0||kr+|j|j |||z |_nA|j|j ||||z}d|_|jx}sdj |S#t$r }tdj ||d}~wwxYwNrr6)rnrjrr@rrorXr )rArvalueroexcs r)rzHTTPResponse._read_chunkedgs||x''' ?sQwC ;!%!5!5!77:D?sj'8LL!56&03&6DO T__Z89?:%C"#"&!5!5!77:D88E? " ; %1s : ;sBB8'B88 C!CC!cf|jtk7sJd}t|} |j}||St ||kr |j |}||z |_||zS|d|}|j |}||d}||z }d|_j#t$rtt|d|wxYw)Nr) rnrjrrr=_safe_readintoror bytes)rAr total_bytesmvbrorBtemp_mvbs r)rzHTTPResponse._readinto_chunked{s||x''' m :!113 %&&s8z)++C0A&01nDO&?*{ +''1!"gq "#  : q;'7!89 9 :sB-B'(B!B0cTt|t}|jj|}t ||k\r|St ||krt ||t |z t j|}|jdd t|||z }|j|jj||j|k\r|jS||z }|j|kr+t |j||jz )a Read the number of bytes requested. This function should be used when 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. rrw) min_MIN_READ_BUF_SIZErRrr=r ioBytesIOseekwritetellgetvalue)rArcursizer&deltas r)rzHTTPResponse._safe_readsc-.ww||G$ t9 K t9w  sSY7 7zz$ !Qw/E JJtww||E* +yy{c!}}& u Gyy{W$$T]]_cDIIK6GHHr6ct|}|jj|}||krtt |d|||z |S)z2Same as _safe_read, but for reading into a buffer.N)r=rRrr r)rArrrBs r)rzHTTPResponse._safe_readintosF!f GG  Q  s7 q!us1u5 5r6c|j|jdk(ry|jr|j|S|j |dks||jkDr |j}|jj |}|s|r|j |S|j:|xjt|zc_|js|j |S)zvRead with at most one underlying system call. If at least one byte is buffered, return that instead. rr6r)rRrhrn_read1_chunkedrpread1r~r=)rArBresults r)rzHTTPResponse.read1s 77?dllf4 <<&&q) ) ;; "AT[[ Aq!!      [[ $ KK3v; &K;;  " r6c|j|jdk(ry|jr|j|S|jj |S)Nrr6)rRrhrn _peek_chunkedpeek)rArBs r)rzHTTPResponse.peeksE 77?dllf4 <<%%a( (ww||Ar6c|j|jdk(ry|jrt||S|j |dks||j kDr |j }|jj |}|s|r|j |S|j :|xj t|zc_|j s|j |S)Nrr6r)rRrhrnrrOrpr~r=)rAlimitrrs r)rOzHTTPResponse.readlines 77?dllf4 <<7#E* * ;; " UT[[5HKKE!!%(%      [[ $ KK3v; &K;;  " r6c|j}||dk(ryd|cxkr|ksn|}|jj|}|xjt |zc_|s t d|Sr)rrRrror=r )rArBrors r)rzHTTPResponse._read1_chunkedsj))+  aQ$*$Aww}}Q 3t9$ % % r6c |j}|y|jj|d|S#t$rYywxYw)Nr6)rr rRr)rArBros r)rzHTTPResponse._peek_chunkedsP --/J  ww||J' 44   s 3 ??c6|jjSr)rRfilenors r)rzHTTPResponse.filenosww~~r6c|j t|jj|xs|}t|ts t |ds|Sdj |S)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. __iter__z, )rSrget_all isinstanceryhasattrrX)rAr'defaultrSs r) getheaderzHTTPResponse.getheadersW << "$ $,,&&t,7 gs #77J+GN99W% %r6ct|j tt|jjS)z&Return list of (header, value) tuples.)rSrlistrrs r) getheaderszHTTPResponse.getheaderss- << "$ $DLL&&())r6c|SrrJrs r)rzHTTPResponse.__iter__s r6c|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. )rSrs r)infozHTTPResponse.info"s*||r6c|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. )rtrs r)geturlzHTTPResponse.geturl9s xxr6c|jS)zuReturn the HTTP status code that was sent with the response, or None if the URL is not an HTTP URL. )rlrs r)getcodezHTTPResponse.getcodeEs {{r6)rNNr))"rGrHrIrurrrr~rrrrrrrrrrrrrrrrOrrrrrrrrr __classcell__rs@r)rrs#<'BI#V: #  &P D =.0;(:0I6&"  5 &(* . r6rctj}|dk(r|jdg|jd|_|S)Nrzhttp/1.1T)ssl_create_default_https_contextset_alpn_protocolspost_handshake_auth) http_versioncontexts r)_create_https_contextrMsC//1Gr""J<0"".&*# Nr6c eZdZdZdZeZeZdZ dZ e dZ e dZ dejddfd Zd"d Zd Zd Zd ZdZdZdZdZdZdZdZd#dZ d$dZdZdZdZ dZ!dZ"d%dddZ#difdddZ$d Z%d!Z&y)&rrzHTTP/1.1r;rc6t|tjS)zFTest whether a file-like object is a text or a binary stream. )rr TextIOBase)streams r) _is_textIOzHTTPConnection._is_textIOds&"--00r6c||jtvryyt|dry t|}|jS#t $rYnwxYwt |tr t|Sy)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_BODYrrnbytes TypeErrorrryr=)bodyrsmvs r)_get_content_lengthz"HTTPConnection._get_content_lengthjsq <||~!88 4  D!B99     dC t9 sA A  A N cR||_||_||_d|_g|_d|_t |_d|_d|_ d|_ i|_ d|_ |j||\|_|_|j!|jt"j$|_yr)timeoutsource_address blocksizerr_buffer_HTTPConnection__response_CS_IDLE_HTTPConnection__staterh _tunnel_host _tunnel_port_tunnel_headers_raw_proxy_headers _get_hostporthostport_validate_hostsocketcreate_connection_create_connection)rArrrrrs r)ruzHTTPConnection.__init__s ,"      !"&!%!3!3D$!?DI DII&#)":":r6c|jr td|j||\|_|_|r|j |_n|j jtd|j DsI|jjdjd}d||jfz|j d<yy)aSet up host and port for HTTP CONNECT tunnelling. In a connection that uses HTTP CONNECT tunnelling, 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. As HTTP/1.1 is used for HTTP CONNECT tunnelling request, as per the RFC (https://tools.ietf.org/html/rfc7231#section-4.3.6), a HTTP Host: header must be provided, matching the authority-form of the request target provided as the destination for the CONNECT request. If a HTTP Host: header is not provided via the headers argument, one is generated and transmitted automatically. z.Can't set up tunnel for established connectionc3BK|]}|jdk(yw)rNr<).0headers r) z,HTTPConnection.set_tunnel..sO:N6<<>V+:Nsidnaasciiz%s:%dHostN) rr RuntimeErrorrrrcopyrclearanyrrY)rArrrS encoded_hosts r) set_tunnelzHTTPConnection.set_tunnels, 99OP P/3/A/A$/M,4, #*<<>D  & & (O$:N:NOO,,33F;BB7KL+2d//61,1D  (Pr6cH|K|jd}|jd}||kDr t||dzd}|d|}n |j}|r|ddk(r |ddk(r|dd}||fS#t$r/||dzddk(r |j}nt d||dzdzYdwxYw) Nr:]r;rxznonnumeric port: '%s'r[r)rfindrr} default_portr )rArrrjs r)rzHTTPConnection._get_hostports < 3A 3A1uOtAaCDz?D BQx(( DGsNtBx3":Dd|"OAaCDzR'#00()@4!:)MNNOsA))5B! B!c||_yr)rg)rAlevels r)set_debuglevelzHTTPConnection.set_debuglevels r6c.d|vr|ddk7rd|zdzS|S)N:r[r/r0rJ)rAips r) _wrap_ipv6zHTTPConnection._wrap_ipv6s( 2:"Q%7*"9t# # r6ctj|jrtd|jd|j |jj d|j |jj dfz}|g}|jjD]o\}}|j d}|j d}t|std|t|rtd||jd||fzq|jd |jd j|~|j|j |j" } |j%\}} } t'|j(|_|j,d kDr+|j*D]}t/d |j1| t2j4j6k7r/|j9t;d| d| j= |j9y#|j9wxYw)Nz-Tunnel host can't contain control characters sCONNECT %s:%d %s r'r(rInvalid header name Invalid header value s%s: %s rMr6rsrrzTunnel connection failed:  )!_contains_disallowed_url_pchar_researchrr}r=rr _http_vsn_strrr_is_legal_header_name_is_illegal_header_valuer@sendrXresponse_classrrrhrrTrRrrgrzrYhttp HTTPStatusOKrOSErrorr) rAconnectrSr%r header_bytes value_bytesresponserkrmessages r)_tunnelzHTTPConnection._tunnels , 3 3D4E4E F $ 1 145 5) OOD--44V< =       % %g .-00)!11779MFE!==3L,,y1K(6 \!KLL' 4 k!KLL NN=L++FF G: w #((7#$ &&tyy&F '/'<'<'> $WdG&3HKK&@D #""55F)V]]_56t)))  :4&'--/ARSTT* NN HNN s 4B4H::I cH|jt|jSdS)z Returns a dictionary with the headers of the response received from the proxy server to the CONNECT request sent to set the tunnel. If the CONNECT request was not sent, the method returns None. N)rr`rs r)get_proxy_response_headersz)HTTPConnection.get_proxy_response_headers s/&&2  7 7 8  r6ctjd||j|j|j |j|jf|j |j |_ |jjtjtjd|jr|j!yy#t$r(}|jtjk7rYd}~Jd}~wwxYw)z3Connect to the host and port specified in __init__.zhttp.client.connectr;N)sysauditrrr rrrr setsockoptr IPPROTO_TCP TCP_NODELAYrMerrno ENOPROTOOPTrrSrAes r)rNzHTTPConnection.connects 'tyy$))D++ YYtyy !4<<1D1DF   II !3!3V5G5G K    LLN   ww%+++, s09C C8C33C8ct|_ |j}|rd|_|j|j}|rd|_|jyy#|j}|rd|_|jwwxYw)z(Close the connection to the HTTP server.N)rrrrrr)rArrrQs r)rzHTTPConnection.close'sr  !99D   H"& H"& s %A(Bc|j'|jr|jn t|jdkDrt dt |t|dr|jdkDr t d|j|}|r|jdkDr t d|j|jx}rc|r|jd}tjd|||jj||j|jx}rcytjd|| |jj|y#t$r`t!|t"j$j&r$|D]}|jj|Yytd t)|zwxYw) zSend `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:rzsending a readableencoding file using iso-8859-1rVzhttp.client.sendz9data should be a bytes-like object or an iterable, got %r)rr auto_openrNrrgrzr{rrrrrrWrXsendallr r collectionsabcIterabletype)rAr&r datablockds r)rHzHTTPConnection.send5s~ 99 ~~ "n$ ??Q  '4: & 4 "*+__T*F$//A-67#yy88)8 ) 0 0 >I ,dI> !!), $yy88)8  $dD1 G II  d # G$  8 89AII%%a( !9;?:!FGG  GsE AG 1G c:|jj|y)zuAdd a line of output to the current request buffer. Assumes that the line does *not* end with \r\n. N)rr@)rArs r)_outputzHTTPConnection._outputZs Ar6c#@K|jdkDr td|j|}|r|jdkDr td|j|jx}r6|r|j d}||j|jx}r5yyw)Nrzreading a readablerbrV)rgrzrrrr)rArrris r)_read_readablezHTTPConnection._read_readableas ??Q  & '* doo) 2 3#==88i8%,,\: O$==88i8s BBBFc|jjddj|j}|jdd=|j||t |dr|j |}n t ||f}|D]e}|s|jdkDr td |r3|jdk(r$t|d d jd |zdz}|j|g|r"|jdk(r|jd yyyy#t$r4 t|}n$#t$rtdt|zwxYwYwxYw) zSend 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. )r6r6rMNrzAmessage_body should be a bytes-like object or an iterable, got %rrzZero length chunk ignoredrXz r(s0 )rextendrXrHrrnrr iterrhrgrz _http_vsnr=r)rA message_bodyencode_chunkedrichunkschunks r) _send_outputzHTTPConnection._send_outputls` J'll4<<( LLO #  #|V,,,\:- |,+_F*9:!dnn&:"5z!nD188AEI!"E %  $..B"6 ,'#7~O $!>>!%l!3$>')H*.|*<)=>>>>s*8 D E D,+E,!E  EEcz|jr!|jjrd|_|jtk(r t|_nt |j|j |||_|xsd}|j||d|d|j}|j|j||jdk(r&|s d}|jdrt|\}}}}}|r. |jd}|j#d t%|n|j&r|j&} |j(} n|j*} |j,} | jd} |j/| } d | vr t%| } | |j0k(r|j#d | n(| j3d} |j#d | d | |s|j#d d yyy#t $r|jd}Y wxYw#t $r| jd} YwxYw) 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/rBrrxrJr(r'r)r:zAccept-Encodingidentity)rrrr_CS_REQ_STARTEDr_validate_methodrh_validate_pathrErl_encode_requestrsr2rrr putheaderr5rrrrr=r4rY) rArsrt skip_hostskip_accept_encodingrequestnetlocnil netloc_encrrhost_encs r) putrequestzHTTPConnection.putrequests ??t779"DO* <<8 #*DL#DLL1 1 f% jS C &T-?-?@ T))'23 >>R >>&)19#.Cc3;%+]]7%; NN6+t000vx8#+??7#;v(D/IJ(0*=( c.;%+]]6%: ;.7#';;v#67s$?G<*H<HHH:9H:c$|jdS)Nr()r)rArs r)rzHTTPConnection._encode_request!s~~g&&r6crtj|}|r td|d|jdy)z&Validate a method name for putrequest.z)method can't contain control characters.  (found at least )N)$_contains_disallowed_method_pchar_rerDr}group)rArsmatchs r)r}zHTTPConnection._validate_method%sI5;;FC ?zJ'',{{}&7q:; ; r6crtj|}|r td|d|jdy)zValidate a url for putrequest.&URL can't contain control characters. rrNrCrDr r)rArtrs r)r~zHTTPConnection._validate_path.sL288= EcWM005 /@CD D r6crtj|}|r td|d|jdy)z9Validate a host so it doesn't contain control characters.rrrNr)rArrs r)rzHTTPConnection._validate_host6sL288> EdXN005 /@CD D r6c|jtk7r tt|dr|j d}t |st d|t|}t|D]r\}}t|dr|j d||<n-t|trt|j d||<t||sct d||dj|}|dz|z}|j|y) zkSend a request header line to the server. For example: h.putheader('Accept', 'text/html') rr(r?rr@s s: N)rr|rrrrFr}r enumeraterrryrGrXrl)rAr%valuesr one_valuers r)rzHTTPConnection.putheader>s <.ns #'0N0N $;."1H(  'R    !#GJ 4(l16(-}~';DD8 Ge G)-bG$G ,=\=r6rcReZdZdZeZdejddddfd ZfdZ xZ S)HTTPSConnectionz(This class allows communication via SSL.Nr )rrrrcrtt| ||||||t|j}||_y)N)r)rrrurrs_context)rArrrrrrrs r)ruzHTTPSConnection.__init__sB /4 1$g2@ >$($$ $ S Sr6rc eZdZy)rNrGrHrIrJr6r)rrs r6rc eZdZy)rNrrJr6r)rrr6rc eZdZy)r NrrJr6r)r r rr6r ceZdZdZy)rc"|f|_||_yr)argsrk)rArks r)ruzUnknownProtocol.__init__sH  r6NrGrHrIrurJr6r)rrsr6rc eZdZy)r NrrJr6r)r r rr6r c eZdZy)r NrrJr6r)r r rr6r c2eZdZddZdZej Zy)r Nc0|f|_||_||_yr)rpartialexpected)rArrs r)ruzIncompleteRead.__init__sH    r6c|jd|jz}nd}d|jjt|j|fzS)Nz, %i more expectedrxz%s(%i bytes read%s))rrrGr=rr^s r)__repr__zIncompleteRead.__repr__sK == $$t}}4AA$(?(?(+DLL(91(>> >r6r)rGrHrIrurr"__str__rJr6r)r r s!>nnGr6r c eZdZy)r NrrJr6r)r r rr6r c eZdZy)rNrrJr6r)rr#rr6rc eZdZy)rNrrJr6r)rr&rr6rc eZdZy)rNrrJr6r)rr)rr6rceZdZdZy)rc<|s t|}|f|_||_yr)r{rrE)rArEs r)ruzBadStatusLine.__init__-s:DE  r6NrrJr6r)rr,sr6rceZdZdZy)rcBtj|dt|fzy)Nz&got more than %d bytes when reading %s)rrurP)rA line_types r)ruzLineTooLong.__init__4s"t%M(0)'<&= >r6NrrJr6r)rr3s>r6rceZdZdZy)rcbtj|dtj|g|i|y)Nrx)rruConnectionResetError)rAposkws r)ruzRemoteDisconnected.__init__9s*tR(%%d7S7B7r6NrrJr6r)rr8s8r6r)r&)Jr email.parserrZ email.messager\rJrrerrWcollections.abcre urllib.parser__all__rrrjrr|rglobalsupdaterK __members__rphraserrPrQrrcompile fullmatchrFrDrGrCrrr*rr5rRMessager8rTr`rbBufferedIOBaserrrrrr@ ImportError Exceptionrrr rr r r r rrrrrrrr)vs0r)rsDL !     #  ,,-#'//"="="D"D"F G"FQQ["F G   8# #67AA%2::&CDKK%/BJJ/@$A!(2rzz-'@$3 E%%--''<$.9 @)0B 2$$B J } } ~!&S.S8 NN$% I  =   m  m  M  ]  m  /  .  . M>-> 8-}8 e. H^+  s H%'H**H21H2__pycache__/cookies.cpython-312.opt-2.pyc000064400000043201152527315050014060 0ustar00 {|j@T ddlZddlZddlZgdZdjZdjZdjZGddeZ ejejzdzZ e d zZ eed eeee z Dcic]}|d |z c}Zej'ed d eddiej(dej*e zj,Zej(dZdZdZej(dj6ZdZdZgdZgdZ dee fdZ!Gdde"Z#dZ$e$dzZ%ej(de$zdze%zd zejLejNzZ(Gd!d"e"Z)Gd#d$e)Z*ycc}w)%N) CookieError BaseCookie SimpleCookiez;  c eZdZy)rN)__name__ __module__ __qualname__%/usr/lib64/python3.12/http/cookies.pyrrsr rz!#$%&'*+-.^_`|~:z ()/<=>?@[]{}z\%03o"\"\z\\z[%s]+z[\x00-\x1F\x7F]c( td|DS)Nc3XK|]"}tjt|$ywN)_control_character_researchstr).0vs r z)_has_control_character..s!AS$++CF3Ss(*)any)vals r_has_control_characterrs ASA AAr cX | t|r|Sd|jtzdzS)Nr) _is_legal_key translate _Translatorrs r_quoter$s3  {mC( S]];//#55r z\\(?:([0-3][0-7][0-7])|(.))cF|drtt|ddS|dS)N)chrint)ms r_unquote_replacer,s't3qtQ<  t r ct|t|dkr|S|ddk7s|ddk7r|S|dd}tt|S)Nr(rrr&)len _unquote_subr,r#s r_unquoter1sO {c#hl  1v}B3 a)C (# ..r )MonTueWedThuFriSatSun) NJanFebMarAprMayJunJulAugSepOctNovDecc nddlm}m}|}|||z\ }}}} } } } } }d|| ||||| | | fzS)Nr)gmtimetimez#%s, %02d %3s %4d %02d:%02d:%02d GMT)rGrF)future weekdayname monthnamerFrGnowyearmonthdayhhmmsswdyzs r_getdaterUsW! &C-3C&L-A*D%b"b"a 0 OS)E"2D"b" E FFr c eZdZ ddddddddd d Zd d hZd ZedZedZedZ dZ d dZ dZ e jZdZdZdZdZdZdZdZd!dZeZdZd dZd dZeej:Zy)"MorselexpiresPathCommentDomainzMax-AgeSecureHttpOnlyVersionSameSite) rXpathcommentdomainmax-agesecurehttponlyversionsamesiterdrec~dx|_x|_|_|jD]}tj ||dy)Nr)_key_value _coded_value _reserveddict __setitem__)selfkeys r__init__zMorsel.__init__s:6:: :DK$"3>>C   T3 +"r c|jSr)riros rrpz Morsel.key s yyr c|jSr)rjrss rvaluez Morsel.value$s {{r c|jSr)rkrss r coded_valuezMorsel.coded_value(s   r c|j}||jvrtd|t||rtd|d|tj |||yNzInvalid attribute .Control characters are not allowed in cookies r)lowerrlrrrmrn)roKVs rrnzMorsel.__setitem__,s_ GGIDNN";< < !!Q ' NqeSTUVTYZ[ [ q!$r Nc|j}||jvrtd|t||rtd|d|tj |||Sry)r{rlrrrm setdefault)rorprs rrzMorsel.setdefault4sViik dnn $=> > !#s +WZ\_ab btS#..r ct|tstStj ||xrO|j |j k(xr4|j |j k(xr|j|jk(Sr) isinstancerWNotImplementedrm__eq__rjrirkromorsels rrz Morsel.__eq__<sj&&)! ! D&)9 v}},9 V[[(9!!V%8%88 :r ct}tj|||jj|j|Sr)rWrmupdate__dict__rs rcopyz Morsel.copyFs2 FD!t}}- r ci}t|jD]S\}}|j}||jvrt d|t ||rt d|d||||<Utj ||yry)rmitemsr{rlrrr)rovaluesdatarprs rrz Morsel.updateLsV **,HC))+C$..(!C"ABB%c3/!#--0G1SG#=>>DI- D$r c(|j||Sr)r)rors r__ior__zMorsel.__ior__Xs F r c:|j|jvSr)r{rl)ror|s r isReservedKeyzMorsel.isReservedKey\swwyDNN**r c|j|jvrtd|t|std|t |||rtd|d|d|||_||_||_y)NzAttempt to set a reserved key z Illegal key rzr)r{rlrr rrirjrk)rorpr coded_vals rsetz Morsel.set_sw 99;$.. (CIJ JS!#78 8 !#sI 6LOQTV_ac c  %r cJ|j|j|jdS)N)rprurw)rirjrkrss r __getstate__zMorsel.__getstate__ms#99[[,,  r c|d}|d}|d}t|||rtd|d|d|||_||_||_y)Nrprurwrzr)rrrirjrk)rostaterprurws r __setstate__zMorsel.__setstate__tsiElgM* !#uk :N!$q ;/CD D  'r c.|d|j|S)Nr) OutputString)roattrsheaders routputz Morsel.outputs $"3"3E":;;r cXd|jjd|jdS)N<: >) __class__r rrss r__repr__zMorsel.__repr__s !^^44d6G6G6IJJr cz|j|}t|r tdd|jddzS)N-Control characters are not allowed in cookiesz rr)rrrreplace)ror output_strings r js_outputzMorsel.js_outputsG))%0 !- 0MN N $$S%0 2 2r cg}|j}||jd|j| |j}t |j }|D]\}}|dk(r ||vr|dk(r4t |tr$||j|dt|J|dk(r+t |tr|d|j||fzz|dk(r4t |tr$||j|dt|||jvr"|s|t|j|||j|d|t|S)N=rrXrcz%s=%dra) appendrprwrlsortedrrr*rUrr$_flags_semispacejoin)rorresultrrrprus rrzMorsel.OutputStrings8 $((D$4$456 =NNEtzz|$JC{%iJuc$:$.."5xGH !j&<w$.."5u!==> !j&<$.."5ve}EF #3t~~c234$.."5u=> $f%%r r)N Set-Cookie:)r r r rlrrqpropertyrprurwrnrrobject__ne__rrrrrrrr__str__rrr classmethodtypes GenericAlias__class_getitem__r r rrWrWs* I #F,!!%/:]]F  + &  (<GK 2&B$E$6$67r rWz,\w\d!#%&'~_`><@,:/\$\*\+\-\.\^\|\)\(\?\}\{\=z\[\]z \s* # Optional whitespace at start of cookie (?P # Start of group 'key' [ax]+? # Any word of at least one letter ) # End of group 'key' ( # Optional group: there may not be a value. \s*=\s* # Equal Sign (?P # Start of group 'val' "(?:[^\\"]|\\.)*" # Any double-quoted string | # or # Special case for "expires" attr (\w{3,6}day|\w{3}),\s # Day of the week or abbreviated day [\w\d\s-]{9,11}\s[\d:]{8}\sGMT # Date and time in specific format | # 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. cXeZdZ dZdZd dZdZdZd dZeZ dZ d d Z d Z e fd Zy)rc ||fSrr rors r value_decodezBaseCookie.value_decodes Cxr c" t|}||fSrr#rorstrvals r value_encodezBaseCookie.value_encodes Sv~r Nc,|r|j|yyr)load)roinputs rrqzBaseCookie.__init__s  IIe  r c |j|t}|j|||tj |||yr)getrWrrmrn)rorp real_valuerwMs r__setzBaseCookie.__sets99 HHS&( # c:{+ sA&r c t|trtj|||y|j |\}}|j |||yr)rrWrmrnr_BaseCookie__set)rorprurvalcvals rrnzBaseCookie.__setitem__sE* eV $   T3 .**51JD$ JJsD$ 'r c g}t|j}|D]>\}}|j||}t|r t d|j |@|j |S)Nr)rrrrrrjoin) rorrseprrrpru value_outputs rrzBaseCookie.outputsi0tzz|$JC <<v6L%l3!"QRR MM, '  xxr cg}t|j}|D].\}}|j|dt|j0d|j j dt|dS)Nrrrr)rrrreprrurr _spacejoin)rolrrprus rrzBaseCookie.__repr__sX tzz|$JC HHT%++%67 8 !^^44jmDDr c g}t|j}|D]%\}}|j|j|'t |Sr)rrrr _nulljoin)rorrrrprus rrzBaseCookie.js_outputsH6tzz|$JC MM%//%0 1   r c t|tr|j|y|jD] \}}|||< yr)rr_BaseCookie__parse_stringr)rorawdatarprus rrzBaseCookie.load sH gs #    ( &mmo U!S .r cd}t|}g}d}d}d}d|cxkr|kr!nn|j||} | sn| jd| jd} } | jd}| ddk(r|sd|j || dd| fn| j t jvrY|sy| 6| j t jvr|j || dfnHy|j || t| fn)| &|j || |j| fd}nyd|cxkr|krnd} |D].\} } } | |k(r| | | <| \}}|j| |||| } 0y) NrFr&r(rpr$T) r/matchgroupendrr{rWrlrr1rr)rorpattin parsed_items morsel_seenTYPE_ATTRIBUTE TYPE_KEYVALUErrprurtprrs r__parse_stringzBaseCookie.__parse_string.s  H   1jqjJJsA&EU+U[[-?C ! A1v}"##^SWe$DE 0 00"=yy{fmm3$++^S$,GH ''huo(NO"##]C9J9J59Q$RS" E1jqjJ *NBU^### d 3d+I+r r)Nrz )r r r rrrqrrnrrrrr_CookiePatternrr r rrrsD1' (  GE! (6:r rceZdZ dZdZy)rct||fSr)r1rs rrzSimpleCookie.value_decoders}c!!r c2t|}|t|fSr)rr$rs rrzSimpleCookie.value_encodeusSvf~%%r N)r r r rrr r rrrks "&r r)+restringr__all__rrrr Exceptionr ascii_lettersdigits _LegalChars_UnescapedCharsrrangemapordr"rcompileescape fullmatchr rrr$subr0r,r1 _weekdayname _monthnamerUrmrW_LegalKeyChars_LegalValueCharsASCIIVERBOSErrr)rs0rrsNXz 7 GG  XX  ) """V]]25GG /E#J#c#.G*HHJH1(Q,HJ HeIv  7YRYY{%;;<FF " #56B 6rzz89==  /6A 8 <:F@8T@8XB!G+      & BJJ ' 2LL^ &: &MJs F __pycache__/server.cpython-312.pyc000064400000155431152527315050013003 0ustar00 {|j2ldZdZgdZddlZddlZddlZddlZddlZ ddl Z ddl Z ddl Z ddl Z ddlZddlZddlZddlZddlZddlZddlZddlZddl mZdZdZdZGd d ej6ZGd d ej:eZGd dej>Z Gdde Z!dZ"da#dZ$dZ%Gdde!Z&dZ'e edddfdZ(e)dk(rddl*Z*ddl+Z+e*jXZ-e-j]ddde-j]dd d!d"#e-j]d$d%e j^d&'e-j]d(d)d*dd+,e-j]d-de0d.d/0e-jcZ2e2jfre&Z4ne!Z4Gd1d2eZ5e(e4e5e2jle2jne2jp3yy)4a@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) HTTPServerThreadingHTTPServerBaseHTTPRequestHandlerSimpleHTTPRequestHandlerCGIHTTPRequestHandlerN) HTTPStatusaD Error response

Error response

Error code: %(code)d

Message: %(message)s.

Error code explanation: %(code)s - %(explain)s.

ztext/html;charset=utf-8iceZdZdZdZy)rctjj||jdd\}}t j ||_||_y)z.Override server_bind to store the server name.N) socketserver TCPServer server_bindserver_addresssocketgetfqdn server_name server_port)selfhostports $/usr/lib64/python3.12/http/server.pyrzHTTPServer.server_bindsE**40((!, d!>>$/N)__name__ __module__ __qualname__allow_reuse_addressrrrrrs  rrceZdZdZy)rTN)rrrdaemon_threadsrrrrrsNrrc NeZdZdZdej j dzZdezZ e Z e Z dZdZdZdZd Zd"d Zd#d Zd#d ZdZdZdZd$dZdZej9ej<ededdDcic] }|d|d c}}Z de e!d<dZ"dZ#d#dZ$dZ%gdZ&gdZ'd Z(d!Z)e*jVjXZ-e.j^jaDcic]}||jb|jdfc}}Z3y cc}}wcc}}w)%raHTTP 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 where is a (case-sensitive) keyword such as GET or POST, is a string containing path information for the request, and should be the string "HTTP/1.0" or "HTTP/1.1". 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 (i.e. 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 where is the protocol version ("HTTP/1.0" or "HTTP/1.1"), is a 3-digit response code indicating success or failure of the request, and 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 (). 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: / where and should be registered MIME types, e.g. "text/html" or "text/plain". zPython/rz BaseHTTP/HTTP/0.9c.d|_|jx|_}d|_t |j d}|j d}||_|j}t|dk(ryt|dk\r|d} |jd st|jd d d }|jd }t|d k7rttd|Dr tdtd|Dr tdt|dt|d f}|dk\r|j$dk\rd|_|dk\r$|jt j&d|zy||_d t|cxkrdks&n|jt j"d|zy|dd \}}t|d k(r0d|_|dk7r$|jt j"d|zy||c|_|_|j(jdr#d |j(j+d z|_ t,j.j1|j2|j4|_|j6j?dd} | jAd k(rd|_n)| jAd!k(r|j$dk\rd|_|j6j?d"d} | jAd#k(r/|j$dk\r |jdk\r|jCsyy#ttf$r&|jt j"d|zYywxYw#t,j.j8$r4}|jt j:dt |Yd}~yd}~wt,j.j<$r4}|jt j:dt |Yd}~yd}~wwxYw)$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-1 rFzHTTP//r .r c3>K|]}|j ywN)isdigit.0 components r z7BaseHTTPRequestHandler.parse_request..3sO99,,..sznon digit in http versionc38K|]}t|dkDyw) N)lenr,s rr/z7BaseHTTPRequestHandler.parse_request..5sKNys9~*Nsz unreasonable length http versionzBad request version (%r))r r zHTTP/1.1)r rzInvalid HTTP version (%s)zBad request syntax (%r)GETzBad HTTP/0.9 request type (%r)z//)_classz Line too longzToo many headers Connectionclose keep-aliveExpectz 100-continue)"commanddefault_request_versionrequest_versionclose_connectionstrraw_requestlinerstrip requestlinesplitr2 startswith ValueErroranyint IndexError send_errorr BAD_REQUESTprotocol_versionHTTP_VERSION_NOT_SUPPORTEDpathlstriphttpclient parse_headersrfile MessageClassheaders LineTooLongREQUEST_HEADER_FIELDS_TOO_LARGE HTTPExceptiongetlowerhandle_expect_100) rversionrAwordsbase_version_numberversion_numberr:rLerrconntypeexpects r parse_requestz$BaseHTTPRequestHandler.parse_requests )-)E)EEw $$.. = !((0 &!!# u:? u:?BiG ))'2$$&-mmC&;A&>#!4!:!:3!?~&!+$$OOO$%@AAKNKK$%GHH!$^A%6!7^A=N9O!O 'D,A,AZ,O(-%'99/2EEG#*D CJ#!# OO&&)K7 9bq  u:?$(D !%**4w>@")4 di 99   %dii..s33DI ;;44TZZ<@> w &$(D !nn,.##z1$)D !!!(B/ LLNn ,%%3$$ 2))+G + **.8:  P{{&&  OO::C {{((  OO::"C    s7B'L<:M4<2M10M14P*O P *PPcb|jtj|jy)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_onlyrCONTINUE end_headersrs rrYz(BaseHTTPRequestHandler.handle_expect_100}s'  3 34 rct |jjd|_t|jdkDr5d|_d|_d|_|jtjy|jsd|_ y|jsyd|j z}t||s.|jtjd|j zyt||}||jj!y#t"$r#}|j%d|d|_ Yd}~yd}~wwxYw) zHandle 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. iir6NTdo_zUnsupported method (%r)zRequest timed out: %r)rQreadliner?r2rAr<r:rHrREQUEST_URI_TOO_LONGr=rahasattrNOT_IMPLEMENTEDgetattrwfileflush TimeoutError log_error)rmnamemethodes rhandle_one_requestz)BaseHTTPRequestHandler.handle_one_requests  #'::#6#6u#=D 4''(50#% ')$!  ? ?@''(,%%%'DLL(E4'..- <>T5)F H JJ     NN2A 6$(D !   s1A,D /D D AD -D D7D22D7cd|_|j|js|j|jsyy)z&Handle multiple requests if necessary.TN)r=rurfs rhandlezBaseHTTPRequestHandler.handles6 $ !''  # # %''rNc |j|\}}||}||}|jd|||j|||j ddd}|dk\r|t j t jt jfvr|j|tj|dtj|dd z}|jd d }|j d |j|j d tt||j!|j"dk7r|r|j$j'|yyy#t$r d\}}YVwxYw)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. )???ryNzcode %d, message %sr5r7Fquote)codemessageexplainzUTF-8replacez Content-TypeContent-LengthHEAD) responsesKeyErrorrq send_response send_headerr NO_CONTENT RESET_CONTENT NOT_MODIFIEDerror_message_formathtmlescapeencodeerror_content_typer>r2rer:rnwrite)rr}r~rshortmsglongmsgbodycontents rrHz!BaseHTTPRequestHandler.send_errors\$ - $t 4 Hg ?G ?G ,dG< 4) w/  CK ..#11#002 2 00;;we<;;we<4G >>'95D   ^T-D-D E   -s3t9~ >  <<6 !d JJ  T "'+ != - , Hg -sEE+*E+c|j||j|||jd|j|jd|j y)zAdd 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. ServerDateN) log_requestrcrversion_stringdate_time_stringrr}r~s rrz$BaseHTTPRequestHandler.send_responsesT  g. 4#6#6#89 !6!6!89rc |jdk7rt|#||jvr|j|d}nd}t|dsg|_|jj d|j ||fzj ddyy) zSend the response header only.r"Nrr6_headers_bufferz %s %d %s latin-1strict)r<rrkrappendrJrrs rrcz)BaseHTTPRequestHandler.send_response_onlys   : -4>>)"nnT215G G4!23')$  ' '**D':*;|jdk7rDt|dsg|_|jj|d|dj dd|j dk(r7|j dk(rd |_y |j d k(rd |_y y y ) z)Send a MIME header to the headers buffer.r"rz: r$rr connectionr7Tr8FN)r<rkrrrrXr=)rkeywordvalues rrz"BaseHTTPRequestHandler.send_header s   : -4!23')$  ' '!(%088HM O ==?l *{{}'(,%,.(-%/ +rcz|jdk7r,|jjd|jyy)z,Send the blank line ending the MIME headers.r"s N)r<rr flush_headersrfs rrez"BaseHTTPRequestHandler.end_headerss5   : -  ' ' 0     .rct|dr<|jjdj|jg|_yy)Nrr)rkrnrjoinrrfs rrz$BaseHTTPRequestHandler.flush_headers s; 4* + JJ  SXXd&:&:; <#%D  ,rct|tr |j}|jd|jt |t |y)zNLog an accepted request. This is called by send_response(). z "%s" %s %sN) isinstancerr log_messagerAr>)rr}sizes rrz"BaseHTTPRequestHandler.log_request%s= dJ '::D ))3t9c$i Arc*|j|g|y)zLog 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)r)rformatargss rrqz BaseHTTPRequestHandler.log_error0s '$'r z\x02xz\\\c ||z}tjj|jd|j d|j |j dy)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 - - [z]  N)sysstderrraddress_stringlog_date_time_string translate_control_char_table)rrrr~s rrz"BaseHTTPRequestHandler.log_messageCsR(4- --/335!++D,D,DEG Hrc:|jdz|jzS)z*Return the server software version string. )server_version sys_versionrfs rrz%BaseHTTPRequestHandler.version_string]s""S(4+;+;;;rcp|tj}tjj|dS)z@Return the current date and time formatted for a message header.T)usegmt)timeemailutils formatdate)r timestamps rrz'BaseHTTPRequestHandler.date_time_stringas-   I{{%%i%==rc tj}tj|\ }}}}}}}} } d||j|||||fz} | S)z.Return the current time formatted for logging.z%02d/%3s/%04d %02d:%02d:%02d)r localtime monthname) rnowyearmonthdayhhmmssxyzss rrz+BaseHTTPRequestHandler.log_date_time_stringgsXiik04s0C-eS"b"aA *T^^E*D"b".> >r)MonTueWedThuFriSatSun) NJanFebMarAprMayJunJulAugSepOctNovDecc |jdS)zReturn the client address.r)client_addressrfs rrz%BaseHTTPRequestHandler.address_stringus""1%%rHTTP/1.0)NNr*)-r)4rrr__doc__rrZrBr __version__rDEFAULT_ERROR_MESSAGErDEFAULT_ERROR_CONTENT_TYPErr;rarYrurwrHrrcrrerrrqr> maketrans itertoolschainrangerordrrrr weekdaynamerrrJrNrO HTTPMessagerRr __members__valuesphrase descriptionr)r-cvs000rrrsqdNckk//1!44K !;.N03 )l\$#J&3#j : . .! & A (--'6yuT{E$tDT'U V'U!Q2aW 'U VX%*D "H4<> DK;I&";;**L ''..00A AHHamm $$0II WHs D 6 D!rcreZdZdZdezZdZdddddxZZd d fd Z d Z d Z dZ dZ dZdZdZxZS)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. z SimpleHTTP/)z index.htmlz index.htmzapplication/gzipapplication/octet-streamzapplication/x-bzip2zapplication/x-xz)z.gzz.Zz.bz2z.xzN directoryc|tj}tj||_t ||i|yr*)osgetcwdfspathrsuper__init__)rrrkwargs __class__s rrz!SimpleHTTPRequestHandler.__init__s6   I9- $)&)rc|j}|r. |j||j|jyy#|jwxYw)zServe a GET request.N) send_headcopyfilernr7rfs rdo_GETzSimpleHTTPRequestHandler.do_GETsC NN    a,  s AAcJ|j}|r|jyy)zServe a HEAD request.N)r r7r s rdo_HEADz SimpleHTTPRequestHandler.do_HEADs NN  GGI rc.|j|j}d}tjj|r5tj j |j}|jjds|jtj|d|d|ddz|d|df}tj j|}|jd||jd d |jy|jD]E}tjj||}tjj!|sC|}n|j#|S|j%|}|jdr!|j'tj(d y t+|d } tj.|j1}d |j2vr1d|j2vr" t4j6j9|j2d } | j:*| j=t>j@jB} | j:t>j@jBurt>j>jE|jFt>j@jB} | j=d} | | kr@|jtjH|j|jKy|jtjT|jd||jd tW|d|jd|jY|jF|j|S#t,$r#|j'tj(d YywxYw#tLtNtPtRf$rYwxYw#|jKxYw)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. Nr'rr r r%Locationr0zFile not foundrbzIf-Modified-Sincez If-None-Match)tzinfo) microsecond Content-typez Last-Modified)-translate_pathrLrisdirurllibparseurlsplitendswithrrMOVED_PERMANENTLY urlunsplitrre index_pagesrisfilelist_directory guess_typerH NOT_FOUNDopenOSErrorfstatfilenorSrrparsedate_to_datetimerrdatetimetimezoneutc fromtimestampst_mtimerr7 TypeErrorrG OverflowErrorrDOKr>r) rrLr parts new_partsnew_urlindexctypefsims last_modifs rr z"SimpleHTTPRequestHandler.send_headsB""499-  77== LL))$))4E::&&s+"":#?#?@"1XuQxqC"1XuQx1  ,,11)<  W5  !137  ")) T5177>>%( D * **400% ==  OOJ002B C T4 A ' !((*%B#t||3't||;(++;; %89;C zz)"kk1B1B1F1FkGzzX%6%6%:%::%-%6%6%D%DKK):):)>)>&@ &0%7%7A%7%F %, ..z/F/FG ,,.GGI#'   z}} -   ^U 3   -s2a5z :   _%%bkk2 4    HQ  OOJ002B C ":}jI8  GGI sK7 N3AP,O"2C4P'B P3)OO"O>;P=O>>PPc  tj|}|j dg} tjj|jd}tj|d}tj}d |}|j!d |j!d |j!d |j!d |d|j!d|d|j!d|d|j!d|D]}tjj#||}|x} } tjj%|r |dz} |dz} tjj'|r|dz} |j!dtjj)| ddtj| dd|j!ddj#|j+|d} t-j.} | j1| | j3d|j5tj6|j9dd|z|j9dt;t=| |j?| S#t$r#|jtj dYywxYw#t$r-tjj|j}YwxYw)zHelper 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 directoryNc"|jSr*)rX)as rz9SimpleHTTPRequestHandler.list_directory..s  r)key surrogatepasserrorsFr{zDirectory listing for zzzzzz z

z

z