B
    9‹dÐƒ  ã               @   s@  d 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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 ddlmZ ddlmZmZmZm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$Z$ddl%m&Z& ddl'm(Z( ddl)m*Z*m+Z+m,Z,m-Z-m.Z. ddl/m0Z0 e 1d¡Z2da3dd„ Z4dd„ Z5G dd„ dej6ƒZ7G dd„ de7ƒZ8G dd„ de8ƒZ9G dd„ de8ƒZ:G dd„ de8ej;ƒZ<d d!„ Z=ej>Z>G d"d#„ d#e8ej;ƒZ?G d$d%„ d%e9ƒZ@G d&d'„ d'ej6ƒZAG d(d)„ d)e8ƒZBG d*d+„ d+ej6ƒZCG d,d-„ d-e8ƒZDd.ZEd/eAfd0e@fd1ej;fd2eDfgZFdS )3z.Base Tornado handlers for the notebook server.é    N)Ú	responses)ÚMorsel)Úurlparse)ÚTemplateNotFound)ÚwebÚgenÚescapeÚhttputil)Úapp_log)Úget_sys_info)ÚApplication)Úfilefind)Ústring_types)Úutcnow)Úcombine_translations)Ú	is_hiddenÚurl_path_joinÚurl_is_absoluteÚ
url_escapeÚurldecode_unix_socket_path)Úcsp_report_uriz[^A-Za-z0-9]c               C   s   t d krt tƒ ¡a t S )N)Ú_sys_info_cacheÚjsonÚdumpsr   © r   r   úc/work/yifan.wang/ringdown/master-ringdown-env/lib/python3.7/site-packages/notebook/base/handlers.pyÚjson_sys_info,   s    r   c               C   s   t  ¡ rt  ¡ jS tS d S )N)r   ZinitializedÚinstanceÚlogr
   r   r   r   r   r   2   s    
r   c               @   sŽ   e Zd ZdZedd„ ƒZdd„ Zddd	„Zd
d„ Zdd„ Z	dd„ Z
edd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZdS )ÚAuthenticatedHandlerz,A RequestHandler with an authenticated user.c          
   C   sD   d| j  di ¡kr | j d d S d dd| j  dt| jtƒ¡ g¡S )z‰The default Content-Security-Policy header

        Can be overridden by defining Content-Security-Policy in settings['headers']
        zContent-Security-PolicyÚheadersz; zframe-ancestors 'self'zreport-uri r   )ÚsettingsÚgetÚjoinr   Úbase_urlr   )Úselfr   r   r   Úcontent_security_policy;   s
    z,AuthenticatedHandler.content_security_policyc             C   s„   i }d|d< |  | j di ¡¡ | j|d< xT| ¡ D ]H\}}y|  ||¡ W q4 tk
rz } z| j |¡ W d d }~X Y q4X q4W d S )NZnosniffzX-Content-Type-Optionsr    zContent-Security-Policy)	Úupdater!   r"   r&   ÚitemsÚ
set_headerÚ	Exceptionr   Údebug)r%   r    Úheader_nameÚvalueÚer   r   r   Úset_default_headersK   s    
z(AuthenticatedHandler.set_default_headersú/Nc             C   sj   t  |¡}tj ¡ tjdd }tƒ }| |dd¡ t |¡|d< ||d< |rV||d< |  	d| 
¡ ¡ d	S )
a™  Deletes the cookie with the given name.

        Tornado's cookie handling currently (Jan 2018) stores cookies in a dict
        keyed by name, so it can only modify one cookie with a given name per
        response. The browser can store multiple cookies with the same name
        but different domains and/or paths. This method lets us clear multiple
        cookies with the same name.

        Due to limitations of the cookie protocol, you must pass the same
        path and domain to clear a cookie as were used when that cookie
        was set (but there is no way to find out on the server side
        which values were used for a given cookie).
        im  )ÚdaysÚ z""ÚexpiresÚpathÚdomainz
Set-CookieN)r   Z
native_strÚdatetimer   Ú	timedeltar   Úsetr	   Zformat_timestampÚ
add_headerÚOutputString)r%   Únamer4   r5   r3   Úmorselr   r   r   Úforce_clear_cookie\   s    
z'AuthenticatedHandler.force_clear_cookiec             C   sH   | j  di ¡}| d| j¡}| j| j|d |rD|dkrD|  | j¡ d S )NÚcookie_optionsr4   )r4   r0   )r!   r"   Ú
setdefaultr$   Zclear_cookieÚcookie_namer=   )r%   r>   r4   r   r   r   Úclear_login_cookieu   s
    z'AuthenticatedHandler.clear_login_cookiec             C   s   | j d krdS | j  | ¡S )NÚ	anonymous)Úlogin_handlerZget_user)r%   r   r   r   Úget_current_user€   s    
z%AuthenticatedHandler.get_current_userc             C   s8   | j jdkrdS | jdks&t| jdƒs*dS | j | ¡ S )zÂAsk my login_handler if I should skip the origin_check

        For example: in the default LoginHandler, if a request is token-authenticated,
        origin checking should be skipped.
        ÚOPTIONSTNÚshould_check_originF)ÚrequestÚmethodrC   ÚhasattrrF   )r%   r   r   r   Úskip_check_origin…   s
    z&AuthenticatedHandler.skip_check_originc             C   s&   | j dkst| j dƒsdS | j  | ¡S )z'Have I been authenticated with a token?NÚis_token_authenticatedF)rC   rI   rK   )r%   r   r   r   Útoken_authenticated’   s    z(AuthenticatedHandler.token_authenticatedc             C   s$   t  dd| jj› ¡}| j d|¡S )Nú-z	username-r@   )Únon_alphanumÚsubrG   Úhostr!   r"   )r%   Zdefault_cookie_namer   r   r   r@   ™   s    z AuthenticatedHandler.cookie_namec             C   s   |   ¡ }|o|dk S )zIs a user currently logged in?rB   )rD   )r%   Úuserr   r   r   Ú	logged_inž   s    zAuthenticatedHandler.logged_inc             C   s   | j  dd¡S )z6Return the login handler for this application, if any.Zlogin_handler_classN)r!   r"   )r%   r   r   r   rC   ¤   s    z"AuthenticatedHandler.login_handlerc             C   s   | j  dd¡S )z4Return the login token for this application, if any.ÚtokenN)r!   r"   )r%   r   r   r   rS   ©   s    zAuthenticatedHandler.tokenc             C   s    | j dkrdS t| j  | j¡ƒS )zªMay a user proceed to log in?

        This returns True if login capability is available, irrespective of
        whether the user is already logged in or not.

        NF)rC   ÚboolZget_login_availabler!   )r%   r   r   r   Úlogin_available®   s    
z$AuthenticatedHandler.login_available)r0   N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__Úpropertyr&   r/   r=   rA   rD   rJ   rL   r@   rR   rC   rS   rU   r   r   r   r   r   8   s   
r   c                   sŠ  e Zd ZdZedd„ ƒZedd„ ƒZedd„ ƒZedd	„ ƒZed
d„ ƒZ	edd„ ƒZ
edd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZedd„ ƒZed d!„ ƒZed"d#„ ƒZed$d%„ ƒZed&d'„ ƒZed(d)„ ƒZed*d+„ ƒZ‡ fd,d-„Zd.d/„ Zd0d1„ ZdGd3d4„Zd5d6„ Z‡ fd7d8„Zd9d:„ Z ‡ fd;d<„Z!d=d>„ Z"d?d@„ Z#edAdB„ ƒZ$dCdD„ Z%dEdF„ Z&‡  Z'S )HÚIPythonHandlerzwIPython-specific extensions to authenticated handling

    Mostly property shortcuts to IPython-specific settings.
    c             C   s   | j  dd¡S )zzWether to user bundle in template. (*.min files)

        Mainly use for development and avoid file recompilation
        Úignore_minified_jsF)r!   r"   )r%   r   r   r   r\   Á   s    z!IPythonHandler.ignore_minified_jsc             C   s   | j  dd ¡S )NÚconfig)r!   r"   )r%   r   r   r   r]   É   s    zIPythonHandler.configc             C   s   t ƒ S )z@use the IPython log by default, falling back on tornado's logger)r   )r%   r   r   r   r   Í   s    zIPythonHandler.logc             C   s   | j  di ¡S )z2User-supplied values to supply to jinja templates.Újinja_template_vars)r!   r"   )r%   r   r   r   r^   Ò   s    z"IPythonHandler.jinja_template_varsc             C   s   | j  dd¡S )z8The version hash to use for cache hints for static filesÚversion_hashr2   )r!   r"   )r%   r   r   r   r_   Û   s    zIPythonHandler.version_hashc             C   s*   | j  dd¡}|rt|ƒr|S t| j|ƒS )NÚmathjax_urlr2   )r!   r"   r   r   r$   )r%   Úurlr   r   r   r`   à   s    zIPythonHandler.mathjax_urlc             C   s   | j  dd¡S )NÚmathjax_configzTeX-AMS-MML_HTMLorMML-full,Safe)r!   r"   )r%   r   r   r   rb   ç   s    zIPythonHandler.mathjax_configc             C   s   | j  dd¡S )Nr$   r0   )r!   r"   )r%   r   r   r   r$   ë   s    zIPythonHandler.base_urlc             C   s   | j  dd¡S )NÚdefault_urlr2   )r!   r"   )r%   r   r   r   rc   ï   s    zIPythonHandler.default_urlc             C   s   | j  dd¡S )NZwebsocket_urlr2   )r!   r"   )r%   r   r   r   Úws_urló   s    zIPythonHandler.ws_urlc             C   s   | j  dd¡S )NÚshow_bannerT)r!   r"   )r%   r   r   r   re   ÷   s    zIPythonHandler.show_bannerc             C   s&   | j  d| j dd¡¡ | j dd¡S )NzUsing contents: %sÚcontents_js_sourcezservices/contents)r   r+   r!   r"   )r%   r   r   r   rf   û   s    z!IPythonHandler.contents_js_sourcec             C   s
   | j d S )NÚkernel_manager)r!   )r%   r   r   r   rg     s    zIPythonHandler.kernel_managerc             C   s
   | j d S )NÚcontents_manager)r!   )r%   r   r   r   rh   	  s    zIPythonHandler.contents_managerc             C   s
   | j d S )NÚsession_manager)r!   )r%   r   r   r   ri     s    zIPythonHandler.session_managerc             C   s
   | j d S )NÚterminal_manager)r!   )r%   r   r   r   rj     s    zIPythonHandler.terminal_managerc             C   s
   | j d S )NÚkernel_spec_manager)r!   )r%   r   r   r   rk     s    z"IPythonHandler.kernel_spec_managerc             C   s
   | j d S )NÚconfig_manager)r!   )r%   r   r   r   rl     s    zIPythonHandler.config_managerc             C   s   | j  dd¡S )z"Normal Access-Control-Allow-OriginÚallow_originr2   )r!   r"   )r%   r   r   r   rm   !  s    zIPythonHandler.allow_originc             C   s   | j  dd¡S )z*Regular expression version of allow_originÚallow_origin_patN)r!   r"   )r%   r   r   r   rn   &  s    zIPythonHandler.allow_origin_patc             C   s   | j  dd¡S )z/Whether to set Access-Control-Allow-CredentialsÚallow_credentialsF)r!   r"   )r%   r   r   r   ro   +  s    z IPythonHandler.allow_credentialsc                s’   t ƒ  ¡  | jr |  d| j¡ n\| jrL|  ¡ }|r|| j |¡r||  d|¡ n0| jr|d| j 	di ¡kr||  d| j
j 	dd¡¡ | jrŽ|  dd¡ dS )zAdd CORS headers, if definedzAccess-Control-Allow-Originr    ÚOriginr2   z Access-Control-Allow-CredentialsÚtrueN)Úsuperr/   rm   r)   rn   Ú
get_originÚmatchrL   r!   r"   rG   r    ro   )r%   Úorigin)Ú	__class__r   r   r/   0  s    
z"IPythonHandler.set_default_headersc             C   s   t |ƒ}|  dd|› ¡ dS )zpSet Content-Disposition: attachment header

        As a method to ensure handling of filename encoding
        zContent-Dispositionzattachment; filename*=utf-8''N)r   r)   )r%   ÚfilenameZescaped_filenamer   r   r   Úset_attachment_headerF  s    z$IPythonHandler.set_attachment_headerc             C   s0   d| j jkr| j j d¡}n| j j dd ¡}|S )Nrp   zSec-Websocket-Origin)rG   r    r"   )r%   ru   r   r   r   rs   Q  s    zIPythonHandler.get_originr2   c             C   s°   | j dks|  ¡ rdS | jj d¡}| jj d¡}|dksB|dkrFdS | ¡ }t|ƒj}||krddS | j rv| j |k}n| jrŽt	| j 
|¡ƒ}nd}|s¬| j d| jj||¡ |S )zÙCheck Origin for cross-site API requests, including websockets

        Copied from WebSocket with changes:

        - allow unspecified host/origin (e.g. scripts)
        - allow token-authenticated requests
        Ú*TÚHostrp   NFz?Blocking Cross Origin API request for %s.  Origin: %s, Host: %s)rm   rJ   rG   r    r"   Úlowerr   Únetlocrn   rT   rt   r   Úwarningr4   )r%   Zorigin_to_satisfy_tornadorP   ru   Úorigin_hostÚallowr   r   r   Úcheck_origin^  s&    
zIPythonHandler.check_originc             C   sÒ   | j dks|  ¡ rdS | jj d¡}| jj d¡}|sF| j d¡ dS |sZ| j d¡ dS t|ƒ}|j}||krtdS |j	› d|j› }| j r˜| j |k}n| j
r°t| j
 |¡ƒ}nd}|sÎ| j d	| jj||¡ |S )
a^  Check Referer for cross-site requests.

        Disables requests to certain endpoints with
        external or missing Referer.

        If set, allow_origin settings are applied to the Referer
        to whitelist specific cross-origin sites.

        Used on GET for api endpoints and /files/
        to block cross-site inclusion (XSSI).
        ry   Trz   ÚRefererzBlocking request with no hostFz Blocking request with no refererz://z<Blocking Cross Origin request for %s.  Referer: %s, Host: %s)rm   rJ   rG   r    r"   r   r}   r   r|   Úschemern   rT   rt   r4   )r%   rP   ÚrefererZreferer_urlZreferer_hostru   r   r   r   r   Úcheck_refererŠ  s0    zIPythonHandler.check_refererc          
      s–   | j s| j dd¡rdS y
tƒ  ¡ S  tjk
r } zN| jjdkr~|  	¡ s€| jj
 d¡}|rjd|› d}nd}t d	|¡|‚n‚ W dd}~X Y nX dS )
z2Bypass xsrf cookie checks when token-authenticatedZdisable_check_xsrfFN>   ÚGETÚHEADr   z#Blocking Cross Origin request from Ú.z$Blocking request from unknown origini“  )rL   r!   r"   rr   Úcheck_xsrf_cookier   Ú	HTTPErrorrG   rH   r„   r    )r%   r.   rƒ   Úmsg)rv   r   r   rˆ   ¹  s    
z IPythonHandler.check_xsrf_cookiec             C   sÆ   | j  dd¡rdS t d| jj¡ d¡}| d¡rH| d¡rH|dd… }t	|ƒ}| d	¡rlt
j |¡rld}n>yt |¡}W n( tk
r¢   || j  d
dg¡k}Y nX |j}|sÂ| j d|| jj¡ |S )z‚Check the host header if remote access disallowed.

        Returns True if the request should continue, False otherwise.
        Zallow_remote_accessFTz^(.*?)(:\d+)?$é   ú[ú]éÿÿÿÿr0   Zlocal_hostnamesÚ	localhostzœBlocking request with non-local 'Host' %s (%s). If the notebook should be accessible at that name, set NotebookApp.allow_remote_access to disable the check.)r!   r"   Úrert   rG   rP   ÚgroupÚ
startswithÚendswithr   Úosr4   ÚexistsÚ	ipaddressÚ
ip_addressÚ
ValueErrorÚis_loopbackr   r}   )r%   rP   Ú
check_hostr   Úaddrr   r   r   rš   Î  s$    zIPythonHandler.check_hostc                s   |   ¡ st d¡‚tƒ  ¡ S )Ni“  )rš   r   r‰   rr   Úprepare)r%   )rv   r   r   rœ   ó  s    
zIPythonHandler.preparec             C   s   | j d  |¡S )z1Return the jinja template object for a given nameZ
jinja2_env)r!   Úget_template)r%   r;   r   r   r   r   ü  s    zIPythonHandler.get_templatec             K   s"   |  | j¡ |  |¡}|jf |ŽS )N)r'   Útemplate_namespacer   Úrender)r%   r;   ÚnsÚtemplater   r   r   Úrender_template   s    
zIPythonHandler.render_templatec             C   sz   t f | j| j| j| j| j d¡| jt| j	ƒ| j
tƒ | j| j| j| j| j	| j d¡t t| jj dd¡ƒ¡| jdœ| j—ŽS )NÚallow_password_changeÚutf8zAccept-Languager2   )r$   rc   rd   rR   r£   rU   Ztoken_availableÚ
static_urlZsys_inforf   r_   r\   Úxsrf_form_htmlrS   Ú
xsrf_tokenZnbjs_translationsre   )Údictr$   rc   rd   rR   r!   r"   rU   rT   rS   r¥   r   rf   r_   r\   r¦   r§   Údecoder   r   r   rG   r    re   r^   )r%   r   r   r   rž     s(    

z!IPythonHandler.template_namespacec          
   C   s€   | j jsdS | j j ¡  d¡}yt |¡}W nN tk
rz } z0| j d|¡ | jj	ddd t
 dd¡|‚W dd}~X Y nX |S )	z,Return the body of the request as JSON data.Nzutf-8zBad JSON: %rzCouldn't parse JSONT)Úexc_infoi  zInvalid JSON in body of request)rG   ÚbodyÚstripr©   r   Úloadsr*   r   r+   Úerrorr   r‰   )r%   r«   Úmodelr.   r   r   r   Úget_json_body  s     zIPythonHandler.get_json_bodyc       
      K   sÈ   |  d¡}d}t  |d¡}d}|rd|d }y|j|j }W n tk
rN   Y nX t|ddƒ}|rd|}t||||d}|  dd	¡ y| j|› d
f|Ž}	W n  t	k
r¸   | jd|Ž}	Y nX |  
|	¡ dS )zrender custom error pagesrª   r2   zUnknown HTTP Errorz	(unknown)r‹   Úreason)Ústatus_codeÚstatus_messageÚmessageÚ	exceptionzContent-Typez	text/htmlz.htmlú
error.htmlN)r¶   )r"   r   Úlog_messageÚargsr*   Úgetattrr¨   r)   r¢   r   Úwrite)
r%   r²   Úkwargsrª   r´   r³   rµ   r±   r    Úhtmlr   r   r   Úwrite_error+  s0    
zIPythonHandler.write_error)r2   )(rV   rW   rX   rY   rZ   r\   r]   r   r^   r_   r`   rb   r$   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   rm   rn   ro   r/   rx   rs   r€   r„   rˆ   rš   rœ   r   r¢   rž   r°   r½   Ú__classcell__r   r   )rv   r   r[   »   sF   	

,/%	r[   c                   sp   e Zd ZdZ‡ fdd„Zdd„ Z‡ fdd„Z‡ fdd	„Ze‡ fd
d„ƒZ	dZ
dd„ Z‡ fdd„Zdd„ Z‡  ZS )Ú
APIHandlerzBase class for API handlersc                s   |   ¡ st d¡‚tƒ  ¡ S )Ni”  )r€   r   r‰   rr   rœ   )r%   )rv   r   r   rœ   S  s    
zAPIHandler.preparec             K   s¢   |   dd¡ t |d¡}d|i}| d¡}|r~|d }t|tƒrZ|jpH||d< |j|d< n$d|d< d	|d< d
 tj	|Ž ¡|d< | j
 |d ¡ |  t |¡¡ d	S )z+APIHandler errors are JSON, not human pageszContent-Typezapplication/jsonzUnknown HTTP Errorr´   rª   r‹   r±   zUnhandled errorNr2   Ú	traceback)r)   r   r"   Ú
isinstancer‰   r·   r±   r#   rÀ   Úformat_exceptionr   r}   Úfinishr   r   )r%   r²   r»   r´   Zreplyrª   r.   r   r   r   r½   X  s    

zAPIHandler.write_errorc                s$   t | dƒr| jS tƒ  ¡  | _}|S )zDRaise 403 on API handlers instead of redirecting to human login pageÚ_user_cache)rI   rÄ   rr   rD   )r%   rQ   )rv   r   r   rD   l  s    
zAPIHandler.get_current_userc                s   | j st d¡‚tƒ  ¡ S )Ni“  )Zcurrent_userr   r‰   rr   Úget_login_url)r%   )rv   r   r   rÅ   t  s    
zAPIHandler.get_login_urlc                s   d  tƒ jdg¡}|S )Nz; zdefault-src 'none')r#   rr   r&   )r%   Zcsp)rv   r   r   r&   |  s    z"APIHandler.content_security_policyTc             C   s2   | j r.t| ddƒr.|  dd¡dkr.tƒ | jd< dS )z$Update last_activity of API requestsrÄ   NZno_track_activityZapi_last_activity)Ú_track_activityr¹   Úget_argumentr   r!   )r%   r   r   r   Úupdate_api_activity‡  s    zAPIHandler.update_api_activityc                s"   |   ¡  |  dd¡ tƒ j||ŽS )NzContent-Typezapplication/json)rÈ   r)   rr   rÃ   )r%   r¸   r»   )rv   r   r   rÃ   ‘  s    zAPIHandler.finishc             O   s®   d| j  di ¡kr*|  d| j d d ¡ n|  dd¡ |  dd¡ | jj dd¡ d¡}|rªtd	d
„ |D ƒƒrª| jrª| js’| j	s’d| j  di ¡krª|  d| jj dd¡¡ d S )NzAccess-Control-Allow-Headersr    z0accept, content-type, authorization, x-xsrftokenzAccess-Control-Allow-Methodsz&GET, PUT, POST, PATCH, DELETE, OPTIONSzAccess-Control-Request-Headersr2   ú,c             s   s   | ]}|  ¡  ¡ d kV  qdS )ÚauthorizationN)r¬   r{   )Ú.0Úhr   r   r   ú	<genexpr>§  s   z%APIHandler.options.<locals>.<genexpr>zAccess-Control-Allow-Originrp   )
r!   r"   r)   rG   r    ÚsplitÚanyrU   rm   rn   )r%   r¸   r»   Zrequested_headersr   r   r   Úoptions–  s     
zAPIHandler.options)rV   rW   rX   rY   rœ   r½   rD   rÅ   rZ   r&   rÆ   rÈ   rÃ   rÐ   r¾   r   r   )rv   r   r¿   P  s   	
r¿   c               @   s   e Zd ZdZdd„ ZdS )ÚTemplate404zRender our 404 templatec             C   s   t  d¡‚d S )Ni”  )r   r‰   )r%   r   r   r   rœ   ¸  s    zTemplate404.prepareN)rV   rW   rX   rY   rœ   r   r   r   r   rÑ   ¶  s   rÑ   c                   sp   e Zd ZdZe‡ fdd„ƒZej‡ fdd„ƒZejdd„ ƒZ	‡ fdd	„Z
‡ fd
d„Zdd„ Z‡ fdd„Z‡  ZS )ÚAuthenticatedFileHandlerz5static files should only be accessible when logged inc                s   t ƒ jd S )Nz; sandbox allow-scripts)rr   r&   )r%   )rv   r   r   r&   ¿  s    z0AuthenticatedFileHandler.content_security_policyc                s   |   ¡  tƒ  |¡S )N)rˆ   rr   Úhead)r%   r4   )rv   r   r   rÓ   Å  s    zAuthenticatedFileHandler.headc             C   sP   |   ¡  tj |¡d dks(|  dd¡rB| dd¡d }|  |¡ tj 	| |¡S )Nr‹   z.ipynbÚdownloadFr0   rŽ   )
rˆ   r”   r4   ÚsplitextrÇ   Úrsplitrx   r   ÚStaticFileHandlerr"   )r%   r4   r;   r   r   r   r"   Ê  s
     
zAuthenticatedFileHandler.getc                s`   | j  d¡}d|kr&| dd¡\}}n|}| d¡r8dS t |¡d }|dkrRdS tƒ  ¡ S d S )Nr0   r‹   z.ipynbzapplication/x-ipynb+jsonr   z
text/plainztext/plain; charset=UTF-8)Úabsolute_pathr¬   rÖ   r“   Ú	mimetypesÚ
guess_typerr   Úget_content_type)r%   r4   Ú_r;   Zcur_mime)rv   r   r   rÛ   Ô  s    
z)AuthenticatedFileHandler.get_content_typec                s&   t ƒ  ¡  d| jjkr"|  dd¡ d S )NÚvzCache-Controlzno-cache)rr   Úset_headersrG   Ú	argumentsr9   )r%   )rv   r   r   rÞ   ã  s    
z$AuthenticatedFileHandler.set_headersc             C   s   d S )Nr   )r%   r   r   r   Úcompute_etagé  s    z%AuthenticatedFileHandler.compute_etagc                sF   t ƒ  ||¡}tj |¡}t||ƒrB| jjsB| j 	d¡ t
 d¡‚|S )zValidate and return the absolute path.

        Requires tornado 3.1

        Adding to tornado's own handling, forbids the serving of hidden files.
        z_Refusing to serve hidden file, via 404 Error, use flag 'ContentsManager.allow_hidden' to enablei”  )rr   Úvalidate_absolute_pathr”   r4   Úabspathr   rh   Zallow_hiddenr   Úinfor   r‰   )r%   ÚrootrØ   Úabs_pathZabs_root)rv   r   r   rá   ì  s    
z/AuthenticatedFileHandler.validate_absolute_path)rV   rW   rX   rY   rZ   r&   r   ÚauthenticatedrÓ   r"   rÛ   rÞ   rà   rá   r¾   r   r   )rv   r   rÒ   ¼  s   
rÒ   c                s*   t jdtdd t ˆ ¡‡ fdd„ƒ}|S )a™  Decorate methods with this to return GitHub style JSON errors.

    This should be used on any JSON API on any handler method that can raise HTTPErrors.

    This will grab the latest HTTPError exception using sys.exc_info
    and then:

    1. Set the HTTP status code based on the HTTPError
    2. Create and return a JSON body with a message field describing
       the error in a human readable form.
    zJ@json_errors is deprecated in notebook 5.2.0. Subclass APIHandler instead.é   )Ú
stacklevelc                s    t  tj| ¡| _ˆ | f|ž|ŽS )N)ÚtypesÚ
MethodTyper¿   r½   )r%   r¸   r»   )rH   r   r   Úwrapper  s    zjson_errors.<locals>.wrapper)ÚwarningsÚwarnÚDeprecationWarningÚ	functoolsÚwraps)rH   rë   r   )rH   r   Újson_errorsû  s
    rñ   c                   sN   e Zd ZdZi Z‡ fdd„Zddd„Zdd„ Zed	d
„ ƒZ	‡ fdd„Z
‡  ZS )ÚFileFindHandlerzBsubclass of StaticFileHandler for serving files from a search pathc                s>   t ƒ  ¡  dˆ jjks.t‡ fdd„ˆ jD ƒƒr:ˆ  dd¡ d S )NrÝ   c             3   s   | ]}ˆ j j |¡V  qd S )N)rG   r4   r’   )rË   r4   )r%   r   r   rÍ   $  s    z.FileFindHandler.set_headers.<locals>.<genexpr>zCache-Controlzno-cache)rr   rÞ   rG   rß   rÏ   Úno_cache_pathsr)   )r%   )rv   )r%   r   rÞ      s    
zFileFindHandler.set_headersNc             C   s8   |pg | _ t|tƒr|g}tdd„ |D ƒƒ| _|| _d S )Nc             s   s(   | ] }t j t j |¡¡t j V  qd S )N)r”   r4   râ   Ú
expanduserÚsep)rË   Úpr   r   r   rÍ   .  s    z-FileFindHandler.initialize.<locals>.<genexpr>)ró   rÁ   r   Útuplerä   Údefault_filename)r%   r4   rø   ró   r   r   r   Ú
initialize'  s    

zFileFindHandler.initializec             C   s   d S )Nr   )r%   r   r   r   rà   2  s    zFileFindHandler.compute_etagc          	   C   st   | j d || jkr| j| S ytj t||ƒ¡}W n tk
rF   dS X || j|< tƒ  d||f ¡ |S Q R X dS )z5locate a file to serve on our static file search pathr2   zPath %s served from %sN)	Ú_lockÚ_static_pathsr”   r4   râ   r   ÚOSErrorr   r+   )ÚclsÚrootsr4   râ   r   r   r   Úget_absolute_path5  s    


z!FileFindHandler.get_absolute_pathc                sB   |dkrt  d¡‚x | jD ]}|tj  |¡rP qW tƒ  ||¡S )z:check if the file should be served (raises 404, 403, etc.)r2   i”  )r   r‰   rä   r”   rõ   r’   rr   rá   )r%   rä   rØ   )rv   r   r   rá   G  s    
z&FileFindHandler.validate_absolute_path)NN)rV   rW   rX   rY   rû   rÞ   rù   rà   Úclassmethodrÿ   rá   r¾   r   r   )rv   r   rò     s   
rò   c               @   s   e Zd Zdd„ ZdS )ÚAPIVersionHandlerc             C   s   |   t dtji¡¡ d S )NÚversion)rÃ   r   r   ÚnotebookÚ__version__)r%   r   r   r   r"   U  s    zAPIVersionHandler.getN)rV   rW   rX   r"   r   r   r   r   r  S  s   r  c               @   s    e Zd ZdZdd„ Ze ZZdS )ÚTrailingSlashHandlerzrSimple redirect handler that strips trailing slashes

    This should be the first, highest priority handler.
    c             C   s>   | j j d¡^}}d| d¡ }d |f|•¡}|  |¡ d S )Nú?r0   r2   )rG   ÚuriÚ	partitionr¬   r#   Úredirect)r%   r4   ÚrestZnew_urir   r   r   r"   `  s    zTrailingSlashHandler.getN)rV   rW   rX   rY   r"   ÚpostÚputr   r   r   r   r  Z  s   r  c               @   s&   e Zd ZdZedd„ ƒZddd„ZdS )	ÚFilesRedirectHandlerz<Handler for redirecting relative URLs to the /files/ handlerc             C   s²   | j }| |¡r$t| jdt|ƒƒ}nl|}| d¡}|j|dshd|krh| j d|¡ | 	d¡ d 
|¡}|j|ds~t d¡‚t| jdt|ƒƒ}| j d| jj|¡ |  |¡ dS )	zgmake redirect logic a reusable static method

        so it can be called from other handlers.
        Útreer0   )r4   ÚfileszDeprecated files/ URL: %si”  zRedirecting %s to %sN)rh   Z
dir_existsr   r$   r   rÎ   Zfile_existsr   r}   Úremover#   r   r‰   r+   rG   r4   r	  )r%   r4   Úcmra   Ú	orig_pathÚpartsr   r   r   Úredirect_to_filesn  s    




z&FilesRedirectHandler.redirect_to_filesr2   c             C   s   |   | |¡S )N)r  )r%   r4   r   r   r   r"   ‹  s    zFilesRedirectHandler.getN)r2   )rV   rW   rX   rY   Ústaticmethodr  r"   r   r   r   r   r  k  s   r  c               @   s"   e Zd ZdZddd„Zdd„ ZdS )	ÚRedirectWithParamsz8Sam as web.RedirectHandler, but preserves URL parametersTc             C   s   || _ || _d S )N)Ú_urlÚ
_permanent)r%   ra   Ú	permanentr   r   r   rù   ‘  s    zRedirectWithParams.initializec             C   s:   d| j krdnd}| | j | jjg¡}| j|| jd d S )Nr  ú&)r  )r  r#   rG   Úqueryr	  r  )r%   rõ   ra   r   r   r   r"   •  s    zRedirectWithParams.getN)T)rV   rW   rX   rY   rù   r"   r   r   r   r   r    s   
r  c               @   s   e Zd ZdZdd„ ZdS )ÚPrometheusMetricsHandlerz<
    Return prometheus metrics for this notebook server
    c             C   s>   | j d r| jst d¡‚|  dtj¡ |  t tj	¡¡ d S )NZauthenticate_prometheusi“  zContent-Type)
r!   rR   r   r‰   r)   Úprometheus_clientZCONTENT_TYPE_LATESTrº   Zgenerate_latestZREGISTRY)r%   r   r   r   r"   Ÿ  s    
zPrometheusMetricsHandler.getN)rV   rW   rX   rY   r"   r   r   r   r   r  ›  s   r  z(?P<path>(?:(?:/[^/]+)+|/?))z.*/Úapiz/(robots\.txt|favicon\.ico)z/metrics)GrY   r6   rï   r–   r   rÙ   r”   r   ÚsysrÀ   ré   rì   Úhttp.clientr   Úhttp.cookiesr   Úurllib.parser   Zjinja2r   Útornador   r   r   r	   Ztornado.logr
   r  Znotebook._sysinfor   Ztraitlets.configr   Zipython_genutils.pathr   Zipython_genutils.py3compatr   r  Znotebook._tzr   Znotebook.i18nr   Znotebook.utilsr   r   r   r   r   Znotebook.services.securityr   ÚcompilerN   r   r   r   ZRequestHandlerr   r[   r¿   rÑ   r×   rÒ   rñ   r‰   rò   r  r  r  r  r  Z
path_regexZdefault_handlersr   r   r   r   Ú<module>   sj   
    f?9$