Initial commit: FuZip - Application de fusion interactive de fichiers ZIP
- 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
This commit is contained in:
190
core/Config.php
Normal file
190
core/Config.php
Normal file
@@ -0,0 +1,190 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user