false, 'error' => $message ], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); exit; } // CORS if (isset($_SERVER['HTTP_ORIGIN'])) { header("Access-Control-Allow-Origin: {$_SERVER['HTTP_ORIGIN']}"); header('Access-Control-Allow-Credentials: true'); header('Access-Control-Max-Age: 86400'); } if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') { if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'])) { header("Access-Control-Allow-Methods: GET, POST, OPTIONS"); } if (isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) { header("Access-Control-Allow-Headers: {$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']}"); } exit(0); } // Vérifier la méthode HTTP if ($_SERVER['REQUEST_METHOD'] !== 'GET') { sendError('Méthode non autorisée. Utilisez GET.', 405); } // Initialiser la session try { $sessionId = SessionManager::init(); Config::log("Extract API - Session : {$sessionId}"); } catch (Exception $e) { sendError('Erreur initialisation session : ' . $e->getMessage(), 500); } // Vérifier les paramètres if (!isset($_GET['side']) || !in_array($_GET['side'], ['left', 'right'])) { sendError('Paramètre "side" manquant ou invalide. Valeurs acceptées : "left", "right".'); } if (!isset($_GET['path']) || empty($_GET['path'])) { sendError('Paramètre "path" manquant. Spécifiez le chemin du fichier dans le ZIP.'); } $side = $_GET['side']; $filePath = $_GET['path']; // Sanitize le chemin pour la sécurité $filePath = Config::sanitizePath($filePath); Config::log("Extraction demandée : {$filePath} depuis {$side}"); $uploadDir = SessionManager::getUploadDir($sessionId); $zipPath = $uploadDir . $side . '.zip'; // Vérifier que le ZIP existe if (!file_exists($zipPath)) { sendError("ZIP '{$side}' non uploadé.", 404); } // Extraire le fichier $zipHandler = new ZipHandler(); $tempOutputPath = $uploadDir . 'temp_extract_' . basename($filePath); try { $success = $zipHandler->extractFile($zipPath, $filePath, $tempOutputPath); if (!$success) { throw new Exception("Fichier introuvable dans le ZIP"); } // Vérifier que le fichier a été extrait if (!file_exists($tempOutputPath)) { throw new Exception("Échec extraction du fichier"); } $fileSize = filesize($tempOutputPath); Config::log("Fichier extrait : " . Config::formatBytes($fileSize)); // Mettre à jour le timestamp SessionManager::updateAccess($sessionId); // Déterminer le type MIME $finfo = finfo_open(FILEINFO_MIME_TYPE); $mimeType = finfo_file($finfo, $tempOutputPath); finfo_close($finfo); // Nom de fichier pour le téléchargement $downloadName = basename($filePath); // Headers pour téléchargement header('Content-Type: ' . $mimeType); header('Content-Disposition: attachment; filename="' . $downloadName . '"'); header('Content-Length: ' . $fileSize); header('Cache-Control: no-cache, must-revalidate'); header('Pragma: no-cache'); header('Expires: 0'); // Stream le fichier $handle = fopen($tempOutputPath, 'rb'); if ($handle === false) { throw new Exception("Impossible d'ouvrir le fichier extrait"); } while (!feof($handle)) { echo fread($handle, Config::STREAM_BUFFER_SIZE); flush(); } fclose($handle); // Nettoyer le fichier temporaire unlink($tempOutputPath); Config::log("Fichier téléchargé : {$downloadName}"); exit; } catch (Exception $e) { // Nettoyer le fichier temporaire en cas d'erreur if (file_exists($tempOutputPath)) { unlink($tempOutputPath); } sendError('Erreur lors de l\'extraction : ' . $e->getMessage(), 500); }