Page 1 sur 1

htmlspecialchars ?

Posté : 13 sept. 2008, 11:39
par Pod
Bonjour,

J'aurais 2 questions par rapport à htmlspecialchars :

1/ Certains disent qu'il faut utiliser htmlspecialchars à l'affichage, d'autres à l'enregistrement. Qu'en est-il réellement ? Et pour intval (avant de stocker des nombres dans MySQL), est-ce de même ?
2/ Pour ma partie admin (contrôle d'une variable de session role définie à la connexion. Si l'utilisateur n'a pas accès à la zone il est redirigé. Ce contrôle est effctué sur toutes les pages d'admin), ai-je besoin aussi de sécuriser avec htmlspecialchars + intval ?


Merci

Posté : 13 sept. 2008, 14:08
par cwdev
Salut,

Certains caractères ont des significations spéciales en HTML, et doivent être remplacés par des entités HTML pour être affichés. htmlspecialchars() remplace tous ces caractères par leur équivalent dans la chaîne string . Cette conversion est très pratique pour la programmation web. Si vous devez remplacer tous les caractères, utilisez plutôt htmlentities() à la place.

htmlspecialchars() est pratique pour éviter que des données fournies par les utilisateurs contiennent des balises HTML, comme pour un forum ou un chat.

Les remplacements effectués sont :

"&" (et commercial) devient "&"
""" (guillemets doubles) devient """ lorsque ENT_NOQUOTES n'est pas utilisée.
"'" (guillemet simple) devient "'" uniquement lorsque ENT_QUOTES est utilisée.
"<" (inférieur à) devient "<"
">" (supérieur à) devient ">"
Donc comme tu le vois, cela ajoutera des caractères à ta base de données, ce qui est totalement inutile et en fonction de la grandeur de ton site, pourrait ralentir mysql.

Donc moi je dis à l'affichage et l'utilisation d'un mysql_escape_string avant l'insertion dans la bdd.
Maintenant évidemment les avis sont partagés.

.cwdev

Posté : 13 sept. 2008, 15:20
par Pod
Donc si j'interprète bien ta citation :
- pour intval(), pas de problèmes, autant l'utiliser à l'enregistrement ? Dans ce cas il n'y a pas besoin de faire mysql_real_escape_string().
- Ca ajoutera des caractères dans la BDD mais en échange, je gagne du temps à l'affichage non ?

Une autre question en passant :
- J'utilise TinyMCE pour ma partie admin. Seulement, si je mets htmlspecialchars, les liens etc sont transformés en texte et ne sont pas interprétés comme des liens. Comment puis-je faire (tout en gardant une certaine sécurité), sur certains forums etc le xHTML est autorisé. J'ai trouvé strip_tags() mais cette fonction est-elle sure ?

Merci

Posté : 13 sept. 2008, 17:02
par cwdev
Pour intval tout dépend de ce que tu veux faire.
Si tu passes par exemple 125.9, intval te retournera 125 (nombre entier).
Si tu veux protéger ta bdd, utilises mysql_real_escape_string
Si tu veux vérifier que la donnée est de forme numérique, utilises is_numeric

strip_tags supprime toutes les balises php et html donc tu auras le même problème.

Pour ta dernière question je ne vois pas le problème des liens, comment insères tu tes liens dans ta base de données ?

Posté : 13 sept. 2008, 18:00
par Pod
En fait actuellement je fais comme ceci :
- J'ai mon formulaire qui envoie des données récupérées en PHP
- Les variables sont traitées avec mysql_real_escape_string et htmlspecialchars/intval selon que ce soit du texte ou un nombre avant d'etre insérées dans la BDD.

Pour strip_tags :
strip_tags supprime toutes les balises sauf celles placées en deuxième argument.

Le problème c'est que j'utilise TinyMCE pour éditer des news etc. Il peut arriver que j'ai besoin de mettre en gras, de mettre des liens etc. Dans ce cas TinyMCE le fait en xHTML, bloqué par htmlspecialchars. Je voudrais donc autoriser quelques balises sûres (<a></a>, <strong></strong>, ...) tout en gardant un minimum de sécurité sur mon site.

Merci

Posté : 14 sept. 2008, 14:16
par cwdev
Donc si je comprends il y a un htmlspecialchars d'office à l'insertion.

Donc pour pouvoir decoder et afficher les liens par exemple, procèdes comme suit :

strip_tags(stripslashes(html_entity_decode($result['texte'])),'<a>');

J'ai essayé et cela fonctionne -> http://cwdev.homeip.net/tests/pod.php

.cwdev

Je te mets le code complet de la page en lien pour que tu voies
<?php
header('Content-type: text/html; charset=utf-8');
$texte = mysql_escape_string(htmlspecialchars($_POST['texte']));
mysql_connect("localhost", " ** ", "**");;
mysql_select_db("tests");
mysql_query('set names utf8');
if(!empty($texte))
{
$query = mysql_query("INSERT INTO pod VALUES('','$texte')")or exit('erreur query 1');
}
$query2 = mysql_query("SELECT * FROM pod ")or exit('erreur query2');
while($result = mysql_fetch_array($query2))
{
echo '<p>'.strip_tags(stripslashes(html_entity_decode($result['texte'])),'<a>').'</p>';
}
mysql_close();
echo '<form method="post" action="pod.php">
<p><textarea name="texte"></textarea></p>
<input type="submit" value="OK"/>
</form>';
?>


Posté : 14 sept. 2008, 14:29
par Pod
Ok, effectivement ça marche. Si ceci est sécurisé, voila (enfin) la solution à mes problèmes ^^

Juste : pourquoi utiliser html_entity_decode (inverse de htmlentities) et non htmlspecialchars_decode ?

Une raison particulière ?

Merci beaucoup ^^

Posté : 14 sept. 2008, 14:36
par cwdev
Euh non, erreur en allant trop vite, désolé. Je viens de répondre à qqun à propos de html_entity_decode sur un autre forum alors c'était resté dans ma tête

Posté : 14 sept. 2008, 15:45
par Pod
Ok. Merci pour toutes ces réponses.

Sujet résolu (je peux pas le marquer dans le titre, je ne suis qu'invité ...) !

Posté : 14 sept. 2008, 15:56
par chrislabricole
Sujet résolu (je peux pas le marquer dans le titre, je ne suis qu'invité ...) !
Alors inscris-toi :)
Un modérateur va venir le mettre ce [Résolu] ;)

Posté : 15 sept. 2008, 01:15
par AB
Donc si je comprends il y a un htmlspecialchars d'office à l'insertion.

Donc pour pouvoir decoder et afficher les liens par exemple, procèdes comme suit :

strip_tags(stripslashes(html_entity_decode($result['texte'])),'<a>');

J'ai essayé et cela fonctionne -> http://cwdev.homeip.net/tests/pod.php

.cwdev

Je te mets le code complet de la page en lien pour que tu voies
<?php
header('Content-type: text/html; charset=utf-8');
$texte = mysql_escape_string(htmlspecialchars($_POST['texte']));
mysql_connect("localhost", " ** ", "**");;
mysql_select_db("tests");
mysql_query('set names utf8');
if(!empty($texte))
{
$query = mysql_query("INSERT INTO pod VALUES('','$texte')")or exit('erreur query 1');
}
$query2 = mysql_query("SELECT * FROM pod ")or exit('erreur query2');
while($result = mysql_fetch_array($query2))
{
echo '<p>'.strip_tags(stripslashes(html_entity_decode($result['texte'])),'<a>').'</p>';
}
mysql_close();
echo '<form method="post" action="pod.php">
<p><textarea name="texte"></textarea></p>
<input type="submit" value="OK"/>
</form>';
?>


Ah bah c'est assez fantaisiste comme code :

1/ Il est conseillé d'utiliser mysql_real_escape_string() plutôt que mysql_escape_string(). Dans ce cas d'ailleurs il faudrait mettre mysql_real_escape_string() après la connexion sinon message d'erreur.

2/ Cela ne sert à rien de faire un htmlspecialchars() pour rentrer les données dans la base puisque tu l'enlèves pour l'affichage avec un htmlspecialchars_decode(). Donc autant ne pas en mettre.

3/ A quoi sert le stripslashes() ? Si tu le mets c'est sans doute parce que ton serveur a la config magic_quote activée. Mais cette option sera supprimée en php6 et il est de toutes façons déconseillé de l'utiliser. Donc pour que cela passe partout (quelque soit la config du serveur) on teste la config du serveur et on applique la fonction stripslashes() sur les données avant l'enregistrement dans la base. Typiquement on fait plutôt comme les premières lignes du code php de ce tuto

Posté : 15 sept. 2008, 08:53
par cwdev
Je suis d'accord pour mysql_escape_string.

Maintenant il utilise TinyCME qui apparement met d'office htmlspecialchars, je ne sais pas si il sait l'enlever donc c'est pour cela que je l'utilise à l'enregistrement des données.
Comme je l'ai dit plus haut dans le post, htmlspecialchars sert à l'affichage.
Oui magic_quotes est activé et je n'allais pas mettre la fonction pour le désactiver vu que ce n'est pas le but du sujet.

Posté : 15 sept. 2008, 14:05
par AB
...
Oui magic_quotes est activé et je n'allais pas mettre la fonction pour le désactiver vu que ce n'est pas le but du sujet.
Ok enfin il ne s'agit pas de désactiver cette fonction au niveau du serveur étant donné que pas mal de personnes travaillent sur des serveurs mutualisés (donc ils n'ont souvent pas accès à cette configuration), simplement de tester la configuration du serveur et d'utiliser stripslashes() uniquement en cas de besoin.
Le problème de ton exemple de code c'est qu'il fonctionnera mal si magic_quotes est désactivé (ce qui sera de plus en plus fréquent), c'est pour cette raison que je me suis permis de faire ces commentaires et de donner un lien vers un exemple de code "universel" :)

Ou alors si ce n'est pas le sujet, on en parle pas mais on ne l'utilise pas non plus sinon ça brouille les cartes pour les débutants. Il faut penser aussi que d'autres personnes que l'auteur du post peuvent lire le topic... C'était juste des remarques pour penser au côté pédagogique, mais bon personne ne t'en voudra d'aider à ta manière :wink:


J'ai bien vu que c'était Pod qui préférait insérer les données avec htmlspecialchars() dans la bdd. Ce n'est pas ton code que je critiquais mais le code que tu as été obligé de faire pour en tenir compte :wink:
On voit très vite la limite du raisonnement " Ca ajoutera des caractères dans la BDD mais en échange, je gagne du temps à l'affichage non ? ". Là précisément ça fait une fonction de plus pour l'enregistrement, l'alourdissement (pas judicieux) de la bdd, et une fonction de plus pour la lecture. Trois inconvénients pour aucun avantage :lol:

Pod, si tu nous lis... :)