summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/file.php93
-rw-r--r--public/index.php15
-rw-r--r--public/upload.php12
3 files changed, 113 insertions, 7 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;
+}
diff --git a/public/index.php b/public/index.php
index e4542d8..9226066 100644
--- a/public/index.php
+++ b/public/index.php
@@ -83,9 +83,8 @@ if (FILE_CATALOG_FANCY_VIEW && $file_id) {
');
$stmt->execute([$file_id, $file_ext]);
$file = $stmt->fetch(PDO::FETCH_ASSOC) ?: null;
- $file_exists = is_file(FILE_UPLOAD_DIRECTORY . "/$file_id.$file_ext");
- if (!$file || !$file_exists) {
+ if (!$file) {
http_response_code(404);
exit();
}
@@ -100,7 +99,6 @@ if (FILE_CATALOG_FANCY_VIEW && $file_id) {
$_SESSION['viewed_file_ids'] = $viewed_file_ids;
if (
- $file_exists &&
isset($file['expires_at']) &&
(
($file['expires_at'] == $file['uploaded_at'] && $file['views'] > 1) ||
@@ -223,9 +221,7 @@ $privacy_exists = is_file($_SERVER['DOCUMENT_ROOT'] . '/static/PRIVACY.txt');
<p>Reason: <b><?= $file['ban_reason'] ?></b></p>
<?php endif; ?>
</section>
- <?php endif; ?>
-
- <?php if ($file_exists): ?>
+ <?php else: ?>
<div class="row grow justify-center">
<section class="file-preview-wrapper" <?= isset($file['width']) ? ('style="max-width:' . max($file['width'], 256) . 'px;"') : '' ?>>
<section class="box">
@@ -281,6 +277,13 @@ $privacy_exists = is_file($_SERVER['DOCUMENT_ROOT'] . '/static/PRIVACY.txt');
<audio controls autoplay>
<source src="<?= $file['full_url'] ?>" type="<?= $file['mime'] ?>">
</audio>
+ <?php elseif (HTML_IFRAME_ENABLE && $file["extension"] === "html" && file_exists(sprintf("%s/%s/index.html", FILE_UPLOAD_DIRECTORY, $file["id"]))): ?>
+ <iframe src="<?= sprintf("%s/%s/index.html", FILE_UPLOAD_DIRECTORY_PREFIX, $file["id"]) ?>"
+ width="800" height="600" frameborder="0"></iframe>
+ <?php elseif (HTML_IFRAME_ENABLE && $file["extension"] === "html"): ?>
+ <iframe
+ src="<?= sprintf("%s/%s.%s", FILE_UPLOAD_DIRECTORY_PREFIX, $file["id"], $file["extension"]) ?>"
+ width="800" height="600" frameborder="0"></iframe>
<?php elseif (str_starts_with($file['mime'], 'text/')): ?>
<pre><?= file_get_contents(FILE_UPLOAD_DIRECTORY . "/{$file['id']}.{$file['extension']}") ?></pre>
<?php elseif ($file['mime'] == 'application/x-shockwave-flash' && !empty(RUFFLE_DRIVER_PATH)): ?>
diff --git a/public/upload.php b/public/upload.php
index bfa1990..6eda3c6 100644
--- a/public/upload.php
+++ b/public/upload.php
@@ -214,6 +214,18 @@ try {
unlink($input_path);
}
+ if (
+ ZIPWEBAPP_ENABLE &&
+ $file_data["extension"] === "zip" &&
+ parse_zip_web_archive(
+ $file_path,
+ sprintf("%s/%s", FILE_UPLOAD_DIRECTORY, $file_id),
+ )
+ ) {
+ $file_data["extension"] = "html";
+ $file_data["mime"] = "text/html";
+ }
+
$file_data['size'] = filesize($file_path);
if (FILE_THUMBNAILS && !is_dir(FILE_THUMBNAIL_DIRECTORY) && !mkdir(FILE_THUMBNAIL_DIRECTORY, 0777, true)) {