U
    k7g                     @   s\   d dl Z d dlZd dlmZmZ d dlmZmZ dd Zdd Z	dd	 Z
G d
d deZdS )    N)sha1sha256)urlparseparse_qsc                 C   s<   t | t |krdS d}t| |D ]\}}|||kM }q"|S )zCompare two strings while protecting against timing attacks

    :param str string1: the first string
    :param str string2: the second string

    :returns: True if the strings are equal, False if not
    :rtype: :obj:`bool`
    FT)lenzip)Zstring1Zstring2resultZc1c2 r
   </tmp/pip-unpacked-wheel-qtbjxrb6/twilio/request_validator.pycompare   s    	r   c                 C   s2   | j s|  S | jdd }| j|d}| S )zRemove the port number from a URI

    :param uri: parsed URI that Twilio requested on your server

    :returns: full URI without a port number
    :rtype: str
    :r   netloc)portgeturlr   split_replace)uri
new_netlocnew_urir
   r
   r   remove_port   s
    r   c                 C   sF   | j r|  S | jdkrdnd}| jd t| }| j|d}| S )zAdd the port number to a URI

    :param uri: parsed URI that Twilio requested on your server

    :returns: full URI with a port number
    :rtype: str
    httpsi  P   r   r   )r   r   schemer   strr   )r   r   r   r   r
   r
   r   add_port+   s    r   c                   @   s4   e Zd Zdd Zdd Zdd Zdd Zd	d
 ZdS )RequestValidatorc                 C   s   | d| _d S Nutf-8)encodetoken)selfr!   r
   r
   r   __init__>   s    zRequestValidator.__init__c           	      C   sz   |}|rDt t|D ].}| ||}t t|D ]}||| 7 }q0qt| j|dt}t	|
 }|d}| S )zCompute the signature for a given request

        :param uri: full URI that Twilio requested on your server
        :param params: post vars that Twilio sent with the request

        :returns: The computed signature
        r   )sortedset
get_valueshmacnewr!   r    r   base64	b64encodedigestdecodestrip)	r"   r   paramss
param_namevaluesvaluemaccomputedr
   r
   r   compute_signatureA   s    
z"RequestValidator.compute_signaturec                 C   sZ   z| |W S  tk
rT   z||W  Y S  tk
rN   || g Y  Y S X Y nX d S )N)ZgetallAttributeErrorgetlist)r"   Z
param_dictr0   r
   r
   r   r&   X   s    zRequestValidator.get_valuesc                 C   s   t |d }| S r   )r   r    	hexdigestr-   )r"   bodyr4   r
   r
   r   compute_hashd   s    zRequestValidator.compute_hashc                 C   s   |dkri }t |}t|}t|}d}t|j}d|kr`t|tr`t| ||d d }i }t| 	|||}	t| 	|||}
|o|	p|
S )a]  Validate a request from Twilio

        :param uri: full URI that Twilio requested on your server
        :param params: dictionary of POST variables or string of POST body for JSON requests
        :param signature: expected signature in HTTP X-Twilio-Signature header

        :returns: True if the request passes validation, False if not
        NTZ
bodySHA256r   )
r   r   r   r   query
isinstancer   r   r:   r5   )r"   r   r.   	signatureZ
parsed_uriZuri_with_portZuri_without_portZvalid_body_hashr;   Zvalid_signatureZvalid_signature_with_portr
   r
   r   validatei   s&    	

 
 zRequestValidator.validateN)__name__
__module____qualname__r#   r5   r&   r:   r>   r
   r
   r
   r   r   =   s
   r   )r)   r'   hashlibr   r   urllib.parser   r   r   r   r   objectr   r
   r
   r
   r   <module>   s   