bepe: UTF-8 Formularfeld validierung

hi,

ich bin gerade dabei unsere site auf UTF-8 umzustellen. d.h. dass ich seiten direkt in UTF-8 an den browser schicke (und mich auch darauf verlassen möchte dass UTF-8 zurückkommt - z.b. bei einer formulareingabe)

1. frage:
erfahrungsgemäss: sollte ich jedes feld einzeln auf UTF-8 validität prüfen (also alle textfelder), oder reichts wenn ich überprüfe ob das formular in UTF-8 gePOSTet wurde (z.b. über eine spezielle zeichensequenz als hidden-field)?

momentan verstecke ich folgendes feld in meinem formular:

<input type="hidden" name="charset_check" value="ä™®‰">

und untersuche es danach mit folgender regex:

// check if the posted data is UTF-8 conform
$regex = '/^(
     [\x09\x0A\x0D\x20-\x7E]            # ASCII
   | [\xC2-\xDF][\x80-\xBF]             # non-overlong 2-byte
   |  \xE0[\xA0-\xBF][\x80-\xBF]        # excluding overlongs
   | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}  # straight 3-byte
   |  \xED[\x80-\x9F][\x80-\xBF]        # excluding surrogates
   |  \xF0[\x90-\xBF][\x80-\xBF]{2}     # planes 1-3
   | [\xF1-\xF3][\x80-\xBF]{3}          # planes 4-15
   |  \xF4[\x80-\x8F][\x80-\xBF]{2}     # plane 16
)*$/x';

... das liefert zufriedenstellende ergebnisse. auch mb_detect_ecoding() scheint gut zu funktionieren, allerdings ist mir die sache mit der mb_detect_order ein bissl suspekt, dass erscheint öfter ein wenig 'buggy'.

2. frage:
wie kann ich die formularfelder inhaltlich validieren? z.b. einen personennamen (auf (un-)gültige zeichen, länge)? ich verwende derzeit z.b. folgende regex:

$word_pattern = '/^([\w ]+)$/u';
echo 'text field: word character check '.$word_pattern.' :<br>';
if (preg_match( $word_pattern , $_REQUEST['textfield']))
   echo "IS valid word";
else
   echo "NOT valid word";

allerdings: sobald ich einen umlaut in das textfield eingebe funktioniert die regex nicht, z.b.:

asdfasd: IS valid word
asdföasdf: NOT valid word

woran kann das liegen? NB: ich versende das formular in UTF-8 (deswegen auch der /u pattern-modifier)

wäre um tipps/hilfe äusserst dankbar.

lg bernhard

  1. hi,

    $word_pattern = '/^([\w ]+)$/u';
    allerdings: sobald ich einen umlaut in das textfield eingebe funktioniert die regex nicht, z.b.:
    asdfasd: IS valid word
    asdföasdf: NOT valid word
    woran kann das liegen?

    http://www.php.net/manual/de/function.preg-match.php, Userkommentar von bjorn at kulturkonsult dot no 31-Mar-2003 08:56
    "Remember that \w respects the current locale used in PCRE's character tables."

    gruß,
    wahsaga

    --
    /voodoo.css:
    #GeorgeWBush { position:absolute; bottom:-6ft; }
    1. Hallo wahsaga,

      diese info kenn ich bereits, meine locale ist auf de_DE.UTF-8 gesetzt auf meinem system (debian). funktioniert aber trotzdem nicht, meine vermutung ist nun dass man es vielleicht irgendwie in php.ini setzen muss, oder ev. mit einkompilieren?

      lg bernhard

      1. hi,

        diese info kenn ich bereits, meine locale ist auf de_DE.UTF-8 gesetzt auf meinem system (debian). funktioniert aber trotzdem nicht, meine vermutung ist nun dass man es vielleicht irgendwie in php.ini setzen muss, oder ev. mit einkompilieren?

        Der Nutzerkommentar von Ned Baldessin, 23-Oct-2004 09:08 auf http://www.php.net/manual/de/ref.pcre.php könnte ebenfalls noch interessant sein.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. Hi wahsaga,

          ich wollte eigentlich die mb_*funktionen vermeiden, da ich zur formularvalidierung HTML_Quickform verwende, und dann sämtliche existierende quickform rules umschreiben müsste auf mb_* kompatibilität (und das bei jedem update der bibliothek wiederholen). ausserdem sollen die mb_* sachen nicht sehr schnell sein.

          ich dachte eigentlich dass /u reichen würde. in den beispielen im netz ist jedenfalls immer davon die rede.

          ausserdem scheint setlocale() bei mir nicht zu funktionieren. weiters weiss ich nicht wie ratsam es ist, bei jedem aufruf der seite die locale zu setzen. wir bieten derzeit portale für at,de,pl,com,uk, und in an ... und weitere werden bald dazu kommen. möchte eigentlich vermeiden jedesmal die locale umzustellen.

          lg bernhard

          hi,

          diese info kenn ich bereits, meine locale ist auf de_DE.UTF-8 gesetzt auf meinem system (debian). funktioniert aber trotzdem nicht, meine vermutung ist nun dass man es vielleicht irgendwie in php.ini setzen muss, oder ev. mit einkompilieren?

          Der Nutzerkommentar von Ned Baldessin, 23-Oct-2004 09:08 auf http://www.php.net/manual/de/ref.pcre.php könnte ebenfalls noch interessant sein.

          gruß,
          wahsaga

          1. Hi

            ich wage zu behaupten eine lösung nun gefunden zu haben, um zu prüfen ob gültige buchstaben eingegeben wurden (egal in welcher sprache):

            http://de.php.net/manual/de/reference.pcre.pattern.syntax.php unter 'Unicode character properties'.

            auch interessant in diesem zusammenhang:

            "Analyzing Unicode Text with Regular Expressions"
            http://icu.sourceforge.net/docs/papers/iuc26_regexp.pdf (pdf)

            ich verwende nun folgendes pattern: /^([\p{L}]+)$/u

            damit kann ich überprüfen ob ein string aus validen buchstaben besteht. wird z.b. ein rufzeichen oder punkt eingegeben, meldet die regex false. habe es bisher probiert mit lateinischen, russischen und griechischen buchstaben, sowie farsi.

            bin zuversichtlich dass es funktionieren wird. zum checken von gültigen formulareingaben (z.b. namen, adressen) werde ich nun diese regex verwenden. für andere string-operationen werde ich dann doch die mb_* funktionen hernehmen (z.b. strpo, strlen, ...)

            lg und danke für eure hilfe!
            bernhard

          2. 你好 bepe,

            ausserdem scheint setlocale() bei mir nicht zu funktionieren.

            Was heisst „nicht funktionieren“? Was gibt es zurück? Was sagt die
            Error-Message?

            weiters weiss ich nicht wie ratsam es ist, bei jedem aufruf der seite
            die locale zu setzen.

            Das ist völlig problemlos. Das macht das Forum hier auch, z. B. um die
            Datum-Strings lokalisiert auszugeben.

            再见,
             克里斯蒂安

            1. hallo christian,

              ausserdem scheint setlocale() bei mir nicht zu funktionieren.

              Was heisst „nicht funktionieren“? Was gibt es zurück? Was sagt die
              Error-Message?

              weiss nicht, hab ich nicht so ausführlich debugged. ich habe setlocale(LC_ALL,'en_US') bzw. setlocale(LC_ALL,'de_DE') ausprobiert, mit jeweils einigen variationen in der schreibweise, bzw. zusätzliche encodings. allerdings habe ich mit setlocale(LC_ALL,0) immer die server-weite locale einstellung zurückbekommen.

              mein ziel war rauszufinden ob es locale abhängig ist dass ein \w in einer regex auch wirklich alle zeichen dieser sprache als word-character erkennt. somit hätte en_US z.b. einen umlaut nicht als word-character erkennen dürfen. hat es aber (die server locale war auf de_DE gesetzt.)

              weiters weiss ich nicht wie ratsam es ist, bei jedem aufruf der seite
              die locale zu setzen.

              Das ist völlig problemlos. Das macht das Forum hier auch, z. B. um die
              Datum-Strings lokalisiert auszugeben.

              ich wollte damit sagen, dass mir nicht ganz klar ist, wie sich das (ver-)setzen einer locale auf andere php prozesse/threads auswirkt. welchen context überschreibt setlocale() nun? die server locale? die prozess locale? die PHP-thread-weite locale? wie wirkt sich das aus wenn php als CGI bzw. apache modul konfiguriert ist?

              z.b.: http://at2.php.net/setlocale -> kommentar vom: 27-Jul-2001

              meine site würde z.b. beim aufruf einer seite im unterverzeichnis /de eine andere locale setzen als bei aufruf einer seite in /pl. ich denke dass dies ein ganz normales problem multilingualer seiten ist.

              ich versuche diese 'locale-awareness' ein wenig dahingehend zu umschiffen, dass ich UTF-8 als zeichensatz verwende, und ansonsten intern für alles andere (z.b. datum, preise in DB, externe web services etc.)  ein fixes standard format verwende (z.b. '.' als komma, unix timstamps für datum) und das nur auf der präsentationsebene (template engine) für das jeweilige portal formatiere.

              lass mir aber gern andere konzepte & strategien aufzeigen diesbezüglich.

              lg bernhard

              1. 你好 bepe,

                mein ziel war rauszufinden ob es locale abhängig ist dass ein \w in
                einer regex auch wirklich alle zeichen dieser sprache als word-character
                erkennt. somit hätte en_US z.b. einen umlaut nicht als word-character
                erkennen dürfen. hat es aber (die server locale war auf de_DE gesetzt.)

                Naja, \w in der libpcre matcht ja nur alle word characters and digits
                bis zu Codepoint 128. Wenn ich mal zitieren darf:

                In UTF-8 mode, characters with values greater than 128 never match \d, \s,
                or \w, and always match \D, \S, and \W. This is true  even when Unicode
                character property support is available.

                Deshalb ist es eh nicht das, was du suchst. Wenn du wirklich
                locale-abhängiges matchen möchtest, musst du den UTF-8-Mode ausschalten
                und ein Locale verwenden, dass einen 1-Byte-Kodierung verwendet. Das hat
                aber nix mit setlocale() zu tun, sondern mit der libpcre, die in diesem
                Punkt auf eher auf Performance als auf korrekten Support setzt.

                weiters weiss ich nicht wie ratsam es ist, bei jedem aufruf der seite
                die locale zu setzen.

                Das ist völlig problemlos. Das macht das Forum hier auch, z. B. um die
                Datum-Strings lokalisiert auszugeben.

                ich wollte damit sagen, dass mir nicht ganz klar ist, wie sich das
                (ver-)setzen einer locale auf andere php prozesse/threads auswirkt.

                Das ist doch alles nachlesbar…

                welchen context überschreibt setlocale() nun? die server locale? die
                prozess locale? die PHP-thread-weite locale? wie wirkt sich das aus wenn
                php als CGI bzw. apache modul konfiguriert ist?

                setlocale() überschreibt das Prozess-Locale. Heisst, wenn du PHP in einem
                Multithreaded-Kontext verwendest, etwa bei einem Apache-Worker-MPM, dann
                überschreiben sich die setlocale()-Aufrufe gegenseitig. Ansonsten, in einer
                „traditionellen“ Multi-Prozess-Umgebung wirkt sich das nicht gross weiter
                auf andere Prozesse aus. Das Locale wird nach Beenden des Scripts wieder
                zurückgesetzt (gehört mit zur Prozedur zur Wiederherstellung des
                Environments), es wirkt sich also auch im Modul-Modus nicht auf den Apache
                aus.

                meine site würde z.b. beim aufruf einer seite im unterverzeichnis /de
                eine andere locale setzen als bei aufruf einer seite in /pl. ich denke
                dass dies ein ganz normales problem multilingualer seiten ist.

                Naja, „Problem“ ist übertrieben ;)

                ich versuche diese 'locale-awareness' ein wenig dahingehend zu
                umschiffen, dass ich UTF-8 als zeichensatz verwende, und ansonsten
                intern für alles andere (z.b. datum, preise in DB, externe web services
                etc.)  ein fixes standard format verwende (z.b. '.' als komma, unix
                timstamps für datum) und das nur auf der präsentationsebene (template
                engine) für das jeweilige portal formatiere.

                lass mir aber gern andere konzepte & strategien aufzeigen diesbezüglich.

                Na, die Strategie ist schon ganz sinnvoll so, andere (inkl. mir) machen es
                auch nicht anders. Aber gerade die Repräsentation nach aussen machen
                Locales um vieles einfacher, vor allem deshalb, weil man damit gleich einen
                ganzen Rutsch von Sprachen unterstützen kann ohne etwas am Source ändern zu
                müssen – hat schließlich alles schonmal jemand aufgeschrieben, in den
                Locale-Definitionen ;)

                再见,
                 克里斯蒂安

                --
                Wundert euch nicht, … | Noch eine Block-Installation: SELFHTML Aktuell
                Unsere Vorstellungen von der Ewigkeit sind genauso nuetlich wie die Mutmassungen eines Kuekens ueber die Aussenwelt bevor es die Eierschale aufbricht.
                http://wwwtech.de/
                1. hi christian

                  Danke für deine sehr ausführliche antwort :-)

                  Deshalb ist es eh nicht das, was du suchst. Wenn du wirklich
                  locale-abhängiges matchen möchtest, musst du den UTF-8-Mode ausschalten
                  und ein Locale verwenden, dass einen 1-Byte-Kodierung verwendet. Das hat
                  aber nix mit setlocale() zu tun, sondern mit der libpcre, die in diesem
                  Punkt auf eher auf Performance als auf korrekten Support setzt.

                  hmm ... dann hab ich wohl ein paar dinge falsch interpretiert ;-) dass ich das /u wegnehmen muss für locale-basiertes matching ist mir tatsächlich nicht selbst eingefallen. was wohl auch damit zu tun hatte, dass mir das setzen der locale aus dem phpscript heraus nie wirklich gelungen ist :-(

                  welchen context überschreibt setlocale() nun? die server locale? die
                  prozess locale? die PHP-thread-weite locale? wie wirkt sich das aus wenn
                  php als CGI bzw. apache modul konfiguriert ist?

                  setlocale() überschreibt das Prozess-Locale. Heisst, wenn du PHP in einem
                  Multithreaded-Kontext verwendest, etwa bei einem Apache-Worker-MPM, dann
                  überschreiben sich die setlocale()-Aufrufe gegenseitig. Ansonsten, in einer
                  „traditionellen“ Multi-Prozess-Umgebung wirkt sich das nicht gross weiter
                  auf andere Prozesse aus. Das Locale wird nach Beenden des Scripts wieder
                  zurückgesetzt (gehört mit zur Prozedur zur Wiederherstellung des
                  Environments), es wirkt sich also auch im Modul-Modus nicht auf den Apache
                  aus.

                  hm ... sehr informativ dieser teil hier. danke!

                  meine site würde z.b. beim aufruf einer seite im unterverzeichnis /de
                  eine andere locale setzen als bei aufruf einer seite in /pl. ich denke
                  dass dies ein ganz normales problem multilingualer seiten ist.

                  Naja, „Problem“ ist übertrieben ;)

                  aber hallo, ich sitz da jetzt schon ein, zwei wochen dran an dieser unicode problematik. also für mich ist das zur verfügungstellen von content in verschiedenen sprachräumen durchaus ein 'problem' - zumindest so lang bis man es mal überwunden hat ;-)

                  Na, die Strategie ist schon ganz sinnvoll so, andere (inkl. mir) machen es
                  auch nicht anders. Aber gerade die Repräsentation nach aussen machen
                  Locales um vieles einfacher, vor allem deshalb, weil man damit gleich einen
                  ganzen Rutsch von Sprachen unterstützen kann ohne etwas am Source ändern zu
                  müssen – hat schließlich alles schonmal jemand aufgeschrieben, in den
                  Locale-Definitionen ;)

                  werde mir das nochmal durch den kopf gehen lassen, vorerst denke ich dass ich ohne der locale-customisierung auch ganz gut zurecht komme.

                  danke & lg,
                  bernhard

                  1. Hi,

                    was wohl auch damit zu tun hatte, dass mir das setzen der locale aus dem phpscript heraus nie wirklich gelungen ist :-(

                    Unix kennt den Befehl locale. Damit kannst Du dir anzeigen lassen, welche Locales das System konkret kennt.

                    setlocale() unterstützt ab 4.3 auch ein Array als Parameter. Das verwende ich, indem ich alle nur denkbaren Locales von versch. Systemen in ein Array packe und übergebe. setlocale() "sucht" sich dann "automatisch" das für das jeweilige System passende raus.

                    (Genauer: Ich verwende dafür eine selbstgeschriebene Funktion, der ich auch bei PHP<4.3 ein solches Array übergeben kann - was mir dann nicht nur beim OS sondern auch bei PHP volle Portabilität der Scripte ermöglicht).

                    werde mir das nochmal durch den kopf gehen lassen, vorerst denke ich dass ich ohne der locale-customisierung auch ganz gut zurecht komme.

                    Notwendig ist es in diesem Fall auch nicht. :-)

                    Gruß, Cybaer

                    --
                    Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
                    1. 你好 Cybaer,

                      was wohl auch damit zu tun hatte, dass mir das setzen der locale aus
                      dem phpscript heraus nie wirklich gelungen ist :-(

                      Unix kennt den Befehl locale. Damit kannst Du dir anzeigen lassen,
                      welche Locales das System konkret kennt.

                      Genauer, mit locale -a ;) Und wenn man eines nicht existiert, gibt es
                      localedef.

                      再见,
                       克里斯蒂安

                      --
                      Wundert euch nicht, … | Noch eine Block-Installation: SELFHTML Aktuell
                      Nur die Weisesten und die Dümmsten können sich nicht ändern.
                      http://wwwtech.de/
                      1. Hi,

                        Und wenn man eines nicht existiert, gibt es
                        localedef.

                        Was nicht in den man-Pages steht: mailto:sklave@mywebhoster.net klappt ggf. auch. >;-)

                        Gruß, Cybaer

                        --
                        Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
          3. Hi,

            weiters weiss ich nicht wie ratsam es ist, bei jedem aufruf der seite die locale zu setzen.

            Na ja, dafür ist es doch da!? =:-o

            Ich habe für jede "meiner" Sites eine eigene Settings-Datei, die automatisch eingebunden werden (und zur Not verzichtbar sind). Und da setlocale ab 4.3 besser funktioniert, nutze ich eine Ersatzroutine die mir die gleiche Funktionalität auch auf älteren PHPs bietet - aufgerufen von *jeder* Seite.

            Gruß, Cybaer

            --
            Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!
            1. Hi cybaer,

              ich habe bereits auf die antwort von christian recht ausführlich meine bedenken dargelegt. es kann ja auch durchaus sein dass ich mir da unnötig sorgen mache.

              aber was mir unklar ist bei der locale-sache ist, dass durch explizites  setzen auf eine bestimmte locale plötzlich alle daten in dem lokal geprägten context vorhanden sind (auch programm-intern). was also wenn ich eine zahl in die DB schreibe? oder ein datum? wird das dann in der lokalen form gespeichert? oder umgekehrt: beim auslesen aus der DB?

              lg bernhard

              1. 你好 bepe,

                aber was mir unklar ist bei der locale-sache ist, dass durch explizites
                setzen auf eine bestimmte locale plötzlich alle daten in dem lokal
                geprägten context vorhanden sind (auch programm-intern). was also wenn
                ich eine zahl in die DB schreibe? oder ein datum? wird das dann in der
                lokalen form gespeichert? oder umgekehrt: beim auslesen aus der DB?

                Ähem, das Speicherungsformat für Datenbanken von Floatern ist immer noch
                das „Ei-Tripple-I“-Format (IEEE 754) ;) Das hat mit Locales nix zu tun;
                erst, wenn du die Zahlen in Strings verwandelst, also zur Repräsentation
                ausgibst, werden sie Locale-abhängig formatiert – vorrausgesetzt du benutzt
                die richtigen[tm] Funktionen dafür. Du musst verstehen, dass die interne
                Repräsentation von Daten nix gemein hat mit der Darstellung derselben.

                再见,
                 克里斯蒂安

                --
                Wundert euch nicht, … | Noch eine Block-Installation: SELFHTML Aktuell
                Wenn der Schüler bereit ist, erscheint der Meister.
                http://wwwtech.de/
                1. hallo christian,

                  aber was mir unklar ist bei der locale-sache ist, dass durch explizites
                  setzen auf eine bestimmte locale plötzlich alle daten in dem lokal
                  geprägten context vorhanden sind (auch programm-intern). was also wenn
                  ich eine zahl in die DB schreibe? oder ein datum? wird das dann in der
                  lokalen form gespeichert? oder umgekehrt: beim auslesen aus der DB?

                  Ähem, das Speicherungsformat für Datenbanken von Floatern ist immer noch
                  das „Ei-Tripple-I“-Format (IEEE 754) ;) Das hat mit Locales nix zu tun;
                  erst, wenn du die Zahlen in Strings verwandelst, also zur Repräsentation
                  ausgibst, werden sie Locale-abhängig formatiert – vorrausgesetzt du benutzt
                  die richtigen[tm] Funktionen dafür. Du musst verstehen, dass die interne
                  Repräsentation von Daten nix gemein hat mit der Darstellung derselben.

                  ich meinte damit dass wenn ein user eine zahl eingibt (sagen wir mal '123,90' weil die locale auf latin1 gesetzt ist) wie die dann in der DB aussieht wenn man vorher nicht drauf schaut dass aus dem ',' ein ',' wird (z.b. durch einen float-cast)? muss man höllisch aufpassen bei so sachen.

                  lg bernhard

                  1. 你好 bepe,

                    ich meinte damit dass wenn ein user eine zahl eingibt (sagen wir mal
                    '123,90' weil die locale auf latin1 gesetzt ist) wie die dann in der DB
                    aussieht wenn man vorher nicht drauf schaut dass aus dem ',' ein ','
                    wird (z.b. durch einen float-cast)? muss man höllisch aufpassen bei so
                    sachen.

                    Sowas macht man ja eh nicht in der Datenbank, Typecasts macht man im
                    Programm, als Teil der Parameter-Validierung ;)

                    再见,
                     克里斯蒂安

                    --
                    Wundert euch nicht, … | Noch eine Block-Installation: SELFHTML Aktuell
                    Die Stärke des Geistes ist unendlich, die Muskelkraft dagegen ist begrenzt.
                    http://wwwtech.de/
  2. Hi,

    und untersuche es danach mit folgender regex:

    In Codierung einer XML Datei herausfinden und korrigieren findest Du eine Validierungsalternative.

    Gruß, Cybaer

    --
    Hinweis an Fragesteller: Fremde haben ihre Freizeit geopfert, um Dir zu helfen. Helfe Du auch im Archiv Suchenden: Beende deinen Thread mit einem "Hat geholfen" oder "Hat nicht geholfen"!