
    2 f                        d Z ddlZddlZddlZddlZddlZddlm	Z	 ddl
mZ ddlZddlZddlmZ ddlZddlZddlmZmZmZmZ ddlmZmZmZ ddlmZ dd	lmZm Z  e ddl!Z!dd
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ddl!m.Z. ddl/m0Z0 ddl1Z1dZ2 e	d          de3de3fd            Z4 G d dej5        j6                  Z7 G d de8          Z9 G d de:          Z; G d de:          Z< G d de8          Z= G d de8          Z> G d de8          Z?d e3d!e(de'e3e3f         e$e"e3e3f                  e"e"e3e3f         d"f         f         de3fd#Z@ G d$ d%e          ZAd&e3de)e"e)eB         e)eB         f                  fd'ZCd(e)eB         d)e)eB         d*eBde3fd+ZDd,e3de)eB         fd-ZE	 dWd.e3d/eFd0e'e3e$eF         f         d1e'e3e$eA         f         d2e)e7         ddfd3ZGd4eFd5eFd0e'e3e$eF         f         d1e'e3e$eA         f         ddf
d6ZHd7e(eBeIeJejK        ej        f         de3fd8ZL ejM        d9g d:          ZN ejO        d;          ZPd<e3deNfd=ZQ ejM        d>g d?          ZR ejO        d@          ZSd<e3deRfdAZTdBe3de+e3ddf         fdCZUd<e3de"e3e'e3e3f         f         fdDZVdEe3dFe'e3e3f         de3fdGZWdHe(e3eFf         dIe(e3eFf         deFfdJZXdK ZY ejO        dL          ZZdMe3de"e3e)eB         f         fdNZ[dOe'e3e$e,         f         de#e"e3e,f                  fdPZ\ ejO        dQ          Z] ejO        dR          Z^dSj_        Z`dBe3de3fdTZadUe3de'e3e3f         fdVZbdS )XzHTTP 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)Futurez 	i  namereturnc                 f    d                     d |                     d          D                       S )ziMap a header name to Http-Header-Case.

    >>> _normalize_header("coNtent-TYPE")
    'Content-Type'
    -c                 6    g | ]}|                                 S  )
capitalize).0ws     F/var/www/equiseq/venv/lib/python3.11/site-packages/tornado/httputil.py
<listcomp>z%_normalize_header.<locals>.<listcomp>L   s     ===Q\\^^===    )joinsplit)r   s    r&   _normalize_headerr+   E   s/     88==TZZ__===>>>r(   c                      e Zd ZdZej        deeee         f         ddfd            Z	ej        deeef         ddfd            Z	ej        de
eef         ddfd            Z	ej        d	eddfd
            Z	dej        d	eddfdZ	dededdfdZdedee         fdZdee
eef                  fdZdeddfdZededd fd            ZdededdfdZdedefdZdeddfdZdefdZdeej                 fdZddZeZdefdZeZdS )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__argr   Nc                     d S Nr"   selfr.   s     r&   __init__zHTTPHeaders.__init__l       r(   c                     d S r0   r"   r1   s     r&   r3   zHTTPHeaders.__init__p   r4   r(   argsc                     d S r0   r"   )r2   r6   s     r&   r3   zHTTPHeaders.__init__t   r4   r(   kwargsc                     d S r0   r"   )r2   r8   s     r&   r3   zHTTPHeaders.__init__x   r4   r(   c                 <   i | _         i | _        d | _        t          |          dk    rft          |          dk    rSt	          |d         t
                    r8|d                                         D ]\  }}|                     ||           d S  | j        |i | d S )N   r   )	_dict_as_list	_last_keylen
isinstancer-   get_alladdupdate)r2   r6   r8   kvs        r&   r3   zHTTPHeaders.__init__|   s    
t99>>c&kkQ..:d1g{3S3S.Q))  1A  DK((((((r(   r   valuec                     t          |          }|| _        || v rRt          | |                   dz   t          |          z   | j        |<   | j        |                             |           dS || |<   dS )z#Adds a new value for the given key.,N)r+   r>   r
   r<   r=   appendr2   r   rF   	norm_names       r&   rB   zHTTPHeaders.add   s~    %d++	"4	?++c1Ju4E4EE Jy! M)$++E22222#DOOOr(   c                 V    t          |          }| j                            |g           S )z2Returns all values for the given header as a list.)r+   r=   getr2   r   rK   s      r&   get_listzHTTPHeaders.get_list   s'    %d++	}  B///r(   c              #   ^   K   | j                                         D ]\  }}|D ]}||fV  	dS )zReturns an iterable of all (name, value) pairs.

        If a header has multiple values, multiple pairs will be
        returned with the same name.
        N)r=   items)r2   r   valuesrF   s       r&   rA   zHTTPHeaders.get_all   sZ       !M//11 	$ 	$LD& $ $Um####$	$ 	$r(   linec                    |d                                          ro| j        t          d          d|                    t                    z   }| j        | j                 dxx         |z  cc<   | j        | j        xx         |z  cc<   dS 	 |                    dd          \  }}n# t          $ r t          d          w xY w| 	                    ||
                    t                               dS )	zUpdates the dictionary with a single header line.

        >>> h = HTTPHeaders()
        >>> h.parse_line("Content-Type: text/html")
        >>> h.get('content-type')
        'text/html'
        r   Nz.first header line cannot start with whitespace :r;   zno colon in header line)isspacer>   HTTPInputErrorlstripHTTP_WHITESPACEr=   r<   r*   
ValueErrorrB   strip)r2   rS   new_partr   rF   s        r&   
parse_linezHTTPHeaders.parse_line   s    7?? 	9~%$%UVVVT[[999HM$.)"---9---Jt~&&&(2&&&&&@"jja00ee @ @ @$%>???@HHT5;;7788888s   B% %B?headersc                      |             }|                     d          D ]8}|                    d          r
|dd         }|r|                    |           9|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`.

        
NrV   )r*   endswithr_   )clsr`   hrS   s       r&   parsezHTTPHeaders.parse   sm     CEE MM$'' 	# 	#D}}T"" !CRCy #T"""r(   c                 N    t          |          }|| j        |<   |g| j        |<   d S r0   r+   r<   r=   rJ   s       r&   __setitem__zHTTPHeaders.__setitem__   s/    %d++	 %
9$)7i   r(   c                 6    | j         t          |                   S r0   )r<   r+   )r2   r   s     r&   __getitem__zHTTPHeaders.__getitem__   s    z+D1122r(   c                 D    t          |          }| j        |= | j        |= d S r0   ri   rN   s      r&   __delitem__zHTTPHeaders.__delitem__   s)    %d++	Jy!M)$$$r(   c                 *    t          | j                  S r0   )r?   r<   r2   s    r&   __len__zHTTPHeaders.__len__   s    4:r(   c                 *    t          | j                  S r0   )iterr<   rp   s    r&   __iter__zHTTPHeaders.__iter__   s    DJr(   c                      t          |           S r0   )r-   rp   s    r&   copyzHTTPHeaders.copy   s    4   r(   c                     g }|                                  D ] \  }}|                    |d|d           !d                    |          S )Nz: rb    )rA   rI   r)   )r2   linesr   rF   s       r&   __str__zHTTPHeaders.__str__   sT    <<>> 	5 	5KD%LLtttUUU34444wwu~~r(   )r   r-   )__name__
__module____qualname____doc__typingoverloadr   strr   r3   r   AnyrB   rO   r   rA   r_   classmethodrg   rj   rl   rn   intrq   r   rt   rv   __copy__rz   __unicode__r"   r(   r&   r-   r-   O   s        8 _gc49n5 $    _ _gc3h/ D    _ _eCHo $    _ _     _
)fj 
)C 
)D 
) 
) 
) 
)
$ 
$C 
$D 
$ 
$ 
$ 
$0S 0T#Y 0 0 0 0
$%S/2 $ $ $ $9s 9t 9 9 9 9, C M    [2+ +C +D + + + +
3 3 3 3 3 3% % % % % %
     (6:.        ! ! ! ! H     KKKr(   r-   c                      e Zd ZdZdZdZdZ	 	 	 	 	 	 	 	 	 	 ddee         dee         dedee	         dee
         d	ee         d
eeeed         f                  ded         ded         dee         ddfdZedeeej        j        f         fd            ZdefdZdefdZ	 ddededee
f         fdZddZdefdZdS )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versionr`   bodyhostfilesHTTPFile
connectionHTTPConnection
start_lineRequestStartLineserver_connectionr   c                    |	|	\  }}}|| _         || _        || _        |pt                      | _        |pd| _        t          |dd           }t          |dd           | _        t          |dd          | _        |p| j        	                    d          pd| _
        t          | j
                                                  d         | _        |pi | _        || _        |
| _        t#          j                    | _        d | _        |#|                    d	          \  | _        }| _        t/          | j        d
          | _        t3          j        | j                  | _        i | _        d S )Nr(   context	remote_ipprotocolhttpHostz	127.0.0.1r   ?Tkeep_blank_values)r   r   r   r-   r`   r   getattrr   r   rM   r   split_host_and_portlower	host_namer   r   r   time_start_time_finish_time	partitionpathqueryr   	argumentsrv   deepcopyquery_argumentsbody_arguments)r2   r   r   r   r`   r   r   r   r   r   r   r   seps                r&   r3   zHTTPServerRequest.__init__]  sI    !#- FC/+--KC	 *i66 +t<<V<<CDL,,V44C	,TY__->->??B[b
$!29;; ?),s););&DIsDJ'
dKKK#}T^<< r(   c                 J   t          | d          st          j                                        | _        d| j        v ra	 t          | j        d                   }|                                D ] \  }}	 || j        |<   # t          $ r Y w xY wn# t          $ r Y nw xY w| j        S )z0A dictionary of ``http.cookies.Morsel`` objects._cookiesCookie)	hasattrr   cookiesSimpleCookier   r`   parse_cookierQ   	Exception)r2   parsedrD   rE   s       r&   r   zHTTPServerRequest.cookies  s     tZ(( 	!))++ M 4<''!)$,x*@AAF !' ! !1!/0DM!,,( ! ! ! !D	!! !   D }s#   B 2
A==
B
	B

BBc                 6    | j         dz   | j        z   | j        z   S )z+Reconstructs the full URL for this request.z://)r   r   r   rp   s    r&   full_urlzHTTPServerRequest.full_url  s    }u$ty048;;r(   c                 d    | j         t          j                    | j        z
  S | j         | j        z
  S )z?Returns the amount of time it took for this request to execute.)r   r   r   rp   s    r&   request_timezHTTPServerRequest.request_time  s0    $9;;!111$t'777r(   Fbinary_formc                     	 | j         dS | j         j        j                            |          S # t          $ r Y dS w xY w)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   )r2   r   s     r&   get_ssl_certificatez%HTTPServerRequest.get_ssl_certificate  s`    *	&t?)0<<' =     	 	 	44	s   0 $0 
>>c                     t          | j                            dd          | j        | j        | j        | j                   | j                                        D ]3\  }}| j                            |g           	                    |           4d S )NContent-Typerx   )
parse_body_argumentsr`   rM   r   r   r   rQ   r   
setdefaultextend)r2   rD   rE   s      r&   _parse_bodyzHTTPServerRequest._parse_body  s    L^R00IJL	
 	
 	
 '--// 	7 	7DAqN%%a,,33A6666	7 	7r(   c                 n     d}d                      fd|D                       } j        j        d|dS )N)r   r   r   r   r   r   z, c                 :    g | ]}|d t          |          S )=)r   )r$   nr2   s     r&   r'   z.HTTPServerRequest.__repr__.<locals>.<listcomp>  s/    IIIaQQQa(8(8(89IIIr(   ())r)   	__class__r{   )r2   attrsr6   s   `  r&   __repr__zHTTPServerRequest.__repr__  sH    MyyIIII5IIIJJ>222DDD99r(   )
NNr   NNNNNNN)Fr   N)r{   r|   r}   r~   r   r   _body_futurer   r   r-   bytesr   r   objectr3   propertyr   r   Morselr   floatr   boolr   r   r   r   r"   r(   r&   r   r      s       Z Zx DE L !%!!)- $"7;1537.2&! &!&! c]&! 	&!
 +&&! uo&! sm&! S$z"2234&! -.&! /0&! $F+&! 
&! &! &! &!P c4<#667    X,<# < < < <8e 8 8 8 8 #( 	tT5 	!   >
7 
7 
7 
7:# : : : : : :r(   r   c                       e Zd ZdZdS )rY   zqException class for malformed HTTP requests or responses
    from remote sources.

    .. versionadded:: 4.0
    Nr{   r|   r}   r~   r"   r(   r&   rY   rY     s          	Dr(   rY   c                       e Zd ZdZdS )HTTPOutputErrorzJException class for errors in HTTP output.

    .. versionadded:: 4.0
    Nr   r"   r(   r&   r   r     s         
 	Dr(   r   c                   6    e Zd ZdZdeddddfdZdeddfd	ZdS )
HTTPServerConnectionDelegatez_Implement this interface to handle requests from `.HTTPServer`.

    .. versionadded:: 4.0
    server_connrequest_connr   r   HTTPMessageDelegatec                     t                      )aj  This 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)r2   r   r   s      r&   start_requestz*HTTPServerConnectionDelegate.start_request  s     "###r(   Nc                     dS )zThis 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"   )r2   r   s     r&   on_closez%HTTPServerConnectionDelegate.on_close  	     	r(   )r{   r|   r}   r~   r   r   r   r"   r(   r&   r   r     sl         
$!$1A$	$ $ $ $F t      r(   r   c                       e Zd ZdZded         dedeed                  fdZde	deed                  fd	Z
dd
ZddZdS )r   z_Implement this interface to handle an HTTP request or response.

    .. versionadded:: 4.0
    r   r   ResponseStartLiner`   r   Nc                     dS )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"   )r2   r   r`   s      r&   headers_receivedz$HTTPMessageDelegate.headers_received  s	    " 	r(   chunkc                     dS )ziCalled when a chunk of data has been received.

        May return a `.Future` for flow control.
        Nr"   r2   r   s     r&   data_receivedz!HTTPMessageDelegate.data_received"  s	    
 	r(   c                     dS )z6Called after the last chunk of data has been received.Nr"   rp   s    r&   finishzHTTPMessageDelegate.finish)  r4   r(   c                     dS )zCalled 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.
        Nr"   rp   s    r&   on_connection_closez'HTTPMessageDelegate.on_connection_close-  r   r(   r   )r{   r|   r}   r~   r   r-   r   r   r   r   r   r   r   r"   r(   r&   r   r     s         AB  
)D/	"	   &5 Xio-F            r(   r   c            	       ^    e Zd ZdZ	 dded         dedee         ddfd	Zdeddfd
Z	ddZ
dS )r   zYApplications use this interface to write their responses.

    .. versionadded:: 4.0
    Nr   r   r`   r   r   zFuture[None]c                     t                      )a  Write 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   )r2   r   r`   r   s       r&   write_headerszHTTPConnection.write_headers<  s    , "###r(   c                     t                      )zWrites a chunk of body data.

        Returns a future for flow control.

        .. versionchanged:: 6.0

           The ``callback`` argument was removed.
        r   r   s     r&   writezHTTPConnection.writeT  s     "###r(   c                     t                      )z3Indicates that the last body data has been written.r   rp   s    r&   r   zHTTPConnection.finish_  s    !###r(   r0   r   )r{   r|   r}   r~   r   r-   r   r   r   r   r   r"   r(   r&   r   r   6  s          "&	$ $AB$ $ 	$
 
$ $ $ $0	$5 	$^ 	$ 	$ 	$ 	$$ $ $ $ $ $r(   r   urlr6   .c           	      d   || S t          |           }t          |t                    r>t          |j        d          }|                    |                                           nt          |t                    st          |t                    r,t          |j        d          }|                    |           n1d	                    t          |                    }t          |          t          |          }t          |d         |d         |d         |d         ||d	         f          } | S )
a  Concatenate 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}r   r;            )r   r@   dictr	   r   r   rQ   listtupleformattype	TypeErrorr   r   )r   r6   
parsed_urlparsed_queryerrfinal_querys         r&   
url_concatr
  d  s(   & |
#J$ 
 !1TJJJDJJLL))))	D$		 :dE#:#:  !1TJJJD!!!!GNNJJ
 
 nnL))K
qMqMqMqMqM	
	 	C Jr(   c                   2    e Zd ZU dZeed<   eed<   eed<   dS )r   zRepresents a file uploaded via a form.

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

    * ``filename``
    * ``body``
    * ``content_type``
    filenamer   content_typeN)r{   r|   r}   r~   r   __annotations__r   r"   r(   r&   r   r     s<           MMM
KKKr(   r   range_headerc                 Z   |                      d          \  }}}|                                |                                }}|dk    rdS |                     d          \  }}}	 t          |          }t          |          }n# t          $ r Y dS w xY w|||dk    r| }d}n|dz  }||fS )ag  Parses 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   r   Nr    r   r;   )r   r]   _int_or_noner\   )r  unit_rF   start_bend_bstartends           r&   _parse_request_ranger    s    > "++C00ND!U**,,%Dwt,,GQW%%5!!   tt
=axx1HC3<s   $B 
BBr  r  totalc                 .    | pd} |p|dz
  }d| d|d|S )zReturns 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
    r   r;   zbytes r    /r"   )r  r  r  s      r&   _get_content_ranger    s4     JQE<%1
CC$uuccc5511r(   valc                 X    |                                  } | dk    rd S t          |           S )Nrx   )r]   r   )r  s    r&   r  r    s(    
))++C
byyts88Or(   r  r   r   r   r`   c                 N   |                      d          r|r!d|v rt          j        d|d                    dS 	 t          |d          }n.# t          $ r!}t          j        d|           i }Y d}~nd}~ww xY w|                                D ]0\  }}|r)|                    |g                               |           1dS |                      d          r|r!d|v rt          j        d|d                    dS 	 |                     d	          }	|	D ]W}
|
	                                
                    d
          \  }}}|dk    r$|r"t          t          |          |||            dS Xt          d          # t          $ r }t          j        d|           Y d}~dS d}~ww xY wdS )aF  Parses 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-urlencodedzContent-Encodingz Unsupported Content-Encoding: %sNTr   z&Invalid x-www-form-urlencoded body: %szmultipart/form-data;r   boundaryzmultipart boundary not foundzInvalid multipart/form-data: %s)
startswithr   warningr   r   rQ   r   r   r*   r]   r   parse_multipart_form_datar   r\   )r  r   r   r   r`   uri_argumentser   rR   fieldsfieldrD   r   rE   s                 r&   r   r     s7    BCC B 	)W44O2G<N4O   F	*44HHHMM 	 	 	ODaHHHMMMMMM	 *//11 	> 	>LD& >$$T2..55f===	> 	> 
	 	 !6	7	7 B 	)W44O2G<N4O   F
	B!'',,F A A!KKMM33C88	3
??q?-d1ggtYNNNEE !?@@@ 	B 	B 	BO=qAAAAAAAAA	BB Bs6   A 
A7A22A7:A,E8 (E8 8
F"FF"r!  datac                 X   |                      d          r|                     d          r
| dd         } |                    d| z   dz             }|dk    rt          j        d           dS |d|                             d| z   dz             }|D ]}|s|                    d          }|dk    rt          j        d	           6t                              |d|         	                    d
                    }|
                    dd          }	t          |	          \  }
}|
dk    s|                    d          st          j        d           ||dz   d         }|
                    d          st          j        d           |d         }|
                    d          rW|
                    dd          }|                    |g                               t          |d         ||                     n|                    |g                               |           dS )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.
       "r;   rV   s   --z.Invalid multipart/form-data: no final boundaryNs   
s   

z#multipart/form-data missing headerszutf-8zContent-Dispositionrx   z	form-datazInvalid multipart/form-data   r   z&multipart/form-data value missing namer  r   zapplication/unknown)r  r   r  )r"  rd   rfindr   r#  r*   findr-   rg   decoderM   _parse_headerr   rI   r   )r!  r)  r   r   final_boundary_indexpartsparteohr`   disp_headerdispositiondisp_paramsrF   r   ctypes                  r&   r$  r$    sS   , 4   "X%6%6t%<%< "AbD>::eh&6&>??r!!HIII&&&'--eh.>.HIIE 9 9 	ii$$"99OABBB##D#J$5$5g$>$>??kk"7<<#0#=#= [+%%T]]7-C-C%O9:::S1Wr\"v&& 	ODEEE6"??:&& 	9KK0EFFET2&&--(45u        r**11%888859 9r(   tsc                    t          | t          t          f          r| }nt          | t          t          j        f          rt          j        |           }nSt          | t          j                  r't          j        | 	                                          }nt          d| z            t          j                            |d          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'
    zunknown timestamp type: %rT)usegmt)r@   r   r   r  r   struct_timecalendartimegmdatetimeutctimetupler  emailutils
formatdate)r:  time_nums     r&   format_timestamprF  W  s     "sEl## ;	B 01	2	2 ;?2&&	B)	*	* ;?2??#4#4554r9:::;!!(4!888r(   r   )r   r   r   z^HTTP/1\.[0-9]$rS   c                     	 |                      d          \  }}}n# t          $ r t          d          w xY wt                              |          st          d|z            t          |||          S )zReturns 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')
    rU   zMalformed HTTP request linez/Malformed HTTP version in HTTP Request-Line: %r)r*   r\   rY   _http_version_rematchr   )rS   r   r   r   s       r&   parse_request_start_linerJ  w  s    < $

3gg < < < :;;;< !!'** 
=G
 
 	
 FD'222s    6r   )r   codereasonz (HTTP/1.[0-9]) ([0-9]+) ([^\r]*)c                 $   t          |           } t                              |           }|st          d          t	          |                    d          t          |                    d                    |                    d                    S )zReturns 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 liner;   r   r   )r
   _http_response_line_rerI  rY   r   groupr   )rS   rI  s     r&   parse_response_start_linerP    st     dD"((..E B@AAAU[[^^SQ-@-@%++a..QQQr(   sc              #     K   | d d         dk    r| dd          } |                      d          }|dk    r|                     dd|          |                     dd|          z
  dz  rQ|                      d|dz             }|dk    r2|                     dd|          |                     dd|          z
  dz  Q|dk     rt          |           }| d |         }|                                V  | |d          } | d d         dk    d S d S )Nr;   r   r   "z\"r   )r/  countr?   r]   )rQ  r  fs      r&   _parseparamrV    s     
BQB%3,,abbEffSkkAgg17733//!''%C2H2HHAMg&&cAg&&C Agg17733//!''%C2H2HHAMg77a&&CdsdGggiicddG BQB%3,,,,,,r(   c                    t          d| z             }t          |          }dg}|D ]}|                    d          }|dk    rq|d|                                                                         }||dz   d                                         }|                    |t          |          f           t          j        	                    |          }|
                    d           i }	|D ]^\  }}
t          j                            |
          }t          |          dk    r"|d         dk    r|d	         dk    r
|dd	         }||	|<   _||	fS )
aY  Parse 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   )DummyrF   r   r   Nr;   r   rS  rV   )rV  nextr/  r]   r   rI   r
   rB  rC  decode_paramspopcollapse_rfc2231_valuer?   )rS   r3  keyparamspir   rF   decoded_paramspdictdecoded_values              r&   r1  r1    sO    d
##E
u++C !F 5 5FF3KK66RaR5;;==&&((Da!eggJ$$&&EMM4E!2!23444[..v66NqE-  m22=AAu::??uQx3593C3C!B$KEd:r(   r]  rb  c                     |s| S | g}t          |                                          D ]7\  }}||                    |           |                    |d|           8d                    |          S )zInverse 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'
    Nr   z; )sortedrQ   rI   r)   )r]  rb  outrD   rE   s        r&   _encode_headerrg    s      
%Cu{{}}%% ) )19JJqMMMM JJ!!!QQ'((((99S>>r(   usernamepasswordc                     t          | t                    rt          j        d|           } t          |t                    rt          j        d|          }t	          |           dz   t	          |          z   S )zEncodes 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   :)r@   r   unicodedata	normalizer   )rh  ri  s     r&   encode_username_passwordro    sh     (L)) :(99(L)) :(99>>D 4>>11r(   c                  2    dd l } |                                 S )Nr   )doctestDocTestSuite)rq  s    r&   doctestsrs    s    NNN!!!r(   z^(.+):(\d+)$netlocc                     t                               |           }|r8|                    d          }t          |                    d                    }n| }d}||fS )zReturns ``(host, port)`` tuple from ``netloc``.

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

    .. versionadded:: 4.1
    r;   r   N)
_netloc_rerI  rO  r   )rt  rI  r   ports       r&   r   r   	  s[     V$$E {{1~~5;;q>>""$<r(   qsc              #   T   K   |                                  D ]\  }}|D ]}||fV  	dS )zgGenerator converting a result of ``parse_qs`` back to name-value pairs.

    .. versionadded:: 5.0
    N)rQ   )rx  rD   vsrE   s       r&   	qs_to_qslr{    sP      
   2 	 	Aa&LLLL	 r(   z\\[0-3][0-7][0-7]z[\\].rx   c           
      j   | t          |           dk     r| S | d         dk    s| d         dk    r| S | dd         } d}t          |           }g }d|cxk    r|k     rIn nEt                              | |          }t                              | |          }|s |s|                    | |d                    ndx}}|r|                    d          }|r|                    d          }|rI|r||k     rA|                    | ||                    |                    | |dz                       |dz   }n`|                    | ||                    |                    t          t          | |dz   |dz            d                               |dz   }d|cxk    r|k     Cn t          |          S )	zHandle 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   r   rS  rV   r;   r,     )	r?   
_OctalPattsearch
_QuotePattrI   r  chrr   	_nulljoin)rQ  r`  r   reso_matchq_matchjrD   s           r&   _unquote_cookier  )  s    	yCFFQJJts{{aesll 	
!B$A 	
AAA
C
q****1*****##Aq))##Aq)) 	w 	JJqu
A 	!a  A 	!a  A 	G 	q1uuJJq1vJJqQx   AAAJJq1vJJs3qQQ/3344555AA' q****1****( S>>r(   cookiec                 b   i }|                      t          d                    D ]}t          d          |v r'|                     t          d          d          \  }}nt          d          |}}|                                |                                }}|s|rt          |          ||<   |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   r;   rx   )r*   r   r]   r  )r  
cookiedictr   r]  r  s        r&   r   r   [  s     Jc#hh'' 
3 
3s88u{{3s88Q//HC 2wwC99;;		S 	3# 	3-c22JsOr(   r0   )cr~   r>  collections.abccollectionsrv   r@  email.utilsrB  	functoolsr   http.clientr   http.cookiesr   resslr   r   rm  urllib.parser   r   r   r	   tornado.escaper
   r   r   tornado.logr   tornado.utilr   r   r   r   r   r   r   r   r   r   r   r   r   r   TYPE_CHECKINGr   asyncior   unittestr[   r   r+   abcMutableMappingr-   r   r   r   rY   r   r   r   r   r
  r   r   r  r  r  r   r   r$  r   r  r=  rF  
namedtupler   compilerH  rJ  r   rN  rP  rV  r1  rg  ro  rs  rv  r   r{  r~  r  r)   r  r  r   r"   r(   r&   <module>r     s@                      ! ! ! ! ! !     				            C C C C C C C C C C C C ; ; ; ; ; ; ; ; ; ;       1 1 1 1 1 1 1 1
 
	                           
 OOO  4?C ?C ? ? ? ?h h h h h+/0 h h hV[: [: [: [: [: [: [: [:|	 	 	 	 	Y 	 	 		 	 	 	 	i 	 	 	    6   :+ + + + +& + + +\+$ +$ +$ +$ +$V +$ +$ +$\,	,
d38nd5c?3U5c?C;O5PP,
 	, , , ,^    z    00eHSM8C=0120 0 0 0f2hsm 2(3- 2 2PS 2 2 2 2c hsm     &*.B .B.B
.B Ce$%.B T(^#$	.B
 k".B 
.B .B .B .Bb7979
79 Ce$%79 T(^#$	79
 
79 79 79 79t9c5%!183DDE99 9 9 90 *;)555  
 2:011 33 3+; 3 3 3 3* +K*666  
 $$GHH RC R,= R R R R.
3 
9S$_5 
 
 
 
   c4S>&9 :        F DcN s    (2CJ2+0e+<2
2 2 2 2 " " " RZ((
 c8C=.@(A    "$sDL() huS&[7I.J     RZ,--
RZ!!
G	/s /s / / / /d c3h      r(   