o
    q>e\6                     @  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   Y/var/www/bmteknikk.ddns.net/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t.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)typer   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__2      
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.   r1   r   r   r   r6   5   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"   r4   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()'.)r5   r   r   	TypeErrorr,   readliner7   r   r   r   r9   F   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,   r8   r   r   r.   r   r   r   __iter__Y   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@   `      zInputStream.closeN)r'   r(   r   r   )r1   r2   r   r3   )r   r:   r   r   )r   r   r   r/   r6   r9   r=   r@   r   r   r   r   r&   1   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/   f   r0   zErrorStream.__init__sr   c                 C  s   t d|t | j| d S )Nzwsgi.error.write())r%   r   r,   writer.   rE   r   r   r   rF   i   s   zErrorStream.writec                 C  s   | j   d S r*   )r,   flushr<   r   r   r   rH   m   s   zErrorStream.flushseqt.Iterable[str]c                 C  s   |D ]}|  | qd S r*   )rF   )r.   rI   liner   r   r   
writelinesp   s   zErrorStream.writelinesc                 C  r>   )Nz(The application closed the error stream!r   r"   r?   r<   r   r   r   r@   t   rA   zErrorStream.closeN)r'   rD   r   r   )rE   r   r   r   rB   )rI   rJ   r   r   )r   r   r   r/   rF   rH   rL   r@   r   r   r   r   rC   e   s    



rC   c                   @  s    e Zd ZdddZdddZdS )GuardedWriterF   t.Callable[[bytes], object]chunks	list[int]r   r   c                 C  s   || _ || _d S r*   )_write_chunks)r.   rF   rO   r   r   r   r/   z   s   
zGuardedWrite.__init__rE   r3   c                 C  s*   t d|t | | | jt| d S )Nzwrite())r%   r3   rQ   rR   appendr5   rG   r   r   r   __call__~   s   
zGuardedWrite.__call__N)rF   rN   rO   rP   r   r   )rE   r3   r   r   )r   r   r   r/   rT   r   r   r   r   rM   y   s    
rM   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]rO   rP   r   r   c                 C  s(   || _ t|j| _d| _|| _|| _d S )NF)	_iteratorr;   __next___nextclosedrX   rO   )r.   rV   rX   rO   r   r   r   r/      s
   
zGuardedIterator.__init__c                 C  s   | S r*   r   r<   r   r   r   r=      s   zGuardedIterator.__iter__r3   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\   rX   r%   r3   rO   rS   r5   )r.   rvr   r   r   r[      s   zGuardedIterator.__next__c                 C  s  d| _ t| jdr| j  | jr| j\}}t| j}|jdtd}|dkrM|D ]\}}|	 }|dvrAt
|rAtd|dt q(|rKtd	t d S d S d
|  krWdk s\n |dkrv|dkrht| dt |rtt| dt d S d S |d ur||krtdt d S d S d S d S )NTr@   zcontent-length)r$   i0  )expireszcontent-locationzEntity header z found in 304 response.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]   hasattrrZ   r@   rX   sumrO   getintlowerr   r   r   r   )r.   status_codeheaders
bytes_sentcontent_lengthkey_valuer   r   r   r@      sH   



zGuardedIterator.closec                 C  s0   | j sztdt W d S  ty   Y d S w d S )Nz4Iterator was garbage collected before it was closed.)r]   r   r   	Exceptionr<   r   r   r   __del__   s   
zGuardedIterator.__del__N)rV   rW   rX   rY   rO   rP   r   r   )r   rU   )r   r3   rB   )r   r   r   r/   r=   r[   r@   ro   r   r   r   r   rU      s    



%rU   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*   )rq   )r.   rq   r   r   r   r/      r0   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!   rw   )r4   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   re   )r.   rr   rl   script_name	path_infor   r   r   check_environ   s>   

zLintMiddleware.check_environstatusr   ri   list[tuple[str, str]]exc_info?None | tuple[type[BaseException], BaseException, TracebackType]rY   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   r4   r   r!   z!Status code must be three digits.r"   rs    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   splitr5   	isdecimalr   r   rf   r$   listtuplerg   
isinstancer   check_headers)	r.   r   ri   r   status_code_strrh   itemnamevaluer   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.rs   r"   r   r4   "zUnquoted etag emitted.locationz+Absolute URLs required for location header.)re   
startswithr   r   r   netloc)r.   ri   r   r   r   r   r   r   N  s,   


&


zLintMiddleware.check_headersapp_iterrW   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_iteratori  s   

zLintMiddleware.check_iteratorr1   r2   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jttf  S )Nr   zA WSGI app takes two arguments.r"   z+A WSGI app does not take keyword arguments.r   r4   rx   ry   zwsgi.file_wrapperr1   r2   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 }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   r4   r!   )r5   r   r   r   rM   )r1   r   r   ri   r   rO   rX   r.   start_responser   r   checking_start_response  s   
z8LintMiddleware.__call__.<locals>.checking_start_responser
   )r1   r2   r   r2   r   r   )r5   r   r   r   r&   rC   r	   rq   tcastr   rU   Tuplerf   r   )r.   r1   r   rr   r   r   r   r   r   rT   s  s(   

zLintMiddleware.__call__N)rq   r   r   r   )rr   r   r   r   )r   r   ri   r   r   r   r   rY   )ri   r   r   r   )r   rW   r   r   )r1   r2   r   r2   r   rW   )
r   r   r   r   r/   r   r   r   r   rT   r   r   r   r   rp      s    


,
4

rp   )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&   rC   rM   rU   rp   r   r   r   r   <module>   s*    	4P