ó
    F\h¼:  ã                   ó*  • S r S/rSSKrSSKrSSKr\R
                  " S5      r\R
                  " S5      r " S S\5      r	S r
S	 rS
 r " S S5      r " S S5      r " S S5      r " S S5      r " S S5      rS rS rS rS rS rS rS rS rg)a&  
Middleware to check for obedience to the WSGI specification.

Some of the things this checks:

* Signature of the application and start_response (including that
  keyword arguments are not used).

* Environment checks:

  - Environment is a dictionary (and not a subclass).

  - That all the required keys are in the environment: REQUEST_METHOD,
    SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors,
    wsgi.multithread, wsgi.multiprocess, wsgi.run_once

  - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the
    environment (these headers should appear as CONTENT_LENGTH and
    CONTENT_TYPE).

  - Warns if QUERY_STRING is missing, as the cgi module acts
    unpredictably in that case.

  - That CGI-style variables (that don't contain a .) have
    (non-unicode) string values

  - That wsgi.version is a tuple

  - That wsgi.url_scheme is 'http' or 'https' (@@: is this too
    restrictive?)

  - Warns if the REQUEST_METHOD is not known (@@: probably too
    restrictive).

  - That SCRIPT_NAME and PATH_INFO are empty or start with /

  - That at least one of SCRIPT_NAME or PATH_INFO are set.

  - That CONTENT_LENGTH is a positive integer.

  - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should
    be '/').

  - That wsgi.input has the methods read, readline, readlines, and
    __iter__

  - That wsgi.errors has the methods flush, write, writelines

* The status is a string, contains a space, starts with an integer,
  and that integer is in range (> 100).

* That the headers is a list (not a subclass, not another kind of
  sequence).

* That the items of the headers are tuples of strings.

* That there is no 'status' header (that is used in CGI, but not in
  WSGI).

* That the headers don't contain newlines or colons, end in _ or -, or
  contain characters codes below 037.

* That Content-Type is given if there is content (CGI often has a
  default content type, but WSGI does not).

* That no Content-Type is given when there is no content (@@: is this
  too restrictive?)

* That the exc_info argument to start_response is a tuple or None.

* That all calls to the writer are with strings, and no other methods
  on the writer are accessed.

* That wsgi.input is used properly:

  - .read() is called with exactly one argument

  - That it returns a string

  - That readline, readlines, and __iter__ return strings

  - That .close() is not called

  - No other methods are provided

* That wsgi.errors is used properly:

  - .write() and .writelines() is called with a string

  - That .close() is not called, and no other methods are provided.

* The response iterator:

  - That it is not a string (it should be a list of a single string; a
    string will work, but perform horribly).

  - That .__next__() returns a string

  - That the iterator is not iterated over until start_response has
    been called (that can signal either a server or application
    error).

  - That .close() is called (doesn't raise exception, only prints to
    sys.stderr, because we only know it isn't called when the object
    is garbage collected).
Ú	validatoré    Nz^[a-zA-Z][a-zA-Z0-9\-_]*$z[\000-\037]c                   ó   • \ rS rSrSrSrg)ÚWSGIWarningéy   z2
Raised in response to WSGI-spec-related warnings
© N)Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Ú__static_attributes__r   ó    Ú'/usr/lib/python3.13/wsgiref/validate.pyr   r   y   s   † ôr   r   c                 ó"   • U (       d  [        U6 eg ©N)ÚAssertionError)ÚcondÚargss     r   Úassert_r   ~   s   € ÞÜ˜dÐ#Ð#ð r   c                 ór   • [        U 5      [        L a  U $ [        SR                  U[	        U 5      5      5      e)Nz!{0} must be of type str (got {1}))ÚtypeÚstrr   ÚformatÚrepr)ÚvalueÚtitles     r   Úcheck_string_typer   ‚   s6   € ÜˆUƒ|”sÒØˆÜ
Ø+×2Ñ2°5¼$¸u»+ÓFóHð Hr   c                 ó   ^ • U 4S jnU$ )aŽ  
When applied between a WSGI server and a WSGI application, this
middleware will check for WSGI compliance on a number of levels.
This middleware does not modify the request or response in any
way, but will raise an AssertionError if anything seems off
(except for a failure to close the application iterator, which
will be printed to stderr -- there's no way to raise an exception
at that point).
c                  óB  >^^• [        [        U 5      S:H  S5        [        U(       + S5        U u  nm[        U5        / mUU4S jn[        US   5      US'   [	        US   5      US'   T" X#5      n[        US L=(       a    US:g  S5        [        U5        [        UT5      $ )	Né   zTwo arguments requiredúNo keyword arguments allowedc                  ó`  >• [        [        U 5      S:H  =(       d    [        U 5      S:H  SU < 35        [        U(       + S5        U S   nU S   n[        U 5      S:X  a  U S   nOS n[        U5        [        U5        [	        X#5        [        U5        TR                  S 5        [        T" U 6 5      $ )Nr    é   zInvalid number of arguments: r!   r   é   )r   ÚlenÚcheck_statusÚcheck_headersÚcheck_content_typeÚcheck_exc_infoÚappendÚWriteWrapper)r   ÚkwÚstatusÚheadersÚexc_infoÚstart_responseÚstart_response_starteds        €€r   Ústart_response_wrapperÚ;validator.<locals>.lint_app.<locals>.start_response_wrapperŸ   sŸ   ø€ Ü”C˜“I ‘N×4¤c¨$£i°1¡nøÚ59Ð;ô>ä˜”FÐ:Ô;Ø˜!‘WˆFØ˜1‘gˆGÜ�4‹y˜A‹~Ø ™7‘à�ä˜Ô Ü˜'Ô"Ü˜vÔ/Ü˜8Ô$à"×)Ñ)¨$Ô/Ü¡°Ð 5Ó6Ð6r   ú
wsgi.inputúwsgi.errorsFz>The application must return an iterator, if only an empty list)r   r%   Úcheck_environÚInputWrapperÚErrorWrapperÚcheck_iteratorÚIteratorWrapper)r   r,   Úenvironr2   Úiteratorr0   r1   Úapplications        @@€r   Úlint_appÚvalidator.<locals>.lint_app”   s«   ú€ Ü”�D“	˜Q‘Ð 8Ô9Ü�B”Ð6Ô7Ø"&Ñˆ�ä�gÔð "$Ðö	7ô& !-¨W°\Ñ-BÓ Cˆ�ÑÜ!-¨g°mÑ.DÓ!Eˆ�Ñá˜wÓ?ˆÜ� Ð$×:¨°UÑ):ØLô	Nô 	�xÔ ä˜xÐ)?Ó@Ð@r   r   )r=   r>   s   ` r   r   r   ˆ   s   ø€ õ'AðR €Or   c                   ó8   • \ rS rSrS rS rS rS rS rS r	Sr
g	)
r7   é¿   c                 ó   • Xl         g r   ©Úinput)ÚselfÚ
wsgi_inputs     r   Ú__init__ÚInputWrapper.__init__Á   s   € Ø�
r   c                 óš   • [        [        U5      S:H  5        U R                  R                  " U6 n[        [	        U5      [
        L 5        U$ ©Nr$   )r   r%   rD   Úreadr   Úbytes©rE   r   Úvs      r   rK   ÚInputWrapper.readÄ   s:   € Ü”�D“	˜Q‘ÔØ�J‰J�OŠO˜TÐ"ˆÜ”�Q“œ5Ð Ô!Øˆr   c                 óš   • [        [        U5      S:*  5        U R                  R                  " U6 n[        [	        U5      [
        L 5        U$ rJ   )r   r%   rD   Úreadliner   rL   rM   s      r   rQ   ÚInputWrapper.readlineÊ   s<   € Ü”�D“	˜Q‘ÔØ�J‰J×Ò Ð&ˆÜ”�Q“œ5Ð Ô!Øˆr   c                 óà   • [        [        U5      S:*  5        U R                  R                  " U6 n[        [	        U5      [
        L 5        U H  n[        [	        U5      [        L 5        M     U$ rJ   )r   r%   rD   Ú	readlinesr   ÚlistrL   )rE   r   ÚlinesÚlines       r   rT   ÚInputWrapper.readlinesÐ   sW   € Ü”�D“	˜Q‘ÔØ—
‘
×$Ò$ dÐ+ˆÜ”�U“œtÐ#Ô$ÛˆDÜ”D˜“J¤%Ð'Ö(ñ àˆr   c              #   óv   #   • U R                  5       =n(       a  Uv •  U R                  5       =n(       a  M  g g 7fr   )rQ   )rE   rW   s     r   Ú__iter__ÚInputWrapper.__iter__Ø   s1   é € Ø—m‘m“oÐ%ˆdÕ%ØŠJð —m‘m“oÐ%ˆd×%Ñ%ùs   ‚39·9c                 ó   • [        SS5        g )Nr   z input.close() must not be called©r   ©rE   s    r   ÚcloseÚInputWrapper.closeÜ   s   € Ü�Ð5Õ6r   rC   N)r   r	   r
   r   rG   rK   rQ   rT   rZ   r_   r   r   r   r   r7   r7   ¿   s    † ò òòòòõ7r   r7   c                   ó2   • \ rS rSrS rS rS rS rS rSr	g)	r8   éß   c                 ó   • Xl         g r   ©Úerrors)rE   Úwsgi_errorss     r   rG   ÚErrorWrapper.__init__á   ó   € Ø!�r   c                 ón   • [        [        U5      [        L 5        U R                  R	                  U5        g r   )r   r   r   re   Úwrite©rE   Úss     r   rj   ÚErrorWrapper.writeä   s$   € Ü”�Q“œ3�ÔØ�‰×Ñ˜!Õr   c                 ó8   • U R                   R                  5         g r   )re   Úflushr^   s    r   ro   ÚErrorWrapper.flushè   s   € Ø�‰×ÑÕr   c                 ó8   • U H  nU R                  U5        M     g r   )rj   )rE   ÚseqrW   s      r   Ú
writelinesÚErrorWrapper.writelinesë   s   € ÛˆDØ�J‰J�tÖò r   c                 ó   • [        SS5        g )Nr   z!errors.close() must not be calledr]   r^   s    r   r_   ÚErrorWrapper.closeï   s   € Ü�Ð6Õ7r   rd   N)
r   r	   r
   r   rG   rj   ro   rs   r_   r   r   r   r   r8   r8   ß   s   † ò"òòòõ8r   r8   c                   ó    • \ rS rSrS rS rSrg)r+   éò   c                 ó   • Xl         g r   ©Úwriter)rE   Úwsgi_writers     r   rG   ÚWriteWrapper.__init__ô   rh   r   c                 óZ   • [        [        U5      [        L 5        U R                  U5        g r   )r   r   rL   r{   rk   s     r   Ú__call__ÚWriteWrapper.__call__÷   s   € Ü”�Q“œ5Ð Ô!Ø�‰�A�r   rz   N)r   r	   r
   r   rG   r   r   r   r   r   r+   r+   ò   s   † ò"õr   r+   c                   ó    • \ rS rSrS rS rSrg)ÚPartialIteratorWrapperéû   c                 ó   • Xl         g r   ©r<   )rE   Úwsgi_iterators     r   rG   ÚPartialIteratorWrapper.__init__ý   s   € Ø%�r   c                 ó.   • [        U R                  S 5      $ r   )r:   r<   r^   s    r   rZ   ÚPartialIteratorWrapper.__iter__   s   € ä˜tŸ}™}¨dÓ3Ð3r   r…   N)r   r	   r
   r   rG   rZ   r   r   r   r   r‚   r‚   û   s   † ò&õ4r   r‚   c                   ó2   • \ rS rSrS rS rS rS rS rSr	g)	r:   i  c                 óJ   • Xl         [        U5      U l        SU l        X l        g )NF)Úoriginal_iteratorÚiterr<   ÚclosedÚcheck_start_response)rE   r†   r�   s      r   rG   ÚIteratorWrapper.__init__  s!   € Ø!.ÔÜ˜]Ó+ˆŒØˆŒØ$8Õ!r   c                 ó   • U $ r   r   r^   s    r   rZ   ÚIteratorWrapper.__iter__  s   € Øˆr   c                 ó   • [        U R                  (       + S5        [        U R                  5      n[	        U5      [
        La  [        SSU< S35        U R                  b  [        U R                  S5        S U l        U$ )NzIterator read after closedFz!Iterator yielded non-bytestring (Ú)zjThe application returns and we started iterating over its body, but start_response has not yet been called)r   rŽ   Únextr<   r   rL   r�   )rE   rN   s     r   Ú__next__ÚIteratorWrapper.__next__  si   € Ü�D—K‘K”Ø(ô	*ä�—‘ÓˆÜ�‹7œ%ÒÜ‘EÃQÐHÔIØ×$Ñ$Ñ0Ü�D×-Ñ-Ø|ô~à(,ˆDÔ%Øˆr   c                 ó~   • SU l         [        U R                  S5      (       a  U R                  R                  5         g g )NTr_   )rŽ   ÚhasattrrŒ   r_   r^   s    r   r_   ÚIteratorWrapper.close  s3   € ØˆŒÜ�4×)Ñ)¨7×3Ñ3Ø×"Ñ"×(Ñ(Õ*ð 4r   c                 ó�   • U R                   (       d  [        R                  R                  S5        [	        U R                   S5        g )Nz/Iterator garbage collected without being closed)rŽ   ÚsysÚstderrrj   r   r^   s    r   Ú__del__ÚIteratorWrapper.__del__   s0   € Ø�{�{Ü�J‰J×ÑØAôCä�—‘Ø=õ	?r   )r�   rŽ   r<   rŒ   N)
r   r	   r
   r   rG   rZ   r–   r_   rž   r   r   r   r   r:   r:     s   † ò9òò
ò+õ
?r   r:   c                 óÈ  • [        [        U 5      [        L S[        U 5      < SU < S35        S H  n[        X;   SU< 35        M     S H  n[        X;  SU< SUS	S  < S
35        M     SU ;  a  [        R                  " S[
        5        U R                  5        HB  nSU;   a  M  [        [        X   5      [        L SU< S[        X   5      < SX   < S35        MD     [        [        U S   5      [        L SU S   < S35        [        U S   S;   SU S   -  5        [        U S   5        [        U S   5        U S   S;  a!  [        R                  " SU S   -  [
        5        [        U R                  S5      (       + =(       d    U S   R                  S5      SU S   -  5        [        U R                  S5      (       + =(       d    U S   R                  S5      SU S   -  5        U R                  S 5      (       a!  [        [        U S    5      S!:¬  S"U S    -  5        U R                  S5      (       d  [        SU ;   S#5        [        U R                  S5      S:g  S$5        g )%Nz&Environment is not of the right type: z (environment: r”   )	ÚREQUEST_METHODÚSERVER_NAMEÚSERVER_PORTúwsgi.versionr4   r5   zwsgi.multithreadzwsgi.multiprocesszwsgi.run_oncez"Environment missing required key: )ÚHTTP_CONTENT_TYPEÚHTTP_CONTENT_LENGTHz%Environment should not have the key: z (use é   z	 instead)ÚQUERY_STRINGz’QUERY_STRING is not in the WSGI environment; the cgi module will use sys.argv when this variable is missing, so application errors are more likelyÚ.zEnvironmental variable z is not a string: z	 (value: r¤   z wsgi.version should be a tuple (zwsgi.url_scheme)ÚhttpÚhttpszwsgi.url_scheme unknown: %rr4   r5   r¡   )ÚGETÚHEADÚPOSTÚOPTIONSÚPATCHÚPUTÚDELETEÚTRACEzUnknown REQUEST_METHOD: %rÚSCRIPT_NAMEÚ/z$SCRIPT_NAME doesn't start with /: %rÚ	PATH_INFOz"PATH_INFO doesn't start with /: %rÚCONTENT_LENGTHr   zInvalid CONTENT_LENGTH: %rzgOne of SCRIPT_NAME or PATH_INFO are required (PATH_INFO should at least be '/' if SCRIPT_NAME is empty)zOSCRIPT_NAME cannot be '/'; it should instead be '', and PATH_INFO should be '/')r   r   ÚdictÚwarningsÚwarnr   Úkeysr   ÚtupleÚcheck_inputÚcheck_errorsÚgetÚ
startswithÚint)r;   Úkeys     r   r6   r6   '  sj  € ÜŒD�‹MœTÑ!ä�Ž=›'ð	#ô$ó!ˆô 	�’Ú69Ð;ö	=ñ	!ó <ˆÜ�Ò"ã"% s¨1¨2£wð0ö	1ñ <ð
 ˜WÓ$Ü�Šð4ô ô		ð �|‰|Ž~ˆØ�#‹:áÜ”�W‘\Ó"¤cÑ)ã”D˜™Ö&¨¬ð6ö	7ñ	 ô ŒD�˜Ñ(Ó)¬UÑ2Ø18¸Ô1HÐJôLäˆGÐ%Ñ&Ð*;Ñ;Ø%¨Ð0AÑ(BÑBôDô �˜Ñ%Ô&Ü�˜Ñ'Ô(ð ÐÑ ð )Mó Mä�ŠØ(¨7Ð3CÑ+DÑDÜô	ô �—‘˜MÓ*Ô*÷ 6Ø�}Ñ%×0Ñ0°Ó5Ø.°¸Ñ1GÑGôIô �—‘˜KÓ(Ô(÷ 4Ø�{Ñ#×.Ñ.¨sÓ3Ø,¨w°{Ñ/CÑCôEð ‡{�{Ð#×$Ñ$Ü”�GÐ,Ñ-Ó.°!Ñ3Ø(¨7Ð3CÑ+DÑDô	Fð �;‰;�}×%Ñ%Ü�˜wÑ&ð>ô	?ô ˆG�K‰K˜Ó&¨#Ñ-ð	"õ#r   c                 óP   • S H   n[        [        X5      SU < SU< 35        M"     g )N)rK   rQ   rT   rZ   zwsgi.input (ú) doesn't have the attribute ©r   r™   )rF   Úattrs     r   r½   r½   h  s%   € Û=ˆÜ”˜
Ô)ãš4ð!ö	"ò >r   c                 óP   • S H   n[        [        X5      SU < SU< 35        M"     g )N)ro   rj   rs   zwsgi.errors (rÄ   rÅ   )rf   rÆ   s     r   r¾   r¾   n  s%   € Û0ˆÜ”˜Ô*ãšDð"ö	#ò 1r   c                 ó$  • [        U S5      n U R                  S S5      S   n[        [        U5      S:H  SU-  5        [	        U5      n[        US:¬  SU-  5        [        U 5      S:  d	  U S   S	:w  a  [
        R                  " S
U -  [        5        g g )NÚStatusr$   r   r#   z)Status codes must be three characters: %réd   zStatus code is invalid: %ré   Ú zjThe status string (%r) should be a three-digit integer followed by a single space and a status explanation)r   Úsplitr   r%   rÁ   r¹   rº   r   )r-   Ústatus_codeÚ
status_ints      r   r&   r&   t  s—   € Ü˜v xÓ0€Fà—,‘,˜t QÓ'¨Ñ*€KÜŒC�Ó Ñ!Ø3°kÑAôCä�[Ó!€JÜˆJ˜#ÑÐ;¸jÑHÔIÜ
ˆ6ƒ{�Qƒ˜& ™) sÓ*Ü�ŠðBàñä!õ	#ð +r   c           
      ó  • [        [        U 5      [        L SU < S[        U 5      < 35        U  GHW  n[        [        U5      [        L SU< S[        U5      < 35        [        [	        U5      S:H  5        Uu  p#[        US5      n[        US5      n[        UR                  5       S:g  S	U-  5        [        S
U;  =(       a    SU;  SU-  5        [        [        R                  U5      SU-  5        [        UR                  S5      (       + =(       a    UR                  S5      (       + SU-  5        [        R                  U5      (       d  GM   [        SSU< S[        R                  U5      R                  S5      < S35        GMZ     g )Nz	Headers (z) must be of type list: zIndividual headers (z) must be of type tuple: r    úHeader namezHeader valuer-   zyThe Status header cannot be used; it conflicts with CGI script, and HTTP status is not given through headers (value: %r).Ú
Ú:z,Header names may not contain ':' or '\n': %rzBad header name: %rÚ-Ú_z#Names may not end in '-' or '_': %rr   zBad header value: z (bad char: r”   )r   r   rU   r¼   r%   r   ÚlowerÚ	header_reÚsearchÚendswithÚbad_header_value_reÚgroup)r.   ÚitemÚnamer   s       r   r'   r'   ‚  sN  € ÜŒD�‹MœTÑ!ã”D˜•Mð	#ô$ô ˆÜ”�T“
œeÑ#ã”T˜$•Zð!ô	"ô 	”�D“	˜Q‘ÔØ‰ˆÜ   }Ó5ˆÜ! %¨Ó8ˆÜ�—
‘
“ Ñ(ðà"ñ#ô	$ô 	�˜DÑ ×4 S°¡_Ø;¸dÑBô	Dä”	× Ñ  Ó&Ð(=ÀÑ(DÔEÜ�D—M‘M #Ó&Ô&×A¨t¯}©}¸SÓ/AÔ+AØ1°DÑ8ô	:ä×%Ñ% e×,Ô,Ü‘AÛÔ)×0Ñ0°Ó7×=Ñ=¸aÖ@ðB÷ Cò% r   c                 ó  • [        U S5      n [        U R                  S S5      S   5      nSnU H=  u  pE[        US5      nUR                  5       S:X  d  M'  X#;  a    g [	        SSU-  5        M?     X#;  a  [	        SSU-  5        g g )	NrÉ   r$   r   )éÌ   i0  rÑ   zcontent-typezJContent-Type header found in a %s response, which must not return content.z,No Content-Type header found in headers (%s))r   rÁ   rÍ   rÖ   r   )r-   r.   ÚcodeÚNO_MESSAGE_BODYrÝ   r   s         r   r(   r(   ›  s”   € Ü˜v xÓ0€FÜˆv�|‰|˜D !Ó$ QÑ'Ó(€Dð !€OÛ‰ˆÜ   }Ó5ˆØ�:‰:‹<˜>Õ)ØÓ*ÙÜ�Að 9Ø<@ñAö Bñ ð Ó"Ü�ÐAÀGÑKÕLð #r   c           	      ór   • [        U S L =(       d    [        U 5      [        L SU < S[        U 5      < 35        g )Nz
exc_info (z) is not a tuple: )r   r   r¼   )r/   s    r   r)   r)   «  s-   € ÜˆH˜Ð×7¤ X£´%Ð 7øÛ.6¼¸X½ÐGõIr   c                 óN   • [        [        U [        [        45      (       + S5        g )NzwYou should not return a string as your application iterator, instead return a single-item list containing a bytestring.)r   Ú
isinstancer   rL   r…   s    r   r9   r9   °  s#   € ô ”
˜8¤c¬5 \Ó2Ô2ð	EõFr   )r   Ú__all__Úrerœ   r¹   Úcompiler×   rÚ   ÚWarningr   r   r   r   r7   r8   r+   r‚   r:   r6   r½   r¾   r&   r'   r(   r)   r9   r   r   r   Ú<module>ré      s¼   ðñ
iðT ˆ-€ó 
Û 
Û à�JŠJÐ3Ó4€	Ø—j’j Ó0Ð ô�'ô ò
$òHò5÷n7ñ 7÷@8ñ 8÷&ñ ÷4ñ 4÷!?ñ !?òF?#òB"ò#ò#òCò2Mò Ió
Fr   