page liste des auteurs

Le script auteurs_liste.php affiche la liste des auteurs sélectionnés d'après les critères saisis dans la page auteurs_cherche.php. C'est la clause WHERE du SELECT sur la table auteurs qui fait cette sélection.

- Si on arrive de la page auteurs_cherche.php, la clause WHERE est faite avec les éléments du formulaire.
- Si on revient de la page auteurs_maj.php, la clause WHERE est faite avec les données stockées dans la variable de session $_SESSION['recherche'].
- Pour être valide, le critère de recherche (ie le nom saisi dans l' input de type text de la page auteurs_cherche.php) ne doit pas être vide. Si on arrive sur cette page avec un critère de recherche vide, un message signale le problème à l'utilisateur. Cela permet de ne jamais afficher tout le contenu de la table auteurs.

liaisons page liste

L'utilisateur a le choix entre plusieurs actions.

- Il peut choisir dans la liste un auteur à modifier ou à supprimer en cliquant sur son nom. L'url du lien pointe sur la page auteurs_maj.php et contient l'id de l'auteur à modifier (crypté bien sûr).
- Il peut cliquer sur le bouton "Recherche" pour revenir à la page de recherche auteurs_cherche.php
- Il peut cliquer sur le bouton "Ajouter" pour passer directement à la phase de création d'un auteur (auteurs_maj.php).

Le code du script auteurs_liste.php est un peu plus complexe que celui de auteurs_cherche.php, surtout à cause de la gestion à faire des éléments saisis. On commence par traiter les paramètres reçus dans le tableau $_POST avant de générer le code HTML de la page. La partie sélection et affichage des résultats a déjà été vue de nombreuses fois dans les pages précédentes. Quelques commentaires après le code.

Script auteurs_liste.php
<?php ob_start(); session_start(); require('bib_params.php'); require('bib_fonctions.php'); $_SESSION['idAuteur'] = 0; /*---------------------------------------------------------- -- Début du traitement des paramètres reçus -- (contenus dans $_POST) ----------------------------------------------------------*/ if (isset($_POST['btnChercher'])) { // Si on vient de la page de recherche, on récupère // les critères de recherche, et on les stocke dans // la variable de session pour pouvoir les réutiliser. // contrôle que les clés attendues dans $_POST // sont bien présentes if (!isset($_POST['radNom']) || !isset($_POST['txtNom'])) { header('Location: auteurs_cherche.php'); exit(); //==> FIN piratage ? } if (!estEntier($_POST['radNom'])) { header('Location: auteurs_cherche.php'); exit(); //==> FIN piratage ? } $position = (int) $_POST['radNom']; if (!estEntre($position, 1, 3)) { header('Location: auteurs_cherche.php'); exit(); //==> FIN piratage ? } $nom = trim($_POST['txtNom']); if ($nom != '') { // Mise à jour de la variable de session $_SESSION['recherche']['pos'] = $position; $_SESSION['recherche']['nom'] = $nom; } } elseif (! isset($_POST['btnListe'])) { header('Location: auteurs_cherche.php'); exit(); //==> FIN piratage ? } /*----------------------------------------------------------- -- Fin du traitement des paramètres reçus -----------------------------------------------------------*/ /*----------------------------------------------------------- -- Envoi du code HTML de la page -----------------------------------------------------------*/ htmlDebut('Liste auteurs', 'bd.css'); if (count($_SESSION['recherche']) == 2){ $bd = bdConnecter(); $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, '%_'); $message = 'Recherche des auteurs dont le nom '; if ($_SESSION['recherche']['pos'] == 1) { $where = "WHERE auNom LIKE '$nom%'"; $message .= 'commence par "'; } elseif ($_SESSION['recherche']['pos'] == 2) { $where = "WHERE auNom LIKE '%$nom%'"; $message .= 'contient "'; } else { $where = "WHERE auNom LIKE '%$nom'"; $message .= 'finit par "'; } $message .= htmlentities($_SESSION['recherche']['nom'], ENT_COMPAT, 'ISO-8859-1').'".'; echo '<p class="pagination">', $message, '</p>'; //-- Requête ---------------------------------------- $sql = "SELECT auID, auNom, auPrenom, auPays FROM auteurs $where ORDER BY auNom, auPrenom"; $r = mysqli_query($bd, $sql) or bdErreur($bd, $sql); //-- Traitement ------------------------------------- if (mysqli_num_rows($r) == 0){ echo '<p class="pagination">La liste est vide</p>'; } else{ htmlTable(array('Nom', 'Prénom', 'Pays'), 'tab-bd'); while ($enr = mysqli_fetch_assoc($r)) { htmlProteger($enr); $id = crypterURl($enr['auID']); $enr['auNom'] = '<a href="auteurs_maj.php?x=' .$id.'">' .$enr['auNom'].'</a>'; unset($enr['auID']); htmlLigne($enr); } echo '</table>'; } // Libération de la mémoire associée au // résultat de la requête mysqli_free_result($r); //-- Déconnexion -------------------------------- mysqli_close($bd); } //-- Boutons ---------------------------------------- echo '<form method="POST" class="maj" ', 'action="auteurs_cherche.php">', count($_SESSION['recherche']) == 0 ? '<p class="pagination"> Veuillez saisir un critère de recherche non vide</p>': '', '<p class="pagination">', '<input type="submit" value="Ajouter" ', 'name="btnNouveau" formaction="auteurs_maj.php">', '<input type="submit" value="Recherche" ', 'name="btnChercher">', '</p>', '</form>'; htmlFin(); ?>

Exécuter auteurs_cherche.php puis auteurs_liste.php

Il y a dans ce script 3 nouveautés :

- l'utilisation de l'opérateur LIKE dans une clause WHERE,
- une fonction de cryptage (et son pendant pour décrypter) dans la bibliothéque bib_fonctions.php,
- la protection des chaînes envoyées dans une requête SQL avec la fonction mysqli_real_escape_string() (cf. chapitre suivant).

L'opérateur SQL LIKE permet d'effectuer des sélections sur une partie seulement d'un champ alphanumérique. Il permet de définir des modèles de sélection plutôt que des des égalités strictes de chaînes de caractères. La définition de ces modèles se fait avec deux "jokers" :

- _ (underscore) remplace un et un seul caractère,
- % (pourcentage) remplace 0, un ou plusieurs caractères.

Exemples :

- abc% représente une chaîne commençant par abc ("abcdefgh", "abc efg", "abcd", "abc").
- %abc% représente une chaîne contenant abc ("xyzabcdef", "xyzabc", "abcdef", "12 abc def").
- %abc représente une chaîne se terminant par abc ("xyzabc", "abc", "123 abc", "abc").
- abc_ représente une chaîne commençant par abc et se terminant par n'importe quel autre caractère ("abcd", "abc ", "abc1"). La chaîne aura obligatoirement 4 caractères.
- a_b_c représente une chaîne commençant par a, suivi de n'importe quel autre caractère, puis de b, suivi de n'importe quel autre caractère, puis de c ("a1b c", "axbyc"). La chaîne aura obligatoirement 5 caractères.

Pour sélectionner un auteur à modifier, l'utilisateur clique sur un lien (le nom de l'auteur). Ce lien est composé avec un paramètre crypté (l'ID de l'auteur). Le cryptage est fait avec la fonction crypterURL() écrite sur les principes vues dans "Web et PHP", "Les liens". Cette fonction est placée dans notre bibliothéque de fonctions bib_fonctions.php.

    /**
     * Crypte une valeur pour la passer dans une URL.
     *
     * @param mixed		$val	La valeur à crypter
     * @return string	La valeur cryptée et encodée url
     */
    function crypterURL($val) {
    	$ivlen = openssl_cipher_iv_length($cipher='AES-128-CBC');
    	$sha2len=32;
    	if (! isset ($_SESSION['cle_crytage'])){
    		$_SESSION['cle_crytage'] = base64_encode(
    		                   openssl_random_pseudo_bytes($ivlen));
    		$_SESSION['cle_hachage'] = base64_encode(
    		                   openssl_random_pseudo_bytes($sha2len));
    	}

    	// -- génération du vecteur d'initialisation
    	$iv = openssl_random_pseudo_bytes($ivlen);
    	// -- cryptage de $val
    	$x = openssl_encrypt($val, $cipher,
    						 base64_decode($_SESSION['cle_crytage']),
    	                     OPENSSL_RAW_DATA, $iv);
    	// -- calcul de la signature de la valeur cryptée
    	$hmac = hash_hmac('sha256', $x,
    	                 base64_decode($_SESSION['cle_hachage']), true);

    	$x = substr($hmac, 0, $sha2len/2)
    	     .$iv.$x.substr($hmac, $sha2len/2);
    	$x = base64_encode($x);
    	return urlencode($x);
    }

On a bien sûr aussi écrit la fonction decrypterURL().

    **
     * Décrypte une valeur cryptée avec la fonction crypterURL
     *
     * @param string	$x	La valeur à décrypter
     * @return mixed	La valeur décryptée ou FALSE si erreur
     */
    function decrypterURL($x) {
    	$ivlen = openssl_cipher_iv_length($cipher='AES-128-CBC');
    	$x = base64_decode($x);
    	$sha2len=32;
    	$hmac = substr($x, 0, $sha2len/2).substr($x, -$sha2len/2);
    	$iv = substr($x, $sha2len/2, $ivlen);
    	$x = substr($x, $sha2len/2 + $ivlen, -$sha2len/2);
    	// calcul de  la signature de la chaine cryptée reçue
    	$hmacCalc = hash_hmac('sha256', $x,
    	                 base64_decode($_SESSION['cle_hachage']), true);
    	if (! hash_equals($hmac, $hmacCalc)){
    		return FALSE;
    	}
    	return openssl_decrypt($x, $cipher,
    	                       base64_decode($_SESSION['cle_crytage']),
    	                       OPENSSL_RAW_DATA, $iv);
    }

Notez, dans la fonction crypterURL(), la condition
if (! isset ($_SESSION['cle_crytage']))
Son utilisation permet de générer une paire de clés différente pour chaque utilisateur.