'; echo '' . $title . ''; echo '
'; // Icône echo '
'; if ($type === 'success') { echo '
'; } elseif ($type === 'info') { echo '
'; } else { // error echo '
'; } echo '
'; echo '

' . $title . '

'; echo '

' . $message . '

'; if ($cta_href) { echo '
' . $cta_label . '
'; } echo '
'; exit; } // ===================== // 1) Token présent & valide // ===================== $rawToken = trim((string) ($_GET['token'] ?? '')); $rawAL = trim((string) ($_GET['al'] ?? '')); if ($rawAL !== '' && ! preg_match('/^[A-Fa-f0-9]{64}$/', $rawAL)) { $rawAL = ''; // on ignore si format suspect } if ($rawToken === '') { ui_exit( $translations['err_titre'] ?? 'Un problème est survenu', $translations['err_lien_invalide'] ?? 'Lien invalide.', 400, 'error', '/', $translations['retour_acceuil'] ?? 'Retour à l’accueil' ); } // Optionnel : on vérifie le format attendu (bin2hex(32) => 64 hexdigits) if (! preg_match('/^[A-Fa-f0-9]{64}$/', $rawToken)) { ui_exit( $translations['err_titre'] ?? 'Un problème est survenu', $translations['err_lien_invalide'] ?? 'Lien invalide.', 400, 'error', '/', $translations['retour_acceuil'] ?? 'Retour à l’accueil' ); } // ===================== // 2) Récupération du compte // ===================== $stmt = $pdo->prepare("SELECT * FROM compte WHERE token_validation = :token LIMIT 1"); $stmt->execute(['token' => $rawToken]); $compte = $stmt->fetch(); if (! $compte) { ui_exit( $translations['err_titre'] ?? 'Un problème est survenu', $translations['err_token_invalide'] ?? 'Token invalide.', 400, 'error', '/', $translations['retour_acceuil'] ?? 'Retour à l’accueil' ); } // ===================== // 3) Validité temporelle (6h) // ===================== try { if (empty($compte['token_validation_expire'])) { throw new RuntimeException('token_validation_expire manquant'); } $expireAt = new DateTime((string) $compte['token_validation_expire']); } catch (Throwable $e) { ui_exit( $translations['err_titre'] ?? 'Un problème est survenu', $translations['tvalidat_err_lien_invalide'] ?? $translations['err_lien_invalide'] ?? 'Lien invalide.', 400, 'error', '/', $translations['retour_acceuil'] ?? 'Retour à l’accueil' ); } $now = new DateTime(); if ($now > $expireAt) { ui_exit( $translations['err_titre'] ?? 'Un problème est survenu', $translations['tvalidat_err_lien_expire'] ?? $translations['err_lien_expire'] ?? 'Le lien de validation a expiré.', 410, 'info', '/connexion.php', $translations['btn_se_connecter'] ?? 'Se connecter' ); } // ===================== // 4) Valider l'email (maj compte) // ===================== try { $stmt = $pdo->prepare(" UPDATE compte SET email_valide = 1, token_validation = NULL, token_validation_expire = NULL WHERE id = :id "); $stmt->execute(['id' => $compte['id']]); } catch (Throwable $e) { error_log('Validation email - UPDATE échouée: ' . $e->getMessage()); ui_exit( $translations['err_titre'] ?? 'Un problème est survenu', $translations['err_serveur'] ?? 'Erreur serveur.', 500, 'error', '/', $translations['retour_acceuil'] ?? 'Retour à l’accueil' ); } // ===================== // 4bis) Auto-login (si al fourni et valide) // ===================== if ($rawAL !== '') { // On recharge le compte pour lire token_autologin + expire (plus propre) $stmt = $pdo->prepare("SELECT id, role, reference_id, token_autologin, token_autologin_expire FROM compte WHERE id = :id LIMIT 1"); $stmt->execute(['id' => (int) $compte['id']]); $c = $stmt->fetch(PDO::FETCH_ASSOC); if ($c && ! empty($c['token_autologin']) && hash_equals((string) $c['token_autologin'], $rawAL)) { // Expiration (obligatoire) $expOk = false; if (! empty($c['token_autologin_expire'])) { try { $exp = new DateTime((string) $c['token_autologin_expire']); $expOk = (new DateTime()) <= $exp; } catch (Throwable $e) { $expOk = false; } } if ($expOk) { // One-time : on invalide le token autologin $pdo->prepare("UPDATE compte SET token_autologin = NULL, token_autologin_expire = NULL WHERE id = :id") ->execute(['id' => (int) $c['id']]); // Connexion session (même logique pour client/praticien) session_regenerate_id(true); $_SESSION['compte_id'] = (int) $c['id']; // <-- IMPORTANT (secure.php l'exige) $_SESSION['role'] = (string) $c['role']; $_SESSION['reference_id'] = (int) $c['reference_id']; if ($_SESSION['role'] === 'client') { $_SESSION['client_id'] = (int) $c['reference_id']; header('Location: /public/client/informations.php'); exit; } if ($_SESSION['role'] === 'praticien') { $_SESSION['praticien_id'] = (int) $c['reference_id']; header('Location: /public/praticien/informations.php'); exit; } // fallback si role inconnu header('Location: /connexion.php'); exit; } } } // ===================== // 5) Écran final (succès) // ===================== // Le texte de succès chez toi contient un lien HTML ; on affiche un message “texte” + un vrai bouton vers la connexion. $successMsg = isset($translations['success_validation_texte']) ? strip_tags((string) $translations['success_validation_texte']) : 'Votre compte est confirmé. Vous pouvez maintenant vous connecter.'; ui_exit( $translations['success_validation_titre'] ?? 'Compte confirmé !', $successMsg, 200, 'success', '/connexion.php', $translations['btn_se_connecter'] ?? 'Se connecter' );