mirror of
https://github.com/Cesarus85/ringfall-mjolnir-vr.git
synced 2026-10-27 10:00:40 +01:00
84 lines
2.9 KiB
Python
84 lines
2.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Embeds a dedicated server's admin page (port/assets/server_ui: index.html,
|
|
app.js, app.css, icon.svg) in the game as C data, for its web port
|
|
(port/linux/src/server_http.c):
|
|
|
|
python tools/server_ui_embed.py OUTPUT.c
|
|
|
|
Each file is checked first against what the page's Content-Security-Policy
|
|
(default-src 'self') would block, or the project forbids: inline scripts and
|
|
styles, style= and on*= attributes, string evaluation, external requests
|
|
(tools/server_sim.py's csp_problems). A file that breaks one stops the build.
|
|
The Linux and Windows builds generate it; the Android and web builds have no
|
|
dedicated server.
|
|
"""
|
|
|
|
import hashlib
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
ROOT = Path(__file__).resolve().parent.parent
|
|
UI = Path("port/assets/server_ui")
|
|
FILES = (
|
|
("index.html", "text/html; charset=utf-8"),
|
|
("app.js", "text/javascript; charset=utf-8"),
|
|
("app.css", "text/css; charset=utf-8"),
|
|
("icon.svg", "image/svg+xml"),
|
|
)
|
|
|
|
sys.path.insert(0, str(ROOT / "tools"))
|
|
from server_sim import csp_problems # noqa: E402
|
|
|
|
|
|
def inputs():
|
|
"""the files the generated C depends on"""
|
|
return [UI / name for name, _ in FILES if (ROOT / UI / name).is_file()]
|
|
|
|
|
|
def main() -> None:
|
|
if len(sys.argv) != 2:
|
|
sys.exit("usage: server_ui_embed.py OUTPUT.c")
|
|
lines = [
|
|
"/* generated by tools/server_ui_embed.py from port/assets/server_ui: do not edit */",
|
|
"",
|
|
"struct server_ui_asset",
|
|
"{",
|
|
"\tconst char *path;",
|
|
"\tconst char *content_type;",
|
|
"\tconst unsigned char *data;",
|
|
"\tunsigned long size;",
|
|
"\tconst char *etag;",
|
|
"};",
|
|
"",
|
|
]
|
|
table = []
|
|
problems = []
|
|
for index, (name, content_type) in enumerate(FILES):
|
|
path = ROOT / UI / name
|
|
if not path.is_file():
|
|
continue
|
|
data = path.read_bytes()
|
|
problems += [f"{UI / name}: {problem}" for problem in csp_problems(name, data.decode("utf-8"))]
|
|
etag = hashlib.sha256(data).hexdigest()[:16]
|
|
lines.append(f"static const unsigned char server_ui_file_{index}[] =")
|
|
lines.append("{")
|
|
for start in range(0, len(data), 24):
|
|
lines.append("\t" + ", ".join(str(byte) for byte in data[start:start + 24]) + ",")
|
|
lines.append("\t0")
|
|
lines.append("};")
|
|
table.append(f'\t{{ "{name}", "{content_type}", server_ui_file_{index}, {len(data)}UL, "{etag}" }},')
|
|
if problems:
|
|
sys.exit("the admin page breaks its Content-Security-Policy:\n " + "\n ".join(problems))
|
|
lines.append("")
|
|
lines.append("const struct server_ui_asset server_ui_assets[] =")
|
|
lines.append("{")
|
|
lines += table or ['\t{ "", "", 0, 0, "" },']
|
|
lines.append("};")
|
|
lines.append(f"const unsigned long server_ui_asset_count = {len(table)}UL;")
|
|
Path(sys.argv[1]).parent.mkdir(parents=True, exist_ok=True)
|
|
Path(sys.argv[1]).write_text("\n".join(lines) + "\n")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|