/** * Configuration complète de la plateforme * Évaluation de Départ Obligatoire * Version sécurisée et sans warnings de session */ // ------------------------- // RAPPORT D'ERREURS // ------------------------- error_reporting(E_ALL); ini_set('display_errors', 1); ini_set('log_errors', 1); ini_set('error_log', __DIR__ . '/error.log'); // ------------------------- // SESSION // ------------------------- // Définir les paramètres uniquement si la session n'est pas déjà active if (session_status() === PHP_SESSION_NONE) { ini_set('session.cookie_httponly', 1); ini_set('session.use_strict_mode', 1); ini_set('session.cookie_samesite', 'Lax'); ini_set('session.gc_maxlifetime', 3600); session_start(); } // ------------------------- // CONFIGURATION DE LA BASE DE DONNÉES // ------------------------- define('DB_HOST', 'autosctsaad.mysql.db'); define('DB_USER', 'autosctsaad); define('DB_PASS', 'Saadaitouali1988'); define('DB_NAME', 'autosctsaad); // ------------------------- // CONFIGURATION APPLICATION // ------------------------- define('APP_NAME', 'Évaluation de Départ Autoschool'); define('APP_URL', 'https://evaluation.autoschool34.fr'); define('APP_DEBUG', false); // Désactivé pour la production define('SESSION_TIMEOUT', 3600); // 1 heure // ------------------------- // VARIABLE PDO GLOBALE // ------------------------- $pdo = null; /** * Connexion PDO sécurisée */ function get_database_connection() { static $local_pdo = null; if ($local_pdo === null) { try { $local_pdo = new PDO( 'mysql:host=' . DB_HOST . ';dbname=' . DB_NAME . ';charset=utf8mb4', DB_USER, DB_PASS, [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_EMULATE_PREPARES => false, PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci" ] ); log_error("✅ Connexion à la base de données réussie"); } catch (PDOException $e) { log_error("❌ ERREUR CRITIQUE - Connexion BDD: " . $e->getMessage()); json_response([ 'success' => false, 'error' => APP_DEBUG ? $e->getMessage() : 'Erreur de connexion au serveur' ], 500); } } return $local_pdo; } // Création de la connexion globale $pdo = get_database_connection(); // ------------------------- // LOGGING DÉTAILLÉ // ------------------------- function log_error($message, $context = []) { $timestamp = date('Y-m-d H:i:s'); $log_message = "[$timestamp] $message"; if (!empty($context)) { $log_message .= ' | Context: ' . json_encode($context, JSON_UNESCAPED_UNICODE); } if (APP_DEBUG) { $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); if (isset($backtrace[1])) { $caller = $backtrace[1]; $log_message .= sprintf( ' | Called from: %s:%d', basename($caller['file'] ?? 'unknown'), $caller['line'] ?? 0 ); } } error_log($log_message); } // ------------------------- // RÉPONSE JSON SÉCURISÉE // ------------------------- function json_response($data, $status = 200) { if (ob_get_level()) ob_clean(); header('Content-Type: application/json; charset=utf-8'); header('Cache-Control: no-cache, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); http_response_code($status); $json = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); if ($json === false) { log_error("Erreur d'encodage JSON: " . json_last_error_msg(), ['data' => $data]); $json = json_encode([ 'success' => false, 'error' => 'Erreur d\'encodage de la réponse' ]); } echo $json; exit; } // ------------------------- // AUTHENTIFICATION // ------------------------- function check_auth() { if (session_status() === PHP_SESSION_NONE) session_start(); if (!isset($_SESSION['user_id'])) { log_error("Accès non autorisé - Session manquante", [ 'session_id' => session_id(), 'ip' => $_SERVER['REMOTE_ADDR'] ?? 'unknown' ]); json_response(['success' => false, 'error' => 'Non authentifié'], 401); } if (isset($_SESSION['login_time']) && (time() - $_SESSION['login_time']) > SESSION_TIMEOUT) { log_error("Session expirée", ['user_id' => $_SESSION['user_id']]); session_destroy(); json_response(['success' => false, 'error' => 'Session expirée'], 401); } return true; } // ------------------------- // VALIDATION ET SANITIZATION // ------------------------- function sanitize_input($data, $type = 'string') { if (is_array($data)) { return array_map(fn($item) => sanitize_input($item, $type), $data); } return match($type) { 'email' => filter_var($data, FILTER_SANITIZE_EMAIL), 'int' => filter_var($data, FILTER_SANITIZE_NUMBER_INT), 'float' => filter_var($data, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION), 'url' => filter_var($data, FILTER_SANITIZE_URL), default => htmlspecialchars(trim($data), ENT_QUOTES, 'UTF-8'), }; } function validate_input($data, $type = 'string') { return match($type) { 'email' => filter_var($data, FILTER_VALIDATE_EMAIL) !== false, 'int' => filter_var($data, FILTER_VALIDATE_INT) !== false, 'float' => filter_var($data, FILTER_VALIDATE_FLOAT) !== false, 'url' => filter_var($data, FILTER_VALIDATE_URL) !== false, 'string' => is_string($data) && !empty(trim($data)), default => !empty($data), }; } // ------------------------- // HANDLER ERREURS ET EXCEPTIONS // ------------------------- set_error_handler(function($errno, $errstr, $errfile, $errline) { $types = [ E_ERROR => 'ERROR', E_WARNING => 'WARNING', E_PARSE => 'PARSE', E_NOTICE => 'NOTICE', E_CORE_ERROR => 'CORE_ERROR', E_CORE_WARNING => 'CORE_WARNING', E_COMPILE_ERROR => 'COMPILE_ERROR', E_COMPILE_WARNING => 'COMPILE_WARNING', E_USER_ERROR => 'USER_ERROR', E_USER_WARNING => 'USER_WARNING', E_USER_NOTICE => 'USER_NOTICE', E_STRICT => 'STRICT', E_RECOVERABLE_ERROR => 'RECOVERABLE_ERROR', E_DEPRECATED => 'DEPRECATED', E_USER_DEPRECATED => 'USER_DEPRECATED' ]; $type = $types[$errno] ?? 'UNKNOWN'; log_error("PHP $type: $errstr", ['file' => basename($errfile), 'line' => $errline]); return in_array($errno, [E_NOTICE, E_DEPRECATED, E_USER_DEPRECATED, E_STRICT]); }); set_exception_handler(function($ex) { log_error("EXCEPTION NON CATCHÉE: " . $ex->getMessage(), [ 'file' => basename($ex->getFile()), 'line' => $ex->getLine(), 'trace' => $ex->getTraceAsString() ]); $resp = APP_DEBUG ? ['success' => false, 'error' => $ex->getMessage(), 'file' => $ex->getFile(), 'line' => $ex->getLine()] : ['success' => false, 'error' => 'Une erreur serveur est survenue']; json_response($resp, 500); }); // ------------------------- // LOG DEMARRAGE // ------------------------- log_error("✅ Configuration chargée - Mode DEBUG: " . (APP_DEBUG ? 'ON' : 'OFF'));