- Backend PHP: architecture MVC avec API REST (upload, merge, preview, extract) - Frontend JavaScript: composants modulaires (arborescence, upload, themes, i18n) - Fonctionnalités: drag&drop, sélection exclusive, détection conflits, persistance état - Sécurité: validation stricte, isolation sessions, sanitization chemins - UI/UX: responsive, thèmes clair/sombre, multi-langue (FR/EN) - Documentation: README complet avec installation et utilisation
136 lines
4.0 KiB
PHP
136 lines
4.0 KiB
PHP
<?php
|
|
/**
|
|
* API Preview - Prévisualisation du contenu d'un fichier
|
|
*
|
|
* Endpoint : GET /api/preview.php
|
|
*
|
|
* Paramètres :
|
|
* - side : 'left' ou 'right'
|
|
* - path : Chemin du fichier dans le ZIP
|
|
* - max_length : (optionnel) Longueur max en octets (défaut: 10000)
|
|
*
|
|
* Réponse JSON :
|
|
* {
|
|
* "success": true,
|
|
* "content": "...",
|
|
* "is_binary": false,
|
|
* "truncated": false
|
|
* }
|
|
*
|
|
* Fonctionnalité : Option A du plan (Prévisualisation contenu fichiers)
|
|
*/
|
|
|
|
header('Content-Type: application/json; charset=utf-8');
|
|
|
|
// 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);
|
|
}
|
|
|
|
require_once __DIR__ . '/../core/Config.php';
|
|
require_once __DIR__ . '/../core/SessionManager.php';
|
|
require_once __DIR__ . '/../core/ZipHandler.php';
|
|
|
|
function sendResponse(array $data, int $httpCode = 200): void {
|
|
http_response_code($httpCode);
|
|
echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
|
exit;
|
|
}
|
|
|
|
function sendError(string $message, int $httpCode = 400): void {
|
|
Config::log("Erreur API preview : {$message}", 'ERROR');
|
|
sendResponse([
|
|
'success' => false,
|
|
'error' => $message
|
|
], $httpCode);
|
|
}
|
|
|
|
// 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("Preview 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'];
|
|
$maxLength = isset($_GET['max_length']) ? (int)$_GET['max_length'] : 10000;
|
|
|
|
// Limiter la longueur max pour éviter surcharge
|
|
$maxLength = min($maxLength, 50000); // Max 50 KB
|
|
|
|
// Sanitize le chemin
|
|
$filePath = Config::sanitizePath($filePath);
|
|
|
|
Config::log("Prévisualisation demandée : {$filePath} depuis {$side} (max: {$maxLength} octets)");
|
|
|
|
$uploadDir = SessionManager::getUploadDir($sessionId);
|
|
$zipPath = $uploadDir . $side . '.zip';
|
|
|
|
// Vérifier que le ZIP existe
|
|
if (!file_exists($zipPath)) {
|
|
sendError("ZIP '{$side}' non uploadé.", 404);
|
|
}
|
|
|
|
// Prévisualiser le fichier
|
|
$zipHandler = new ZipHandler();
|
|
|
|
try {
|
|
$content = $zipHandler->previewFile($zipPath, $filePath, $maxLength);
|
|
|
|
if ($content === null) {
|
|
throw new Exception("Fichier introuvable dans le ZIP");
|
|
}
|
|
|
|
// Déterminer si c'est un fichier binaire
|
|
$isBinary = strpos($content, '[Fichier binaire - prévisualisation impossible]') === 0;
|
|
|
|
// Déterminer si le contenu a été tronqué
|
|
$truncated = strpos($content, '... (tronqué)') !== false;
|
|
|
|
// Mettre à jour le timestamp
|
|
SessionManager::updateAccess($sessionId);
|
|
|
|
Config::log("Prévisualisation envoyée : " . strlen($content) . " caractères");
|
|
|
|
sendResponse([
|
|
'success' => true,
|
|
'file_path' => $filePath,
|
|
'side' => $side,
|
|
'content' => $content,
|
|
'is_binary' => $isBinary,
|
|
'truncated' => $truncated,
|
|
'content_length' => strlen($content)
|
|
]);
|
|
|
|
} catch (Exception $e) {
|
|
sendError('Erreur lors de la prévisualisation : ' . $e->getMessage(), 500);
|
|
}
|