Schrift
[thread]12468[/thread]

UTF-8 und POST-Parameter

Leser: 5


<< >> 10 Einträge, 1 Seite
JoeD
 2008-09-10 12:52
#114477 #114477
User since
2008-09-10
3 Artikel
BenutzerIn
[default_avatar]
Hi,
ich sitze schon seit ein paar Tagen daran zu verstehen, wie man mit Perl UTF-8 bewältigt... Ich komme aber leider nicht dahinter und wundere mich, dass so etwas so undurchsichtig sein kann, aber wahrscheinlich liegts nur an mir.

Meine Quellcode-Dateien sind alle als UTF-8 codiert. Variablen (Strings), die ich dort definiere, müssten demnach ja auch UTF-8-codiert sein. Ich verwende den Schalter -CS, sodass alle Ein- und Ausgaben das UTF-8-Format besitzten. Wenn ich mit print einen String mit Umlauten ausgebe, funktioniert es wunderbar.

Nun sende ich mit einem Formular (per POST) Daten an das Script. Wenn ich diese direkt ausgebe, werden die Umlaute falsch dargestellt. Und ich verstehe nicht warum!

Hier ist mein Script:

Code (perl): (dl )
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
#!/usr/bin/perl -w -CO

use strict;
use utf8;
use CGI qw/:standard/;

my $URLRAWDATA = "";
if ($ENV{'REQUEST_METHOD'} eq "POST") {
   read(STDIN, $URLRAWDATA, $ENV{'CONTENT_LENGTH'});
}
else {
   $URLRAWDATA = $ENV{'QUERY_STRING'};
}
my %URLDATA;
my @data = split (/&/, $URLRAWDATA);
for (@data) {
   my ($key, $value) = split /=/;
   $value =~ s/%0D%0A/<\|br\|>/g;
   $value =~ tr/+/ /;
   $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
   $URLDATA{$key} = $value;
}

print "Content-type: text/html\n\n";
print "äöü ";   # richtige Umlaute: äöü
print $URLDATA{'name'}; # fehlerhafte Umlaute: äöü


Ich hoffe mir kann hierbei jemand weiterhelfen.

Ich habe auch schon einiges ausprobiert mit den Funktionen encode/decode und Encode::from_to(..), aber was da genau passiert (ob da nur ein Flag gesetzt wird oder umrechnungen stattfinden) verstehe ich nicht aus der perldoc.

Vielen Dank schonmal! Gruß
Johannes
nepos
 2008-09-10 13:11
#114478 #114478
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Zum eigentlichen Problem kann ich nichts sagen, aber wieso bitte bindest du CPAN:CGI ein, benutzt es dann aber gar nicht? Parameter manuell auslesen ist nicht grade der saubere Stil, das macht das Modul ja schon für dich.
moritz
 2008-09-10 13:11
#114479 #114479
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Quote
Code: (dl )
print "Content-type: text/html\n\n";


Das ist der erste Fehler: du musst dem Browser schon die Kodierung mitteilen:

Code: (dl )
print "Content-Type: text/html; charset=utf-8\n\n";


Der zweite Fehler ist, dass du die param()-Funktion von CGI neu erfindest.

Der dritte Fehler ist, dass $URLRAWDATA dekodierte Parameter enthält wenn wenn die Daten von STDIN gelesen werden (wegen -CS), aber bytestrings aus $ENV{'QUERY_STRING'};.

Je nach CGI.pm-Version kann es reichen, sowas zu schreiben:

Code (perl): (dl )
1
2
3
4
5
6
7
use CGI;
my $q = CGI->new;
$q->charset('UTF-8');

print $q->header();

print $q->param('name');


Bei älteren CGI.pm Versionen musst du noch von Hand dekodieren:

Code (perl): (dl )
1
2
3
4
5
6
7
8
9
use CGI;
use Encode qw(decode_utf8);
my $q = CGI->new;
$q->charset('UTF-8');

print $q->header();

my $name = decode_utf($q->param('name'))
print $name;


Siehe auch Perl und Zeichenkodierungen.
renee
 2008-09-10 13:44
#114480 #114480
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Das -C in der Shebang-Zeile ist nutzlos, weil da die Standard-Streams schon aufgebaut sind. In Perl 5.10 gibt's da auch 'nen Fehler (oder zumindest 'ne Warnung)...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
moritz
 2008-09-10 13:49
#114481 #114481
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
renee+2008-09-10 11:44:33--
Das -C in der Shebang-Zeile ist nutzlos, weil da die Standard-Streams schon aufgebaut sind. In Perl 5.10 gibt's da auch 'nen Fehler (oder zumindest 'ne Warnung)...


Oh, das war mir nicht bewusst. Dann sollte man sowas nehmen:

Code: (dl )
1
2
binmode STDOUT, ':encoding(UTF-8)';
binmode STDIN, ':encoding(UTF-8)';


Update: Unter Linux funktioniert das -CS auf der Kommandozeile wunderbar, aber nur wenn man mit ./script.pl startet, nicht wenn man mit 'perl script.pl' startet. Also eher Finger davon lassen...
pq
 2008-09-10 13:59
#114482 #114482
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
renee+2008-09-10 11:44:33--
Das -C in der Shebang-Zeile ist nutzlos

aber nur unter windows, oder?
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
renee
 2008-09-10 14:11
#114483 #114483
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Nein... Deswegen ist das -C in der Shebang-Zeile ab Perl 5.10 auch nicht mehr erlaubt...

Update: siehe auch http://search.cpan.org/~rgarcia/perl-5.10.0/pod/pe...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
JoeD
 2008-09-10 16:40
#114490 #114490
User since
2008-09-10
3 Artikel
BenutzerIn
[default_avatar]
Hi,
zuerst einmal vielen Dank für die Antworten! Ich habe jetzt denke ich alle von euch genannten Fehler beseitigt, und das folgende Script funktioniert:

Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/usr/bin/perl -w

use strict;
use utf8;
use CGI;
use Encode qw(decode_utf8);

binmode STDOUT, ':encoding(UTF-8)';
binmode STDIN, ':encoding(UTF-8)';

my $q = CGI->new;
$q->charset('UTF-8');
print $q->header();

print "äöü";
print decode_utf8($q->param('name'));


Die decode_utf8-Funtion ist bei mir offenbar nötig, dann werden die Umlaute aus dem Parameter korrekt dargestellt, und auch die, die ich direkt im Quellcode angebe.

Jetzt muss ich einen UTF-8-String in iso-8859-1 umwandeln, da ich daraus einen Dateinamen machen will. Das funktioniert mit Encode::from_to($str, 'utf8', 'iso-8859-1') leider nicht. Wie denn?

(Es geht nicht nur um einen Dateinamen sondern auch um Mailversand, den ich nicht mit UTF-8 durchführen möchte, obwohl die meisten Mailprogramme ja UTF-8 anzeigen können...)
moritz
 2008-09-10 17:45
#114506 #114506
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
JoeD+2008-09-10 14:40:54--
Jetzt muss ich einen UTF-8-String in iso-8859-1 umwandeln, da ich daraus einen Dateinamen machen will. Das funktioniert mit Encode::from_to($str, 'utf8', 'iso-8859-1') leider nicht. Wie denn?


Also wenn $str ein schon dekodierter String ist, reicht Encode::encode('ISO-8859-1', $str).
Ansonsten solltest du zwischen utf8 und UTF-8 unterscheiden. Wenn es um Encode geht, ist UTF-8 das was du willst, und utf8 ein Perl-internes Sonderdingens, dass du nicht verwenden solltest.

Quote
(Es geht nicht nur um einen Dateinamen sondern auch um Mailversand, den ich nicht mit UTF-8 durchführen möchte, obwohl die meisten Mailprogramme ja UTF-8 anzeigen können...)


Ja, alle ausser einige kaputte Versionen von Outlook (+Express, glaube) die leider den Markt dominieren.

Grüße,
Moritz
JoeD
 2008-09-10 18:21
#114508 #114508
User since
2008-09-10
3 Artikel
BenutzerIn
[default_avatar]
So, es scheint alles zu funktionieren. Ganz verstehe ich noch nicht, was bei decode_utf8 und was bei encode passiert, aber es klappt jetzt so wie ich es mir vorstelle. Deshalb nochmal vielen Dank an alle Beteiligten, ich hätte nicht gedacht, dass ich so schnell Antwort erhalte.

Viele Grüße,
Johannes
<< >> 10 Einträge, 1 Seite



View all threads created 2008-09-10 12:52.