Il est indispensable de protéger toutes les chaînes de caractères provenant d'une saisie utilisateur avec mysqli_real_escape_string() dans toutes les requêtes SQL.

Dans le script auteurs_liste.php on utilise une chaîne saisie par l'utilisateur pour composer une partie de la requête SQL de sélection.

    $nom = mysqli_real_escape_string($bd,$_SESSION['recherche']['nom']);

    // pour notamment empécher un utilisateur de lister
    // toute la table si il saisit un pourcent
    // dans le critère de recherche
    $nom = addcslashes($nom, '%_');

    if ($_SESSION['recherche']['pos'] == 1) {
    	$where = "WHERE auNom LIKE '$nom%'";
    	...
    } elseif ($_SESSION['recherche']['pos'] == 2) {
    	$where = "WHERE auNom LIKE '%$nom%'";
    	...
    } else {
    	$where = "WHERE auNom LIKE '%$nom'";
    	...
    }
    ...

    //-- Requête ----------------------------------------
    $sql = "SELECT auID, auNom, auPrenom, auPays
    		FROM auteurs
    		$where
    		ORDER BY auNom, auPrenom";

C'est quelque chose que l'on réalise très souvent, soit pour composer la clause WHERE d'une requête SELECT, soit dans les requêtes INSERT ou UPDATE.

Avant insertion dans une requête SQL, il est primordial de protéger les chaînes saisies par l'utilisateur avec la fonction mysqli_real_escape_string(), car ces chaînes pourraient contenir des caractères spéciaux qu'on ne peut pas insérés tels quels dans une requête SQL : guillemets simples ou doubles, \0, \n, ctrl-Z, etc.

La fonction mysqli_real_escape_string() protège tous ces caractères spéciaux en les échappant avec un \.

Dans l'exemple suivant, la chaîne saisie n'est pas protégée. Pour voir le résultat, saisissez un nom avec un ou des guillemets simples (par exemple O'Reilly ou Le Floc'h ou N'Go).

Exemple : pas de protection des chaînes
<?php ob_start(); require('bib_params.php'); require('bib_fonctions.php'); //--------------------------------------------------- // Phase affichage du formulaire de saisie if (!isset($_POST['btnOk'])) { htmlDebut('Rechercher auteurs', 'bd.css'); echo '<form method="POST" ', 'action="', $_SERVER['PHP_SELF'], '">', 'Nom <input type="text" name="txtNom">', '<input type="submit" name="btnOk" value="Ok">', '</form>'; htmlFin(); exit(); // ==> FIN si affichage formulaire } //--------------------------------------------------- // Phase traitement de la saisie htmlDebut('Liste auteurs', 'bd.css'); $bd = bdConnecter(); $nom = trim($_POST['txtNom']); //-- Requête -- $sql = "SELECT auNom, auPrenom, auPays FROM auteurs WHERE auNom LIKE '%$nom%' ORDER BY auNom, auPrenom"; $r = mysqli_query($bd, $sql) or bdErreur($bd, $sql); //-- Liste -- htmlTable(array('Nom', 'Prénom', 'Pays'), 'tab-bd'); while ($enr = mysqli_fetch_assoc($r)) { htmlProteger($enr); htmlLigne($enr); } // Libération de la mémoire associée au résultat de la requête mysqli_free_result($r); //-- Déconnexion ------------------------------------ mysqli_close($bd); echo '</table>'; htmlFin(); ?>

En "protégeant" la chaîne saisie avec mysqli_real_escape_string(), l'erreur dans la requête SELECT disparait.

Exemple : protection des chaînes
<?php ob_start(); require('bib_params.php'); require('bib_fonctions.php'); //--------------------------------------------------- // Phase affichage du formulaire de saisie if (!isset($_POST['btnOk'])) { htmlDebut('Rechercher auteurs', 'bd.css'); echo '<form method="POST" ', 'action="', $_SERVER['PHP_SELF'], '">', 'Nom <input type="text" name="txtNom">', '<input type="submit" name="btnOk" value="Ok">', '</form>'; htmlFin(); exit(); // ==> FIN si affichage formulaire } //--------------------------------------------------- // Phase traitement de la saisie htmlDebut('Liste auteurs', 'bd.css'); $bd = bdConnecter(); $nom = trim($_POST['txtNom']); echo '<hr> DEBUG, avant $nom = ', $nom; $nom = mysqli_real_escape_string($bd, $nom); echo '<hr> DEBUG, après $nom = ', $nom; //-- Requête -- $sql = "SELECT auNom, auPrenom, auPays FROM auteurs WHERE auNom LIKE '%$nom%' ORDER BY auNom, auPrenom"; echo '<hr> DEBUG, $sql =<br><pre>', $sql; echo '</pre><hr>'; $r = mysqli_query($bd, $sql) or bdErreur($bd, $sql); //-- Liste -- htmlTable(array('Nom', 'Prénom', 'Pays'), 'tab-bd'); while ($enr = mysqli_fetch_assoc($r)) { htmlProteger($enr); htmlLigne($enr); } // Libération de la mémoire associée au résultat de la requête mysqli_free_result($r); //-- Déconnexion ------------------------------------ mysqli_close($bd); echo '</table>'; htmlFin(); ?>

La fonction mysqli_real_escape_string() permet également de se protéger contre les attaques de type injections SQL.

Notez, dans la page auteurs_liste.php, l'utilisation de la fonction addcslashes() qui permet d'échapper des caractères supplémentaires, ici le pourcent (%) et l'underscore (_), afin de leur oter leur sens spécial avant insertion dans la requête SQL.

Il est indispensable de protéger toutes les chaînes de caractères provenant d'une saisie utilisateur avec mysqli_real_escape_string() dans toutes les requêtes SQL.