o
    'h8                     @  s  d Z ddlmZ ddlZddlmZ ddlmZ ddl	m
Z
 ddlmZ dd	lmZ dd
lmZ ejrEddlmZ ddlmZ ddlmZ G dd deZG dd deZefd&ddZG dd dZG dd dZG d d! d!ZG d"d# d#ZG d$d% d%ZdS )'a  
WSGI Protocol Linter
====================

This module provides a middleware that performs sanity checks on the
behavior of the WSGI server and application. It checks that the
:pep:`3333` WSGI spec is properly implemented. It also warns on some
common HTTP errors such as non-empty responses for 304 status codes.

.. autoclass:: LintMiddleware

:copyright: 2007 Pallets
:license: BSD-3-Clause
    )annotationsN)TracebackType)urlparse)warn   )Headers)is_entity_header)FileWrapper)StartResponse)WSGIApplication)WSGIEnvironmentc                   @     e Zd ZdZdS )WSGIWarningz Warning class for WSGI warnings.N__name__
__module____qualname____doc__ r   r   T/var/www/html/olx_land/venv/lib/python3.10/site-packages/werkzeug/middleware/lint.pyr   !       r   c                   @  r   )HTTPWarningz Warning class for HTTP warnings.Nr   r   r   r   r   r   %   r   r   contextstrobjobjectneedtypereturnNonec                 C  s<   t ||urt| d|jdt |jdtdd d S d S )Nz
 requires z, got .   
stacklevel)r   r   r   r   )r   r   r   r   r   r   
check_type)   s   
r$   c                   @  s>   e Zd ZdddZdd
dZdddZdddZdddZdS )InputStreamstreamt.IO[bytes]r   r   c                 C  
   || _ d S N_streamselfr&   r   r   r   __init__3      
zInputStream.__init__argst.Anybytesc                 G  sB   t |dkrtdtdd nt |dkrtdtdd | jj| S )Nr   zWSGI does not guarantee an EOF marker on the input stream, thus making calls to 'wsgi.input.read()' unsafe. Conforming servers may never return from this call.r   r"      z2Too many parameters passed to 'wsgi.input.read()'.)lenr   r   r+   readr-   r0   r   r   r   r5   6   s   zInputStream.readc                 G  sL   t |dkrtdtdd nt |dkrtdtdd ntd| jj| S )Nr   z_Calls to 'wsgi.input.readline()' without arguments are unsafe. Use 'wsgi.input.read()' instead.r   r"   r3   z~'wsgi.input.readline()' was called with a size hint. WSGI does not support this, although it's available on all major servers.z5Too many arguments passed to 'wsgi.input.readline()'.)r4   r   r   	TypeErrorr+   readliner6   r   r   r   r8   G   s   zInputStream.readlinet.Iterator[bytes]c                 C  s6   zt | jW S  ty   tdtdd t d Y S w )Nz'wsgi.input' is not iterable.r   r"   r   )iterr+   r7   r   r   r-   r   r   r   __iter__Z   s   zInputStream.__iter__c                 C     t dtdd | j  d S )Nz(The application closed the input stream!r   r"   r   r   r+   closer;   r   r   r   r?   a      zInputStream.closeN)r&   r'   r   r   )r0   r1   r   r2   )r   r9   r   r   )r   r   r   r.   r5   r8   r<   r?   r   r   r   r   r%   2   s    



r%   c                   @  s>   e Zd ZdddZdd	d
ZdddZdddZdddZdS )ErrorStreamr&   	t.IO[str]r   r   c                 C  r(   r)   r*   r,   r   r   r   r.   g   r/   zErrorStream.__init__sr   c                 C  s   t d|t | j| d S )Nzwsgi.error.write())r$   r   r+   writer-   rD   r   r   r   rE   j   s   zErrorStream.writec                 C  s   | j   d S r)   )r+   flushr;   r   r   r   rG   n   s   zErrorStream.flushseqt.Iterable[str]c                 C  s   |D ]}|  | qd S r)   )rE   )r-   rH   liner   r   r   
writelinesq   s   zErrorStream.writelinesc                 C  r=   )Nz(The application closed the error stream!r   r"   r>   r;   r   r   r   r?   u   r@   zErrorStream.closeN)r&   rC   r   r   )rD   r   r   r   rA   )rH   rI   r   r   )r   r   r   r.   rE   rG   rK   r?   r   r   r   r   rB   f   s    



rB   c                   @  s    e Zd ZdddZdddZdS )GuardedWriterE   t.Callable[[bytes], object]chunks	list[int]r   r   c                 C  s   || _ || _d S r)   )_write_chunks)r-   rE   rN   r   r   r   r.   {   s   
zGuardedWrite.__init__rD   r2   c                 C  s*   t d|t | | | jt| d S )Nzwrite())r$   r2   rP   rQ   appendr4   rF   r   r   r   __call__   s   
zGuardedWrite.__call__N)rE   rM   rN   rO   r   r   )rD   r2   r   r   )r   r   r   r.   rS   r   r   r   r   rL   z   s    
rL   c                   @  s>   e Zd Zdd	d
ZdddZdddZdddZdddZdS )GuardedIteratoriteratort.Iterable[bytes]headers_settuple[int, Headers]rN   rO   r   r   c                 C  s(   || _ t|j| _d| _|| _|| _d S )NF)	_iteratorr:   __next___nextclosedrW   rN   )r-   rU   rW   rN   r   r   r   r.      s
   
zGuardedIterator.__init__c                 C  s   | S r)   r   r;   r   r   r   r<      s   zGuardedIterator.__iter__r2   c                 C  sP   | j r
tdtdd |  }| jstdtdd td|t | jt	| |S )Nz Iterated over closed 'app_iter'.r   r"   z8The application returned before it started the response.zapplication iterator items)
r\   r   r   r[   rW   r$   r2   rN   rR   r4   )r-   rvr   r   r   rZ      s   zGuardedIterator.__next__c                 C  s*  d| _ t| jdr| j  | jr| j\}}t| j}|jdtd}|dkrQ|D ]\}}|	 }|dvrCt
|rCtd|dtd	d
 q(|rOtdtd	d
 d S d S d|  kr[dk s`n |dkr~|dkrnt| dtd	d
 |r|t| dtd	d
 d S d S |d ur||krtdtd	d
 d S d S d S d S )NTr?   zcontent-length)r   i0  )expireszcontent-locationzEntity header z found in 304 response.r   r"   z#304 responses must not have a body.d         r   z- responses must have an empty content length.z  responses must not have a body.zGContent-Length and the number of bytes sent to the client do not match.)r\   hasattrrY   r?   rW   sumrN   getintlowerr   r   r   r   )r-   status_codeheaders
bytes_sentcontent_lengthkey_valuer   r   r   r?      s`   







#zGuardedIterator.closec                 C  s4   | j sz
tdtdd W d S  ty   Y d S w d S )Nz4Iterator was garbage collected before it was closed.r   r"   )r\   r   r   	Exceptionr;   r   r   r   __del__   s   zGuardedIterator.__del__N)rU   rV   rW   rX   rN   rO   r   r   )r   rT   )r   r2   rA   )r   r   r   r.   r<   rZ   r?   rn   r   r   r   r   rT      s    



1rT   c                   @  sL   e Zd ZdZd"ddZd#d
dZd$ddZd%ddZd&ddZd'dd Z	d!S )(LintMiddlewarea  Warns about common errors in the WSGI and HTTP behavior of the
    server and wrapped application. Some of the issues it checks are:

    -   invalid status codes
    -   non-bytes sent to the WSGI server
    -   strings returned from the WSGI application
    -   non-empty conditional responses
    -   unquoted etags
    -   relative URLs in the Location header
    -   unsafe calls to wsgi.input
    -   unclosed iterators

    Error information is emitted using the :mod:`warnings` module.

    :param app: The WSGI application to wrap.

    .. code-block:: python

        from werkzeug.middleware.lint import LintMiddleware
        app = LintMiddleware(app)
    appr   r   r   c                 C  r(   r)   )rp   )r-   rp   r   r   r   r.      r/   zLintMiddleware.__init__environr   c                 C  s   t |turtdtdd dD ]}||vr td|dtdd q|d d	kr.td
tdd |dd}|dd}|rL|d dkrLtd|tdd |r`|d dkrbtd|tdd d S d S d S )Nz/WSGI environment is not a standard Python dict.   r"   )	REQUEST_METHODSERVER_NAMESERVER_PORTwsgi.version
wsgi.inputwsgi.errorszwsgi.multithreadzwsgi.multiprocesszwsgi.run_oncezRequired environment key z
 not foundr!   rv   )r3   r   z"Environ is not a WSGI 1.0 environ.SCRIPT_NAME 	PATH_INFOr   /z+'SCRIPT_NAME' does not start with a slash: z)'PATH_INFO' does not start with a slash: )r   dictr   r   rd   )r-   rq   rk   script_name	path_infor   r   r   check_environ   s>   

zLintMiddleware.check_environstatusr   rh   list[tuple[str, str]]exc_info?None | tuple[type[BaseException], BaseException, TracebackType]rX   c           
      C  sV  t d|t |d dd }t|dks| stdtdd t|dk s+|d dkr6td	|d
tdd t|}|dk rEtdtdd t|t	urRtdtdd |D ]9}t|t
usbt|dkritdtdd |\}}t|tusyt|turtdtdd | dkrtdtdd qT|d urt|t
stdtdd t|}	| |	 ||	fS )Nr   r3   r   r!   z!Status code must be three digits.r"   rr    zInvalid value for status zJ. Valid status strings are three digits, a space and a status explanation.r_   zStatus code < 100 detected.zHeader list is not a list.r   z#Header items must be 2-item tuples.z'Header keys and values must be strings.zFThe status header is not supported due to conflicts with the CGI spec.zInvalid value for exc_info.)r$   r   splitr4   	isdecimalr   r   re   r   listtuplerf   
isinstancer   check_headers)
r-   r   rh   r   status_code_strrg   itemnamevalueheaders_objr   r   r   check_start_response)  sF   

z#LintMiddleware.check_start_responser   c                 C  s   | d}|d ur:|dr |drtdtdd |dd  }|d d |d	d    kr2d
ks:n tdtdd | d}|d urQt|jsStdtdd d S d S d S )Netag)zW/w/r   z)Weak etag indicator should be upper case.rr   r"   r   r3   "zUnquoted etag emitted.locationz+Absolute URLs required for location header.)rd   
startswithr   r   r   netloc)r-   rh   r   r   r   r   r   r   ]  s,   


&


zLintMiddleware.check_headersapp_iterrV   c                 C  s    t |trtdtdd d S d S )NzThe application returned a string. The response will send one character at a time to the client, which will kill performance. Return a list or iterable instead.r!   r"   )r   r   r   r   )r-   r   r   r   r   check_iteratorx  s   

zLintMiddleware.check_iteratorr0   r1   kwargsc                   s   t |dkrtdtdd |rtdtdd |d }|d | t|d |d< t|d |d< t|d	< g g  d fdd}|t	d|}
| t|t	tttf  S )Nr   zA WSGI app takes two arguments.r"   z+A WSGI app does not take keyword arguments.r   r3   rw   rx   zwsgi.file_wrapperr0   r1   r   r   t.Callable[[bytes], None]c                    s   t | dvrtdt |  dtdd |rtdtdd | d }| d }t | d	kr.| d nd }|||d d < t||| S )
N>   r   r!   zInvalid number of arguments: z, expected 2 or 3.r   r"   z1'start_response' does not take keyword arguments.r   r3   r!   )r4   r   r   r   rL   )r0   r   r   rh   r   rN   rW   r-   start_responser   r   checking_start_response  s$   z8LintMiddleware.__call__.<locals>.checking_start_responser
   )r0   r1   r   r1   r   r   )r4   r   r   r   r%   rB   r	   rp   tcastr   rT   r   re   r   )r-   r0   r   rq   r   r   r   r   r   rS     s(   

zLintMiddleware.__call__N)rp   r   r   r   )rq   r   r   r   )r   r   rh   r   r   r   r   rX   )rh   r   r   r   )r   rV   r   r   )r0   r1   r   r1   r   rV   )
r   r   r   r   r.   r   r   r   r   rS   r   r   r   r   ro      s    


,
4

ro   )r   r   r   r   r   r   r   r   ) r   
__future__r   typingr   typesr   urllib.parser   warningsr   datastructuresr   httpr   wsgir	   TYPE_CHECKING_typeshed.wsgir
   r   r   Warningr   r   r   r$   r%   rB   rL   rT   ro   r   r   r   r   <module>   s*    	4^