-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathextract-json-archive.py
More file actions
executable file
·77 lines (58 loc) · 1.99 KB
/
extract-json-archive.py
File metadata and controls
executable file
·77 lines (58 loc) · 1.99 KB
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
76
77
#!/usr/bin/env python3
import argparse
import base64
import json
import locale
import os
from pathlib import Path
import signal
import sys
__version__ = "0.1.0"
def has_colors(fp=sys.stdout):
if os.environ.get("NO_COLOR"):
return False
if os.environ.get("CLICOLOR_FORCE") or os.environ.get("FORCE_COLOR"):
return True
return fp.isatty()
def to_path(root: Path, name: str) -> Path:
name = os.path.normpath(name)
if name.startswith("/") or name.startswith(".."):
raise ValueError(f"cannot evade {root}")
result = root / name
result = result.resolve()
if result.relative_to(root) == Path("."):
raise ValueError(f"cannot evade {root}")
return result
def test_to_path():
import pytest
assert to_path(Path("/foo"), "bar/baz") == Path("/foo/bar/baz")
for invalid in ["/bar", "../bar", "bar/../..", "."]:
with pytest.raises(ValueError):
print(to_path(Path("/foo"), invalid))
def main():
locale.setlocale(locale.LC_ALL, "")
signal.signal(signal.SIGINT, signal.SIG_DFL)
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
parser = argparse.ArgumentParser()
parser.add_argument(
"-o", "--output", type=Path, default=Path.cwd(),
help="Output directory (default: current directory)",
)
parser.add_argument(
"file", type=argparse.FileType(mode="r"), nargs="?",
default=sys.stdin,
)
parser.add_argument("--version", action="version", version=__version__)
args = parser.parse_args()
if args.file.isatty():
print(f"warning: {parser.prog} is reading stdin", file=sys.stderr)
with args.file:
jdata = json.load(args.file)
args.output = args.output.resolve()
for entry in jdata:
print(f"Extracting {entry['filename']!r}")
target = to_path(args.output, entry["filename"])
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(base64.b64decode(entry["data"]))
if __name__ == "__main__":
main()