Ë
    Û�ðiby  ã                   ó¨  — d Z ddlZddlmZ  G d„ de«      Z G d„ de«      Z G d„ d	e«      Zd
Z G d„ de«      Z	 G d„ de«      Z
 G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ de«      Z G d„ d e«      Z G d!„ d"e«      Z G d#„ d$e«      Z G d%„ d&«      Z G d'„ d(«      Zy))zš
HTTP parser for ASGI workers.

Provides callback-based parsing using either the fast C parser (gunicorn_h1c)
or the pure Python PythonProtocol fallback.
é    N)ÚIntEnumc                   ó   — e Zd ZdZy)Ú
ParseErrorz&Base error raised during HTTP parsing.N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__© ó    úO/var/www/html/Extract/venv/lib/python3.12/site-packages/gunicorn/asgi/parser.pyr   r      ó   „ Ú0r   r   c                   ó   — e Zd ZdZy)ÚInvalidProxyLinezInvalid PROXY protocol v1 line.Nr   r   r   r   r   r      s   „ Ú)r   r   c                   ó   — e Zd ZdZy)ÚInvalidProxyHeaderz!Invalid PROXY protocol v2 header.Nr   r   r   r   r   r      s   „ Ú+r   r   s   

 
QUIT
c                   ó   — e Zd ZdZdZdZy)Ú	PPCommandzPROXY protocol v2 commands.r   é   N)r   r   r	   r
   ÚLOCALÚPROXYr   r   r   r   r       s   „ Ù%Ø€EØ�Er   r   c                   ó    — e Zd ZdZdZdZdZdZy)ÚPPFamilyz#PROXY protocol v2 address families.r   r   é   é   N)r   r   r	   r
   ÚUNSPECÚINETÚINET6ÚUNIXr   r   r   r   r   &   s   „ Ù-Ø€FØ€DØ€EØ�Dr   r   c                   ó   — e Zd ZdZdZdZdZy)Ú
PPProtocolz&PROXY protocol v2 transport protocols.r   r   r   N)r   r   r	   r
   r   ÚSTREAMÚDGRAMr   r   r   r!   r!   .   s   „ Ù0Ø€FØ€FØ�Er   r!   c                   ó   — e Zd ZdZy)ÚLimitRequestLinez&Request line exceeds configured limit.Nr   r   r   r   r%   r%   5   r   r   r%   c                   ó   — e Zd ZdZy)ÚLimitRequestHeadersz+Too many headers or header field too large.Nr   r   r   r   r'   r'   9   s   „ Ú5r   r'   c                   ó   — e Zd ZdZy)ÚInvalidRequestLinezInvalid request line.Nr   r   r   r   r)   r)   =   ó   „ Úr   r)   c                   ó   — e Zd ZdZy)ÚInvalidRequestMethodzInvalid HTTP method.Nr   r   r   r   r,   r,   A   ó   „ Úr   r,   c                   ó   — e Zd ZdZy)ÚInvalidHTTPVersionzInvalid HTTP version.Nr   r   r   r   r/   r/   E   r*   r   r/   c                   ó   — e Zd ZdZy)ÚInvalidHeaderNamezInvalid header name.Nr   r   r   r   r1   r1   I   r-   r   r1   c                   ó   — e Zd ZdZy)ÚInvalidHeaderzInvalid header value.Nr   r   r   r   r3   r3   M   r*   r   r3   c                   ó   — e Zd ZdZy)ÚUnsupportedTransferCodingz$Unsupported Transfer-Encoding value.Nr   r   r   r   r5   r5   Q   s   „ Ú.r   r5   c                   ó   — e Zd ZdZy)ÚInvalidChunkSizez0Invalid chunk size in chunked transfer encoding.Nr   r   r   r   r7   r7   U   s   „ Ú:r   r7   c                   ó   — e Zd ZdZy)ÚInvalidChunkExtensionz%Invalid chunk extension per RFC 9112.Nr   r   r   r   r9   r9   Y   s   „ Ú/r   r9   c                   ó˜   — e Zd ZdZdZ	 	 	 	 	 	 	 	 	 	 	 	 dd„Zd„ Zed„ «       Zd„ Z	d„ Z
d	„ Zd
„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zd„ Zy)ÚPythonProtocola‡  Callback-based HTTP/1.1 parser (pure Python fallback).

    Mirrors H1CProtocol interface for seamless switching between
    the C extension and pure Python implementations.

    Callbacks:
        on_message_begin: () -> None - Called when request starts
        on_url: (url: bytes) -> None - Called with request URL/path
        on_header: (name: bytes, value: bytes) -> None - Called for each header
        on_headers_complete: () -> bool - Called when headers done (return True to skip body)
        on_body: (chunk: bytes) -> None - Called with body data chunks
        on_message_complete: () -> None - Called when request is complete
    )Ú_on_message_beginÚ_on_urlÚ
_on_headerÚ_on_headers_completeÚ_on_bodyÚ_on_message_completeÚ_stateÚ_bufferÚ_headers_listÚmethodÚpathÚhttp_versionÚheadersÚcontent_lengthÚ
is_chunkedÚshould_keep_aliveÚis_completeÚ_body_remainingÚ
_skip_bodyÚ_chunk_stateÚ_chunk_sizeÚ_chunk_remainingÚ_limit_request_lineÚ_limit_request_fieldsÚ_limit_request_field_sizeÚ"_permit_unconventional_http_methodÚ#_permit_unconventional_http_versionÚ_header_countÚ_proxy_protocolÚ_proxy_protocol_infoÚ_proxy_protocol_doneNc                 óÚ  — || _         || _        || _        || _        || _        || _        || _        || _        |	| _        |
| _	        || _
        d| _        || _        d | _        |dk(  | _        |dk7  rdnd| _        t!        «       | _        g | _        d | _        d | _        d | _        g | _        d | _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        d| _        y )Nr   ÚoffÚproxy_protocolÚrequest_lineFTÚsize) r<   r=   r>   r?   r@   rA   rR   rS   rT   rU   rV   rW   rX   rY   rZ   rB   Ú	bytearrayrC   rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   )ÚselfÚon_message_beginÚon_urlÚ	on_headerÚon_headers_completeÚon_bodyÚon_message_completeÚlimit_request_lineÚlimit_request_fieldsÚlimit_request_field_sizeÚ!permit_unconventional_http_methodÚ"permit_unconventional_http_versionr]   s                r   Ú__init__zPythonProtocol.__init__z   s  € ð "2ˆÔØˆŒØ#ˆŒØ$7ˆÔ!ØˆŒØ$7ˆÔ!ð $6ˆÔ Ø%9ˆÔ"Ø)AˆÔ&Ø2SˆÔ/Ø3UˆÔ0ØˆÔð  .ˆÔØ$(ˆÔ!Ø$2°eÑ$;ˆÔ!ð +9¸EÒ*AÑ&À~ˆŒÜ “{ˆŒØˆÔð ˆŒØˆŒ	Ø ˆÔØˆŒØ"ˆÔØˆŒØ!%ˆÔØ ˆÔð  !ˆÔØˆŒð #ˆÔØˆÔØ !ˆÕr   c                 ó°  — | j                   j                  |«       | j                   r¯| j                  dk(  r| j                  «       s‚y| j                  dk(  r| j	                  «       sby| j                  dk(  r| j                  «       sBy| j                  dk(  r| j                  «       s"y| j                  dk(  r| j                  «       syy| j                   rŒ®yy)zÃProcess data, fire callbacks synchronously.

        Args:
            data: bytes or bytearray of incoming data

        Raises:
            ParseError: If the HTTP request is malformed
        r]   r^   rH   ÚbodyÚchunkedN)rC   ÚextendrB   Ú_parse_proxy_protocolÚ_parse_request_lineÚ_parse_headersÚ_parse_bodyÚ_parse_chunked_body)ra   Údatas     r   ÚfeedzPythonProtocol.feedµ   s±   € ð 	�‰×Ñ˜DÔ!à�lŠlØ�{‰{Ð.Ò.Ø×1Ñ1Ô3ØØ—‘ Ò.Ø×/Ñ/Ô1ØØ—‘ 	Ò)Ø×*Ñ*Ô,ØØ—‘ Ò&Ø×'Ñ'Ô)ØØ—‘ 	Ò)Ø×/Ñ/Ô1Øàð# �l�lr   c                 ó   — | j                   S )z%Return proxy protocol info if parsed.)rY   ©ra   s    r   Úproxy_protocol_infoz"PythonProtocol.proxy_protocol_infoÓ   s   € ð ×(Ñ(Ð(r   c                 ó  — d| _         | j                  j                  «        g | _        d| _        d| _        d| _        g | _        d| _        d| _	        d| _
        d| _        d| _        d| _        d| _        d| _        d| _        d| _        y)z#Reset for next request (keepalive).r^   NFTr   r_   )rB   rC   ÚclearrD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rW   rz   s    r   ÚresetzPythonProtocol.resetØ   sŒ   € à$ˆŒØ�‰×ÑÔØˆÔØˆŒØˆŒ	Ø ˆÔØˆŒØ"ˆÔØˆŒØ!%ˆÔØ ˆÔØ ˆÔØˆŒØ"ˆÔØˆÔØ !ˆÔØˆÕr   c                 óš   — | j                   dk(  r<| j                  dk(  r,d| _         d| _        | j                  r| j                  «        yyyy)z¯Mark parsing complete for EOF handling.

        Call when no more data will be received. Handles edge cases like
        chunked encoding without final trailer CRLF.
        rp   ÚtrailerÚcompleteTN)rB   rO   rL   rA   rz   s    r   ÚfinishzPythonProtocol.finishì   sO   € ð �;‰;˜)Ò#¨×(9Ñ(9¸YÒ(Fà$ˆDŒKØ#ˆDÔØ×(Ò(Ø×)Ñ)Õ+ð )ð	 )GÐ#r   c                 ó
  — t        | j                  «      dk  ry| j                  }|dv r&| j                  dd t        k(  r| j	                  «       S |dv r"| j                  dd dk(  r| j                  «       S d| _        d	| _        y)
z˜Parse PROXY protocol header if enabled.

        Returns True if parsing is complete (or not applicable),
        False if more data is needed.
        é   F)Úv2ÚautoN)Úv1r†   é   s   PROXY Tr^   )ÚlenrC   rX   ÚPP_V2_SIGNATUREÚ_parse_proxy_protocol_v2Ú_parse_proxy_protocol_v1rZ   rB   )ra   Úmodes     r   rr   z$PythonProtocol._parse_proxy_protocolù   s�   € ô ˆt�|‰|Ó˜rÒ!Øà×#Ñ#ˆð �>Ñ! d§l¡l°3°BÐ&7¼?Ò&JØ×0Ñ0Ó2Ð2ð �>Ñ! d§l¡l°2°AÐ&6¸)Ò&CØ×0Ñ0Ó2Ð2ð %)ˆÔ!Ø$ˆŒØr   c                 ó2  — | j                   j                  d«      }|dk(  r$t        | j                   «      dkD  rt        d«      ‚yt	        | j                   d| «      j                  d«      }| j                   d|dz   …= |j                  d	«      }t        |«      dk  rt        d
«      ‚|d   j                  «       }|dk(  rddddddœ| _        n�|dv r‹t        |«      dk7  rt        d|z  «      ‚	 |d   }|d   }t        |d   «      }t        |d   «      }d|cxk  rdk  r$n t        d«      ‚d|cxk  rdk  st        d«      ‚ t        d«      ‚|||||dœ| _        nt        d|z  «      ‚d| _        d| _        y# t        $ r}	t        d|	z  «      ‚d}	~	ww xY w)z|Parse PROXY protocol v1 (text format).

        Format: PROXY <PROTO> <SRC_ADDR> <DST_ADDR> <SRC_PORT> <DST_PORT>

        ó   
éÿÿÿÿék   zPROXY v1 header too longFNúlatin-1r   ú zInvalid PROXY v1 liner   ÚUNKNOWN©r]   Úclient_addrÚclient_portÚ
proxy_addrÚ
proxy_port)ÚTCP4ÚTCP6rˆ   zInvalid PROXY v1 line for %sr   é   é   zInvalid PROXY v1 port: %sr   iÿÿ  zInvalid PROXY v1 port rangezUnknown PROXY v1 protocol: %sTr^   )rC   Úfindr‰   r   ÚbytesÚdecodeÚsplitÚupperrY   ÚintÚ
ValueErrorrZ   rB   )
ra   ÚidxÚlineÚpartsÚprotoÚs_addrÚd_addrÚs_portÚd_portÚes
             r   rŒ   z'PythonProtocol._parse_proxy_protocol_v1  sÒ  € ð �l‰l×Ñ Ó(ˆØ�"Š9ä�4—<‘<Ó  3Ò&Ü&Ð'AÓBÐBØä�T—\‘\ $ 3Ð'Ó(×/Ñ/°	Ó:ˆØ�L‰L˜˜# ™'˜Ð"ð —
‘
˜3“ˆÜˆu‹:˜Š>Ü"Ð#:Ó;Ð;à�a‘—‘Ó ˆà�IÒð #,Ø#Ø#Ø"Ø"ñ)ˆDÕ%ð Ð&Ñ&Ü�5‹z˜QŠÜ&Ð'EÈÑ'MÓNÐNðHØ˜q™�Ø˜q™�Ü˜U 1™X›�Ü˜U 1™X›�ð ˜Ô( 5Ô(Ü&Ð'DÓEÐEð ./°&Ô-A¸EÒ-AÜ&Ð'DÓEÐEð .BÜ&Ð'DÓEÐEð #(Ø%Ø%Ø$Ø$ñ)ˆDÕ%ô #Ð#BÀUÑ#JÓKÐKà$(ˆÔ!Ø$ˆŒØøô% ò HÜ&Ð'BÀQÑ'FÓGÐGûðHús   Ã/&E: Å:	FÆFÆFc                 óD  — t        | j                  «      dk  ry| j                  d   }| j                  d   }t        j                  dt	        | j                  dd «      «      d   }|dz  d	z	  }|d
k7  rt        d|z  «      ‚|dz  }|t        j                  t        j                  fvrt        d|z  «      ‚d|z   }t        | j                  «      |k  ryt	        | j                  d| «      }| j                  d|…= |t        j                  k(  rddddddœ| _	        d| _
        d| _        y|dz  d	z	  }|dz  }	|t        j                  k(  r t        |«      dk  rt        d«      ‚dj                  d„ |dd	 D «       «      }
dj                  d„ |d	d D «       «      }t        j                  d|dd «      d   }t        j                  d|dd «      d   }|	t        j                   k(  rdnd}�n|t        j"                  k(  rËt        |«      dk  rt        d«      ‚t        j                  d|dd «      }t        j                  d|dd «      }dj                  d „ |D «       «      }
dj                  d!„ |D «       «      }t        j                  d|dd" «      d   }t        j                  d|d"d «      d   }|	t        j                   k(  rd#nd$}n=|t        j$                  k(  rd%dddddœ| _	        d| _
        d| _        yt        d&|z  «      ‚||
|||dœ| _	        d| _
        d| _        y)'z(Parse PROXY protocol v2 (binary format).é   Fr„   é   z>Hé   r   éð   rœ   r   z Unsupported PROXY v2 version: %dé   z Unsupported PROXY v2 command: %dNr   r•   Tr^   z"Invalid PROXY v2 IPv4 address dataú.c              3   ó2   K  — | ]  }t        |«      –— Œ y ­w©N©Ústr©Ú.0Úbs     r   ú	<genexpr>z:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>‚  s   è ø€ Ò<¨œc !ŸfÑ<ùó   ‚c              3   ó2   K  — | ]  }t        |«      –— Œ y ­wr¶   r·   r¹   s     r   r¼   z:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>ƒ  s   è ø€ Ò=¨œc !ŸfÑ=ùr½   é   é
   rš   ÚUDP4é$   z"Invalid PROXY v2 IPv6 address dataz>8Hé    ú:c              3   ó&   K  — | ]	  }d |z  –— Œ y­w©z%xNr   ©rº   Úws     r   r¼   z:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>�  ó   è ø€ Ò8¨1˜d Q�hÑ8ùó   ‚c              3   ó&   K  — | ]	  }d |z  –— Œ y­wrÆ   r   rÇ   s     r   r¼   z:PythonProtocol._parse_proxy_protocol_v2.<locals>.<genexpr>�  rÉ   rÊ   é"   r›   ÚUDP6r   z'Unsupported PROXY v2 address family: %d)r‰   rC   ÚstructÚunpackrŸ   r   r   r   r   rY   rZ   rB   r   r   Újoinr!   r"   r   r   )ra   Úver_cmdÚfam_protÚlengthÚversionÚcommandÚ
total_sizeÚ	addr_dataÚfamilyÚprotocolr©   rª   r«   r¬   r¨   Ús_wordsÚd_wordss                    r   r‹   z'PythonProtocol._parse_proxy_protocol_v2O  s4  € ô ˆt�|‰|Ó˜rÒ!Øð —,‘,˜rÑ"ˆØ—<‘< Ñ#ˆÜ—‘˜t¤U¨4¯<©<¸¸2Ð+>Ó%?Ó@ÀÑCˆð ˜T‘> aÑ'ˆØ�aŠ<Ü$Ð%GÈ'Ñ%QÓRÐRð ˜D‘.ˆØœ9Ÿ?™?¬I¯O©OÐ<Ñ<Ü$Ð%GÈ'Ñ%QÓRÐRð ˜&‘[ˆ
Üˆt�|‰|Ó˜zÒ)Øô ˜$Ÿ,™, r¨*Ð5Ó6ˆ	Ø�L‰L˜˜*˜Ð%ð ”i—o‘oÒ%à")Ø#Ø#Ø"Ø"ñ)ˆDÔ%ð )-ˆDÔ%Ø(ˆDŒKØð ˜T‘/ aÑ'ˆØ˜d‘?ˆà”X—]‘]Ò"ä�9‹~ Ò"Ü(Ð)MÓNÐNØ—X‘XÑ<¨i¸¸¨mÔ<Ó<ˆFØ—X‘XÑ=¨i¸¸!¨nÔ=Ó=ˆFÜ—]‘] 4¨°1°R¨Ó9¸!Ñ<ˆFÜ—]‘] 4¨°2°bÐ)9Ó:¸1Ñ=ˆFØ&¬*×*;Ñ*;Ò;‘FÀŠEà”x—~‘~Ò%ä�9‹~ Ò"Ü(Ð)MÓNÐNä—m‘m E¨9°S°b¨>Ó:ˆGÜ—m‘m E¨9°R¸Ð+;Ó<ˆGØ—X‘XÑ8°Ô8Ó8ˆFØ—X‘XÑ8°Ô8Ó8ˆFÜ—]‘] 4¨°2°bÐ)9Ó:¸1Ñ=ˆFÜ—]‘] 4¨°2°bÐ)9Ó:¸1Ñ=ˆFØ&¬*×*;Ñ*;Ò;‘FÀ‰Eà”x—‘Ò&ð #+Ø#Ø#Ø"Ø"ñ)ˆDÔ%ð )-ˆDÔ%Ø(ˆDŒKØô %Ð%NÐQWÑ%WÓXÐXð $Ø!Ø!Ø Ø ñ%
ˆÔ!ð %)ˆÔ!Ø$ˆŒØr   c                 óô  — | j                   j                  d«      }|dk(  ry| j                  dkD  r|| j                  kD  rt        d«      ‚t	        | j                   d| «      }| j                   d|dz   …= |j                  dd«      }t        |«      d	k7  rt        d
«      ‚|d   | _        |d   | _	        | j                  s?| j                  | j                  «      s$t        | j                  j                  d«      «      ‚|d   }|dk(  rd| _        nw|dk(  rd| _        nj| j                  st!        |j                  d«      «      ‚|j#                  d«      r	 t%        |dd «      }d|f| _        nt!        |j                  d«      «      ‚| j(                  r| j)                  «        | j*                  r| j+                  | j                  «       d| _        y# t&        $ r t!        |j                  d«      «      ‚w xY w)z,Parse request line, return True if complete.r�   r�   Fr   zRequest line is too largeNr   ó    r   zInvalid request liner   r’   s   HTTP/1.1©r   r   s   HTTP/1.0©r   r   s   HTTP/1.é   rH   T)rC   rž   rR   r%   rŸ   r¡   r‰   r)   rE   rF   rU   Ú_is_valid_methodr,   r    rG   rV   r/   Ú
startswithr£   r¤   r<   r=   rB   )ra   r¥   r¦   r§   rÔ   Úminors         r   rs   z"PythonProtocol._parse_request_line±  sÓ  € à�l‰l×Ñ Ó(ˆØ�"Š9Øð ×#Ñ# aÒ'¨C°$×2JÑ2JÒ,JÜ"Ð#>Ó?Ð?ä�T—\‘\ $ 3Ð'Ó(ˆØ�L‰L˜˜# ™'˜Ð"ð —
‘
˜4 Ó#ˆÜˆu‹:˜Š?Ü$Ð%;Ó<Ð<à˜A‘hˆŒØ˜!‘HˆŒ	ð ×6Ò6Ø×(Ñ(¨¯©Ô5Ü*¨4¯;©;×+=Ñ+=¸iÓ+HÓIÐIð ˜‘(ˆØ�kÒ!Ø &ˆDÕØ˜Ò#Ø &ˆDÕà×;Ò;Ü(¨¯©¸	Ó)BÓCÐCà×!Ñ! *Ô-ðHÜ ¨¨ Ó,�EØ)*¨E¨
�DÕ%ô )¨¯©¸	Ó)BÓCÐCà×!Ò!Ø×"Ñ"Ô$Ø�<Š<Ø�L‰L˜Ÿ™Ô#àˆŒØøô "ò HÜ,¨W¯^©^¸IÓ-FÓGÐGðHús   ÅG Ç$G7c                 óv  — 	 | j                   j                  d«      }|dk(  ryt        | j                   d| «      }| j                   d|dz   …= |s| j                  «        y| j                  dkD  r&t        |«      dz   | j                  kD  rt        d«      ‚| xj                  d	z  c_        | j                  dkD  r$| j                  | j                  kD  rt        d
«      ‚|j                  d«      }|dk(  rt        d«      ‚|d| j                  «       }| j                  |«      st        |j                  d«      «      ‚||d	z   d j                  «       }| j                  |«      rt        d«      ‚|j                  «       }| j                   j#                  ||f«       | j$                  r| j%                  ||«       �Œ¹)z3Parse headers, return True if headers are complete.Tr�   r�   FNr   r   z!Request header field is too larger   zToo many headersó   :zMissing colon in headerr’   z"Invalid characters in header value)rC   rž   rŸ   Ú_finalize_headersrT   r‰   r'   rW   rS   r3   ÚstripÚ_is_valid_tokenr1   r    Ú_has_invalid_header_charsÚlowerrD   Úappendr>   )ra   r¥   r¦   ÚcolonÚnameÚvalueÚ
name_lowers          r   rt   zPythonProtocol._parse_headersæ  s›  € àØ—,‘,×#Ñ# GÓ,ˆCØ�bŠyØä˜Ÿ™ d sÐ+Ó,ˆDØ—‘˜X˜c A™g˜XÐ&áà×&Ñ&Ô(Øð ×-Ñ-°Ò1´c¸$³iÀ!±mÀd×FdÑFdÒ6dÜ)Ð*MÓNÐNð ×Ò !Ñ#ÕØ×)Ñ)¨AÒ-°$×2DÑ2DÀt×GaÑGaÒ2aÜ)Ð*<Ó=Ð=ð —I‘I˜d“OˆEØ˜Š{Ü#Ð$=Ó>Ð>à˜˜�<×%Ñ%Ó'ˆDØ×'Ñ'¨Ô-Ü'¨¯©°IÓ(>Ó?Ð?à˜ ™˜Ð$×*Ñ*Ó,ˆEØ×-Ñ-¨eÔ4Ü#Ð$HÓIÐIð Ÿ™›ˆJØ×Ñ×%Ñ% z°5Ð&9Ô:à�ŠØ—‘ 
¨EÔ2ñQ r   c                 óZ  — | j                   | _        d}d}| j                  D �]	  \  }}|dk(  r,|�t        d«      ‚	 t        |«      }|dk  rt        d«      ‚|}Œ8|dk(  rž|j                  d	«      D �cg c]  }|j                  «       ‘Œ }}|D ]l  }|j                  «       }	|	d
k(  r|rt        d«      ‚d}Œ(|	dk(  r|sŒ0t        d«      ‚|	dv r|rt        d«      ‚d| _        ŒTt        |j                  d«      «      ‚ ŒÛ|dk(  sŒá|j                  «       }d|v rd| _        Œýd|v s�Œd| _        �Œ |r=| j                  dk  rt        d«      ‚|�t        d«      ‚d| _        d| _        d| _        n|�|| _        || _        nd| _        d| _        | j                  dk(  r1| j                  r%t        d„ | j                  D «       «      }
|
sd| _        | j                   r| j!                  «       | _        | j"                  r,d| _        d| _        | j(                  r| j)                  «        yy| j                  rd| _        d| _        y| j                  r| j                  dkD  rd| _        yd| _        d| _        | j(                  r| j)                  «        yy# t        $ r t        d«      ‚w xY wc c}w )ay  Called when all headers received.

        Validates headers for request smuggling vulnerabilities:
        - Rejects duplicate Content-Length headers
        - Rejects requests with both Content-Length and Transfer-Encoding
        - Rejects chunked Transfer-Encoding in HTTP/1.0
        - Rejects stacked chunked encoding
        - Validates Transfer-Encoding values
        NFs   content-lengthzDuplicate Content-Length headerzInvalid Content-Length valuer   zNegative Content-Lengths   transfer-encodingó   ,s   chunkedzStacked chunked encodingTs   identityz'Invalid Transfer-Encoding after chunked)s   compresss   deflates   gzipr’   ó
   connections   closeó
   keep-aliverÞ   z(Chunked encoding not allowed in HTTP/1.0z%Content-Length with Transfer-Encodingr�   rß   c              3   óT   K  — | ]   \  }}|d k(  xr d|j                  «       v –— Œ" y­w)rò   ró   N)rê   )rº   rí   rî   s      r   r¼   z3PythonProtocol._finalize_headers.<locals>.<genexpr>e  s4   è ø€ ò  á�D˜%ð ˜Ñ%ÒH¨-¸5¿;¹;»=Ð*HÓHñ ùs   ‚&(r�   rp   r_   ro   )rD   rH   r3   r£   r¤   r¡   rç   rê   rK   r5   r    rG   rJ   rI   rM   Úanyr?   rN   rB   rL   rA   rO   )ra   rI   rp   rí   rî   Úcl_valueÚvÚvalsÚvalÚ	val_lowerÚhas_keepalives              r   ræ   z PythonProtocol._finalize_headers  sÝ  € ð ×)Ñ)ˆŒð ˆØˆàŸ<™<ó +	2‰KˆD�%ØÐ(Ò(à!Ð-Ü'Ð(IÓJÐJðHÜ" 5›z�Hð ˜a’<Ü'Ð(AÓBÐBØ!)‘àÐ-Ò-ð ,1¯;©;°tÓ+<Ö= a˜Ÿ™�	Ð=�Ð=Øò O�CØ #§	¡	£�IØ  JÒ.á"Ü"/Ð0JÓ"KÐKØ"&™Ø" kÒ1â"Ü"/Ð0YÓ"ZÐZØ"Ð&HÑHá"Ü"/Ð0YÓ"ZÐZà16˜Õ.ô 8¸¿
¹
À9Ó8MÓNÐNñ'Oð* ˜Ó&Ø—k‘k“m�Ø˜s‘?Ø-2�DÕ*Ø" cÓ)Ø-1�DÖ*ðW+	2ñ\ à× Ñ  6Ò)Ü#Ð$NÓOÐOàÐ)Ü#Ð$KÓLÐLØ"ˆDŒOØ"&ˆDÔØ#%ˆDÕ ØÐ'Ø"0ˆDÔØ#1ˆDÕ ð #'ˆDÔØ#$ˆDÔ ð ×Ñ Ò&¨4×+AÒ+Aäñ  à#'§<¡<ô ó ˆMñ !Ø).�Ô&à×$Ò$Ø"×7Ñ7Ó9ˆDŒOð �?Š?Ø$ˆDŒKØ#ˆDÔØ×(Ò(Ø×)Ñ)Õ+ð )à�_Š_Ø#ˆDŒKØ &ˆDÕØ× Ò  T×%8Ñ%8¸1Ò%<Ø ˆD�Kð %ˆDŒKØ#ˆDÔØ×(Ò(Ø×)Ñ)Õ+ð )øôk "ò HÜ'Ð(FÓGÐGðHüò >s   ¼JÁ2J(ÊJ%c                 ó²  — | j                   r| j                  dk  ryt        t        | j                   «      | j                  «      }t	        | j                   d| «      }| j                   d|…= | xj                  |z  c_        | j
                  r| j                  |«       | j                  dk  r*d| _        d| _        | j                  r| j                  «        y)z$Parse Content-Length delimited body.r   FNr�   T)	rC   rM   Úminr‰   rŸ   r@   rB   rL   rA   )ra   Ú
chunk_sizeÚchunks      r   ru   zPythonProtocol._parse_body�  s²   € à�|Š|˜t×3Ñ3°qÒ8Øäœ˜TŸ\™\Ó*¨D×,@Ñ,@ÓAˆ
Ü�d—l‘l ; JÐ/Ó0ˆØ�L‰L˜˜*˜Ð%Ø×Ò 
Ñ*Õà�=Š=Ø�M‰M˜%Ô à×Ñ 1Ò$Ø$ˆDŒKØ#ˆDÔØ×(Ò(Ø×)Ñ)Ô+àr   c                 ó„  — | j                   �r›| j                  dk(  �r| j                   j                  d«      }|dk(  ryt        | j                   d| «      }| j                   d|dz   …= |j                  d«      }|dk7  r||dz   d }d	|v rt	        d
«      ‚|d| }||j                  «       k7  rt        d«      ‚|st        d«      ‚|D ]  }|dvsŒt        d«      ‚ 	 t        |d«      | _        | j                  dk(  r	d| _        �n•| j                  | _
        d| _        �n{| j                  dk(  r¦| j                   syt        t        | j                   «      | j                  «      }t        | j                   d| «      }| j                   d|…= | xj                  |z  c_
        | j                  r| j                  |«       | j                  dk(  rÎd| _        nÆ| j                  dk(  r0t        | j                   «      dk  ry| j                   dd…= d| _        n‡| j                  dk(  rx| j                   j                  d«      }|dk(  ryt        | j                   d| «      }| j                   d|dz   …= |s+d| _        d| _        | j                   r| j!                  «        y| j                   r�Œ›y# t        $ r t        d«      ‚w xY w)z Parse chunked transfer encoding.r_   r�   r�   FNr   ó   ;r   ó   zbare CR not allowedzWhitespace in chunk sizezEmpty chunk sizes   0123456789abcdefABCDEFzInvalid character in chunk sizer¯   zInvalid chunk sizer   r€   rw   Úcrlfr�   T)rC   rO   rž   rŸ   r9   rç   r7   r£   rP   r¤   rQ   rý   r‰   r@   rB   rL   rA   )	ra   r¥   Ú	size_lineÚ	semicolonÚ	chunk_extÚcÚto_readrÿ   r¦   s	            r   rv   z"PythonProtocol._parse_chunked_body–  s·  € à�l‹lØ× Ñ  FÓ*à—l‘l×'Ñ'¨Ó0�Ø˜"’9Ø ä! $§,¡,¨t°Ð"4Ó5�	Ø—L‘L  #¨¡' Ð*ð &ŸN™N¨4Ó0�	Ø ’?à )¨)°a©-¨.Ð 9�IØ 	Ñ)Ü3Ð4IÓJÐJØ )¨*¨9Ð 5�Ið  	§¡Ó 1Ò1Ü*Ð+EÓFÐFÙ Ü*Ð+=Ó>Ð>ð #ò R�AØÐ 9Ò9Ü.Ð/PÓQÐQðRðAÜ'*¨9°bÓ'9�DÔ$ð ×#Ñ# qÒ(à(1�DÖ%à,0×,<Ñ,<�DÔ)Ø(.�DÖ%à×"Ñ" fÒ,à—|’|Ø äœc $§,¡,Ó/°×1FÑ1FÓG�Ü˜dŸl™l¨8¨GÐ4Ó5�Ø—L‘L  ' Ð*Ø×%Ò%¨Ñ0Õ%à—=’=Ø—M‘M %Ô(à×(Ñ(¨AÒ-à(.�DÕ%à×"Ñ" fÒ,ä�t—|‘|Ó$ qÒ(Ø Ø—L‘L  ! Ð$Ø$*�Õ!à×"Ñ" iÒ/à—l‘l×'Ñ'¨Ó0�Ø˜"’9Ø ä˜TŸ\™\¨$¨3Ð/Ó0�Ø—L‘L  #¨¡' Ð*áà",�D”KØ'+�DÔ$Ø×0Ò0Ø×1Ñ1Ô3Øðe �lŒlðh øôg "ò AÜ*Ð+?Ó@Ð@ðAús   ÃJ* Ê*J?c                 ór   — |sydt        |«      cxk  rdk  sy y|D ]  }|dv sŒ y | j                  |«      S )z>Check if method is valid token with conventional restrictions.Fr   é   s   abcdefghijklmnopqrstuvwxyz#)r‰   rè   )ra   rE   r  s      r   rá   zPythonProtocol._is_valid_methodî  sR   € áØà”C˜“KÔ% 2Ò%Øð &Øàò 	ˆAØÐ2Ò2Ùð	ð ×#Ñ# FÓ+Ð+r   c                 ó<   — |sy|D ]  }|dk  s|dkD  r y|dv sŒ y y)z6Check if data contains only RFC 9110 token characters.Fé!   é~   s   "(),/:;<=>?@[\]{}"Tr   )ra   rw   r  s      r   rè   zPythonProtocol._is_valid_tokenû  s8   € áØØò 	ˆAØ�4Šx˜1˜tš8ÙàÐ*Ò*Ùð	ð r   c                 ó"   — d|v xs
 d|v xs d|v S )z&Check for NUL, CR, LF in header value.ó    r  ó   
r   )ra   rî   s     r   ré   z(PythonProtocol._has_invalid_header_chars  s   € à˜%ÐÒC 5¨E >ÒC°U¸e°^ÐCr   )NNNNNNéþ  éd   r  FFr\   )r   r   r	   r
   Ú	__slots__rm   rx   Úpropertyr{   r~   r‚   rr   rŒ   r‹   rs   rt   ræ   ru   rv   rá   rè   ré   r   r   r   r;   r;   ]   sž   „ ñð€Ið  ØØØ ØØ ØØ Ø!%Ø*/Ø+0Øó9"òvð< ñ)ó ð)òò(,òò2;òz`òD3òj*3òXm,ò^ò*Vòp,ò
óDr   r;   c                   ó8   — e Zd ZdZdZd„ Zedd„«       Zd„ Zd„ Z	y)	ÚCallbackRequestzxRequest object built from callback parser state.

    Works with both H1CProtocol (C extension) and PythonProtocol.
    ©rE   ÚurirF   ÚqueryÚfragmentrÔ   rH   Úheaders_bytesÚschemeÚraw_pathrI   rp   Ú
must_closer{   Ú_expect_100_continuec                 óÖ   — d | _         d | _        d | _        d | _        d | _        d | _        g | _        g | _        d| _        d| _	        d| _
        d| _        d| _        d | _        d| _        y )NÚhttpr   r   Fr  rz   s    r   rm   zCallbackRequest.__init__  so   € ØˆŒØˆŒØˆŒ	ØˆŒ
ØˆŒØˆŒØˆŒØˆÔØˆŒØˆŒØˆÔØˆŒØˆŒØ#'ˆÔ Ø$)ˆÕ!r   c                 óÌ  — ddl m}  | «       }|j                  j                  d«      |_        |j                  }d|v rQ|j                  dd«      \  }}||_         ||«      j                  dd¬«      |_        |j                  d	«      |_        n,||_         ||«      j                  dd¬«      |_        d
|_        |j                  d	«      |_        d
|_	        |j                  |_        t        t        |dd«      xs |j                  «      |_        |j                  D ��	cg c]5  \  }}	|j                  d	«      j!                  «       |	j                  d	«      f‘Œ7 c}	}|_        |rdnd|_        |j$                  xs d|_        |j&                  |_        |j*                   |_        |j                  D ](  \  }
}|
dk(  sŒ|j/                  «       dk(  sŒ d|_         |S  |S c c}	}w )zåBuild request from callback parser state.

        Args:
            parser: H1CProtocol or PythonProtocol instance
            is_ssl: Whether connection is SSL/TLS

        Returns:
            CallbackRequest instance
        r   )Úunquote_to_bytesÚasciió   ?r   zutf-8Úreplace)Úerrorsr’   Ú Úasgi_headersNÚhttpsr!  s   expects   100-continueT)Úurllib.parser#  rE   r    rF   r¡   r  r  r  r  rG   rÔ   ÚlistÚgetattrrH   r  r¢   r  rI   rJ   rp   rK   r  rê   r  )ÚclsÚparserÚis_sslr#  ÚreqÚraw_urlÚ	path_partÚ
query_partÚnr÷   rí   rî   s               r   Úfrom_parserzCallbackRequest.from_parser*  sº  € õ 	2á‹eˆØ—]‘]×)Ñ)¨'Ó2ˆŒ
ð —+‘+ˆØ�7‰?Ø$+§M¡M°$¸Ó$:Ñ!ˆI�zØ$ˆCŒLÙ'¨	Ó2×9Ñ9¸'È)Ð9ÓTˆCŒHØ"×)Ñ)¨)Ó4ˆC�Ià"ˆCŒLÙ'¨Ó0×7Ñ7¸È	Ð7ÓRˆCŒHØˆCŒIà—.‘. Ó+ˆŒØˆŒØ×)Ñ)ˆŒô
 !¤¨°ÀÓ!FÒ!XÈ&Ï.É.ÓYˆÔð Ÿ™÷
á��1ð �X‰X�iÓ ×&Ñ&Ó(¨!¯(©(°9Ó*=Ò>ó
ˆŒñ
 !'‘W¨FˆŒ
Ø#×2Ñ2Ò7°aˆÔØ×'Ñ'ˆŒØ#×5Ñ5Ð5ˆŒð "Ÿ>™>ò 	‰KˆD�%Ø�yÓ  U§[¡[£]°oÓ%EØ+/�Ô(Øàˆ
ð	ð
 ˆ
ùó!
s   Ä!:G c                 óÊ   — | j                   ry| j                  D ]9  \  }}|dk(  sŒ|j                  «       j                  d«      }|dk(  r y|dk(  r y n | j                  dk  S )z8Check if connection should be closed after this request.TÚ
CONNECTIONz 	Úclosez
keep-aliveFrß   )r  rH   rê   rç   rÔ   )ra   rí   rî   r÷   s       r   Úshould_closezCallbackRequest.should_closec  sj   € à�?Š?ØØŸ<™<ò 	‰KˆD�%Ø�|Ó#Ø—K‘K“M×'Ñ'¨Ó.�Ø˜’<ÙØ˜,Ò&Ù Ùð	ð �|‰|˜vÑ%Ð%r   c                 ó^   — |j                  «       }| j                  D ]  \  }}||k(  sŒ|c S  y)z.Get a header value by name (case-insensitive).N)r¢   rH   )ra   rí   Úhr÷   s       r   Ú
get_headerzCallbackRequest.get_headerq  s5   € à�z‰z‹|ˆØ—L‘Lò 	‰DˆAˆqØ�D‹yØ’ð	ð r   N)F)
r   r   r	   r
   r  rm   Úclassmethodr6  r:  r=  r   r   r   r  r    s2   „ ñð
€Iò*ð" ò6ó ð6òp&ór   r  )r
   rÎ   Úenumr   Ú	Exceptionr   r   r   rŠ   r   r   r!   r%   r'   r)   r,   r/   r1   r3   r5   r7   r9   r;   r  r   r   r   ú<module>rA     sõ   ðñ
ó Ý ô1�ô 1ô*�zô *ô,˜ô ,ð
 F€ô�ô ôˆwô ô�ô ô1�zô 1ô6˜*ô 6ô ˜ô  ô˜:ô ô ˜ô  ô˜
ô ô �Jô  ô/ 
ô /ô;�zô ;ô0˜Jô 0÷l
Dñ l
D÷^kò kr   