Add upload overwrite confirmation

This commit is contained in:
Mikei386
2026-06-23 22:18:39 +02:00
parent 76fc7e7251
commit aa58014cd7
6 changed files with 60 additions and 12 deletions
@@ -12,10 +12,11 @@ if (($_POST['uploadMode'] ?? '') === 'chunk') {
$chunkIndex = filter_var($_POST['chunkIndex'] ?? null, FILTER_VALIDATE_INT);
$totalChunks = filter_var($_POST['totalChunks'] ?? null, FILTER_VALIDATE_INT);
$encoded = (string)($_POST['data'] ?? '');
$overwrite = unav_upload_bool($_POST['overwrite'] ?? false);
if ($relativeName === '' || $chunkIndex === false || $totalChunks === false || $chunkIndex < 0 || $totalChunks < 1 || $chunkIndex >= $totalChunks) {
unav_error(400, 'Invalid upload chunk');
}
$destination = unav_prepare_upload_destination($target['path'], $relativeName);
$destination = unav_prepare_upload_destination($target['path'], $relativeName, $overwrite);
$temporary = $destination['path'] . '.u-nav-upload';
if ($chunkIndex === 0) {
@unlink($temporary);
@@ -30,6 +31,16 @@ if (($_POST['uploadMode'] ?? '') === 'chunk') {
unav_error(500, 'Could not write upload chunk');
}
$complete = $chunkIndex === $totalChunks - 1;
if ($complete && file_exists($destination['path'])) {
if (!$overwrite) {
@unlink($temporary);
unav_error(409, 'Destination already exists');
}
if (is_dir($destination['path']) || !@unlink($destination['path'])) {
@unlink($temporary);
unav_error(409, 'Destination cannot be overwritten');
}
}
if ($complete && !rename($temporary, $destination['path'])) {
@unlink($temporary);
unav_error(500, 'Could not finalize upload');
@@ -47,7 +58,11 @@ if (($_POST['uploadMode'] ?? '') === 'chunk') {
if (isset($_GET['relativePath']) || isset($_SERVER['HTTP_X_UNAV_RELATIVE_PATH'])) {
$relativeName = (string)($_GET['relativePath'] ?? $_SERVER['HTTP_X_UNAV_RELATIVE_PATH']);
$destination = unav_prepare_upload_destination($target['path'], $relativeName);
$overwrite = unav_upload_bool($_GET['overwrite'] ?? ($_SERVER['HTTP_X_UNAV_OVERWRITE'] ?? false));
$destination = unav_prepare_upload_destination($target['path'], $relativeName, $overwrite);
if ($overwrite && file_exists($destination['path']) && !is_dir($destination['path']) && !@unlink($destination['path'])) {
unav_error(409, 'Destination cannot be overwritten');
}
$bytes = file_put_contents($destination['path'], file_get_contents('php://input'), LOCK_EX);
if ($bytes === false) {
unav_error(500, 'Could not store uploaded file');
@@ -61,6 +76,7 @@ if (isset($_GET['relativePath']) || isset($_SERVER['HTTP_X_UNAV_RELATIVE_PATH'])
}
$uploaded = [];
$overwrite = unav_upload_bool($_POST['overwrite'] ?? false);
$names = unav_upload_array($_FILES['files']['name'] ?? []);
$errors = unav_upload_array($_FILES['files']['error'] ?? []);
$tmpNames = unav_upload_array($_FILES['files']['tmp_name'] ?? []);
@@ -70,7 +86,10 @@ foreach ($names as $index => $name) {
unav_error(400, 'Upload failed');
}
$relativeName = $relativePaths[$index] ?? $name;
$destination = unav_prepare_upload_destination($target['path'], (string)$relativeName);
$destination = unav_prepare_upload_destination($target['path'], (string)$relativeName, $overwrite);
if ($overwrite && file_exists($destination['path']) && !is_dir($destination['path']) && !@unlink($destination['path'])) {
unav_error(409, 'Destination cannot be overwritten');
}
if (!move_uploaded_file($tmpNames[$index] ?? '', $destination['path'])) {
unav_error(500, 'Could not store uploaded file');
}
@@ -82,7 +101,7 @@ foreach ($names as $index => $name) {
unav_json(['uploaded' => $uploaded], 201);
function unav_prepare_upload_destination(string $targetPath, string $relativeName): array {
function unav_prepare_upload_destination(string $targetPath, string $relativeName, bool $overwrite = false): array {
$safeName = unav_upload_safe_relative_path($relativeName);
$relativeParent = dirname($safeName);
if ($relativeParent !== '.') {
@@ -94,7 +113,12 @@ function unav_prepare_upload_destination(string $targetPath, string $relativeNam
}
$destination = unav_destination_path($targetPath . '/' . $safeName);
if (file_exists($destination['path'])) {
unav_error(409, 'Destination already exists');
if (!$overwrite) {
unav_error(409, 'Destination already exists');
}
if (is_dir($destination['path'])) {
unav_error(409, 'Destination directory already exists');
}
}
if (!is_dir(dirname($destination['path']))) {
unav_error(500, 'Could not create upload directory');
@@ -126,3 +150,7 @@ function unav_upload_safe_relative_path(string $name): string {
}
return implode('/', $parts);
}
function unav_upload_bool($value): bool {
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
}