feat(v2.0.2): Corrections de sécurité critiques et fonctionnalité de réactivation des devis

- Correction de 14 vulnérabilités SQL (8 critiques, 6 moyennes)
- Suppression de la fonction autocomplete non utilisée
- Migration complète vers PDO avec requêtes préparées
- Ajout du bouton 'Réactiver' pour les devis archivés (statut 20 → 1)
- Conversion des appels $.ajax en fetch API (vanilla JS)
- Correction des erreurs JavaScript empêchant l'attachement d'événements
- Mise à jour de la documentation (README.md et TODO.md)

Sécurité: Utilisation systématique de intval() et requêtes préparées PDO
UI: Nouveau bouton vert dans la grille 2x2 des actions sur devis archivés
Historique: Traçabilité dans devis_histo lors de la réactivation
This commit is contained in:
2025-09-12 20:25:48 +02:00
parent eabb4bf67a
commit 443b0509df
16 changed files with 4355 additions and 3318 deletions

View File

@@ -137,18 +137,53 @@ switch ($Route->_action) {
$mobile = $data[14];
$email = nettoie_text($data[15]);
$sql = "SELECT c.* FROM clients c WHERE c.code='" . $code . "';";
$record = getinfos($sql, "gen");
try {
$db = Database::getInstance();
$sql = 'SELECT c.* FROM clients c WHERE c.code = :code';
$stmt = $db->prepare($sql);
$stmt->bindParam(':code', $code, PDO::PARAM_STR);
$stmt->execute();
$record = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (Exception $e) {
error_log("Erreur recherche client : " . $e->getMessage());
$record = [];
}
switch (count($record)) {
case 0:
//! Code client non trouvé = nouveau client
$sql = 'INSERT INTO clients SET code="' . $code . '", libelle="' . $libelle . '", siret="' . $siret . '", adresse1="' . $adresse1 . '", adresse2="' . $adresse2 . '", adresse3="' . $adresse3 . '", cp="' . $cp . '", ville="' . $ville . '", ';
$sql .= 'type_client="' . $fkType . '", contact_nom="' . $contactNom . '", contact_prenom="' . $contactPrenom . '", contact_fonction="' . $contactFonction . '", telephone="' . $telephone . '", mobile="' . $mobile . '", email="' . $email . '", chk_import=1;';
fwrite($fhlog, $row . "---" . $sql . "\r\n");
$fkClient = qSQL($sql, "gen", true);
try {
$db = Database::getInstance();
$sql = 'INSERT INTO clients SET code = :code, libelle = :libelle, siret = :siret, adresse1 = :adresse1, adresse2 = :adresse2, adresse3 = :adresse3, cp = :cp, ville = :ville, ';
$sql .= 'type_client = :type_client, contact_nom = :contact_nom, contact_prenom = :contact_prenom, contact_fonction = :contact_fonction, telephone = :telephone, mobile = :mobile, email = :email, chk_import = 1';
$stmt = $db->prepare($sql);
$stmt->execute([
':code' => $code,
':libelle' => $libelle,
':siret' => $siret,
':adresse1' => $adresse1,
':adresse2' => $adresse2,
':adresse3' => $adresse3,
':cp' => $cp,
':ville' => $ville,
':type_client' => $fkType,
':contact_nom' => $contactNom,
':contact_prenom' => $contactPrenom,
':contact_fonction' => $contactFonction,
':telephone' => $telephone,
':mobile' => $mobile,
':email' => $email
]);
$fkClient = $db->lastInsertId();
fwrite($fhlog, $row . "--- Ajout client avec requête préparée\r\n");
} catch (Exception $e) {
error_log("Erreur insertion client : " . $e->getMessage());
fwrite($fhlog, "Erreur insertion : " . $e->getMessage() . "\r\n");
$fkClient = 0;
}
fwrite($fhlog, "--- Ajout fait\r\n");
$message = "Importation Clients SAP : Le client " . $libelle . " vient d'être créé en " . $ville . " (" . $cp . ")";
$sql = 'INSERT INTO notifications SET dateheure="' . date("Y-m-d H:i:s") . '", fk_user=' . $fkUser . ', action="Création fiche", theme="Fiche Client", message="' . $message . '";';
$fkUserSafe = intval($fkUser);
$sql = 'INSERT INTO notifications SET dateheure="' . date("Y-m-d H:i:s") . '", fk_user=' . $fkUserSafe . ', action="Création fiche", theme="Fiche Client", message="' . $message . '";';
qSQL($sql, "gen");
fwrite($fhlog, "--- Fin Creation ---" . "\r\n");
@@ -158,11 +193,34 @@ switch ($Route->_action) {
//! Un seul enregistrement trouvé : on met à jour le client
$rec = $record[0];
$sql = 'UPDATE clients SET libelle="' . $libelle . '", siret="' . $siret . '", adresse1="' . $adresse1 . '", adresse2="' . $adresse2 . '", adresse3="' . $adresse3 . '", cp="' . $cp . '", ville="' . $ville . '", ';
$sql .= 'type_client="' . $fkType . '", contact_nom="' . $contactNom . '", contact_prenom="' . $contactPrenom . '", contact_fonction="' . $contactFonction . '", telephone="' . $telephone . '", mobile="' . $mobile . '", email="' . $email . '", chk_import=1 ';
$sql .= 'WHERE code="' . $code . '";';
qSQL($sql);
fwrite($fhlog, $row . "---" . $sql . "\r\n");
try {
$db = Database::getInstance();
$sql = 'UPDATE clients SET libelle = :libelle, siret = :siret, adresse1 = :adresse1, adresse2 = :adresse2, adresse3 = :adresse3, cp = :cp, ville = :ville, ';
$sql .= 'type_client = :type_client, contact_nom = :contact_nom, contact_prenom = :contact_prenom, contact_fonction = :contact_fonction, telephone = :telephone, mobile = :mobile, email = :email, chk_import = 1 ';
$sql .= 'WHERE code = :code';
$stmt = $db->prepare($sql);
$stmt->execute([
':libelle' => $libelle,
':siret' => $siret,
':adresse1' => $adresse1,
':adresse2' => $adresse2,
':adresse3' => $adresse3,
':cp' => $cp,
':ville' => $ville,
':type_client' => $fkType,
':contact_nom' => $contactNom,
':contact_prenom' => $contactPrenom,
':contact_fonction' => $contactFonction,
':telephone' => $telephone,
':mobile' => $mobile,
':email' => $email,
':code' => $code
]);
fwrite($fhlog, $row . "--- MàJ client avec requête préparée\r\n");
} catch (Exception $e) {
error_log("Erreur mise à jour client : " . $e->getMessage());
fwrite($fhlog, "Erreur MàJ : " . $e->getMessage() . "\r\n");
}
fwrite($fhlog, "--- Fin MaJ ---" . "\r\n");
break;