o
    h'                     @   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+   A/var/www/html/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   Z
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)valueZ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,   r?      s   z_FlaskFormCSRF.setup_formc                 C   s   t | jj| jjdS )N)r   r'   )r   r=   csrf_secretcsrf_field_name)r@   Z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=   rD   Zcsrf_time_limitrE   r   loggerinfoargs)r@   rA   fieldr5   r+   r+   r,   validate_csrf_token   s   
z"_FlaskFormCSRF.validate_csrf_token)__name__
__module____qualname__r?   rF   rL   __classcell__r+   r+   rB   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)r@   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 )NZ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 )NrW   rX   rY   .)r7   r   methodZendpointZ
blueprintsr&   	blueprintrS   Zview_functionsrN   rM   rR   protect)viewdestrU   r@   r+   r,   csrf_protect   s   


z*CSRFProtect.init_app.<locals>.csrf_protect)

extensionsr7   
setdefaultrQ   r&   r   Z	jinja_envglobalsZcontext_processorZbefore_request)r@   rU   rh   r+   rg   r,   rT      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   r^   )r   r7   r   rA   r&   endswithheaders)r@   r(   Z
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 )	NrY   r   r_   zThe referrer header is missing.zhttps:///z%The referrer does not match the host.T)r   rb   r   r7   r   rp   r   rH   rI   rJ   _error_responseZ	is_secureZreferrerhostsame_originr   rG   )r@   r5   Zgood_referrerr+   r+   r,   rd      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)

        ra   )	
isinstancer   rS   addstrjoinrN   rM   rR   )r@   re   Zview_locationr+   r+   r,   exempt  s   

zCSRFProtect.exemptc                 C   s   t |r<   )	CSRFError)r@   reasonr+   r+   r,   rr   2  s   zCSRFProtect._error_responser<   )
rM   rN   rO   __doc__rV   rT   rp   rd   ry   rr   r+   r+   r+   r,   r      s    
)r   c                   @   s   e Zd ZdZdZdS )rz   zRaise 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)rM   rN   rO   r|   descriptionr+   r+   r+   r,   rz   6  s    rz   c                 C   s4   t | }t |}|j|jko|j|jko|j|jkS r<   )r   schemehostnameport)Zcurrent_uriZcompare_uricurrentcomparer+   r+   r,   rt   A  s   

rt   )NN)NNN)NTr6   )!r   r2   loggingr    urllib.parser   Zflaskr   r   r   r   r   Zitsdangerousr   r	   r
   Zwerkzeug.exceptionsr   Zwtformsr   Zwtforms.csrf.corer   __all__	getLoggerrM   rH   r   r   r   r;   r   rz   rt   r+   r+   r+   r,   <module>   s6    


+5
 