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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
#!/usr/bin/perl -w use HTML::Template; use CGI::Simple; use DBI; use Devel::Peek; use CGI::Carp qw(fatalsToBrowser carpout); open(LOG, ">/var/www/utftest/log.txt"); carpout(LOG); use Encode qw( encode decode ); use utf8; binmode(STDIN, ":encoding(utf8)"); #Einem bereits geöffneten Kanal kann nachträglich auch ein Konverter zugewiesen werden_ #binmode(STDOUT, ":encoding(UTF-8)"); my $dbh = DBI->connect( 'DBI:mysql:database=testdb' . ';host=localhost', 'root', 'womex', { RaiseError => 1, Print_warn => 1, Warn => 1, mysql_enable_utf8 => 1} ) or die "Can't connect to database!"; #cgi Objekt für Zugriff auf per GET oder POST erhaltene Formulavariablen my $cgi = new CGI::Simple; #Werte aller Formularelemente in Form eines Hashes my %cgiHash = $cgi->Vars(); # open the html template my $template = HTML::Template->new( filename => 'test.tmpl', utf8 => 1 ); $template->param( spalte => $cgiHash{'input'} ); $template->param( spalte2 => encode('utf-8','5 mal Euro: €€€€€') ); #SQl Statement, welches die Daten der Pflichfelder aus dem Formular speichern läßt. my $sth = $dbh->prepare( qq{ INSERT INTO utftbl SET spalte = ? }); #Durchführen des inserts in die Tabelle mit den Pflichtdaten unless ( $sth->execute( $cgiHash{'input'} ) ) { warn sprintf( "[Error]: Reason: [%s].", $dbh->errstr ); } my ($return_value) = $dbh->last_insert_id( undef, undef, 'utftbl', 'id' ); $sth = $dbh->prepare( qq{ SELECT spalte from utftbl where id=$return_value }); #Durchführen des selects in die Tabelle mit den Pflichtdaten unless ( $sth->execute() ) { warn sprintf( "[Error]: Reason: [%s].", $dbh->errstr ); } my @arr = $sth->fetchrow_array(); #Wenn Datenbank String als utf-8 kodierter String eingelesen wurde und #wir nichts an diesem verändert haben, dann können wird diesen direkt ohne #Dekodierung/Enkodierung direkt rausschreiben, falls die Ausgabe auch in utf-8 deklariert ist. $template->param( spalte3 => $arr[0] ); $template->param( spalte4 => encode('utf-8',"Präfix€uro:") . $arr[0] ); print( "Content-Type: text/html; charset=UTF-8\n\n", $template->output ); Dump($cgiHash{'input'}); Dump($arr[0]); Dump($template); __END__ SV = PV(0x84b8930) at 0x8488d28 REFCNT = 1 FLAGS = (POK,pPOK,UTF8) PV = 0x84f4aa8 "Das BU\303\242\302\202\302\254RO"\0 [UTF8 "Das BU\x{e2}\x{82}\x{ac}RO"] CUR = 14 LEN = 16 SV = PV(0x84ca9d0) at 0x8532288 REFCNT = 1 FLAGS = (POK,pPOK,UTF8) PV = 0x851c1f0 "Das BU\303\242\302\202\302\254RO"\0 [UTF8 "Das BU\x{e2}\x{82}\x{ac}RO"] CUR = 14 LEN = 16 SV = RV(0x8180df0) at 0x8450788 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x81cbd78 SV = PVHV(0x8158820) at 0x81cbd78 REFCNT = 1 FLAGS = (PADBUSY,PADMY,OBJECT,SHAREKEYS) IV = 4 NV = 0 STASH = 0x8154744 "HTML::Template" ARRAY = 0x84f4b08 (0:4, 1:4) hash quality = 137.5% KEYS = 4 FILL = 4 MAX = 7 RITER = -1 EITER = 0x0 Elt "param_map" HASH = 0xfaf3dd80 SV = RV(0x8180d24) at 0x852a7f0 REFCNT = 1 FLAGS = (ROK) RV = 0x852a7a8 SV = PVHV(0x85510b0) at 0x852a7a8 REFCNT = 1 FLAGS = (SHAREKEYS,HASKFLAGS) UV = 4 NV = 0 ARRAY = 0x8517b40 (0:5, 1:2, 2:1) hash quality = 91.7% KEYS = 4 FILL = 3 MAX = 7 RITER = -1 EITER = 0x0 Elt "spalte4" [UTF8 "spalte4"] HASH = 0xcf2c47e3 SV = RV(0x8180e48) at 0x8532078 REFCNT = 1 FLAGS = (ROK) RV = 0x8532048 Elt "parse_stack" HASH = 0x4c50ad1 SV = RV(0x8180d1c) at 0x852a808 REFCNT = 1 FLAGS = (ROK) RV = 0x8531b44 SV = PVAV(0x8487eb4) at 0x8531b44 REFCNT = 1 FLAGS = () IV = 0 NV = 0 ARRAY = 0x8361280 FILL = 8 MAX = 11 ARYLEN = 0x852a700 FLAGS = (REAL) Elt No. 0 SV = RV(0x8180e24) at 0x852a5f8 REFCNT = 1 FLAGS = (ROK) RV = 0x821092c Elt No. 1 SV = RV(0x8180e2c) at 0x8531d18 REFCNT = 1 FLAGS = (ROK) RV = 0x8256718 Elt No. 2 SV = RV(0x8180e34) at 0x8531d48 REFCNT = 1 FLAGS = (ROK) RV = 0x8220084 Elt No. 3 SV = RV(0x8180e38) at 0x8531e08 REFCNT = 1 FLAGS = (ROK) RV = 0x8531d00 Elt "options" HASH = 0xa12ff3a2 SV = RV(0x8180c50) at 0x8488d1c REFCNT = 1 FLAGS = (ROK) RV = 0x8488e24 SV = PVHV(0x84d8568) at 0x8488e24 REFCNT = 1 FLAGS = (SHAREKEYS,HASKFLAGS) UV = 33 NV = 0 ARRAY = 0x851a8c0 (0:37, 1:22, 2:4, 3:1) hash quality = 105.3% KEYS = 33 FILL = 27 MAX = 63 RITER = -1 EITER = 0x0 Elt "cache_debug" HASH = 0x3cb23b45 SV = IV(0x8480070) at 0x848e8a8 REFCNT = 1 FLAGS = (IOK,pIOK) IV = 0
Quote[Tue Aug 2 16:29:11 2011] form.cgi: Wide character in print at /var/www/utftest/form.cgi line 74.
2011-08-02T15:34:33 pqwie du an der ausgabe von Dump($arr[0]); siehst, ist der string schon dekodiert, von mysql_enable_utf8.
2011-08-02T15:53:59 mcfaqAber wenn ich mit diesem Wissen rangehe und beim Einfügen ins template encode('utf-8',$arr[0]) einsetze, dann führt das zu einem Fehler.
Quote.DB Euros(1):Das BUâ¬RO
QuoteTemplate Euros: â¬â¬â¬
Form Euros:Das BUâ¬RO
Perl Euros:5 mal Euro: â¬â¬â¬â¬â¬
DB Euros(1):Das BUâ¬RO
DB Euros(2):Präfixâ¬uro:Das BUâ¬RO
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 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
#!/usr/bin/perl -w #use HTML::Template; use HTML::Template::Compiled; use CGI::Simple; use DBI; use Devel::Peek; use CGI::Carp qw(fatalsToBrowser carpout); open(LOG, ">/var/www/utftest/log.txt"); carpout(LOG); use Encode qw( encode decode ); use utf8; #binmode(STDIN, ":encoding(utf8)"); #Einem bereits geöffneten Kanal kann nachträglich auch ein Konverter zugewiesen werden_ binmode(STDOUT, ":encoding(UTF-8)"); my $dbh = DBI->connect( 'DBI:mysql:database=testdb' . ';host=localhost', 'root', 'womex', { RaiseError => 1, PrintWarn => 1, Warn => 1, mysql_enable_utf8 => 1} ) or die "Can't connect to database!"; #cgi Objekt für Zugriff auf per GET oder POST erhaltene Formulavariablen my $cgi = new CGI::Simple; #Codierung der Daten auf UTF-8 setzen: --> trotzdem werden diese nicht automatisch dekodiert (siehe Dump) $cgi->charset('utf-8'); #Werte aller Formularelemente in Form eines Hashes my %cgiHash = $cgi->Vars(); #SQl Statement, welches die Daten der Pflichfelder aus dem Formular speichern läßt. my $sth = $dbh->prepare( qq{ INSERT INTO utftbl SET spalte = ? }); #Durchführen des inserts in die Tabelle mit den Pflichtdaten unless ( $sth->execute( $cgiHash{'input'} ) ) { warn sprintf( "[Error]: Reason: [%s].", $dbh->errstr ); } #Wiederauslesen des zuletzt eingefügten Eintrags aus der DB Tabelle my ($return_value) = $dbh->last_insert_id( undef, undef, 'utftbl', 'id' ); $sth = $dbh->prepare( qq{ SELECT spalte from utftbl where id=$return_value }); #Durchführen des selects in die Tabelle mit den Pflichtdaten unless ( $sth->execute() ) { warn sprintf( "[Error]: Reason: [%s].", $dbh->errstr ); } my @arr = $sth->fetchrow_array(); ########################## F A Z I T ########################################## #Mit dem original HTML::Template klappt dieses Vorgehen allerdings nicht. # open the html template #my $template = HTML::Template->new( filename => 'test.tmpl', utf8 => 1 ); ###################################### Fazit ################################## # open the html template my $template = HTML::Template::Compiled->new( filename => 'test.tmpl', open_mode => ':utf8' ); #Füllen des Templates mit den Daten verschiedener Herkunft # #hier muss ich trotzdem manuell dekodieren $template->param( spalte => decode('utf-8',$cgiHash{'input'}) ); $template->param( spalte2 => '5 mal Euro: €€€€€' ); $template->param( spalte3 => $arr[0] ); $template->param( spalte4 => "Präfix€uro:" . $arr[0] ); #Ausgeben an den Server print( "Content-Type: text/html; charset=UTF-8\n\n", $template->output ); #Dump von Rohdaten Dump($cgiHash{'input'}); Dump($arr[0]); foreach($template->param()){ Dump($_); } Dump($template); __END__ SV = PV(0x85ed1b8) at 0x85ca900 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x862a8a8 "Das BU\342\202\254RO"\0 CUR = 11 LEN = 12 SV = PV(0x85de08c) at 0x8674c04 REFCNT = 1 FLAGS = (POK,pPOK,UTF8) PV = 0x86720e0 "Das BU\342\202\254RO"\0 [UTF8 "Das BU\x{20ac}RO"] CUR = 11 LEN = 12 [Wed Aug 3 14:25:40 2011] form.cgi: You are using query() but have not specified that you want to use it (specify with use_query => 1) at /var/www/utftest/form.cgi line 111 SV = RV(0x817c3d0) at 0x84efe74 REFCNT = 1 FLAGS = (PADBUSY,PADMY,ROK) RV = 0x85ca8d0 SV = PVAV(0x85bc738) at 0x85ca8d0 REFCNT = 1 FLAGS = (OBJECT) IV = 0 NV = 0 STASH = 0x8154768 "HTML::Template::Compiled" ARRAY = 0x862b078 FILL = 30 MAX = 59 ARYLEN = 0x0 FLAGS = (REAL) Elt No. 0 SV = RV(0x817c3e8) at 0x85ca9d8 REFCNT = 1 FLAGS = (ROK) RV = 0x85ca840 SV = PVHV(0x8681a38) at 0x85ca840 REFCNT = 1 FLAGS = (SHAREKEYS,HASKFLAGS) UV = 4 NV = 0 ARRAY = 0x8667c58 (0:5, 1:2, 2:1) hash quality = 91.7% KEYS = 4 FILL = 3 MAX = 7 RITER = -1 EITER = 0x0 Elt "spalte4" [UTF8 "spalte4"] HASH = 0xcf2c47e3 SV = PV(0x8665f54) at 0x85cabb8 REFCNT = 1 FLAGS = (POK,pPOK,UTF8) PV = 0x8632668 "Pr\303\244fix\342\202\254uro:Das BU\342\202\254RO"\0 [UTF8 "Pr\x{e4}fix\x{20ac}uro:Das BU\x{20ac}RO"] CUR = 25 LEN = 28 Elt No. 1 SV = PVNV(0x85d08b0) at 0x85ca87c REFCNT = 1 FLAGS = (ROK) IV = 0 NV = 0 RV = 0x85ca870 SV = PVAV(0x85bc764) at 0x85ca870 REFCNT = 2 FLAGS = () IV = 0 NV = 0 ARRAY = 0x0 FILL = -1 MAX = -1 ARYLEN = 0x0 FLAGS = (REAL) PV = 0x85ca870 "" CUR = 0 LEN = 0 Elt No. 2 SV = PV(0x85ed254) at 0x85ca864 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x862ac90 "d41d8cd98f00b204e9800998ecf8427e"\0 CUR = 32 LEN = 36 Elt No. 3 SV = PV(0x85ed248) at 0x85ca8c4 REFCNT = 1 FLAGS = (POK,pPOK) PV = 0x862ab80 "test.tmpl"\0 CUR = 9 LEN = 12
Quotecpan> m HTML::Template
CPAN: Storable loaded ok
Going to read /home/developer/.cpan/Metadata
Database was generated on Wed, 03 Aug 2011 05:31:11 GMT
Module id = HTML::Template
DESCRIPTION a simple HTML templating system
CPAN_USERID SAMTREGAR (Sam Tregar <sam@tregar.com>)
CPAN_VERSION 2.9
CPAN_FILE S/SA/SAMTREGAR/HTML-Template-2.9.tar.gz
DSLI_STATUS MmpO (mature,mailing-list,perl,object-oriented)
MANPAGE HTML::Template - Perl module to use HTML Templates from CGI scripts
INST_FILE /usr/local/share/perl/5.8.8/HTML/Template.pm
INST_VERSION 2.9
1
2
3
developer@vm:/var/www/utftest$ sudo cpanm HTML::Template
HTML::Template is up to date. (2.9)
developer@vm:/var/www/utftest$
2011-08-03T13:25:21 mcfaqWarum muss ich trotz Setzens des charset von CGI immer noch diesen String dekodieren, wenn ich ihn ins template schreibe, aber nicht, wenn ich ihn die DB Tabelle schreibe???
1 2 3 4 5 6 7 8 9
#Durchführen des inserts in die Tabelle mit den Pflichtdaten unless ( $sth->execute( $cgiHash{'input'} ) ) { warn sprintf( "[Error]: Reason: [%s].", $dbh->errstr ); }
1 2 3 4 5 6 7 8
#Durchführen des inserts in die Tabelle mit den Pflichtdaten unless ( $sth->execute( decode('utf-8',$cgiHash{'input'}) ) ) { warn sprintf( "[Error]: Reason: [%s].", $dbh->errstr ); }
2011-08-03T13:25:21 mcfaqDas komische aber war, dass mein cpanm mir folgendes meldete:
Code: (dl )1
2
3developer@vm:/var/www/utftest$ sudo cpanm HTML::Template
HTML::Template is up to date. (2.9)
developer@vm:/var/www/utftest$
Außerdem:
2011-08-03T13:25:21 mcfaq
Warum muss ich trotz Setzens des charset von CGI immer noch diesen String dekodieren, wenn ich ihn ins template schreibe
1 2 3 4 5 6 7 8 9 10
... $template->param( spalte => decode('utf-8',$cgiHash{'input'}) ); ... #Durchführen des inserts in die Tabelle mit den Pflichtdaten unless ( $sth->execute( decode('utf-8',$cgiHash{'input'}) ) ) { ...
1 2 3 4 5 6 7 8 9 10
... $template->param( spalte => $cgiHash{'input'} ); ... #Durchführen des inserts in die Tabelle mit den Pflichtdaten unless ( $sth->execute( $cgiHash{'input'} ) ) { ...
2011-08-03T12:59:45 pqdann ist der mirror nicht richtig aktualisiert worden.
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
44
mit binmode für STDIN:
Template Euros: €€€
Form Euros:Das BU€RO
Perl Euros:5 mal Euro: €€€€€
DB Euros(1):Das BU€RO
DB Euros(2):Präfix€uro:Das BU€RO
-------------------------------------
ohne binmodes:
Template Euros: ���
Form Euros:Das BUâ?¬RO
Perl Euros:5 mal Euro: �����
DB Euros(1):Das BU€RO
DB Euros(2):Präfixâ?¬uro:Das BU€RO
-------------------------------------
mit binmode für STDOUT:
Template Euros: ���
Form Euros:Das BUâ?¬RO
Perl Euros:5 mal Euro: �����
DB Euros(1):Das BU€RO
DB Euros(2):Präfixâ?¬uro:Das BU€RO
-------------------------------------
mit beiden binmodes:
Template Euros: ���
Form Euros:Das BUâ?¬RO
Perl Euros:5 mal Euro: �����
DB Euros(1):Das BUâ?¬RO
DB Euros(2):Präfix�uro:Das BU�RO
2011-08-03T09:58:09 mcfaqFazit:
Es scheint keine Lösung für das Problem zu geben. Mann muss halt per Hand die DB Ergebnisse aus utf-8 dekodieren.