Ë
    ÚŠ±jKŠ  ã                   óÐ  — d Z ddl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	 e
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 e
d&«      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__© ó    úY/var/www/io.vulcan-creative.com/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
)ó   hostó   content-lengthó   transfer-encodings   trailers   authorizations   tec                   ó   — 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   3   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(   B   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*   F   s   „ Ú5r   r*   c                   ó   — e Zd ZdZy)ÚInvalidRequestLinezInvalid request line.Nr   r   r   r   r,   r,   J   ó   „ Úr   r,   c                   ó   — e Zd ZdZy)ÚInvalidRequestMethodzInvalid HTTP method.Nr   r   r   r   r/   r/   N   ó   „ Úr   r/   c                   ó   — e Zd ZdZy)ÚInvalidHTTPVersionzInvalid HTTP version.Nr   r   r   r   r2   r2   R   r-   r   r2   c                   ó   — e Zd ZdZy)ÚInvalidHeaderNamezInvalid header name.Nr   r   r   r   r4   r4   V   r0   r   r4   c                   ó   — e Zd ZdZy)ÚInvalidHeaderzInvalid header value.Nr   r   r   r   r6   r6   Z   r-   r   r6   c                   ó   — e Zd ZdZy)ÚUnsupportedTransferCodingz$Unsupported Transfer-Encoding value.Nr   r   r   r   r8   r8   ^   s   „ Ú.r   r8   c                   ó   — e Zd ZdZy)ÚInvalidChunkSizez0Invalid chunk size in chunked transfer encoding.Nr   r   r   r   r:   r:   b   s   „ Ú:r   r:   c                   ó   — e Zd ZdZy)ÚInvalidChunkExtensionz%Invalid chunk extension per RFC 9112.Nr   r   r   r   r<   r<   f   s   „ Ú/r   r<   )r   s   content-typec                   ó®   — e Zd ZdZdZ	 	 	 	 	 	 	 	 	 	 	 	 dd„Zd„ Zd„ Ze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@   rA   rB   rC   rD   rU   rV   rW   rX   rY   rZ   r[   r\   r]   rE   Ú	bytearrayrF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   )Ú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__‘   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`   ra   rK   ÚbodyÚchunkedN)rF   ÚextendrE   Ú_parse_proxy_protocolÚ_parse_request_lineÚ_parse_headersÚ_parse_bodyÚ_parse_chunked_body)rd   Údatas     r   ÚfeedzPythonProtocol.feedÌ   s±   € ð 	�‰×Ñ˜DÔ!à�lŠlØ�{‰{Ð.Ò.Ø×1Ñ1Ô3ØØ—‘ Ò.Ø×/Ñ/Ô1ØØ—‘ 	Ò)Ø×*Ñ*Ô,ØØ—‘ Ò&Ø×'Ñ'Ô)ØØ—‘ 	Ò)Ø×/Ñ/Ô1Øàð# �l�lr   c                 óF   — | j                   syt        | j                  «      S )az  Bytes fed after the completed message (b'' if none or not complete).

        Matches the accessor H1CProtocol gained in 0.6.8, so a caller does not
        have to know which parser it holds. Nothing extra is buffered here:
        feed() leaves the state loop once the message completes, and both the
        content-length and chunked paths delete what they consume.
        r   )rO   ÚbytesrF   ©rd   s    r   Ú	remainingzPythonProtocol.remainingê   s   € ð ×ÒØÜ�T—\‘\Ó"Ð"r   c                  ó   — y)z9Always False: this parser keeps the whole tail, uncapped.Fr   r~   s    r   Úremaining_truncatedz"PythonProtocol.remaining_truncatedö   s   € ð r   c                 ó   — | j                   S )z%Return proxy protocol info if parsed.)r\   r~   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).ra   NFTr   rb   )rE   rF   ÚclearrG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rR   rS   rT   rZ   r~   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.
        rs   ÚtrailerÚcompleteTN)rE   rR   rO   rD   r~   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 Tra   )ÚlenrF   r[   ÚPP_V2_SIGNATUREÚ_parse_proxy_protocol_v2Ú_parse_proxy_protocol_v1r]   rE   )rd   Úmodes     r   ru   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                 ó  — | 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   }|dk(  rt        j                  nt        j                  }	 t        j                  ||«       t        j                  ||«       	 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        t        f$ r t        d|z  «      ‚w xY w# 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   r¢   zInvalid PROXY v1 %s addressé   é   zInvalid PROXY v1 port: %sr   iÿÿ  zInvalid PROXY v1 port rangezUnknown PROXY v1 protocol: %sTra   )rF   Úfindr‘   r   r}   ÚdecodeÚsplitÚupperr\   ÚsocketÚAF_INETÚAF_INET6Ú	inet_ptonÚOSErrorÚ
ValueErrorÚintr]   rE   )rd   ÚidxÚlineÚpartsÚprotoÚs_addrÚd_addrÚafÚs_portÚd_portÚes              r   r”   z'PythonProtocol._parse_proxy_protocol_v1:  s7  € ð �l‰l×Ñ Ó(ˆØ�"Š9ä�4—<‘<Ó  3Ò&Ü&Ð'AÓBÐBØä�T—\‘\ $ 3Ð'Ó(×/Ñ/°	Ó:ˆØ�L‰L˜˜# ™'˜Ð"ð —
‘
˜3“ˆÜˆu‹:˜Š>Ü"Ð#:Ó;Ð;à�a‘—‘Ó ˆà�IÒð #,Ø#Ø#Ø"Ø"ñ)ˆDÕ%ð Ð&Ñ&Ü�5‹z˜QŠÜ&Ð'EÈÑ'MÓNÐNà˜1‘XˆFØ˜1‘XˆFð $)¨F¢?”—’¼¿¹ˆBðNÜ× Ñ   VÔ,Ü× Ñ   VÔ,ðHÜ˜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à$(ˆÔ!Ø$ˆŒØøô1 œZÐ(ò NÜ&Ð'DÀuÑ'LÓMÐMðNûô ò HÜ&Ð'BÀQÑ'FÓGÐGûðHús$   Ä,G ÅG- ÇG*Ç-	H	Ç6HÈH	c                 óp  — 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                  t        j                  fv r|	t        j                   k7  rt        d«      ‚|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   }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   }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�   Tra   z1PROXY v2: only TCP (STREAM) protocol is supportedz"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¢   é$   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£   r   z'Unsupported PROXY v2 address family: %d)r‘   rF   ÚstructÚunpackr}   r   r   r   r   r\   r]   rE   r   r    r!   r$   r%   Újoinr   )rd   Ú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_v2�  sL  € ô ˆ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‘?ˆð ”h—m‘m¤X§^¡^Ð4Ñ4¸ÄZ×EVÑEVÒ9VÜ$ØCóð ð ”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ØŠ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Ø‰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«      «      ‚| j                  dk(  r| j                  dk7  rt        d
«      ‚| j                  dk7  rC| j                  dk7  r4| j                  j                  d«      sd| j                  vrt        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   OPTIONSs   CONNECTó   /s   ://s   HTTP/1.1©r   r   s   HTTP/1.0©r   r   s   HTTP/1.é   rK   T)rF   r¦   rU   r(   r}   r¨   r‘   r,   rH   rI   rX   Ú_is_valid_methodr/   r§   Ú
startswithrJ   rY   r2   r°   r¯   r?   r@   rE   )rd   r±   r²   r³   rß   Úminors         r   rv   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ð �9‰9˜Ò §¡°
Ò!:Ü$Ð%;Ó<Ð<ð �K‰K˜:Ò%Ø—I‘I Ò%ØŸ	™	×,Ñ,¨TÔ2Ø $§)¡)Ñ+Ü$Ð%;Ó<Ð<ð ˜‘(ˆØ�kÒ!Ø &ˆDÕØ˜Ò#Ø &ˆDÕà×;Ò;Ü(¨¯©¸	Ó)BÓCÐCà×!Ñ! *Ô-ðHÜ ¨¨ Ó,�EØ)*¨E¨
�DÕ%ô )¨¯©¸	Ó)BÓCÐCà×!Ò!Ø×"Ñ"Ô$Ø�<Š<Ø�L‰L˜Ÿ™Ô#àˆŒØøô "ò HÜ,¨W¯^©^¸IÓ-FÓGÐGðHús   ÇI É$I2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)rF   r¦   r}   Ú_finalize_headersrW   r‘   r*   rZ   rV   r6   ÚstripÚ_is_valid_tokenr4   r§   Ú_has_invalid_header_charsÚlowerrG   ÚappendrA   )rd   r±   r²   ÚcolonÚnameÚvalueÚ
name_lowers          r   rw   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                 óè  — | j                   | _        d}d}t        «       }| j                  D �]F  \  }}|t        v r2||v rt	        d|j                  d«      z  «      ‚|j                  |«       |dk(  r,|�t	        d«      ‚	 t        |«      }|dk  rt	        d	«      ‚|}Œr|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| _        �ŒI |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 )a³  Called when all headers received.

        Validates headers for request smuggling vulnerabilities:
        - Rejects duplicate Content-Length headers
        - Rejects duplicate Host and Content-Type 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
        NFúDuplicate %s headerrš   r   zDuplicate Content-Length headerzInvalid Content-Length valuer   zNegative Content-Lengthr   ó   ,s   chunkedzStacked chunked encodingTs   identityz'Invalid Transfer-Encoding after chunked)s   compresss   deflates   gzipó
   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>´  s4   è ø€ ò  á�D˜%ð ˜Ñ%ÒH¨-¸5¿;¹;»=Ð*HÓHñ ùs   ‚&(r‰   rs   rb   rr   )rG   rK   ÚsetÚRFC9110_5_3_SINGLETON_FIELDSr6   r§   Úaddr°   r¯   r¨   rô   r÷   rN   r8   rJ   rM   rL   rP   ÚanyrB   rQ   rE   rO   rD   rR   )rd   rL   rs   Úseen_singletonsrú   rû   Úcl_valueÚvÚvalsÚvalÚ	val_lowerÚhas_keepalives               r   ró   z PythonProtocol._finalize_headersV  s%  € ð ×)Ñ)ˆŒð ˆØˆÜ›%ˆàŸ<™<ó 4	2‰KˆD�%ð Ô3Ñ3Ø˜?Ñ*Ü'Ø-°·±¸IÓ0FÑFóHð Hà×#Ñ# 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Ö*ði4	2ñn à× Ñ  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   Â KÂ6K/ËK,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)	rF   rP   Úminr‘   r}   rC   rE   rO   rD   )rd   Ú
chunk_sizeÚchunks      r   rx   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(  rÒ| j                   j                  d«      }|dk(  ryt        | j                   d| «      }| j                   d|dz   …= |s+d| _        d| _        | j                   r| j!                  «        y|j                  d«      }	|	dkD  rD|d|	 j                  d«      j#                  «       }
|
t$        v rt'        |
j)                  d«      «      ‚| j                   r�Œ÷y# t        $ r t        d«      ‚w xY w)z Parse chunked transfer encoding.rb   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ˆ   rz   Úcrlfr‰   Trò   s    	rš   )rF   rR   r¦   r}   r<   rô   r:   r°   rS   r¯   rT   r  r‘   rC   rE   rO   rD   r÷   ÚRFC9110_6_5_1_FORBIDDEN_TRAILERr4   r§   )rd   r±   Ú	size_lineÚ	semicolonÚ	chunk_extÚcÚto_readr  r²   rù   rú   s              r   ry   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Øð Ÿ	™	 $›�Ø˜1’9Ø  ˜<×-Ñ-¨fÓ5×;Ñ;Ó=�DØÔ>Ñ>Ü/°·±¸IÓ0FÓGÐGðu �lŒlðx øôw "ò AÜ*Ð+?Ó@Ð@ðAús   ÃL ÌL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õ   )rd   rH   r  s      r   rî   zPythonProtocol._is_valid_methodE  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   )rd   rz   r  s      r   rõ   zPythonProtocol._is_valid_tokenR  s8   € áØØò 	ˆAØ�4Šx˜1˜tš8ÙàÐ*Ò*Ùð	ð r   c                 óD   — |D ]  }|dk  sd|cxk  rdk  sn |dk(  sŒ y y)zARFC 9110 section 5.5: only VCHAR, SP, HTAB, and obs-text allowed.rÌ   rÍ   é   é   TFr   )rd   rû   r  s      r   rö   z(PythonProtocol._has_invalid_header_chars^  s2   € àò 	ˆAØ�DŠy˜D AÔ-¨Ô-°°d³Ùð	ð r   )NNNNNNéþ  éd   r$  FFr_   )r   r   r	   r
   Ú	__slots__rp   r{   r   Úpropertyr�   rƒ   r†   rŠ   ru   r”   r“   rv   rw   ró   rx   ry   rî   rõ   rö   r   r   r   r>   r>   t   s·   „ ñð€Ið  ØØØ ØØ ØØ Ø!%Ø*/Ø+0Øó9"òvò<
#ð ñó ðð ñ)ó ð)òò(,òò2EòNgòR>ò@*3òXx,òtò*^ò@,ò
ó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.
    ©rH   ÚurirI   ÚqueryÚfragmentrß   rK   Úheaders_bytesÚschemeÚraw_pathrL   rs   Ú
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*  r~   s    r   rp   zCallbackRequest.__init__s  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}	}|_        t#        «       }
|j                  D ]P  \  }}|j%                  «       }|t&        v sŒ||
v rt)        d|j                  d	«      z  «      ‚|
j+                  |«       ŒR |rdnd|_        |j.                  xs d|_        |j0                  |_        |j4                   |_        |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_headersNrþ   Úhttpsr4  s   expects   100-continueT)Úurllib.parser6  rH   r§   rI   r¨   r0  r,  r+  r-  rJ   rß   ÚlistÚgetattrrK   r.  r©   r  r÷   r  r6   r  r/  rL   rM   rs   rN   r1  r2  )ÚclsÚparserÚis_sslr6  ÚreqÚraw_urlÚ	path_partÚ
query_partÚnr	  r  rú   Ú_valueÚloweredrû   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Ó*=Ò>ó
ˆŒô ›%ˆØ"ŸN™Nò 	-‰LˆD�&Ø—j‘j“lˆGØÔ6Ò6Ø˜oÑ-Ü'Ø-°·±¸yÓ0IÑIóKð Kà×#Ñ# GÕ,ð	-ñ !'‘W¨FˆŒ
Ø#×2Ñ2Ò7°aˆÔØ×'Ñ'ˆŒØ#×5Ñ5Ð5ˆŒð "Ÿ>™>ò 	‰KˆD�%Ø�yÓ  U§[¡[£]°oÓ%EØ+/�Ô(Øàˆ
ð	ð
 ˆ
ùó=
s   Ä!:I	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ì   )r1  rK   r÷   rô   rß   )rd   rú   rû   r	  s       r   Úshould_closezCallbackRequest.should_closeË  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©   rK   )rd   rú   Úhr	  s       r   Ú
get_headerzCallbackRequest.get_headerÙ  s5   € à�z‰z‹|ˆØ—L‘Lò 	‰DˆAˆqØ�D‹yØ’ð	ð r   N)F)
r   r   r	   r
   r&  rp   ÚclassmethodrK  rO  rR  r   r   r   r)  r)  f  s4   „ ñð
€Iò*ð" òDó ðDòL&ór   r)  )r
   rª   rÙ   Úenumr   Ú	Exceptionr   r   r   r’   Ú	frozensetr  r   r   r$   r(   r*   r,   r/   r2   r4   r6   r8   r:   r<   r  r>   r)  r   r   r   ú<module>rW     s  ðñ
ó Û Ý ô1�ô 1ô*�zô *ô,˜ô ,ð
 F€ñ
 #,ð -ó #Ð ô�ô ôˆwô ô�ô ô1�zô 1ô6˜*ô 6ô ˜ô  ô˜:ô ô ˜ô  ô˜
ô ô �Jô  ô/ 
ô /ô;�zô ;ô0˜Jô 0ñ  )ð *ó  Ð ÷oñ o÷dyò yr   