Skip to content

Commit 605eaa7

Browse files
danpfgnestor
authored andcommitted
Added a flag to allow access of hidden files (#2819)
* Added a flag to allow access of hidden files The flag '--allow-hidden' will allow Tornado to access hidden files such as '.images/my_img.jpg' * Fixed jupyterlab not following allow-hidden Jupyterlab stores its options in a different location than the standard notebook. Added the ability to check there as well. * Updated implementation for any app Previously I was accessing the settings dict based on the name of the app that was being used. ex 'NotebookApp', or 'LabApp'. Now the setting is passed directly into the Tornado settings, and can be accessed via a more general method. * Added/fixed unit tests for test_hidden_files Fixed broken unit tests by setting the default to allow_hidden=False then added unit test in FilesTest:test_hidden_files that checks for the accessibility of files with allow_hidden=True * allow-hidden now works everywhere Previously allow-hidden flag only allowed hidden files to be accessed via tornado. Now you can use the allow-hidden flag to access hidden directories and files via the filebrowser. * Remove --allow-hidden alias * Move allow_hidden option onto ContentsManager * Use try/finally to ensure allow_hidden option is set back to False after test * Allow access to hidden files, but don't list them for now * Simplify hidden check for listing again * Fix indentation
1 parent e4529a4 commit 605eaa7

File tree

6 files changed

+32
-10
lines changed

6 files changed

+32
-10
lines changed

notebook/base/handlers.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,8 @@ def validate_absolute_path(self, root, absolute_path):
612612
"""
613613
abs_path = super(AuthenticatedFileHandler, self).validate_absolute_path(root, absolute_path)
614614
abs_root = os.path.abspath(root)
615-
if is_hidden(abs_path, abs_root):
616-
self.log.info("Refusing to serve hidden file, via 404 Error")
615+
if is_hidden(abs_path, abs_root) and not self.contents_manager.allow_hidden:
616+
self.log.info("Refusing to serve hidden file, via 404 Error, use flag 'ContentsManager.allow_hidden' to enable")
617617
raise web.HTTPError(404)
618618
return abs_path
619619

notebook/files/handlers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def head(self, path):
3434
def get(self, path, include_body=True):
3535
cm = self.contents_manager
3636

37-
if cm.is_hidden(path):
37+
if cm.is_hidden(path) and not cm.allow_hidden:
3838
self.log.info("Refusing to serve hidden file, via 404 Error")
3939
raise web.HTTPError(404)
4040

notebook/services/contents/filemanager.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ def _default_root_dir(self):
7878
return getcwd()
7979

8080
save_script = Bool(False, config=True, help='DEPRECATED, use post_save_hook. Will be removed in Notebook 5.0')
81-
8281
@observe('save_script')
8382
def _update_save_script(self, change):
8483
if not change['new']:
@@ -288,7 +287,7 @@ def _dir_model(self, path, content=True):
288287

289288
if not os.path.isdir(os_path):
290289
raise web.HTTPError(404, four_o_four)
291-
elif is_hidden(os_path, self.root_dir):
290+
elif is_hidden(os_path, self.root_dir) and not self.allow_hidden:
292291
self.log.info("Refusing to serve hidden directory %r, via 404 Error",
293292
os_path
294293
)
@@ -426,7 +425,7 @@ def get(self, path, content=True, type=None, format=None):
426425

427426
def _save_directory(self, os_path, model, path=''):
428427
"""create a directory"""
429-
if is_hidden(os_path, self.root_dir):
428+
if is_hidden(os_path, self.root_dir) and not self.allow_hidden:
430429
raise web.HTTPError(400, u'Cannot create hidden directory %r' % os_path)
431430
if not os.path.exists(os_path):
432431
with self.perm_to_403():

notebook/services/contents/manager.py

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from ipython_genutils.importstring import import_item
2020
from traitlets import (
2121
Any,
22+
Bool,
2223
Dict,
2324
Instance,
2425
List,
@@ -56,6 +57,8 @@ class ContentsManager(LoggingConfigurable):
5657

5758
root_dir = Unicode('/', config=True)
5859

60+
allow_hidden = Bool(False, config=True, help="Allow access to hidden files")
61+
5962
notary = Instance(sign.NotebookNotary)
6063
def _notary_default(self):
6164
return sign.NotebookNotary(parent=self)

notebook/tests/test_files.py

+23-3
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,41 @@ def test_hidden_files(self):
4141
f.write('foo')
4242
with open(pjoin(path, '.foo'), 'w') as f:
4343
f.write('.foo')
44-
44+
4545
for d in not_hidden:
4646
path = pjoin(nbdir, d.replace('/', os.sep))
4747
r = self.request('GET', url_path_join('files', d, 'foo'))
4848
r.raise_for_status()
4949
self.assertEqual(r.text, 'foo')
5050
r = self.request('GET', url_path_join('files', d, '.foo'))
5151
self.assertEqual(r.status_code, 404)
52-
52+
5353
for d in hidden:
5454
path = pjoin(nbdir, d.replace('/', os.sep))
5555
for foo in ('foo', '.foo'):
5656
r = self.request('GET', url_path_join('files', d, foo))
5757
self.assertEqual(r.status_code, 404)
58-
58+
59+
self.notebook.contents_manager.allow_hidden = True
60+
try:
61+
for d in not_hidden:
62+
path = pjoin(nbdir, d.replace('/', os.sep))
63+
r = self.request('GET', url_path_join('files', d, 'foo'))
64+
r.raise_for_status()
65+
self.assertEqual(r.text, 'foo')
66+
r = self.request('GET', url_path_join('files', d, '.foo'))
67+
r.raise_for_status()
68+
self.assertEqual(r.text, '.foo')
69+
70+
for d in hidden:
71+
path = pjoin(nbdir, d.replace('/', os.sep))
72+
for foo in ('foo', '.foo'):
73+
r = self.request('GET', url_path_join('files', d, foo))
74+
r.raise_for_status()
75+
self.assertEqual(r.text, foo)
76+
finally:
77+
self.notebook.contents_manager.allow_hidden = False
78+
5979
def test_contents_manager(self):
6080
"make sure ContentsManager returns right files (ipynb, bin, txt)."
6181

notebook/tree/handlers.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def get(self, path=''):
4040
cm = self.contents_manager
4141

4242
if cm.dir_exists(path=path):
43-
if cm.is_hidden(path):
43+
if cm.is_hidden(path) and not cm.allow_hidden:
4444
self.log.info("Refusing to serve hidden directory, via 404 Error")
4545
raise web.HTTPError(404)
4646
breadcrumbs = self.generate_breadcrumbs(path)

0 commit comments

Comments
 (0)