Hansi: STDIN kann nur einmal übergeben werden !?

Hallo an alle,

ich bin gerade dabei das Forum-Skript WebBBS an meine Bedürfnisse anzupassen. Das Forum soll dann von verschiedenen Usern, die kein eigenes CGI verwenden können benutzbar sein. Dazu wird nun (das ist neu in dem Skrip) bei jedem Aufruf ein Parameter user=BenutzerID übergeben. Sollte der user unbekannt sein, wird er auf user=nobody umgeleitet.

Um nun im Eingangsskript schon entscheiden zu können, ob der User einen Account hat oder nicht werden die übergebenen Parameter mit der Funktion &getvars die wohl in jedem zweiten Skript verwendet wird aufgesplittet. Für die Aufsplittung der Parameter im eigentlichen webbbs-Skript ist eine etwas aufwendigere Methode eingebaut.

-Ich möchte die Überprüfung auf jeden Fall außerhalb des Hauptscripts belassen, da noch mehr Services geplant bzw. im Test sind, die auf die gleiche Uservalidierung zurückgreifen-

So jetzt kommts. Wenn die Parameter über die Eingabezeile(URL) übergeben wird läuft alles im grünen Bereich. Sobald aber die Parameter über das POST eines Formulars übergeben werden, arbeitet die erste Funktion &getvars normal und leitet die Anfrage auch normal an das Hauptskript. Die Funktion &Parse_Form im Hauptskript bekommt nun aber keine Werte mehr zum analysieren.

Hier die einführenden Zeilen:

sub getvars
  {
  if ($ENV{'REQUEST_METHOD'} eq 'GET') {
      # Split the name-value pairs
      @pairs = split(/&/, $ENV{'QUERY_STRING'});
  }
  elsif ($ENV{'REQUEST_METHOD'} eq 'POST') {
    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
    @pairs = split(/&/, $buffer);
  }
  foreach $pair (@pairs) {
.....

sub Parse_Form {
if ($NaughtyWords) {
  @naughtywords = split(/ /,$NaughtyWords);
}
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
@pairs = split(/&/, $buffer);
foreach $pair (@pairs){
  ($val1, $val2) = split(/=/, $pair);
.....

Dieses Problem hat mich die letzte Nacht ungefähr 5 Std. beschäftigt. Die einzige Lösung, die dann auch funktioniert hatte, war daß ich in der Funktion &Parse_Form die Zeile read(STDIN, $buffer.... auskommentiert habe. Komischerweise war das die einzige Änderung, die ich zum Schluß gemacht habe. Alles funktionierte dann wie gewünscht.

Ich kann mir nun aber nicht vorstellen, daß man STDIN nur einmal auslesen kann. Oder? Ich denke natürlich in erster Linie an menschliches Versagen. Schließlich befasse ich mich erst seit ca. 3 Monaten intensiv mit Perl.

Nun die Frage: Habe ich womöglich mit meiner Vermutung recht? Oder habe ich hier Bockmist gebaut?

Ein einfaches Auskommentieren und dann funkt's kann ich so nicht hinnehmen. Schließlich werden ja (hoffentlich) mehr wie nur zwei Leute darauf zurückgreifen.

Tschuldigung daß es so lange wurde:-)

Im voraus möchte ich mich schon einmal bei allen bedanken, die einen Gedanken beisteuern wollen.

Gruß Hansi

  1. Moin!

    So jetzt kommts. Wenn die Parameter über die Eingabezeile(URL) übergeben wird läuft alles im grünen Bereich. Sobald aber die Parameter über das POST eines Formulars übergeben werden, arbeitet die erste Funktion &getvars normal und leitet die Anfrage auch normal an das Hauptskript. Die Funktion &Parse_Form im Hauptskript bekommt nun aber keine Werte mehr zum analysieren.

    Muß aber auch so sein, weil im Skriptablauf zweimal hintereinander der Befehl

    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});

    aufgerufen wurde. Beim 2. mal wurde STDIN ja schon "ausgelesen" und liefert nix mehr nach. Ob man STDIN "schließen" und wieder "öffnen" und danach neu auslesen kann ist mir unbekannt, vielleicht weiß da jemand mehr...? Kleines Beispiel zur Veranschaulichung: Wenn Du z.B. stattdessen 2 mal den Befehl

    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}/2);

    verwenden würdest - also jedesmal nur die Hälfte der geposteten Datenmasse lesen - wäre es ja auch ziemlich unlogisch, wenn der read-Befehl auch beim 2. mal wieder "von oben anfangen" würde.

    Da Du $buffer als globale Variable verwendest, ist Deine Lösung, einfach den 2. read-Befehl auszukommentieren, in der Tat korrekt.

    Ich hoffe, ich konnte alle Klarheiten beseitigen ;-)

    Viele Grüße

    Andreas

  2. Hallo Hansi!

    Ich kann mir nun aber nicht vorstellen, daß man STDIN nur einmal auslesen kann. Oder? Ich denke natürlich in erster Linie an menschliches Versagen. Schließlich befasse ich mich erst seit ca. 3 Monaten intensiv mit Perl.

    Ist aber so!

    Man kann sich aber sein eigenes STDIN öffnen. Am besten nimmt man hierzu ein(e) PIPE.
    Das ist eine virtuelle Datei oder ein Datenloch oder -Rohr ... Auf der einen Seite schreibst Du was rein und auf der anderen Seite liest Du es wieder aus:

    #----------------------------------------------
    use FileHandle;

    my ($pipeOut, $pipeIn) = FileHandle::pipe();
    read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
    print $pipeIn $buffer x 10;  #je nachdem, wie oft man auslesen möchte - mehr schadet aber nicht
    $pipeIn->close;

    nun STDIN verbiegen

    open STDIN, "<&=" . fileno $pipeOut;

    hier hinter kann man nun STDIN 10 mal auslesen ...

    #----------------------------------------------

    Hoffe das hilft erst mal weiter,
       Jörk

    1. Hallo Jörk!

      Ist aber so!

      Dann kann ich ja beruhigt weitermachen.

      #----------------------------------------------
      use FileHandle;

      my ($pipeOut, $pipeIn) = FileHandle::pipe();
      read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
      print $pipeIn $buffer x 10;  #je nachdem, wie oft man auslesen möchte - mehr schadet aber nicht
      $pipeIn->close;

      nun STDIN verbiegen

      open STDIN, "<&=" . fileno $pipeOut;

      hier hinter kann man nun STDIN 10 mal auslesen ...

      #----------------------------------------------

      Kann es sein, daß sich hier ein kleiner Fehler eingeschlichen hat?;-)
      Wenn STDIN nur einmal ausgelesen werden kann, dann sollte es doch erst am Ende Deines Beispiels ausgelesen werden.

      Hoffe das hilft erst mal weiter,

      Das tut es. Danke!

      Hansi