3
š(ƒh”  ã               @   s,  d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m
Z
 ddlmZ ddlmZmZ ddlmZmZmZ ddlmZ ejd	ƒZG d
d„ deƒZG dd„ deƒZdd„ Zdd„ Zdd„ Zd#dd„ZG dd„ deƒZ dde dfdd„Z!dde dfdd„Z"G dd „ d eƒZ#G d!d"„ d"e#ƒZ$dS )$a`  
Functions for creating and restoring url-safe signed JSON objects.

The format used looks like this:

>>> signing.dumps("hello")
'ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk'

There are two components here, separated by a ':'. The first component is a
URLsafe base64 encoded JSON of the object passed to dumps(). The second
component is a base64 encoded hmac/SHA1 hash of "$first_component:$secret"

signing.loads(s) checks the signature and returns the deserialized object.
If the signature fails, a BadSignature exception is raised.

>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk")
u'hello'
>>> signing.loads("ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk-modified")
...
BadSignature: Signature failed: ImhlbGxvIg:1QaUZC:YIye-ze3TTx7gtSv422nZA4sgmk-modified

You can optionally compress the JSON prior to base64 encoding it to save
space, using the compress=True argument. This checks if compression actually
helps and only applies compression if the result is a shorter string:

>>> signing.dumps(range(1, 20), compress=True)
'.eJwFwcERACAIwLCF-rCiILN47r-GyZVJsNgkxaFxoDgxcOHGxMKD_T7vhAml:1QaUaL:BA0thEZrp4FQVXIXuOvYJtLJSrQ'

The fact that the string is compressed is signalled by the prefixed '.' at the
start of the base64 JSON.

There are 65 url-safe characters: the 64 used by url-safe base64 and the ':'.
These functions make use of all of them.
é    )Úunicode_literalsN)Úsettings)Úbaseconv)Úconstant_time_compareÚsalted_hmac)Úforce_bytesÚ	force_strÚ
force_text)Úimport_stringz^[A-z0-9-_=]*$c               @   s   e Zd ZdZdS )ÚBadSignaturez"
    Signature does not match
    N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   ú7/tmp/pip-install-q3hcpn_q/Django/django/core/signing.pyr   6   s   r   c               @   s   e Zd ZdZdS )ÚSignatureExpiredz<
    Signature timestamp is older than required max_age
    N)r   r   r   r   r   r   r   r   r   =   s   r   c             C   s   t j| ƒjdƒS )Nó   =)Úbase64Úurlsafe_b64encodeÚstrip)Úsr   r   r   Ú
b64_encodeD   s    r   c             C   s    dt | ƒ d  }tj| | ƒS )Nr   é   )Úlenr   Úurlsafe_b64decode)r   Úpadr   r   r   Ú
b64_decodeH   s    r   c             C   s   t t| ||ƒjƒ ƒS )N)r   r   Údigest)ÚsaltÚvalueÚkeyr   r   r   Úbase64_hmacM   s    r"   ú%django.core.signing.get_cookie_signerc             C   s$   t tjƒ}ttjƒ}|d| | dS )Ns   django.http.cookies)r   )r
   r   ZSIGNING_BACKENDr   Ú
SECRET_KEY)r   ÚSignerr!   r   r   r   Úget_cookie_signerQ   s    

r&   c               @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚJSONSerializerzW
    Simple wrapper around json to be used in signing.dumps and
    signing.loads.
    c             C   s   t j|ddjdƒS )Nú,ú:)Ú
separatorszlatin-1)r(   r)   )ÚjsonÚdumpsÚencode)ÚselfÚobjr   r   r   r,   \   s    zJSONSerializer.dumpsc             C   s   t j|jdƒƒS )Nzlatin-1)r+   ÚloadsÚdecode)r.   Údatar   r   r   r0   _   s    zJSONSerializer.loadsN)r   r   r   r   r,   r0   r   r   r   r   r'   W   s   r'   zdjango.core.signingFc       	      C   s`   |ƒ j | ƒ}d}|r:tj|ƒ}t|ƒt|ƒd k r:|}d}t|ƒ}|rNd| }t||dj|ƒS )a‹  
    Returns URL-safe, sha1 signed base64 compressed JSON string. If key is
    None, settings.SECRET_KEY is used instead.

    If compress is True (not the default) checks if compressing using zlib can
    save some space. Prepends a '.' to signify compression. This is included
    in the signature, to protect against zip bombs.

    Salt can be used to namespace the hash, so that a signed string is
    only valid for a given namespace. Leaving this at the default
    value or re-using a salt value across different parts of your
    application without good cause is a security risk.

    The serializer is expected to return a bytestring.
    Fé   Tó   .)r   )r,   ÚzlibÚcompressr   r   ÚTimestampSignerÚsign)	r/   r!   r   Ú
serializerr6   r2   Zis_compressedÚ
compressedÚbase64dr   r   r   r,   c   s    
r,   c             C   s`   t t||dj| |dƒ}d}|dd… dkr>|dd… }d}t|ƒ}|rTtj|ƒ}|ƒ j|ƒS )z}
    Reverse of dumps(), raises BadSignature if signature fails.

    The serializer is expected to accept a bytestring.
    )r   )Úmax_ageFNr3   r4   T)r   r7   Úunsignr   r5   Ú
decompressr0   )r   r!   r   r9   r<   r;   r>   r2   r   r   r   r0   „   s    
r0   c               @   s.   e Zd Zddd„Zdd„ Zdd„ Zd	d
„ ZdS )r%   Nr)   c             C   sP   |pt j| _t|ƒ| _tj| jƒr.td| ƒ‚t|pFd| jj	| jj
f ƒ| _d S )NzJUnsafe Signer separator: %r (cannot be empty or consist of only A-z0-9-_=)z%s.%s)r   r$   r!   r   ÚsepÚ_SEP_UNSAFEÚmatchÚ
ValueErrorÚ	__class__r   r   r   )r.   r!   r?   r   r   r   r   Ú__init__š   s    
zSigner.__init__c             C   s   t | jd || jƒ}t|ƒS )NZsigner)r"   r   r!   r   )r.   r    Ú	signaturer   r   r   rE   ¥   s    zSigner.signaturec             C   s"   t |ƒ}tdƒ|| j| j|ƒf S )Nz%s%s%s)r   Ústrr?   rE   )r.   r    r   r   r   r8   ª   s    zSigner.signc             C   sZ   t |ƒ}| j|kr td| j ƒ‚|j| jdƒ\}}t|| j|ƒƒrJt|ƒS td| ƒ‚d S )NzNo "%s" found in valuer3   zSignature "%s" does not match)r   r?   r   Úrsplitr   rE   r	   )r.   Zsigned_valuer    Úsigr   r   r   r=   ®   s    
zSigner.unsign)Nr)   N)r   r   r   rD   rE   r8   r=   r   r   r   r   r%   ˜   s   
r%   c                   s2   e Zd Zdd„ Z‡ fdd„Zd‡ fdd„	Z‡  ZS )	r7   c             C   s   t jjttjƒ ƒƒS )N)r   Úbase62r-   ÚintÚtime)r.   r   r   r   Ú	timestampº   s    zTimestampSigner.timestampc                s0   t |ƒ}tdƒ|| j| jƒ f }tt| ƒj|ƒS )Nz%s%s%s)r   rF   r?   rL   Úsuperr7   r8   )r.   r    )rC   r   r   r8   ½   s    zTimestampSigner.signNc                sr   t t| ƒj|ƒ}|j| jdƒ\}}tjj|ƒ}|dk	rnt|t	j
ƒrJ|jƒ }tjƒ | }||krntd||f ƒ‚|S )zk
        Retrieve original value and check it wasn't signed more
        than max_age seconds ago.
        r3   NzSignature age %s > %s seconds)rM   r7   r=   rG   r?   r   rI   r1   Ú
isinstanceÚdatetimeÚ	timedeltaÚtotal_secondsrK   r   )r.   r    r<   ÚresultrL   Zage)rC   r   r   r=   Â   s    zTimestampSigner.unsign)N)r   r   r   rL   r8   r=   Ú__classcell__r   r   )rC   r   r7   ¸   s   r7   )r#   )%r   Ú
__future__r   r   rO   r+   ÚrerK   r5   Zdjango.confr   Zdjango.utilsr   Zdjango.utils.cryptor   r   Zdjango.utils.encodingr   r   r	   Zdjango.utils.module_loadingr
   Úcompiler@   Ú	Exceptionr   r   r   r   r"   r&   Úobjectr'   r,   r0   r%   r7   r   r   r   r   Ú<module>"   s0   

! 