B
    â•]bø>  ã               @  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
mZmZmZ ddl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„Z0e0Z1ddddNd!œdOdP„Z2ddQd6œdRd„Z3e3Z4dSddTœdUd„Z5e5Z6dSdVdTœdWd„Z7dddXœdYd„Z8e dZ¡Z9dddd d!œd[d\„Z:ddddVd!œd]d^„Z;dd_d6œd`d„Z<ddddaœdbd„Z=dS )cé    )ÚannotationsN)ÚCallableÚListÚOptionalÚSequenceÚTupleÚTypeVarÚcasté   )Ú
exceptions)Ú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\   y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   ú:)Ú	ipaddressZ
ip_addressÚ
ValueErrorÚversion)r!   r"   r#   Zaddress© r-   ú1lib/python3.7/site-packages/websockets/headers.pyr   &   s    
zOptional[str])Ú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  s4   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   ÚInvalidHeaderFormatÚ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  sD   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   r:   Ú_unquote_reÚsubr;   r6   )r/   r0   r8   r4   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Ð   x t ||ƒdkr t||d ƒ}qW g }x”| |||ƒ\}}| |¡ t||ƒ}|t|ƒkrZP t ||ƒdkrxt||d ƒ}nt |d||¡‚x t ||ƒdkr¨t||d ƒ}qŠW |t|ƒkr(P q(W |t|ƒksÌt‚|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   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    rN   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   Z
Connection)rM   rN   )r/   r-   r-   r.   r   ô   s    z>[-!#$%&\'*+.^_`|~0-9a-zA-Z]+(?:/[-!#$%&\'*+.^_`|~0-9a-zA-Z]+)?zTuple[UpgradeProtocol, int]c             C  s:   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   r;   r6   )r/   r0   r8   r4   r-   r-   r.   Úparse_upgrade_protocol	  s
    rP   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   rP   )r/   r-   r-   r.   r     s    zTuple[ExtensionParameter, int]c             C  s¢   t | ||ƒ\}}t| |ƒ}d}t| |ƒdkr–t| |d ƒ}t| |ƒdkr||}t| ||ƒ\}}t |¡dkrŒt |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:   )r/   r0   r8   ÚnamerB   Z
pos_beforer-   r-   r.   Úparse_extension_item_param-  s    

rS   zTuple[ExtensionHeader, int]c             C  sl   t | ||ƒ\}}t| |ƒ}g }x:t| |ƒdkrXt| |d ƒ}t| ||ƒ\}}| |¡ q W 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   rS   rJ   r	   r   )r/   r0   r8   rR   Ú
parametersZ	parameterr-   r-   r.   Úparse_extension_itemQ  s    
rV   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   rV   )r/   r-   r-   r.   r   j  s    r   zList[ExtensionParameter])rR   rU   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 )NrQ   r-   )Ú.0rR   rB   r-   r-   r.   ú
<listcomp>”  s   z(build_extension_item.<locals>.<listcomp>)Újoinr	   r   )rR   rU   r-   r-   r.   Úbuild_extension_item‡  s    	
rZ   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`.

    z, c             s  s   | ]\}}t ||ƒV  qd S )N)rZ   )rW   rR   rU   r-   r-   r.   ú	<genexpr>¢  s    z"build_extension.<locals>.<genexpr>)rY   )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   )r/   r0   r8   rL   r-   r-   r.   Úparse_subprotocol_item©  s    r]   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   r]   )r/   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`.

    z, )rY   )r^   r-   r-   r.   r   É  s    ÚNonec             C  sN   t | tƒstdƒ‚t | tƒr$tdƒ‚x$| D ]}t |¡s*td|› ƒ‚q*W 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+   )r^   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   )rb   Úcharsetr-   r-   r.   r   ä  s    	z[A-Za-z0-9-._~+/]+=*c             C  s4   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:   r;   r6   )r/   r0   r8   r4   r-   r-   r.   Úparse_token68õ  s
    
re   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:   )r/   r0   r8   r-   r-   r.   Ú	parse_end  s    rf   zTuple[str, str]c             C  sì   t | ddƒ\}}| ¡ dkr.t dd|› ¡‚t| |ƒdkrLt dd| |¡‚|d7 }t| |dƒ\}}t| |dƒ yt 	| 
¡ ¡ ¡ }W n$ tjk
rª   t dd¡d	‚Y nX y| 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   ZAuthorizationZbasiczunsupported scheme: ú zexpected space after schemer
   z#expected base64-encoded credentialsNr)   z&expected username:password credentials)r<   Úlowerr   ZInvalidHeaderValuer2   r:   re   rf   Úbase64Z	b64decodeÚencodeÚdecodeÚbinasciiÚErrorÚsplitr+   )r/   Zschemer0   Úbasic_credentialsÚ	user_passÚusernameÚpasswordr-   r-   r.   r     s4    

)rq   rr   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   ri   Z	b64encoderj   rk   )rq   rr   rp   ro   r-   r-   r.   r   @  s    )>Z
__future__r   ri   rl   r*   ÚreÚtypingr   r   r   r   r   r   r	   Ú r   r   r   r   r   r   r   Ú__all__r   r   r2   Úcompiler3   r7   r9   r<   r>   r?   rA   rD   rF   rG   rM   rN   r   rO   rP   r   rS   rV   r   Zparse_extension_listrZ   r   Zbuild_extension_listr]   r   Zparse_subprotocol_listr   Zbuild_subprotocol_listr   r   rd   re   rf   r   r   r-   r-   r-   r.   Ú<module>   st   $ 




D$

	0