Ë
    ÚŠ±jŒ8  ã                  ó<  — 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"                  rddlmZ ddlmZ ddlmZ  G d„ de«      Z G d„ de«      Zefdd„Z G d„ d«      Z G d„ d«      Z G d„ d«      Z G d„ d«      Z G d„ d«      Zy)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y)ÚWSGIWarningz Warning class for WSGI warnings.N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    ú]/var/www/io.vulcan-creative.com/venv/lib/python3.12/site-packages/werkzeug/middleware/lint.pyr   r   !   ó   „ Ú*r   r   c                  ó   — e Zd ZdZy)ÚHTTPWarningz Warning class for HTTP warnings.Nr   r   r   r   r   r   %   r   r   r   c           	     ó�   — t        |«      |ur9t        | ›d|j                  ›dt        |«      j                  ›d�t        d¬«       y y )Nz
 requires z, got ú.é   ©Ú
stacklevel)Útyper   r   r   )ÚcontextÚobjÚneeds      r   Ú
check_typer$   )   sH   € ÜˆCƒy˜ÑÜØˆk˜ D§M¡MÐ#4°F¼4À»9×;MÑ;MÐ:PÐPQÐRÜØö	
ð r   c                  ó4   — e Zd Zdd„Zdd„Zdd„Zd	d„Zd
d„Zy)ÚInputStreamc                ó   — || _         y ©N©Ú_stream©ÚselfÚstreams     r   Ú__init__zInputStream.__init__3   ó	   € Øˆ�r   c                ó¶   — t        |«      dk(  rt        dt        d¬«       n t        |«      dk7  rt        dt        d¬«        | j                  j                  |Ž S )Nr   zŸWSGI 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,   Úargss     r   r3   zInputStream.read6   sY   € Üˆt‹9˜Š>Üð*ô Øöô �‹Y˜!Š^ÜØDÜØõð
 !ˆt�|‰|× Ñ  $Ð'Ð'r   c                óÎ   — t        |«      dk(  rt        dt        d¬«       n,t        |«      dk(  rt        dt        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   r1   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()'.)r2   r   r   Ú	TypeErrorr*   Úreadliner4   s     r   r8   zInputStream.readlineG   sf   € Üˆt‹9˜Š>Üð0äØö	ô �‹Y˜!Š^ÜðOäØö	ô ÐSÓTÐTØ$ˆt�|‰|×$Ñ$ dÐ+Ð+r   c                ó†   — 	 t        | j                  «      S # t        $ r  t        dt        d¬«       t        d«      cY S w xY w)Nz'wsgi.input' is not iterable.r   r   r   )Úiterr*   r7   r   r   ©r,   s    r   Ú__iter__zInputStream.__iter__Z   s;   € ð	Ü˜Ÿ™Ó%Ð%øÜò 	ÜÐ0´+È!ÕLÜ˜“8ŠOð	ús   ‚ —&A ¿A c                ó\   — t        dt        d¬«       | j                  j                  «        y )Nz(The application closed the input stream!r   r   ©r   r   r*   Úcloser;   s    r   r?   zInputStream.closea   ó    € ÜÐ7¼ÐQRÕSØ�‰×ÑÕr   N)r-   zt.IO[bytes]ÚreturnÚNone)r5   út.AnyrA   Úbytes)rA   zt.Iterator[bytes]©rA   rB   )r   r   r   r.   r3   r8   r<   r?   r   r   r   r&   r&   2   s   „ óó(ó",ó&ôr   r&   c                  ó4   — e Zd Zdd„Zdd„Zd	d„Zd
d„Zd	d„Zy)ÚErrorStreamc                ó   — || _         y r(   r)   r+   s     r   r.   zErrorStream.__init__g   r/   r   c                ó\   — t        d|t        «       | j                  j                  |«       y )Nzwsgi.error.write())r$   Ústrr*   Úwrite©r,   Úss     r   rK   zErrorStream.writej   s!   € ÜÐ'¨¬CÔ0Ø�‰×Ñ˜1Õr   c                ó8   — | j                   j                  «        y r(   )r*   Úflushr;   s    r   rO   zErrorStream.flushn   s   € Ø�‰×ÑÕr   c                ó4   — |D ]  }| j                  |«       Œ y r(   )rK   )r,   ÚseqÚlines      r   Ú
writelineszErrorStream.writelinesq   s   € Øò 	ˆDØ�J‰J�tÕñ	r   c                ó\   — t        dt        d¬«       | j                  j                  «        y )Nz(The application closed the error stream!r   r   r>   r;   s    r   r?   zErrorStream.closeu   r@   r   N)r-   z	t.IO[str]rA   rB   )rM   rJ   rA   rB   rE   )rQ   zt.Iterable[str]rA   rB   )r   r   r   r.   rK   rO   rS   r?   r   r   r   rG   rG   f   s   „ óóóóôr   rG   c                  ó   — e Zd Zdd„Zdd„Zy)ÚGuardedWritec                ó    — || _         || _        y r(   )Ú_writeÚ_chunks)r,   rK   Úchunkss      r   r.   zGuardedWrite.__init__{   s   € ØˆŒØˆ�r   c                ó�   — t        d|t        «       | j                  |«       | j                  j	                  t        |«      «       y )Nzwrite())r$   rD   rX   rY   Úappendr2   rL   s     r   Ú__call__zGuardedWrite.__call__   s/   € Ü�9˜a¤Ô'Ø�‰�AŒØ�‰×ÑœC ›FÕ#r   N)rK   zt.Callable[[bytes], object]rZ   ú	list[int]rA   rB   )rM   rD   rA   rB   )r   r   r   r.   r]   r   r   r   rV   rV   z   s   „ óô$r   rV   c                  óD   — e Zd Z	 	 	 	 	 	 	 	 dd„Zdd„Zd	d„Zd
d„Zd
d„Zy)ÚGuardedIteratorc                óp   — || _         t        |«      j                  | _        d| _        || _        || _        y )NF)Ú	_iteratorr:   Ú__next__Ú_nextÚclosedÚheaders_setrZ   )r,   Úiteratorrf   rZ   s       r   r.   zGuardedIterator.__init__†   s2   € ð "ˆŒÜ˜(“^×,Ñ,ˆŒ
ØˆŒØ&ˆÔØˆ�r   c                ó   — | S r(   r   r;   s    r   r<   zGuardedIterator.__iter__’   s   € Øˆr   c                ó  — | j                   rt        dt        d¬«       | j                  «       }| j                  st        dt        d¬«       t        d|t        «       | j                  j                  t        |«      «       |S )Nz Iterated over closed 'app_iter'.r   r   z8The application returned before it started the response.zapplication iterator items)
re   r   r   rd   rf   r$   rD   rZ   r\   r2   )r,   Úrvs     r   rc   zGuardedIterator.__next__•   se   € Ø�;Š;ÜÐ3´[ÈQÕOà�Z‰Z‹\ˆà×ÒÜØJÜØõô 	Ð/°´UÔ;Ø�‰×Ñœ3˜r›7Ô#Øˆ	r   c                óz  — d| _         t        | j                  d«      r| j                  j                  «        | j                  rø| j                  \  }}t        | j                  «      }|j                  dt        ¬«      }|dk(  rW|D ]<  \  }}|j                  «       }|dvsŒt        |«      sŒ't        d|›d�t        d	¬
«       Œ> |rt        dt        d	¬
«       y y d|cxk  rdk  sn |dk(  r3|dk7  rt        |› d�t        d	¬
«       |rt        |› d�t        d	¬
«       y y |�||k7  rt        dt        d	¬
«       y y y y )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.)re   Úhasattrrb   r?   rf   ÚsumrZ   ÚgetÚintÚlowerr	   r   r   r   )r,   Ústatus_codeÚheadersÚ
bytes_sentÚcontent_lengthÚkeyÚ_values          r   r?   zGuardedIterator.close¦   s_  € ØˆŒä�4—>‘> 7Ô+Ø�N‰N× Ñ Ô"à×ÒØ#'×#3Ñ#3Ñ ˆK˜Ü˜TŸ[™[Ó)ˆJØ$Ÿ[™[Ð)9Ä˜[ÓDˆNà˜cÒ!Ø#*ò 	‘K�C˜ØŸ)™)›+�CØÐ"AÒAÔFVØõGô Ø,¨S¨GÐ3JÐKÜ'Ø'(öð	ñ ÜØ=Ü#Ø#$öð ð ˜Ô) cÔ)¨[¸CÒ-?Ø! QÒ&ÜØ&˜-Ð'TÐUÜ#Ø#$õñ
 ÜØ&˜-Ð'GÐHÜ#Ø#$öð ð  Ð+°À*Ò0LÜð,äØ ö	ð 1MÐ+ðG r   c                ób   — | j                   s	 t        dt        d¬«       y y # t        $ r Y y w xY w)Nz4Iterator was garbage collected before it was closed.r   r   )re   r   r   Ú	Exceptionr;   s    r   Ú__del__zGuardedIterator.__del__×   s8   € Ø�{Š{ðÜØJÜØ öð øô ò Ùðús   Ž" ¢	.­.N)rg   út.Iterable[bytes]rf   útuple[int, Headers]rZ   r^   rA   rB   )rA   r`   )rA   rD   rE   )r   r   r   r.   r<   rc   r?   r}   r   r   r   r`   r`   …   sB   „ ð
à#ð
ð )ð
ð ð	
ð
 
ó
óóó"/ôb	r   r`   c                  óP   — e Zd ZdZd	d„Zd
d„Z	 	 	 	 	 	 	 	 dd„Zdd„Zdd„Zdd„Z	y)Ú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)
    c                ó   — || _         y r(   )Úapp)r,   rƒ   s     r   r.   zLintMiddleware.__init__ú   s	   € Øˆ�r   c                óŠ  — t        |«      t        urt        dt        d¬«       dD ]  }||vsŒt        d|›d�t        d¬«       Œ |d   d	k7  rt        d
t        d¬«       |j	                  dd«      }|j	                  dd«      }|r|d   dk7  rt        d|›�t        d¬«       |r|d   dk7  rt        d|›�t        d¬«       y y y )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   r‰   )r1   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   rr   )r,   Úenvironry   Úscript_nameÚ	path_infos        r   Úcheck_environzLintMiddleware.check_environý   så   € Ü�‹=¤Ñ$ÜØAÜØõð


ò 	ˆCð ˜'Ò!ÜØ/°¨w°jÐAÜØ öð	ð" �>Ñ" fÒ,ÜÐ5´{ÈqÕQà—k‘k -°Ó4ˆØ—K‘K ¨RÓ0ˆ	á˜; q™>¨SÒ0ÜØ=¸k¸_ÐMÜØõñ ˜ 1™¨Ò,ÜØ;¸I¸=ÐIÜØöð -ˆ9r   c                óF  — t        d|t        «       |j                  d d«      d   }t        |«      dk7  s|j	                  «       st        dt        d¬«       t        |«      dk  s|d   dk7  rt        d	|›d
�t        d¬«       t        |«      }|dk  rt        dt        d¬«       t        |«      t        urt        dt        d¬«       |D ]’  }t        |«      t        ust        |«      dk7  rt        dt        d¬«       |\  }}t        |«      t        ust        |«      t        urt        dt        d¬«       |j                  «       dk(  sŒ�t        dt        d¬«       Œ” |�"t        |t        «      st        dt        d¬«       t        |«      }	| j                  |	«       ||	fS )NÚstatusr1   r   r   z!Status code must be three digits.r   r…   ú zInvalid value for status zJ. Valid status strings are three digits, a space and a status explanation.rm   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$   rJ   Úsplitr2   Ú	isdecimalr   r   rs   r    ÚlistÚtuplert   Ú
isinstancer   Úcheck_headers)
r,   r–   rv   Úexc_infoÚstatus_code_strru   ÚitemÚnameÚvalueÚheaders_objs
             r   Úcheck_start_responsez#LintMiddleware.check_start_response)  s€  € ô 	�8˜V¤SÔ)Ø Ÿ,™, t¨QÓ/°Ñ2ˆäˆÓ 1Ò$¨O×,EÑ,EÔ,GÜÐ4´kÈaÕPäˆv‹;˜Š?˜f Q™i¨3Ò.ÜØ+¨F¨:ð 6=ð =äØõ	ô ˜/Ó*ˆà˜ÒÜÐ.´ÈÕJä�‹=¤Ñ$ÜÐ-¬{ÀqÕIàò 	ˆDÜ�D‹z¤Ñ&¬#¨d«)°qª.ÜÐ:¼KÐTUÕVØ‰KˆD�%Ü�D‹z¤Ñ$¬¨U«¼3Ñ(>ÜØ=¼{ÐWXõð �z‰z‹|˜xÓ'Üð4äØ ö	ð	ð  Ð¬
°8¼UÔ(CÜÐ.´ÈÕJä˜gÓ&ˆØ×Ñ˜;Ô'à˜KÐ'Ð'r   c                ó^  — |j                  d«      }|�^|j                  d«      r(|j                  d«      rt        dt        d¬«       |dd  }|d d |d	d  cxk(  rd
k(  sn t        dt        d¬«       |j                  d«      }|�)t	        |«      j
                  st        dt        d¬«       y y y )NÚetag)zW/úw/r§   z)Weak etag indicator should be upper case.r…   r   r   r1   éÿÿÿÿú"zUnquoted etag emitted.Úlocationz+Absolute URLs required for location header.)rr   Ú
startswithr   r   r   Únetloc)r,   rv   r¦   rª   s       r   r�   zLintMiddleware.check_headers]  s¯   € Ø�{‰{˜6Ó"ˆàÐØ�‰˜|Ô,Ø—?‘? 4Ô(ÜØCÜ#Ø#$õð ˜A˜B�x�à˜˜!�H  R S 	Ô0¨SÔ0ÜÐ-¬{ÀqÕIà—;‘;˜zÓ*ˆàÐÜ˜HÓ%×,Ò,ÜØAÜØ öð -ð  r   c                óJ   — t        |t        «      rt        dt        d¬«       y y )Nz The 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œ   rJ   r   r   )r,   Úapp_iters     r   Úcheck_iteratorzLintMiddleware.check_iteratorx  s&   € Ü�h¤Ô$Üð6ô Øöð %r   c                óö  ‡ ‡‡‡— t        |«      dk7  rt        dt        d¬«       |rt        dt        d¬«       |d   }|d   Š‰ j                  |«       t	        |d   «      |d<   t        |d   «      |d<   t        |d	<   g Šg Š	 	 	 	 	 	 dˆˆˆ ˆfd
„}‰ j                  |t        j                  d|«      «      }‰ j                  |«       t        |t        j                  t        t        t        f   ‰«      ‰«      S )Nr   zA WSGI app takes two arguments.r   z+A WSGI app does not take keyword arguments.r   r1   rŠ   r‹   zwsgi.file_wrapperc                 ó  •— t        | «      dvrt        dt        | «      › d�t        d¬«       |rt        dt        d¬«       | d   }| d   }t        | «      d	k(  r| d   nd }‰j                  |||«      ‰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   r1   r   )r2   r   r   r¤   rV   )	r5   Úkwargsr–   rv   rž   rZ   rf   r,   Ústart_responses	        €€€€r   Úchecking_start_responsez8LintMiddleware.__call__.<locals>.checking_start_response™  s¤   ø€ ô �4‹y Ñ&ÜØ3´C¸³I°;Ð>PÐQÜØ õñ ÜØGÜØ õð ˜q™'ˆFØ-1°!©WˆGô ˜t›9¨š>��Q’¨tð ð "×6Ñ6°v¸wÈÓQˆK™ˆNÜ¡¨v°wÀÓ IÈ6ÓRÐRr   r   )r5   rC   r²   rC   rA   zt.Callable[[bytes], None])r2   r   r   r”   r&   rG   r
   rƒ   ÚtÚcastr¯   r`   r›   rs   r   )	r,   r5   r²   r‘   r´   r®   rZ   rf   r³   s	   `     @@@r   r]   zLintMiddleware.__call__‚  s
  û€ Üˆt‹9˜Š>ÜÐ2´KÈAÕNáÜØ=¼{ÐWXõð $(¨¡7ˆØ(,¨Q©ˆà×Ñ˜7Ô#Ü +¨G°LÑ,AÓ Bˆ�ÑÜ!,¨W°]Ñ-CÓ!Dˆ�Ñô (3ˆÐ#Ñ$à#%ˆØˆð	SØð	SØ$)ð	Sà&÷	Sð 	Sð4 —8‘8˜G¤Q§V¡V¨OÐ=TÓ%UÓVˆØ×Ñ˜HÔ%ÜØ”a—f‘fœU¤3¬ <Ñ0°+Ó>Àó
ð 	
r   N)rƒ   r   rA   rB   )r‘   r   rA   rB   )r–   rJ   rv   zlist[tuple[str, str]]rž   z?None | tuple[type[BaseException], BaseException, TracebackType]rA   r   )rv   r   rA   rB   )r®   r~   rA   rB   )r5   rC   r²   rC   rA   r~   )
r   r   r   r   r.   r”   r¤   r�   r¯   r]   r   r   r   r�   r�   ã   sN   „ ñó,ó*ðX2(àð2(ð 'ð2(ð Tð	2(ð
 
ó2(óhó6ô5
r   r�   )r!   rJ   r"   Úobjectr#   r    rA   rB   ) r   Ú
__future__r   Útypingrµ   Útypesr   Úurllib.parser   Úwarningsr   Údatastructuresr   Úhttpr	   Úwsgir
   ÚTYPE_CHECKINGÚ_typeshed.wsgir   r   r   ÚWarningr   r   rJ   r$   r&   rG   rV   r`   r�   r   r   r   ú<module>rÃ      sŽ   ðñõ #ã Ý Ý !Ý å $Ý #Ý à‡?‚?Ý,Ý.Ý.ô+�'ô +ô+�'ô +ð 8;ô 
÷1ñ 1÷hñ ÷($ñ $÷[ñ [÷|T
ò T
r   