CactusCrew

CactusCrew
 
PEAR : Un bug dans HTML_QuickForm ?

Depuis quelques temps, j'ai des problèmes avec les groupes de text, les hierselect. Mais j'ai peut être trouvé la solution.

Fichier de test

Voici un exemple de formulaire avec un groupe de text :

<?php
require_once 'HTML/QuickForm.php';
$form = new HTML_QuickForm('example');
 
$A_group	= array();
$A_group[]	= $form->createElement('text', 'test');
$A_group[]	= $form->createElement('text', 'foo');
 
$form->addGroup($A_group, 'tagada');
 
$form->addElement('submit', 'go', 'Go');
 
$form->display();
 
if ($form->validate()) {
	echo '<pre>';
	print_r($form->getSubmitValues());
	echo '</pre>';
	
}
 
?>

Ce qui nous donne ceci, à vide.

Mise en évidence du problème :

Une fois rempli et validé, voici le résultat que j'obtiens :

J'obtiens des caractères venu de l'espace ! Totalement illisible !
J'ai bien sûr essayé sur un autre server. Mais je n'avais aucun souci. Dois-je en tiré la conclusion que le problème viens de mon server ?

Mais quelle est donc la particularité de mon server qui fait planter mon formulaire ?


Je me suis lancé dans la recherche de la source du problème dans les classes de PEAR.
Je suis remonté jusqu'à la classe HTML_QuickForm_Element et sa méthode _findValue.

<?php
function _findValue(&$values)
    {
        if (empty($values)) {
            return null;
        }
        $elementName = $this->getName();
        if (isset($values[$elementName])) {
            return $values[$elementName];
        } elseif (strpos($elementName, '[')) {
            $myVar = "['" . str_replace(array(']', '['), array('', "']['"), $elementName) . "']";
            return eval("return (isset(\$values$myVar)) ? \$values$myVar : null;");
        } else {
            return null;
        }
    } 
?>

En résumé, pour mon élément groupe, PEAR appelle _findValue pour trouver la valeur "postée" des "sous-éléments" tagadatest et tagadafoo.
Voici le contenu de $value passé en paramètre : @@array(2) {

 tagada = array(2) {
       test = string(5) "Hello !"
       foo = string(7) "Good bye !"
 }
 go = string(2) "Go"

}@@

Le premier test si la valeur de l'élément est disponible dans la première dimension du tableau. Dans notre cas, tagadatest ne l'est pas.
On passe donc au second test, pour déterminer si l'élément est "composé".
Puis nous effectons un rennomage en 'tagada''test'.

Et là c'est le drame... on fait un eval !
Cet eval est censé retourner $value'tagada''test'.

Pourquoi utiliser ici un eval qui est, rappelons le, trés fortement recommandé de ne pas utiliser ?
Je ne sais pas pourquoi sur ce serveur cette eval "plante", je ne sais pas quelle configuration fait qu'une telle chose arrive, mais je pense qu'il y a moyen de réaliser l'opértion autrement.

Une solution ?
<?php
 function _findValue(&$values)
    {
        if (empty($values)) {
            return null;
        }
        $elementName = $this->getName();
        if (isset($values[$elementName])) {
            return $values[$elementName];
        } elseif ($I_pos	= strpos($elementName, '[')) {
        	$S_element	= substr($elementName, 0, $I_pos);
        	$S_indice	= substr($elementName, $I_pos + 1);
        	$S_indice	= substr($S_indice, 0, strlen($S_indice) - 1);
 
        	if (isset($values[$S_element][$S_indice])) {
        		return $values[$S_element][$S_indice];
        		
        	}
        	
                 // ancienne version, au cas ou...
        	$myVar = "['" . str_replace(array(']', '['), array('', "']['"), $elementName) . "']";
                return eval("return (isset(\$values$myVar)) ? \$values$myVar : null;");
        } else {
            return null;
        }
    }
?>

En clair, je récupère le nom de l'élément correspondant à la clé de la première dimension, puis "l'indice" de la seconde dimension. De là, j'accède au tableau de valeurs que je n'ai plus qu'à retourner.

Cette méthode simple, peut être améliorée à l'aide de regex par exemple. Et sera nettement moins dangereuse qu'un eval.

Conclusion

Pourquoi un eval ne fonctionne pas sur mon serveur ? Je n'ai sais rien, si quelqu'un à une idée, je suis preneur. Quoi qu'il en soit je pense qu'il est vraiment préférable de l'éviter.
Puis-je espérer une amélioration de cette méthode dans la prochaine version de HTML_QuickForm2 ? Je l'espère !
Dans tout les cas, j'ai posté un rapport de bug afin d'otenir plus d'explications.

 
PDF
« retour à l'accueil
Commentaires
1.   Tatane  |  jeudi 10 août 2006 à 15:21

Ca c'est une analyse !
Truc de fou ce machin là ... tiens moi au jus si t'as un jour une réponse à ton bug, ça m'intéresse de savoir ;-)

Bon allez je retourne me prendre le chou avec cette daubasse de Typo3 et ses fabuleux "TemplaVoila" .... vive Xibux et ses templates XHTML !!

Vraiment une merde sans nom ce Typo3 ...

 
2.   Nicolas SUPRIN  |  jeudi 10 août 2006 à 15:53

Bug posté, on va bien voir.
Ils me conseillent de faire une mise à jour du PHP 5.0.5 vers une plus récente comme 5.1.4.
Mais étant donné que les version récente de PHP nous posent des problèmes de configuration, et que notre 5.0.5 est en prod, c'est tendu...

Sinon Tatane, tu te souviens, on avait déja eu ce souci plusieurs fois sans jamais trop comprendre d'où ça venait... je pense que voila en partie la solution...

 
3.   Bertrand Mansion  |  jeudi 10 août 2006 à 16:09

Eval(), tel qu'il est utilisé dans HTML_QuickForm ne pose pas de problèmes. Eval() peut poser des problèmes de sécurité lorsqu'il est utilisé bêtement, dans les autres cas, il permet de profiter de la nature dynamique du langage PHP. C'est une fonction qui est aussi largement utilisée dans Ruby on Rails et dans les frameworks écrits en Python. Ce n'est pas parce que tout le monde dit "n'utilisez pas eval()" qu'il faut appliquer.

En revanche, ta solution de remplacement au eval() est fausse puisqu'elle ne permet pas de retrouver la valeur d'éléments dont le nom contient plusieurs [], ex: data[form][test][0]
J'attends toujours une meilleure solution à cette fonction :)

En ce qui concerne ton problème d'affichage, je pense que cela peut provenir de ton navigateur, de ton fichier source php (son encodage), du serveur ou autre chose, mais peut-être pas de PHP, et en tout cas pas de QuickForm puisque ce code fonctionne partout ailleurs, même avec 5.0.5 puisque j'ai un serveur qui tourne avec.

 
4.   Nicolas SUPRIN  |  jeudi 10 août 2006 à 16:27

Merci Bertrand, c'est vrai que je n'avais pas pensé aus éléments contenant plus de 2 dimensions.

Mais je ne pense pas que cela vienne de mon navigateur, étant donné que j'ai fais le test sur plusieurs autres machines, dont un mac... et j'ai le même résultat.

As-tu essayé mon script de test sur ton server 5.0.5 ?

Si tu ne rencontres pas de problème, sa m'inquièterai, cela signifiant que ce n'est pas la version de PHP qui est incriminée. Si tel est le cas, qu'est-ce que cela peut-il être ? Je ne connais aucune configuration propre à eval... et je ne pense pas que cela existe....

 
5.   Bertrand Mansion  |  jeudi 10 août 2006 à 17:57

Je viens de tester avec 5.0.4 sur ubuntu et aucun problème. Je n'ai pas de 5.0.5 sous la main mais je ne pense pas que le problème vienne de PHP ou de QuickForm. Le problème vient sûrement d'ailleurs. Essaye avec un autre navigateur pour voir...

 
6.   Nicolas SUPRIN  |  vendredi 11 août 2006 à 08:41

J'ai bien essayé sous Safari sur Mac... la même chose. J'ai vraiment l'impression d'avoir un buffer overflow au niveau du eval.

Ne penses-tu pas qu'il y aurait un autre moyen de procéder sans cet eval ? Je ne pense pas que nous sommes les seules sur terre à avoir rencontrer ce problème !

 
7.   Nicolas SUPRIN  |  vendredi 11 août 2006 à 09:29

J'ai fait le test sur notre serveur de prod. Même environnement (Red Hat, PHP 5.0.5, même version des package HTML_QuickForm, à priopri mêmes configurations d'Apache et PHP...) que le serveur de dev.

Et la je n'ai aucun souci !

C'est à en perdre son latin. Je ne trouve rien sur le net sur une éventuelle configuration qui entrainerait ce problème sur dev.

Par contre, j'ai afficher le resulat de l'eval dans la méthode _findValue, et c'est encore plus déroutant :

 
8.   Nicolas SUPRIN  |  vendredi 11 août 2006 à 09:36

J'ai également fais un test sur un serveur Virtuel (VM Ware) copie conforme du server de dev, et la pas de souci non plus.
Nous allons tenter un reboot de dev... (Comme disait ma grand mère, dans le doute, reboot !)

 
9.   Bertrand Mansion  |  vendredi 11 août 2006 à 09:42

Comment ton fichier source PHP est-il encodé ? Assure-toi qu'il est encodé en Latin 1 ou en UTF-8 sans BOM. Encore une fois, c'est la première fois que nous avons un rapport de bug de ce genre sur les centaines que nous avons pu recevoir depuis 2000. Le problème ne vient pas de QuickForm ni de l'utilisation du eval() (stoppe le FUD), le bug se trouve ailleurs, dans ton environnement. Peut-être la barrette de mémoire vive, j'ai déjà vu des trucs bizarres avec des RAM défectueuses ?

 
10.   Nicolas SUPRIN  |  vendredi 11 août 2006 à 10:04

Merci Mr PEAR de suivre le problème :)
L'encodage des fichiers est en ANSI UNIX... Comme tout les autres...
Je penche aussi pour un default de mémoire... Reboot programmé pendant la pause de midi... croisons les doigts !

 
11.   Nicolas SUPRIN  |  vendredi 11 août 2006 à 14:26

Aprés reboot, toujours pareil... :( je désepère !

 
12.   Nicolas SUPRIN  |  mercredi 16 août 2006 à 09:30

j'ai trouver une solution plus propre (et un poil plus rapide) pour ne plus utiliser eval... : http://blog.cactuscrew.com/52-_findvalue.html
Si un quelqu'un chez PEAR pouvait jeter un oeil...

 
« retour à l'accueil
Trackbacks

Aucun trackback.

Les trackbacks pour ce billet sont fermés.

 
Ajouter un commentaire

Les commentaires pour ce billet sont fermés.