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 :

[Système] Accents et locales


Sujet :

Langage PHP

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 7
    Par défaut [Système] Accents et locales
    Bonjour,

    J'essaie d'écrire une fonction qui me renvoie true si la chaine passée en argument est considérée comme correcte, false sinon. Elle est destinée à être utilisée pour traiter toutes les données venant des formulaires.

    Sont considérés comme corrects les caractères suivants:
    a-z A-Z 0-9 '

    J'ai donc écrit:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function isCorrectString($str){
    	return ereg("^[a-zA-Z0-9'(\')èéàç]+$", $str);
    }
    note: le (\') est là car, pour une raison que j'ignore, mon script récupère \' quand je tape ' dans mon champ de texte de formulaire, comme s'il addslashait automatiquement (option du serveur?).

    Le problème est que les chaines avec des accents donnent un retour à false au lieu de true. J'ai testé différentes façon d'écrire l'expression régulière mais rien n'y fait.

    De même, ereg("[èéàç]", $str); renvoie toujours false, même quand je tape une chaine contenant un ou plusieurs caractères accentués.

    Le serveur apache sur lequel le code php s'execute est en ISO8859-1. J'ai essayé un setlocale(LC_ALL,'fr-FR.ISO8859-1'); en début de code php mais ça ne change rien.

    Je suis assez désemparé car c'est pour projet important pour moi et la sécurité se doit d'être forte, je tiens vraiment à limiter l'étendue des caractères acceptés dans une chaîne (seul le ' est autorisé, mais la chaine est soumise ensuite à mysql_escape_string()).

    Si quelqu'un connaît ou soupçonne la raison de ce comportement de php, j'apprécierais énormément votre aide.

  2. #2
    Membre émérite

    Profil pro
    H4X0|2 @ YourLabs Business Service
    Inscrit en
    Octobre 2006
    Messages
    657
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : H4X0|2 @ YourLabs Business Service
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2006
    Messages : 657
    Par défaut
    Citation Envoyé par http://fr3.php.net/manual/fr/reference.pcre.pattern.syntax.php
    \xhh
    caractère en hexadécimal, de code hh
    Des codes hexa de lettres accentuées : http://perso-info.enst-bretagne.fr/~...o/faq.html#q17

  3. #3
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Par défaut
    Vous avez visiblement les magic_quotes activées sur votre serveur auquel cas la fonction stripslashes devrait régler le problème (attention cependant à ne pas oublier d'appeler des fonctions comme mysql_real_escape_string en fonction de ce à quoi vont servir vos différentes données).

    Je ne pense pas que les fonctions POSIX (ereg*) utilisent les informations des locales à l'inverse des fonctions PCRE (preg_*). D'autres avantages à utiliser ces fonctions (PCRE) : elles subsisteront à terme ce qui n'est pas le cas des fonctions POSIX, elles sont plus performantes et plus souples.

    Note : [a-zA-Z0-9'(\')èéàç] ne correspond pas à ce que je pense que vous pensez. Il s'agit d'une classe de caractères donc chaque caractère qui y apparaît sera traité de façon indépendante et solitaire : le bout (\') sera considéré comme ( ou ) ou un caractère qui n'est pas censé exister \'.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function isCorrectString($str) {
        return preg_match("/^[[:alnum:]']+$/i", stripslashes($str));
    }

  4. #4
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 7
    Par défaut
    Merci beaucoup pour vos réponses.

    Solution de is_null:
    Ca fonctionne. Il suffit de donner les codes hexa des caractères que l'on veut. La doc php dit:
    Après "\x", deux caractères hexadécimaux sont lus (les lettres peuvent être en majuscule ou minuscule). En mode UTF-8, "\x{...}" est aurotisé, où le contenu des accolades est une chaîne hexadécimale. Il sera interprété comme un caractère UTF-8 où le numéro de code est le numéro hexadécimal donné. La séquence d'échappement hexadécimale originale, \xhh, correspond à un caractère UTF-8 sur 2 octets si la valeur est plus grande que 127.
    J'ai donc fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    return ereg("^[a-zA-Z0-9'(\')\xe9\xc9\xe8\xc8\xea\xca\xeb\xcb\xe0\xc0\xe4\xc4\xee\xce\xef\xcf\xf9\xfc\xdc\xe7\xc7]+$", $str);
    et ça marche. Par contre comme le dit julp, les caractères "(" , ")" et " \' " sont pris en compte alors qu'ils ne devraient pas. Un strip_slashes devrait résoudre le problème.

    Merci is_null !

    Je vais tester de ce pas la solution de julp qui a l'air plus propre et me renseigner sur les fonctions PCRE et magic_quotes (mon code est destiné à être utilisé par plusieurs personnes différentes et peut être que tous les serveurs n'auront pas la même configuration concernant magic_quotes).

    Je vous tient au courant de mes recherches, merci encore!

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 7
    Par défaut
    Quelques nouvelles:

    Effectivement j'ai les magic_quotes activés. Il me faut donc adapter mon code à la configuration du serveur. J'ai trouvé un code qui supprime les \ du tableau passé en argument et un code nettoyant les tableaux des magic_quotes dont le fonctionnement m'échappe un peu.

    Comme je traite toujours les données venant de mes formulaires avec plusieurs méthodes (trim(), html_special_chars(), ...), j'ai simplement créé une petite méthode qui vire les \ si les magic_quotes sont activés.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    // supprime les \ d'echappement si magic_quotes_gpc est activé
    // a utiliser pour toutes les donnees venant de l'utilisateur (GET, POST, COOKIES, ...)
    function remove_magic_quotes($str){
    	if(get_magic_quotes_gpc() == 1){
    		$str = stripslashes($str);
    	}
    	return $str;
    }
    Maintenant je peux utiliser la fonction de julp, mais je précise 2 points:
    - il faut tout de même rajouter les caractères accentués avec leur codes hexadécimaux \xhh
    - une chaine contenant un \ suivit d'un caractère est reconnue par l'expression régulière. Je suppose que c'est parcequ'il s'attends à une option. C'est un peu embettant car un \ n'a rien a faire dans les données que j'attends d'un formulaire, mais je ne vois pas trop comment faire pour résoudre ce problème.

    J'espère que tout ça pourra servir à d'autres !

    Merci encore pour vos réponses!

  6. #6
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Par défaut
    Citation Envoyé par Jihash
    - il faut tout de même rajouter les caractères accentués avec leur codes hexadécimaux \xhh
    C'est que vos locales ne sont pas convenablement configurées.

    Citation Envoyé par Jihash
    - une chaine contenant un \ suivit d'un caractère est reconnue par l'expression régulière. Je suppose que c'est parcequ'il s'attends à une option. C'est un peu embettant car un \ n'a rien a faire dans les données que j'attends d'un formulaire, mais je ne vois pas trop comment faire pour résoudre ce problème.
    Pourriez-vous être plus précis/clair ? Il existe des caractères spéciaux dont les plus connus sont \t pour la tabulation et \r et/ou \n pour une nouvelle ligne suivant le système d'exploitation employé. N'oubliez pas non plus que les métacaractères ont besoin d'être échappés afin qu'ils retrouvent leur signification en tant que simple caractère ([, ], (, ), +, *, ... - voir la fonction preg_quote). Enfin pour une séquence de caractères (c'est à dire une suite d'au moins deux caractères), une classe de caractères ne vous permettra pas de faire valoir celle-ci en tant que chaîne. Il faut alors employer les alternatives (|). Exemple : je veux toto ou un nombre : ^toto|[0-9]+$ et non ^[0-9toto]+$ ou ^[0-9to]+$ (motifs autorisant des correspondances comme t0t0 ou encore 91to23, ...). Mais vous aviez peut être déjà compris ce point pour avoir tenté de vous l'expliquer plus tôt.

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 7
    Par défaut
    Pour être plus clair, oici les résultats de is_correct_string en fonction de la chaîne en argument:

    Chaine: \ retour: false
    Chaine: df\ retour: true
    Chaine: \fg retour: true
    Chaine: sq\hg retour: true

  8. #8
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Par défaut
    Il faut alors corriger le motif. Pourriez-vous nous redonner le code complet actuel de la fonction ?

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 7
    Par défaut
    Citation Envoyé par julp
    C'est que vos locales ne sont pas convenablement configurées.
    A priori (si j'ai bien compris) ce n'est pas un problème car mon code doit être compatible anglais / français. Si je précise le code hexadécimal, je n'ai aucun problème quelles que soient les locales et quel que soit l'environnement. Me trompe-je? (je suis encore débutant en php)

    Le code de la fonction est le suivant:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function is_correct_string($str){
    	return preg_match("/^[a-z0-9'\xe9\xc9\xe8\xc8\xea\xca\xeb\xcb\xe0\xc0\xe4\xc4\xee\xce\xef\xcf\xf9\xfc\xdc\xe7\xc7]+$/i", remove_magic_quotes($str));
    }
    Si on supprime les codes hexa des caractères accentués (pour plus de clarté) ça donne ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function is_correct_string($str){
    	return preg_match("/^[a-z0-9']+$/i", remove_magic_quotes($str));
    }

  10. #10
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Par défaut
    Citation Envoyé par Jihash
    A priori (si j'ai bien compris) ce n'est pas un problème car mon code doit être compatible anglais / français. Si je précise le code hexadécimal, je n'ai aucun problème quelles que soient les locales et quel que soit l'environnement. Me trompe-je? (je suis encore débutant en php)
    ça dépendra encore une fois de vos locales car les caractères accentués sont situés dans la partie ASCII étendue donc si le serveur utilise un encodage cyrillique, par exemple, il trouvera d'autres caractères avec ces codes.

    Même en activant les magic_quotes_gpc je n'obtiens pas de correspondances lorsque j'ajoute un ou des backslashs

    Par contre pour revenir sur les accents, j'ai oublié de corriger la classe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    function is_correct_string($str){
    	return preg_match("/^[[:alnum:]']+$/i", remove_magic_quotes($str));
    }
    [:alnum:] est l'équivalent de [a-zA-Z0-9] mais inclue les accents (sinon ce n'est pas le cas).

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 7
    Par défaut
    Merci pour la classe [:alnum:].

    Je suis désolé, mais je n'arrive pas à comprendre ce problème de locales. Mes différents recherches sur google me donnent des résultats qui ont peu à voir avec mon problème (comment changer les locales de sa machine, histoire de l'utf-8, ...).

    Ma machine utilise utf-8 (un $ locale -a me le confirme).
    Je suppose que mon serveur apache (local) et php utilisent donc utf-8 eux aussi. Cependant j'ai lu que php était incapable de gérer utf-8 et considérait donc les données comme du ISO8859.

    Pour info, phpmyadmin me donne ça à propos des variables du serveur:
    character set client utf8
    (Valeur globale) latin1
    character set connection utf8
    (Valeur globale) latin1
    character set database latin1
    character set filesystem binary
    character set results utf8
    (Valeur globale) latin1
    character set server latin1
    character set system utf8
    character sets dir /usr/share/mysql/charsets/
    collation connection utf8_unicode_ci
    (Valeur globale) latin1_swedish_ci
    collation database latin1_swedish_ci
    collation server latin1_swedish_ci
    Je précise que les caractères accentués de la chaîne testée par is_correct_string(string) s'affichent normalement quand je dis a mon navigateur d'utiliser ISO8859 et de manière incorrecte quand je lui dit d'utiliser utf-8. Celà laisse supposer que si is_correct_string ne reconnaît pas les chaînes accentuées c'est qu'il traite les chaînes en utilisant utf-8 et non iso8859-1 (ou 8859-15).
    Pourtant setlocale(LC_ALL,'fr-FR.ISO8859-1'); n'a rien changé

    Tous les setlocale que j'ai pu faire n'ont rien changé. Je n'y comprends pas grand chose.
    A quoi sert la fonction setlocale? Comment les locales sont utilisées par le serveur et par le script php?

    De plus, je m'inquiète pour la portabilité de mon code. Comment le faire fonctionner sur des serveurs différents?

    Merci de votre attention

    Citation Envoyé par julp
    Même en activant les magic_quotes_gpc je n'obtiens pas de correspondances lorsque j'ajoute un ou des backslashs
    Peut-être que justement le backslash fait partie de la 2ème partie de la table ascii?

    C'est étrange effectivement, mais moins gênant que les accents. De plus, je dois peut-être pouvoir arriver a quelquechose en rajoutant [^\\] dans ma regexp.

  12. #12
    Membre expérimenté

    Profil pro
    Inscrit en
    Juin 2002
    Messages
    6 152
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2002
    Messages : 6 152
    Par défaut
    Les accents ne passent toujours pas ? La partie importante des locales c'est la langue (permet les comparaisons, définir quel caractère appartient à quelle classe, ...) - cf man 5 locale.

    Oui définir la liste des caractères interdits est une autre méthode pour définir les caractères qui sont autorisés à figurer. Mais les backslahs en trop ont forcément une origine (ont été doublés par un traitement comme addslashes par exemple).

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2007
    Messages : 7
    Par défaut
    Ca y est, ça marche. Voici comment j'ai résolu le problème.

    1- Rappel des faits:
    En demandant au navigateur d'afficher la page dans différents charsets, on s'aperçoit que les caractères accentués ne sont pas affichés correctement avec utf-8. Sachant que mon serveur est sur ma machine et que ma machine utilise utf-8, j'en déduit que par défaut le serveur utilise utf-8 pour tester les chaines de caractères et que c'est pour celà que les caractères accentués sont rejetés.

    2- La solution devrait être de dire, en tête du script, d'utiliser un jeu de caractères acceptant les accents (Les ISO-8859-1 ou ISO-8859-15 ou un simple fr_FR). Je fais donc des setlocale( LC_ALL, 'fr_FR' ); et des setlocale(LC_ALL,'fr-FR.ISO8859-1'); en début de script.
    Resultat: ça ne change rien.

    3- Je me demande si les locales de jeux de caractères sus-cités existent bien sur mon système. Après vérification, je m'aperçoit que seul utf-8 est installé. J'installe donc (après maintes péripéties) la locale fr_FR (sans pour autant l'utiliser par defaut sur mon système).

    4- En faisant setlocale( LC_ALL, 'fr_FR' ); en début de script, ça marche! les caractères accentués, trémas et autres ç sont acceptés par la regexp.

    Merci beaucoup julp!

    PS: problème résolu pour les backslashes, je faisais 2 fois remove_magic_quotes(qui appelle stripslashes) au lieu d'une.

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

Discussions similaires

  1. Flux rss: affichage accent serveur local et serveur distant
    Par moudjahidine dans le forum Langage
    Réponses: 1
    Dernier message: 04/10/2013, 17h01
  2. Réponses: 0
    Dernier message: 18/08/2008, 18h13
  3. [Système] bureau à distance local/en ligne
    Par grimberman dans le forum Langage
    Réponses: 1
    Dernier message: 30/05/2008, 16h49
  4. Réponses: 1
    Dernier message: 19/02/2008, 09h03
  5. [Système] Système de chat local
    Par trecks dans le forum Langage
    Réponses: 2
    Dernier message: 10/11/2007, 15h38

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