8792 sujets

Développement web côté serveur, CMS

Pages :
Salut,
Voici ma première fonction, encore inachevée.
Bon, j'ai surtout galéré pour les expressions régulières...
Au final cette fonction devrait me permettre de traiter tout les réultats des
formulaires de mon site, avant de les enregistrer dans une BDD.
Je voudrais savoir ce que vous en pensez, si j'ai oublié des éléments importants pour la sécurité par exemple.


function MsgSecuDeco($message, $bbcode, $smilies)
{
$message=stripslashes($message);
$message=htmlentities($message, ENT_QUOTES); // SECU

//$message=preg_replace('/\n|\r|(\n\r)/m', '<br/>', $message); //remplace passage à la ligne par <br/>
$message=nl2br($message);
$message=trim($message); //enlève espace, ligne blanche...etc en début et fin de message

if ($bbcode=='on')
{
$message=preg_replace('!\[b\](.+)\[\/b\]!isU', '<strong>$1</strong>', $message); //gras
$message=preg_replace('!\[i\](.+)\[\/i\]!isU', '<strong>$1</strong>', $message); //italic
$message=preg_replace('!\[u\](.+)\[\/u\]!isU', '<strong>$1</strong>', $message); //souligné
$message=preg_replace('!\[color=(red|green|blue|yellow|purple|olive)\](.+)\[/color\]!isU', '<span style="color:$1">$2</span>', $message); 
$message=preg_replace('!\[code\](.+)\[\/code\]!isU', '&nbsp;&nbsp;<strong>[ code]</strong><div style="border:1px dashed #000000; background-color:#F0F0F0;">$1</div>&nbsp;&nbsp;<strong>[/ code]</strong>', $message);
$message = preg_replace('!http://[a-z0-9._/-]+!i', '<a href="$0" target="_blank">$0</a>', $message);
}

if ($smilies=='on')
{
$chemin='img/webdesign/smilies/';
$message=preg_replace('!:-\)|:\)!i', '<img src="'.$chemin.'sourire.gif" alt="smilie sourire" />', $message);
$message=preg_replace('!;-\)|;\)!i', '<img src="'.$chemin.'clin-doeil.gif" alt="smilie clin d\'oeil" />', $message);
$message=preg_replace('!:-\(|;\(!i', '<img src="'.$chemin.'triste.gif" alt="smilie triste" />', $message);
$message=str_replace(":&#039;-(", '<img src="'.$chemin.'pleure.gif" alt="smilie pleurant" />', $message);
$message=preg_replace('!:-o|:o!i', '<img src="'.$chemin.'etonne.gif" alt="smilie étonné" />', $message);
$message=preg_replace('!:o\)|:o\)!i', '<img src="'.$chemin.'clown.gif" alt="smilie clown" />', $message);

}

return $message;
}


Merci !

@ +
Modifié par Graph-Site (08 Aug 2005 - 20:49)
Après avoir longuement cherché à faire un parser BBCodes, j'ai finalement abandonné. J'avais quand même créé quelque chose d'assez complet mais qui ne génèrerait pas forcément du code valide (notamment à cause du croisement de balises).

J'ai relevé plusieurs erreurs :

* si c'est avant insertion dans la BD, que viens faire le stripslashes

* je n'utilise plus htmlentities avant insertion, je lui prefère htmlspecialchars qui encore juste les caractères indispensables, ne rallonge donc pas inutilement les chaînes, permet de faire des recherches dans la base plus facilement (sans avoir à tout convertir avant)... mais ça c'est une question de goût

* sur mon parseur au lieu du nl2br, je remplaçais 2 espaces successifs par un nouveau paragraphe

* si tu remplaces gras et souligné^par <strong> ça va pas le faire

* le souligné devrait être réservé au lien

* il faut remplacer tes (.+) par (.+?) dans tes regexp car je crois que si tu mets ça : <b>abc</b>def<b>ghi</b> il te le remplacer par abc</b>def<b> au lieu de abcdefghi

* pour optimiser ton code, au lieu de faire plein de preg_replace successifs il faut passer par des tableaux (nommés par exemple $pattern[] et $replacement[])

* pour tes smileys, passer par str_replace à la place de preg_replace sera plus optimisé (et passer pas des tableaux aussi)

* tu devrais afficher la taille de tes images dans la balise <img width="..." height="..." />

* que ce passera-t-il si je tape <b>abc<i>def</b>ghi</i> ? Réponse : un code non valide. (raison qui m'a fait passer à l'excellent parseur wiki de neokraft.net)

Bon courage Smiley cligne
Pour info, voici le code de mon parseur BBCodes abandonné. Je lui ai donné pas mal de fonctionnalité (un peu usine à gaz quoi...) mais j'ai buté au moment de voir comment je pouvais être sûr de générer un code XHTML strict (en détectant les croisements).

<?php
function bbDecode($txt)
{
	$txt=trim($txt);

	//liste :
	//[list]
	//[*]element1
	//[*]element2
	//[/list]
	$txt=preg_replace_callback('/\[list\]\r\n(\[\*\].*\r\n)\[\/list\]/si','decodeList',$txt);
	//image sans texte alternatif : [img]image.jpg[/img]
	$txt=preg_replace_callback('/\[img\](([a-z0-9~&#\/@=%\?\.:])+?)\[\/img\]/i','decodeImg',$txt);
	//image avec texte alternatif : [img=image.jpg]image[/img]
	$txt=preg_replace_callback('/\[img=(([a-z0-9~&#\/@=%\?\.:])+?)\](.+?)\[\/img\]/i','decodeImg',$txt);
	//lien sans texte : [url]http://www.google.fr[/url]
	$txt=preg_replace_callback('/\[url\](([a-z0-9~&#\/@=%\?\.:])+?)\[\/url\]/i','decodeUrl',$txt);
	//lien avec texte : [url=http://www.google.fr]google[/url]
	$txt=preg_replace_callback('/\[url=(([a-z0-9~&#\/@=%\?\.:])+?)\](.+?)\[\/url\]/i','decodeUrl',$txt);
	
	//email sans texte : [email]login@site.fr[/email]
	$search[0]='/\[email\]([[:alnum:]]([-_.]?[[:alnum:]])*@[[:alnum:]]([-.]?[[:alnum:]])*.([a-z]{2,6}))\[\/email\]/i';
	$replace[0]='<a href="mailto:\\1" title="\\1">\\1</a>';
	//email avec texte : [email=login@site.fr]login[/email]
	$search[1]='/\[email=([[:alnum:]]([-_.]?[[:alnum:]])*@[[:alnum:]]([-.]?[[:alnum:]])*.([a-z]{2,6}))\](.+)\[\/email\]/i';
	$replace[1]='<a href="mailto:\\1" title="\\5">\\5</a>';
	//texte en gras : [b]texte[/b]
	$search[2]='/\[b\](.+?)\[\/b\]/i';
	$replace[2]='<strong>\\1</strong>';
	//texte en italique : [i]texte[/i]
	$search[3]='/\[i\](.+?)\[\/i\]/i';
	$replace[3]='<em>\\1</em>';
	//texte barré : [s]texte[/s]
	$search[4]='/\[s\](.+?)\[\/s\]/i';
	$replace[4]='<del>\\1</del>';
	//texte plus grand : [larger] (...) [/larger]
	$search[5]='/\[big\](.+?)\[\/big\]/i';
	$replace[5]='<big>\\1</big>';
	//texte plus petit : [smaller] (...) [/smaller]
	$search[6]='/\[small\](.+?)\[\/small\]/i';
	$replace[6]='<small>\\1</small>';
	//citation sans l'auteur
	$search[7]='/\[quote\](.+?)\[\/quote\]/i';
	$replace[7]='<q>\\1</q>';
	//citation avec l'auteur
	$search[8]='/\[quote=(.+?)\](.+?)\[\/quote\]/i';
	$replace[8]='<cite>\\1</cite>&nbsp;: <q>\\2</q>';
	//retours à la ligne
	$search[9]='/(\r\n){2}(\r\n)*/';
	$replace[9]='</p>'."\n".'<p>';
	
	//remplacements...
	$txt=preg_replace($search,$replace,$txt);
	
	unset($search);
	unset($replace);
	
	//espace insécable devant !
	$search[0]=' !';
	$replace[0]='&nbsp;!';
	//espace insécable devant ?
	$search[1]=' ?';
	$replace[1]='&nbsp;?';
	//espace insécable devant ;
	$search[2]=' ;';
	$replace[2]='&nbsp;;';
	//espace insécable devant :
	$search[3]=' :';
	$replace[3]='&nbsp;:';
	//espace insécable devant «
	$search[4]='« ';
	$replace[4]='«&nbsp;';
	//espace insécable devant »
	$search[5]=' »';
	$replace[5]='&nbsp;»';
	//suppression des tabulations
	$search[6]="\t";
	$replace[6]='$nbsp;';
	//remplacement des sauts de ligne consécutifs
	$search[7]="\r\n";
	$replace[7]='<br />';
	//émoticône grand sourire [lol]
	$search[8]=':D';
	$replace[8]='<img src="./img/smileys/biggrin.gif" alt="Émoticône&nbsp;: grand sourire" width="15" height="15" />';
	//émoticône content [smile]
	$search[9]=':)';
	$replace[9]='<img src="./img/smileys/smile.gif" alt="Émoticône&nbsp;: content" width="15" height="15" />';
	//émoticône clin d'oeil [cligne]
	$search[10]=';)';
	$replace[10]='<img src="./img/smileys/wink.gif" alt="Émoticône&nbsp;: clin d\'oeil" width="15" height="15" />';
	//émoticône étonné :o
	$search[11]=':o';
	$replace[11]='<img src="./img/smileys/eek.gif" alt="Émoticône&nbsp;: étonné" width="15" height="15" />';
	//émoticône fâché :@
	$search[12]=':@';
	$replace[12]='<img src="./img/smileys/upsetw.gif" alt="Émoticône&nbsp;: fâché" width="15" height="15" />';	
	//émoticône cool 8)
	$search[13]='8)';
	$replace[13]='<img src="./img/smileys/cool.gif" alt="Émoticône&nbsp;: cool" width="15" height="15" />';	
	//émoticône triste  [decu]
	$search[14]=' [decu]';
	$replace[14]='<img src="./img/smileys/sad.gif" alt="Émoticône&nbsp;: triste" width="15" height="15" />';	
	//émoticône sarcastique @|
	$search[15]='@|';
	$replace[15]='<img src="./img/smileys/roll.gif" alt="Émoticône&nbsp;: sarcastique" width="15" height="15" />';	
	//remplacements
	$txt=str_replace($search,$replace,$txt);
	//affichage du texte décodé
	return '<p>'.$txt.'</p>';
}

//liste :
//[list]
//[*]element1
//[*]element2
//[/list]
function decodeList($txt)
{
	return preg_replace('/\[\*\]([^(\[\*\])]+)\r\n/si','<li>\\1</li>','<ul>'.$txt[1].'</ul>');
}

//image sans texte alternatif : [img]image.jpg[/img]
//image avec texte alternatif : [img=image.jpg]image[/img]
function decodeImg($img)
{
	if(is_file($img[1])&&is_readable($img[1]))
	{
		$imgSize=getimagesize($img[1]);
		if(!isset($img[3]))
		{
			return '<img src="'.$img[1].'" alt="'.$img[1].'" '.$imgSize[3].' />';
		}
		else
		{
			return '<img src="'.$img[1].'" alt="'.$img[3].'" '.$imgSize[3].' />';
		}	
	}
	else
	{
		if(!isset($img[3]))
		{
			return '[img]'.$img[1].'[/img]';
		}
		else
		{
			return '[img='.$img[1].']'.$img[3].'[/img]';
		}
	}
}

//lien sans texte : [url]http://www.google.fr[/url]
//lien avec texte : [url=http://www.google.fr]google[/url]
function decodeUrl($url)
{
	if(@fopen($url[1],'r'))
	{
		if(!isset($url[3]))
		{
			return '<a href="'.$url[1].'" title="'.$url[1].'">'.$url[1].'</a>';
		}
		else
		{
			return '<a href="'.$url[1].'" title="'.$url[3].'">'.$url[3].'</a>';
		}	
	}
	else
	{
		if(!isset($url[3]))
		{
			return '[url]'.$url[1].'[/url]';
		}
		else
		{
			return '[url='.$url[1].']'.$url[3].'[/url]';
		}	
	}
}

//Avant insertion dans la base de données...
function bbCode($txt)
{
	return htmlspecialchars($txt,ENT_QUOTES);
}
?>
Salut, merci pour ta réponse, qui est vraiment très complète Smiley cligne

a écrit :
si c'est avant insertion dans la BD, que viens faire le stripslashes

> et bien si je me rapelle bien, lorsque l'on récupère les résultats dun formulaire en POST...il y a des \ devant les ' et " ...
Je préfère donc les enlever avant de mettre le htmlentities, avec un ENT_QUOTES qui si je me rappelle bien va coder les ' et " ave leurs équivalents HTML et ainsi éviter leur interprétation. J'ai bon ?

a écrit :
htmlspecialchars()

> Merci, c'est mieux en effet Smiley smile


a écrit :
si tu remplaces gras et souligné^par <strong> ça va pas le faire

> en effet...petite étourderie, mais comme je l'ai dis, je n'ai pas fini Smiley smile

a écrit :
le souligné devrait être réservé au lien

Pourquoi ? C'est relatif à l'accessibilité ?

Pour ceci [b ]abc[/b ]def[b ]ghi[ /b] et bien ça marche impeccablement.
Le fait de mettre un ? serait à mon avis incorrect puisque le + est déjà un "quantifieur"...

Array=très bonne idée, mais comme j'ab*vais vraiment du mal au début j'ai préféré commencer simple Smiley cligne je vais maintenant pouvoir corriger !

Pour les smilie, je pense qu'actuellement c'est bien étant donné qu'à chaque fois, il y a plusieurs possibilités pour un même résultat, donc je ne vois pas comment faire ça avec str_replace()

a écrit :
tu devrais afficher la taille de tes images dans la balise <img width="..." height="..." />

Oui, c'est prévu merci, mais je n'ai pas encore choisi les smilies.

Pour le croisement des balises, c'est vrai, mais je ne suis pas capable de résoudre ce problème, je vais chercher un peu vois si je trouve des exemples.

Merci pour ton aide, pour l'adresse, et pour ton code qui m'aidera sans doute à améliorer la synthaxe du mien Smiley smile
Modifié par Graph-Site (09 Aug 2005 - 08:56)
Graph-Site a écrit :
lorsque l'on récupère les résultats dun formulaire en POST...il y a des \ devant les ' et "
Je ne crois pas non.
Graph-Site a écrit :
Pourquoi ? C'est relatif à l'accessibilité ?
Oui.
Graph-Site a écrit :
Pour ceci [b ]abc[/b ]def[b ]ghi[ /b] et bien ça marche impeccablement. Le fait de mettre un ? serait à mon avis un conrrect puisque le + est déjà un "quantifieur"...
Si tu recherches une occurence de <b>(.+)</b> il serait aussi correcte qu'on te retourne <b>blabla</b> que <b>blab</b>bla</b> par exemple. Or j'ai constaté que de mettre (.+?) empêchait cette erreur. Si ça marche chez toi tant mieux mais je ne pense pas que ce soit une erreur.
Graph-Site a écrit :
à chaque fois, il y a plusieurs possibilités pour un même résultat, donc je ne vois pas comment faire ça avec str_replace()
c'est simple :
$search[0]=':)';
$pattern[0]='<img src="content.gif" alt="content" width="15" height"15" />';
$search[1]=' [smile]';
$pattern[1]='<img src="content.gif" alt="content" width="15" height"15" />';
L'utilisation de tableau étant nettement plus rapide, je crois que cette solution restera plus rapide que la tienne surtout que str_replace est sur des petites chaînes plus rapides que preg_replace.
Graph-Site a écrit :
tu devrais afficher la taille de tes images dans la balise <img width="..." height="..." /> Oui, c'est prévu merci, mais je n'ai pas encore choisi les smilies.
Mon conseil serait dechoisir des smileys tous de même dimension pour ne pas perturber l'affichage de ton texte, c'est à dire pour que tous les interlignes soient à peu près égaux.
Graph-Site a écrit :
Pour le croisement des balises, c'est vrai, mais je ne suis pas capable de résoudre ce problème, je vais chercher un peu vois si je trouve des exemples.
C'est tout à fait possible mais c'est très compliqué, surtout que contrairement à moi (qui n'ai pas réussi je le rappelle) tu n'as pas de formation en informatique (algorithmique).

Bon courage cependant !
a écrit :

$search[0]=':)';
$pattern[0]='<img src="content.gif" alt="content" width="15" height"15" />';
$search[1]=' smile ';
$pattern[1]='<img src="content.gif" alt="content" width="15" height"15" />';


que je suis bête moi (surtout le matin en me levant ! lol)

a écrit :
Mon conseil serait dechoisir des smileys tous de même dimension pour ne pas perturber l'affichage de ton texte, c'est à dire pour que tous les interlignes soient à peu près égaux.

Oui, c'est un bon conseil, mais il n'y à pas de prob, c'est ce que je comptais faire, sauf que je ne sais pas encore quelle sera la taille des smilies en général 15x15 sans doute mais peut-être un peu plus !

a écrit :
C'est tout à fait possible mais c'est très compliqué, surtout que contrairement à moi (qui n'ai pas réussi je le rappelle) tu n'as pas de formation en informatique (algorithmique).

hehe, mais j'ai moi aussi une formation en informatique très poussée :
l'année dernière, en seconde, j'ai pris l'option Mesure Physique et Informatique Smiley lol mdr
Peut-être y arriverais-je si je trouve un code tout beau tout propre fourni par un(e) gentil(le) programmeur(/euse) Smiley ravi

a écrit :
Je ne crois pas non.

Pourtant je suis quasi sûr, je vais coder un petit exemple vite fait.

EDIT :
Pour le stripslashes :
<?php
if (isset($_POST['message']))
{
$message=$_POST['message'];
echo $message.'<hr /><br />';
$message=stripslashes($message);
echo $message;
}
else {
?>
<form  action="form.php" method="POST">
<textarea name="message"></textarea>
<input type="submit" value="go">
</form>

<?php
}
?>


Si je tape test ' " dans le texte area $_POST['message'] devient test ' "
Si je lui applique la fonction, le message redevient bien ce que j'avais tapé Smiley cligne
Le résultat est le même avec un input type=text à la place du textarea

Tu n'aurais pas stp quelque chose à propos du soulignement et de son importance pour les liens ?
Modifié par Graph-Site (09 Aug 2005 - 09:46)
Il me semblait que l'envoi "brut" de données provenant d'un textarea vers un champs d'une table type text avait le même effet que le stripslahes(). Essaye d'envoyer un $_POST['texte'] contenant des guillemets, tu verras bien… Smiley smile
ah d'accord, c'est bon à savoir Smiley cligne
Mais étant donné que je ne l'envois pas directement, je suis donc obligé de faire un strislashes ?
a écrit :
je suis donc obligé de faire un strislashes ?

Je ne pense pas, non… Essaye sans la fonction stripslashes tu verras bien…
Normalement,
on fait un stripslashes a l'affichage !
Pas au moment d'inserer dans la BDD.

Les anti slashes servent justement a éviter les injection SQL...

Pour le htmlspecialchars, pareil, je le prefere a htmlentities.

En ce qui concerne les smilies, moi je prefere les générer a l'affichage, car sur un champs de BDD a nombre de caractéres limité, cela peut poser probleme !

En ce qui concerne la procedure de BBcode,
je t'invite a lire l'article de Dew, tres bien fait a cette adresse

Enfin, pour ce qui est du croisement des balises, en effet cela serais plutôt compliquer a mettre en place, et j'avou ne jamais y avoir reelement penser Smiley ohwell

Bonne chance Smiley cligne
Merci,
Je crois qu'en effet, j'ai pris le problème à l'envers, mieux vaut que je traite les messages en les affichant, ce sera beaucoup plus logique Smiley smile
Bon, je refait complètement cette fonction, mais je vais en faire 2 ou 3 à la place Smiley smile
Merci @ tous encore une fois Smiley cligne
Mobman02 a écrit :
Normalement,
on fait un stripslashes a l'affichage !
Pas au moment d'inserer dans la BDD.

Les anti slashes servent justement a éviter les injection SQL...

C'est plus sûr de :
- faire un stripslashes() sur les données envoyées par l'utilisateur,
- vérifier ces données (caractères autorisés, longueur de la chaine, etc.),
- utiliser mysql_real_escape_string() au moment d'insérer les données en base.

Extrait de la doc à propos de mysql_real_escape_string() :
a écrit :
Cette fonction doit toujours (avec quelques exceptions) être utilisée pour protéger vos données avant d'envoyer la requête à MySQL.
Faire du parsing à l'affichage (comme convertir les smileys en texte, ou le BBcode) c'est une très mauvaise idée, pour une raison logique de performances : à l'insertion, c'est une seule fois, à l'affichage, c'est à chaque fois...

Il faut toujours faire le plus possible à l'insertion, ça sera toujours profitable (l'argument de la place prise dans la BDD ne fais pas le poids dans ce cas).
Elentar a écrit :
Faire du parsing à l'affichage (comme convertir les smileys en texte, ou le BBcode) c'est une très mauvaise idée, pour une raison logique de performances : à l'insertion, c'est une seule fois, à l'affichage, c'est à chaque fois...

Il faut toujours faire le plus possible à l'insertion, ça sera toujours profitable (l'argument de la place prise dans la BDD ne fais pas le poids dans ce cas).


ah je pense que pour ce que tu affirmes il y bien 10 sortes de gens ...
ça se tiens, c'est vrai...bon, à mon en fait tu as largement raison !
Mais je devrais tout de même traiter les résultats dans le sens inverse,
lorsque la personne voudra éditer un message...

merci à tous
djfeat a écrit :
- utiliser mysql_real_escape_string() au moment d'insérer les données en base.
Je ne connaissais pas cette fonction tiens. Si toutes les données des requêtes sont codées avec htmlspecialchars ou urlencode, y'a-t-il encore des craintes à avoir quant à la sécurité ?
Elentar a écrit :
Faire du parsing à l'affichage (comme convertir les smileys en texte, ou le BBcode) c'est une très mauvaise idée, pour une raison logique de performances : à l'insertion, c'est une seule fois, à l'affichage, c'est à chaque fois...

Il faut toujours faire le plus possible à l'insertion, ça sera toujours profitable (l'argument de la place prise dans la BDD ne fais pas le poids dans ce cas).
Ca se tient. Pour défendre l'autre partie, je dirais que c'est plus pérenne de faire ça dans l'autre sens car le HTML est plus facilement amené à évoluer que le BBCode. Et puis si l'on fait les modification il faut prévoir un parser qui fait BBCode -> HTML et un autre qui fait HTML -> BBCode; ceci pour permettre de proposer à l'utilisateur ce qu'il a déjà saisi, s'il a des modifs à faire.

Effectivement au niveau des performances c'est pas la meilleure solution, mais avec un système de cache (tout de suite les grand moyens Smiley lol )... ça se fait !
solo > ce n'est pas faux, c'est sûr.
Parser à l'affichage a ses avantages, et selon les cas ça peut être préférable (par exemple lorsqu'il y a plusieurs syntaxes, comment savoir laquelle a utilisé la personne pour rédiger son message, lorsqu'elle veut l'éditer ?).

Dans les cas les plus courants de l'utilisation de BBcode, je pense quand même qu'il est préférable d'épargner un parsing à chaque affichage.
Après on pourrait discuter longtemps sur ça, mais on ne pourra pas se mettre d'accord pour un cas général de toutes façons Smiley lol

Graph-Site > Exact, il faut coder un unparser dans ce cas.
Mais vu qu'on visualise plus souvent un message qu'on l'édite (enfin, dans la plupart des scripts...), ça reste du boulot en moins pour le serveur.
Modifié par Elentar (09 Aug 2005 - 17:30)
Pour apporter un éclairage complémentaire : le problème se pose de manière beaucoup plus velue pour les wikis.

Ceux-ci, dans leur quasi-totalité, font du parsing à l'affichage et garde en BDD la source en syntaxe wiki (cas-type: wikipedia)

Parmi les raisons :
- le double parsing à l'édition, jouable avec une syntaxe simple du type BBCode, devient très aventureux avec une syntaxe plus complexe.
- le mode édition étant au moins aussi utilisé que le mode affichage, le stokage HTML en BDD serait assez pervers pour l'économie de ressources serveur
- le recours aux caches serveur/client compense efficacement le coût du parsing à l'affichage
- les procédures d'export sont simplifiées, puisque la même base de parser peut être exploitée pour produire plusieurs formats en sortie à partir de la BDD

le Il faut toujours faire le plus possible à l'insertion... n'est en fait pas si simple Smiley cligne
Modifié par Laurent Denis (09 Aug 2005 - 17:43)
Pages :