U
    ^~HjV'  ã                   @   sÒ   d dl Z d dlZd dlmZ d dl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 d d	lmZ d d
lmZ d dlmZ d dlmZ G dd„ dƒZG dd„ dƒZG dd„ dƒZdd„ ZdS )é    N)Úimport_module)Úsettings)ÚUpdateError)ÚSuspiciousOperation)Úparse_cookie)ÚSimpleCookie)Útimezone)Ú	force_str)Ú
LazyObject)Ú	http_date)Údatabase_sync_to_asyncc                	   @   s<   e Zd ZdZdd„ Zdd„ Zeddd„ƒZeddd„ƒZdS )ÚCookieMiddlewarezž
    Extracts cookies from HTTP or WebSocket-style scopes and adds them as a
    scope["cookies"] entry with the same format as Django's request.COOKIES.
    c                 C   s
   || _ d S ©N©Úinner©Úselfr   © r   ú5/tmp/pip-unpacked-wheel-a46u9ts2/channels/sessions.pyÚ__init__   s    zCookieMiddleware.__init__c                 Ã   s`   d|krt dƒ‚| dg ¡D ]"\}}|dkrt| d¡ƒ} qDqi }|  t||d�||¡I d H S )NÚheaderszCookieMiddleware was passed a scope that did not have a headers key (make sure it is only passed HTTP or WebSocket connections)s   cookieÚlatin1)Úcookies)Ú
ValueErrorÚgetr   Údecoder   Údict)r   ÚscopeÚreceiveÚsendÚnameÚvaluer   r   r   r   Ú__call__   s    ÿzCookieMiddleware.__call__Ú Nú/FÚlaxc                 C   sx  t |ƒ}tƒ }|||< |dk	rˆt|tjƒrzt |¡rBt |tj¡}|| ¡  }|tj	dd� }d}t
d|jd |j ƒ}q”||| d< nd|| d< |dk	rÄ||| d< |sÄtt ¡ | ƒ|| d< |dk	rØ||| d	< |dk	rì||| d
< |rüd|| d< |	�rd|| d< |
dk	�r:|
 ¡ dk�s.tdƒ‚|
|| d< | ¡ D ]0}| dg ¡ dt|jdd� ¡ dd�f¡ �qBdS )aY  
        Sets a cookie in the passed HTTP response message.

        ``expires`` can be:
        - a string in the correct format,
        - a naive ``datetime.datetime`` object in UTC,
        - an aware ``datetime.datetime`` object in any time zone.
        If it is a ``datetime.datetime`` object then ``max_age`` will be calculated.
        Né   )Úsecondsr   i€Q Úexpiresr#   zmax-ageÚpathÚdomainTÚsecureÚhttponly)Ústrictr%   Únonez1samesite must be either 'strict', 'lax' or 'none'Úsamesiter   s
   Set-Cookie)Úheaderzutf-8)Úencoding)r	   r   Ú
isinstanceÚdatetimer   Zis_awareZ
make_naiveÚutcÚutcnowÚ	timedeltaÚmaxÚdaysr'   r   ÚtimeÚlowerÚAssertionErrorÚvaluesÚ
setdefaultÚappendÚbytesÚoutputÚstrip)ÚclsÚmessageÚkeyr!   Úmax_ager(   r)   r*   r+   r,   r/   r   ÚdeltaÚcr   r   r   Ú
set_cookie.   sD    

üÿzCookieMiddleware.set_cookiec                 C   s   | j ||d||dd�S )z1
        Deletes a cookie in a response.
        r   zThu, 01-Jan-1970 00:00:00 GMT)rE   r)   r*   r(   )rH   )rB   rC   rD   r)   r*   r   r   r   Údelete_cookier   s    úzCookieMiddleware.delete_cookie)r#   NNr$   NFFr%   )r$   N)	Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r"   ÚclassmethodrH   rI   r   r   r   r   r      s           õCr   c                   @   s<   e Zd ZdZdgZdgZdd„ Zdd„ Zdd„ Zd	d
„ Z	dS )ÚInstanceSessionWrapperzf
    Populates the session in application instance scope, and wraps send to save
    the session.
    zhttp.response.startc                 C   s`   t j| _tt jƒj| _t|ƒ| _d| jkr2d| _	n$d| jkrDt
dƒ‚tƒ | jd< d| _	|| _d S )NÚsessionFr   zPNo cookies in scope - SessionMiddleware needs to run inside of CookieMiddleware.T)r   ÚSESSION_COOKIE_NAMEÚcookie_namer   ZSESSION_ENGINEZSessionStoreÚsession_storer   r   Ú	activatedr   r
   Ú	real_send)r   r   r   r   r   r   r   �   s    


ÿzInstanceSessionWrapper.__init__c                 Ã   s(   | j d  | j¡}|  |¡| j d _d S )Nr   rP   )r   r   rR   rS   Z_wrapped)r   Úsession_keyr   r   r   Úresolve_session¥   s    z&InstanceSessionWrapper.resolve_sessionc                 Ã   s"  | j �r| jd j}| jd  ¡ }|d | jk�r| dd¡dk�r|sPtj�r|  ¡ I dH  |d | j	k�r|rœtj
| jd krštj|tj
tjtjd� nv| jd  ¡ r´d}d}n"| jd  ¡ }t ¡ | }t|ƒ}tj|| j| jd j||tjtjtjpþdtj�pdtjd	�
 |  |¡I dH S )
zG
        Overridden send that also does session saves/cookies.
        rP   ÚtypeÚstatuséÈ   iô  Nr   )r)   r*   )rE   r(   r*   r)   r+   r,   r/   )rT   r   ÚmodifiedZis_emptyÚsave_message_typesr   r   ZSESSION_SAVE_EVERY_REQUESTÚsave_sessionÚcookie_response_message_typesrQ   r   rI   ZSESSION_COOKIE_PATHZSESSION_COOKIE_DOMAINZget_expire_at_browser_closeZget_expiry_ager9   r   rH   rR   rV   ZSESSION_COOKIE_SECUREZSESSION_COOKIE_HTTPONLYZSESSION_COOKIE_SAMESITErU   )r   rC   r[   ÚemptyrE   r(   Zexpires_timer   r   r   r   ©   sP    ÿþýýü

özInstanceSessionWrapper.sendc                 Ã   s^   z<t jdkr"| jd  ¡ I dH  nt| jd jƒƒ I dH  W n tk
rX   tdƒ‚Y nX dS )z,
        Saves the current session.
        )é   r&   rP   Nz‚The request's session was deleted before the request completed. The user may have logged out in a concurrent request, for example.)ÚdjangoÚVERSIONr   Zasaver   Úsaver   r   )r   r   r   r   r]   ß   s    
ÿz#InstanceSessionWrapper.save_sessionN)
rJ   rK   rL   rM   r\   r^   r   rW   r   r]   r   r   r   r   rO   �   s   6rO   c                   @   s    e Zd ZdZdd„ Zdd„ ZdS )ÚSessionMiddlewarezü
    Class that adds Django sessions (from HTTP cookies) to the
    scope. Works with HTTP or WebSocket protocol types (or anything that
    provides a "headers" entry in the scope).

    Requires the CookieMiddleware to be higher up in the stack.
    c                 C   s
   || _ d S r   r   r   r   r   r   r   ù   s    zSessionMiddleware.__init__c                 Ã   s0   t ||ƒ}| ¡ I dH  |  |j||j¡I dH S )z{
        Instantiate a session wrapper for this scope, resolve the session and
        call the inner application.
        N)rO   rW   r   r   r   )r   r   r   r   Úwrapperr   r   r   r"   ü   s    
zSessionMiddleware.__call__N)rJ   rK   rL   rM   r   r"   r   r   r   r   rd   ð   s   rd   c                 C   s   t t| ƒƒS r   )r   rd   r   r   r   r   ÚSessionMiddlewareStack	  s    rf   )r3   r9   Ú	importlibr   ra   Zdjango.confr   Z%django.contrib.sessions.backends.baser   Zdjango.core.exceptionsr   Zdjango.httpr   Zdjango.http.cookier   Zdjango.utilsr   Zdjango.utils.encodingr	   Zdjango.utils.functionalr
   Zdjango.utils.httpr   Zchannels.dbr   r   rO   rd   rf   r   r   r   r   Ú<module>   s"   no