- 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
191 lines
5.5 KiB
PHP
191 lines
5.5 KiB
PHP
<?php
|
|
/**
|
|
* Configuration globale de FuZip
|
|
*
|
|
* Ce fichier contient toutes les constantes de configuration
|
|
* pour l'application de fusion de fichiers ZIP.
|
|
*/
|
|
|
|
class Config {
|
|
/**
|
|
* Taille maximale d'un fichier ZIP en octets (500 MB)
|
|
* Modifié selon les besoins spécifiés dans le plan
|
|
*/
|
|
const MAX_FILE_SIZE = 500 * 1024 * 1024; // 500 MB
|
|
|
|
/**
|
|
* Durée de vie d'une session en secondes (24 heures)
|
|
* Après ce délai, les dossiers de session sont supprimés
|
|
*/
|
|
const SESSION_LIFETIME = 24 * 3600; // 24 heures
|
|
|
|
/**
|
|
* Chemin absolu vers le dossier uploads
|
|
* Utilise DIRECTORY_SEPARATOR pour compatibilité multi-plateforme
|
|
*/
|
|
const UPLOAD_DIR = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'uploads' . DIRECTORY_SEPARATOR;
|
|
|
|
/**
|
|
* Extensions de fichiers interdites dans les ZIP
|
|
* Pour des raisons de sécurité
|
|
*/
|
|
const FORBIDDEN_EXTENSIONS = [
|
|
'exe', 'bat', 'sh', 'ps1', 'php', 'phtml',
|
|
'php3', 'php4', 'php5', 'phps', 'cgi'
|
|
];
|
|
|
|
/**
|
|
* Types MIME autorisés pour les uploads
|
|
*/
|
|
const ALLOWED_MIME_TYPES = [
|
|
'application/zip',
|
|
'application/x-zip',
|
|
'application/x-zip-compressed',
|
|
'application/octet-stream' // Parfois utilisé pour les ZIP
|
|
];
|
|
|
|
/**
|
|
* Signatures magiques des fichiers ZIP (magic bytes)
|
|
* Pour vérifier l'authenticité du fichier
|
|
*/
|
|
const ZIP_MAGIC_BYTES = [
|
|
'504B0304', // PK.. (ZIP standard)
|
|
'504B0506', // PK.. (ZIP vide)
|
|
'504B0708' // PK.. (ZIP spanned)
|
|
];
|
|
|
|
/**
|
|
* Nombre maximum de fichiers par ZIP
|
|
* Pour éviter les problèmes de performance
|
|
*/
|
|
const MAX_FILES_PER_ZIP = 10000;
|
|
|
|
/**
|
|
* Profondeur maximale de l'arborescence
|
|
* Pour éviter les problèmes de récursion
|
|
*/
|
|
const MAX_TREE_DEPTH = 50;
|
|
|
|
/**
|
|
* Timeout pour le traitement d'un ZIP (en secondes)
|
|
*/
|
|
const PROCESSING_TIMEOUT = 300; // 5 minutes
|
|
|
|
/**
|
|
* Taille du buffer pour le streaming de fichiers
|
|
*/
|
|
const STREAM_BUFFER_SIZE = 8192; // 8 KB
|
|
|
|
/**
|
|
* Langues supportées
|
|
*/
|
|
const SUPPORTED_LANGUAGES = ['fr', 'en'];
|
|
|
|
/**
|
|
* Langue par défaut
|
|
*/
|
|
const DEFAULT_LANGUAGE = 'fr';
|
|
|
|
/**
|
|
* Mode debug (activer les logs détaillés)
|
|
* À désactiver en production
|
|
*/
|
|
const DEBUG_MODE = true;
|
|
|
|
/**
|
|
* Chemin vers le fichier de log
|
|
*/
|
|
const LOG_FILE = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'fuzip_debug.log';
|
|
|
|
/**
|
|
* Obtient le chemin complet normalisé du dossier uploads
|
|
*
|
|
* @return string Chemin absolu vers uploads/
|
|
*/
|
|
public static function getUploadDir(): string {
|
|
$path = realpath(self::UPLOAD_DIR);
|
|
if ($path === false) {
|
|
// Si le dossier n'existe pas encore, le créer
|
|
if (!file_exists(self::UPLOAD_DIR)) {
|
|
mkdir(self::UPLOAD_DIR, 0755, true);
|
|
}
|
|
$path = realpath(self::UPLOAD_DIR);
|
|
}
|
|
return $path . DIRECTORY_SEPARATOR;
|
|
}
|
|
|
|
/**
|
|
* Vérifie si une extension de fichier est interdite
|
|
*
|
|
* @param string $filename Nom du fichier
|
|
* @return bool True si l'extension est interdite
|
|
*/
|
|
public static function isForbiddenExtension(string $filename): bool {
|
|
$extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
|
|
return in_array($extension, self::FORBIDDEN_EXTENSIONS);
|
|
}
|
|
|
|
/**
|
|
* Vérifie si un type MIME est autorisé
|
|
*
|
|
* @param string $mimeType Type MIME à vérifier
|
|
* @return bool True si le type MIME est autorisé
|
|
*/
|
|
public static function isAllowedMimeType(string $mimeType): bool {
|
|
return in_array($mimeType, self::ALLOWED_MIME_TYPES);
|
|
}
|
|
|
|
/**
|
|
* Log un message (si DEBUG_MODE activé)
|
|
*
|
|
* @param string $message Message à logger
|
|
* @param string $level Niveau (INFO, WARNING, ERROR)
|
|
*/
|
|
public static function log(string $message, string $level = 'INFO'): void {
|
|
if (!self::DEBUG_MODE) {
|
|
return;
|
|
}
|
|
|
|
$timestamp = date('Y-m-d H:i:s');
|
|
$logMessage = "[{$timestamp}] [{$level}] {$message}" . PHP_EOL;
|
|
|
|
file_put_contents(self::LOG_FILE, $logMessage, FILE_APPEND);
|
|
}
|
|
|
|
/**
|
|
* Convertit une taille en octets en format lisible
|
|
*
|
|
* @param int $bytes Taille en octets
|
|
* @return string Taille formatée (ex: "2.5 MB")
|
|
*/
|
|
public static function formatBytes(int $bytes): string {
|
|
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
|
|
$bytes = max($bytes, 0);
|
|
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
|
|
$pow = min($pow, count($units) - 1);
|
|
$bytes /= (1 << (10 * $pow));
|
|
|
|
return round($bytes, 2) . ' ' . $units[$pow];
|
|
}
|
|
|
|
/**
|
|
* Sanitize un nom de fichier/dossier
|
|
* Retire les caractères dangereux et les séquences ..
|
|
*
|
|
* @param string $name Nom à sanitizer
|
|
* @return string Nom nettoyé
|
|
*/
|
|
public static function sanitizePath(string $name): string {
|
|
// Retirer les séquences dangereuses
|
|
$name = str_replace(['..', '\\', chr(0)], '', $name);
|
|
|
|
// Garder seulement les caractères alphanumériques, espaces, tirets, underscores, points et slashes
|
|
$name = preg_replace('/[^a-zA-Z0-9\s\-_\.\/]/', '', $name);
|
|
|
|
// Retirer les slashes multiples
|
|
$name = preg_replace('#/+#', '/', $name);
|
|
|
|
return trim($name);
|
|
}
|
|
}
|