prepare($requete); $stmt->bind_param('s', $nom_fichier); $stmt->execute(); $stmt->bind_result($statut); $trouve = $stmt->fetch(); $stmt->close(); if (!$trouve) return null; return ['statut' => $statut]; } // ---------------------------------------------------------------------------- // Met à jour une ligne TB_Archives_traitees existante (contrairement à // cron_archivage.php, qui en crée toujours une nouvelle) - la ligne de // quarantaine, créée au moment de la mise en attente, est ici tranchée // définitivement (cf synthèse §39). // ---------------------------------------------------------------------------- function Trancher_archive_en_attente($db, $nom_fichier, $id_bateau_final, $id_generation, $statut, $detail_erreur = null, $mmsi_recu = null, $mmsi_attendu = null) { // MMSI_recu/MMSI_attendu ne sont mis à jour QUE si connus à cet appel (une archive mise en quarantaine // 'sans_affectation' n'avait pas encore de MMSI à comparer) - sinon, on conserve les valeurs déjà // enregistrées au moment de la mise en quarantaine initiale, plutôt que de les écraser par NULL // (cf synthèse §39) : if ($mmsi_recu !== null) { $requete = "UPDATE TB_Archives_traitees SET ID_Bateau_final=?, ID_Generation=?, Statut=?, Detail_erreur=?, MMSI_recu=?, MMSI_attendu=?, Date_resolution=NOW() WHERE Nom_fichier=?"; $stmt = $db->prepare($requete); $stmt->bind_param('iisssss', $id_bateau_final, $id_generation, $statut, $detail_erreur, $mmsi_recu, $mmsi_attendu, $nom_fichier); } else { $requete = "UPDATE TB_Archives_traitees SET ID_Bateau_final=?, ID_Generation=?, Statut=?, Detail_erreur=?, Date_resolution=NOW() WHERE Nom_fichier=?"; $stmt = $db->prepare($requete); $stmt->bind_param('iisss', $id_bateau_final, $id_generation, $statut, $detail_erreur, $nom_fichier); } $ok = $stmt->execute(); $stmt->close(); return $ok; } // ---------------------------------------------------------------------------- // Reconstruit l'adresse MAC (format XX:XX:XX:XX:XX:XX) à partir des 12 // premiers caractères hexadécimaux du nom de fichier. // ---------------------------------------------------------------------------- function Adresse_mac_depuis_nom($nom_fichier) { preg_match('/^([0-9A-Fa-f]{12})_/', $nom_fichier, $m); return implode(':', str_split(strtoupper($m[1]), 2)); } function Executer_cron_quarantaine() { Ouverture_bdd("127.0.0.1:3307", BDD_USER, BDD_PASSWORD, BDD_DATABASE); $db = $_SESSION['db']; if (!is_dir(REPERTOIRE_QUARANTAINE)) { echo "Répertoire de quarantaine introuvable (" . REPERTOIRE_QUARANTAINE . ") - rien à faire.\n"; Fermeture_bdd(); return; } $fichiers = array_values(array_filter(scandir(REPERTOIRE_QUARANTAINE), fn($f) => preg_match('/^[0-9A-Fa-f]{12}_\d{6}_\d{6}_[0-9A-Fa-f]{16}\.sql\.gz\.enc$/', $f))); echo count($fichiers) . " archive(s) en quarantaine à réexaminer.\n\n"; foreach ($fichiers as $nom) { $chemin = REPERTOIRE_QUARANTAINE . "/" . $nom; $adresse_mac = Adresse_mac_depuis_nom($nom); $verrou = Verrouiller_boitier($adresse_mac); if (!$verrou['ok']) { echo " - {$nom} : " . $verrou['raison'] . " - réexamen au prochain passage.\n"; continue; } try { $ligne = Lire_ligne_en_attente($db, $nom); if ($ligne === null) { echo " - {$nom} : aucune ligne TB_Archives_traitees en attente trouvée - incohérence, à examiner manuellement.\n"; continue; } $contenu_chiffre = file_get_contents($chemin); $affectation = Resoudre_affectation_active($db, $adresse_mac); if (!$affectation['existe']) { echo " - {$nom} : toujours aucune affectation active - reste en quarantaine.\n"; continue; } $id_bateau = $affectation['id_bateau']; $dechiffrement = Decrypter_archive($contenu_chiffre); if (!$dechiffrement['ok']) { // Un échec de déchiffrement ne se résoudra pas en attendant (contrairement à l'affectation ou // au MMSI, qui dépendent d'une action administrative future) - rejet direct, comme // cron_archivage.php (cf synthèse §38) : echo " - {$nom} : ÉCHEC de déchiffrement (" . $dechiffrement['raison'] . ") - rejetée.\n"; Trancher_archive_en_attente($db, $nom, $id_bateau, null, 'rejetee', "Échec de déchiffrement : " . $dechiffrement['raison']); if (!is_dir(REPERTOIRE_ERREURS)) @mkdir(REPERTOIRE_ERREURS, 0750, true); rename($chemin, REPERTOIRE_ERREURS . "/" . $nom); continue; } $mmsi_recu = $dechiffrement['entete']['No_mmsi'] ?? null; $mmsi_attendu_connu = null; if ($mmsi_recu !== null) { $verification_mmsi = Verifier_mmsi($db, $id_bateau, $mmsi_recu); $mmsi_attendu_connu = $verification_mmsi['attendu']; if ($verification_mmsi['statut'] === 'quarantaine') { echo " - {$nom} : MMSI toujours divergent ({$mmsi_recu} / {$verification_mmsi['attendu']}) - reste en quarantaine.\n"; continue; } } // La cause de la quarantaine est levée : traitement complet, même déroulé que cron_archivage.php : $origine_bdd = $dechiffrement['entete']['Origine_bdd'] ?? 'normale'; $version_cible = $dechiffrement['entete']['Version_soft_no_package'] ?? null; $generation_active = Resoudre_generation_active($db, $id_bateau); $nouvelle_generation = Nouvelle_generation_necessaire($origine_bdd, $generation_active); $fichier_sql = Resoudre_fichier_sql($db, $version_cible); if ($fichier_sql === false) { echo " - {$nom} : version logicielle '{$version_cible}' inconnue de TB_Versions - rejetée.\n"; Trancher_archive_en_attente($db, $nom, $id_bateau, null, 'rejetee', "Version logicielle '{$version_cible}' inconnue de TB_Versions", $mmsi_recu, $mmsi_attendu_connu); if (!is_dir(REPERTOIRE_ERREURS)) @mkdir(REPERTOIRE_ERREURS, 0750, true); rename($chemin, REPERTOIRE_ERREURS . "/" . $nom); continue; } $contenu_fichier_sql = @file_get_contents(REPERTOIRE_VERSIONS_SQL . "/" . $fichier_sql); if ($contenu_fichier_sql === false) { echo " - {$nom} : fichier {$fichier_sql} introuvable sur le VPS - rejetée.\n"; Trancher_archive_en_attente($db, $nom, $id_bateau, null, 'rejetee', "Fichier {$fichier_sql} introuvable sur le VPS", $mmsi_recu, $mmsi_attendu_connu); if (!is_dir(REPERTOIRE_ERREURS)) @mkdir(REPERTOIRE_ERREURS, 0750, true); rename($chemin, REPERTOIRE_ERREURS . "/" . $nom); continue; } if ($nouvelle_generation) { $zone_usine = Extraire_zone_usine($contenu_fichier_sql); if ($zone_usine === false) { echo " - {$nom} : marqueur Factory_structure introuvable dans {$fichier_sql} - rejetée.\n"; Trancher_archive_en_attente($db, $nom, $id_bateau, null, 'rejetee', "Marqueur Factory_structure introuvable dans {$fichier_sql}", $mmsi_recu, $mmsi_attendu_connu); if (!is_dir(REPERTOIRE_ERREURS)) @mkdir(REPERTOIRE_ERREURS, 0750, true); rename($chemin, REPERTOIRE_ERREURS . "/" . $nom); continue; } $motif = ($origine_bdd === 'factory' || $origine_bdd === 'restauration') ? $origine_bdd : 'creation_initiale'; $resultat_generation = Creer_generation($db, $id_bateau, $motif, $zone_usine); if (!$resultat_generation['ok']) { echo " - {$nom} : échec de création de génération : " . $resultat_generation['raison'] . " - rejetée.\n"; Trancher_archive_en_attente($db, $nom, $id_bateau, null, 'rejetee', "Échec de création de génération : " . $resultat_generation['raison'], $mmsi_recu, $mmsi_attendu_connu); if (!is_dir(REPERTOIRE_ERREURS)) @mkdir(REPERTOIRE_ERREURS, 0750, true); rename($chemin, REPERTOIRE_ERREURS . "/" . $nom); continue; } $nom_base_cible = $resultat_generation['nom_base']; } else { $nom_base_cible = $generation_active['nom_base']; } $chargement = Charger_contenu_archive($nom_base_cible, $dechiffrement['sql']); if (!$chargement['ok']) { echo " - {$nom} : échec de chargement dans {$nom_base_cible} : " . $chargement['raison'] . " - rejetée.\n"; Trancher_archive_en_attente($db, $nom, $id_bateau, null, 'rejetee', "Échec de chargement dans {$nom_base_cible} : " . $chargement['raison'], $mmsi_recu, $mmsi_attendu_connu); if (!is_dir(REPERTOIRE_ERREURS)) @mkdir(REPERTOIRE_ERREURS, 0750, true); rename($chemin, REPERTOIRE_ERREURS . "/" . $nom); continue; } $generation_pour_enregistrement = Resoudre_generation_active($db, $id_bateau); Trancher_archive_en_attente($db, $nom, $id_bateau, $generation_pour_enregistrement['cle'], 'traitee', null, $mmsi_recu, $mmsi_attendu_connu); unlink($chemin); echo " - {$nom} : quarantaine levée, chargée dans {$nom_base_cible}.\n"; } finally { Liberer_boitier($verrou['poignee']); } } Fermeture_bdd(); } Executer_cron_quarantaine();