zaphod: UTF-8 dekodieren (?)

Moin,
mal wieder das unbeliebte, alte Hütchenspiel: Ich habe hier einen Schwung Daten via CGI zu unicodieren und leider das Problem, dass sich in einem Feld bereits UTF-8-Daten befinden und probiere schon eine Weile daran herum, eine Doppelkodierung zu vermeiden.
Der simpelste Versuch
use Encode;
$test=decode("UTF-8",$string); (mit "utf8" übrigens auch nicht)
klappte nicht, entflaggen
Encode::_utf8_off($string);
ebensowenig wie transkodieren
from_to($string,"utf8","latin1");
Bekanntes Resultat ist immer: Vermurkste Umlaute/ß/"
Der letzte Ansatz scheint mir eigentlich logisch, die Frage wäre aber: Welches Format haben eigentlich Daten zunächst, die in ein per CGI so
$cgi->header(-charset => 'UTF-8'),
$cgi->start_html(-encoding => 'UTF-8'),
$cgi->start_form(-method => 'post',
generiertes Formular eingegeben werden?
(Und die dumme Frage: Kann man eigentlich doppelt DEkodieren?)

Grüße
Zaphod

  1. interessante fragestellung.
    Ich ärgere mich auch immer wieder mit den zeichenkodierungen rum, wenn mal wieder ein Service noch auf dem alten läuft oder man eine gemischte Webseite probiert zu wrappen!

    Bin echt auf Lösungsansätze gespannt, meine Lösung hab ich grade nicht zur hand, werde das aber nachholen!

    1. Tach!

      Bin echt auf Lösungsansätze gespannt, meine Lösung hab ich grade nicht zur hand, werde das aber nachholen!

      Eine Lösung kann nur individuell gefunden werden. Allgemein kann man nur sagen: Man muss wissen, an welcher Stelle welche Kodierung vorliegt, damit man sie korrekt verarbeiten oder gezielt umkodieren kann. Zudem muss jedem weiterverarbeitenden Teil die Kodierung bekanntgegeben werden. Anhand der Daten eine Kodierung zu erkennen ist nur sehr bedingt möglich. Deshalb sollte man zwischen zwei Systemen immer aktiv die Zeichenkodierung bekanntgeben/aushandeln.

      dedlfix.

  2. Tach!

    Vorab: Ich kenne Perl so gut wie gar nicht, kann dir also nur allgemein antworten.

    Ich habe hier einen Schwung Daten via CGI zu unicodieren und leider das Problem, dass sich in einem Feld bereits UTF-8-Daten befinden und probiere schon eine Weile daran herum, eine Doppelkodierung zu vermeiden.

    Was ist "Feld" in deinem Fall?

    Der simpelste Versuch
    use Encode;
    $test=decode("UTF-8",$string); (mit "utf8" übrigens auch nicht)
    klappte nicht, entflaggen
    Encode::_utf8_off($string);
    ebensowenig wie transkodieren
    from_to($string,"utf8","latin1");
    Bekanntes Resultat ist immer: Vermurkste Umlaute/ß/"

    "Klappt nicht" ist genauso wenig hilfreich wie "vermurkste Umlaute". Aus diesen Aussagen kann ich dir keinen Erklärungsversuch generieren, der bei der Ursachenermittlung helfen könnte. Also bitte: Was sind die Eingabedaten (wenn möglich die problematischen Teile auch in Hex-Darstellung), was ist das konkrete Ergebnis?

    Der letzte Ansatz scheint mir eigentlich logisch, die Frage wäre aber: Welches Format haben eigentlich Daten zunächst, die in ein per CGI so
    $cgi->header(-charset => 'UTF-8'),
    $cgi->start_html(-encoding => 'UTF-8'),
    $cgi->start_form(-method => 'post',
    generiertes Formular eingegeben werden?

    Sie haben genau die Kodierung, die der Browser verwendet. Wenn an ihm nichts verstellt ist, nimmt er üblicherweise die Kodierung, die für die Seite verwendet wurde, die das Formular enthält. Die Reihenfolge, wo der Browser die Kodierungsangabe sucht, findest du unter "Beachten Sie" am Ende des Abschnitts "In Richtung Client" von http://wiki.selfhtml.org/wiki/Themen:Zeichencodierung/Webserver. Beim Formular (form-Element) kommt noch das Attribut accept-charset hinzu, das einige Browser beachten und welches die anderen Angaben übertrumpfen soll.

    (Und die dumme Frage: Kann man eigentlich doppelt DEkodieren?)

    Du kannst so oft kodieren und dekodieren, wie du lustig bist. Ob dabei sinnvolle Dinge rauskommen ist eine andere Frage.

    a & b -> HTML-Kodieren: a & b -> HTML-Kodieren: a & b

    a & b -> HTML-Dekodieren: a & b -> HTML-Dekodieren: a & b -> HTML-Dekodieren: a & b (aber eigentlich Syntaxfehler)

    Dekodieren gibt es bei Zeichenkodierungen im Prinzip nicht, die Zeichen liegen (während der Verarbeitung) immer in irgendeiner Form der Kodierung vor. Du kannst lediglich umkodieren. Wenn du allerdings einen ISO-8859-1-Text mit Zeichen oberhalb von x7F als UTF-8 zu interpretieren versuchst, gibt es Zeichenverlust.

    dedlfix.

  3. Dein Formular ist offensichtlich mangelhaft. Wieso zeigst du nicht deinen ganzen Code? Willst du uns Helfern absichtlich mit Glaskugelorakeln das Leben schwer machen?

    Das funktioniert:

      
    #!/usr/bin/env perl  
    use CGI qw();  
    use Encode qw(decode encode);  
    use HTML::Entities qw(encode_entities);  
      
    my $cgi = CGI->new;  
    my $characters = decode 'UTF-8', $cgi->param('data'), Encode::FB_CROAK | Encode::LEAVE_SRC;  
    # hier $characters verarbeiten  
    my $octets = encode 'UTF-8', $characters, Encode::FB_CROAK | Encode::LEAVE_SRC;  
      
    print $cgi->header(-type => 'application/xhtml+xml', -charset => 'UTF-8'),  
    $cgi->start_html(-encoding => 'UTF-8'),  
    $cgi->start_form(-method => 'post', '-accept-charset' => 'UTF-8'),  
    $cgi->input({-type => 'text', name => 'data'}),  
    $cgi->input({-type => 'submit'}),  
    $cgi->end_form,  
    $cgi->hr,  
    encode_entities($octets, q(<>&")),  
    $cgi->end_html;
    

    Und nun die übliche Belehrung: CGI ist schon lange keine zeitgemäße Technologie mehr, und CGI.pm hat ein abscheuliches Interface, das zu schwierig zu bedienen ist, um richtige Ergebnisse zu erhalten. Steige um auf PSGI und ein modernes Webframework.

    (Und die dumme Frage: Kann man eigentlich doppelt DEkodieren?)

    Versuch es doch einmal! Was beobachtest du? Welche Schlüsse ziehst du daraus?

    1. Okeydokey-
      hier das vorläufige Zwischenergebnis einiger Testreihen.

      Dein Formular ist offensichtlich mangelhaft.

      Nö- es ist mit deinem fast identisch:

        
      use CGI;  
      use CGI::Carp qw(fatalsToBrowser);  
      $CGI::POST_MAX = 1024 * 100;  
      $CGI::DISABLE_UPLOADS = 1;  
      use Encode qw(decode encode);  
      use utf8;  
      use strict;  
        
      my ($test, $noutf);  
        
      $cgi=new CGI;  
      $xline=$cgi->param('test');  
      #$xline=UTF-Line von Feed (z.B. "Überflieger dröhnen ärgerlich")  
      $noutf=decode 'UTF-8', $xline, Encode::FB_CROAK | Encode::LEAVE_SRC;  
      #Habe ich jetzt mal von dir übernommen, aber ein schlichtes  
      #$noutf = decode("UTF-8", $xline); geht genauso  
        
        
      print $cgi->header(-charset => 'UTF-8'),  
            $cgi->start_html(-title => '+++ test',  
                             -encoding => 'UTF-8'),  
            $cgi->p($noutf),                        # !!!  
            $cgi->start_form(-method => 'post',  
                             -action => 'test.pl'  
                             '-accept-charset' => 'UTF-8'),  
            $cgi->start_table()."\n",  
            $cgi->Tr($cgi->td('TEST:'),  
            $cgi->td($cgi->textfield(-name =>'test', -size => 80, -value => $noutf)))."\n",  
            $cgi->Tr($cgi->td('kommentar'), $cgi->td(  
            $cgi->textarea(-name =>'comment', -rows => 10, -columns => 70)))."\n",  
            $cgi->Tr($cgi->td('+++'),  
                     $cgi->td($cgi->submit(-name =>'los', -value =>'los')))."\n",  
            $cgi->end_table(),  
            $cgi->end_form(),  
            $cgi->end_html();  
        
      
      

      Lustig dabei:
      Die testweise Ausgabe
      $cgi->p($noutf),
      hat das erwartbare Ergebnis: Umlaute werden nicht korrekt angezeigt.
      Bei der Ausgabe im Textfield aber sehr wohl!
      Zwischendurch habe ich den Output des Formulars mal durch eine schlichte Testroutine geschickt:

        
      $cgi=new CGI;  
      @all=$cgi->param();  
        
      print "Content-Type: text/html; charset=UTF-8\n\n";  
      foreach (@all)  
      {  
       $val=$cgi->param($_);  
       if (is_utf8($val))  
       {  
        print "UTF-8: ";  
       }  
       else  
       {  
        print "Nope: ";  
       }  
       print "$val<br>";  
      }  
      
      

      Tja: Hier kommt bei allen Werten "Nope"- also kein UTF-8 (?)
      Firefox erkennt das allerdings als Zeichenkodierung und zeigt alle Umlaute korrekt an.

      Das verarbeitende Script macht hauptsächlich

        
      use XML::DOM;  
      use CGI qw(-utf8);  
      use CGI::Carp qw(fatalsToBrowser);  
      use utf8;  
      use bytes;  
        
      $cgi=new CGI;  
      $test=$cgi->param('test');  
      $comment=$cgi->param('comment');  
        
      $parser=XML::DOM::Parser->new();  
      $doc=$parser->parsefile($file);  
      $root=$doc->getDocumentElement();  
      $entries=$doc->getElementsByTagName("entry");  
        
      $new=$doc->createElement("entry");  
      $xtest=$doc->createElement("test");  
      $xtest->addText($test);  
      $xtest=$doc->createElement("comment");  
      $xtest->addText($comment);  
      $new->appendChild($comment);  
      $root->insertBefore($new,$entries->item(0));  
        
      open my $utf, ">:utf8", $file or die $!;  
      $doc->print($utf);  
      $doc->dispose;  
      
      

      Also 08/15.
      Und der Parser gibt die Entries nochmal einzeln aus.
      Der Knackpunkt scheint also die Schreibroutine zu sein. Egal, was ich versuche, das Resultat ist immer:
      Im Comment sind die Umlaute ok, im Test-Element nicht.
      Versuche ich hier nochmal
      $tst2=decode 'UTF-8', $test, Encode::FB_CROAK | Encode::LEAVE_SRC;

      Steigt der Parser beim Auslesen mit
      utf8 "\xFC" does not map to Unicode at (...)
      aus.

      Gibts noch andere Möglichkeiten, per XML::DOM zu schreiben?
      (Achja: $doc->printToFile($file) zerschießt das ganze Dokument, so dass es kein Parser mehr lesen kann)

      Grüße
      Zaphod

      1. hi,

        aus meiner Praxis mal ein bischen geplaudert: Mit kodierten Zeichenketten, egal ob utf-8 oder iso-8859-1, musst Du nur 'arbeiten' wenn Stringfunktionen wie substr(), index(), lc(), uc() usw. zum Einsatz kommen.

        Selbst wenn MySQL im Spiel ist, kannst Du da Oktetten (!= Zeichenketten) hinschicken, alleine das Attribut { mysql_enable_utf8 => 1 } regelt die zeichenorientierte Kommunikation, allerdings musst Du beachten, dass das was der DB-Driver zurückliefert dann utf-8-kodierte Zeichenketten sind. Im Fall von Anwendungen mit DB-Anbindung wirst Du ohnehin die String-Funktionen der DB-Engine überlassen (i.d.R.).

        Perl-intern kannst Du, bis auf o.g. Stringfunktionen fast alles byteorientiert erledigen, und alles was IO (FileHandle, STDOUT, Sockets) betrifft, sind Bewegungen von Bytes, kodierte Zeichenketten sind da völlig deplatziert.

        Verzichte auch beim CGI-Modul auf das -utf8 Flag und flagge die empfangenen Oktetten erst dann mit dem entsprechenden Encoding, wenn das tatsächlich gebraucht wird. Dann verlierst Du auch nicht die Übersicht.

        Und überhaupt: Bis Perl v5.8 (Encode.pm) war ein
        uc('iso-8859-1: ä');
        gar nicht möglich.

        Hotti

      2. Dein erstes Programm ist mangelhaft, es kompiliert nicht einmal. Gib doch ein wenig acht, was für Code du postet! Liederliche Programmierer können niemals gute Ergebnisse erzielen.

        #Habe ich jetzt mal von dir übernommen, aber ein schlichtes
        #$noutf = decode("UTF-8", $xline); geht genauso

        Diese Aussage ist falsch, was du selbst hättest beobachten können, wenn du ein wenig ausgiebiger getestet hättest. Fehlerhafte Oktettsequenzen werden nämlich so, wie du es geschrieben hast, einfach mit Unicodeersetzungszeichen verbuttert und ruinieren damit unwiderruflich deine Textdaten ohne irgendeine Warnung oder Fehlermeldung. Deshalb bekommst du diesen Ruin erst mit, wenn es schon zu spät ist, oder womöglich gar nicht.

        Nach Behebung der offensichtlichen Syntaxfehler in deinem Programm bleibt festzustellen, dass du für Texteingaben hereinkommende Oktette zwar korrekt nach Zeichen dekodierst, aber dann versuchst, die Zeichen unkodiert auszugeben. Das ist falsch. Du musst Zeichen, wenn sie nach draußen gelangen, in Oktette kodieren, siehe Dokumentation.

        Außerdem musst du Inhalte maskieren, wenn sie in HTML-Kontext eingebettet sind; das hast du auch vernachlässigt und somit eine sicherheitsrelevante Cross-Site-Scripting-Lücke geschaffen! Das ist echt schlimm. Lies dir mein Programm noch einmal aufmerksam durch und vollziehe jeden Schritt nach.

        Ich schrieb:

        Und nun die übliche Belehrung: … Steige um auf PSGI und ein modernes Webframework.

        Warum gehst du nicht auf den Rat ein? Mit CGI.pm halst du dir nur unnötig Arbeit und Ärger auf.

        if (is_utf8($val))
        {
          print "UTF-8: ";
        }

        Nein, diese Abfrage ist vollkommen falsch und sinnlos und muss entfernt werden.
        • Falsch, weil is_utf8 nicht überprüft, ob eine Oktettfolge gültiges UTF-8 ist¹, sondern ob beim skalaren Wert ein gewisser Markierer gesetzt ist. Dieser Markierer ist rein für Perls interne Zwecke und hat nur die Leute zu interessieren, welche XS programmieren².
        • Sinnlos, weil du eigentlich prüfen möchtest, ob du Zeichen oder Oktette hast. Perl kann dir das nicht sagen, du musst stattdessen selber Buch darüber führen, welcher Semantik eine Variable unterliegt! Ich rüge die Verwendung von deinen Variablennamen, z.B. $xline, das ist sagt nichts darüber aus, welche Bedeutung der Inhalt halt. Benutze in Zukunft eine Form der ungarischen Notation, bei der man auf einen Blick erkennt, ob eine Variable Oktette oder Zeichen enthalten soll.

        ¹ Auf gültiges UTF-8 überprüft man einfach, indem man versucht zu dekodieren, wie ich das in meinem Programm geschrieben habe. Wenn es sich um ungültiges UTF-8 handelt, gibt es eine Exception.
        ² Du programmierst nicht XS.

        use bytes;

        Das ist Murks, entferne das. Die Verwendung dieses Pragmas ist nahezu immer ein Versuch, etwas mit der groben Keule geradezubiegen. Dabei musst du zwangsläufig scheitern und machst aus Unverständnis nur noch mehr kaputt, siehe Dokumentation.

        use XML::DOM;

        Dieses Modul ist überholt, man verwendet XML::LibXML.

        use CGI qw(-utf8);

        Die Verwendung des Imports -utf8 ist problematisch, entferne ihn und dekodiere für Texteingaben hereinkommende Oktette manuell, so wie ich das in meinem Programm gezeigt habe! Für Nicht-Text-Eingaben wie z.B. Uploads verhält sich CGI.pm unter dem Einfluss des Imports -utf8 fehlerhaft und zerstört unwiderruflich die Daten, siehe Dokumentation.

        Zum Rest vom Code äußere ich mich vorerst nicht im Detail. Setze meine Ratschläge um und melde deinen Fortschritt.

    2. gudn tach CPAN!

      Und nun die übliche Belehrung: CGI ist schon lange keine zeitgemäße Technologie mehr, und CGI.pm hat ein abscheuliches Interface, das zu schwierig zu bedienen ist, um richtige Ergebnisse zu erhalten. Steige um auf PSGI und ein modernes Webframework.

      im hinblick auf das selfhtml-wiki und perl (siehe auch http://wiki.selfhtml.org/wiki/Diskussion:Perl) bin ich am ueberlegen, wie man kurze, aber voll funktionstuechtige perl-beispiele bastelt, die sowohl didaktischen anspruechen genuegen, als auch leicht verstaendlich sind aber auch von profis ohne bauchweh oder augenkrebs angeschaut werden koennen. wie wuerdest du vorgehen?

      mit catalyst und dancer habe ich mich bisher nur oberflaechlich befasst, habe aber den eindruck, dass das nix fuer anfanger ist. dann lieber cgi, weil man da wenigstens noch ansatzweise die (vermutlich vertraute) html-struktur erkennt.

      eine andere moeglichkeit waere: ganz ohne html-schnick, aber das wuerde imho nicht so zu selfhtml passen.

      prost
      seth

      1. hi,

        eine andere moeglichkeit waere: ganz ohne html-schnick, aber das wuerde imho nicht so zu selfhtml passen.

        So richtig brauchbar an CGI.pm ist nur die param()-Funktion, um den Rest ist es schade, weil das kaum jemand nutzt (ich kenne niemanden außer Struppi?). Selbst für CGI::header() gibt es seit Jahren eine zweckmäßigere Alternative HTTP::Headers.

        Was die Ausgabe von HTML betrifft: Auch in Perl gibt es erstklassige Template-Engines womit sich moderne Design-Patterns wie z.B. MVC umsetzen lassen.

        Was Perl im reinen CGI-Betrieb für komplexe Frameworks auf den ersten Blick untauglich macht, ist die Tatsache, dass bei jedem Request der Interpreter geladen und viel Code kompiliert werden muss. Aber auch hierzu gibt es Lösungswege, z.B. mod_perl oder einzelne ausführbare Scripts als FastCGI. Oder der Code wird auf Responseklassen verteilt, so dass nur kompiliert wird, was zum beantworten eines Requests tatsächlich gebraucht wird (mein FW ist so gebaut, ausführbar ist nur ein sogenannter Bootstrap-Loader).

        Und überhaupt ermöglicht Perl seit Jahren einen modernen Programmierstil mit OO-Interfaces wie z.B. IO::File (mit Blick auf den verlinkten SELF-Wiki).

        Last but not least: Um Perl ein bischen interessanter zu machen, würde ich für den SELF-Wiki einen Artikel schreiben welcher dem Leser Wege zeigt, die aus dem total verstaubten Perl-Image herausführen, wie wäre es damit?

        Hotti

        1. Om nah hoo pez nyeetz, hotti!

          Last but not least: Um Perl ein bischen interessanter zu machen, würde ich für den SELF-Wiki einen Artikel schreiben welcher dem Leser Wege zeigt, die aus dem total verstaubten Perl-Image herausführen, wie wäre es damit?

          Ich freu mich aufs Lesen.

          Matthias

          --
          1/z ist kein Blatt Papier.

          1. hi,

            Ich freu mich aufs Lesen.

            Ein Script habe ich schon fertig, kannst Du es mal testen und versuchen nachzuvollziehen, was ich mir dabei gedacht habe?

            package main; steht hier für eine einfache Responseklasse und nur für diese eine Anwendung. Diese Klasse könnte genausogut als Basisklasse für alle möglichen Extensions dienen, guck mal, ob Du die Basismethoden erkennst ;)

            Ansonsten ist das doch alles selbsterklärend.

            Text::Template als einfache Template-Engine müsstest Du mal fix installieren.

              
            #!/usr/bin/perl  
              
            use strict;  
            use warnings;  
            use Text::Template;  
            use HTTP::Headers;  
            require CGI;  
            use CGI::Carp qw(fatalsToBrowser);  
              
            package main;  
              
            # main control, das Response-Objekt als Instanz der Klasse main  
            my $mc = main->new() or die $@; # CGI::Carp würde hier einspringen  
              
            # Diese Klasse kennt nur einen Content-Type  
            $mc->set_header("Content-Type" => "text/html; charset=UTF-8");  
              
            # TRY-Block  
            eval{  
            	# die Methoden init(), browse(), control() dürfen Exceptions werfen  
            	$mc->init();  
            	if($mc->param()) { $mc->control() }  
            	else{ $mc->browse() }  
            };  
            # CATCH Exceptions, in Perl ist der dazugehörige Text in $@ zu finden  
            if(my $EVE = $@){  
            	print $mc->header(), qq(<pre>Fehler: $EVE</pre>);  
            }  
            else{  
            	print $mc->header(), $mc->bodybuild();  
            }  
              
              
            ########################### Methods #######################################  
              
            # Erstelle eine Instanz der package (class) main  
            # Konstruktor  
            sub new{  
            	my $class = shift;  
            	my $self = bless{}, $class;  
            	return eval{  
            		$self->{HTTP_HEADERS} = HTTP::Headers->new();		  
            		$self->{TEXT_TEMPLATE} = Text::Template->new(TYPE => 'FILEHANDLE', SOURCE => *DATA ) or die $@;  
            		$self->{CGI} = new CGI;  
            		$self->{STASH} = {};  # Data-Hash für das Template  
            		$self;  
            	};  
            }  
              
            # Template-Prozess und Rückgabe des BODY  
            sub bodybuild{  
            	my $self = shift;  
            	return $self->{TEXT_TEMPLATE}->fill_in( HASH => $self->{STASH});  
            }  
              
            # Zusätzliche Funktion, steht über browse() und über control()  
            sub init{  
            	my $self = shift;  
            	$self->{STASH}{date} = localtime;  
            	$self->{STASH}{url}  = $ENV{SCRIPT_NAME};  
            }  
            # der Controller  
            sub control{  
            	my $self = shift;  
            	if($self->param('calc')){  
            		# fülle das Formular wieder mit den eingegebenen Werten  
            		$self->{STASH}{Zahl_a} = trim($self->param('Zahl_a'));  
            		$self->{STASH}{Zahl_b} = trim($self->param('Zahl_b'));	  
            	  
            		# prüfe die Eingaben im STASH  
            		if(! $self->{STASH}{Zahl_a}){  
            			$self->{STASH}{mesg} = "Zahl a fehlt, bitte zwei Zahlen eingeben!";  
            			return;  
            		}  
            		elsif(! $self->{STASH}{Zahl_b}){  
            			$self->{STASH}{mesg} = "Zahl b fehlt, bitte zwei Zahlen eingeben!";  
            			return;  
            		}  
            		elsif($self->{STASH}{Zahl_a} !~ /^\d+$/){  
            			$self->{STASH}{mesg} = "Zahl a ist keine Ganze Zahl!";  
            			return;  
            		}  
            		elsif($self->{STASH}{Zahl_b} !~ /^\d+$/){  
            			$self->{STASH}{mesg} = "Zahl b ist keine Ganze Zahl!";  
            			return;  
            		}  
            		else{ # Ergebnis kann ausgegeben werden  
            			my $res = $self->{STASH}{Zahl_a} + $self->{STASH}{Zahl_b};  
            			$self->{STASH}{mesg} = $res;  
            		}  
            	}  
            	else{  
            		# werfe eine Exception  
            		die "Unbekannter Parameter!\n";  
            	}  
            }  
            # Methode wird aufgerufen, wenn keine GET/POST Parameter im Request sind  
            sub browse{  
            	my $self = shift;  
            	$self->{STASH}{mesg} = "Bitte nur ganze Zahlen eingeben!";  
            }  
            # Leerzeichen am Anfang und am Ende entfernen  
            # Am Ende werden auch etwaige Zeilenumbrüche entfernt  
            sub trim{  
            	my $s = shift;  
            	$s =~ s/^\s+//;  
            	$s = unpack "A*", $s;  
            	return $s;  
            }  
              
            ########################### Delegations ###################################  
            # HTTP::Headers  
            # die zu delegierenden Methoden bekommen hier andere Namen  
            sub set_header{  
            	my $self = shift;  
            	return $self->{HTTP_HEADERS}->header(@_);  
            }  
            # gibt alle gesetzten Header als String zurück  
            sub header{  
            	my $self = shift;  
            	return $self->{HTTP_HEADERS}->as_string(@_, "\n\n");  
            }  
              
            # CGI, delegiere die param()-Methode mit demselben Namen wie CGI::param()  
            sub param{  
            	my $self = shift;  
            	return $self->{CGI}->param(@_);  
            }  
            ###########################################################################  
            # Das Template ist unterhalb des Tokens __DATA__ notiert  
            __DATA__  
            <h1>Ein einfaches Formular, Date: {$date}</h1>  
              
            <p>Hinweis/Ergebnis: {$mesg}</p>  
              
            <form action="{$url}">  
            	<fieldset><legend><strong>Zahl a, Zahl b, Enter:</strong></legend>  
            		<input name="Zahl_a" value="{$Zahl_a}" title="Zahl a">  
            		<input name="Zahl_b" value="{$Zahl_b}" title="Zahl b">  
            		<input type="submit" name="calc" value="Summe a+b berechnen">  
            	</fieldset>  
            </form>  
              
            <p>  
            	<a href="{$url}">Form ohne Parameter neu Laden</a>  
            </p>  
            
            
            1. hi,

              Ich freu mich aufs Lesen.

              Testen Online

              Hotti

              1. Om nah hoo pez nyeetz, hotti!

                Meine Meinung ist, dass man da durchaus einen Wiki-Artikel zum Einstieg (auch in OOP-Denke) draus machen kann. Bei der Fehlerbehandlung fände ich es schöner, wenn immer alle Fehler angezeigt werden. So dann bau deinen Artikel drum rum.

                Matthias

                --
                1/z ist kein Blatt Papier.

                1. Om nah hoo pez nyeetz, hotti!

                  Hai!

                  {.. ]So dann bau deinen Artikel drum rum.

                  Er steht drunter:

                  Script und Artikel

                  Horst Gunter

                  1. Om nah hoo pez nyeetz, hotti!

                    Script und Artikel

                    Wenn du den Leuten, objektorientierte Programmierung nahe bringen möchtest, dann fehlt da noch eine ganze Menge drum herum. Ich finde das Beispiel an sich garnicht so schlecht, ob es aber wirklich geeignet ist, die Jünger der algorithmischen Programmierung zur Abkehr zu bewegen, wage ich zu bezweifeln. Am Ergebnis selbst sieht man ja nicht, welches Programmierparadigma dahintersteckt. Nur mal so als Stichworte: Klasse, Objekt, Methode, Konstruktor, privat, public, ...

                    Matthias

                    --
                    1/z ist kein Blatt Papier.

                    1. Moin,

                      [..]Nur mal so als Stichworte: Klasse, Objekt, Methode, Konstruktor,

                      Pass auf, dass Dir diese Worte nicht die Augen ausstechen, beim Lesen des Artikels ;)

                      privat, public, ...

                      Perl ist in dieser Hinsicht nicht so pragmatisch, public/private sind Sache der Vereinbarung...

                      Aber was ich machen könnte: Die im Artikel beschriebene Aufteilung in die zwei Klassen in einem Programmierbeispiel zeigen.

                      Hotti

                      1. Om nah hoo pez nyeetz, hotti!

                        [..]Nur mal so als Stichworte: Klasse, Objekt, Methode, Konstruktor,

                        Pass auf, dass Dir diese Worte nicht die Augen ausstechen, beim Lesen des Artikels ;)

                        Ich hab die Begriffe schon gelesen, aber du musst sie auch _erläutern_

                        Matthias

                        --
                        1/z ist kein Blatt Papier.

                        1. Ich hab die Begriffe schon gelesen, aber du musst sie auch _erläutern_

                          Was ist denn an meinen Erläuterungen unverständlich?

                          1. Om nah hoo pez nyeetz, hotti!

                            Was ist denn an meinen Erläuterungen unverständlich?

                            Gedacht sollte der Artikel ja für Anfänger in der OOP sein. "Um Perl ein bischen interessanter zu machen, würde ich für den SELF-Wiki einen Artikel schreiben welcher dem Leser Wege zeigt, die aus dem total verstaubten Perl-Image herausführen, wie wäre es damit?" (hotti) Das leistet der Artikel nicht.

                            Wenn ich algorithmisch/funktionaler Programmierstil mit verstaubt gleichsetze und OOP mit modern, was zugegebenermaßen ziemlich schwarz-weiß ist, haut mich dein Artikel nicht vom Hocker.

                            Ein Leser weiß. u.U. nicht, was eine Klasse ist, weiß nicht, dass, ob oder warum es Sinn macht, GUI und Programmlogik von einander zu trennen. Langer Rede kurzer Sinn: Fürs Wiki derzeit ungeeignet.

                            Matthias

                            --
                            1/z ist kein Blatt Papier.

                            1. hi,

                              Gedacht sollte der Artikel ja für Anfänger in der OOP sein. "Um Perl ein bischen interessanter zu machen, würde ich für den SELF-Wiki einen Artikel schreiben welcher dem Leser Wege zeigt, die aus dem total verstaubten Perl-Image herausführen, wie wäre es damit?" (hotti) Das leistet der Artikel nicht.

                              Ok. Es ist auch keine leichte Aufgabe.

                              Ein Leser weiß. u.U. nicht, was eine Klasse ist, weiß nicht, dass, ob oder warum es Sinn macht, GUI und Programmlogik von einander zu trennen.

                              Das sind keine Perl-Specials.

                              Fürs Wiki derzeit ungeeignet.

                              Dann melde Dich wieder, wenn die Zeit gekommen ist ;)

                              Hotti

      2. Om nah hoo pez nyeetz, seth!

        eine andere moeglichkeit waere: ganz ohne html-schnick, aber das wuerde imho nicht so zu selfhtml passen.

        Der _sichtbare_ BeispielCode sollte völlig ohne HTML auskommen. Ich weiß nicht wie es in der Doku ist, aber im Wiki können sichtbarer BeispielCode und "So-siehts-aus"-Dokument völlig unterschiedlich sein.

        Matthias

        --
        1/z ist kein Blatt Papier.

        1. gudn tach!

          eine andere moeglichkeit waere: ganz ohne html-schnick, aber das wuerde imho nicht so zu selfhtml passen.

          Der _sichtbare_ BeispielCode sollte völlig ohne HTML auskommen. Ich weiß nicht wie es in der Doku ist, aber im Wiki können sichtbarer BeispielCode und "So-siehts-aus"-Dokument völlig unterschiedlich sein.

          hmm, bisher bin ich immer davon ausgegangen, dass es der alten doku darum ging, zu zeigen, wie man perl insb. fuers web verwendet. aber stimmt, eigentlich wurde perl ja viel allgemeiner beschrieben. insofern waere es tatsaechlich ueberlegenswert, den html-kram einfach ersatzlos zu beseitigen. den beispielcode wuerde es auf jeden fall wesentlich uebersichtlicher machen.

          prost
          seth

      3. wie wuerdest du vorgehen?

        Ich würde Plack lehren, das ist auf derselben Abstraktionsebene wie CGI.pm. Von dort aus steigt man leicht auf ein featurereiches Framework hoch.

        mit catalyst und dancer habe ich mich bisher nur oberflaechlich befasst, habe aber den eindruck, dass das nix fuer anfanger ist.

        Dancer schon.

        dann lieber cgi, weil man da wenigstens noch ansatzweise die (vermutlich vertraute) html-struktur erkennt.

        *verwirrt* Das ist ein komplett orthogonales Thema.

        1. gudn tach!

          wie wuerdest du vorgehen?
          Ich würde Plack lehren, das ist auf derselben Abstraktionsebene wie CGI.pm. Von dort aus steigt man leicht auf ein featurereiches Framework hoch.

          ah, ok, muesste ich mir mal naeher anschauen.

          dann lieber cgi, weil man da wenigstens noch ansatzweise die (vermutlich vertraute) html-struktur erkennt.
          *verwirrt* Das ist ein komplett orthogonales Thema.

          mir geht's um die (also um alle) perl-beispiele in selfhtml. aber nach der antwort von Matthias bin ich nun wieder am ueberlegen, ob man dieses beiwerk vielleicht tatsaechlich in den normalen beispielen weglassen sollte und stattdessen den-webkram in einem separaten artikel erklaert.

          prost
          seth

  4. Moin,
    dass sich in einem Feld bereits UTF-8-Daten befinden und probiere schon eine Weile daran herum, eine Doppelkodierung zu vermeiden.

    Wenn Dir das Feld bekannt ist, was hindert Dich daran nur die "falsch" kodierten Felder zu bearbeiten?

    Fred

  5. hi,

    Der letzte Ansatz scheint mir eigentlich logisch, die Frage wäre aber: Welches Format haben eigentlich Daten zunächst, die in ein per CGI so
    $cgi->header(-charset => 'UTF-8'),
    $cgi->start_html(-encoding => 'UTF-8'),
    $cgi->start_form(-method => 'post',
    generiertes Formular eingegeben werden?

    Das Form wird mit einem HTTP-Header "Content-type: text/html; charset=UTF-8" ausgeliefert. Sofern der Benutzer vor dem Submit die Kodierung nicht ändert:

    Du bekommst UTF-8-Oktetten (bytesemantic, raw).

    Mit

      
    use CGI qw(-utf8);  
    
    

    Du bekommst UTF-8-kodierte Zeichenketten (charactersemantic).

    Wenn Du UTF-8-Zeichen wieder ausgeben willst, auf STDOUT oder FileHandler, dürfen das keine UTF-8-kodierte Zeichenketten sein, sondern müssen UTF-8-Oktetten sein.

    Perl unterscheidet das seit v5.6 (anno domini 2001).

    Hotti

    1. Mit

      use CGI qw(-utf8);

      Du bekommst UTF-8-kodierte Zeichenketten (charactersemantic).

      Schäm dich! Das ist schlechter Rat ohne Nennung der Doku und Warnung über die Nebenwirkungen. Zaphod wird sich schön ärgern, dass du ihm die Uploads kaputtgemacht hast.

      Es ist vorziehen, Textfelder manuell zu dekodieren (Codebeispiel).

      1. hi,

        Schäm dich! Das ist schlechter Rat ohne Nennung der Doku

        Hab ich ihm schon mal an einer anderen Stelle verlinkt, Du liest doch hier mit oder???

        und Warnung über die Nebenwirkungen. Zaphod wird sich schön ärgern, dass du ihm die Uploads kaputtgemacht hast.

        Er wird sicher selbst lesen können, was da steht.

        Es ist vorziehen, Textfelder manuell zu dekodieren (Codebeispiel).

        Ja und? Es gibt mehrere Möglichkeiten, die habe ich auch aufgeschrieben.

        Btw. deine Empfehlung:
        »» use CGI qw();

        Da kannst Du auch

        require CGI;

        notieren.

        Hotti