o
    NK&hI                  	   @  s  d dl mZ d dlZd dlmZ d dlmZmZmZ d dl	m
Z
 d dlmZ d dlmZ eeeef  Zeeeef  Zeeeeef f Zeeeef  Zd\ZZed	e d
e de dejZdZeeZede d ZG dd dZ G dd dZ!G dd de"Z#dDddZ$dEddZ%ed e de d!e d"ejZ&dFd$d%Z'dFd&d'Z(dGd+d,Z)dHd.d/Z*dId2d3Z+d4d5 e,d6D Z-dJd<d=Z.	dKdLdBdCZ/dS )M    )annotationsN)Iterable)AnyOptionalUnion)unquote)InvalidHeader)STATUS_CODES)z([\w!#$%&'*+\-.^_`|~]+)z	"([^"]*)"z;\s*z=(?:|)z*(?:[0-9A-Fa-f]{0,4}:){2,7}[0-9A-Fa-f]{0,4}z((?:\[z)\])|[a-zA-Z0-9.\-]{1,253})(?::(\d{1,5}))?c                   @  sP   e Zd ZdZdddZdd	 Zd
d ZdddZedddZ	e
dddZdS )	MediaTypea~  A media type, as used in the Accept header.

    This class is a representation of a media type, as used in the Accept
    header. It encapsulates the type, subtype and any parameters, and
    provides methods for matching against other media types.

    Two separate methods are provided for searching the list:
    - 'match' for finding the most preferred match (wildcards supported)
    -  operator 'in' for checking explicit matches (wildcards as literals)

    Args:
        type_ (str): The type of the media type.
        subtype (str): The subtype of the media type.
        **params (str): Any parameters for the media type.
    type_strsubtypeparamsc                 K  sb   || _ || _t|dd| _|| _| d| | _d| j dt| j | jdk| j dkf| _d S )Nqz1.0/*)	typer   floatgetr   r   mimelenkey)selfr   r   r    r   @/var/www/html/venv/lib/python3.10/site-packages/sanic/headers.py__init__5   s   
zMediaType.__init__c                 C  s    | j ddd | j D  S )N c                 s  s$    | ]\}}d | d| V  qdS );=Nr   .0kvr   r   r   	<genexpr>H      " z%MediaType.__repr__.<locals>.<genexpr>)r   joinr   itemsr   r   r   r   __repr__G   s    zMediaType.__repr__c                 C  s>   t |trd|v rtd| j|kS t |tr| j|jkS tS )zjCheck for mime (str or MediaType) identical type/subtype.
        Parameters such as q are not considered.r    z&Use match() to compare with parameters)
isinstancer   
ValueErrorr   r   NotImplemented)r   otherr   r   r   __eq__J   s   


zMediaType.__eq__mime_with_paramsUnion[str, MediaType]returnOptional[MediaType]c                   s   t |tr
t|n|}|r>t fdd|j D r> j|jks, jdks,|jdkr> j|jks< jdks<|jdkr> S dS )a  Match this media type against another media type.

        Check if this media type matches the given mime type/subtype.
        Wildcards are supported both ways on both type and subtype.
        If mime contains a semicolon, optionally followed by parameters,
        the parameters of the two media types must match exactly.

        .. note::
            Use the `==` operator instead to check for literal matches
            without expanding wildcards.


        Args:
            media_type (str): A type/subtype string to match.

        Returns:
            MediaType: Returns `self` if the media types are compatible.
            None: Returns `None` if the media types are not compatible.
        c                 3  s$    | ]\}} j ||kV  qd S N)r   r   r"   r*   r   r   r&   x   r'   z"MediaType.match.<locals>.<genexpr>r   N)	r,   r   r   _parseallr   r)   r   r   )r   r1   mtr   r*   r   matchW   s    

 zMediaType.matchboolc                 C  s   t dd | j| jfD S )zReturn True if this media type has a wildcard in it.

        Returns:
            bool: True if this media type has a wildcard in it.
        c                 s  s    | ]}|d kV  qdS )r   Nr   )r#   partr   r   r   r&          z)MediaType.has_wildcard.<locals>.<genexpr>)anyr   r   r*   r   r   r   has_wildcard   s   zMediaType.has_wildcardc                 C  sz   |  }d|vr
d S |d^}}|dd\}}|r|s$td| dd dd |D D }| | | fi |S )	Nr   r       zInvalid media type: c                 S  s   i | ]\}}|  |  qS r   )strip)r#   r   valuer   r   r   
<dictcomp>   s    z$MediaType._parse.<locals>.<dictcomp>c                 s  s    | ]	}| d dV  qdS )r!   r?   N)split)r#   paramr   r   r   r&      s    z#MediaType._parse.<locals>.<genexpr>)r@   rC   r-   lstriprstrip)clsr1   mtyper   
raw_paramsr   r   r   r   r   r   r6      s   zMediaType._parseN)r   r   r   r   r   r   )r1   r2   r3   r4   )r3   r:   )r1   r   r3   r4   )__name__
__module____qualname____doc__r   r+   r0   r9   propertyr>   classmethodr6   r   r   r   r   r   $   s    

0r   c                   @  s^   e Zd Z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dZ
ed#ddZdS )$Matcheda  A matching result of a MIME string against a header.

    This class is a representation of a matching result of a MIME string
    against a header. It encapsulates the MIME string, the header, and
    provides methods for matching against other MIME strings.

    Args:
        mime (str): The MIME string to match.
        header (MediaType): The header to match against, if any.
    r   r   headerr4   c                 C  s   || _ || _d S r5   )r   rQ   )r   r   rQ   r   r   r   r      s   
zMatched.__init__c                 C  s   | rd|  d| j  dS dS )N<z	 matched >z
<no match>rQ   r*   r   r   r   r+      s   zMatched.__repr__c                 C     | j S r5   )r   r*   r   r   r   __str__   s   zMatched.__str__c                 C  s
   | j d uS r5   rT   r*   r   r   r   __bool__   s   
zMatched.__bool__r/   r   r3   r:   c                 C  sL   z	|  |\}}W n
 ty   Y dS w t|o$| jr|jp$| j o$|j S )NF)_compare	TypeErrorr:   rQ   )r   r/   compother_acceptr   r   r   r0      s   zMatched.__eq__tuple[bool, Matched]c                 C  s\   t |trt|}| j|krd|fS |}t |tr"| j|jk|fS td| j d| d)NTz8Comparison not supported between unequal mime types of 'z' and '')r,   r   rP   parser   rQ   rY   )r   r/   parsedr   r   r   rX      s   



zMatched._compareUnion[str, Matched]Optional[Matched]c                 C  s>   t |tr
t|n|}| jr|jsdS | j|jr|S dS )a  Match this MIME string against another MIME string.

        Check if this MIME string matches the given MIME string. Wildcards are supported both ways on both type and subtype.

        Args:
            other (str): A MIME string to match.

        Returns:
            Matched: Returns `self` if the MIME strings are compatible.
            None: Returns `None` if the MIME strings are not compatible.
        N)r,   r   rP   r^   rQ   r9   )r   r/   acceptr   r   r   r9      s   zMatched.matchrawc                 C  s   t |}| ||S r5   r   r6   )rG   rc   
media_typer   r   r   r^      s   

zMatched.parseN)r   r   rQ   r4   )r/   r   r3   r:   )r3   r\   )r/   r`   r3   ra   )rc   r   r3   rP   )rJ   rK   rL   rM   r   r+   rV   rW   r0   rX   r9   rO   r^   r   r   r   r   rP      s    



rP   c                   @  s(   e Zd ZdZddddd	Zd
d ZdS )
AcceptLista'  A list of media types, as used in the Accept header.

    The Accept header entries are listed in order of preference, starting
    with the most preferred. This class is a list of `MediaType` objects,
    that encapsulate also the q value or any other parameters.

    Two separate methods are provided for searching the list:
    - 'match' for finding the most preferred match (wildcards supported)
    -  operator 'in' for checking explicit matches (wildcards as literals)

    Args:
        *args (MediaType): Any number of MediaType objects.
    T)accept_wildcardsmimesr   r3   rP   c                  s:   t  fddt| D }t|r|d dd  S d S )a  Find a media type accepted by the client.

        This method can be used to find which of the media types requested by
        the client is most preferred against the ones given as arguments.

        The ordering of preference is set by:
        1. The order set by RFC 7231, s. 5.3.2, giving a higher priority
            to q values and more specific type definitions,
        2. The order of the arguments (first is most preferred), and
        3. The first matching entry on the Accept header.

        Wildcards are matched both ways. A match is usually found, as the
        Accept headers typically include `*/*`, in particular if the header
        is missing, is not manually set, or if the client is a browser.

        Note: the returned object behaves as a string of the mime argument
        that matched, and is empty/falsy if no match was found. The matched
        header entry `MediaType` or `None` is available as the `m` attribute.

        Args:
            mimes (List[str]): Any MIME types to search for in order of preference.
            accept_wildcards (bool): Match Accept entries with wildcards in them.

        Returns:
            Match: A match object with the mime string and the MediaType object.
        c                 3  sL    | ]!\}} s|j stD ]\}}||r|j ||||fV  qqd S r5   )r>   	enumerater9   r   )r#   jaccir   rg   rh   r   r   r&     s    z#AcceptList.match.<locals>.<genexpr>r   N)r   N)sortedri   rP   )r   rg   rh   ar   rm   r   r9     s   zAcceptList.matchc                 C  s   d dd | D S )z5Format as Accept header value (parsed, not original).z, c                 s  s    | ]}t |V  qd S r5   )r   r#   mr   r   r   r&   '  r<   z%AcceptList.__str__.<locals>.<genexpr>)r(   r*   r   r   r   rV   %  s   zAcceptList.__str__N)rh   r   r3   rP   )rJ   rK   rL   rM   r9   rV   r   r   r   r   rf      s    $rf   rb   Optional[str]r3   c                 C  sp   | s| dkr	t  S d} zdd dd | dD D }|stt t|dd d	W S  ty7   td
|  w )a~  Parse an Accept header and order the acceptable media types according to RFC 7231, s. 5.3.2

    https://datatracker.ietf.org/doc/html/rfc7231#section-5.3.2

    Args:
        accept (str): The Accept header value to parse.

    Returns:
        AcceptList: A list of MediaType objects, ordered by preference.

    Raises:
        InvalidHeader: If the header value is invalid.
    r   z*/*c                 S     g | ]}|r|qS r   r   )r#   r8   r   r   r   
<listcomp>=  s    z parse_accept.<locals>.<listcomp>c                 S  s   g | ]}t |qS r   rd   )r#   rH   r   r   r   ru   ?  s    ,c                 S  rU   r5   r   )xr   r   r   <lambda>D  s    zparse_accept.<locals>.<lambda>rw   z Invalid header value in Accept: )rf   rC   r-   ro   r   )rb   rp   r   r   r   parse_accept*  s   rz   rA   r   tuple[str, Options]c                 C  sP   |  d}|dkri }ndd t| |d D }| d| } |   |fS )a	  Parse content-type and content-disposition header values.

    E.g. `form-data; name=upload; filename="file.txt"` to
    ('form-data', {'name': 'upload', 'filename': 'file.txt'})

    Mostly identical to cgi.parse_header and werkzeug.parse_options_header
    but runs faster and handles special characters better.

    Unescapes %22 to `"` and %0D%0A to `
` in field values.

    Args:
        value (str): The header value to parse.

    Returns:
        Tuple[str, Options]: The header value and a dict of options.
    r    r   c                 S  s<   i | ]}| d  | dp| dddddqS )r?         z%22"z%0D%0A
)grouplowerreplacerq   r   r   r   rB   ^  s    z(parse_content_header.<locals>.<dictcomp>N)find_paramfinditerr@   r   )rA   posoptionsr   r   r   parse_content_headerI  s   
r   z(?:z)=z\s*($|[;,])Optional[Options]c                 C  s  |  dd}|j}|du s|sdS d|}||vrdS d }}g }d}t|ddd D ]P}| |ks:|dkrC|r> nA|dd= | }| \}	}
}}| ddd }|	p_|
	ddddd }|
||f |d	v rv||krvd
}|r~|dkr~ nq.|rtt|S dS )zParse RFC 7239 Forwarded headers.
    The value of `by` or `secret` must match `config.FORWARDED_SECRET`
    :return: dict with keys and values, or None if nothing matched
    	forwardedNrv   Fr   r    z"\r~   )secretbyT)getallFORWARDED_SECRETr(   _rparamr   startendgroupsr   r   appendfwd_normalizereversed)headersconfigrQ   r   sepr   r   foundrr   	val_token
val_quotedr   valr   r   r   parse_forwardedp  s4   

r   c              	     s   |j }|j}|o|d  s=|r=|dksJ z|j}dd dd |D D }||   W n ttfy<   Y nw  sAdS  fdd}t| S )	z Parse traditional proxy headers.Nr   c                 S  rt   r   r   )r#   pr   r   r   ru     s    z$parse_xforwarded.<locals>.<listcomp>c                 s  s(    | ]}| d D ]}| V  q	qdS )rv   N)rC   r@   )r#   hr   r   r   r   r&     s    
z#parse_xforwarded.<locals>.<genexpr>c                  3  s0    d fV  dD ]\} }|  |d fV  qd S )Nfor))protozx-scheme)r   zx-forwarded-proto)hostzx-forwarded-host)portzx-forwarded-port)pathzx-forwarded-path)getone)r   rQ   addrr   r   r   r     s
   
z!parse_xforwarded.<locals>.options)REAL_IP_HEADERPROXIES_COUNTr   r   FORWARDED_FOR_HEADERKeyError
IndexErrorr   )r   r   real_ip_headerproxies_countforwarded_forproxiesr   r   r   r   parse_xforwarded  s(   
r   fwdOptionsIterableOptionsc              	   C  s   i }| D ]D\}}|durHz2|dv rt |||< n%|dv r#| ||< n|dkr.t|||< n|dkr9t|||< n|||< W q tyG   Y qw q|S )zNormalize and convert values extracted from forwarded headers.

    Args:
        fwd (OptionsIterable): An iterable of key-value pairs.

    Returns:
        Options: A dict of normalized key-value pairs.
    N)r   r   )r   r   r   r   )fwd_normalize_addressr   intr   r-   )r   retr   r   r   r   r   r     s&   	r   r   c                 C  s:   | dkrt  | dr| S t| rd|  d} |  S )zNormalize address fields of proxy headers.

    Args:
        addr (str): An address string.

    Returns:
        str: A normalized address string.
    unknown_[])r-   
startswith_ipv6_re	fullmatchr   )r   r   r   r   r     s   	

r   r   #tuple[Optional[str], Optional[int]]c                 C  s<   t | }|s	dS | \} }|  |durt|fS dfS )zSplit host:port into hostname and port.

    Args:
        host (str): A host string.

    Returns:
        Tuple[Optional[str], Optional[int]]: A tuple of hostname and port.
    )NNN)_host_rer   r   r   r   )r   rr   r   r   r   r   
parse_host  s
   
	r   c                 C  s    g | ]}d |t |df qS )s   HTTP/1.1 %d %b
s   UNKNOWN)r	   r   )r#   statusr   r   r   ru     s    ru   i  r   r   r   HeaderBytesIterablebytesc                 C  s*   t |  }|D ]}|d| 7 }q|d7 }|S )zFormat a HTTP/1.1 response header.

    Args:
        status (int): The HTTP status code.
        headers (HeaderBytesIterable): An iterable of header tuples.

    Returns:
        bytes: The formatted response header.
    s   %b: %b
s   
)_HTTP1_STATUSLINES)r   r   r   r   r   r   r   format_http1_response   s
   r   rQ   prefixes!Optional[Union[list, tuple, set]]#tuple[Optional[str], Optional[str]]c                 C  sT   |r
t |tttfsd}| dur&|D ]}|| v r%|| |d  f  S qd| fS )aO  Parses any header with the aim to retrieve any credentials from it.

    Args:
        header (Optional[str]): The header to parse.
        prefixes (Optional[Union[List, Tuple, Set]], optional): The prefixes to look for. Defaults to None.

    Returns:
        Tuple[Optional[str], Optional[str]]: The prefix and the credentials.
    )BasicBearerTokenNr   )r,   listtupleset	partitionr@   )rQ   r   prefixr   r   r   parse_credentials  s   r   )rb   rs   r3   rf   )rA   r   r3   r{   )r3   r   )r   r   r3   r   )r   r   r3   r   )r   r   r3   r   )r   r   r   r   r3   r   r5   )rQ   rs   r   r   r3   r   )0
__future__r   recollections.abcr   typingr   r   r   urllib.parser   sanic.exceptionsr   sanic.helpersr	   r   r   HeaderIterabler   r   dictr   r   r   _token_quotedcompileASCIIr   _ipv6r   r   r   rP   r   rf   rz   r   r   r   r   r   r   r   ranger   r   r   r   r   r   r   <module>   sF    "

O
8
"$

&
&


