HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //home/arjun/projects/env/lib/python3.10/site-packages/tornado/__pycache__/httputil.cpython-310.pyc
o

we��
@szdZddlZddlZddlZddlZddlZddlm	Z	ddl
mZddlZ
ddlZddlmZddlZddlZddlmZmZmZmZddlmZmZmZddlmZdd	lmZm Z eddl!Z!dd
l!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,e!j-r�ddl!m.Z.ddl/m0Z0ddl1Z1e	d
�de2de2fdd��Z3Gdd�dej4j5�Z6Gdd�de7�Z8Gdd�de9�Z:Gdd�de9�Z;Gdd�de7�Z<Gdd�de7�Z=Gdd�de7�Z>d e2d!e(de'e2e2fe$e"e2e2fe"e"e2e2fd"ffde2fd#d$�Z?Gd%d&�d&e�Z@d'e2de)e"e)eAe)eAffd(d)�ZBd*e)eAd+e)eAd,eAde2fd-d.�ZCd/e2de)eAfd0d1�ZD	did2e2d3eEd4e'e2e$eEfd5e'e2e$e@fd6e)e6ddfd7d8�ZFd9eEd:eEd4e'e2e$eEfd5e'e2e$e@fddf
d;d<�ZGd=e(eAeHeIejJejfde2fd>d?�ZKe�Ld@gdA��ZMe�NdB�ZOdCe2deMfdDdE�ZPe�LdFgdG��ZQe�NdH�ZRdCe2deQfdIdJ�ZSdKe2de+e2ddffdLdM�ZTdCe2de"e2e'e2e2fffdNdO�ZUdPe2dQe'e2e2fde2fdRdS�ZVdTe(e2eEfdUe(e2eEfdeEfdVdW�ZWdXdY�ZXe�NdZ�ZYd[e2de"e2e)eAffd\d]�ZZd^e'e2e$e,fde#e"e2e,ffd_d`�Z[e�Nda�Z\e�Ndb�Z]dcj^Z_dKe2de2fddde�Z`dfe2de'e2e2ffdgdh�ZadS)jz�HTTP utility code shared by clients and servers.

This module also defines the `HTTPServerRequest` class which is exposed
via `tornado.web.RequestHandler.request`.
�N)�	lru_cache)�	responses)�SSLError)�	urlencode�urlparse�
urlunparse�	parse_qsl)�
native_str�parse_qs_bytes�utf8)�gen_log)�
ObjectDict�unicode_type)�Tuple�Iterable�List�Mapping�Iterator�Dict�Union�Optional�	Awaitable�	Generator�AnyStr)�Deque)�Futurei��name�returncCsd�dd�|�d�D��S)ziMap a header name to Http-Header-Case.

    >>> _normalize_header("coNtent-TYPE")
    'Content-Type'
    �-cSsg|]}|���qS�)�
capitalize)�.0�wrr�I/home/arjun/projects/env/lib/python3.10/site-packages/tornado/httputil.py�
<listcomp>Isz%_normalize_header.<locals>.<listcomp>)�join�split)rrrr#�_normalize_headerBsr'c@s�eZdZdZejdeeeefddfdd��Z	ejdeeefddfdd��Z	ejde
eefddfd	d��Z	ejd
eddfdd��Z	dejd
eddfdd�Z	d
ededdfdd�Zd
edeefdd�Z
dee
eeffdd�Zdeddfdd�Zededdfdd��Zd
ededdfdd�Zd
edefdd�Zd
eddfdd �Zdefd!d"�Zdeejfd#d$�Zd)d%d&�ZeZdefd'd(�ZeZdS)*�HTTPHeadersa�A dictionary that maintains ``Http-Header-Case`` for all keys.

    Supports multiple values per key via a pair of new methods,
    `add()` and `get_list()`.  The regular dictionary interface
    returns a single value per key, with multiple values joined by a
    comma.

    >>> h = HTTPHeaders({"content-type": "text/html"})
    >>> list(h.keys())
    ['Content-Type']
    >>> h["Content-Type"]
    'text/html'

    >>> h.add("Set-Cookie", "A=B")
    >>> h.add("Set-Cookie", "C=D")
    >>> h["set-cookie"]
    'A=B,C=D'
    >>> h.get_list("set-cookie")
    ['A=B', 'C=D']

    >>> for (k,v) in sorted(h.get_all()):
    ...    print('%s: %s' % (k,v))
    ...
    Content-Type: text/html
    Set-Cookie: A=B
    Set-Cookie: C=D
    �_HTTPHeaders__argrNcC�dS�Nr��selfr)rrr#�__init__i�zHTTPHeaders.__init__cCr*r+rr,rrr#r.mr/�argscGr*r+r)r-r0rrr#r.qr/�kwargscKr*r+r)r-r1rrr#r.ur/cOsri|_i|_d|_t|�dkr/t|�dkr/t|dt�r/|d��D]
\}}|�||�q"dS|j|i|��dS)N�r)	�_dict�_as_list�	_last_key�len�
isinstancer(�get_all�add�update)r-r0r1�k�vrrr#r.ys&�r�valuecCsTt|�}||_||vr$t||�dt|�|j|<|j|�|�dS|||<dS)z#Adds a new value for the given key.�,N)r'r5r	r3r4�append�r-rr=�	norm_namerrr#r9�s�zHTTPHeaders.addcCst|�}|j�|g�S)z2Returns all values for the given header as a list.)r'r4�get�r-rrArrr#�get_list�szHTTPHeaders.get_listccs.�|j��D]\}}|D]}||fVqqdS)z�Returns an iterable of all (name, value) pairs.

        If a header has multiple values, multiple pairs will be
        returned with the same name.
        N)r4�items)r-r�valuesr=rrr#r8�s���zHTTPHeaders.get_all�linecCs�|d��r-|jdurtd��d|��}|j|jd|7<|j|j|7<dSz
|�dd�\}}WntyBtd��w|�||�	��dS)	z�Updates the dictionary with a single header line.

        >>> h = HTTPHeaders()
        >>> h.parse_line("Content-Type: text/html")
        >>> h.get('content-type')
        'text/html'
        rNz.first header line cannot start with whitespace� ����:r2zno colon in header line)
�isspacer5�HTTPInputError�lstripr4r3r&�
ValueErrorr9�strip)r-rG�new_partrr=rrr#�
parse_line�s
�zHTTPHeaders.parse_line�headerscCs>|�}|�d�D]}|�d�r|dd�}|r|�|�q|S)a�Returns a dictionary from HTTP header text.

        >>> h = HTTPHeaders.parse("Content-Type: text/html\r\nContent-Length: 42\r\n")
        >>> sorted(h.items())
        [('Content-Length', '42'), ('Content-Type', 'text/html')]

        .. versionchanged:: 5.1

           Raises `HTTPInputError` on malformed headers instead of a
           mix of `KeyError`, and `ValueError`.

        �
�
NrI)r&�endswithrQ)�clsrR�hrGrrr#�parse�s

�zHTTPHeaders.parsecCs"t|�}||j|<|g|j|<dSr+�r'r3r4r@rrr#�__setitem__�s
zHTTPHeaders.__setitem__cCs|jt|�Sr+)r3r')r-rrrr#�__getitem__�szHTTPHeaders.__getitem__cCst|�}|j|=|j|=dSr+rYrCrrr#�__delitem__�szHTTPHeaders.__delitem__cC�
t|j�Sr+)r6r3�r-rrr#�__len__��
zHTTPHeaders.__len__cCr]r+)�iterr3r^rrr#�__iter__�r`zHTTPHeaders.__iter__cCst|�Sr+)r(r^rrr#�copy�szHTTPHeaders.copycCs2g}|��D]
\}}|�d||f�qd�|�S)Nz%s: %s
�)r8r?r%)r-�linesrr=rrr#�__str__�s
zHTTPHeaders.__str__)rr()�__name__�
__module__�__qualname__�__doc__�typing�overloadr�strrr.r�Anyr9rDrr8rQ�classmethodrXrZr[r\�intr_rrbrc�__copy__rf�__unicode__rrrr#r(Ls4 

r(c@s
eZdZdZdZdZdZ										d"deedeededee	dee
d	eed
eeeedfded
deddee
ddfdd�Zedeeejjffdd��Zdefdd�Zdefdd�Z	d#dededee
ffdd�Zd$dd�Zdefd d!�ZdS)%�HTTPServerRequesta7
A single HTTP request.

    All attributes are type `str` unless otherwise noted.

    .. attribute:: method

       HTTP request method, e.g. "GET" or "POST"

    .. attribute:: uri

       The requested uri.

    .. attribute:: path

       The path portion of `uri`

    .. attribute:: query

       The query portion of `uri`

    .. attribute:: version

       HTTP version specified in request, e.g. "HTTP/1.1"

    .. attribute:: headers

       `.HTTPHeaders` dictionary-like object for request headers.  Acts like
       a case-insensitive dictionary with additional methods for repeated
       headers.

    .. attribute:: body

       Request body, if present, as a byte string.

    .. attribute:: remote_ip

       Client's IP address as a string.  If ``HTTPServer.xheaders`` is set,
       will pass along the real IP address provided by a load balancer
       in the ``X-Real-Ip`` or ``X-Forwarded-For`` header.

    .. versionchanged:: 3.1
       The list format of ``X-Forwarded-For`` is now supported.

    .. attribute:: protocol

       The protocol used, either "http" or "https".  If ``HTTPServer.xheaders``
       is set, will pass along the protocol used by a load balancer if
       reported via an ``X-Scheme`` header.

    .. attribute:: host

       The requested hostname, usually taken from the ``Host`` header.

    .. attribute:: arguments

       GET/POST arguments are available in the arguments property, which
       maps arguments names to lists of values (to support multiple values
       for individual names). Names are of type `str`, while arguments
       are byte strings.  Note that this is different from
       `.RequestHandler.get_argument`, which returns argument values as
       unicode strings.

    .. attribute:: query_arguments

       Same format as ``arguments``, but contains only arguments extracted
       from the query string.

       .. versionadded:: 3.2

    .. attribute:: body_arguments

       Same format as ``arguments``, but contains only arguments extracted
       from the request body.

       .. versionadded:: 3.2

    .. attribute:: files

       File uploads are available in the files property, which maps file
       names to lists of `.HTTPFile`.

    .. attribute:: connection

       An HTTP request is attached to a single HTTP connection, which can
       be accessed through the "connection" attribute. Since connections
       are typically kept open in HTTP/1.1, multiple requests can be handled
       sequentially on a single connection.

    .. versionchanged:: 4.0
       Moved from ``tornado.httpserver.HTTPRequest``.
    N�HTTP/1.0�method�uri�versionrR�body�host�files�HTTPFile�
connection�HTTPConnection�
start_line�RequestStartLine�server_connectionrc
Cs�|	dur	|	\}}}||_||_||_|pt�|_|pd|_t|dd�}t|dd�|_t|dd�|_|p:|j�	d�p:d|_
t|j
���d|_
|pIi|_||_|
|_t��|_d|_|durg|�d	�\|_}|_t|jd
d�|_t�|j�|_i|_dS)N��context�	remote_ip�protocol�http�Hostz	127.0.0.1r�?T��keep_blank_values)rurvrwr(rRrx�getattrr�r�rBry�split_host_and_port�lower�	host_namerzr|r��time�_start_time�_finish_time�	partition�path�queryr
�	argumentsrc�deepcopy�query_arguments�body_arguments)
r-rurvrwrRrxryrzr|r~r�r��seprrr#r.Zs,




zHTTPServerRequest.__init__c	Cs�t|d�s>tj��|_d|jvr>z	t|jd�}Wnty$Y|jSw|��D]\}}z||j|<Wq)ty=Yq)w|jS)z0A dictionary of ``http.cookies.Morsel`` objects.�_cookies�Cookie)	�hasattrr��cookies�SimpleCookier�rR�parse_cookie�	ExceptionrE)r-�parsedr;r<rrr#r��s"
�

��zHTTPServerRequest.cookiescCs|jd|j|jS)z+Reconstructs the full URL for this request.z://)r�ryrvr^rrr#�full_url�szHTTPServerRequest.full_urlcCs$|jdurt��|jS|j|jS)z?Returns the amount of time it took for this request to execute.N)r�r�r�r^rrr#�request_time�s
zHTTPServerRequest.request_timeF�binary_formcCs:z|jdur	WdS|jjjj|d�WStyYdSw)a>Returns the client's SSL certificate, if any.

        To use client certificates, the HTTPServer's
        `ssl.SSLContext.verify_mode` field must be set, e.g.::

            ssl_ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
            ssl_ctx.load_cert_chain("foo.crt", "foo.key")
            ssl_ctx.load_verify_locations("cacerts.pem")
            ssl_ctx.verify_mode = ssl.CERT_REQUIRED
            server = HTTPServer(app, ssl_options=ssl_ctx)

        By default, the return value is a dictionary (or None, if no
        client certificate is present).  If ``binary_form`` is true, a
        DER-encoded form of the certificate is returned instead.  See
        SSLSocket.getpeercert() in the standard library for more
        details.
        http://docs.python.org/library/ssl.html#sslsocket-objects
        N)r�)r|�stream�socket�getpeercertr)r-r�rrr#�get_ssl_certificate�s

��z%HTTPServerRequest.get_ssl_certificatecCsNt|j�dd�|j|j|j|j�|j��D]\}}|j�|g��	|�qdS)N�Content-Typerd)
�parse_body_argumentsrRrBrxr�rzrEr��
setdefault�extend)r-r;r<rrr#�_parse_body�s��zHTTPServerRequest._parse_bodycs,d}d��fdd�|D��}d�jj|fS)N)r�ryrurvrwr�z, csg|]}d|t�|�f�qS)z%s=%r)r�)r!�nr^rr#r$�sz.HTTPServerRequest.__repr__.<locals>.<listcomp>z%s(%s))r%�	__class__rg)r-�attrsr0rr^r#�__repr__�szHTTPServerRequest.__repr__)
NNrtNNNNNNN)F�rN)rgrhrirjr�r��_body_futurerrmr(�bytesrr�objectr.�propertyr�r��Morselr��floatr��boolrr�r�r�rrrr#rs�sd\��������	�
��
�(��
�
rsc@�eZdZdZdS)rLzqException class for malformed HTTP requests or responses
    from remote sources.

    .. versionadded:: 4.0
    N�rgrhrirjrrrr#rL�srLc@r�)�HTTPOutputErrorzJException class for errors in HTTP output.

    .. versionadded:: 4.0
    Nr�rrrr#r��sr�c@s8eZdZdZdeddddfdd�Zdedd	fd
d�Zd	S)�HTTPServerConnectionDelegatez_Implement this interface to handle requests from `.HTTPServer`.

    .. versionadded:: 4.0
    �server_conn�request_connr}r�HTTPMessageDelegatecC�t��)ajThis method is called by the server when a new request has started.

        :arg server_conn: is an opaque object representing the long-lived
            (e.g. tcp-level) connection.
        :arg request_conn: is a `.HTTPConnection` object for a single
            request/response exchange.

        This method should return a `.HTTPMessageDelegate`.
        ��NotImplementedError)r-r�r�rrr#�
start_request�sz*HTTPServerConnectionDelegate.start_requestNcC�dS)z�This method is called when a connection has been closed.

        :arg server_conn: is a server connection that has previously been
            passed to ``start_request``.
        Nr)r-r�rrr#�on_close��z%HTTPServerConnectionDelegate.on_close)rgrhrirjr�r�r�rrrr#r��s��
�r�c@s`eZdZdZdeddedeedfdd�Zd	e	deedfd
d�Z
ddd
�Zddd�ZdS)r�z_Implement this interface to handle an HTTP request or response.

    .. versionadded:: 4.0
    r~�r�ResponseStartLinerRrNcCr�)a�Called when the HTTP headers have been received and parsed.

        :arg start_line: a `.RequestStartLine` or `.ResponseStartLine`
            depending on whether this is a client or server message.
        :arg headers: a `.HTTPHeaders` instance.

        Some `.HTTPConnection` methods can only be called during
        ``headers_received``.

        May return a `.Future`; if it does the body will not be read
        until it is done.
        Nr)r-r~rRrrr#�headers_receivedsz$HTTPMessageDelegate.headers_received�chunkcCr�)ziCalled when a chunk of data has been received.

        May return a `.Future` for flow control.
        Nr�r-r�rrr#�
data_receivedsz!HTTPMessageDelegate.data_receivedcCr�)z6Called after the last chunk of data has been received.Nrr^rrr#�finish&r/zHTTPMessageDelegate.finishcCr�)z�Called if the connection is closed without finishing the request.

        If ``headers_received`` is called, either ``finish`` or
        ``on_connection_close`` will be called, but not both.
        Nrr^rrr#�on_connection_close*r�z'HTTPMessageDelegate.on_connection_closer�)
rgrhrirjrr(rrr�r�r�r�r�rrrr#r�s��

�
r�c	@sReZdZdZ	ddeddedeeddfd	d
�Zdeddfdd�Z	dd
d�Z
dS)r}zYApplications use this interface to write their responses.

    .. versionadded:: 4.0
    Nr~r�rRr�rzFuture[None]cCr�)aWrite an HTTP header block.

        :arg start_line: a `.RequestStartLine` or `.ResponseStartLine`.
        :arg headers: a `.HTTPHeaders` instance.
        :arg chunk: the first (optional) chunk of data.  This is an optimization
            so that small responses can be written in the same call as their
            headers.

        The ``version`` field of ``start_line`` is ignored.

        Returns a future for flow control.

        .. versionchanged:: 6.0

           The ``callback`` argument was removed.
        r�)r-r~rRr�rrr#�
write_headers9szHTTPConnection.write_headerscCr�)z�Writes a chunk of body data.

        Returns a future for flow control.

        .. versionchanged:: 6.0

           The ``callback`` argument was removed.
        r�r�rrr#�writeQs	zHTTPConnection.writecCr�)z3Indicates that the last body data has been written.r�r^rrr#r�\szHTTPConnection.finishr+r�)rgrhrirjrr(rr�r�r�r�rrrr#r}3s	����
�r}�urlr0.cCs�|dur|St|�}t|t�rt|jdd�}|�|���n"t|t�s(t|t�r5t|jdd�}|�|�nd�	t
|��}t|��t|�}t
|d|d|d|d||d	f�}|S)
aConcatenate url and arguments regardless of whether
    url has existing query parameters.

    ``args`` may be either a dictionary or a list of key-value pairs
    (the latter allows for multiple values with the same key.

    >>> url_concat("http://example.com/foo", dict(c="d"))
    'http://example.com/foo?c=d'
    >>> url_concat("http://example.com/foo?a=b", dict(c="d"))
    'http://example.com/foo?a=b&c=d'
    >>> url_concat("http://example.com/foo?a=b", [("c", "d"), ("c", "d2")])
    'http://example.com/foo?a=b&c=d&c=d2'
    NTr�z7'args' parameter should be dict, list or tuple. Not {0}rr2���)rr7�dictrr�r�rE�list�tuple�format�type�	TypeErrorrr)r�r0�
parsed_url�parsed_query�err�final_queryrrr#�
url_concatas0
���
r�c@s*eZdZUdZeed<eed<eed<dS)r{z�Represents a file uploaded via a form.

    For backwards compatibility, its instance attributes are also
    accessible as dictionary keys.

    * ``filename``
    * ``body``
    * ``content_type``
    �filenamerx�content_typeN)rgrhrirjrm�__annotations__r�rrrr#r{�s


r{�range_headercCs�|�d�\}}}|��|��}}|dkrdS|�d�\}}}z
t|�}t|�}Wn
ty3YdSw|durM|durI|dkrE|}d}||fS|d7}||fS)agParses a Range header.

    Returns either ``None`` or tuple ``(start, end)``.
    Note that while the HTTP headers use inclusive byte positions,
    this method returns indexes suitable for use in slices.

    >>> start, end = _parse_request_range("bytes=1-2")
    >>> start, end
    (1, 3)
    >>> [0, 1, 2, 3, 4][start:end]
    [1, 2]
    >>> _parse_request_range("bytes=6-")
    (6, None)
    >>> _parse_request_range("bytes=-6")
    (-6, None)
    >>> _parse_request_range("bytes=-0")
    (None, 0)
    >>> _parse_request_range("bytes=")
    (None, None)
    >>> _parse_request_range("foo=42")
    >>> _parse_request_range("bytes=1-2,6-10")

    Note: only supports one range (ex, ``bytes=1-2,6-10`` is not allowed).

    See [0] for the details of the range header.

    [0]: http://greenbytes.de/tech/webdav/draft-ietf-httpbis-p5-range-latest.html#byte.ranges
    �=r�Nrrr2)r�rO�_int_or_nonerN)r��unit�_r=�start_b�end_b�start�endrrr#�_parse_request_range�s&��r�r�r��totalcCs"|pd}|p|d}d|||fS)z�Returns a suitable Content-Range header:

    >>> print(_get_content_range(None, 1, 4))
    bytes 0-0/4
    >>> print(_get_content_range(1, 3, 4))
    bytes 1-2/4
    >>> print(_get_content_range(None, None, 4))
    bytes 0-3/4
    rr2zbytes %s-%s/%sr)r�r�r�rrr#�_get_content_range�s
r��valcCs|��}|dkr
dSt|�S)Nrd)rOrp)r�rrr#r��sr�r�rxr�rzrRc
CsT|�d�rN|rd|vrt�d|d�dSzt|dd�}Wnty7}zt�d|�i}WYd}~nd}~ww|��D]\}}|rK|�|g��|�q<dS|�d�r�|rcd|vrct�d|d�dSz+|�d	�}	|	D]}
|
�	��
d
�\}}}
|dkr�|
r�tt|
�|||�WdSqkt
d��ty�}z
t�d
|�WYd}~dSd}~wwdS)aFParses a form request body.

    Supports ``application/x-www-form-urlencoded`` and
    ``multipart/form-data``.  The ``content_type`` parameter should be
    a string and ``body`` should be a byte string.  The ``arguments``
    and ``files`` parameters are dictionaries that will be updated
    with the parsed contents.
    z!application/x-www-form-urlencodedzContent-Encodingz Unsupported Content-Encoding: %sNTr�z&Invalid x-www-form-urlencoded body: %szmultipart/form-data�;r��boundaryzmultipart boundary not foundzInvalid multipart/form-data: %s)�
startswithr�warningr
r�rEr�r�r&rOr��parse_multipart_form_datarrN)r�rxr�rzrR�
uri_arguments�errF�fields�fieldr;r�r<rrr#r��sL
�����
�
����r�r��datacCsZ|�d�r|�d�r|dd�}|�d|d�}|dkr$t�d�dS|d|��d|d�}|D]w}|s8q3|�d�}|dkrGt�d	�q3t�|d|��	d
��}|�
dd�}	t|	�\}
}|
d
ksh|�d�snt�d�q3||dd�}|�
d�s�t�d�q3|d}
|�
d�r�|�
dd�}|�|
g��
t|d||d��q3|�|
g��
|�q3dS)a]Parses a ``multipart/form-data`` body.

    The ``boundary`` and ``data`` parameters are both byte strings.
    The dictionaries given in the arguments and files parameters
    will be updated with the contents of the body.

    .. versionchanged:: 5.1

       Now recognizes non-ASCII filenames in RFC 2231/5987
       (``filename*=``) format.
    �"r2rIs--z.Invalid multipart/form-data: no final boundaryNs
s

z#multipart/form-data missing headerszutf-8zContent-Dispositionrdz	form-datazInvalid multipart/form-data����rz&multipart/form-data value missing namer�r�zapplication/unknown)r�rxr�)r�rU�rfindrr�r&�findr(rX�decoderB�
_parse_headerr�r?r{)r�r�r�rz�final_boundary_index�parts�part�eohrR�disp_header�disposition�disp_paramsr=r�ctyperrr#r�sD







���r��tscCsht|ttf�r
|}n"t|ttjf�rt�|�}nt|tj�r&t�|�	��}nt
d|��tjj
|dd�S)a�Formats a timestamp in the format used by HTTP.

    The argument may be a numeric timestamp as returned by `time.time`,
    a time tuple as returned by `time.gmtime`, or a `datetime.datetime`
    object. Naive `datetime.datetime` objects are assumed to represent
    UTC; aware objects are converted to UTC before formatting.

    >>> format_timestamp(1359312200)
    'Sun, 27 Jan 2013 18:43:20 GMT'
    zunknown timestamp type: %rT)�usegmt)r7rpr�r�r��struct_time�calendar�timegm�datetime�utctimetupler��email�utils�
formatdate)r	�time_numrrr#�format_timestampTs
rr)rur�rwz^HTTP/1\.[0-9]$rGcCsNz
|�d�\}}}Wntytd��wt�|�s!td|��t|||�S)z�Returns a (method, path, version) tuple for an HTTP 1.x request line.

    The response is a `collections.namedtuple`.

    >>> parse_request_start_line("GET /foo HTTP/1.1")
    RequestStartLine(method='GET', path='/foo', version='HTTP/1.1')
    rHzMalformed HTTP request linez/Malformed HTTP version in HTTP Request-Line: %r)r&rNrL�_http_version_re�matchr)rGrur�rwrrr#�parse_request_start_linets�
�rr�)rw�code�reasonz (HTTP/1.[0-9]) ([0-9]+) ([^\r]*)cCs@t|�}t�|�}|std��t|�d�t|�d��|�d��S)z�Returns a (version, code, reason) tuple for an HTTP 1.x response line.

    The response is a `collections.namedtuple`.

    >>> parse_response_start_line("HTTP/1.1 200 OK")
    ResponseStartLine(version='HTTP/1.1', code=200, reason='OK')
    z!Error parsing response start liner2r�r�)r	�_http_response_line_rerrLr��grouprp)rGrrrr#�parse_response_start_line�s

"r�sccs��|dd�dkrg|dd�}|�d�}|dkrD|�dd|�|�dd|�drD|�d|d�}|dkrD|�dd|�|�dd|�ds(|dkrLt|�}|d|�}|��V||d�}|dd�dks	dSdS)Nr2r�r�"z\"r�)r��countr6rO)rr��frrr#�_parseparam�s�
((�
�r!cCs�td|�}t|�}dg}|D](}|�d�}|dkr7|d|�����}||dd���}|�|t|�f�qtj�	|�}|�
d�i}	|D]&\}}
tj�|
�}t|�dkri|ddkri|d	dkri|dd	�}||	|<qG||	fS)
aYParse a Content-type like header.

    Return the main content-type and a dictionary of options.

    >>> d = "form-data; foo=\"b\\\\a\\\"r\"; file*=utf-8''T%C3%A4st"
    >>> ct, d = _parse_header(d)
    >>> ct
    'form-data'
    >>> d['file'] == r'T\u00e4st'.encode('ascii').decode('unicode_escape')
    True
    >>> d['foo']
    'b\\a"r'
    r�)�Dummyr=r�rNr2r�rrI)
r!�nextr�rOr�r?r	rr�
decode_params�pop�collapse_rfc2231_valuer6)rGr�key�params�p�irr=�decoded_params�pdict�
decoded_valuerrr#r�s&
�
$
rr'r,cCsT|s|S|g}t|���D]\}}|dur|�|�q
|�d||f�q
d�|�S)z�Inverse of _parse_header.

    >>> _encode_header('permessage-deflate',
    ...     {'client_max_window_bits': 15, 'client_no_context_takeover': None})
    'permessage-deflate; client_max_window_bits=15; client_no_context_takeover'
    Nz%s=%sz; )�sortedrEr?r%)r'r,�outr;r<rrr#�_encode_header�s
r0�username�passwordcCs@t|t�rt�d|�}t|t�rt�d|�}t|�dt|�S)z�Encodes a username/password pair in the format used by HTTP auth.

    The return value is a byte string in the form ``username:password``.

    .. versionadded:: 5.1
    �NFC�:)r7r�unicodedata�	normalizer)r1r2rrr#�encode_username_password�s

	
r7cCsddl}|��S)Nr)�doctest�DocTestSuite)r8rrr#�doctests�sr:z^(.+):(\d+)$�netloccCs>t�|�}|r|�d�}t|�d��}||fS|}d}||fS)z�Returns ``(host, port)`` tuple from ``netloc``.

    Returned ``port`` will be ``None`` if not present.

    .. versionadded:: 4.1
    r2r�N)�
_netloc_rerrrp)r;rry�portrrr#r�s

�r��qsccs,�|��D]\}}|D]}||fVqqdS)zgGenerator converting a result of ``parse_qs`` back to name-value pairs.

    .. versionadded:: 5.0
    N)rE)r>r;�vsr<rrr#�	qs_to_qsls���r@z\\[0-3][0-7][0-7]z[\\].rdcCsn|dus
t|�dkr|S|ddks|ddkr|S|dd�}d}t|�}g}d|kr2|kr�nt|�St�||�}t�||�}|sU|sU|�||d��	t|�Sd}}|r`|�d�}|rg|�d�}|r�|ro||kr�|�|||��|�||d�|d}n|�|||��|�tt||d|d�d���|d}d|kr�|ks7t|�St|�S)	z�Handle double quotes and escaping in cookie values.

    This method is copied verbatim from the Python 3.5 standard
    library (http.cookies._unquote) so we don't have to depend on
    non-public interfaces.
    Nr�rrrIr2r��)	r6�
_OctalPatt�search�
_QuotePattr?r��chrrp�	_nulljoin)rr*r��res�o_match�q_match�jr;rrr#�_unquote_cookie&s@	��


$��rK�cookiecCsri}|�td��D]-}td�|vr|�td�d�\}}ntd�|}}|��|��}}|s0|r6t|�||<q	|S)a[Parse a ``Cookie`` HTTP header into a dict of name/value pairs.

    This function attempts to mimic browser cookie parsing behavior;
    it specifically does not follow any of the cookie-related RFCs
    (because browsers don't either).

    The algorithm used is identical to that used by Django version 1.9.10.

    .. versionadded:: 4.4.2
    r�r�r2rd)r&rmrOrK)rL�
cookiedictr�r'r�rrr#r�Xs�r�r+)brjr�collections.abc�collectionsrcr�email.utilsr�	functoolsr�http.clientr�http.cookiesr��re�sslrr�r5�urllib.parserrrr�tornado.escaper	r
r�tornado.logr�tornado.utilr
rrkrrrrrrrrrrr�
TYPE_CHECKINGr�asyncior�unittestrmr'�abc�MutableMappingr(r�rsr�rLr�r�r�r}r�r{rpr�r�r�r�r�r�r�r�rr�
namedtupler�compilerrr�rrr!rr0r7r:r<r�r@rBrDr%rFrKr�rrrr#�<module>s�4	,_
	..�.��
�/�
�"3������
�1����
�:�
��
�
"
#
�
�
�
*


2