summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/file.php93
1 files changed, 92 insertions, 1 deletions
diff --git a/lib/file.php b/lib/file.php
index ebfc009..65a2abe 100644
--- a/lib/file.php
+++ b/lib/file.php
@@ -150,4 +150,95 @@ function remove_video_letterbox(string $input_path, string $output_path)
exec("ffmpeg -nostdin -i $input_path -vf $area -c:a copy $output_path 2>&1", $output, $code);
return $code == 0;
-} \ No newline at end of file
+}
+
+function parse_zip_web_archive(string $input_path, string $output_path)
+{
+ $allowed_extensions = [
+ "html",
+ "js",
+ "css",
+ "png",
+ "jpg",
+ "jpeg",
+ "gif",
+ "mp3",
+ "ogg",
+ "wasm",
+ "atlas",
+ "skin",
+ "txt",
+ "fnt",
+ "json",
+ "glb",
+ "glsl",
+ "map",
+ "teavmdbg",
+ "xml",
+ "ds_store",
+ ];
+ $max_total_uncompressed = 128 * 1024 * 1024;
+ $max_file_size = 32 * 1024 * 1024;
+
+ $zip = new ZipArchive();
+ if ($zip->open($input_path) !== true) {
+ throw new RuntimeException("Invalid ZIP");
+ }
+
+ $is_webapp = false;
+ for ($i = 0; $i < $zip->numFiles; $i++) {
+ $stat = $zip->statIndex($i);
+ $is_webapp = $stat["name"] == "index.html";
+ if ($is_webapp) {
+ break;
+ }
+ }
+
+ if (!$is_webapp) {
+ $zip->close();
+ return $is_webapp;
+ }
+
+ $total_uncompressed = 0;
+ for ($i = 0; $i < $zip->numFiles; $i++) {
+ $stat = $zip->statIndex($i);
+ $path = $stat["name"];
+ if (strpos($path, "..") !== false) {
+ throw new RuntimeException("Invalid file path");
+ }
+
+ if (
+ strpos($path, "__MACOSX/") === 0 ||
+ (basename($path)[0] === "." &&
+ strstr(basename($path), 0, 2) === "._")
+ ) {
+ continue;
+ }
+
+ $ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
+ error_log($ext);
+ if (!in_array($ext, $allowed_extensions) && $stat["size"] > 0) {
+ throw new RuntimeException(
+ "Forbidden file type in the archive: $path",
+ );
+ }
+
+ $total_uncompressed += $stat["size"];
+ if (
+ $total_uncompressed > $max_total_uncompressed ||
+ $stat["size"] > $max_file_size
+ ) {
+ throw new RuntimeException("ZIP too large when uncompressed");
+ }
+ }
+
+ mkdir($output_path, 0755, true);
+ if (!$zip->extractTo($output_path)) {
+ rmdir($output_path);
+ throw new RuntimeException("ZIP extraction failed");
+ }
+
+ $zip->close();
+
+ return $is_webapp;
+}