o
    ‹åg»'  ã                   @   s  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 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Ze e¡Zddd„Zd dd„Z	d!dd„ZG dd„ deƒZG dd„ dƒZG dd„ deƒZdd„ Z dS )"é    N)Úurlparse)Ú	Blueprint)Úcurrent_app)Úg)Úrequest)Úsession)ÚBadData)ÚSignatureExpired)ÚURLSafeTimedSerializer)Ú
BadRequest)ÚValidationError)ÚCSRF)Úgenerate_csrfÚvalidate_csrfÚCSRFProtectc                 C   s¸   t | dtjdd�} t |dddd�}|tvrWt| dd�}|tvr+t t 	d	¡¡ 
¡ t|< z	| t| ¡}W n tyP   t t 	d	¡¡ 
¡ t|< | t| ¡}Y nw tt||ƒ t |¡S )
a  Generate a CSRF token. The token is cached for a request, so multiple
    calls to this function will generate the same token.

    During testing, it might be useful to access the signed token in
    ``g.csrf_token`` and the raw token in ``session['csrf_token']``.

    :param secret_key: Used to securely sign the token. Default is
        ``WTF_CSRF_SECRET_KEY`` or ``SECRET_KEY``.
    :param token_key: Key where token is stored in session for comparison.
        Default is ``WTF_CSRF_FIELD_NAME`` or ``'csrf_token'``.
    ÚWTF_CSRF_SECRET_KEYú%A secret key is required to use CSRF.©ÚmessageÚWTF_CSRF_FIELD_NAMEÚ
csrf_tokenú%A field name is required to use CSRF.úwtf-csrf-token©Úsalté@   )Ú_get_configr   Ú
secret_keyr   r
   r   ÚhashlibÚsha1ÚosÚurandomÚ	hexdigestÚdumpsÚ	TypeErrorÚsetattrÚget)r   Ú	token_keyÚ
field_nameÚsÚtoken© r+   úJ/var/www/html/flaskapp/venv/lib/python3.10/site-packages/flask_wtf/csrf.pyr      s0   üüþ
r   c              
   C   sÌ   t |dtjdd�}t |dddd�}t |ddd	d
�}| stdƒ‚|tvr'tdƒ‚t|dd�}z	|j| |d�}W n! tyG } ztdƒ|‚d}~w tyW } ztdƒ|‚d}~ww t	 
t| |¡sdtdƒ‚dS )a  Check if the given data is a valid CSRF token. This compares the given
    signed token to the one stored in the session.

    :param data: The signed CSRF token to be checked.
    :param secret_key: Used to securely sign the token. Default is
        ``WTF_CSRF_SECRET_KEY`` or ``SECRET_KEY``.
    :param time_limit: Number of seconds that the token is valid. Default is
        ``WTF_CSRF_TIME_LIMIT`` or 3600 seconds (60 minutes).
    :param token_key: Key where token is stored in session for comparison.
        Default is ``WTF_CSRF_FIELD_NAME`` or ``'csrf_token'``.

    :raises ValidationError: Contains the reason that validation failed.

    .. versionchanged:: 0.14
        Raises ``ValidationError`` with a specific error message rather than
        returning ``True`` or ``False``.
    r   r   r   r   r   r   ÚWTF_CSRF_TIME_LIMITé  F)ÚrequiredzThe CSRF token is missing.z"The CSRF session token is missing.r   r   )Úmax_agezThe CSRF token has expired.NzThe CSRF token is invalid.zThe CSRF tokens do not match.)r   r   r   r   r   r
   Úloadsr	   r   ÚhmacÚcompare_digest)Údatar   Ú
time_limitr'   r(   r)   r*   Úer+   r+   r,   r   B   s<   üü
€
€ÿÿr   TúCSRF is not configured.c                 C   s.   | du rt j ||¡} |r| du rt|ƒ‚| S )a¦  Find config value based on provided value, Flask config, and default
    value.

    :param value: already provided config value
    :param config_name: Flask ``config`` key
    :param default: default value if not provided or configured
    :param required: whether the value must not be ``None``
    :param message: error message if required config is not found
    :raises KeyError: if required config is not found
    N)r   Úconfigr&   ÚRuntimeError)ÚvalueÚconfig_nameÚdefaultr/   r   r+   r+   r,   r   v   s
   r   c                       s,   e Zd Z‡ fdd„Zdd„ Zdd„ Z‡  ZS )Ú_FlaskFormCSRFc                    s   |j | _ tƒ  |¡S ©N)ÚmetaÚsuperÚ
setup_form)ÚselfÚform©Ú	__class__r+   r,   rA   Ž   s   z_FlaskFormCSRF.setup_formc                 C   s   t | jj| jjd�S )N)r   r'   )r   r?   Úcsrf_secretÚcsrf_field_name)rB   Úcsrf_token_fieldr+   r+   r,   Úgenerate_csrf_token’   s   ÿz"_FlaskFormCSRF.generate_csrf_tokenc              
   C   s^   t  dd¡rd S zt|j| jj| jj| jjƒ W d S  ty. } z	t	 
|jd ¡ ‚ d }~ww )NÚ
csrf_validFr   )r   r&   r   r4   r?   rF   Úcsrf_time_limitrG   r   ÚloggerÚinfoÚargs)rB   rC   Úfieldr6   r+   r+   r,   Úvalidate_csrf_token—   s   
ü€þz"_FlaskFormCSRF.validate_csrf_token)Ú__name__Ú
__module__Ú__qualname__rA   rI   rP   Ú__classcell__r+   r+   rD   r,   r=   �   s    r=   c                   @   sB   e Zd ZdZddd„Zdd„ Zdd„ Zd	d
„ Zdd„ Zdd„ Z	dS )r   a[  Enable CSRF protection globally for a Flask app.

    ::

        app = Flask(__name__)
        csrf = CSRFProtect(app)

    Checks the ``csrf_token`` field sent with forms, or the ``X-CSRFToken``
    header sent with JavaScript requests. Render the token in templates using
    ``{{ csrf_token() }}``.

    See the :ref:`csrf` documentation.
    Nc                 C   s&   t ƒ | _t ƒ | _|r|  |¡ d S d S r>   )ÚsetÚ_exempt_viewsÚ_exempt_blueprintsÚinit_app)rB   Úappr+   r+   r,   Ú__init__·   s
   ÿzCSRFProtect.__init__c                    s°   ˆˆ j d< ˆ j dd¡ ˆ j dd¡ tˆ j dg d¢¡ƒˆ jd< ˆ j dd¡ ˆ j d	d
dg¡ ˆ j dd¡ ˆ j dd¡ tˆ jjd< ˆ  dd„ ¡ ˆ j	‡ ‡fdd„ƒ}d S )NÚcsrfÚWTF_CSRF_ENABLEDTÚWTF_CSRF_CHECK_DEFAULTÚWTF_CSRF_METHODS)ÚPOSTÚPUTÚPATCHÚDELETEr   r   ÚWTF_CSRF_HEADERSzX-CSRFTokenzX-CSRF-Tokenr-   r.   ÚWTF_CSRF_SSL_STRICTc                   S   s   dt iS )Nr   )r   r+   r+   r+   r,   Ú<lambda>Ì   s    z&CSRFProtect.init_app.<locals>.<lambda>c                     sŒ   ˆ j d sd S ˆ j d sd S tjˆ j d vrd S tjsd S ˆ j tj¡ˆjv r)d S ˆ j tj¡} | j	› d| j
› �}|ˆjv r@d S ˆ ¡  d S )Nr\   r]   r^   Ú.)r8   r   ÚmethodÚendpointÚ
blueprintsr&   Ú	blueprintrW   Úview_functionsrR   rQ   rV   Úprotect)ÚviewÚdest©rY   rB   r+   r,   Úcsrf_protectÎ   s   


z*CSRFProtect.init_app.<locals>.csrf_protect)
Ú
extensionsr8   Ú
setdefaultrU   r&   r   Ú	jinja_envÚglobalsÚcontext_processorÚbefore_request)rB   rY   rp   r+   ro   r,   rX   ¾   s   

ÿzCSRFProtect.init_appc                 C   sv   t jd }tj |¡}|r|S tjD ]}| |¡r$tj| }|r$|  S qt jd D ]}tj |¡}|r8|  S q*d S )Nr   rc   )r   r8   r   rC   r&   ÚendswithÚheaders)rB   r(   Ú
base_tokenÚkeyr   Úheader_namer+   r+   r,   Ú_get_csrf_tokenç   s    



€ÿzCSRFProtect._get_csrf_tokenc              
   C   s¸   t jtjd vr
d S zt|  ¡ ƒ W n" ty4 } zt |j	d ¡ |  
|j	d ¡ W Y d }~nd }~ww t jrWtjd rWt jsE|  
d¡ dt j› d�}tt j|ƒsW|  
d¡ dt_d S )	Nr^   r   rd   zThe referrer header is missing.zhttps://ú/z%The referrer does not match the host.T)r   rg   r   r8   r   r|   r   rL   rM   rN   Ú_error_responseÚ	is_secureÚreferrerÚhostÚsame_originr   rJ   )rB   r6   Úgood_referrerr+   r+   r,   rl      s    €þ


zCSRFProtect.protectc                 C   sL   t |tƒr| j |¡ |S t |tƒr|}n	d |j|jf¡}| j |¡ |S )a  Mark a view or blueprint to be excluded from CSRF protection.

        ::

            @app.route('/some-view', methods=['POST'])
            @csrf.exempt
            def some_view():
                ...

        ::

            bp = Blueprint(...)
            csrf.exempt(bp)

        rf   )	Ú
isinstancer   rW   ÚaddÚstrÚjoinrR   rQ   rV   )rB   rm   Úview_locationr+   r+   r,   Úexempt  s   

zCSRFProtect.exemptc                 C   s   t |ƒ‚r>   )Ú	CSRFError)rB   Úreasonr+   r+   r,   r~   2  s   zCSRFProtect._error_responser>   )
rQ   rR   rS   Ú__doc__rZ   rX   r|   rl   r‰   r~   r+   r+   r+   r,   r   ¨   s    
)r   c                   @   s   e Zd ZdZdZdS )rŠ   zïRaise if the client sends invalid CSRF data with the request.

    Generates a 400 Bad Request response with the failure reason by default.
    Customize the response by registering a handler with
    :meth:`flask.Flask.errorhandler`.
    zCSRF validation failed.N)rQ   rR   rS   rŒ   Údescriptionr+   r+   r+   r,   rŠ   6  s    rŠ   c                 C   s4   t | ƒ}t |ƒ}|j|jko|j|jko|j|jkS r>   )r   ÚschemeÚhostnameÚport)Úcurrent_uriÚcompare_uriÚcurrentÚcomparer+   r+   r,   r‚   A  s   
ÿ
ýr‚   )NN)NNN)NTr7   )!r   r2   Úloggingr    Úurllib.parser   Úflaskr   r   r   r   r   Úitsdangerousr   r	   r
   Úwerkzeug.exceptionsr   Úwtformsr   Úwtforms.csrf.corer   Ú__all__Ú	getLoggerrQ   rL   r   r   r   r=   r   rŠ   r‚   r+   r+   r+   r,   Ú<module>   s6    


+5
ÿ 