
    #/hƊ                     "   S r SSKrSSKrSSKrSSKrSSKrSSKJ	r	  SSK
Jr  SSKrSSKrSSKJr  SSKrSSKrSSKJrJrJrJr  SSKJrJrJr  SSKJrJr  \  SSKrSS	KJ r J!r!J"r"J#r#J$r$J%r%J&r&J'r'J(r(J)r)J*r*  \RV                  (       a  SS
KJ,r,  SSK-J.r.  SSK/r/Sr0\	" S5      S\1S\14S j5       r2 " S S\Rf                  Rh                  5      r5 " S S\65      r7 " S S\85      r9 " S S\85      r: " S S\65      r; " S S\65      r< " S S\65      r=S\1S \&S\%\1\14   \"\ \1\14      \ \ \1\14   S!4   4   S\14S" jr> " S# S$\5      r?S%\1S\'\ \'\@   \'\@   4      4S& jrAS'\'\@   S(\'\@   S)\@S\14S* jrBS+\1S\'\@   4S, jrC SVS-\1S.\DS/\%\1\"\D   4   S0\%\1\"\?   4   S1\'\5   SS4S2 jjrES3\DS4\DS/\%\1\"\D   4   S0\%\1\"\?   4   SS4
S5 jrFS6\&\@\G\H\R                  \R
                  4   S\14S7 jrJ\R                  " S8/ S9Q5      rL\R                  " S:5      rNS;\1S\L4S< jrO\R                  " S=/ S>Q5      rP\R                  " S?5      rQS;\1S\P4S@ jrRSA\1S\)\1SS4   4SB jrSS;\1S\ \1\%\1\14   4   4SC jrTSD\1SE\%\1\14   S\14SF jrUSG\&\1\D4   SH\&\1\D4   S\D4SI jrVSJ rW\R                  " SK5      rXSL\1S\ \1\'\@   4   4SM jrYSN\%\1\"\*   4   S\!\ \1\*4      4SO jrZ\R                  " SP5      R                  r\SQ\R                  S\14SR jr^SA\1S\14SS jr_ST\1S\%\1\14   4SU jr`g)WzHTTP 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)
ObjectDictunicode_type)TupleIterableListMappingIteratorDictUnionOptional	Awaitable	GeneratorAnyStr)Deque)Futurez 	i  namereturnc                     SR                  U R                  S5       Vs/ s H  oR                  5       PM     sn5      $ s  snf )z]Map a header name to Http-Header-Case.

>>> _normalize_header("coNtent-TYPE")
'Content-Type'
-)joinsplit
capitalize)r   ws     2/usr/lib/python3/dist-packages/tornado/httputil.py_normalize_headerr%   D   s1     88TZZ_=_\\^_=>>=s   ?c                   0   \ rS rSrSr\R                  S\\\	\   4   SS4S j5       r
\R                  S\\\4   SS4S j5       r
\R                  S\\\4   SS4S	 j5       r
\R                  S
\SS4S j5       r
S\R                  S
\SS4S jr
S\S\SS4S jrS\S\	\   4S jrS\\\\4      4S jrS\SS4S jr\S\SS 4S j5       rS\S\SS4S jrS\S\4S jrS\SS4S jrS\4S jrS\\R                     4S jrSS jr\rS\4S jr\rSrg)HTTPHeadersN   a  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                     g N selfr)   s     r$   __init__HTTPHeaders.__init__k           c                     g r+   r,   r-   s     r$   r/   r0   o   r1   r2   argsc                     g r+   r,   )r.   r4   s     r$   r/   r0   s   r1   r2   kwargsc                     g r+   r,   )r.   r6   s     r$   r/   r0   w   r1   r2   c                    0 U l         0 U l        S U l        [        U5      S:X  aU  [        U5      S:X  aF  [	        US   [
        5      (       a.  US   R                  5        H  u  p4U R                  X45        M     g U R                  " U0 UD6  g )N   r   )	_dict_as_list	_last_keylen
isinstancer'   get_alladdupdate)r.   r4   r6   kvs        r$   r/   r0   {   sr    
t9>c&kQ.:d1g{3S3SQ) * KK((r2   r   valuec                     [        U5      nX0l        X0;   aH  [        X   5      S-   [        U5      -   U R                  U'   U R                  U   R                  U5        gX U'   g)z#Adds a new value for the given key.,N)r%   r<   r
   r:   r;   appendr.   r   rD   	norm_names       r$   r@   HTTPHeaders.add   s^    %d+	"4?+c1Ju4EE JJy! MM)$++E2#Or2   c                 P    [        U5      nU R                  R                  U/ 5      $ )z2Returns all values for the given header as a list.)r%   r;   getr.   r   rI   s      r$   get_listHTTPHeaders.get_list   s#    %d+	}}  B//r2   c              #   n   #    U R                   R                  5        H  u  pU H  nX4v   M
     M     g7f)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)r.   r   valuesrD   s       r$   r?   HTTPHeaders.get_all   s2      !MM//1LDm#   2s   35linec                    US   R                  5       (       av  U R                  c  [        S5      eSUR                  [        5      -   nU R
                  U R                     S==   U-  ss'   U R                  U R                  ==   U-  ss'   g UR                  SS5      u  p4U R                  X4R                  [        5      5        g! [         a    [        S5      ef = f)	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 :r9   zno colon in header line)isspacer<   HTTPInputErrorlstripHTTP_WHITESPACEr;   r:   r!   
ValueErrorr@   strip)r.   rT   new_partr   rD   s        r$   
parse_lineHTTPHeaders.parse_line   s     7??~~%$%UVVT[[99HMM$..)"-9-JJt~~&(2&@"jja0 HHT;;78  @$%>??@s   C	 	Cheadersc                     U " 5       nUR                  S5       H8  nUR                  S5      (       a  USS nU(       d  M'  UR                  U5        M:     U$ )aL  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`.


NrW   )r!   endswithr`   )clsrb   hrT   s       r$   parseHTTPHeaders.parse   sR     E MM$'D}}T""CRytT"	 (
 r2   c                 V    [        U5      nX R                  U'   U/U R                  U'   g r+   r%   r:   r;   rH   s       r$   __setitem__HTTPHeaders.__setitem__   s(    %d+	 %

9$)7i r2   c                 2    U R                   [        U5         $ r+   )r:   r%   )r.   r   s     r$   __getitem__HTTPHeaders.__getitem__   s    zz+D122r2   c                 N    [        U5      nU R                  U	 U R                  U	 g r+   rl   rM   s      r$   __delitem__HTTPHeaders.__delitem__   s$    %d+	JJy!MM)$r2   c                 ,    [        U R                  5      $ r+   )r=   r:   r.   s    r$   __len__HTTPHeaders.__len__   s    4::r2   c                 ,    [        U R                  5      $ r+   )iterr:   rv   s    r$   __iter__HTTPHeaders.__iter__   s    DJJr2   c                     [        U 5      $ r+   )r'   rv   s    r$   copyHTTPHeaders.copy   s    4  r2   c                     / nU R                  5        H  u  p#UR                  U< SU< S35        M      SR                  U5      $ )Nz: rd    )r?   rG   r    )r.   linesr   rD   s       r$   __str__HTTPHeaders.__str__   s8    <<>KDLLtU34 *wwu~r2   )r;   r:   r<   )r   r'   ) __name__
__module____qualname____firstlineno____doc__typingoverloadr   strr   r/   r   Anyr@   rN   r   r?   r`   classmethodri   rm   rp   rs   intrw   r   r{   r~   __copy__r   __unicode____static_attributes__r,   r2   r$   r'   r'   N   s   8 __gc49n5 $   __gc3h/ D   __eCHo $   __   
)fjj 
)C 
)D 
)
$ 
$C 
$D 
$0S 0T#Y 0
$%S/2 $9s 9t 9, C M  2+ +C +D +
3 3 3% % %
  (6::.  ! H  Kr2   r'   c                   Z   \ rS rSrSrSrSrSr          SS\\	   S\\	   S\	S\\
   S\\   S	\\	   S
\\\	\S   4      S\S   S\S   S\\   SS4S jjr\S\\	\R$                  R&                  4   4S j5       rS\	4S jrS\4S jr SS\S\S\\4   4S jjrSS jrS\	4S jrSrg)HTTPServerRequest   a[	  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methoduriversionrb   bodyhostfilesHTTPFile
connectionHTTPConnection
start_lineRequestStartLineserver_connectionr   c                    U	b  U	u  pnXl         X l        X0l        U=(       d
    [        5       U l        U=(       d    SU l        [        USS 5      n[        USS 5      U l        [        USS5      U l        U=(       d$    U R                  R                  S5      =(       d    SU l
        [        U R                  R                  5       5      S   U l        U=(       d    0 U l        Xl        Xl        ["        R"                  " 5       U l        S U l        Ub  UR)                  S	5      u  U l        ol        [/        U R,                  S
S9U l        [2        R4                  " U R0                  5      U l        0 U l        g )Nr2   context	remote_ipprotocolhttpHostz	127.0.0.1r   ?Tkeep_blank_values)r   r   r   r'   rb   r   getattrr   r   rL   r   split_host_and_portlower	host_namer   r   r   time_start_time_finish_time	partitionpathqueryr   	argumentsr~   deepcopyquery_argumentsbody_arguments)r.   r   r   r   rb   r   r   r   r   r   r   r   seps                r$   r/   HTTPServerRequest.__init__\  s    !#- F/+-KC	 *i6 +t<V<CDLL,,V4C	,TYY__->?B[b
$!299; ?),s);&DIsJ'

dK#}}T^^< r2   c                    [        U S5      (       d  [        R                  R                  5       U l        SU R
                  ;   aM   [        U R
                  S   5      nUR                  5        H  u  p# X0R                  U'   M     U R                  $ U R                  $ ! [         a     M=  f = f! [         a     U R                  $ f = f)z0A dictionary of ``http.cookies.Morsel`` objects._cookiesCookie)	hasattrr   cookiesSimpleCookier   rb   parse_cookierQ   	Exception)r.   parsedrB   rC   s       r$   r   HTTPServerRequest.cookies  s     tZ(())+ M 4<<'!)$,,x*@AF !'!/0MM!, !/ }}t}}  ) ! !	! !  }}s$   B/ 4B
B,+B,/
CCc                 T    U R                   S-   U R                  -   U R                  -   $ )z+Reconstructs the full URL for this request.z://)r   r   r   rv   s    r$   full_urlHTTPServerRequest.full_url  s#    }}u$tyy0488;;r2   c                     U R                   c"  [        R                  " 5       U R                  -
  $ U R                   U R                  -
  $ )z?Returns the amount of time it took for this request to execute.)r   r   r   rv   s    r$   request_timeHTTPServerRequest.request_time  s<    $99;!1!111$$t'7'777r2   binary_formc                      U R                   c  gU R                   R                  R                  R                  US9$ ! [         a     gf = f)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   s     r$   get_ssl_certificate%HTTPServerRequest.get_ssl_certificate  sS    *	&??))00<<' =    		s   = ,= 
A
	A
c                 B   [        U R                  R                  SS5      U R                  U R                  U R
                  U R                  5        U R                  R                  5        H0  u  pU R                  R                  U/ 5      R                  U5        M2     g )NContent-Typer   )
parse_body_argumentsrb   rL   r   r   r   rQ   r   
setdefaultextend)r.   rB   rC   s      r$   _parse_bodyHTTPServerRequest._parse_body  sx    LL^R0IIJJLL	
 ''--/DANN%%a,33A6 0r2   c                     SnSR                  U Vs/ s H  o"< S[        X5      < 3PM     sn5      nU R                  R                  < SU< S3$ s  snf )N)r   r   r   r   r   r   z, =())r    r   	__class__r   )r.   attrsnr4   s       r$   __repr__HTTPServerRequest.__repr__  sI    Myy5I5aQ(895IJ>>22D99 Js   A)r   r   r   r   r   r   r   r   rb   r   r   r   r   r   r   r   r   r   r   r   )
NNzHTTP/1.0NNNNNNN)Fr   N)r   r   r   r   r   r   r   _body_futurer   r   r'   bytesr   r   objectr/   propertyr   r   Morselr   floatr   boolr   r   r   r   r   r,   r2   r$   r   r      sf   Zx DE L !%!!)- $"7;1537.2&!&! c]&! 	&!
 +&&! uo&! sm&! S$z"2234&! -.&! /0&! $F+&! 
&!P c4<<#6#667  ,<# <8e 8 #(	tT5 	!>
7:# :r2   r   c                       \ rS rSrSrSrg)rZ   i  zeException class for malformed HTTP requests or responses
from remote sources.

.. versionadded:: 4.0
r,   Nr   r   r   r   r   r   r,   r2   r$   rZ   rZ     s     	r2   rZ   c                       \ rS rSrSrSrg)HTTPOutputErrori  zBException class for errors in HTTP output.

.. versionadded:: 4.0
r,   Nr   r,   r2   r$   r   r     s    
 	r2   r   c                   @    \ rS rSrSrS\SSSS4S jrS\SS	4S
 jrSrg	)HTTPServerConnectionDelegatei  zWImplement this interface to handle requests from `.HTTPServer`.

.. versionadded:: 4.0
server_connrequest_connr   r   HTTPMessageDelegatec                     [        5       e)a:  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)r.   r   r   s      r$   start_request*HTTPServerConnectionDelegate.start_request  s     "##r2   Nc                     g)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,   )r.   r   s     r$   on_close%HTTPServerConnectionDelegate.on_close       	r2   r,   )	r   r   r   r   r   r   r   r   r   r,   r2   r$   r   r     s7    
$!$1A$	$F t r2   r   c                   r    \ rS rSrSrS\S   S\S\\S      4S jr	S	\
S\\S      4S
 jrSS jrSS jrSrg)r   i  zWImplement this interface to handle an HTTP request or response.

.. versionadded:: 4.0
r   r   ResponseStartLinerb   r   Nc                     g)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   rb   s      r$   headers_received$HTTPMessageDelegate.headers_received  s    " 	r2   chunkc                     g)zYCalled when a chunk of data has been received.

May return a `.Future` for flow control.
Nr,   r.   r  s     r$   data_received!HTTPMessageDelegate.data_received!  s    
 	r2   c                     g)z6Called after the last chunk of data has been received.Nr,   rv   s    r$   finishHTTPMessageDelegate.finish(  r1   r2   c                     g)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,   rv   s    r$   on_connection_close'HTTPMessageDelegate.on_connection_close,  r   r2   r,   r   )r   r   r   r   r   r   r'   r   r   r   r   r  r  r  r   r,   r2   r$   r   r     s]    AB  
)D/	"	&5 Xio-F r2   r   c            	       `    \ rS rSrSr SS\S   S\S\\   SS	4S
 jjr	S\SS	4S jr
SS jrSrg)r   i5  zQApplications use this interface to write their responses.

.. versionadded:: 4.0
Nr   r   rb   r  r   zFuture[None]c                     [        5       e)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   )r.   r   rb   r  s       r$   write_headersHTTPConnection.write_headers;  s    , "##r2   c                     [        5       e)zWrites a chunk of body data.

Returns a future for flow control.

.. versionchanged:: 6.0

   The ``callback`` argument was removed.
r   r  s     r$   writeHTTPConnection.writeS  s     "##r2   c                     [        5       e)z3Indicates that the last body data has been written.r   rv   s    r$   r  HTTPConnection.finish^  s    !##r2   r,   r+   r   )r   r   r   r   r   r   r'   r   r   r  r  r  r   r,   r2   r$   r   r   5  sY     "&	$AB$ $ 	$
 
$0	$5 	$^ 	$$r2   r   urlr4   .c           	         Uc  U $ [        U 5      n[        U[        5      (       a4  [        UR                  SS9nUR                  UR                  5       5        Ou[        U[        5      (       d  [        U[        5      (       a&  [        UR                  SS9nUR                  U5        O%SR                  [        U5      5      n[        U5      e[        U5      n[        US   US   US   US   UUS   45      n U $ )	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'
Tr   z7'args' parameter should be dict, list or tuple. Not {0}r   r9            )r   r>   dictr	   r   r   rQ   listtupleformattype	TypeErrorr   r   )r  r4   
parsed_urlparsed_queryerrfinal_querys         r$   
url_concatr%  c  s    & |
#J$ !1!1TJDJJL)	D$		:dE#:#: !1!1TJD!GNNJ
 nL)K
qMqMqMqMqM	
	C Jr2   c                   8    \ rS rSr% Sr\\S'   \\S'   \\S'   Srg)r   i  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_typer,   N)	r   r   r   r   r   r   __annotations__r   r   r,   r2   r$   r   r     s     M
Kr2   r   range_headerc                 $   U R                  S5      u  pnUR                  5       UR                  5       p1US:w  a  gUR                  S5      u  pBn [        U5      n[        U5      nUb  Uc  US:w  a  U* nSnXg4$ US-  nXg4$ ! [         a     gf = f)a  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   r9   )r   r^   _int_or_noner]   )r*  unit_rD   start_bend_bstartends           r$   _parse_request_ranger3    s    > "++C0NDU**,%w,GW%5! =ax < 1HC<  s   B 
BBr1  r2  totalc                 P    U =(       d    Sn U=(       d    US-
  nSU < SU< SU< 3$ )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   r9   zbytes r   /r,   )r1  r2  r4  s      r$   _get_content_ranger7    s(     JQE<%1
C$c511r2   valc                 F    U R                  5       n U S:X  a  g [        U 5      $ )Nr   )r^   r   )r8  s    r$   r,  r,    s     
))+C
bys8Or2   r(  r   r   r   rb   c                    U R                  S5      (       am  U(       a  SU;   a  [        SUS   -  5      e [        USS9nUR	                  5        H/  u  pxU(       d  M  UR                  U/ 5      R                  U5        M1     gU R                  S5      (       a  U(       a  SU;   a  [        SUS   -  5      e U R                  S	5      n	U	 HL  n
U
R                  5       R                  S
5      u  pnUS:X  d  M-  U(       d  M6  [        [        U5      XU5          g   [        S5      eg! [         a  n[        SU-  5      UeSnAff = f! [         a  n[        SU-  5      UeSnAff = f)a.  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: %sTr   z&Invalid x-www-form-urlencoded body: %sNzmultipart/form-data;r   boundaryzmultipart boundary not foundzInvalid multipart/form-data: %s)
startswithrZ   r   r   rQ   r   r   r!   r^   r   parse_multipart_form_datar   )r(  r   r   r   rb   uri_argumentser   rR   fieldsfieldrB   r   rC   s                 r$   r   r     sx    BCC)W4 2W=O5PP 	V*44HM *//1LDv$$T2.55f= 2 
	 	 !6	7	7)W4 2W=O5PP 
	O!'',F!KKM33C8	
?qq-d1gtN	   %%CDD 
8  	V !IA!MNTUU	V&  	O !BQ!FGQN	OsA   
D( 9<E	 9E	 E	 E	 (
E2EE	
E'E""E'r<  datac           	      z   U R                  S5      (       a  U R                  S5      (       a  U SS n UR                  SU -   S-   5      nUS:X  a  [        S5      eUSU R	                  SU -   S-   5      nU GHA  nU(       d  M  UR                  S5      nUS:X  a  [        S	5      e[        R                  USU R                  S
5      5      nUR                  SS5      n	[        U	5      u  pU
S:w  d  UR                  S5      (       d  [        S5      eXgS-   S nUR                  S5      (       d  [        S5      eUS   nUR                  S5      (       aA  UR                  SS5      nUR                  U/ 5      R                  [        US   XS95        GM   UR                  U/ 5      R                  U5        GMD     g)aA  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.
   "r9   rW   s   --z4Invalid multipart/form-data: no final boundary foundNs   
s   

z#multipart/form-data missing headerszutf-8zContent-Dispositionr   z	form-datazInvalid multipart/form-data   r   z multipart/form-data missing namer'  r   zapplication/unknown)r'  r   r(  )r=  rf   rfindrZ   r!   findr'   ri   decoderL   _parse_headerr   rG   r   )r<  rC  r   r   final_boundary_indexpartsparteohrb   disp_headerdispositiondisp_paramsrD   r   ctypes                  r$   r>  r>    s   , 4  X%6%6t%<%<Ab>::eh&6&>?r!STT&&'--eh.>.HIEii$"9 !FGG##D#J$5$5g$>?kk"7<#0#= +%T]]7-C-C !>??1Wr"v&& !CDD6"??:&&KK0EFET2&--(45   r*11%8/ r2   tsc                    [        U [        [        45      (       a  U nO[        U [        [        R
                  45      (       a  [        R                  " U 5      nOR[        U [        R                  5      (       a%  [        R                  " U R                  5       5      nO[        SU -  5      e[        R                  R                  USS9$ )ay  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)rT  time_nums     r$   format_timestampr`  O  s     "sEl##	B 0 01	2	2??2&	B))	*	*??2??#454r9::;;!!(4!88r2   r   )r   r   r   z^HTTP/1\.[0-9]$rT   c                      U R                  S5      u  pn[        R	                  U5      (       d  [        SU-  5      e[        XU5      $ ! [         a    [        S5      ef = f)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')
rV   zMalformed HTTP request linez/Malformed HTTP version in HTTP Request-Line: %r)r!   r]   rZ   _http_version_rematchr   )rT   r   r   r   s       r$   parse_request_start_linerd  o  so    < $

3g
 !!'**=G
 	
 F'22  < :;;<s   A
 
A r   )r   codereasonz (HTTP/1.[0-9]) ([0-9]+) ([^\r]*)c                     [        U 5      n [        R                  U 5      nU(       d  [        S5      e[	        UR                  S5      [        UR                  S5      5      UR                  S5      5      $ )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 liner9   r  r  )r
   _http_response_line_rerc  rZ   r   groupr   )rT   rc  s     r$   parse_response_start_linerj    sY     dD"((.E@AAU[[^SQ-@%++a.QQr2   sc              #     #    U S S S:X  a  U SS  n U R                  S5      nUS:  a{  U R                  SSU5      U R                  SSU5      -
  S-  (       aL  U R                  SUS-   5      nUS:  a1  U R                  SSU5      U R                  SSU5      -
  S-  (       a  ML  US:  a  [        U 5      nU S U nUR                  5       v   XS  n U S S S:X  a  M  g g 7f)Nr9   r;  r   "z\"r  )rI  countr=   r^   )rk  r2  fs      r$   _parseparamrp    s     
BQ%3,abEffSkAg17733/!''%C2HHAM&&cAg&C Ag17733/!''%C2HHAMM7a&CdsGggidG BQ%3,s   BC#5CCc                 4   [        SU -   5      n[        U5      nS/nU Hn  nUR                  S5      nUS:  d  M  USU R                  5       R	                  5       nXES-   S R                  5       nUR                  U[        U5      45        Mp     [        R                  R                  U5      nUR                  S5        0 n	U HN  u  pj[        R                  R                  U
5      n[        U5      S:  a  US   S:X  a  US	   S:X  a  USS	 nXyU'   MP     X)4$ )
a1  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;  )DummyrD   r   r   Nr9   r  rm  rW   )rp  nextrI  r^   r   rG   r
   r\  r]  decode_paramspopcollapse_rfc2231_valuer=   )rT   rM  keyparamspir   rD   decoded_paramspdictdecoded_values              r$   rK  rK    s    d
#E
u+C !FFF3K6Ra5;;=&&(D!egJ$$&EMM4E!234  [[..v6NqE-22=Au:?uQx3593C!BKEd	  .
 :r2   rw  r|  c                     U(       d  U $ U /n[        UR                  5       5       H3  u  p4Uc  UR                  U5        M  UR                  U< SU< 35        M5     SR                  U5      $ )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'
r   z; )sortedrQ   rG   r    )rw  r|  outrB   rC   s        r$   _encode_headerr    s]     
%Cu{{}%9JJqM JJ!Q'( & 99S>r2   usernamepasswordc                     [        U [        5      (       a  [        R                  " SU 5      n [        U[        5      (       a  [        R                  " SU5      n[	        U 5      S-   [	        U5      -   $ )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   )r  r  s     r$   encode_username_passwordr    sZ     (L))((9(L))((9>D 4>11r2   c                  *    SS K n U R                  5       $ )Nr   )doctestDocTestSuite)r  s    r$   doctestsr    s    !!r2   z^(.+):(\d+)$netlocc                     [         R                  U 5      nU(       a.  UR                  S5      n[        UR                  S5      5      nX#4$ U nSnX#4$ )z{Returns ``(host, port)`` tuple from ``netloc``.

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

.. versionadded:: 4.1
r9   r  N)
_netloc_rerc  ri  r   )r  rc  r   ports       r$   r   r     sT     V$E{{1~5;;q>" < <r2   qsc              #   Z   #    U R                  5        H  u  pU H  nX4v   M
     M     g7f)z_Generator converting a result of ``parse_qs`` back to name-value pairs.

.. versionadded:: 5.0
N)rQ   )r  rB   vsrC   s       r$   	qs_to_qslr    s*     
 A&L  s   )+z\\(?:([0-3][0-7][0-7])|(.))mc                 P    U S   (       a  [        [        U S   S5      5      $ U S   $ )Nr9      r  )chrr   )r  s    r$   _unquote_replacer    s'    t3qtQ<  tr2   c                 |    U b  [        U 5      S:  a  U $ U S   S:w  d	  U S   S:w  a  U $ U SS n [        [        U 5      $ )zHandle double quotes and escaping in cookie values.

This method is copied verbatim from the Python 3.13 standard
library (http.cookies._unquote) so we don't have to depend on
non-public interfaces.
r  r   rm  rW   r9   )r=   _unquote_subr  )rk  s    r$   _unquote_cookier  &  sO     	yCFQJts{aesl 	
!BA (!,,r2   cookiec                 6   0 nU R                  [        S5      5       Hx  n[        S5      U;   a  UR                  [        S5      S5      u  p4O[        S5      UpCUR                  5       UR                  5       pCU(       d	  U(       d  Mk  [        U5      X'   Mz     U$ )aC  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   r9   r   )r!   r   r^   r  )r  
cookiedictr  rw  r8  s        r$   r   r   A  s     Jc#h's8u{{3s8Q/HC 2w99;		S##-c2JO ( r2   r+   )ar   rX  collections.abccollectionsr~   rZ  email.utilsr\  	functoolsr   http.clientr   http.cookiesr   resslr   r   r  urllib.parser   r   r   r	   tornado.escaper
   r   r   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   rZ   r   r   r   r   r%  r   r   r3  r7  r,  r   r   r>  r   r  rW  r`  
namedtupler   compilerb  rd  r   rh  rj  rp  rK  r  r  r  r  r   r  subr  Matchr  r  r   r,   r2   r$   <module>r     s          !  	    C C ; ; 1
 
     
  4?C ?C ? ?h+//00 hV[: [:|	Y 		i 	6 :+& +\+$V +$\,	,
d38nd5c?3U5c?C;O5PP,
 	,^z  00eHSM8C=0120f2hsm 2(3- 2 2PS 2c hsm  &*+O+O
+O Ce$%+O T(^#$	+O
 k"+O 
+O\3939
39 Ce$%39 T(^#$	39
 
39l9c5%!1!183D3DDE990 ))5 
 ::01 33 3+; 3*  **6 
 $GH RC R,= R.
3 
9S$_5 
   c4S>&9 :  F DcN s (2CJ2+0e+<2
2 " ZZ(
 c8C=.@(A "$sDL() huS&[7I.J  zz89== S -s -s -6 c3h r2   