zaphod: CGI-Modul & UTF-8

Moin,
ich generiere ein Formular, das Daten für einen (UTF-8) Feed entgegennimmt per CGI-Modul, gesetzt ist:

$cgi->header(-charset => 'UTF-8'),
$cgi->start_html(-encoding => 'UTF-8'),

Das verarbeitende Script schreibt per

open my $test, ">:utf8", $file;

Es gibt aber offensichtlich trotzdem Probleme (Umlaute), die hinterher nicht korrekt dargestellt werden. Nun weiß ich allerdings nicht, wo sonst noch UTF-8-Encoding gesetzt werden könnte.
3 Ansätze hätte ich:

  1. Täusche ich mich, oder ist es tatsächlich nicht vorgesehen, via CGI-Modul für Formulare die übliche Option "accept-charset" zu setzen? In der manpage steht nichts dazu drin und der Versuch, es wie alle anderen Optionen zu setzen

$cgi->start_form(-method => 'post',
                 -accept-charset => 'UTF-8',

schlägt fehl. Gibt es da noch einen anderen Weg?

  1. Das Schreiben per ">:utf8" klappt nicht wirklich- wie ließe sich das überprüfen?

  2. Schließlich bestätigte sich noch einer der elenden Verdachtsmomente: Das verarbeitende Script ist nicht in UTF-8 gespeichert (use utf8 ist gesetzt).
    Also habe ich es auf die Schnelle per Windows-Editor so gespeichet/BOM gesetzt, das führt aber  beim Test zu Error 500- das log sagt:
    (8)Exec format error
    Tja-

falls wer einen Tipp hätte...

Beste Grüße
Zaphod

  1. Tach!

    Ich kann dir nicht Perl-spezifisch sondern nur allgemein antworten.

    Das verarbeitende Script schreibt per
    open my $test, ">:utf8", $file;

    Ein Script kann nur dann in der korrekten Ziel-Kodierung ausgeben, wenn auch die Quell-Kodierung bekannt und korrekt ist. Es gibt kein "egal was ist, mach UTF-8". Das würde voraussetzen, dass man zweifelsfrei Kodierungen erkennen könnte.

    Es gibt aber offensichtlich trotzdem Probleme (Umlaute), die hinterher nicht korrekt dargestellt werden. Nun weiß ich allerdings nicht, wo sonst noch UTF-8-Encoding gesetzt werden könnte.

    Mach Kontrollausgaben. Lass dir die Werte in hexadezimaler Form ausgeben. Für PHP kann man dazu eine URL-Kodierung sehr gut missbrauchen. Das geht sicher in Perl auch.

    1. Täusche ich mich, oder ist es tatsächlich nicht vorgesehen, via CGI-Modul für Formulare die übliche Option "accept-charset" zu setzen?

    Die Frage kann ich nicht beantworten. Im Allgemeinen braucht man diesen Parameter nicht und er funktioniert auch nicht in allen (alten?) Browsern. Es reicht, der Seite eine Kodierung anzugeben und der Browser wird diese zum Zurücksenden von Formulardaten verwenden.

    1. Das Schreiben per ">:utf8" klappt nicht wirklich- wie ließe sich das überprüfen?

    Mit Kontrollausgaben. Wenn es eine Datei ist, nimm einen Hexeditor zum anschauen.

    1. Schließlich bestätigte sich noch einer der elenden Verdachtsmomente: Das verarbeitende Script ist nicht in UTF-8 gespeichert (use utf8 ist gesetzt).
      Also habe ich es auf die Schnelle per Windows-Editor so gespeichet/BOM gesetzt, das führt aber  beim Test zu Error 500- das log sagt:
      (8)Exec format error

    Die BOM ist bei UTF-8 nicht notwendig und wie du siehst, kommt sie dir hier in die Quere. Lass sie weg.

    dedlfix.

  2. hi,

    open my $test, ">:utf8", $file;

    Da setzt Du für den Layer eine Kodierung. Alles was Du dann in den Handler schreibst (mit print), das muss dieser Kodierung entsprechen (utf-8).

    Perl unterscheidet seit 5.6 zwischen kodierten Zeichenketten und Oktetten, also zwischen byte- und charactersemantic. Gelegentlich ist dabei von einem UTF-8-Flag die Rede, wenn es sich um utf-8-kodierte Zeichenketten handelt.

    UTF-8-kodiert Zeichenketten != Oktetten

    Web/CGI: Eingaben, die mit CGI.pm geparst werden, sind im Default keine UTF-8-kodierten Zeichenketten, sondern Oktetten.

    Es gibt mehrere Möglichkeiten:

    • dem CGI.pm mitteilen, dass die Eingaben als UTF-8-kodierte Zeichenketten geliefert werden (neuere CGI.pm, bitte bei CPAN nachschauen)
    • die bytesemantic beibehalten und beim print in einen Handler (Datei) diesen auf :raw belassen
    • Encode.pm benutzen um zwischen byte- und charactersemantic wechseln zu können (Encode.pm ist ab 5.8 verfügbar)
    • Pragma use bytes; no bytes;
    1. Täusche ich mich, oder ist es tatsächlich nicht vorgesehen, via CGI-Modul für Formulare die übliche Option "accept-charset" zu setzen? In der manpage steht nichts dazu drin und der Versuch, es wie alle anderen Optionen zu setzen

    Entscheidend ist die Angabe der Kodierung im Content-Type-HTTP-Header, mit welchem das Formular ausgeliefert wird.

      
    use CGI qw(-utf8);  
    
    

    Liefert Dir die Eingaben als UTF-8-kodierte Zeichenketten. Wenn das mit print in einen Handler (Filehandler, STDOUT) gehen soll, muss das utf-8-Flag wieder entfernt werden, so dass die reinen Oktetten vorliegen. Oder der Handler/Layer wird entsprechend gesetzt ':utf8'.

    CGI.pm

    Hotti

    1. Moin Hotti,
      besten Dank für den ausführlichen Hintergrund-Report. Dieser kleine Zauberspruch

      use CGI qw(-utf8);

      im verarbeitenden Script tat es schon.  
      In Zusammenarbeit mit use bytes dann auch der Parser.  
        
      Big Up  
      Zaphod  
      
      
      1. hi Zaphod,

        im verarbeitenden Script tat es schon.
        In Zusammenarbeit mit use bytes dann auch der Parser.

        Das freut mich. Also, dieses utf-8-Geraffel seit Perl v5.6 ist schon manchmal verwirrend: UTF-8 ist nicht UTF-8, weil es diesen SvUTF8 gibt (Scalar-Value UTF8). Perl ist in dieser Hinsicht immer noch in Bewegung, d.h., die Version spielt gelegentlich eine Rolle.

        Btw., im Wiki der Perl-Community gibt es dazu einen Artikel, schwer zu finden, aber guck mal, da steht das alles noch ein bischen ausführlicher.

        Viele Grüße,
        Hotti