|
2 | 2 |
|
3 | 3 | from pathlib import PurePath |
4 | 4 |
|
| 5 | +from jupyter_core.paths import jupyter_path |
| 6 | + |
| 7 | +import tornado |
| 8 | + |
5 | 9 |
|
6 | 10 | class SnippetsLoader: |
7 | | - def __init__(self, snippet_dir): |
8 | | - self.snippet_dir = snippet_dir |
| 11 | + def __init__(self): |
| 12 | + self.snippet_paths = jupyter_path("code_snippets") |
9 | 13 |
|
10 | 14 | def collect_snippets(self): |
11 | | - # TODO: handle multiple directories |
12 | | - root = self.snippet_dir |
13 | 15 | snippets = [] |
14 | | - for dirpath, dirnames, filenames in os.walk(root): |
15 | | - for f in filenames: |
16 | | - fullpath = PurePath(dirpath).relative_to(root).joinpath(f) |
17 | | - snippets.append(fullpath.parts) |
| 16 | + for root_path in self.snippet_paths: |
| 17 | + for dirpath, dirnames, filenames in os.walk(root_path): |
| 18 | + for f in filenames: |
| 19 | + fullpath = PurePath(dirpath).relative_to(root_path).joinpath(f) |
| 20 | + |
| 21 | + if fullpath.parts not in snippets: |
| 22 | + snippets.append(fullpath.parts) |
| 23 | + |
18 | 24 | snippets.sort() |
19 | 25 | return snippets |
20 | 26 |
|
21 | 27 | def get_snippet_content(self, snippet): |
22 | 28 | try: |
23 | | - path = os.path.join(self.snippet_dir, *snippet) |
24 | | - with open(path) as f: |
25 | | - content = f.read() |
26 | | - except: |
27 | | - content = '' |
| 29 | + for root_path in self.snippet_paths: |
| 30 | + path = os.path.join(root_path, *snippet) |
| 31 | + |
| 32 | + # Prevent access to the entire file system when the path contains '..' |
| 33 | + accessible = os.path.realpath(path).startswith(root_path) |
28 | 34 |
|
29 | | - return content |
| 35 | + if accessible and os.path.isfile(path): |
| 36 | + with open(path) as f: |
| 37 | + return f.read() |
| 38 | + except: |
| 39 | + raise tornado.web.HTTPError(status_code=500) |
30 | 40 |
|
| 41 | + raise tornado.web.HTTPError(status_code=404) |
0 commit comments