a
    mzfLF                     @   s$  d 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	m
Z
mZmZmZmZmZ z(ddlmZmZ ddlmZmZmZ W n6 ey   ddlmZmZ ddlmZmZmZ Y n0 g d	Ze Zd
e_ G dd deZdTddZeddd ZZed Z Z!ed Z"Z#ed Z$Z%G dd deZ&e&Z'G dd de&Z(e(Z)G dd de&Z*e*Z+G dd deZ,e,Z-G dd de&Z.e.Z/G dd  d eZ0e0Z1G d!d" d"eZ2e2Z3G d#d$ d$eZ4e4Z5G d%d& d&eZ6dUd'd(Z7e7Z8G d)d* d*eZ9e9Z:G d+d, d,eZ;e;Z<G d-d. d.eZ=e=Z>G d/d0 d0eZ?e?Z@G d1d2 d2eZAeAZBG d3d4 d4eZCeCZDG d5d6 d6eZEdVd7d8ZFeFZGG d9d: d:eZHdWd;d<ZIeIZJG d=d> d>ejKZLdXd@dAZMdYdBdCZNdDdE ZOdFdG ZPdZdHdIZQdJdK ZRdLdM ZSdNdO ZTdPdQ ZUeUeT_Ve  ZWZXdReW_ eYdSkr ddlZZZeZ[  dS )[z-
Web API (wrapper around WSGI)
(from web.py)
    N)BytesIO)urljoin   )dictaddintgetsafestrstoragestorifythreadeddict)unquotequote)CookieErrorMorselSimpleCookie)3configheaderdebuginputdata	setcookiecookiesctx	HTTPErrorOKCreatedAccepted	NoContentokcreatedaccepted	nocontentRedirectFoundSeeOtherNotModifiedTempRedirectredirectfoundseeothernotmodifiedtempredirect
BadRequestUnauthorized	ForbiddenNotFoundNoMethodNotAcceptableConflictGonePreconditionFailedUnsupportedMediaTypeUnavailableForLegalReasons
badrequestunauthorized	forbiddennotfoundnomethodnotacceptableconflictgonepreconditionfailedunsupportedmediatypeunavailableforlegalreasonsInternalErrorinternalerrorz
A configuration object for various aspects of web.py.

`debug`
   : when True, enables reloading, disabled template caching and sets internalerror to debugerror.
c                   @   s   e Zd Zi dfddZdS )r    c                 C   s8   |t _| D ]\}}t|| q|| _t| | d S N)r   statusitemsr   r   	Exception__init__)selfrE   headersr   kv rM   8/var/www/media/lib/python3.9/site-packages/web/webapi.pyrH   Z   s
    zHTTPError.__init__N)__name__
__module____qualname__rH   rM   rM   rM   rN   r   Y   s   r   c                    sd   |d u r  ddd }  ddd dd}|p:d  }|i f fdd	}t|ttf||dS )N r   rC   z`%s` statusc                    s   t |  || d S rD   r   rH   )rI   r   rJ   rE   rM   rN   rH   j   s    z_status_code.<locals>.__init__)__doc__rH   )splitreplacetyper   object)rE   r   	classname	docstringrH   rM   rT   rN   _status_codeb   s    r\   z200 OKrC   )r   z201 Createdz202 Acceptedz204 No Contentc                   @   s   e Zd ZdZdddZdS )r!   z#A `301 Moved Permanently` redirect.301 Moved PermanentlyFc                 C   sN   t tj|}|dr0|r"tj}ntj}|| }d|d}t| ||d dS )z
        Returns a `status` redirect to the new URL.
        `url` is joined with the base URL so that things like
        `redirect("about") will work properly.
        /	text/html)Content-TypeZLocationrC   N)r   r   path
startswithZrealhomehomer   rH   )rI   urlrE   absolutenewlocrc   rJ   rM   rM   rN   rH   |   s    

zRedirect.__init__N)r]   FrO   rP   rQ   rU   rH   rM   rM   rM   rN   r!   y   s   r!   c                   @   s   e Zd ZdZdddZdS )r"   zA `302 Found` redirect.Fc                 C   s   t j| |d|d d S )Nz	302 Foundre   r!   rH   rI   rd   re   rM   rM   rN   rH      s    zFound.__init__N)Frg   rM   rM   rM   rN   r"      s   r"   c                   @   s   e Zd ZdZdddZdS )r#   zA `303 See Other` redirect.Fc                 C   s   t j| |d|d d S )Nz303 See Otherrh   ri   rj   rM   rM   rN   rH      s    zSeeOther.__init__N)Frg   rM   rM   rM   rN   r#      s   r#   c                   @   s   e Zd ZdZdd ZdS )r$   zA `304 Not Modified` status.c                 C   s   t | d d S )Nz304 Not ModifiedrS   )rI   rM   rM   rN   rH      s    zNotModified.__init__Nrg   rM   rM   rM   rN   r$      s   r$   c                   @   s   e Zd ZdZdddZdS )r%   z$A `307 Temporary Redirect` redirect.Fc                 C   s   t j| |d|d d S )Nz307 Temporary Redirectrh   ri   rj   rM   rM   rN   rH      s    zTempRedirect.__init__N)Frg   rM   rM   rM   rN   r%      s   r%   c                   @   s   e Zd ZdZdZdddZdS )r+   z`400 Bad Request` error.zbad requestNc                 C   s&   d}ddi}t | |||p| j d S )Nz400 Bad Requestr`   r_   r   rH   messagerI   rl   rE   rJ   rM   rM   rN   rH      s    zBadRequest.__init__)NrO   rP   rQ   rU   rl   rH   rM   rM   rM   rN   r+      s   r+   c                   @   s   e Zd ZdZdZdddZdS )r,   z`401 Unauthorized` error.r7   Nc                 C   s&   d}ddi}t | |||p| j d S )Nz401 Unauthorizedr`   r_   rk   rm   rM   rM   rN   rH      s    zUnauthorized.__init__)Nrn   rM   rM   rM   rN   r,      s   r,   c                   @   s   e Zd ZdZdZdddZdS )r-   z`403 Forbidden` error.r8   Nc                 C   s&   d}ddi}t | |||p| j d S )Nz403 Forbiddenr`   r_   rk   rm   rM   rM   rN   rH      s    zForbidden.__init__)Nrn   rM   rM   rM   rN   r-      s   r-   c                   @   s   e Zd ZdZdZdddZdS )	_NotFoundz`404 Not Found` error.z	not foundNc                 C   s&   d}ddi}t | |||p| j d S )Nz404 Not Foundr`   ztext/html; charset=utf-8rk   rm   rM   rM   rN   rH      s    z_NotFound.__init__)Nrn   rM   rM   rM   rN   ro      s   ro   c                 C   s.   | rt | S tdr$tjd  S t  S dS )zIReturns HTTPError with '404 Not Found' error from the active application.	app_stackN)ro   r   getrp   r9   rl   rM   rM   rN   r.      s
    
r.   c                   @   s   e Zd ZdZdZdddZdS )r/   z!A `405 Method Not Allowed` error.zmethod not allowedNc                    sR   d}i }d|d< g d} r. fdd|D }d ||d< t| ||| j d S )	Nz405 Method Not Allowedr_   r`   )GETHEADPOSTPUTDELETEc                    s   g | ]}t  |r|qS rM   )hasattr).0methodclsrM   rN   
<listcomp>      z%NoMethod.__init__.<locals>.<listcomp>z, ZAllow)joinr   rH   rl   )rI   r}   rE   rJ   methodsrM   r|   rN   rH     s    zNoMethod.__init__)Nrn   rM   rM   rM   rN   r/      s   r/   c                   @   s   e Zd ZdZdZdddZdS )r0   z`406 Not Acceptable` error.znot acceptableNc                 C   s&   d}ddi}t | |||p| j d S )Nz406 Not Acceptabler`   r_   rk   rm   rM   rM   rN   rH     s    zNotAcceptable.__init__)Nrn   rM   rM   rM   rN   r0     s   r0   c                   @   s   e Zd ZdZdZdddZdS )r1   z`409 Conflict` error.r<   Nc                 C   s&   d}ddi}t | |||p| j d S )Nz409 Conflictr`   r_   rk   rm   rM   rM   rN   rH   $  s    zConflict.__init__)Nrn   rM   rM   rM   rN   r1     s   r1   c                   @   s   e Zd ZdZdZdddZdS )r2   z`410 Gone` error.r=   Nc                 C   s&   d}ddi}t | |||p| j d S )Nz410 Goner`   r_   rk   rm   rM   rM   rN   rH   2  s    zGone.__init__)Nrn   rM   rM   rM   rN   r2   -  s   r2   c                   @   s   e Zd ZdZdZdddZdS )r3   z `412 Precondition Failed` error.zprecondition failedNc                 C   s&   d}ddi}t | |||p| j d S )Nz412 Precondition Failedr`   r_   rk   rm   rM   rM   rN   rH   @  s    zPreconditionFailed.__init__)Nrn   rM   rM   rM   rN   r3   ;  s   r3   c                   @   s   e Zd ZdZdZdddZdS )r4   z#`415 Unsupported Media Type` error.zunsupported media typeNc                 C   s&   d}ddi}t | |||p| j d S )Nz415 Unsupported Media Typer`   r_   rk   rm   rM   rM   rN   rH   N  s    zUnsupportedMediaType.__init__)Nrn   rM   rM   rM   rN   r4   I  s   r4   c                   @   s   e Zd ZdZdZdddZdS )_UnavailableForLegalReasonsz*`451 Unavailable For Legal Reasons` error.zunavailable for legal reasonsNc                 C   s&   d}ddi}t | |||p| j d S )Nz!451 Unavailable For Legal Reasonsr`   r_   rk   rm   rM   rM   rN   rH   \  s    z$_UnavailableForLegalReasons.__init__)Nrn   rM   rM   rM   rN   r   W  s   r   c                 C   s.   | rt | S tdr$tjd  S t  S dS )z]Returns HTTPError with '415 Unavailable For Legal Reasons' error from the active application.rp   rq   N)r   r   rr   rp   r@   rs   rM   rM   rN   r5   b  s
    
r5   c                   @   s   e Zd ZdZdZdddZdS )_InternalErrorz500 Internal Server Error`.zinternal server errorNc                 C   s&   d}ddi}t | |||p| j d S )Nz500 Internal Server Errorr`   r_   rk   rm   rM   rM   rN   rH   t  s    z_InternalError.__init__)Nrn   rM   rM   rM   rN   r   o  s   r   c                 C   s.   | rt | S tdr$tjd  S t  S dS )zNReturns HTTPError with '500 internal error' error from the active application.rp   rq   N)r   r   rr   rp   rB   rs   rM   rM   rN   rA   z  s
    
rA   c                   @   s   e Zd ZdZdddZdS )cgiFieldStorageaA  
    Subclass cgi.FieldStorage, as read_binary expects fp to return
    bytes. If the headers do not contain a content-disposition with a
    filename, cgi.FieldStorage's make_file will create a TemporaryFile
    with `w+` flags. The write to that temporary file will fail, due
    to incorrect encoding in Python 3.
    Nc                 C   s
   t dS )z
        For backwards compatibility with Python 2, make_file accepted
        a binary flag. This was unused, and removed in Python 3.
        zwb+)tempfileTemporaryFile)rI   binaryrM   rM   rN   	make_file  s    zcgiFieldStorage.make_file)N)rO   rP   rQ   rU   r   rM   rM   rM   rN   r     s   r   Fc                 C   s|   t | t | } }d| v s2d| v s2d|v s2d|v r:td|du rhtjD ]\}}| |  krH dS qHtj| |f dS )z
    Adds the header `hdr: value` with the response.

    If `unique` is True and a header with that name already exists,
    it doesn't add a new one.
    
zinvalid characters in headerTN)r   
ValueErrorr   rJ   lowerappend)hdrvalueuniquehrL   rM   rM   rN   r     s     r   c                    s  | pd} dd }t j }i  }}|  dv r|d dv r|dd d	r|t d
}|s|d }t||dd}|t _n0t }t	|t
r|d}t|}t||dd}||}|  dv rd|d< |t|dd} fdd t fddt|| D S )z2Returns storage object with GET or POST arguments.bothc                    s&    j d u rg  _ t fdd D S )Nc                    s   g | ]}| | fqS rM   rM   )rz   rK   fsrM   rN   r~     r   z-rawinput.<locals>.dictify.<locals>.<listcomp>)listdictr   rM   r   rN   dictify  s    
zrawinput.<locals>.dictify)r   postputpatchREQUEST_METHOD)rv   rw   PATCHCONTENT_TYPErC   z
multipart/_fieldstorage
wsgi.inputr   )fpenvironkeep_blank_valueszutf-8)r   rr   rt   )r   r   c                    s4   t | tr fdd| D S | jd u r,| jS | S d S )Nc                    s   g | ]} |qS rM   rM   )rz   xprocess_fieldstoragerM   rN   r~     r   z:rawinput.<locals>.process_fieldstorage.<locals>.<listcomp>)
isinstancer   filenamer   r   r   rM   rN   r     s
    

z&rawinput.<locals>.process_fieldstoragec                    s   g | ]\}}| |fqS rM   rM   rz   rK   rL   r   rM   rN   r~     r   zrawinput.<locals>.<listcomp>)r   envcopyr   rr   rb   r   r   r   r   strencoder   r   r   rF   )r{   r   eabr   drM   r   rN   rawinput  s.    



r   c                  O   sV   | dd}t|}z$|dd t|g| R i |W S  tyP   t Y n0 dS )z
    Returns a `storage` object with the GET and POST arguments.
    See `storify` for how `requireds` and `defaults` work.
    _methodr   Z_unicodeTN)popr   
setdefaultr	   KeyErrorr6   )	requiredsdefaultsr   outrM   rM   rN   r     s    r   c                  C   sT   dt vrNt jddkr*t jd  t _n$tt jdd} t jd | t _t jS )z'Returns the data sent with the request.r   ZHTTP_TRANSFER_ENCODINGchunkedr   CONTENT_LENGTHr   )r   r   rr   readr   r   )ZclrM   rM   rN   r     s    r   c           	      C   s   t  }t| t| } }|| |t| t|tr@|dk r@d}||d< |pTtjd |d< |rf||d< |rr||d< |r~d|d	< | }|r|	 d
v r|d| 7 }t
d| dS )zSets a cookie.r   i 6eexpiresr^   ra   domainsecureThttponly)strictZlaxnonez; SameSite=%sz
Set-CookieN)r   r   setr   r   intr   ZhomepathOutputStringr   r   )	namer   r   r   r   r   ra   samesitemorselrM   rM   rN   r     s"    r   c                 C   s   d| v rt  }z||  W nJ tyf   t  }| dD ]&}z|| W q: ty^   Y q:0 q:Y n0 tdd | D }nHi }| dD ]8}|dd}t|dkr|\}}t| || < q|S )a  Parse a HTTP_COOKIE header and return dict of cookie names and decoded values.

    >>> sorted(parse_cookies('').items())
    []
    >>> sorted(parse_cookies('a=1').items())
    [('a', '1')]
    >>> sorted(parse_cookies('a=1%202').items())
    [('a', '1 2')]
    >>> sorted(parse_cookies('a=Z%C3%A9Z').items())
    [('a', 'Z\xc3\xa9Z')]
    >>> sorted(parse_cookies('a=1; b=2; c=3').items())
    [('a', '1'), ('b', '2'), ('c', '3')]

    # TODO: cclauss re-enable this test
    # >>> sorted(parse_cookies('a=1; b=w("x")|y=z; c=3').items())
    # [('a', '1'), ('b', 'w('), ('c', '3')]

    >>> sorted(parse_cookies('a=1; b=w(%22x%22)|y=z; c=3').items())
    [('a', '1'), ('b', 'w("x")|y=z'), ('c', '3')]

    >>> sorted(parse_cookies('keebler=E=mc2').items())
    [('keebler', 'E=mc2')]
    >>> sorted(parse_cookies(r'keebler="E=mc2; L=\"Loves\"; fudge=\012;"').items())
    [('keebler', 'E=mc2; L="Loves"; fudge=\n;')]
    ";c                 S   s   g | ]\}}|t |jfqS rM   )r   r   r   rM   rM   rN   r~   ;  r   z!parse_cookies.<locals>.<listcomp>=r      )	r   loadr   rV   r   rF   lenr   strip)http_cookiecookie
attr_valuer   	key_valuekeyr   rM   rM   rN   parse_cookies  s&    r   c                  O   s^   dt vr t jdd}t|t _ztt jg| R i |W S  tyX   t  t Y n0 dS )a(  Returns a `storage` object with all the request cookies in it.

    See `storify` for how `requireds` and `defaults` work.

    This is forgiving on bad HTTP_COOKIE input, it tries to parse at least
    the cookies it can.

    The values are converted to unicode if _unicode=True is passed.
    _parsed_cookiesZHTTP_COOKIErC   N)	r   r   rr   r   r   r	   r   r6   StopIteration)r   r   r   rM   rM   rN   r   G  s    
r   c                  G   sB   zt jd }W n   tj}Y n0 | D ]}tt||d q&dS )z=
    Prints a prettyprinted version of `args` to stderr.
    wsgi.errors)filerC   )r   r   sysstderrprintpprintpformat)argsr   argrM   rM   rN   r   ]  s    r   c                 C   s0   zt jd }W n   tj}Y n0 ||  d S )Nr   )r   r   r   r   write)r   r   rM   rM   rN   _debugwritej  s
    r   a%  
A `storage` object containing various information about the request:

`environ` (aka `env`)
   : A dictionary containing the standard WSGI environment variables.

`host`
   : The domain (`Host` header) requested by the user.

`home`
   : The base path for the application.

`ip`
   : The IP address of the requester.

`method`
   : The HTTP method used.

`path`
   : The path request.

`query`
   : If there are no query arguments, the empty string. Otherwise, a `?` followed
     by the query string.

`fullpath`
   : The full path requested, including query arguments (`== path + query`).

### Response Data

`status` (default: "200 OK")
   : The status code to be used in the response.

`headers`
   : A list of 2-tuples to be used in the response.

`output`
   : A string to be used as the response.
__main__)NNN)N)N)N)F)N)rC   NFFNN)\rU   cgir   r   r   ior   urllib.parser   utilsr   r   r   r   r	   r
   r   r   http.cookiesr   r   r   ImportErrorurllibCookie__all__r   rG   r   r\   r   r   r   r   r   r   r    r   r!   r&   r"   r'   r#   r(   r$   r)   r%   r*   r+   r6   r,   r7   r-   r8   ro   r.   r9   r/   r:   r0   r;   r1   r<   r2   r=   r3   r>   r4   r?   r   r5   r@   r   rA   rB   FieldStorager   r   r   r   r   r   r   r   r   r   r   r   contextrO   doctesttestmodrM   rM   rM   rN   <module>   s    :	








0      
5
(
