IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

[Cookies] Guillemets simples et doubles?


Sujet :

Langage PHP

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 14
    Points : 7
    Points
    7
    Par défaut [Cookies] Guillemets simples et doubles?
    Bonjour,

    Voilà, je me doute que la question aie été abordée maintes fois, mais il faut bien qu'un post mette un terme à ce genre de questions...

    LA QUESTION:
    Comment insérer dans une base MySQL un texte plein (avec plusieurs guillemets simples, guillemets doubles etc...) sans modifier "le contenu de ce texte" une fois dans la base? (== quelle structure de requete utiliser et méthode d'échappement?).
    Par exemple, pour la phrase suivante...
    <texte à insérer>
    Alors il m'a dit "salut vieux".
    </texte à insérer>
    ... retrouver dans dans la BDD exactement:
    Alors il m'a dit "salut vieux".


    Juste avant l'insert, le texte est réécris pour confirmation.
    Je veux également pouvoir l'afficher exactement tel qu'il a été écrit, sans provoquer d'erreur et écrire la moitié du texte ;-) ...
    Quelqu'un a t'il un exemple qui marche à mettre en ligne svp?!
    Merci!!

    Yoyo

  2. #2
    Futur Membre du Club
    Inscrit en
    Février 2005
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 4
    Points : 5
    Points
    5
    Par défaut
    Je ne suis pas sur de bien comprendre ton soucis...

    Moi, pour ne pas avoir de soucis, j'utilise le fonction mysql_real_escape_string

    Plus précisément j'utilise même les fonctions suivantes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
     
    <?php
    /**
     * Applique la fonction stripslashes recursivement
     */
    function stripslashes_deep($value)
    {
       $value = is_array($value) ?
                   array_map('stripslashes_deep', $value) :
                   stripslashes($value);
     
       return $value;
    }
     
    /**
     * Protège la variable avant l'insertion
     */
    function quote_smart($value)
    {
       // Stripslashes si nécessaire
       if (get_magic_quotes_gpc()) {
           $value = stripslashes_deep($value);
       }
     
       // Protection si ce n'est pas un entier
       if (!is_int($value)) {
           $value = "'" . mysql_real_escape_string($value) . "'";
       }
     
       return $value;
    }
     
    // Connexion
    $link = mysql_connect('localhost', 'mysql_user', 'mysql_password')
       OR die('Could not connect: ' . mysql_error());
     
    // Fabrication d'une requête sécurisée
    $query = sprintf("SELECT * FROM users WHERE user=%s AND password=%s",
               quote_smart($_POST['username']),
               quote_smart($_POST['password']));
     
    mysql_query($query);
    ?>
    ça marche très très bien. Je n'ai rien inventé :
    http://fr.php.net/manual/fr/function...ape-string.php

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Bonjour Demiurge,

    Celà me semble un peu compliqué, même au niveau de la requete...

    En fait, j'ai un textarea (ou autre). L'utilisateur entre le texte qu'il veut, avec guillemets simples et doubles bien sûr...
    A la validation (get ou post celà dépend), il tombe sur une page réécrivant son texte à l'identique pour confirmation.
    Au clic sur confirmation (get ou post celà dépend), page de traitement qui fait fait l'insert réel dans la base.
    ENSUITE, je vais manuellement dans ma base MySQL, je cheque le contenu du champ textarea inséré : il est identique à ce que l'utilisateur avait marqué, c'est ce que je veux...
    ENSUITE, je fais une requete sur mon site pour extraire et afficher ce texte dans une page : il est toujours identique, c'est ce que je veux.

    Voilà ce que je souhaite faire...
    Si quelqu'un a un code (simple!) qui pemette de faire l'ensemble sans soucis (requetes incluses) il rendra (au moins) un homme heureux ;-)

    Merci!

    Yoyo

    P.S.: pour situer exactement mon problème, j'essaie des solutions d'échappement mais à force d'essayer, j'arrive avec:
    texte entré dans area: j'aime les "cheveux "verts"
    texte dans base : j\'aime les \\\"
    texte extrait dans page : idem texte base !
    Arf!!! C éreintant...

  4. #4
    Futur Membre du Club
    Inscrit en
    Février 2005
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Février 2005
    Messages : 4
    Points : 5
    Points
    5
    Par défaut
    Ce n'est pas compliqué, c'est ce qu'il faut faire pour :
    1. sécuriser son code
    2. éviter les erreurs
    3. éviter que le code envoyé via le form modifie le sens de la requête (très vrai pour les parties login/mdp)

    Il suffit de mettre ces fonctiosn dans un fichier include, et le tour est joué.

    Franchement, c'est ce qui est conseillé par php.net, et je pense que c'est une bonne référence !

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Bon, en fait le problème c'est que j'ai des requetes à rallonge, donc avec le type de requete:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $query = sprintf("SELECT * FROM users WHERE user=%s AND password=%s", 
               quote_smart($_POST['username']), 
               quote_smart($_POST['password']));
    ... çà va être un peu le bord.. pour s'y retrouver parmi mes 15 colonnes...

    D'autant qu'ensuite je fais des recherches sur les termes entrés dans la base, donc si je cherche - maitre d'hotel "génial" - il faut absolument que dans ma base ce soit écrit la même chose...

    S'il vous plait, qui pourrait me mettre un exemple simple que je puisse suivre avec 4 champs (genre idmessage, titre, envoyeur, message) avec 5 pages comprennant:
    - un masque de saisie
    - une page de confirmation de saisie qui réécrit exactement les valeurs écrites dans le masque (- ces valeurs sont ensuite renvoyées en post via hidden pour etre définitivement entrées dans la base en cliquant sur 'valider ces données')
    - une page permettant la lecture du message enregistré dans la base.
    - un masque txtbox permettant de chercher une expression (chaine) contenue dans le champ message (cette expression pouvant contenir des ' ou des ") - méthode LIKE suffisante...
    - une page affichant les résultats


    J'ai trop honte de vous demander çà mais j'ai tellement de mal à parvenir à faire ce truc simple qu'il me faut décomposer votre code (et composer le plus simplement possible) au goutte-à-goutte...
    Faites très simple, sérieux je commence à avoir peur, c'est juste une insertion-lecture et j'ai du mal !
    Merci à tous ceux qui se donnent du mal pour aider les plus faibles...
    Je perd trop de temps avec ces histoires de guillemets et simple-quote
    Yoyo

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Bon...
    Je voulais pas abuser, désolé...
    Mais çà m'aurait grâve aidé..
    Bref, celà ne m'a tout de même pas empêché de faire quelques tests en aparte, histoire d'avancer...
    Du coup, je gère correctement les simple quote (à priori)...

    Message envoyé par post dans textarea:
    Ceci est un test avec des simple'simple et des double"double.


    Page de confirmation des données entrées :
    Celà affiche correctement dans la page le message avec tous les ' et tous les "...
    Un input hidden est placé pour rebalancer en post dès que validé...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if ($_POST["message"]){ echo "<br>".stripslashes($_POST["message"]) ;
    echo"<input name='message' type='hidden' value=\"".$_POST["message"]."\">"; }
    Page d'enregistrement dans base:
    Le message enregistre seulement l'expression suivante dans la base:
    Ceci est un test avec des simple'simple et des double
    (et donc ignore totalement les " et ce qu'il y a après...)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    if (isset($_POST["message"])){
    $message= stripslashes(stripslashes($_POST["message"]));}else{$message="";}
     
    // REQUETE :
     
    $requete = "INSERT INTO mesmessages (titre,envoyeur,message)
    			VALUES (\"$idmessage\",\"$titre\",\"$message\")";

    Comment corriger pour que celà fonctionne correctement???
    Merci beaucoup,

    Yoyo

  7. #7
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    J'avais justement répondu aux questions de ce type (quels sont les traitements à faire pour mettre des données dans une requête, pour les afficher dans une page web et pour les afficher dans un champ de formulaire), avec une réponse précise et pertinente, mais le sujet semble avoir été effacé.

    Sur le moment je n'ai pas envie de le rerédiger, d'autant plus que je viens déjà de rédiger d'autres trucs longs (et un peu chiants, certes) il y a quelques minutes.
    D'ailleurs je me demande si ça a de l'intérêt de se démener pour écrire des messages intéressants puisqu'au final ils sont effacés.
    Boost ftw

  8. #8
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Insérer des données dans une requête.

    On génère en PHP une chaîne de caractères qu'on envoit ensuite à un SGBD indépendant pour gérer la requête ainsi construite.
    Tout comme il existe des types en PHP, il y aussi des types en SQL, mais ceux-ci ne sont pas vraiment liés.

    Par exemple une chaîne de caractères, en SQL, doit se trouver entre en guillemets simples.
    Ainsi, la requête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT titre FROM livres WHERE auteur = 'Simone Weil'
    est valide syntaxiquement.

    En PHP, sa déclaration devient
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = 'SELECT titre FROM livres WHERE auteur = \'Simone Weil\'';
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = "SELECT titre FROM livres WHERE auteur = 'Simone Weil'";
    selon que l'on choisisse d'utiliser les simples ou double guillemets pour déclarer la chaîne de caractères.

    Bien entendu, il faut qu'il soit possible que cette chaîne contienne elle-même un guillemet simple. Le système d'échappement dépend du SGBD, mais il existe globalement deux écoles : soit on échappe avec un \, soit avec un autre '.
    L'idéal, pour échapper, étant d'utiliser la fonction spécifique fournie par le pilote du SGBD (mysql_escape_string, sqlite_escape_string, etc.)

    Voyons voir ce que ça donne, naïvement (sans échappement), avec des variables en GET.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = "SELECT titre FROM livres WHERE auteur = '{$_GET['auteur']}'";
    (interprétation de la variable avec les guillemets doubles)
    ou
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = 'SELECT titre FROM livres WHERE auteur = \''.$_GET['auteur'].'\'';
    (concaténation, guillemets simples)
    Le plus souvent on retrouve apparement de la concaténation avec des guillemets doubles, probablement parce que les gens ne savent pas interpréter des tableaux à l'intérieur de ces derniers..

    Si vous mettez auteur à O'malley puis tentez d'executer la requête, vous aurez une syntax error de la part du SGBD.
    Dans ce cas, ce n'est pas dangereux, c'est juste un bug, mais dans d'autres cela peut produire une grave faille de sécurité.

    Comme la plupart des débutants font comme dans les exemples (mauvais) cités ci-dessus, PHP a inventé un mécanisme pour protéger les newbies de cette faille, que l'on appelle l'injection SQL. Ce système, c'est le magic_quotes_gpc.
    S'il est activé, il réalise tout bêtement un addslashes (ce qui correspond au moyen d'échappement de mysql) sur toutes les variables GET, POST et Cookie. Effectivement, ça protège. Mais c'est peu élégant, pas portable et surtout pas logique. Je suis désolé, moi quand je récupère $_GET['auteur'], je veux le contenu du paramètre passé dans l'url, pas un truc pré-encodé pour un certain SGBD.
    Il est donc nécessaire, au début de chaque script PHP, de détecter si magic_quotes_gpc est activé et si c'est le cas, effectuer un stripslashes récursivement sur toutes les valeurs de GET, POST et Cookie. Plus d'informations sur cette opération sur la documentation de la fonction get_magic_quotes_gpc().

    On obtient donc au final
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = 'SELECT titre FROM livres WHERE auteur = \''.la_fonction_dechappement_qui_va_bien($_GET['auteur']).'\'';
    (on est ici obligé d'utiliser la concaténation).
    Je conseille personnellement d'utiliser une classe générique pour faire de l'SQL et de créer alors une méthode "escape".

    Bon, d'accord, c'est moche et pas vraiment pratique à taper.
    Il est néanmoins facile de faire une fonction du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = uneFonctionGeniale('SELECT titre FROM livres WHERE auteur = ?', $_GET['auteur']);
    qui s'occupe alors, en fonction du type de la variable fournie, de convertir en type de la variable SQL et d'échapper si nécessaire.

    Note sur les types SQL numériques.
    Je vois souvent des trucs du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT titre FROM livres WHERE id = '6'
    Si id est déclaré comme étant un type numérique (int, smallint et compagnie) alors il ne devrait pas y avoir de guillemets simples. Cela fonctionne tout de même car la plupart des SGBD acceptent le transtypage.
    L'idéal est de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT titre FROM livres WHERE id = 6
    Attention, cela nécessite précaution si on utilise des variables PHP en GET qui sont des chaînes.
    Par exemple faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = 'SELECT titre FROM livres WHERE id = '.$_GET['id'];
    est dangereux (dans ce cas précis, à part produire des erreurs de syntaxe ou des comportements étranges, rien de critique)
    Il faudrait plutôt faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = 'SELECT titre FROM livres WHERE id = '.intval($_GET['id']);
    L'idéal étant, encore une fois, de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = uneFonctionGeniale('SELECT titre FROM livres WHERE id = ?', $_GET['id']);
    (pas optimisé mais pas de problème de sécurité) ou mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $sql = uneFonctionGeniale('SELECT titre FROM livres WHERE id = ?', intval($_GET['id']));
    Certains préféreront forcer le type avec des masques genre %d ou %s à la place du ?, à la printf.

    Bon, je pense avoir répondu, dans la globalité, au problème.
    Si ça ne suffit pas ou si certains points sont obscurs, merci de me le signaler.


    Afficher des données dans une page HTML

    HTML étant un sous-langage de SGML (XHTML étant un sous-langage de XML, modernisation de SGML), il est nécessaire de respecter sa syntaxe. En particulier, <, > et & sont des caractères réservés (pour définir des éléments et des entités), il faut donc les échapper avec un mécanisme particulier.
    De même, à l'intérieur des attributs, qu'on délimité généralement par des guillemets doubles, il faut échapper les guillemets doubles.
    En effet il ne faut pas écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <p>Regarde ça >> ;), c'est cool & cie.</p>
    mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <p>Regarde ça &gt;&gt; ;), c'est cool &amp; cie.</p>
    Ou encore, il ne faut pas écrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <input type="text" value="Mon nom est Bond, "James" Bond">
    mais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    <input type="text" value="Mon nom est Bond, &quot;James&quot; Bond">
    En PHP, tout cela se fait avec la fonction htmlspecialchars().
    La fonction htmlentities() réalise aussi un travail similaire mais en plus convertit les caractères non ASCII en entités, ce qui, en plus d'être inutile, est totalement stupide, du moins si l'on est capable de gérer son charset (ce qui devrait être le cas quand on rédige une application de gestion de contenu).

    Pour du texte normal (du texte dans un élément, pas dans un attribut quoi) il faut utiliser htmlspecialchars avec l'option ENT_NOQUOTES. On peut aussi l'utiliser avec les autres options, mais ce sont des octets gaspillés pour rien.
    Pour un attribut, on utilise htmlspecialchars avec l'option ENT_COMPAT, qui est l'option par défaut. Si on n'utilise pas les doubles guillemets mais les simples, il faut spécifier une autre option. Tout cela est documenté.
    Boost ftw

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Guillemet simple ou double ?
    Par yol-rt dans le forum Langage
    Réponses: 5
    Dernier message: 08/07/2010, 09h19
  2. Guillemets simples ou doubles
    Par Malikak dans le forum Langage
    Réponses: 5
    Dernier message: 22/06/2006, 18h05
  3. problème apostrophes simple et double
    Par dor_boucle dans le forum Langage
    Réponses: 9
    Dernier message: 20/02/2006, 13h48
  4. Réponses: 4
    Dernier message: 05/07/2004, 13h17

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo