Journal du Net > Développeur > PHP >  PHP > transformation en register_global=off
Pratique
 
04/07/2007

Simplifier un code PHP avec register_globals = Off

Comment alléger un programme ne fonctionnant qu'en "register_globals = On" en le rendant compatible avec "register_globals = Off" sans autre modification que l'inclusion d'un fichier d'une seule ligne.
  Envoyer Imprimer  

 
En savoir plus
 
 
 

Sur les serveurs Web correctement configurés, PHP fonctionne en "registers_global = Off": les variables des registres Environnement, GET, POST, Cookie, et Built-in (souvent désignées par variables EGPCS) ne sont pas vues comme des variables globales.

C'est naturellement plus sûr, en particulier pour les variables de formulaires qu'il est ainsi beaucoup plus dur d'abuser par une URL bien sentie...

Par contre c'est un peu plus lourd pour le programmeur qui doit, pour désigner la variable récupérée d'un formulaire, utiliser des lourds $_GET['toto'] ou $_POST['toto'] au lieu d'un simple $toto en register_globals = On.

Simplifier le code : idée 1

On peut revenir à un comportement de type register_globals = On en commençant son script par autant de lignes du type if (isset( $_GET['var_i'])) {$toto = $_GET['var_i'];}qu'on a de variables à récupérer...

Ça marche bien mais, c'est laborieux et pour que ça marche dans tous les cas, il faut mettre autant de lignes que de variables potentiellement récupérables. C'est-à-dire que si le script comporte de multiples formulaires indépendants qui le rappellent, il faut que toutes les variables à récupérer dans tous les cas d'appel possibles soient listées... Il faut reconnaitre qu'évaluer 37 fois if (isset( $_GET['var_i'])) $toto = $_GET['var_i'] ; si seulement 2 variables sont concernées par l'appel courant, ça n'est pas très optimal.

Mais surtout, il est des cas pour lesquels cela ne marche pas, en particulier si les noms des variables du formulaire sont dynamiques. En effet, prenons le code simple suivant :

echo("<input type=TEXT size=6 value=\"$ValeurChamp\" 
name=\"grep_".mysql_field_name($result,$i)."\">");

Ici,le nom de la variable à récupérer est fonction du champ de la table MySQL. Sachant que le script attaque potentiellement toutes les bases du serveur MySQL, le nombre de tables et donc de champs rend caduque la précédente méthode d'énumération des variables.

Simplifier le code : idée 2

L'idée est finalement simple : au lieu d'énumérer les variables potentiellement récupérables, partons plutôt du tableau qui les contient, soit par exemple le tableau _GET.

Il suffit, pour toutes les clés X définies dans le tableau _GET à l'appel du script, c'est-à-dire à tous les noms des variables qui ont été passées par la méthode GET, de générer la ligne de code $X = $_GET['X'].

Maintenant, il faut l'écrire en PHP. Voici le fichier Recup__GET_vars.php à inclure [1] au début de vos scripts PHP écrits pour register_globals = On afin qu'ils fonctionnent immédiatement en register_globals = Off du point de vue des variables GET. [2]

<?php
while (list($key, $val) = each($_GET)) {$$key=$val;}
?>

Explications

Pour commencer on va récupérer les paires (clé, valeur) du tableau _GET, c'est-à-dire les paires ("nom de variable", $_GET['nom_de_variable']). La fonction each($_GET) va beaucoup nous aider.

Extrait de la doc PHP : "each($array) retourne la paire clé/valeur courante du tableau array et avance le pointeur de tableau. Cette paire est retournée dans un tableau de 4 éléments, avec les clés 0, 1, key, et value. Les éléments 0 et key contiennent le nom de la clé et 1 et value contiennent la valeur."

 
En savoir plus
 
 
 

D'après cette définition, list($key, $val) = each($_GET) met dans $key l'élément de clé "0" du tableau renvoyé par each, c'est-à-dire le nom de la variable. De la même manière $val est instanciée par l'élément de clé "1" du tableau renvoyé par each, donc la valeur de la variable ayant pour nom $key.

Reste le problème de désigner la variable elle-même (soit $V) dans notre code alors que nous ne disposons que d'une variable ($key) de type chaine contenant le nom de cette variable (soit "V"). L'idéal serait de pouvoir écrire $$key et que PHP l'interprète comme $V...

Ça tombe bien, PHP permet ça.

 

[1] La commande require(Recup__GET_vars.php) inclura et exécutera le code de Recup__GET_vars.php. Toutes les variables définies dans Recup__GET_vars.php seront disponibles pour le script. L'absence du fichier en argument de require produit une erreur fatale, tandis qu'on a seulement un warning avec la fonction voisine include.
[2] Il suffit bien sûr de remplacer GET par un autre registre (POST, etc.) pour créer le fichier monoligne à inclure permettant de gérer les variables de ce registre.

Cet article a été réalisé par G a.k.a Gérard Milhaud sous licence creative commons


JDN Développeur Envoyer Imprimer Haut de page

Sondage

Adobe parviendra-t-il à percer avec sa nouvelle suite de création Web Edge ?

Tous les sondages