U
    g;>                     @  s  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 ddlmZmZmZmZmZmZ ddd	d
dddddddgZe	dZdddddddZddddddZedZddddddZedZdddd d!d"d#Zed$Zed%Zdddd d!d&d'Zed(Z ed)Z!ddd*d+d,Z"d-dddd.d/d0d1Z#dddd2d!d3d4Z$dd5d6d7dZ%ed8Z&dddd9d!d:d;Z'dd<d6d=d	Z(dddd>d!d?d@Z)ddddAd!dBdCZ*ddDd6dEd
Z+e+Z,dFdGddHdIdJZ-dKddLdMdZ.e.Z/ddddNd!dOdPZ0ddQd6dRdZ1e1Z2dSddTdUdZ3e3Z4dSdVdTdWdZ5dddXdYdZ6edZZ7dddd d!d[d\Z8ddddVd!d]d^Z9dd_d6d`dZ:ddddadbdZ;dS )c    )annotationsN)CallableSequenceTypeVarcast   )InvalidHeaderFormatInvalidHeaderValue)ConnectionOptionExtensionHeaderExtensionNameExtensionParameterSubprotocolUpgradeProtocol
build_hostparse_connectionparse_upgradeparse_extensionbuild_extensionparse_subprotocolbuild_subprotocolvalidate_subprotocolsbuild_www_authenticate_basicparse_authorization_basicbuild_authorization_basicTstrintbool)hostportsecurereturnc                 C  s\   zt | }W n tk
r"   Y nX |jdkr:d|  d} ||rDdndkrX|  d| } | S )z#
    Build a ``Host`` header.

       []i  P   :)	ipaddress
ip_address
ValueErrorversion)r   r    r!   address r-   6/tmp/pip-unpacked-wheel-dx_q7dq3/websockets/headers.pyr   &   s    
z
str | None)headerposr"   c                 C  s   |t | krdS | | S )z
    Return the next character from ``header`` at the given position.

    Return :obj:`None` at the end of ``header``.

    We never need to peek more than one character ahead.

    N)len)r/   r0   r-   r-   r.   
peek_aheadB   s    	r2   z[\t ]*c                 C  s    t | |}|dk	st| S )z
    Parse optional whitespace from ``header`` at the given position.

    Return the new position.

    The whitespace itself isn't returned because it isn't significant.

    N)_OWS_rematchAssertionErrorend)r/   r0   r4   r-   r-   r.   	parse_OWSQ   s    
r7   z[-!#$%&\'*+.^_`|~0-9a-zA-Z]+ztuple[str, int])r/   r0   header_namer"   c                 C  s2   t | |}|dkr"t|d| || | fS )z
    Parse a token from ``header`` at the given position.

    Return the token value and the new position.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    Nzexpected token)	_token_rer4   r   groupr6   r/   r0   r8   r4   r-   r-   r.   parse_tokenc   s    
r<   zC"(?:[\x09\x20-\x21\x23-\x5b\x5d-\x7e]|\\[\x09\x20-\x7e\x80-\xff])*"z\\([\x09\x20-\x7e\x80-\xff])c                 C  sB   t | |}|dkr"t|d| |td| dd | fS )z
    Parse a quoted string from ``header`` at the given position.

    Return the unquoted value and the new position.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    Nzexpected quoted stringz\1r   )_quoted_string_rer4   r   _unquote_resubr:   r6   r;   r-   r-   r.   parse_quoted_string{   s    
rA   z[\x09\x20-\x7e\x80-\xff]*z([\x22\x5c]))valuer"   c                 C  s.   t | }|dkrtddtd|  d S )zh
    Format ``value`` as a quoted string.

    This is the reverse of :func:`parse_quoted_string`.

    Nz-invalid characters for quoted-string encoding"z\\\1)_quotable_re	fullmatchr*   	_quote_rer@   )rB   r4   r-   r-   r.   build_quoted_string   s    
rG   z(Callable[[str, int, str], tuple[T, int]]zlist[T])
parse_itemr/   r0   r8   r"   c                 C  s   t ||dkrt||d }q g }| |||\}}|| t||}|t|krTqt ||dkrrt||d }nt|d||t ||dkrt||d }q|t|kr"qq"|t|kst|S )a  
    Parse a comma-separated list from ``header`` at the given position.

    This is appropriate for parsing values with the following grammar:

        1#item

    ``parse_item`` parses one item.

    ``header`` is assumed not to start or end with whitespace.

    (This function is designed for parsing an entire header value and
    :func:`~websockets.http.read_headers` strips whitespace from values.)

    Return a list of items.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    ,r   zexpected comma)r2   r7   appendr1   r   r5   )rH   r/   r0   r8   itemsitemr-   r-   r.   
parse_list   s"    

rM   ztuple[ConnectionOption, int]c                 C  s   t | ||\}}tt||fS )z
    Parse a Connection option from ``header`` at the given position.

    Return the protocol value and the new position.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    )r<   r   r
   r/   r0   r8   rL   r-   r-   r.   parse_connection_option   s    rO   zlist[ConnectionOption])r/   r"   c                 C  s   t t| ddS )z
    Parse a ``Connection`` header.

    Return a list of HTTP connection options.

    Args
        header: value of the ``Connection`` header.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    r   
Connection)rM   rO   r/   r-   r-   r.   r      s    z>[-!#$%&\'*+.^_`|~0-9a-zA-Z]+(?:/[-!#$%&\'*+.^_`|~0-9a-zA-Z]+)?ztuple[UpgradeProtocol, int]c                 C  s8   t | |}|dkr"t|d| |tt| | fS )z
    Parse an Upgrade protocol from ``header`` at the given position.

    Return the protocol value and the new position.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    Nzexpected protocol)_protocol_rer4   r   r   r   r:   r6   r;   r-   r-   r.   parse_upgrade_protocol  s    rS   zlist[UpgradeProtocol]c                 C  s   t t| ddS )z
    Parse an ``Upgrade`` header.

    Return a list of HTTP protocols.

    Args:
        header: Value of the ``Upgrade`` header.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    r   ZUpgrade)rM   rS   rQ   r-   r-   r.   r     s    ztuple[ExtensionParameter, int]c                 C  s   t | ||\}}t| |}d}t| |dkrt| |d }t| |dkrz|}t| ||\}}t|dkrt|d| |nt | ||\}}t| |}||f|fS )z
    Parse a single extension parameter from ``header`` at the given position.

    Return a ``(name, value)`` pair and the new position.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    N=r   rC   zinvalid quoted header content)r<   r7   r2   rA   r9   rE   r   )r/   r0   r8   namerB   Z
pos_beforer-   r-   r.   parse_extension_item_param'  s$    
   
rV   ztuple[ExtensionHeader, int]c                 C  sh   t | ||\}}t| |}g }t| |dkrVt| |d }t| ||\}}|| qtt||f|fS )a  
    Parse an extension definition from ``header`` at the given position.

    Return an ``(extension name, parameters)`` pair, where ``parameters`` is a
    list of ``(name, value)`` pairs, and the new position.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    ;r   )r<   r7   r2   rV   rJ   r   r   )r/   r0   r8   rU   
parametersZ	parameterr-   r-   r.   parse_extension_itemK  s    
rY   zlist[ExtensionHeader]c                 C  s   t t| ddS )a  
    Parse a ``Sec-WebSocket-Extensions`` header.

    Return a list of WebSocket extensions and their parameters in this format::

        [
            (
                'extension name',
                [
                    ('parameter name', 'parameter value'),
                    ....
                ]
            ),
            ...
        ]

    Parameter values are :obj:`None` when no value is provided.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    r   zSec-WebSocket-Extensions)rM   rY   rQ   r-   r-   r.   r   d  s    r   zlist[ExtensionParameter])rU   rX   r"   c                 C  s    d tt| gdd |D  S )zc
    Build an extension definition.

    This is the reverse of :func:`parse_extension_item`.

    z; c                 S  s*   g | ]"\}}|d kr|n| d| qS )NrT   r-   ).0rU   rB   r-   r-   r.   
<listcomp>  s   z(build_extension_item.<locals>.<listcomp>)joinr   r   )rU   rX   r-   r-   r.   build_extension_item  s    	
r]   zSequence[ExtensionHeader])
extensionsr"   c                 C  s   d dd | D S )zl
    Build a ``Sec-WebSocket-Extensions`` header.

    This is the reverse of :func:`parse_extension`.

    , c                 s  s   | ]\}}t ||V  qd S )N)r]   )rZ   rU   rX   r-   r-   r.   	<genexpr>  s    z"build_extension.<locals>.<genexpr>r\   )r^   r-   r-   r.   r     s    
ztuple[Subprotocol, int]c                 C  s   t | ||\}}tt||fS )z
    Parse a subprotocol from ``header`` at the given position.

    Return the subprotocol value and the new position.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    )r<   r   r   rN   r-   r-   r.   parse_subprotocol_item  s    rb   zlist[Subprotocol]c                 C  s   t t| ddS )z
    Parse a ``Sec-WebSocket-Protocol`` header.

    Return a list of WebSocket subprotocols.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    r   zSec-WebSocket-Protocol)rM   rb   rQ   r-   r-   r.   r     s    
zSequence[Subprotocol])subprotocolsr"   c                 C  s
   d | S )zl
    Build a ``Sec-WebSocket-Protocol`` header.

    This is the reverse of :func:`parse_subprotocol`.

    r_   ra   )rc   r-   r-   r.   r     s    Nonec                 C  sJ   t | tstdt | tr$td| D ]}t|s(td| q(dS )zT
    Validate that ``subprotocols`` is suitable for :func:`build_subprotocol`.

    zsubprotocols must be a listz&subprotocols must be a list, not a strzinvalid subprotocol: N)
isinstancer   	TypeErrorr   r9   rE   r*   )rc   Zsubprotocolr-   r-   r.   r     s    


)realmr"   c                 C  s    t | } t d}d|  d| S )z
    Build a ``WWW-Authenticate`` header for HTTP Basic Auth.

    Args:
        realm: Identifier of the protection space.

    zUTF-8zBasic realm=z
, charset=)rG   )rg   charsetr-   r-   r.   r     s    	z[A-Za-z0-9-._~+/]+=*c                 C  s2   t | |}|dkr"t|d| || | fS )z
    Parse a token68 from ``header`` at the given position.

    Return the token value and the new position.

    Raises:
        InvalidHeaderFormat: On invalid inputs.

    Nzexpected token68)_token68_rer4   r   r:   r6   r;   r-   r-   r.   parse_token68  s    
rj   c                 C  s   |t | k rt|d| |dS )z8
    Check that parsing reached the end of header.

    ztrailing dataN)r1   r   )r/   r0   r8   r-   r-   r.   	parse_end  s    rk   ztuple[str, str]c                 C  s   t | dd\}}| dkr,tdd| t| |dkrHtdd| ||d7 }t| |d\}}t| |d zt|	 
 }W n" tjk
r   tddd	Y nX z|d
d\}}W n  tk
r   tddd	Y nX ||fS )a!  
    Parse an ``Authorization`` header for HTTP Basic Auth.

    Return a ``(username, password)`` tuple.

    Args:
        header: Value of the ``Authorization`` header.

    Raises:
        InvalidHeaderFormat: On invalid inputs.
        InvalidHeaderValue: On unsupported inputs.

    r   Authorizationbasiczunsupported scheme:  zexpected space after schemer   z#expected base64-encoded credentialsNr'   z&expected username:password credentials)r<   lowerr	   r2   r   rj   rk   base64	b64decodeencodedecodebinasciiErrorsplitr*   )r/   schemer0   basic_credentials	user_passusernamepasswordr-   r-   r.   r     sF       )rz   r{   r"   c                 C  s4   d| kst |  d| }t|  }d| S )z
    Build an ``Authorization`` header for HTTP Basic Auth.

    This is the reverse of :func:`parse_authorization_basic`.

    r'   zBasic )r5   rp   	b64encoderr   rs   )rz   r{   ry   rx   r-   r-   r.   r   8  s    )<
__future__r   rp   rt   r(   retypingr   r   r   r   
exceptionsr   r	   r
   r   r   r   r   r   __all__r   r   r2   compiler3   r7   r9   r<   r>   r?   rA   rD   rF   rG   rM   rO   r   rR   rS   r   rV   rY   r   Zparse_extension_listr]   r   Zbuild_extension_listrb   r   Zparse_subprotocol_listr   Zbuild_subprotocol_listr   r   ri   rj   rk   r   r   r-   r-   r-   r.   <module>   sz    




B$

	0