o
    j                     @   sd  d dl mZ d dlZd dlZd dlZd dlZd dlmZmZm	Z	m
Z
 d dlmZmZmZmZmZmZmZmZmZmZmZ d dlmZmZmZ d dlmZ d dlmZmZ dadadZ d	d
 Z!dZ"G dd deZ#G dd deZ$G dd deZ%dZ&dZ'dZ(dZ)e*de+e) Z,e*dZ-e*dZ.e*dZ/e0dZ1dd Z2G dd dZ3G dd de3Z4dS )     )IntEnumN)ChunkedReaderLengthReader	EOFReaderBody)InvalidHeaderInvalidHeaderName
NoMoreDataInvalidRequestLineInvalidRequestMethodInvalidHTTPVersionLimitRequestLineLimitRequestHeadersUnsupportedTransferCodingObsoleteFoldingExpectationFailed)InvalidProxyLineInvalidProxyHeaderForbiddenProxyRequest)InvalidSchemeHeaders)bytes_to_strsplit_request_uri)permit_obsolete_foldingstrip_header_spacesc                 C   s   t | dd}|dkrdS tdu r&z
ddl}da|aW n ty%   daY nw ts0|dkr0td	ts4dS ttd
sC|dkrAtddS g }tD ]}t | |drT|| qG|rf|dkrdtdd	| dS dS )a  Check if fast C parser is available and should be used.

    Returns False if:
    - http_parser='python' is explicitly set
    - gunicorn_h1c is not installed (in 'auto' mode)
    - gunicorn_h1c < 0.4.1 (in 'auto' mode)
    - Incompatible compatibility flags are enabled (in 'auto' mode)

    Raises RuntimeError if:
    - http_parser='fast' but gunicorn_h1c is not installed
    - http_parser='fast' but gunicorn_h1c < 0.4.1
    - http_parser='fast' but incompatible flags are enabled
    http_parserautopythonFNr   Tfastz1gunicorn_h1c not installed but http_parser='fast'r   zigunicorn_h1c >= 0.4.1 required for http_parser='fast'. Please upgrade: pip install --upgrade gunicorn_h1czqhttp_parser='fast' is incompatible with compatibility flags: %s. Use http_parser='python' or disable these flags.z, )
getattr_fast_parser_availablegunicorn_h1c_fast_parser_moduleImportErrorRuntimeErrorhasattr_FAST_PARSER_INCOMPATIBLE_FLAGSappendjoin)cfgparser_settingr    incompatibleflag r,   J/var/www/ai-app/venv/lib/python3.10/site-packages/gunicorn/http/message.py_check_fast_parser#   sF   

r.   s   

 
QUIT
c                   @   s   e Zd ZdZdZdZdS )	PPCommandzPROXY protocol v2 commands.r      N)__name__
__module____qualname____doc__LOCALPROXYr,   r,   r,   r-   r/   f   s    r/   c                   @   s    e Zd ZdZdZdZdZdZdS )PPFamilyz#PROXY protocol v2 address families.r   r0         N)r1   r2   r3   r4   UNSPECINETINET6UNIXr,   r,   r,   r-   r7   l   s    r7   c                   @   s   e Zd ZdZdZdZdZdS )
PPProtocolz&PROXY protocol v2 transport protocols.r   r0   r8   N)r1   r2   r3   r4   r:   STREAMDGRAMr,   r,   r,   r-   r>   t   s
    r>   i  i   z!#$%&'*+-.^_`|~z[%s0-9a-zA-Z]+z[a-z#]zHTTP/(\d)\.(\d)z[\x00-\x08\x0a-\x1f\x7f])HOSTCONTENT-LENGTHTRANSFER-ENCODINGTRAILERAUTHORIZATIONTEc                 C   sL   d|v rdS zt | }W n
 ty   Y dS w |D ]	}||v r# dS qdS )zCheck if IP address is in the allow list.

    Args:
        ip_str: The IP address string to check
        allow_list: The original allow list (strings, may contain "*")
        networks: Pre-computed ipaddress.ip_network objects from config
    *TF)	ipaddress
ip_address
ValueError)ip_str
allow_listnetworksipnetworkr,   r,   r-   _ip_in_allow_list   s   rP   c                   @   sR   e Zd Zdd Zdd Zdd Zdd Z		dd
dZdddZdd Z	dd Z
dS )Messagec                 C   s   || _ || _|| _|| _d | _g | _g | _d | _|jrdnd| _	d| _
d| _|j| _| jdks4| jtkr7t| _|j| _| jdkrCt| _| jpGt}| j|d  d | _| | j}| j| |   d S )NhttpshttpFr   r8      )r(   unreader	peer_addrremote_addrversionheaderstrailersbodyis_sslscheme
must_close_expected_100_continuelimit_request_fieldsMAX_HEADERSlimit_request_field_sizeDEFAULT_MAX_HEADERFIELD_SIZEmax_buffer_headersparseunreadset_body_reader)selfr(   rU   rV   max_header_field_sizeunusedr,   r,   r-   __init__   s6   



zMessage.__init__c                 C   s
   d| _ d S )NT)r^   rh   r,   r,   r-   force_close   s   
zMessage.force_closec                 C   s   t  N)NotImplementedError)rh   rU   r,   r,   r-   re      s   zMessage.parsec                 C   s>   | j }t| jtrt| jd |j| r|j|jfS i g fS )a>  Return the (secure_scheme_headers, forwarder_headers) the peer is allowed to set.

        When the peer's address is not in ``forwarded_allow_ips`` (or networks),
        configured forwarding/secure-scheme policy must be ignored to prevent
        spoofing.  Returns ``({}, [])`` when the peer is untrusted.
        r   )	r(   
isinstancerV   tuplerP   forwarded_allow_ipsforwarded_allow_networkssecure_scheme_headersforwarder_headers)rh   r(   r,   r,   r-   _peer_trusted_for_forwarded   s   z#Message._peer_trusted_for_forwardedFc           	      C   s   |s|dkr|  dkr| jdk rnd| _nt|||v r>||| k}|r(dnd}|d r7|| jkr6t nd|d< || _d|v rf||v sJd	|v rO	 ||fS | jjd
krZ	 ||fS | jjdkrbdS t|||fS )a   Apply per-header policy shared between Python and fast parsers.

        Mutates ``self._expected_100_continue`` and ``self.scheme`` as needed.
        ``scheme_state`` is a single-element list used as a mutable sentinel
        so the caller can detect repeated scheme headers.

        Returns the (name, value) pair to retain, or ``None`` to drop the
        header (per ``header_map='drop'``).  Raises the same exceptions the
        Python path raises so behavior is identical regardless of parser.
        EXPECTz100-continuer0   r0   TrR   rS   r   _rG   	dangerousdropN)	lowerrX   r_   r   r]   r   r(   
header_mapr   )	rh   namevaluescheme_statert   ru   from_trailersecurer]   r,   r,   r-   _apply_header_policy   s4   

	zMessage._apply_header_policyc                 C   s  g }dd | dD }dg}|ri g }}n|  \}}|rt|| jkr*td|d}t|td }	|ddkrBt|| dd	\}
}| jj	rS|

d
}
t|
s\t|
|
 }
|rj|
tv rjt|
|d
g}|r|d dr| jjst|
|d}|	t|td 7 }	|	| j  krdkrtd ||d |r|d dsyd|}t|rt|
|	| j  krdkrtd | j|
|||||d}|d u rq|| |s|S )Nc                 S      g | ]}t |qS r,   r   ).0liner,   r,   r-   
<listcomp>      z)Message.parse_headers.<locals>.<listcomp>   
Fzlimit request headers fieldsr   z
:r0    	) 	z!limit request headers fields sizez	 r   r   )splitrv   lenr`   r   popfindr   r(   r   rstripTOKEN_RE	fullmatchr   upperRFC9110_6_5_1_FORBIDDEN_TRAILERstrip
startswithr   r   rb   r&   r'   !RFC9110_5_5_INVALID_AND_DANGEROUSsearchr   )rh   datar   rY   linesr   rt   ru   currheader_lengthr~   r   keptr,   r,   r-   parse_headers  s`   







7zMessage.parse_headersc                 C   s  d}d }| j D ]^\}}|dkr|d urtd| d|}q|dkredd |dD }|D ]8}| dkr?|r<td| dd	}q,| d
krN|rMtd| dq,| dv ra|r\td| d|   q,t|q|r| jdk rstd| d|d ur}td| dtt| | j	| _
d S |d urzt| rt|}ntd| dW n ty   td| dw |dk rtd| dtt| j	|| _
d S tt| j	| _
d S )NFrB   )reqrC   c                 S   s   g | ]}|  qS r,   )r   )r   vr,   r,   r-   r   q  r   z+Message.set_body_reader.<locals>.<listcomp>,chunkedTidentity)compressdeflategziprx   r   )rY   r   r   r|   rm   r   rX   r   r   rU   r[   str	isnumericintrJ   r   r   )rh   r   content_lengthr~   r   valsvalr,   r,   r-   rg   e  sV   


zMessage.set_body_readerc                 C   sZ   | j rdS | jD ]\}}|dkr'| d}|dkr dS |dkr% dS  nq| jdkS )NT
CONNECTIONr   closez
keep-aliveFr0   r   )r^   rY   r|   r   rX   )rh   hr   r,   r,   r-   should_close  s   
zMessage.should_closeNF)r1   r2   r3   rk   rm   re   rv   r   r   rg   r   r,   r,   r,   r-   rQ      s    

<J<rQ   c                       s   e Zd Zd  fdd	Zd!ddZdd Zd	d
 Zdd Zd!ddZd"ddZ	dd Z
dd Zdd Zdd Zdd Zdd Z fddZ  ZS )#Requestr0   c                    s   d | _ d | _d | _d | _d | _|j| _| jdk rt| _| jdkr$d| _n| jtkr0t| _t| _n| j| _|| _d | _	t
|| _t ||| d S )Nr   i   )methoduripathqueryfragmentlimit_request_lineMAX_REQUEST_LINE_fast_limit_request_line
req_numberproxy_protocol_infor.   	_use_fastsuperrk   )rh   r(   rU   rV   r   	__class__r,   r-   rk     s$   



zRequest.__init__Fc                 C   s0   |  }|s|rt t| || d S rn   )readStopIterationr	   getvaluewriterh   rU   bufstopr   r,   r,   r-   get_data  s   zRequest.get_datac                 C   s\   t  }| j||dd | jj}|dkr| jdkr| |||}| jr(| ||S | ||S )NT)r   offr0   )		bytearray	read_intor(   proxy_protocolr   _handle_proxy_protocolr   _parse_fast_parse_pythonrh   rU   r   moder,   r,   r-   re     s   zRequest.parsec              
   C   s  t |}d}	 ztj||| j| j| j| jj| jjd}W n tj	yB   t
|}| || t |}t
|| j| j kr@tdY n tjyT } ztt|d}~w tjyf } ztt|d}~w tjyx } ztt|d}~w tjy } ztt|d}~w tjy } ztt|d}~w tjy } ztt|d}~w tjy } ztt|d}~ww qt|d | _t|d | _| jjr| j | _t
| jdkrt| jzt| j}W n ty   t| jw |jpd| _|jpd| _|jpd| _d	|d
 f| _ g | _!dg}| " \}	}
|d D ]%\}}t| }t|}| #||||	|
}|du rCq%| j!$| q%|d }||d S )z:Parse request using fast C parser (gunicorn_h1c >= 0.4.1).r   T)last_lenr   r`   rb   !permit_unconventional_http_method"permit_unconventional_http_versionmax buffer headersNr   r    r0   minor_versionFrY   consumed)%bytesr!   parse_requestr   r`   rb   r(   r   r   IncompleteErrorr   r   rd   r   r   r   r   r   r   r   
ParseErrorr
   r   r   r   casefold_http_methodr   r   rJ   r   r   r   rX   rY   rv   r   r&   )rh   rU   r   r   r   resultepartsr   rt   ru   
name_bytesvalue_bytesr~   r   r   r   r,   r,   r-   r     s   	$


zRequest._parse_fastc                 C   s   |  ||| j\}}| | t|}|dd dk}	 |d}|dd dk}|dk rE|sE| || t|}t|| jkrDtdnnq|rU| j	
|dd  dS | j|d| d	d
| _||d d }|S )z'Parse request using pure Python parser.Nr8   r   Ts   

r   r       Fr   rT   )	read_liner   parse_request_liner   r   r   r   rd   r   rU   rf   r   rY   )rh   rU   r   r   r   doneidxretr,   r,   r-   r   ;  s*   

zRequest._parse_pythonc                 C   s0   |  }|s|rt tt||| dS )z7Read data from unreader and append to bytearray buffer.N)r   r   r	   r   extendr   r,   r,   r-   r   [  s   zRequest.read_intor   c                 C   s   t |}	 |d}|dkr ||  krdkrn nt||n"t|d |  kr.dkr7n ntt||| || t |}q|d| t||d d fS )z<Read a line from buffer, returning (line, remaining_buffer).Tr   r   r8   N)r   r   r   r   r   r   )rh   rU   r   limitr   r   r,   r,   r-   r   d  s   

 
zRequest.read_linec                 C   sD   t ||k r| || t ||k st|d| t||d fS )z.Read exactly count bytes from buffer/unreader.N)r   r   r   r   )rh   rU   r   countr,   r,   r-   
read_bytesw  s    zRequest.read_bytesc                 C   s   t |dk r| || t |dk s|dv r(|dd tkr(|   | ||S |dv r>|dd dkr>|   | ||S |S )ztHandle PROXY protocol detection and parsing.

        Returns the buffer with proxy protocol data consumed.
           )v2r   N)v1r      s   PROXY )r   r   PP_V2_SIGNATUREproxy_protocol_access_check_parse_proxy_protocol_v2_parse_proxy_protocol_v1r   r,   r,   r-   r   }  s   zRequest._handle_proxy_protocolc                 C   s>   t | jtrt| jd | jj| j st| jd dS dS )z2Check if proxy protocol is allowed from this peer.r   N)rp   rV   rq   rP   r(   proxy_allow_ipsproxy_allow_networksr   rl   r,   r,   r-   r     s   z#Request.proxy_protocol_access_checkc                 C   s  t |}d|vr| || t |}d|vs|d}t|d| }t||d d }|d}t|dkr<t||d }|d }	|d }
|dvrRtd	| |d
krrzt	tj
|	 t	tj
|
 W n+ tyq   t|w |dkrzt	tj|	 t	tj|
 W n ty   t|w zt|d }t|d }W n ty   td| w d|  krdkrn nd|  krdksn td| ||	||
|d| _|S )z`Parse PROXY protocol v1 (text format).

        Returns buffer with v1 header consumed.
        r   Nr8   r   r   r0   r9   )TCP4TCP6zprotocol '%s' not supportedr   r   rT      zinvalid port %sr   i  r   client_addrclient_port
proxy_addr
proxy_port)r   r   r   r   r   r   r   r   socket	inet_ptonAF_INETOSErrorAF_INET6r   rJ   r   )rh   rU   r   r   r   r   	remainingbitsprotos_addrd_addrs_portd_portr,   r,   r-   r     sZ   

.z Request._parse_proxy_protocol_v1c                 C   s|  t |dk r| || t |dk s|d }|d }tdt|dd d }|d@ d? }|d	kr8td
| |d@ }|tjtjfvrJtd| d| }t ||k r`| || t ||k sT|tjkrvdddddd| _	t
||d S |d@ d? }	|d@ }
|
tjkrtdt|dd|  }|	tjkr|dk rtdttj|dd }ttj|dd }td|dd d }td|dd d }d}n\|	tjkr|dk rtdttj|dd }ttj|dd }td|dd d }td|dd d }d}n|	tjkr'dddddd| _	t
||d S td|	 |||||d| _	t
||d S )zbParse PROXY protocol v2 (binary format).

        Returns buffer with v2 header consumed.
           r      z>H   r      rT   r8   zunsupported version %d   zunsupported command %dr5   Nr   zonly TCP protocol is supportedz"insufficient address data for IPv4   
   r   $   z"insufficient address data for IPv6    "   r   r:   zunsupported address family %d)r   r   structunpackr   r   r/   r5   r6   r   r   r>   r?   r7   r;   r  	inet_ntopr  r<   r  r:   )rh   rU   r   ver_cmd	fam_protolengthrX   commandtotal_header_sizefamilyprotocol	addr_datar  r  r  r  r  r,   r,   r-   r     sz   


z Request._parse_proxy_protocol_v2c                 C   s  dd | ddD }t|dkrtt||d | _| jjs?t| jr+t	| jdt|d   kr9dks?n t	| jt
| jsJt	| j| jjrT| j | _|d | _t| jdkrftt|| jd	krv| jd
krvtt|| jdkr| jd	kr| jdsd| jvrtt|zt| j}W n ty   tt|w |jpd| _|jpd| _|jpd| _t|d }|d u rt|d t|dt|df| _d| j  krdk sn | jjst| jd S d S )Nc                 S   r   r,   r   )r   bitr,   r,   r-   r   5  r   z.Request.parse_request_line.<locals>.<listcomp>    r8   r9   r      r0   rG   OPTIONSCONNECT/z://r   r   )r8   r   )r   r   r
   r   r   r(   r   METHOD_BADCHAR_REr   r   r   r   r   r   r   r   r   rJ   r   r   r   
VERSION_REr   r   grouprX   r   )rh   
line_bytesr
  r   matchr,   r,   r-   r   4  sR   










zRequest.parse_request_linec                    s2   t    t| jjtrtt| jd| _d S d S )Nr   )	r   rg   rp   r[   readerr   r   r   rU   rl   r   r,   r-   rg   x  s   
zRequest.set_body_reader)r0   r   )r   )r1   r2   r3   rk   r   re   r   r   r   r   r   r   r   r   r   r   rg   __classcell__r,   r,   r   r-   r     s    
W
 
	=]Dr   )5enumr   rH   rer  r  gunicorn.http.bodyr   r   r   r   gunicorn.http.errorsr   r   r	   r
   r   r   r   r   r   r   r   r   r   r   r   gunicorn.utilr   r   r   r!   r%   r.   r   r/   r7   r>   r   ra   rc   RFC9110_5_6_2_TOKEN_SPECIALScompileescaper   r+  r,  r   	frozensetr   rP   rQ   r   r,   r,   r,   r-   <module>   s@   4@



  