UTF-8 Formularfeld validierung
bepe
- php
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
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
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
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
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
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
你好 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.
再见,
克里斯蒂安
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
你好 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 ;)
再见,
克里斯蒂安
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
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
你好 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.
再见,
克里斯蒂安
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
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
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
你好 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.
再见,
克里斯蒂安
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
你好 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 ;)
再见,
克里斯蒂安
Hi,
und untersuche es danach mit folgender regex:
In Codierung einer XML Datei herausfinden und korrigieren findest Du eine Validierungsalternative.
Gruß, Cybaer