La fonction filter_sanitize_regexp n'existe pas (je dois dire que vu le
peu de possibilit�, j'ai du mal � saisir l'int�r�t des filter_*).
Je voulais simplement filtrer les caract�res d'une chaine qui sont dans
une expression r�guli�re.
En fait, j'ai une fonction qui peut soit valider, soit filtrer... comme
filter_* en fait, mais avec des filtres que j'ai pr�d�fini.
Or, ma fonction a un param�tre $filtre qui, s'il est TRUE, efface les
caract�res qui ne colle pas avec la regexp.
J'ai r�ussi ce que je voulais faire, mais �a m'�tonnerait qu'il n'existe
pas plus simple. J'ai eu beau chercher et tenter d'utiliser un peu
toutes les fonctions PHP dispo (sauf preg_filter qui n'est que pour >=
5.3), mais rien ne va.
Donc �a donne �a :
function regexp($type, $value, $filter=false){
switch($type) {
case "email":
$regex="/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/";
break;
case "md5":
$regex="/^[0-9a-f]{32}+$/";
break;
}
/* etc. Toutes mes def ; j'ai fait un switch comme j'aurais pu faire
autre chose */
$regex = preg_replace('`^\/\^`', '/', $regex, 1);
$regex = preg_replace('`\$\/`', '/', $regex, 1);
if(preg_match_all($regex, $value, $r)) {
$chaine = '';
foreach($r[0] as $value) {
echo '<p>'.$value.'</p>';
$chaine .= $value;
}
return $chaine;
}
}
else {
if (preg_match($regex, $value)) return false;
else return $message;
}
}
C'est super bourrin, notamment la concat�nation de la sortie du
preg_match_all.
Autre chose : je n'ai pas trop compris pourquoi dans mon preg_replace je
ne pouvais pas simplement mettre preg_replace('`\$$`', '', $regex, 1)
(idem pour le ^).
Si vous avez pig� qq chose � mes explications, y a-t-il quelque chose de
moins moche ?
.[...]{2,4}$ ? et .museum alors ?
Le filtre FILTER_SANITIZE_REGEXP, tu veux dire ? Je ne vois pas bien ce
que pourrait faire un tel filtre vu que pratiquement la totalitᅵ des
caractᅵres Unicode peut se trouver dans une regexp.
> (je dois dire que vu le
> peu de possibilitᅵ, j'ai du mal ᅵ saisir l'intᅵrᅵt des filter_*).
Euh... Ok pour le MD5, mais en ce qui concerne les adresses de courriel
tu as bien FILTER_VALIDATE_EMAIL et FILTER_SANITIZE_EMAIL, qui sont
certainement bien supᅵrieures ᅵ l'immense majoritᅵ des tests que l'on
trouve sur la toile.
> Je voulais simplement filtrer les caractᅵres d'une chaine qui sont dans
> une expression rᅵguliᅵre.
> En fait, j'ai une fonction qui peut soit valider, soit filtrer... comme
> filter_* en fait, mais avec des filtres que j'ai prᅵdᅵfini.
> Or, ma fonction a un paramᅵtre $filtre qui, s'il est TRUE, efface les
> caractᅵres qui ne colle pas avec la regexp.
Pour n'importe quelle regexp ? Hum... J'aimerais bien voir comment il se
dᅵbrouille avec la suivante :
$regexp = '/^([a-z])(?!\1).$/';
Cette regexp valide toute chaᅵne de deux caractᅵres dont le premier est
une lettre minuscule entre a et z, et le second est n'importe quoi
*sauf* la premiᅵre lettre.
> J'ai rᅵussi ce que je voulais faire, mais ᅵa m'ᅵtonnerait qu'il n'existe
> pas plus simple. J'ai eu beau chercher et tenter d'utiliser un peu
> toutes les fonctions PHP dispo (sauf preg_filter qui n'est que pour >=
> 5.3), mais rien ne va.
>
> Donc ᅵa donne ᅵa :
>
> function regexp($type, $value, $filter=false){
> switch($type) {
> case "email":
> $regex="/^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/";
C'est curieux : tu contrᅵles l'absence de deux ᅵ . ᅵ successifs dans la
partie droite, mais pas dans la partie gauche. Par ailleurs, rien
n'interdit d'avoir un chiffre ou un trait d'union dans le TLD, et il
existe dᅵjᅵ des TLD de plus de 4 caractᅵres.
Mais bon, dᅵjᅵ tu acceptes le ᅵ + ᅵ dans la partie gauche, ta rᅵgle ne
fait donc pas partie de la majoritᅵ des plus nulles.
Je rappelle ᅵ tout hasard que j'ai dᅵjᅵ parlᅵ de ᅵa dans la FAQ :
<http://faqfclphp.free.fr/#rub5.3>.
Oh, je rectifie ce que j'ai dit plus haut : tu acceptes aussi d'avoir
plusieurs ᅵ . ᅵ de suite dans la partie droite, la seule restriction
concernant le nombre de lettres aprᅵs le dernier !
> break;
> case "md5":
> $regex="/^[0-9a-f]{32}+$/";
Est-ce qu'il ne serait pas plus rapide de faire un strcspn avec la
chaᅵne "0123456789abcdef" suivi d'un strlen ? Ce n'est pas forcᅵment le
cas, hein, je me pose juste la question.
> break;
> }
> /* etc. Toutes mes def ; j'ai fait un switch comme j'aurais pu faire
> autre chose */
>
> $regex = preg_replace('`^\/\^`', '/', $regex, 1);
> $regex = preg_replace('`\$\/`', '/', $regex, 1);
Note que tu n'as pas besoin de protᅵger le / puisque tu ne l'as pas
choisi comme dᅵlimiteur :
$regex = preg_replace('`^/\^`', '/', $regex, 1);
$regex = preg_replace('`\$/`', '/', $regex, 1);
Par ailleurs, comme tu ancres tes deux expressions (enfin... tu as
oubliᅵ pour la deuxiᅵme, mais en tout cas tu sembles espᅵrer qu'il
prendra la derniᅵre occurrence et donc la seule), il n'est pas
nᅵcessaire de limiter le nombre de remplacements :
$regex = preg_replace('`^/\^`', '/', $regex);
$regex = preg_replace('`\$/$`', '/', $regex);
ᅵ tout hasard, quoique ᅵa n'ajoute pas forcᅵment de la lisibilitᅵ ici,
tu peux le faire en une seule passe :
$regex = preg_replace(array('`^/\^`', '`\$/$`'), '/', $regex);
Cela dit, ce qui me semblerait plus lisible est ce qui suit (ᅵ supposer
que la regexp commence et finit bien par '/^' et '$/' respectivement) :
$regex = substr_replace($regex, '/', 0, 2);
$regex = substr_replace($regex, '/', -2, 2);
Voire :
$regex = substr_replace($regex, '', 1, 1);
$regex = substr_replace($regex, '', -2, 1);
Ou encore :
$regex = '/' . substr($regex, 2, -2) . '/';
> if(preg_match_all($regex, $value, $r)) {
> $chaine = '';
> foreach($r[0] as $value) {
> echo '<p>'.$value.'</p>';
> $chaine .= $value;
> }
> return $chaine;
> }
> }
> else {
> if (preg_match($regex, $value)) return false;
> else return $message;
> }
> }
Je demande un peu de temps pour comprendre la fin de ce code...
> Autre chose : je n'ai pas trop compris pourquoi dans mon preg_replace je
> ne pouvais pas simplement mettre preg_replace('`\$$`', '', $regex, 1)
Ben... parce que le caractᅵre $ n'est pas le dernier de la chaᅵne ! Mais
bien sᅵr, si tu n'as qu'un seul caractᅵre $ ceci devrait fonctionner :
preg_replace('`\$`', '', $regex)
> (idem pour le ^).
C'est ici que le paramᅵtre limit ᅵ 1 peut servir ; que le caractᅵre ^
soit ou non tout seul, celui que tu veux virer est le premier :
preg_replace('`\^`', '', $regex, 1)
> Si vous avez pigᅵ qq chose ᅵ mes explications, y a-t-il quelque chose de
> moins moche ?
Oui : adapter ton test avec $filter=TRUE au cas par cas, plutᅵt que
d'essayer de deviner comment faire le SANITIZE ᅵ partir du VALIDATE !
Mais bon, j'ai encore ᅵ comprendre la fin de ton code.
--
Olivier Miakinen
> $regex = '/' . substr($regex, 2, -2) . '/';
>
Au fait, non parce qu'il y a parfois des options. Mais qu'est-ce donc
que ce Olivier qui ne tient pas compte de toutes les possibilitᅵs
existantes ?
> Le filtre FILTER_SANITIZE_REGEXP, tu veux dire ? Je ne vois pas bien ce
> que pourrait faire un tel filtre vu que pratiquement la totalitᅵ des
> caractᅵres Unicode peut se trouver dans une regexp.
>
??? FILTER_VALIDATE_REGEXP n'est pas lᅵ pour valider une regexp mais
bien pour valider des donnᅵes en fonction d'un regexp. Je cite "Valide
une valeur avec une expression rationnelle regexp"
Eh bien pareil pour FILTER : un filtre qui supprimerait tout ce qui ne
match pas la regexp.
>> (je dois dire que vu le
>> peu de possibilitᅵ, j'ai du mal ᅵ saisir l'intᅵrᅵt des filter_*).
>
> Euh... Ok pour le MD5, mais en ce qui concerne les adresses de courriel
> tu as bien FILTER_VALIDATE_EMAIL et FILTER_SANITIZE_EMAIL, qui sont
> certainement bien supᅵrieures ᅵ l'immense majoritᅵ des tests que l'on
> trouve sur la toile.
>
Youpi. Voilᅵ le seul qui sert effectivement ᅵ quelque chose.
> Pour n'importe quelle regexp ? Hum... J'aimerais bien voir comment il se
> dᅵbrouille avec la suivante :
ᅵa ne fonctionne effectivement pas *du tout* avec toutes les regexp (pas
testᅵ la tienne) et c'est bien pour ᅵa que j'aurais aimᅵ un
FILTER_SANITIZE_REGEXP !
> Oh, je rectifie ce que j'ai dit plus haut : tu acceptes aussi d'avoir
> plusieurs ᅵ . ᅵ de suite dans la partie droite, la seule restriction
> concernant le nombre de lettres aprᅵs le dernier !
L'erreur pour les domaines en 6 lettres, ok, je veux bien (ce n'ᅵtait
pas le propos du fil ; heureusement que j'ai pas postᅵ la douzaine de
regexp qu'il y a dans le code !). Pour le reste, c'est absolument
volontaire. J'avais une regexp trᅵs complᅵte (celle officielle tout
simplement) mais je n'en veux plus car je *ne* souhaite *pas* avoir
certains caractᅵres farfelus (pour des raisons que je ne vais pas
exposer puisque ce n'ᅵtait pas du tout le propos de ce fil).
>
>> break;
>> case "md5":
>> $regex="/^[0-9a-f]{32}+$/";
>
> Est-ce qu'il ne serait pas plus rapide de faire un strcspn avec la
> chaᅵne "0123456789abcdef" suivi d'un strlen ? Ce n'est pas forcᅵment le
> cas, hein, je me pose juste la question.
>
Et aprᅵs ᅵa se moque quand on compare "" ᅵ '' :)
Ici, le but est la concision.
> Voire :
> $regex = substr_replace($regex, '', 1, 1);
> $regex = substr_replace($regex, '', -2, 1);
> Ou encore :
> $regex = '/' . substr($regex, 2, -2) . '/';
>
Oui, tu as raison.
> Oui : adapter ton test avec $filter=TRUE au cas par cas, plutᅵt que
> d'essayer de deviner comment faire le SANITIZE ᅵ partir du VALIDATE !
> Mais bon, j'ai encore ᅵ comprendre la fin de ton code.
>
C'est dommage mais ᅵa semble ᅵtre la seule possibilitᅵ.
Je ne sais pas ce que tu essais de comprendre. La fonction renvoie un
message d'erreur (traduit selon la langue), sinon c'est que c'est ok.
ᅵa y est, j'ai compris la fin du code. J'ai deux critiques, une sur la
forme et une sur le fond.
Sur la forme d'abord :
Le 18/12/2009 22:45, Olivier Masson a ᅵcrit :
>
> if(preg_match_all($regex, $value, $r)) {
> $chaine = '';
> foreach($r[0] as $value) {
> echo '<p>'.$value.'</p>';
> $chaine .= $value;
> }
> return $chaine;
> }
Attention, il y a une accolade fermante en trop ici.
> }
> else {
> if (preg_match($regex, $value)) return false;
ᅵMHA, ce preg_match est complᅵtement inutile. En effet, pour qu'il serve
ᅵ quelque chose il faudrait qu'il retourne 1 alors que le preg_match_all
qui prᅵcᅵde aurait retournᅵ 0 ou FALSE, or je ne vois pas comment le
preg_match pourrait retourner autre chose que 0 ou FALSE dans les mᅵmes
conditions.
> else return $message;
> }
> }
Maintenant sur le fond. Ton SANITIZE gᅵnᅵrᅵ automatiquement ᅵ partir du
VALIDATE me semble inappropriᅵ. Prenons par exemple le cas du MD5 :
$regex="/^[0-9a-f]{32}+$/";
Un SANITIZE devrait logiquement supprimer tous les caractᅵres autres que
des chiffres hexa et rien que ceux-lᅵ. Supposons une sᅵrie de 128
chiffres hexa reprᅵsentant les 64 valeurs de 00 ᅵ 3f, et supposons que
le formatage (par exemple dans un courriel) place 40 chiffres hexa par
ligne :
000102030405060708090a0b0c0d0e0f10111213
1415161718191a1b1c1d1e1f2021222324252627
28292a2b2c2d2e2f303132333435363738393a3b
3c3d3e3f
On doit s'attendre logiquement ᅵ ce que le SANITIZE donne ceci :
000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f
Or, en rᅵalitᅵ, le tien donnera cela :
000102030405060708090a0b0c0d0e0f1415161718191a1b1c1d1e1f2021222328292a2b2c2d2e2f3031323334353637
Moi, j'appelle ᅵa un bug... Et donc, j'en reviens ᅵ mon conseil
prᅵcᅵdent : ᅵcrire le test de SANITIZE indᅵpendamment du test de
VALIDATE au lieu d'essayer de dᅵduire celui-lᅵ de celui-ci.
Cordialement,
--
Olivier Miakinen
Ah, donc ce n'ᅵtait pas un oubli de ne pas ancrer la deuxiᅵme regexp !
Dans ce cas, remplace au moins le preg_replace par un str_replace :
$regex = str_replace('$/', '/', $regex);
--
Olivier Miakinen
> Moi, j'appelle ᅵa un bug... Et donc, j'en reviens ᅵ mon conseil
> prᅵcᅵdent : ᅵcrire le test de SANITIZE indᅵpendamment du test de
> VALIDATE au lieu d'essayer de dᅵduire celui-lᅵ de celui-ci.
>
>
Oui, ᅵa me semble une option plus rᅵaliste. Je pensais que faire un
SANITIZE serait plus simple mais comme je bosse depuis 3j en ᅵtant
malade, j'ai un peu de mal...
Merci de ton aide.