Files
FileRise/restoreFiles.php

175 lines
6.1 KiB
PHP

<?php
require_once 'config.php';
header('Content-Type: application/json');
// --- CSRF Protection ---
$headers = array_change_key_case(getallheaders(), CASE_LOWER);
$receivedToken = isset($headers['x-csrf-token']) ? trim($headers['x-csrf-token']) : '';
if ($receivedToken !== $_SESSION['csrf_token']) {
echo json_encode(["error" => "Invalid CSRF token"]);
http_response_code(403);
exit;
}
// Ensure user is authenticated
if (!isset($_SESSION['authenticated']) || $_SESSION['authenticated'] !== true) {
echo json_encode(["error" => "Unauthorized"]);
http_response_code(401);
exit;
}
// Define the trash directory and trash metadata file.
$trashDir = rtrim(TRASH_DIR, '/\\') . DIRECTORY_SEPARATOR;
if (!file_exists($trashDir)) {
mkdir($trashDir, 0755, true);
}
$trashMetadataFile = $trashDir . "trash.json";
$trashData = [];
if (file_exists($trashMetadataFile)) {
$json = file_get_contents($trashMetadataFile);
$trashData = json_decode($json, true);
if (!is_array($trashData)) {
$trashData = [];
}
}
// Helper: Generate the metadata file path for a given folder.
// For "root", returns "root_metadata.json". Otherwise, replaces slashes, backslashes, and spaces with dashes and appends "_metadata.json".
function getMetadataFilePath($folder) {
if (strtolower($folder) === 'root' || $folder === '') {
return META_DIR . "root_metadata.json";
}
return META_DIR . str_replace(['/', '\\', ' '], '-', $folder) . '_metadata.json';
}
// Read request body.
$data = json_decode(file_get_contents("php://input"), true);
// Validate request.
if (!isset($data['files']) || !is_array($data['files'])) {
echo json_encode(["error" => "No file or folder identifiers provided"]);
exit;
}
// Define a safe file name pattern.
$safeFileNamePattern = '/^[A-Za-z0-9_\-\.\(\) ]+$/';
$restoredItems = [];
$errors = [];
foreach ($data['files'] as $trashFileName) {
$trashFileName = trim($trashFileName);
if (!preg_match($safeFileNamePattern, $trashFileName)) {
$errors[] = "$trashFileName has an invalid format.";
continue;
}
// Find the matching trash record.
$recordKey = null;
foreach ($trashData as $key => $record) {
if (isset($record['trashName']) && $record['trashName'] === $trashFileName) {
$recordKey = $key;
break;
}
}
if ($recordKey === null) {
$errors[] = "No trash record found for $trashFileName.";
continue;
}
$record = $trashData[$recordKey];
if (!isset($record['originalFolder']) || !isset($record['originalName'])) {
$errors[] = "Incomplete trash record for $trashFileName.";
continue;
}
$originalFolder = $record['originalFolder'];
$originalName = $record['originalName'];
// Convert the absolute original folder to a relative folder.
$relativeFolder = 'root';
if (strpos($originalFolder, UPLOAD_DIR) === 0) {
$relativeFolder = trim(substr($originalFolder, strlen(UPLOAD_DIR)), '/\\');
if ($relativeFolder === '') {
$relativeFolder = 'root';
}
}
// Build destination path.
if ($relativeFolder !== 'root') {
$destinationPath = rtrim(UPLOAD_DIR, '/\\') . DIRECTORY_SEPARATOR . $relativeFolder . DIRECTORY_SEPARATOR . $originalName;
} else {
$destinationPath = rtrim(UPLOAD_DIR, '/\\') . DIRECTORY_SEPARATOR . $originalName;
}
// If the record is for a folder, recreate the folder.
if (isset($record['type']) && $record['type'] === 'folder') {
if (!file_exists($destinationPath)) {
if (mkdir($destinationPath, 0755, true)) {
$restoredItems[] = $originalName . " (folder restored)";
} else {
$errors[] = "Failed to restore folder $originalName.";
continue;
}
} else {
$errors[] = "Folder already exists at destination: $originalName.";
continue;
}
// Remove the trash record and continue.
unset($trashData[$recordKey]);
continue;
}
// For files: Ensure the destination directory exists.
$destinationDir = dirname($destinationPath);
if (!file_exists($destinationDir)) {
if (!mkdir($destinationDir, 0755, true)) {
$errors[] = "Failed to create destination folder for $originalName.";
continue;
}
}
if (file_exists($destinationPath)) {
$errors[] = "File already exists at destination: $originalName.";
continue;
}
// Move the file from trash to its original location.
$sourcePath = $trashDir . $trashFileName;
if (file_exists($sourcePath)) {
if (rename($sourcePath, $destinationPath)) {
$restoredItems[] = $originalName;
// Update metadata for the restored file.
$metadataFile = getMetadataFilePath($relativeFolder);
$metadata = [];
if (file_exists($metadataFile)) {
$metadata = json_decode(file_get_contents($metadataFile), true);
if (!is_array($metadata)) {
$metadata = [];
}
}
$restoredMeta = [
"uploaded" => isset($record['uploaded']) ? $record['uploaded'] : date(DATE_TIME_FORMAT),
"uploader" => isset($record['uploader']) ? $record['uploader'] : "Unknown"
];
$metadata[$originalName] = $restoredMeta;
file_put_contents($metadataFile, json_encode($metadata, JSON_PRETTY_PRINT));
unset($trashData[$recordKey]);
} else {
$errors[] = "Failed to restore $originalName.";
}
} else {
$errors[] = "Trash file not found: $trashFileName.";
}
}
// Write back updated trash metadata.
file_put_contents($trashMetadataFile, json_encode(array_values($trashData), JSON_PRETTY_PRINT));
if (empty($errors)) {
echo json_encode(["success" => "Items restored: " . implode(", ", $restoredItems)]);
} else {
echo json_encode(["error" => implode("; ", $errors) . ". Items restored: " . implode(", ", $restoredItems)]);
}
exit;
?>