schmaidt: Zeilenumbruch in Perl-GBook Skript

Erstmal ein großes Danke das Ihr es mit dem neuen Forum geschafft habt!!!

Und vielleicht kann mir dadurch auch endlich jemand bei meinem Problem helfen, was in anderen Foren nicht geschafft wurde.

Es geht um folgendes: Ich habe mir schon vor einiger Zeit ein eigenes Gästebuch Skript in Perl geschrieben, welches Recht simpel ist aber sehr gut seine Arbeit tut. Allerdings habe ich es immer noch nicht hingekriegt, dass wenn man im Eingabefeld der Nachricht durch ENTER einen Zeilenumbruch erzwingen will, dass dieser dann auch wirklich in der Nachricht gezeigt wird!

Falls mir jemand helfen kann und dazu aber vielleicht das Skript sehen muss, dem kann ich das natürlich zuschicken oder teilweise hier posten!

Danke schonmal, schmaidt

  1. Hallo,
    wenn ich dich richtig verstehe meinst du die Nachricht nach dem Verschicken an den Server !? Oder etwa beim schreiben im Textfeld ?
    Bei ersteren mußt du die Zeilenumbrüche durch <br>`s ersetzen.
    $text =~ s/\n/<br>/g

    viele Grüße
    Thomas

  2. Hallo

    Allerdings habe ich es immer noch nicht hingekriegt, dass wenn man im Eingabefeld der Nachricht durch ENTER einen Zeilenumbruch erzwingen will, dass dieser dann auch wirklich in der Nachricht gezeigt wird!

    So ein kleiner Teil des Scriptes wäre schon ganz gut, aber probiers mal so:

    use strict;
    use CGI;
    my $q = new CGI;

    $_ = $q->param('feld');
    s/\n/<br>/g;

    Und das funktioniert nicht?

    Tschö Matti

  3. Moinmoin!

    [...] Allerdings habe ich es immer noch nicht hingekriegt, dass wenn man im Eingabefeld der Nachricht durch ENTER einen Zeilenumbruch erzwingen will, dass dieser dann auch wirklich in der Nachricht gezeigt wird!

    Wenn im Eingabefeld ein Zeilenumbruch vorkommt, wird dieser auch als Zeilenumbruch übergeben und hinterher in die Nachricht ge-print-et. Guck dir mal den Sourcecode der ausgegebenen HTML-Seite an, da sind die Zeilenumbrüche drin ;)

    Das simple Problem liegt darin, dass ein Zeilenumbruch im HTML-Source nicht als solcher im Browser angezeigt wird. Ersetze einfach alle in der Nachricht vorkommenden Zeilenumbrüche durch <br>-Tags, dann werden sie auch im Browser angezeigt:

    $nachrichtentext =~ s/\n/<br>/;

    beim Speichern des Gästebucheintrags dürfte ausreichen.

    Liebe Grüße
    Buggi

    1. [Nachtrag]

      $nachrichtentext =~ s/\n/<br>/;

      muss

      $nachrichtentext =~ s/\n/<br>/g;

      heißen, da sonst nur der erste vorkommende Zeilenumbruch ersetzt wird (ups).

      Liebe Grüße
      Buggi

      PS: Lustig, was hier jetzt schon für ein reger Verkehr ist *g*

      1. Moin Buggi!

        $nachrichtentext =~ s/\n/<br>/g;

        Windows- und UNIX-Browser senden als Zeilenumbruch unterschiedliche Zeichen.
        Windows: 0Dh 0Ah (\r\n)
        UNIX:    0Ah     (\n)

        Damit nicht ein einsames 0Dh im Text stehen bleibt, sollte so:

        $nachrichtentext =~ s/(\r\n)|(\n)/<BR>/g;

        ersetzt werden.

        Gruß Frank

        1. Danke ja, aber ich weiss leider immer noch nicht, wohin diese zeilen im Quellcode hinkommen. In meinem zweiten Posting habe ich den Quelltext auch gepostet, kann mir nicht jemand sagen, wohin die Befehle müssen?

          Bitte & Danke, schmaidt

        2. Hallo FrankS

          Windows- und UNIX-Browser senden als Zeilenumbruch unterschiedliche Zeichen.
          Windows: 0Dh 0Ah (\r\n)
          UNIX:    0Ah     (\n)

          Und sendet der Mac nicht einfach nur \r als Zeilenumbruch?

          Welche Lösung gibt es dann?
          s/\r\n/<br>/g;
          s/\r/<br>/g;
          s/\n/<br>/g;

          Jedenfalls das erste muss da stehen bleiben.

          Tschö Matti

          1. Hi Matti

            Und sendet der Mac nicht einfach nur \r als Zeilenumbruch?

            Interessant, das muß ich mal probieren, dann hätte eins meiner Scripte ja noch einen dicken Fehler, der u.U. zur Zerstörung von Daten führen könnte *schwitz*

            Wie wär's dann mit
            $nachrichtentext =~ s/(\r)|(\r\n)|(\n)/<BR>/g;

            Gruß Frank

  4. Hmmm, die Sache ist, dass ich mich so gut nun auch nicht auskenne mit Perl und den Speichern-Teil aus einem anderen übernommen hab. Die Befehle die Ihr mir gepostet habt, kenne ich, aber mein Problem liegt glaube ich da, dass ich nicht genau weiss, wo sie hingehören. I
    Ich poste Euch mal den Teil, in dem ich glaube, dass die Sachen hinmüssen.

    use strict;   # enforce declarations and quoting
    use CGI qw(:standard);  # import shortcuts

    sub bail {   # Funktion zur Ausgabe bei Fehlern
        my $error = "@_";
        print h1("Unerwarteter Fehler"), p($error), end_html;
        die $error;
    }

    my(
        $CHATNAME,  # Name der Datei der Gästebucheinträge
        $MAXSAVE,   # Wieviele Einträge sind möglich
        $TITLE,     # Seitentitel- und Überschrift
        $cur,       # Neuer Eintrag ins Gästebuch
        @entries,   # Alle Einträge
        $entry,     # Ein einzelner Eintrag
        $LOCK_EX,   # hardcoded value for flock
        $counter, # Nummerierung der Einträge
        $help,
    );

    $LOCK_EX = 2;   # hardcoded value for flock

    $TITLE = "schmaidt.de - guestbook";
    $CHATNAME = "../CHATFILE";    # Pfad der Datei der Einträge
    $MAXSAVE = 900;
    $cur = CGI->new(); # current request
    if ($cur->param("message")) {      # Es existiert ein Eintrag
        $cur->param("date", scalar localtime); # aktuelle Zeit
        @entries = ($cur);       # Speichern des Eintrags in das Array
    }

    open the file for read-write (preserving old contents)

    open(CHANDLE, "+< $CHATNAME") ||
        bail("cannot open $CHATNAME: $!");

    get exclusive lock on the guestbook

    ($LOCK_EX == exclusive lock)

    flock(CHANDLE, $LOCK_EX) || bail("cannot flock $CHATNAME: $!");

    grab up to $MAXSAVE old entries, newest first

    while (!eof(CHANDLE) && @entries < $MAXSAVE) {
        # pass the filehandle by reference
        $entry = CGI->new(\*CHANDLE);
        push @entries, $entry;
    }
    seek(CHANDLE, 0, 0) || bail("cannot rewind $CHATNAME: $!");
    foreach $entry (@entries) {
        $entry->save(\*CHANDLE); # pass the filehandle by reference
    }
    truncate(CHANDLE, tell(CHANDLE)) ||
        bail("cannot truncate $CHATNAME: $!");
    close(CHANDLE) || bail("cannot close $CHATNAME: $!");

    Ich hab jetzt erstmal einen ziemlich großen Teil gepostet, weil ich sicher gehen wollte, dass der richtige Bereich doch noch fehlt. Wäre Euch also echt dankbar, wenn Ihr mir sagen könntet wo es hin soll!

    Danke, schmaidt

    1. Hi nochmal!

      Die Befehle die Ihr mir gepostet habt, kenne ich, aber mein Problem
      liegt glaube ich da, dass ich nicht genau weiss, wo sie hingehören.

      if ($cur->param("message")) {      # Es existiert ein Eintrag

      An dieser Stelle prüfts Du, ob jemand einen neuen Eintrag inzufügen will.
      im Parameter "message" steht offensichtlich der Text.

      $cur->param("date", scalar localtime); # aktuelle Zeit

      Hier wird noch die aktuelle Zeit eingefügt

      @entries = ($cur);       # Speichern des Eintrags in das Array

      zur Weiterverarbeitung abgespeichert. Davor muß nun diese Änderung rein.

      }

      Also so (zum Verständnis schön in einzelnen Schritten):
      if ($cur->param("message")) {              # Es ...
          ###neu
          $temp = $cur->param("message");        # lesen
          $temp = s/(\r\n)|(\n)/<BR>/g;          # \n gegen <BR> tauschen
          $cur->param("message", $temp);         # schreiben
          ###
          $cur->param("date", scalar localtime); # aktuelle Zeit
          @entries = ($cur);                     # Speichern ...
      }

      Über einen Teil sollte aber auch noch diskutiert werden:

      open the file for read-write (preserving old contents)

      open(CHANDLE, "+< $CHATNAME") || bail("cannot open $CHATNAME: $!");

      get exclusive lock on the guestbook

      ($LOCK_EX == exclusive lock)

      flock(CHANDLE, $LOCK_EX) || bail("cannot flock $CHATNAME: $!");

      Das flock soll verhindern, das die Datei von 2 Prozessen gleichzeitig geöffnet wird (2 User posten gleichzeitig einen Eintrag). Über diesen Mechanismus wurde schon viel diskutiert...

      Eigentlich funktioniert das so:
      Prozess1: öffnet die Datei
      Prozess1: setzt exclusive lock
      Prozess1: bearbeitet Datei
      Prozess1: Schließt Datei hebt damit den lock wieder auf

      Jetzt mit 2 Prozessen:
      Prozess1: öffnet die Datei
      Prozess1: setzt exclusive lock
                                        Prozess2: öffnet die Datei
                                        Prozess2: will exclusive lock setzen,
                                                  kann aber nicht, da bereits
                                                  gesetzt, wird vertagt
      Prozess1: bearbeitet Datei
      Prozess1: Schließt Datei hebt
                damit den lock wieder auf
                                        Prozess2: wird geweckt, kann nun
                                                  exclusive lock setzen
                                        Prozess2: bearbeitet Datei
                                        Prozess2: Schließt Datei hebt
                                                  damit den lock wieder auf

      (Vorausstzung: open und flock sind auf Deinem Server richtig implementiert - Stichwort atomare Befehle)

      Damit merkt der User, der den 2. Prozess gestartet hat, nicht, dass ein Zugriffskonflikt stattfand, es dauert nur etwas länger. Bei Dir passiert aber etwas anderes: Der 2.Prozess wird mit einer Fehlermeldung beendet. Es reicht also diese Zeile:
      flock(CHANDLE, $LOCK_EX);

      Na dann,
      Gruß Frank

      P.S. Hoffentlich ist die Formatierung nach dem Absenden noch lesbar.

      1. Hi nochmal!

        Die Befehle die Ihr mir gepostet habt, kenne ich, aber mein Problem
        liegt glaube ich da, dass ich nicht genau weiss, wo sie hingehören.

        if ($cur->param("message")) {      # Es existiert ein Eintrag
        An dieser Stelle prüfts Du, ob jemand einen neuen Eintrag inzufügen will.
        im Parameter "message" steht offensichtlich der Text.
            $cur->param("date", scalar localtime); # aktuelle Zeit
        Hier wird noch die aktuelle Zeit eingefügt
            @entries = ($cur);       # Speichern des Eintrags in das Array
        zur Weiterverarbeitung abgespeichert. Davor muß nun diese Änderung rein.
        }

        Also so (zum Verständnis schön in einzelnen Schritten):
        if ($cur->param("message")) {              # Es ...
            ###neu
            $temp = $cur->param("message");        # lesen
            $temp = s/(\r\n)|(\n)/<BR>/g;          # \n gegen <BR> tauschen
            $cur->param("message", $temp);         # schreiben
            ###
            $cur->param("date", scalar localtime); # aktuelle Zeit
            @entries = ($cur);                     # Speichern ...
        }

        Über einen Teil sollte aber auch noch diskutiert werden:

        open the file for read-write (preserving old contents)

        open(CHANDLE, "+< $CHATNAME") || bail("cannot open $CHATNAME: $!");

        get exclusive lock on the guestbook

        ($LOCK_EX == exclusive lock)

        flock(CHANDLE, $LOCK_EX) || bail("cannot flock $CHATNAME: $!");

        Das flock soll verhindern, das die Datei von 2 Prozessen gleichzeitig geöffnet wird (2 User posten gleichzeitig einen Eintrag). Über diesen Mechanismus wurde schon viel diskutiert...

        Eigentlich funktioniert das so:
        Prozess1: öffnet die Datei
        Prozess1: setzt exclusive lock
        Prozess1: bearbeitet Datei
        Prozess1: Schließt Datei hebt damit den lock wieder auf

        Jetzt mit 2 Prozessen:
        Prozess1: öffnet die Datei
        Prozess1: setzt exclusive lock
                                          Prozess2: öffnet die Datei
                                          Prozess2: will exclusive lock setzen,
                                                    kann aber nicht, da bereits
                                                    gesetzt, wird vertagt
        Prozess1: bearbeitet Datei
        Prozess1: Schließt Datei hebt
                  damit den lock wieder auf
                                          Prozess2: wird geweckt, kann nun
                                                    exclusive lock setzen
                                          Prozess2: bearbeitet Datei
                                          Prozess2: Schließt Datei hebt
                                                    damit den lock wieder auf

        (Vorausstzung: open und flock sind auf Deinem Server richtig implementiert - Stichwort atomare Befehle)

        Damit merkt der User, der den 2. Prozess gestartet hat, nicht, dass ein Zugriffskonflikt stattfand, es dauert nur etwas länger. Bei Dir passiert aber etwas anderes: Der 2.Prozess wird mit einer Fehlermeldung beendet. Es reicht also diese Zeile:
        flock(CHANDLE, $LOCK_EX);

        Na dann,
        Gruß Frank

        P.S. Hoffentlich ist die Formatierung nach dem Absenden noch lesbar.

        DANKE DANKE DANKE. So hat es dann endlich geklappt. Allerdings hattest Du einen kleinen Tipfehler drin. Es muss nämlich

        $temp =~ s/(\r\n)|(\n)/<BR>/g;    statt
        $temp = s/(\r\n)|(\n)/<BR>/g;    heißen!

        Aber das hab selbst ich - die Laie - noch alleine hingekriegt!

        Danke nochmals, schmaidt

        1. Hallo Schmaidt

          DANKE DANKE DANKE. So hat es dann endlich geklappt. Allerdings hattest Du einen kleinen Tipfehler drin. Es muss nämlich

          $temp =~ s/(\r\n)|(\n)/<BR>/g;    statt
          $temp = s/(\r\n)|(\n)/<BR>/g;    heißen!

          Ich könnte mich ja jetzt rausreden, so nach dem Motto: Extra reingemacht, den Fehler, ein bischen Perl-Übung kann ja nicht schaden ;-)

          Aber so ist das, wenn man ungetesteten Code postet.

          Bis dann
           Gruß Frank

      2. Hi nochmal!

        Die Befehle die Ihr mir gepostet habt, kenne ich, aber mein Problem
        liegt glaube ich da, dass ich nicht genau weiss, wo sie hingehören.

        if ($cur->param("message")) {      # Es existiert ein Eintrag
        An dieser Stelle prüfts Du, ob jemand einen neuen Eintrag inzufügen will.
        im Parameter "message" steht offensichtlich der Text.
            $cur->param("date", scalar localtime); # aktuelle Zeit
        Hier wird noch die aktuelle Zeit eingefügt
            @entries = ($cur);       # Speichern des Eintrags in das Array
        zur Weiterverarbeitung abgespeichert. Davor muß nun diese Änderung rein.
        }

        Also so (zum Verständnis schön in einzelnen Schritten):
        if ($cur->param("message")) {              # Es ...
            ###neu
            $temp = $cur->param("message");        # lesen
            $temp = s/(\r\n)|(\n)/<BR>/g;          # \n gegen <BR> tauschen
            $cur->param("message", $temp);         # schreiben
            ###
            $cur->param("date", scalar localtime); # aktuelle Zeit
            @entries = ($cur);                     # Speichern ...
        }

        Über einen Teil sollte aber auch noch diskutiert werden:

        open the file for read-write (preserving old contents)

        open(CHANDLE, "+< $CHATNAME") || bail("cannot open $CHATNAME: $!");

        get exclusive lock on the guestbook

        ($LOCK_EX == exclusive lock)

        flock(CHANDLE, $LOCK_EX) || bail("cannot flock $CHATNAME: $!");

        Das flock soll verhindern, das die Datei von 2 Prozessen gleichzeitig geöffnet wird (2 User posten gleichzeitig einen Eintrag). Über diesen Mechanismus wurde schon viel diskutiert...

        Eigentlich funktioniert das so:
        Prozess1: öffnet die Datei
        Prozess1: setzt exclusive lock
        Prozess1: bearbeitet Datei
        Prozess1: Schließt Datei hebt damit den lock wieder auf

        Jetzt mit 2 Prozessen:
        Prozess1: öffnet die Datei
        Prozess1: setzt exclusive lock
                                          Prozess2: öffnet die Datei
                                          Prozess2: will exclusive lock setzen,
                                                    kann aber nicht, da bereits
                                                    gesetzt, wird vertagt
        Prozess1: bearbeitet Datei
        Prozess1: Schließt Datei hebt
                  damit den lock wieder auf
                                          Prozess2: wird geweckt, kann nun
                                                    exclusive lock setzen
                                          Prozess2: bearbeitet Datei
                                          Prozess2: Schließt Datei hebt
                                                    damit den lock wieder auf

        (Vorausstzung: open und flock sind auf Deinem Server richtig implementiert - Stichwort atomare Befehle)

        Damit merkt der User, der den 2. Prozess gestartet hat, nicht, dass ein Zugriffskonflikt stattfand, es dauert nur etwas länger. Bei Dir passiert aber etwas anderes: Der 2.Prozess wird mit einer Fehlermeldung beendet. Es reicht also diese Zeile:
        flock(CHANDLE, $LOCK_EX);

        Na dann,
        Gruß Frank

        P.S. Hoffentlich ist die Formatierung nach dem Absenden noch lesbar.

        Achso, und danke natürlich auch für den Tip mit dem flock. Habe ich gleich geändert und schon einmal ausprobiert. Auch das klappt!

        Danke, schmaidt