-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFetchClientFile.py
75 lines (58 loc) · 2.37 KB
/
FetchClientFile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
#!/usr/bin/env python
"""Retrieve a file from the CDR client set.
"""
from cdrcgi import Controller
from functools import cached_property
from pathlib import Path
from sys import stdout
class Control(Controller):
"""Access to the current CDR login session and page-building tools."""
SUBTITLE = "Fetch Client File"
LOGNAME = "FetchClientFile"
def populate_form(self, page):
"""Prompt for the file and an optional comment.
Pass:
page - HTMLPage on which we place the fields
"""
fieldset = page.fieldset("Select File")
fieldset.append(page.select("path", options=self.paths))
page.form.append(fieldset)
def show_report(self):
"""Send the selected file back to the browser."""
if self.path:
path = self.client_files / self.path
if "/.." in str(path) or "\\.." in str(path):
self.logger.warning("suspected hacking with path %s", path)
self.bail()
try:
file_bytes = path.read_bytes()
except Exception as e:
self.logger.exception("reading %s", path)
self.bail(f"{path}: {e}")
self.logger.info("fetching %s", path)
headers = "\r\n".join([
"Content-Type: application/octet-stream",
f"Content-Disposition: attachment; filename={path.name}",
f"Content-Length: {len(file_bytes)}",
]) + "\r\n\r\n"
stdout.buffer.write(headers.encode("utf-8"))
if file_bytes:
stdout.buffer.write(file_bytes)
@cached_property
def client_files(self):
"""Location where the client files are stored."""
return Path(self.session.tier.basedir, "ClientFiles")
@cached_property
def path(self):
"""Relative path to the file selected for deletion."""
return self.fields.getvalue("path")
@cached_property
def paths(self):
"""List of client files installed on the CDR Server."""
paths = [p for p in self.client_files.rglob("*") if p.is_file()]
paths = [p.relative_to(self.client_files) for p in paths]
paths = [str(p) for p in paths]
return [["", "- Select file -"]] + sorted(paths, key=str.lower)
if __name__ == "__main__":
"""Don't execute the script if loaded as a module."""
Control().run()