B
    ‹æ@\Ž  ã               @   sb   d Z ddlmZmZmZmZ ddlZe e¡Z	ddl
mZ dZdd„ Zdd	„ Zd
d„ Zdd„ ZdS )zc Provide some utility functions useful for implementing different
components in ``bokeh.server``.

é    )Úabsolute_importÚdivisionÚprint_functionÚunicode_literalsN)Únetutil)Úbind_socketsÚcheck_whitelistÚcreate_hosts_whitelistÚ
match_hostc             C   s`   t j|p
d| d}t|ƒst‚dd„ |D ƒ}t|ƒdks@tdƒ‚| ¡ }|rX||ksXt‚||fS )aô   Bind a socket to a port on an address.

    Args:
        address (str) :
            An address to bind a port on, e.g. ``"localhost"``

        port (int) :
            A port number to bind.

            Pass 0 to have the OS automatically choose a free port.

    This function returns a 2-tuple with the new socket as the first element,
    and the port that was bound as the second. (Useful when passing 0 as a port
    number to bind any free port.)

    Returns:
        (socket, port)

    r   )ÚportÚaddressc             S   s   h | ]}|  ¡ d  ’qS )é   )Zgetsockname)Ú.0Ús© r   ú0lib/python3.7/site-packages/bokeh/server/util.pyú	<setcomp>D   s    zbind_sockets.<locals>.<setcomp>r   zMultiple ports assigned??)r   r   ÚlenÚAssertionErrorÚpop)r   r   ZssZportsZactual_portr   r   r   r   .   s    r   c                s2   dˆ krˆ d ‰ ˆ |krdS t ‡ fdd„|D ƒƒS )a¸   Check a given request host against a whitelist.

    Args:
        host (str) :
            A host string to compare against a whitelist.

            If the host does not specify a port, then ``":80"`` is implicitly
            assumed.

        whitelist (seq[str]) :
            A list of host patterns to match against

    Returns:
        ``True``, if ``host`` matches any pattern in ``whitelist``, otherwise
        ``False``

     ú:z:80Tc             3   s   | ]}t ˆ |ƒV  qd S )N)r
   )r   Úpattern)Úhostr   r   ú	<genexpr>c   s    z"check_whitelist.<locals>.<genexpr>)Úany)r   Z	whitelistr   )r   r   r   K   s
    r   c          	   C   sô   | sdt |ƒ gS g }xØ| D ]Ð}d|kr4t d|¡ |dkrH| |¡ q| d¡}t|ƒdkr‚|d dkrrtdƒ‚| |d	 ¡ qt|ƒd
kràyt|d ƒ W n  tk
r¾   td| ƒ‚Y nX |d dkrÔtdƒ‚| |¡ qtd| ƒ‚qW |S )an  

    This whitelist can be used to restrict websocket or other connections to
    only those explicitly originating from approved hosts.

    Args:
        host_list (seq[str]) :
            A list of string `<name>` or `<name>:<port>` values to add to the
            whitelist.

            If no port is specified in a host string, then ``":80"``  is
            implicitly assumed.

        port (int) :
            If ``host_list`` is empty or ``None``, then the whitelist will
            be the single item list `` [ 'localhost:<port>' ]``

            If ``host_list`` is not empty, this parameter has no effect.

    Returns:
        list[str]

    Raises:
        ValueError, if host or port values are invalid

    Note:
        If any host in ``host_list`` contains a wildcard ``*`` a warning will
        be logged regarding permissive websocket connections.

    z
localhost:Ú*z›Host wildcard %r will allow connections originating from multiple (or possibly all) hostnames or IPs. Use non-wildcard values to restrict access explicitlyr   r   r   Ú zEmpty host valuez:80é   zInvalid port in host value: %szInvalid host value: %s)ÚstrÚlogZwarningÚappendÚsplitr   Ú
ValueErrorÚint)Z	host_listr   Zhostsr   Úpartsr   r   r   r	   e   s4    


r	   c             C   s¸   d| kr|   dd¡\} }nd}d|krD|  dd¡\}}|dkrHd}nd}|dk	r\||kr\dS |  d¡} | d¡}t|ƒt| ƒkr„dS x.t| |ƒD ] \}}||ks|dkr¬qqdS qW dS )aa   Match a host string against a pattern

    Args:
        host (str)
            A hostname to compare to the given pattern

        pattern (str)
            A string representing a hostname pattern, possibly including
            wildcards for ip address octets or ports.

    This function will return ``True`` if the hostname matches the pattern,
    including any wildcards. If the pattern contains a port, the host string
    must also contain a matching port.

    Returns:
        bool

    Examples:

        >>> match_host('192.168.0.1:80', '192.168.0.1:80')
        True
        >>> match_host('192.168.0.1:80', '192.168.0.1')
        True
        >>> match_host('192.168.0.1:80', '192.168.0.1:8080')
        False
        >>> match_host('192.168.0.1', '192.168.0.2')
        False
        >>> match_host('192.168.0.1', '192.168.*.*')
        True
        >>> match_host('alice', 'alice')
        True
        >>> match_host('alice:80', 'alice')
        True
        >>> match_host('alice', 'bob')
        False
        >>> match_host('foo.example.com', 'foo.example.com.net')
        False
        >>> match_host('alice', '*')
        True
        >>> match_host('alice', '*:*')
        True
        >>> match_host('alice:80', '*')
        True
        >>> match_host('alice:80', '*:80')
        True
        >>> match_host('alice:8080', '*:80')
        False

    r   r   Nr   FÚ.T)Úrsplitr!   r   Úzip)r   r   Z	host_portZpattern_portÚhÚpr   r   r   r
   ¤   s&    2

r
   )Ú__doc__Z
__future__r   r   r   r   ZloggingZ	getLoggerÚ__name__r   Ztornador   Ú__all__r   r   r	   r
   r   r   r   r   Ú<module>
   s   
		
?