HP-User: Ausgabereihenfolge / Laut gedacht...

Hallo Leute

Zunächst möchte ich einen Teilerfolg melden. Die Lesefunktion geht schon mal.
Kleiner Schönheitsfehler: Die neuesten Gästebuchnachrichten stehen ganz unten, statt obendrauf!

So:
Schreibtechnisch möchte ich nichts ändern. Ich öffne die Datei für anhängenden Schreibzugriff und das funktioniert auch. Beim Auslesen müsste ich allerdings etwas tricksen.

Meine Idee:
Ich lese aus und packe die Daten in ein Array.Dann müsste ich *überleg* die ältesten Daten unten im Arraytopf haben, und die neuesten oben im Array. Wenn ich jetzt das Array auslese, kommt doch dann der neueste Datensatz zuerst heraus? Oder schöpft das Perl das Array wieder von unten ab?

Wie gesagt - nur mal laut gedacht...

Zum testen:

http://www.einschlafzeit.de/gaestebuch.html

Dort mal was schreiben und lesen, da sieht man, dass er es unten anfügt.

  1. Dann müsste ich *überleg* die ältesten Daten unten im Arraytopf haben, und die neuesten oben im Array.

    Wenn du sie so reinliest, ja. Wenn du sie anders rum sortiert da reinliest, nein.

    Wenn ich jetzt das Array auslese, kommt doch dann der neueste Datensatz zuerst heraus?

    Wenn du es von vorne her ausliest, hast du das erste zuerst.

    Merkst du was? Das kommt doch auf deinen Code an.
    Perl macht da gar nichts von selbst. Mit einer foreach Schleife wird die Reihenfolge erstes-bis-letztes eingehalten. Aber ob du die verwendest und wie du die Daten aus der DB ausliest (ORDER BY) und da rein steckst, ist doch nur von deinem sonstigen Code abhängig.

    Mein Tip: mach es so wie du es haben willst, dann tut es das was es soll :-)
    klingt zwar erst mal ziemlich blöd, aber vielleicht machts ja klick?

    1. Hi Encoder

      Jetzt wird es doch noch knifflig...

      Dieser Code scheint soweit zu funktionieren:

      --------------------------------------------------------------------------

      open(LESER, "<coresys/message.csv") or die "ERROR: Unable to open the Message-file during read-access!";  
      flock(LESER, LOCK_SH);  
        
      my @Collector;  
      my $counter = 0;  
        
      while(! eof(LESER)){  
      my $zeile = <LESER>;  
      my ($DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden) = split(/;/,$zeile);  
        
      $counter = ($counter + 1);  
        
      push (@Collector, $counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden);  
      }  
        
      close(LESER);
      

      --------------------------------------------------------------------------

      Ich gehe also davon aus, dass das Array "@Collector" ordnungsgemäß befüllt wurde. Auch wenn ich hier zusätzlich den Skalar "$counter" hineingequetscht habe.

      Das Herausholen des Arrayinhaltes "@Collector" will aber nicht klappen. Ich habe dies so versucht:

      --------------------------------------------------------------------------

      foreach $counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden (@Collector) {  
        
      print <<"ENDE";  
      <div class="buch_eintrag">  
      <p class="textvariante_c">($counter) Name: $DB_nick [Datum: $DB_Monatstag.$DB_Monat.$DB_Jahr / $DB_Stunden:$DB_Minuten:$DB_Sekunden Uhr]  
      </p>  
      <p class="textvariante_d">$DB_nachricht.  
      </p>  
      </div>  
      ENDE  
        
      }
      

      --------------------------------------------------------------------------

      Vielleicht sieht einer einen Fehler, warum das Array nichts ausgeben will.

      Gruss HP-User

      1. Hallo Forum


        foreach $counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden (@Collector) {

        print <<"ENDE";
        <div class="buch_eintrag">
        <p class="textvariante_c">($counter) Name: $DB_nick [Datum: $DB_Monatstag.$DB_Monat.$DB_Jahr / $DB_Stunden:$DB_Minuten:$DB_Sekunden Uhr]
        </p>
        <p class="textvariante_d">$DB_nachricht.
        </p>
        </div>
        ENDE

        }

        
        > --------------------------------------------------------------------------  
          
        Soweit ich das jetzt nachgelesen habe geht "foreach" nur für einen Skalar...  
        Und es scheint so, dass die Skalare im Array wohl als Skalare abgelegt sind, ohne trennendes Komma oder ähnlich. Also ist auch ein "Splitting" dieser Art erfolglos:  
          
        `my ($counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden) = split(@Collector);`{:.language-perl}  
          
        Laut selfhtml soll man mit einem Skalar der gleich heisst, wie das Array , über die "eckige Klammer" auf einzelne Positionen zugereifen können:  
          
        Also @Collector wäre über $Collector[1] der zweite Skalar im Array.  
          
        Gelesen hier:  
          
        <http://de.selfhtml.org/perl/sprache/listen.htm#funktionen_operationen>  
          
        Also ganz steig ich da noch nicht durch. Die Frage muss sein:  
        Wie hole ich mir eine Liste/Reihe/Datensatz von Skalaren aus dem Array -> also Zeilenweise?  
          
        Gruß HP-User
        
        1. Hallo Leute

          Hab die Lösung. Thema erledigt. Abhilfe verschaffte "unshift".

          Gruss HP-User

          1. hi,

            falls Du viel mit CSV-Dateien machst, zum Einen gibts es das Modul Text::CSV und zum Anderen ists oft besser, mit namentlichen Feldern zu arbeiten.

            Name;Vorname;Str;PLZ;Ort

            wird gesplittet, Du bekommst eine Liste qw(Name Vorname Str PLZ Ort), das wären die Feldnamen (z.B. aus der ersten Zeile der CSV-Datei).

            Mit einem Hash-Slice über einen Helper-Hash bekommst Du die Werte, je Zeile ein Hash:

              
            # Schleifenkörper über die Zeilen einer CSV-Datei  
            my %hh = (); # Helper Hash  
            @hh{qw(Name Vorname Str PLZ Ort)} = split ";",  
              Haselhuhn;Horst;Clausstraße;54321;Karl-Marx-Stadt; # Zeile  
            
            

            und dieser Hash je Zeile wird auf ein Array gepusht als Referenz:

              
            push @kladde, \%hh;  
            
            

            Beim Ausgeben ist der Zugriff ganz einfach per Name möglich aus der Referenz heraus, jedes Array-Element ist eine $ref:

            my $name = $ref->{'Name'};

            Des Weiteren kann damit auch über ein beliebiges Feld sortiert werden, z.B. über den 'Ort':

              
            foreach my $ref( sort {$a->{'Ort'} cmp $b->{'Ort'} } @kladde) {}  
            
            

            Machs Beste draus ;)

            Hotti

            1. Hi hotti

              Mit einem Hash-Slice über einen Helper-Hash bekommst Du die Werte, je Zeile ein Hash:

              Ihr mit eurem ewigem Hasch... Ich kiffe nicht...

              scnr. HP-User

      2. Dein Code ist grauenhaft. Ich male mir aus, wenn der Rest so aussieht wie der Ausschnitt, ist die Wahrscheinlichkeit groß, dass du datenintegritäts- und sicherheitskritische Fehler eingebaut hast. Ich empfehle mal eine automatische Analyse mit perlcritic (gleich online ausprobieren) auf der behutsamsten Stufe.

        Wenn dir an einer professionellen Kritik gelegen ist, die auf die Fehler eingeht und besseres Design erörtert, zeige bitte den ganzen Code.

        1. Hi CPAN

          Dein Code ist grauenhaft. Ich male mir aus, wenn der Rest [...

          So grauenhaft kann er gar nicht sein - dafür ist er viel zu kurz ;-)

          Wenn dir an einer professionellen Kritik gelegen ist, die auf die Fehler eingeht und besseres Design erörtert, zeige bitte den ganzen Code.

          Kann ich machen, allerdings erst heute Abend - bin auf Arbeit in der Mittagspause - da komm ich jetzt nicht ran.

          Aber dann müsste ich dir den auf einer anderen Perlforumseite zeigen. Dieses andere Forum hat einen Bereich, der nicht archiviert wird. Dort wär es möglich. Ich möchte nämlich nicht, dass mein Code bis zum St. Nimmerleinstag im Selfarchiv verfügbar ist.

          Gruss und Dank

          HP-User

          PS.:Du wirst sehen, dass alles wunderbar mit "#" angeschrieben ist, und jeder ohne Probleme den Code lesen kann. So grauenhaft ist das nicht!

          Ausserden finde ich es nicht schlimm, wenn ich noch die alten Filehandle benutze. So bleibt die Seite wenigstens "Abwärtskompatibel" *lol*

          1. Hi CPAN

            Ich poste es mal trotzdem hierher, hab die privaten Stellen unkenntlich gemacht:

              
            #!/usr/bin/perl -w  
              
            ###############################################################################  
            # guest-reader.pl:                 Version 1.00                               #  
            # Developed started in:            02.08.2012                                 #  
            # Finished in:                     03.08.2012                                 #  
            # Programmed by:                   XXXXXXXXXXXXXXX                            #  
            ###############################################################################  
              
            use strict;  
            use warnings;  
            use Fcntl ':flock';  
            use CGI -no_xhtml;  
            use CGI::Carp qw(fatalsToBrowser warningsToBrowser);  
            use Encode;  
              
            ######################################  
            # Extra-Skalar-Group (ESG) / Skalare #  
            ######################################  
              
            my $DB_nick;  
            my $DB_nachricht;  
            my $DB_zaehler;  
            my $DB_gbrgelesen;  
            my $DB_IPAdresse;  
            my $DB_Monatstag;  
            my $DB_Monat;  
            my $DB_Jahr;  
            my $DB_Stunden;  
            my $DB_Minuten;  
            my $DB_Sekunden;  
              
            ##################  
            # Html-Protokoll #  
            ##################  
              
            print CGI->header('text/html');  
              
            ##################################  
            # Read-Out-Engine / Buchausleser #  
            ##################################  
              
            open(LESER, "<XXXXXXX/XXXXXXX.csv") or die "ERROR: Unable to open the Message-file during read-access!";  
            flock(LESER, LOCK_SH);  
              
            my @Collector;  
            my $counter = 0;  
              
            while(! eof(LESER)){  
            my $zeile = <LESER>;  
            my ($DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden) = split(/;/,$zeile);  
              
            $counter = ($counter + 1);  
              
            unshift (@Collector, $counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden);  
            }  
              
            close(LESER);  
              
            foreach ( my $i=0; $i<@Collector; $i+=12) {  
              my ($counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden)=@Collector[ $i .. $i+11 ];  
              
              print <<"ENDE";  
            <div class="buch_eintrag">  
            <p class="textvariante_c">($counter) Name: $DB_nick [Datum: $DB_Monatstag.$DB_Monat.$DB_Jahr / $DB_Stunden:$DB_Minuten:$DB_Sekunden Uhr]  
            </p>  
            <p class="textvariante_d">$DB_nachricht.  
            </p>  
            </div>  
            ENDE  
            }  
              
            print <<"ENDE";  
            </div>  
              
            <img id="absatz_bild" border="0" src="reading_book.png" width="500" height="262" alt="Buchleser">  
              
            </div>  
              
            </body>  
            </html>  
            ENDE  
            exit;  
            
            

            Und nun dein Urteil?

            Hinweise: Die "komischen" Skalarnamen stammen aus dem guest-writer-Program. Falls du meinst es wäre nicht optimal strukturiert: Das liegt daran, dass das Script über SSI eine vorhandene Html-Seite ergänzt, und diese Ergänzung halt genau an dieser Stelle zu stehen hat. Sonst stimmt der Ausgabecode nicht. Ich seh auch gerade das ModulEncode im Kopf, dass für das Lesescript eigentlich überflüssig ist. Es steht da, weil das im guest-writer-Program benötigt wurde. Da ich das writer-Prog zuerst geschrieben habe, hab ich den Kopf halt übernommen.

            An einer Stelle hatte ich externe Hilfe, und verstehe besonders die "[]"-Eckklammern am ende nicht:

              
            foreach ( my $i=0; $i<@Collector; $i+=12) {  
              my ($counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden)=@Collector[ $i .. $i+11 ];  
            
            

            Da wär ich um ne Erklärung froh. Den Rest versteh ich, da selbst entwickelt, soweit.

            Gruss HP-User

            1. Ich vermutete datenintegritäts- und sicherheitskritische Fehler. Diese sind tatsächlich vorhanden. Wenn ein Feldinhalt (z.B. "Nachricht") ein Semikolon enthält, verrutschen die Inhalte und werden nicht mehr den korrekten Variablen zugeordnet, die Ausgabe wird ruiniert. Inhalte werden vor der Ausgabe nicht kodiert, so dass ein Angreifer beliebigen schadhaften Code einschleusen kann. Dies ist ernst und gehört dringend verbessert! Ich spare mir die Details, bei der kompletten Überarbeitung bleibt nichts mehr vom fehlerhaften übrig.

              Nun zum Design auf hoher Abstraktion: du benutzt keine bewährten Methoden und Mittel, um deine Ziele umzusetzen, vermutlich aus Unkenntnis, dass es sie gibt (nämlich: Datenbanken und Vorlagen). Dadurch wird dein Code unnötig lang und fehleranfällig, da du besagte Methoden und Mittel selber schlecht umsetzt, statt auf vorhandenen Code zurückzugreifen.

              Es folgt Designkritik zu konkreten Punkten:

              #!/usr/bin/perl -w

              Dieser Schalter ist überholt. Du benutzt bereits den Ersatz, das lexikalische Pragma warnings. Entferne den Schalter!

              Du schreibst ein CGI-Programm, es führt also Code im Auftrag anderer Leute (also der Benutzer deines Webangebots) aus. Schalte Taintchecks mittels -T ein!

              ###############################################################################

              Solche Verzierungen taugen als Illuminierung mittelalterlicher Manuskripte, gehören aber nicht in den Quellcode. Entferne sie! Wenn du Unterteilung von logischen Codeeinheiten sichtbar machen möchtest, benutze Subroutinen und rücke sie ein!

              guest-reader.pl:                 Version 1.00

              Dieses Metadatum gehört nicht in einen Programmiererkommentar. Benutze die reservierte Packagevariable $VERSION!

              our $VERSION = '1.00';

              Developed started in:            02.08.2012

              Finished in:                     03.08.2012

              Das gehört nicht in den Code. Dein Versionskontrollsystem gibt bereits Aufschluss über diese Daten. Entferne sie!

              Programmed by:                   XXXXXXXXXXXXXXX

              Dieses Metadatum gehört nicht in einen Programmiererkommentar, sondern in die Dokumentation. Benutze den dafür in Pod vorgesehenen Absatz!

              Extra-Skalar-Group (ESG) / Skalare

              So was gibt es nicht. Hier fehlt Dokumentation zum Verständnis!

              my $DB_nick;
              my $DB_nachricht;
              my $DB_zaehler;
              my $DB_gbrgelesen;
              my $DB_IPAdresse;
              my $DB_Monatstag;
              my $DB_Monat;
              my $DB_Jahr;
              my $DB_Stunden;
              my $DB_Minuten;
              my $DB_Sekunden;

              Du hast mehrere Skalarvariablen, deren Namen mit dem gleichen Präfix anfangen. Das sollte immer ein Warnsignal sein, dass hier besser eine Verbundvariable taugen würde. Aggregiere deine Datenfelder in einem Hash!

              Auch hat Deutsch nichts in Programmen verloren. Schreibe den Code, insbesondere die Bezeichner, auf englisch!

              Html-Protokoll

              So etwas gibt es nicht. CGI implementiert das Protokoll HTTP. Das ist allgemein bekannt, lasse das weg!

              print CGI->header('text/html');

              Die Zeichenkodierung fehlt. Die empfohlene Kodierung für das Web ist UTF-8. Halte deine Daten UTF-8 vor und gebe sie so kodiert aus!

              Read-Out-Engine / Buchausleser

              Hier gibt es keine Engine. Das Wort hat eine spezielle Bedeutung, nicht jeder Code ist eine Engine. Ersetze den Kommentar mit einer benannten Subroutine!

              open(LESER, "<XXXXXXX/XXXXXXX.csv") or die "ERROR: Unable to open the Message-file during read-access!";

              Das ist unidiomatisch. Verwende immer die Drei-Argumente-Variante von open! Verwende lexikalische Dateihandles! Die Fehlernachricht sagt nicht, warum das Öffnen fehlschlägt. Überlasse autodie die Fehlerprüfung und Erzeugung der Fehlernachricht!

              use autodie qw(:all);
                  open my $messages, '<', 'XXXXXXX/XXXXXXX.csv';

              while(! eof(LESER)){
              my $zeile = <LESER>;

              Das ist unidiomatisch. Iteriere einfach bis zur Abbruchbedingung, dass readline mangels Eingabe fehlschlägt!

              while (my $line = <$messages>) {

              my ($DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden) = split(/;/,$zeile);

              Dies gibt vor, ein CSV-Parser zu sein. Es funktioniert aber nicht, weil er Escapingregeln missachtet. Benutze einen korrekten Parser, z.B. Text::CSV!

              Mit dem späteren Code wird klar, dass die Daten in tabellarischer Form vorliegen. Das bewährte Mittel zur Datenwiedergabe ist eine ACID-konforme Datenbank. Verzichte auf CSV/manuelles Locking und überlasse das dem DBMS!

              $counter = ($counter + 1);

              Das ist unidiomatisch. Benutze den Inkrementoperator!

              $counter++;

              unshift (@Collector, $counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden);

              Es ist eine enorme Speicherverschwendung, erst alle Daten in eine riesige Datenstruktur einzusammeln und dann darüber zu iterieren, um die Ausgabe zu befüllen. Ab einer gewissen Menge von Daten wird dieses Programm nicht mehr funktionieren, die Experten sprechen davon, dass es nicht skaliert. Stattdessen befülle die Ausgabe stückchenweise mit jeweils nur einem Datensatz auf einmal!

              foreach ( my $i=0; $i<@Collector; $i+=12) {
              my ($counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden)=@Collector[ $i .. $i+11 ];

              Es befindet sich hier magische Zahlen. Benutze Konstanten! Wenn du dein Datenschema änderst, z.B. eine neue Spalte hinzufügst, so braucht nur die Konstante angepasst werden.

              exit;

              Das ist überflüssig.

              ━━━━━━━━━━━━

              Es folgt nun das verbesserte Programm unter Einhaltung der derzeit als bewährt erachteten Methoden und Mittel. Ein Großteil der vorher genannten Ratschläge ist hiermit hinfällig.

                
              use utf8;  
              use strictures;  
              use CGI qw();  
              use DateTime::Format::RFC3339 qw();  
              use DBIx::Class::Schema::Loader qw();  
              use Template qw();  
                
              my $c = CGI->new;  
              print $c->header('text/html; charset=UTF-8');  
              my $d = DateTime::Format::RFC3339->new;  
              my $t = Template->new;  
              my $template = \<<'TEMPLATE';  
              <div class="buch_eintrag">  
              <p class="textvariante_c">([% e.counter %]) Name: [% e.nickname|html %] [Datum: [% e.posted.dmy('.') %] / [% e.posted.hms(':') %] Uhr]  
              </p>  
              <p class="textvariante_d">[% e.message|html %].  
              </p>  
              </div>  
              TEMPLATE  
                
              DBIx::Class::Schema::Loader->naming('current');  
              my $gb = DBIx::Class::Schema::Loader->connect->resultset('Guestbook')->search({}, {order_by => {-desc => 'counter'}});  
              while (my $entry = $gb->next) {  
                  $entry->posted($d->parse_datetime($entry->posted));  
                  $t->process($template, { e => $entry });  
              }  
                
              print <<'FOOTER';  
              </div>  
              <img id="absatz_bild" border="0" src="reading_book.png" width="500" height="262" alt="Buchleser">  
              </div>  
              </body>  
              </html>  
              FOOTER  
                
              __END__  
                
              =encoding UTF-8  
                
              =head1 NAME  
                
              guest-reader.pl - display guestbook and page footer  
                
              =head1 DESCRIPTION  
                
              Displays guestbook entries in reverse order. Displays the HTML page footer.  
                
              =head2 Database schema  
                
                  create table guestbook (  
                      counter serial primary key,  
                      nickname text not null,  
                      message text not null,  
                      gbr_read boolean not null default 'true',  
                      ip_address inet not null,  
                      posted timestamp with time zone not null  
                  );  
                
              =head1 ENVIRONMENT  
                
              Requires the DSN to be set in order to connect to the database. See  
              L<DBI/DBI ENVIRONMENT VARIABLES>.  
                
              =head1 AUTHOR  
                
              XXXXXXXXXXXXXXX  
              
              

              ━━━━━━━━━━━━

              es wäre nicht optimal strukturiert

              Du halst dir mit SSI Ärger auf, die gesamte Struktur leidet darunter. Statt HTML seriell zusammenzustückeln, arbeite mit transkludierten Vorlagen! Moderne Webframeworks haben die Technologien SSI und CGI längst abgelöst. Du hast nur einen Teil deines Webangebots hergezeigt, und ich kann nur das verbessern, was ich sehe.

              verstehe besonders die "[]"-Eckklammern am ende nicht

              Es ist ein Arrayslice über die Indizes $i bis $i plus 11.

              1. Abend CPAN

                Ich vermutete datenintegritäts- und sicherheitskritische Fehler. Diese sind tatsächlich vorhanden. Wenn ein Feldinhalt (z.B. "Nachricht") ein Semikolon enthält, verrutschen die Inhalte und werden nicht mehr den korrekten Variablen zugeordnet, die Ausgabe wird ruiniert. Inhalte werden vor der Ausgabe nicht kodiert, so dass ein Angreifer beliebigen schadhaften Code einschleusen kann. Dies ist ernst und gehört dringend verbessert! Ich spare mir die Details, bei der kompletten Überarbeitung bleibt nichts mehr vom fehlerhaften übrig.

                Sorry, das ist absoluter quatsch! Du siehst ja nur den "Reader", und der liest bekanntlich, und schreibt nichts in die csv! Der "Writer" ist sehr sicher. Und da nur der "Writer"in die csv-Datei schreiben darf, brauche ich beim "Reader" keine Semikolons fürchten. Semikolons werden in Gatterzeichen umcodiert. Und beim auslesen wird aus dem Gatterzeichen wieder ein Semikolon. Eine Zeile hat sich kurz nach dem posten des reader-Codes geändert:

                $DB_nachricht =~ s/#/;/g;

                Die war glaub oben noch nicht drin!

                Nun zum Design auf hoher Abstraktion: du benutzt keine bewährten Methoden und Mittel, um deine Ziele umzusetzen, vermutlich aus Unkenntnis, dass es sie gibt (nämlich: Datenbanken und Vorlagen). Dadurch wird dein Code unnötig lang und fehleranfällig, da du besagte Methoden und Mittel selber schlecht umsetzt, statt auf vorhandenen Code zurückzugreifen.

                Das ist Absicht. Ich will kein TEXT::CSV oder DBD::CSV. Sondern nur selbstgemachtes!

                Es folgt Designkritik zu konkreten Punkten:

                #!/usr/bin/perl -w

                Dieser Schalter ist überholt. Du benutzt bereits den Ersatz, das lexikalische Pragma warnings. Entferne den Schalter!

                Dieser Schalter wird von mir, ich schätze mal sicher schon die letzten 5 Jahre, benutzt. Ohne das es Anlass zur Sorge gegeben hätte.

                Du schreibst ein CGI-Programm, es führt also Code im Auftrag anderer Leute (also der Benutzer deines Webangebots) aus. Schalte Taintchecks mittels -T ein!

                Das kenne ich nicht -> muss nachlesen, für was das ist.

                ###############################################################################

                Solche Verzierungen taugen als Illuminierung mittelalterlicher Manuskripte, gehören aber nicht in den Quellcode. Entferne sie! Wenn du Unterteilung von logischen Codeeinheiten sichtbar machen möchtest, benutze Subroutinen und rücke sie ein!

                Ich steh total auf solche Hinweise im Code. Wenn ich ein Jahr später was ändern muss, weiss ich gleich, um was es im nächsten Block geht.

                guest-reader.pl:                 Version 1.00

                Dieses Metadatum gehört nicht in einen Programmiererkommentar. Benutze die reservierte Packagevariable $VERSION!

                our $VERSION = '1.00';

                Developed started in:            02.08.2012

                Finished in:                     03.08.2012

                Das gehört nicht in den Code. Dein Versionskontrollsystem gibt bereits Aufschluss über diese Daten. Entferne sie!

                Da bin ich anderer Meinung *g*. Das wer, wie und wann gehört in den Code! A) Wie willst du später beweisen, wenn einer deinen Code kopiert und nutzt, das es dein Code ist? Es gibt ja Blindkopierer ohne Codeahnung. B)Wenn sich einer später den Code anguckt, sieht er gleich, wer der Vater des Codes war. Beim C64 kamm das auch immer in den Code!

                Programmed by:                   XXXXXXXXXXXXXXX

                Dieses Metadatum gehört nicht in einen Programmiererkommentar, sondern in die Dokumentation. Benutze den dafür in Pod vorgesehenen Absatz!

                Die Doku liest eh keiner ;-)
                Aber zur Beruhigung: Ist alles auf Papier ausgedruckt und nochmal auf CD gebrannt - inklusive Anleitung - Ja, da bin ich ganz akurat.

                Extra-Skalar-Group (ESG) / Skalare

                So was gibt es nicht. Hier fehlt Dokumentation zum Verständnis!

                Da hast du recht. Das ist, weil im Writer-Program diese Skalare extra für die Speicherung benötigt wurden. Und weil Porgammierer faul sind, hab ich die grad so übernommen.

                Du hast mehrere Skalarvariablen, deren Namen mit dem gleichen Präfix anfangen.

                Klar, DB-steht für _D_aten_B_ank (Skalar) Einer meiner bewährten Methoden um zu wissen woher der Inhalt ist.

                Das sollte immer ein Warnsignal sein, dass hier besser eine Verbundvariable taugen würde. Aggregiere deine Datenfelder in einem Hash!

                Das mir dem Hash haben schon mehrere gesagt. Leider kenne ich die nicht, und der Umgang mit Ihnen (Hash) ist mir unbekannt ->muss das wanwenden, das ich kenne.

                Auch hat Deutsch nichts in Programmen verloren. Schreibe den Code, insbesondere die Bezeichner, auf englisch!

                Das Prigramm ist für Deutschland, Österreich und Schweiz(D-CH). Da kann der Inhalt auch ruhig deutsch sein. Bei Internationalen Projekten pflichte ich dir aber bei.

                print CGI->header('text/html');

                Die Zeichenkodierung fehlt. Die empfohlene Kodierung für das Web ist UTF-8. Halte deine Daten UTF-8 vor und gebe sie so kodiert aus!

                Das ist doch schon passiert. Das Script ergänzt nur die Html-Seite.

                Read-Out-Engine / Buchausleser

                Hier gibt es keine Engine. Das Wort hat eine spezielle Bedeutung, nicht jeder Code ist eine Engine. Ersetze den Kommentar mit einer benannten Subroutine!

                Das ist der Hinweis für mich, dass jetzt der Teil im Programm folgt, der die Daten holt. Dieser Teil verrichtet arbeit ->Read-Out-Engine

                open(LESER, "<XXXXXXX/XXXXXXX.csv") or die "ERROR: Unable to open the Message-file during read-access!";

                Das ist unidiomatisch. Verwende immer die Drei-Argumente-Variante von open! Verwende lexikalische Dateihandles! Die Fehlernachricht sagt nicht, warum das Öffnen fehlschlägt. Überlasse autodie die Fehlerprüfung und Erzeugung der Fehlernachricht!

                my ($DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden) = split(/;/,$zeile);

                Dies gibt vor, ein CSV-Parser zu sein. Es funktioniert aber nicht, weil er Escapingregeln missachtet. Benutze einen korrekten Parser, z.B. Text::CSV!

                Das gibt nicht vor irgendwas zu sein. Es ist einfach ein Stück Code, dass Daten holt und ausgibt. Und das war einene heiden Arbeit, bis das syntaktisch fehlerfrei lief.

                $counter = ($counter + 1);

                Das ist unidiomatisch. Benutze den Inkrementoperator!

                $counter++;

                Deines ist kürzer, meines menschlicher - und letzterer muss den Code bearbeiten.

                unshift (@Collector, $counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden);

                Es ist eine enorme Speicherverschwendung, erst alle Daten in eine riesige Datenstruktur einzusammeln und dann darüber zu iterieren, um die Ausgabe zu befüllen. Ab einer gewissen Menge von Daten wird dieses Programm nicht mehr funktionieren, die Experten sprechen davon, dass es nicht skaliert. Stattdessen befülle die Ausgabe stückchenweise mit jeweils nur einem Datensatz auf einmal!

                Hier hab ich lange überlegt, ob ich einen Satz bearbeite, dann Html ausgebe und dann denn nächsten bearbeite. Da ich denke, das es besser ist, wenn perl die Html-Daten in einem rutsch ausgibt, hab ich zuerst alle daten bearbeitet, und dann am stück ausgegeben. Für ein Gästebuch ausreichend. Für Firmen mit Artikelnummern, Lieferschein-Nummer, Auftrags-Nummern usw. ist der Bearbeitungsteil (aus Speichergründen) natürlich klein zu halten - Full ACK. Dann würd ich mich aber in DBD::CSV einarbeiten, weil dass wär mir dann zuviel.

                foreach ( my $i=0; $i<@Collector; $i+=12) {
                my ($counter, $DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden)=@Collector[ $i .. $i+11 ];

                Es befindet sich hier magische Zahlen. Benutze Konstanten! Wenn du dein Datenschema änderst, z.B. eine neue Spalte hinzufügst, so braucht nur die Konstante angepasst werden.

                exit;

                Das ist überflüssig.

                Dachte ich schon - ich habs zur Sicherhet platziert *schande über mein Haupt*

                Es folgt nun das verbesserte Programm unter Einhaltung der derzeit als bewährt erachteten Methoden und Mittel. Ein Großteil der vorher genannten Ratschläge ist hiermit hinfällig. [...]

                Das mag "stilistisch" besser sein - für mich aber in _weiten_ Teilen nicht mehr lesbar. -> Ich versteh dann mein eigenes Programm nicht mehr.

                es wäre nicht optimal strukturiert

                Du halst dir mit SSI Ärger auf, [...]

                SSI ist absolut genial. Ich möchte darauf nie mehr verzichten müssen. Geschmaksache!

                Puh...

                Soweit bis hierher

                Gruss HP-User

                1. Hallo CPAN ;-)

                  
                  #!/usr/bin/perl -w
                  
                  ###############################################################################
                  # guest-writer.pl:                 Version 1.00                               #
                  # Developed started in:            01.08.2012                                 #
                  # Finished in:                     01.08.2012                                 #
                  # Programmed by:                   XXXXXXXXXXXXXXX                            #
                  ###############################################################################
                  
                  use strict;
                  use warnings;
                  use Fcntl ':flock';
                  use CGI -no_xhtml;
                  use CGI::Carp qw(fatalsToBrowser warningsToBrowser);
                  use Encode;
                  
                  ########################
                  # Parameter einsammeln #
                  ########################
                  
                  my $nick = CGI::param('nick');
                  my $nachricht = CGI::param('nachricht');
                  my $zaehler = CGI::param('zaehler');
                  my $gbrgelesen = CGI::param('gbrgelesen');
                  my $spamschutz = CGI::param('spamschutz');
                  my $comparator = CGI::param('comparator');
                  my $IPAdresse = $ENV {'REMOTE_ADDR'};
                  
                  ###############################################
                  # Cleanup-Input-Filter (CIF) / Umbruchbezogen #
                  ###############################################
                  
                  $nick =~ s/\015\012|\015|\012//g;
                  $nachricht =~ s/\015\012|\015|\012//g;
                  $zaehler =~ s/\015\012|\015|\012//g;
                  $gbrgelesen =~ s/\015\012|\015|\012//g;
                  $spamschutz =~ s/\015\012|\015|\012//g;
                  $comparator =~ s/\015\012|\015|\012//g;
                  
                  chomp($nick);
                  chomp($nachricht);
                  chomp($zaehler);
                  chomp($gbrgelesen);
                  chomp($spamschutz);
                  chomp($comparator);
                  
                  ###########################################
                  # Evil-Input-Filter (EIF) / Längenbezogen #
                  ###########################################
                  
                  my $utf8str = decode('utf-8', $nick);
                  my $size = length($utf8str);
                  if($size > 30){
                                 goto NamenUmfangError;
                                }
                  
                  my $utf8str = decode('utf-8', $nachricht);
                  my $size = length($utf8str);
                  if($size > 400){
                                  goto TextUmfangError;
                                 }
                  
                  my $utf8str = decode('utf-8', $zaehler);
                  my $size = length($utf8str);
                  if($size > 3){
                                goto AnzeigeUmfangError;
                               }
                  
                  my $utf8str = decode('utf-8', $gbrgelesen);
                  my $size = length($utf8str);
                  if($size > 2){
                                goto GBRUmfangError;
                               }
                  
                  my $utf8str = decode('utf-8', $spamschutz);
                  my $size = length($utf8str);
                  if($size > 7){
                                goto SpamUmfangError;
                               }
                  
                  my $utf8str = decode('utf-8', $comparator);
                  my $size = length($utf8str);
                  if($size > 20){
                                 goto VergleichUmfangError;
                                }
                  
                  ############################################
                  # Evil-Input-Filter (EIF) / Zeichenbezogen #
                  ############################################
                  
                  $nick =~ s/;//g;
                  $nick =~ s/<//g;
                  $nick =~ s/>//g;
                  $nick =~ s/\*//g;
                  $nick =~ s/|//g;
                  $nick =~ s/\[//g;
                  $nick =~ s/\]//g;
                  $nick =~ s/{//g;
                  $nick =~ s/}//g;
                  $nick =~ s/@//g;
                  $nick =~ s/&//g;
                  $nick =~ s/\\//g;
                  $nick =~ s/ //g;
                  
                  $nachricht =~ s/#//g;
                  $nachricht =~ s/;/#/g;
                  $nachricht =~ s/<//g;
                  $nachricht =~ s/>//g;
                  $nachricht =~ s/\*//g;
                  $nachricht =~ s/|//g;
                  $nachricht =~ s/\[//g;
                  $nachricht =~ s/\]//g;
                  $nachricht =~ s/{//g;
                  $nachricht =~ s/}//g;
                  $nachricht =~ s/@//g;
                  $nachricht =~ s/&//g;
                  $nachricht =~ s/\\//g;
                  
                  $zaehler =~ s/;//g;
                  $zaehler =~ s/<//g;
                  $zaehler =~ s/>//g;
                  $zaehler =~ s/\*//g;
                  $zaehler =~ s/|//g;
                  $zaehler =~ s/\[//g;
                  $zaehler =~ s/\]//g;
                  $zaehler =~ s/{//g;
                  $zaehler =~ s/}//g;
                  $zaehler =~ s/@//g;
                  $zaehler =~ s/&//g;
                  $zaehler =~ s/\\//g;
                  $zaehler =~ s/ //g;
                  
                  $gbrgelesen =~ s/;//g;
                  $gbrgelesen =~ s/<//g;
                  $gbrgelesen =~ s/>//g;
                  $gbrgelesen =~ s/\*//g;
                  $gbrgelesen =~ s/|//g;
                  $gbrgelesen =~ s/\[//g;
                  $gbrgelesen =~ s/\]//g;
                  $gbrgelesen =~ s/{//g;
                  $gbrgelesen =~ s/}//g;
                  $gbrgelesen =~ s/@//g;
                  $gbrgelesen =~ s/&//g;
                  $gbrgelesen =~ s/\\//g;
                  $gbrgelesen =~ s/ //g;
                  
                  $spamschutz =~ s/;//g;
                  $spamschutz =~ s/<//g;
                  $spamschutz =~ s/>//g;
                  $spamschutz =~ s/\*//g;
                  $spamschutz =~ s/|//g;
                  $spamschutz =~ s/\[//g;
                  $spamschutz =~ s/\]//g;
                  $spamschutz =~ s/{//g;
                  $spamschutz =~ s/}//g;
                  $spamschutz =~ s/@//g;
                  $spamschutz =~ s/&//g;
                  $spamschutz =~ s/\\//g;
                  $spamschutz =~ s/ //g;
                  
                  $comparator =~ s/;//g;
                  $comparator =~ s/<//g;
                  $comparator =~ s/>//g;
                  $comparator =~ s/\*//g;
                  $comparator =~ s/|//g;
                  $comparator =~ s/\[//g;
                  $comparator =~ s/\]//g;
                  $comparator =~ s/{//g;
                  $comparator =~ s/}//g;
                  $comparator =~ s/@//g;
                  $comparator =~ s/&//g;
                  $comparator =~ s/\\//g;
                  $comparator =~ s/ //g;
                  
                  ######################################
                  # Extra-Skalar-Group (ESG) / Skalare #
                  ######################################
                  
                  my $sesamkey;
                  my $masterkey;
                  my $DB_nick;
                  my $DB_nachricht;
                  my $DB_zaehler;
                  my $DB_gbrgelesen;
                  my $DB_IPAdresse;
                  my $DB_Monatstag;
                  my $DB_Monat;
                  my $DB_Jahr;
                  my $DB_Stunden;
                  my $DB_Minuten;
                  my $DB_Sekunden;
                  
                  ############################################
                  # Date-And-Time (DAT) / Datum und  Uhrzeit #
                  ############################################
                  
                  my ($Sekunden, $Minuten, $Stunden, $Monatstag, $Monat,
                      $Jahr, $Wochentag, $Jahrestag, $Sommerzeit) = localtime(time);
                  my $CTIME_String = localtime(time);
                  $Monat+=1;
                  $Jahrestag+=1;
                  $Monat = $Monat < 10 ? $Monat = "0".$Monat : $Monat;
                  $Monatstag = $Monatstag < 10 ? $Monatstag = "0".$Monatstag : $Monatstag;
                  $Stunden = $Stunden < 10 ? $Stunden = "0".$Stunden : $Stunden;
                  $Minuten = $Minuten < 10 ? $Minuten = "0".$Minuten : $Minuten;
                  $Sekunden = $Sekunden < 10 ? $Sekunden = "0".$Sekunden : $Sekunden;
                  $Jahr+=1900;
                  
                  ###########################################
                  # Precise-Input-Check (PIC) / Nameninhalt #
                  ###########################################
                  
                  if ($nick =~ /EZ ?- ?Team/i) {
                                                goto NamenUmfangError;
                                               }
                  
                  if ($nick eq "") {
                                    goto NamenUmfangError;
                                   }
                  
                  if ($nick eq "XXXXXXXXXXXX") {
                                                $nick = "EZ-Team";
                                               }
                  
                  ####################################
                  # Precise-Input-Check (PIC) / Text #
                  ####################################
                  
                  if ($nachricht eq "") {goto TextUmfangError;}
                  
                  #######################################
                  # Precise-Input-Check (PIC) / Anzeige #
                  #######################################
                  
                  my $zahlstatus = "N";
                  my $wertstatus = "N";
                  
                  if ($zaehler =~ /\d/) { $zahlstatus = "Y";}
                  if ($zaehler <= "400" ) { $wertstatus = "Y";}
                  if ($zahlstatus eq "Y" and $wertstatus eq "Y") {goto AnzeigeOK;}
                  goto AnzeigeUmfangError;
                  
                  AnzeigeOK:
                  
                  ################################################
                  # Precise-Input-Check (PIC) / Gaestebuchregeln #
                  ################################################
                  
                  if ($gbrgelesen ne "on") {goto GBRUmfangError;}
                  
                  ##########################################
                  # Precise-Input-Check (PIC) / Spamschutz #
                  ##########################################
                  $sesamkey = "";
                  
                  if ($comparator eq "Goldfisch") {
                                                   $sesamkey = "gold";
                                                  }
                  
                  if ($comparator eq "Grünfink") {
                                                  $sesamkey = "grün";
                                                 }
                  
                  if ($comparator eq "Rotbarsch") {
                                                   $sesamkey = "rot";
                                                  }
                  
                  if ($comparator eq "Braunbär") {
                                                  $sesamkey = "braun";
                                                 }
                  
                  if ($comparator eq "Blauwal") {
                                                   $sesamkey = "blau";
                                                  }
                  
                  if ($comparator eq "Silberreiher") {
                                                      $sesamkey = "silber";
                                                     }
                  
                  if ($comparator eq "Gelbkopfgecko") {
                                                       $sesamkey = "gelb";
                                                      }
                  
                  if ($comparator eq "Schwarzfußiltis") {
                                                         $sesamkey = "schwarz";
                                                        }
                  
                  if ($comparator eq "Weißkopfseeadler") {
                                                          $sesamkey = "weiß";
                                                         }
                  if ($sesamkey eq "") {
                                        goto SpamUmfangError;
                                       }
                  
                  if ($spamschutz ne $sesamkey) {
                                                 goto SpamUmfangError;
                                                }
                  
                  ####################################################
                  ####################################################
                  ## Point-Of-Released-Input (PORI) / Wertefreigabe ##
                  ####################################################
                  ####################################################
                  
                  #################################################
                  # Multi-Post-Blocker (MPB) / Mehrfachpostsperre #
                  #################################################
                  
                  open(FILEMASTER, "<XXXXXXXXXX.csv") or die "ERROR: Unable to open the Message-file during read-access!";
                  flock(FILEMASTER, LOCK_EX);
                  my $DeltaMinuten = "";
                  my $GlobalDB_Minuten = "";
                  
                  while(! eof(FILEMASTER)){
                  my $zeile = <FILEMASTER>;
                  my ($DB_nick, $DB_nachricht, $DB_zaehler, $DB_gbrgelesen, $DB_IPAdresse, $DB_Monatstag, $DB_Monat, $DB_Jahr, $DB_Stunden, $DB_Minuten, $DB_Sekunden) = split(/;/,$zeile);
                  $GlobalDB_Minuten = $DB_Minuten;
                  $DeltaMinuten = ($Minuten - $DB_Minuten);
                  if ($DB_IPAdresse eq $IPAdresse and $DB_Monatstag eq $Monatstag and $DB_Monat eq $Monat and $DB_Jahr eq $Jahr and $DB_Stunden eq $Stunden and $DeltaMinuten < 5) {
                  close(FILEMASTER);
                  goto TimeLock;
                  }
                  }
                  close(FILEMASTER);
                  
                  #############################################
                  # Data-Save-Engine (DSE) / Datenspeicherung #
                  #############################################
                  
                  open(FILEMASTER, "+>>XXXXXXXXXX.csv") or die "ERROR: Unable to open the Message-file during write-access!";
                  flock(FILEMASTER, LOCK_EX);
                  print FILEMASTER $nick,';',$nachricht,';',$zaehler,';',$gbrgelesen,';',$IPAdresse,';',$Monatstag,';',$Monat,';',$Jahr,';',$Stunden,';',$Minuten,';',$Sekunden,"\n";
                  close(FILEMASTER);
                  
                  ####################
                  # HTML-Textausgabe #
                  ####################
                  
                  print CGI->header('text/html');
                  
                  print <<"ENDE";
                  ENDE
                  exit;
                  
                  ###############################################
                  # Error-Block-Output (EBO) / NamenUmfangError #
                  ###############################################
                  
                  NamenUmfangError:
                  print CGI->header('text/html');
                  
                  print <<"ENDE";
                  ENDE
                  exit;
                  
                  ##############################################
                  # Error-Block-Output (EBO) / TextUmfangError #
                  ##############################################
                  
                  TextUmfangError:
                  print CGI->header('text/html');
                  
                  print <<"ENDE";
                  ENDE
                  exit;
                  
                  #################################################
                  # Error-Block-Output (EBO) / AnzeigeUmfangError #
                  #################################################
                  
                  AnzeigeUmfangError:
                  print CGI->header('text/html');
                  
                  print <<"ENDE";
                  ENDE
                  exit;
                  
                  #############################################
                  # Error-Block-Output (EBO) / GBRUmfangError #
                  #############################################
                  
                  GBRUmfangError:
                  print CGI->header('text/html');
                  
                  print <<"ENDE";
                  ENDE
                  exit;
                  
                  ##############################################
                  # Error-Block-Output (EBO) / SpamUmfangError #
                  ##############################################
                  
                  SpamUmfangError:
                  print CGI->header('text/html');
                  
                  print <<"ENDE";
                  ENDE
                  exit;
                  
                  #########################################
                  # Time-Lock-Security (TLS) / Zeitsperre #
                  #########################################
                  
                  TimeLock:
                  print CGI->header('text/html');
                  
                  print <<"ENDE";
                  ENDE
                  exit;
                  
                  ###################################################
                  # Error-Block-Output (EBO) / VergleichUmfangError #
                  ###################################################
                  
                  VergleichUmfangError:
                  print CGI->header('text/html');
                  
                  print <<"ENDE";
                  ENDE
                  exit;
                  
                  

                  Damit du mal den "Writer" siehst und sich deine Bedenken zerstreuen lassen...

                  Gruss HP-User

                  PS.: Du wirst das von Berufswegen machen, und wer 6000 € im Monat verdient, der muss halt schon noch ein bischen mehr können als ich. Für mich reicht das hier allemal - ich verdien ja auch keine 6000,- Klötze hehe

                  1. Das Programm ist so banane/kaputt, ich müsste einen halben Tag damit verbringen, es zu kritisieren. Die Zeit ist mir dafür zu schade, insbesonders weil du wenig Lernbereitschaft signalisierst, ich hab nicht die Lust, mich erneut runterputzen zu lassen.

                    Dass du schon 5 Jahre Perl programmierst, kannst du meiner Oma erzählen, die glaubt dir das vielleicht. Wenn du keine Hashes und Taintcheck kennst, dann benutzt du Perl eher erst 5 Wochen. Die Codequalität sieht so aus.

                    1. Abend CPAN

                      Das du es in Perl "drauf" hast, steht außer Frage. Das sieht man ja an deinen Antworten in diesem und in den zahlreichen anderen threads.

                      Das Programm ist so banane/kaputt, ich müsste einen halben Tag damit verbringen, es zu kritisieren.

                      1. Kaputt ist es nicht, da es fehlerfrei läuft.

                      2.Banane im Sinne von einfach? Ja, ist ja auch von einem "Normalsterblichem" geschrieben. Wo steht geschrieben, das Programme kompliziert sein müssen?

                      Die Zeit ist mir dafür zu schade,[...]

                      Dann lass es. Ich wollte nur mal das ganze Programm einstellen, um zu zeigen, dass es auch "alternative" Programmierstile gibt, die nicht besser, aber auch nicht schlechter sein müssen. Das Ergebnis zählt - es muss seine Aufgabe erfüllen.

                      ich hab nicht die Lust, mich erneut runterputzen zu lassen.

                      Das hingegen tut mir Leid, wenn eine meiner Antworten so herüber kam. *grosses Sorry*. Denn sowas ist nicht meine Absicht gewesen.

                      Falls du die Stelle mit dem "Das ist Quatsch" meinst: Da bin ich nach wie vor der Meinung, das man nicht aus einem Leser-Programm auf die Sicherheit der CSV schliessen kann, wenn man das Schreibprogramm nicht kennt. Und hier musst du ehrlicherweise zugeben, das ich den Input im Writer-Programm mehr als gründlich unter die Lupe genommen habe:

                      Umbruch Codes, Wagenrückläufe, Länge, Inhalt, Zeichen uvm wurden abgeklopft, damit ja nichts passiert.

                      Dass du schon 5 Jahre Perl programmierst, kannst du meiner Oma erzählen, die glaubt dir das vielleicht.

                      Das ist jetzt unschön :-(

                      Wenn du keine Hashes und Taintcheck kennst, dann benutzt du Perl eher erst 5 Wochen. Die Codequalität sieht so aus.

                      Wieso, wenn nich noch nie ein Hash gebraucht habe? Woher soll ich es dann kennen, geschweige denn vermissen? Ich war immerhin so kreativ, sämtliche Probleme auch ohne Hash zu lösen.

                      Über Taincheck hab ich mich mittlerweile informiert: Ist ein Resourcenfresser - unnötig und allerhöchstens für Testläufe geeignet. Man soll sich nicht darauf verlassen und lieber ordentlich den Input zu Fuss checken.

                      Nochmal, ich arbeite jeden Tag hart und hab nach Feierabend nur ein wenig Zeit zum Perlen. Ich hab kein IT-Studium oder ähnliches. Und für das autodidaktische Aneignen von Perlcode bin ich gut in der Lage, Aufgabenstellungen programmtechnisch funktionsfähig umzusetzen. Perl soll Spass machen - es ist ein Hobby von mir. Mehr nicht. Und jedesmal, wenn ein Script läuft, freu ich mich...

                      Gruss HP-User