'; 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 { $created_at = new DateTime($compte['cree_le']); } catch (Throwable $e) { // Par prudence : si la date est illisible, on refuse ui_exit( $translations['err_titre'] ?? 'Un problème est survenu', $translations['err_lien_invalide'] ?? 'Lien invalide.', 400, 'error', '/', $translations['retour_acceuil'] ?? 'Retour à l’accueil' ); } $now = new DateTime(); $diffH = ($now->getTimestamp() - $created_at->getTimestamp()) / 3600; if ($diffH > 6) { // Supprimer les enregistrements expirés try { $pdo->beginTransaction(); $pdo->prepare("DELETE FROM compte WHERE id = :id")->execute(['id' => $compte['id']]); $ref_id = (int)$compte['reference_id']; if (($compte['role'] ?? '') === 'praticien') { $pdo->prepare("DELETE FROM praticien WHERE id = :id")->execute(['id' => $ref_id]); } else { $pdo->prepare("DELETE FROM client WHERE id = :id")->execute(['id' => $ref_id]); } $pdo->commit(); } catch (Throwable $e) { if ($pdo->inTransaction()) $pdo->rollBack(); error_log('Validation email - purge expirée é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' ); } ui_exit( $translations['err_titre'] ?? 'Un problème est survenu', $translations['err_lien_expire'] ?? 'Le lien de validation a expiré.', 410, 'info', '/', $translations['retour_acceuil'] ?? 'Retour à l’accueil' ); } // ===================== // 4) Valider l'email (maj compte) // ===================== try { $stmt = $pdo->prepare("UPDATE compte SET email_valide = 1, token_validation = 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' );