U
    8ÄT_L6  ã                   @   sâ   d dl Z d dlZd dlZd dlZd dlmZmZ d dlmZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZmZmZ d d	lmZ d d
lmZ d dlmZ ejej ZG dd„ deƒZG dd„ deƒZG dd„ dƒZ dS )é    N)ÚdatetimeÚ	timedelta)Úsettings)ÚSuspiciousSession)Úsigning)ÚSuspiciousOperation)Útimezone)Úconstant_time_compareÚget_random_stringÚsalted_hmac)ÚRemovedInDjango40Warning)Úimport_string)ÚLANGUAGE_SESSION_KEYc                   @   s   e Zd ZdZdS )ÚCreateErrorz‡
    Used internally as a consistent exception type to catch from save (see the
    docstring for SessionBase.save() for details).
    N©Ú__name__Ú
__module__Ú__qualname__Ú__doc__© r   r   úI/tmp/pip-unpacked-wheel-dv63caxw/django/contrib/sessions/backends/base.pyr      s   r   c                   @   s   e Zd ZdZdS )ÚUpdateErrorzF
    Occurs if Django tries to update a session that was deleted.
    Nr   r   r   r   r   r       s   r   c                   @   s¦  e Zd ZdZdZdZeƒ Zd\dd„Zdd„ Z	d	d
„ Z
dd„ Zdd„ Zedd„ ƒZd]dd„Zefdd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd%d&„ Zd'd(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd/d0„ Zd1d2„ Zd3d4„ Z d5d6„ Z!d7d8„ Z"d9d:„ Z#d;d<„ Z$d=d>„ Z%ee$ƒZ&ee$e%ƒZ'd^d@dA„Z(ee(ƒZ)dBdC„ Z*dDdE„ Z+dFdG„ Z,dHdI„ Z-dJdK„ Z.dLdM„ Z/dNdO„ Z0dPdQ„ Z1dRdS„ Z2d_dTdU„Z3d`dVdW„Z4dXdY„ Z5e6dZd[„ ƒZ7dS )aÚSessionBasez-
    Base class for all Session classes.
    Z
testcookieZworkedNc                 C   s"   || _ d| _d| _ttjƒ| _d S )NF)Ú_session_keyÚaccessedÚmodifiedr   r   ZSESSION_SERIALIZERÚ
serializer©ÚselfÚsession_keyr   r   r   Ú__init__0   s    zSessionBase.__init__c                 C   s
   || j kS ©N©Ú_session©r   Úkeyr   r   r   Ú__contains__6   s    zSessionBase.__contains__c                 C   s"   |t krtjdtdd� | j| S )Nz‘The user language will no longer be stored in request.session in Django 4.0. Read it from request.COOKIES[settings.LANGUAGE_COOKIE_NAME] instead.é   )Ú
stacklevel)r   ÚwarningsÚwarnr   r#   r$   r   r   r   Ú__getitem__9   s     üzSessionBase.__getitem__c                 C   s   || j |< d| _d S ©NT©r#   r   ©r   r%   Úvaluer   r   r   Ú__setitem__C   s    
zSessionBase.__setitem__c                 C   s   | j |= d| _d S r,   r-   r$   r   r   r   Ú__delitem__G   s    zSessionBase.__delitem__c                 C   s   d| j j S )Nzdjango.contrib.sessions.)Ú	__class__r   ©r   r   r   r   Úkey_saltK   s    zSessionBase.key_saltc                 C   s   | j  ||¡S r!   )r#   Úget)r   r%   Údefaultr   r   r   r5   O   s    zSessionBase.getc                 C   s8   | j p|| jk| _ || jkr dn|f}| jj|f|žŽ S )Nr   )r   r#   Ú_SessionBase__not_givenÚpop)r   r%   r6   Úargsr   r   r   r8   R   s    zSessionBase.popc                 C   s,   || j kr| j | S d| _|| j |< |S d S r,   r-   r.   r   r   r   Ú
setdefaultW   s
    


zSessionBase.setdefaultc                 C   s   | j | | j< d S r!   )ÚTEST_COOKIE_VALUEÚTEST_COOKIE_NAMEr3   r   r   r   Úset_test_cookie_   s    zSessionBase.set_test_cookiec                 C   s   |   | j¡| jkS r!   )r5   r<   r;   r3   r   r   r   Útest_cookie_workedb   s    zSessionBase.test_cookie_workedc                 C   s   | | j = d S r!   )r<   r3   r   r   r   Údelete_test_cookiee   s    zSessionBase.delete_test_cookiec                 C   s   d| j j }t||ƒ ¡ S )Nzdjango.contrib.sessions)r2   r   r   Ú	hexdigest)r   r/   r4   r   r   r   Ú_hashh   s    zSessionBase._hashc                 C   s*   t jdkr|  |¡S tj|| j| jdd�S )zGReturn the given session dictionary serialized and encoded as a string.Úsha1T)Úsaltr   Úcompress)r   ZDEFAULT_HASHING_ALGORITHMÚ_legacy_encoder   Údumpsr4   r   )r   Úsession_dictr   r   r   Úencodem   s    

  þzSessionBase.encodec                 C   s�   zt j|| j| jd�W S  t jk
rn   z|  |¡W  Y S  tk
rh   t d¡}| 	d¡ i  Y  Y S X Y n tk
rŠ   |  |¡ Y S X d S )N)rC   r   z!django.security.SuspiciousSessionúSession data corrupted)
r   Úloadsr4   r   ZBadSignatureÚ_legacy_decodeÚ	ExceptionÚloggingÚ	getLoggerÚwarning)r   Úsession_dataÚloggerr   r   r   Údecodew   s    

zSessionBase.decodec                 C   s4   |   ¡  |¡}|  |¡}t | ¡ d | ¡ d¡S )Nó   :Úascii)r   rF   rA   Úbase64Ú	b64encoderH   rR   )r   rG   Ú
serializedÚhashr   r   r   rE   ˆ   s    
zSessionBase._legacy_encodec              
   C   s°   t  | d¡¡}zF| dd¡\}}|  |¡}t| ¡ |ƒsDtdƒ‚n|  ¡  	|¡W S W nT t
k
rª } z6t|tƒr’t d|jj ¡}| t|ƒ¡ i  W Y ¢S d }~X Y nX d S )NrT   rS   é   rI   zdjango.security.%s)rU   Ú	b64decoderH   ÚsplitrA   r	   rR   r   r   rJ   rL   Ú
isinstancer   rM   rN   r2   r   rO   Ústr)r   rP   Zencoded_datarX   rW   Zexpected_hashÚerQ   r   r   r   rK   Ž   s    


zSessionBase._legacy_decodec                 C   s   | j  |¡ d| _d S r,   )r#   Úupdater   )r   Zdict_r   r   r   r_   ¡   s    zSessionBase.updatec                 C   s
   || j kS r!   r"   r$   r   r   r   Úhas_key¥   s    zSessionBase.has_keyc                 C   s
   | j  ¡ S r!   )r#   Úkeysr3   r   r   r   ra   ¨   s    zSessionBase.keysc                 C   s
   | j  ¡ S r!   )r#   Úvaluesr3   r   r   r   rb   «   s    zSessionBase.valuesc                 C   s
   | j  ¡ S r!   )r#   Úitemsr3   r   r   r   rc   ®   s    zSessionBase.itemsc                 C   s   i | _ d| _d| _d S r,   )Ú_session_cacher   r   r3   r   r   r   Úclear±   s    zSessionBase.clearc                 C   s.   z| j  o| j W S  tk
r(   Y dS X dS )zBReturn True when there is no session_key and the session is empty.TN)r   rd   ÚAttributeErrorr3   r   r   r   Úis_empty¹   s    zSessionBase.is_emptyc                 C   s   t dtƒ}|  |¡s |S q dS )z)Return session key that isn't being used.é    N)r
   ÚVALID_KEY_CHARSÚexistsr   r   r   r   Ú_get_new_session_keyÀ   s    

z SessionBase._get_new_session_keyc                 C   s   | j d kr|  ¡ | _ | j S r!   )r   rk   r3   r   r   r   Ú_get_or_create_session_keyÇ   s    

z&SessionBase._get_or_create_session_keyc                 C   s   |ot |ƒdkS )z”
        Key must be truthy and at least 8 characters long. 8 characters is an
        arbitrary lower bound for some minimal key security.
        é   )Úlenr$   r   r   r   Ú_validate_session_keyÌ   s    z!SessionBase._validate_session_keyc                 C   s   | j S r!   )Ú_SessionBase__session_keyr3   r   r   r   Ú_get_session_keyÓ   s    zSessionBase._get_session_keyc                 C   s   |   |¡r|| _nd| _dS )zV
        Validate session key on assignment. Invalid values will set to None.
        N)ro   rp   ©r   r/   r   r   r   Ú_set_session_keyÖ   s    
zSessionBase._set_session_keyFc                 C   sJ   d| _ z| jW S  tk
rB   | jdks,|r4i | _n
|  ¡ | _Y nX | jS )zž
        Lazily load session from storage (unless "no_load" is True, when only
        an empty dict is stored) and store it in the current instance.
        TN)r   rd   rf   r   Úload)r   Zno_loadr   r   r   Ú_get_sessionâ   s    zSessionBase._get_sessionc                 C   s   t jS r!   )r   ZSESSION_COOKIE_AGEr3   r   r   r   Úget_session_cookie_ageó   s    z"SessionBase.get_session_cookie_agec                 K   sˆ   z|d }W n t k
r(   t ¡ }Y nX z|d }W n t k
rT   |  d¡}Y nX |sb|  ¡ S t|tƒsp|S || }|jd |j S )zÕGet the number of seconds until the session expires.

        Optionally, this function accepts `modification` and `expiry` keyword
        arguments specifying the modification and expiry of the session.
        ÚmodificationÚexpiryÚ_session_expiryi€Q )	ÚKeyErrorr   Únowr5   rv   r\   r   ÚdaysÚseconds)r   Úkwargsrw   rx   Údeltar   r   r   Úget_expiry_ageö   s    
zSessionBase.get_expiry_agec                 K   s~   z|d }W n t k
r(   t ¡ }Y nX z|d }W n t k
rT   |  d¡}Y nX t|tƒrd|S |pn|  ¡ }|t|d� S )zÔGet session the expiry date (as a datetime object).

        Optionally, this function accepts `modification` and `expiry` keyword
        arguments specifying the modification and expiry of the session.
        rw   rx   ry   )r}   )rz   r   r{   r5   r\   r   rv   r   )r   r~   rw   rx   r   r   r   Úget_expiry_date  s    
zSessionBase.get_expiry_datec                 C   sN   |dkr,z
| d= W n t k
r&   Y nX dS t|tƒrBt ¡ | }|| d< dS )a*  
        Set a custom expiration for the session. ``value`` can be an integer,
        a Python ``datetime`` or ``timedelta`` object or ``None``.

        If ``value`` is an integer, the session will expire after that many
        seconds of inactivity. If set to ``0`` then the session will expire on
        browser close.

        If ``value`` is a ``datetime`` or ``timedelta`` object, the session
        will expire at that specific future time.

        If ``value`` is ``None``, the session uses the global session expiry
        policy.
        Nry   )rz   r\   r   r   r{   rr   r   r   r   Ú
set_expiry$  s    

zSessionBase.set_expiryc                 C   s"   |   d¡dkrtjS |   d¡dkS )a  
        Return ``True`` if the session is set to expire when the browser
        closes, and ``False`` if there's an expiry date. Use
        ``get_expiry_date()`` or ``get_expiry_age()`` to find the actual expiry
        date/age, if there is one.
        ry   Nr   )r5   r   ZSESSION_EXPIRE_AT_BROWSER_CLOSEr3   r   r   r   Úget_expire_at_browser_close>  s    z'SessionBase.get_expire_at_browser_closec                 C   s   |   ¡  |  ¡  d| _dS )zc
        Remove the current session data from the database and regenerate the
        key.
        N)re   Údeleter   r3   r   r   r   ÚflushI  s    zSessionBase.flushc                 C   s,   | j }| j}|  ¡  || _|r(|  |¡ dS )zU
        Create a new session key, while retaining the current session data.
        N)r#   r   Úcreaterd   r„   )r   Údatar%   r   r   r   Ú	cycle_keyR  s    zSessionBase.cycle_keyc                 C   s   t dƒ‚dS )zF
        Return True if the given session_key already exists.
        z9subclasses of SessionBase must provide an exists() methodN©ÚNotImplementedErrorr   r   r   r   rj   _  s    zSessionBase.existsc                 C   s   t dƒ‚dS )zÅ
        Create a new session instance. Guaranteed to create a new object with
        a unique key and will have saved the result once (with empty data)
        before the method returns.
        z8subclasses of SessionBase must provide a create() methodNr‰   r3   r   r   r   r†   e  s    zSessionBase.createc                 C   s   t dƒ‚dS )zä
        Save the session data. If 'must_create' is True, create a new session
        object (or raise CreateError). Otherwise, only update an existing
        object and don't create one (raise UpdateError if needed).
        z6subclasses of SessionBase must provide a save() methodNr‰   )r   Zmust_creater   r   r   Úsavem  s    zSessionBase.savec                 C   s   t dƒ‚dS )zx
        Delete the session data under this key. If the key is None, use the
        current session key value.
        z8subclasses of SessionBase must provide a delete() methodNr‰   r   r   r   r   r„   u  s    zSessionBase.deletec                 C   s   t dƒ‚dS )z@
        Load the session data and return a dictionary.
        z6subclasses of SessionBase must provide a load() methodNr‰   r3   r   r   r   rt   |  s    zSessionBase.loadc                 C   s   t dƒ‚dS )a  
        Remove expired sessions from the session store.

        If this operation isn't possible on a given backend, it should raise
        NotImplementedError. If it isn't necessary, because the backend has
        a built-in expiration mechanism, it should be a no-op.
        z.This backend does not support clear_expired().Nr‰   )Úclsr   r   r   Úclear_expired‚  s    	zSessionBase.clear_expired)N)N)F)F)N)8r   r   r   r   r<   r;   Úobjectr7   r    r&   r+   r0   r1   Úpropertyr4   r5   r8   r:   r=   r>   r?   rA   rH   rR   rE   rK   r_   r`   ra   rb   rc   re   rg   rk   rl   ro   rq   rs   r   r   ru   r#   rv   r€   r�   r‚   rƒ   r…   rˆ   rj   r†   r‹   r„   rt   Úclassmethodr�   r   r   r   r   r   '   sh   




	

	

r   )!rU   rM   Ústringr)   r   r   Zdjango.confr   Z"django.contrib.sessions.exceptionsr   Zdjango.corer   Zdjango.core.exceptionsr   Zdjango.utilsr   Zdjango.utils.cryptor	   r
   r   Zdjango.utils.deprecationr   Zdjango.utils.module_loadingr   Zdjango.utils.translationr   Úascii_lowercaseÚdigitsri   rL   r   r   r   r   r   r   r   Ú<module>   s"   