From a50ac36bd554366a80f907d4d16b552d53c69ddf 2012-01-06 10:00:14 From: Min RK <benjaminrk@gmail.com> Date: 2012-01-06 10:00:14 Subject: [PATCH] Merge pull request #1211 from minrk/localfiles Files in notebook-dir are served by the nbserver as `files/<relativepath>`. --- diff --git a/IPython/frontend/html/notebook/handlers.py b/IPython/frontend/html/notebook/handlers.py index df3b65c..62bc795 100644 --- a/IPython/frontend/html/notebook/handlers.py +++ b/IPython/frontend/html/notebook/handlers.py @@ -108,6 +108,7 @@ def authenticate_unless_readonly(f, self, *args, **kwargs): @web.authenticated def auth_f(self, *args, **kwargs): return f(self, *args, **kwargs) + if self.application.read_only: return f(self, *args, **kwargs) else: @@ -175,6 +176,14 @@ class AuthenticatedHandler(RequestHandler): return "%s://%s" % (proto, self.request.host) +class AuthenticatedFileHandler(AuthenticatedHandler, web.StaticFileHandler): + """static files should only be accessible when logged in""" + + @authenticate_unless_readonly + def get(self, path): + return web.StaticFileHandler.get(self, path) + + class ProjectDashboardHandler(AuthenticatedHandler): @authenticate_unless_readonly diff --git a/IPython/frontend/html/notebook/notebookapp.py b/IPython/frontend/html/notebook/notebookapp.py index beb356b..b0360e5 100644 --- a/IPython/frontend/html/notebook/notebookapp.py +++ b/IPython/frontend/html/notebook/notebookapp.py @@ -48,7 +48,8 @@ from .kernelmanager import MappingKernelManager from .handlers import (LoginHandler, LogoutHandler, ProjectDashboardHandler, NewHandler, NamedNotebookHandler, MainKernelHandler, KernelHandler, KernelActionHandler, IOPubHandler, - ShellHandler, NotebookRootHandler, NotebookHandler, RSTHandler + ShellHandler, NotebookRootHandler, NotebookHandler, RSTHandler, + AuthenticatedFileHandler, ) from .notebookmanager import NotebookManager @@ -103,7 +104,8 @@ class NotebookWebApplication(web.Application): (r"/kernels/%s/shell" % _kernel_id_regex, ShellHandler), (r"/notebooks", NotebookRootHandler), (r"/notebooks/%s" % _notebook_id_regex, NotebookHandler), - (r"/rstservice/render", RSTHandler) + (r"/rstservice/render", RSTHandler), + (r"/files/(.*)", AuthenticatedFileHandler, {'path' : notebook_manager.notebook_dir}), ] settings = dict( template_path=os.path.join(os.path.dirname(__file__), "templates"), @@ -280,7 +282,7 @@ class NotebookApp(BaseIPythonApplication): static_path = self.webapp_settings.get("static_path", os.path.join(os.path.dirname(__file__), "static")) if os.path.exists(os.path.join(static_path, 'mathjax', "MathJax.js")): self.log.info("Using local MathJax") - return u"static/mathjax/MathJax.js" + return u"/static/mathjax/MathJax.js" else: self.log.info("Using MathJax from CDN") return u"http://cdn.mathjax.org/mathjax/latest/MathJax.js" diff --git a/IPython/frontend/html/notebook/templates/layout.html b/IPython/frontend/html/notebook/templates/layout.html index 8d5e4d2..407e2ab 100644 --- a/IPython/frontend/html/notebook/templates/layout.html +++ b/IPython/frontend/html/notebook/templates/layout.html @@ -6,10 +6,10 @@ <title>{% block title %}IPython Notebook{% end %}</title> - <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" /> - <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" /> - <link rel="stylesheet" href="static/css/layout.css" type="text/css" /> - <link rel="stylesheet" href="static/css/base.css" type="text/css"/> + <link rel="stylesheet" href="/static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/layout.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/base.css" type="text/css"/> {% block stylesheet %} {% end %} @@ -21,7 +21,7 @@ <body {% block params %}{% end %}> <div id="header"> - <span id="ipython_notebook"><h1><img src='static/ipynblogo.png' alt='IPython Notebook'/></h1></span> + <span id="ipython_notebook"><h1><img src='/static/ipynblogo.png' alt='IPython Notebook'/></h1></span> {% block login_widget %} @@ -72,11 +72,11 @@ </div> -<script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script> -<script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/loginmain.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/loginmain.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script> {% block script %} {% end %} diff --git a/IPython/frontend/html/notebook/templates/notebook.html b/IPython/frontend/html/notebook/templates/notebook.html index ab160a1..11daece 100644 --- a/IPython/frontend/html/notebook/templates/notebook.html +++ b/IPython/frontend/html/notebook/templates/notebook.html @@ -15,20 +15,20 @@ window.mathjax_url = "{{mathjax_url}}"; </script> - <link rel="stylesheet" href="static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" /> - <link rel="stylesheet" href="static/codemirror/lib/codemirror.css"> - <link rel="stylesheet" href="static/codemirror/mode/markdown/markdown.css"> - <link rel="stylesheet" href="static/codemirror/mode/rst/rst.css"> - <link rel="stylesheet" href="static/codemirror/theme/ipython.css"> - <link rel="stylesheet" href="static/codemirror/theme/default.css"> + <link rel="stylesheet" href="/static/jquery/css/themes/aristo/jquery-wijmo.css" type="text/css" /> + <link rel="stylesheet" href="/static/codemirror/lib/codemirror.css"> + <link rel="stylesheet" href="/static/codemirror/mode/markdown/markdown.css"> + <link rel="stylesheet" href="/static/codemirror/mode/rst/rst.css"> + <link rel="stylesheet" href="/static/codemirror/theme/ipython.css"> + <link rel="stylesheet" href="/static/codemirror/theme/default.css"> - <link rel="stylesheet" href="static/prettify/prettify.css"/> + <link rel="stylesheet" href="/static/prettify/prettify.css"/> - <link rel="stylesheet" href="static/css/boilerplate.css" type="text/css" /> - <link rel="stylesheet" href="static/css/layout.css" type="text/css" /> - <link rel="stylesheet" href="static/css/base.css" type="text/css" /> - <link rel="stylesheet" href="static/css/notebook.css" type="text/css" /> - <link rel="stylesheet" href="static/css/renderedhtml.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/boilerplate.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/layout.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/base.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/notebook.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/renderedhtml.css" type="text/css" /> {% comment In the notebook, the read-only flag is used to determine %} {% comment whether to hide the side panels and switch off input %} @@ -42,7 +42,7 @@ > <div id="header"> - <span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='static/ipynblogo.png' alt='IPython Notebook'/></a></h1></span> + <span id="ipython_notebook"><h1><a href='..' alt='dashboard'><img src='/static/ipynblogo.png' alt='IPython Notebook'/></a></h1></span> <span id="save_widget"> <input type="text" id="notebook_name" size="20"></textarea> <button id="save_notebook"><u>S</u>ave</button> @@ -258,40 +258,40 @@ </div> -<script src="static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script> -<script src="static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script> -<script src="static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/jquery/js/jquery-1.6.2.min.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/jquery/js/jquery-ui-1.8.14.custom.min.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/jquery/js/jquery.autogrow.js" type="text/javascript" charset="utf-8"></script> -<script src="static/codemirror/lib/codemirror.js" charset="utf-8"></script> -<script src="static/codemirror/mode/python/python.js" charset="utf-8"></script> -<script src="static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script> -<script src="static/codemirror/mode/xml/xml.js" charset="utf-8"></script> -<script src="static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script> -<script src="static/codemirror/mode/css/css.js" charset="utf-8"></script> -<script src="static/codemirror/mode/rst/rst.js" charset="utf-8"></script> -<script src="static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script> +<script src="/static/codemirror/lib/codemirror.js" charset="utf-8"></script> +<script src="/static/codemirror/mode/python/python.js" charset="utf-8"></script> +<script src="/static/codemirror/mode/htmlmixed/htmlmixed.js" charset="utf-8"></script> +<script src="/static/codemirror/mode/xml/xml.js" charset="utf-8"></script> +<script src="/static/codemirror/mode/javascript/javascript.js" charset="utf-8"></script> +<script src="/static/codemirror/mode/css/css.js" charset="utf-8"></script> +<script src="/static/codemirror/mode/rst/rst.js" charset="utf-8"></script> +<script src="/static/codemirror/mode/markdown/markdown.js" charset="utf-8"></script> -<script src="static/pagedown/Markdown.Converter.js" charset="utf-8"></script> +<script src="/static/pagedown/Markdown.Converter.js" charset="utf-8"></script> -<script src="static/prettify/prettify.js" charset="utf-8"></script> +<script src="/static/prettify/prettify.js" charset="utf-8"></script> -<script src="static/js/namespace.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/utils.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/cell.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/codecell.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/textcell.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/kernel.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/layout.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/savewidget.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/quickhelp.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/pager.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/panelsection.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/printwidget.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/notebook.js" type="text/javascript" charset="utf-8"></script> -<script src="static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/namespace.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/utils.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/cell.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/codecell.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/textcell.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/kernel.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/kernelstatus.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/layout.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/savewidget.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/quickhelp.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/loginwidget.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/pager.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/panelsection.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/printwidget.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/leftpanel.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/notebook.js" type="text/javascript" charset="utf-8"></script> +<script src="/static/js/notebookmain.js" type="text/javascript" charset="utf-8"></script> </body> diff --git a/IPython/frontend/html/notebook/templates/projectdashboard.html b/IPython/frontend/html/notebook/templates/projectdashboard.html index d3036af..3dfc52b 100644 --- a/IPython/frontend/html/notebook/templates/projectdashboard.html +++ b/IPython/frontend/html/notebook/templates/projectdashboard.html @@ -5,7 +5,7 @@ IPython Dashboard {% end %} {% block stylesheet %} - <link rel="stylesheet" href="static/css/projectdashboard.css" type="text/css" /> + <link rel="stylesheet" href="/static/css/projectdashboard.css" type="text/css" /> {% end %} {% block meta %} @@ -38,6 +38,6 @@ data-base-kernel-url={{base_kernel_url}} {% end %} {% block script %} - <script src="static/js/notebooklist.js" type="text/javascript" charset="utf-8"></script> - <script src="static/js/projectdashboardmain.js" type="text/javascript" charset="utf-8"></script> + <script src="/static/js/notebooklist.js" type="text/javascript" charset="utf-8"></script> + <script src="/static/js/projectdashboardmain.js" type="text/javascript" charset="utf-8"></script> {% end %} diff --git a/docs/examples/notebooks/00_notebook_tour.ipynb b/docs/examples/notebooks/00_notebook_tour.ipynb index dc99083..a62c2de 100644 --- a/docs/examples/notebooks/00_notebook_tour.ipynb +++ b/docs/examples/notebooks/00_notebook_tour.ipynb @@ -778,6 +778,45 @@ { "cell_type": "markdown", "source": [ + "## Local Files", + "", + "The above examples embed images and video from the notebook filesystem in the output", + "areas of code cells. It is also possible to request these files directly in markdown cells", + "if they reside in the notebook directory via relative urls prefixed with `files/`:", + "", + " files/[subdirectory/]<filename>", + "", + "", + "For example, in the example notebook folder, we have the Python logo, addressed as:", + "", + " <img src=\"files/python-logo.svg\" />", + "", + "<img src=\"files/python-logo.svg\" />", + "", + "and a video with the HTML5 video tag:", + "", + " <video controls src=\"files/animation.m4v\" />", + "", + "<video controls src=\"files/animation.m4v\" />", + "", + "These do not embed the data into the notebook file,", + "and require that the files exist when you are viewing the notebook.", + "", + "### Security of local files", + "", + "Note that this means that the IPython notebook server also acts as a generic file server", + "for files inside the same tree as your notebooks. Access is not granted outside the", + "notebook folder so you have strict control over what files are visible, but for this", + "reason it is highly recommended that you do not run the notebook server with a notebook", + "directory at a high level in your filesystem (e.g. your home directory).", + "", + "When you run the notebook in a password-protected manner, local file access is restricted", + "to authenticated users unless read-only views are active." + ] + }, + { + "cell_type": "markdown", + "source": [ "### External sites", "", "You can even embed an entire page from another site in an iframe; for example this is today's Wikipedia",