CGI-Perl Skript

Hallo!
Ich soll ein Perl-CGI-Skript schreiben, welches Anmeldedaten(Benutzername, Kennwort) eines Benutzers entgegennimmt und diese mit einer Textdatei abgleicht.
In der Textdatei stehen die Berechtigten mit Komma getrennt drin(Benutzername, Kennwort).Das Skript soll antworten, ob der Benutzer verlinkt wird oder nicht.
Weiß irgendwie nicht wie ich anfangen soll.
Kann mir jemand helfen?

Viele liebe Grüße.
carlson

Hallo carlson,

Kann mir jemand helfen?

Helfen kann man dir schon, aber sicher nicht das ganze Skript schreiben. Schreib mal genauer, wo es klemmt. Was hast Du denn schon und wo kommst Du nicht weiter?
Zur ersten Anregung: Dein File, in dem die Daten der User mit Passwörtern stehen, nennt sich CSV-Datei.
Das kannst Du entweder ganz konventionell Zeile für Zeile einlesen und z.B. mit split auswerten:

my ($Name, $Vorname, $Passwort) = split(/,/,$zeile);

Etwas komfortabler ist das Modul Text::CSV
http://perlmeme.org/tutorials/parsing_csv.html
Noch luxeriöser ist das Modul DBD::CSV. Damit kannst Du deine CSV-Datei wie eine SQL-Datenbank abfragen:
http://search.cpan.org/~hmbrand/DBD-CSV-0.33/lib/DBD…
Ist aber für deine Aufgabe sicher schon etwas überdimensioniert.
Soviel zu dem einen Teil der Aufgabe. Sollten die Schwierigkeiten noch woanders liegen, müsstest Du das genauer sagen.

Viele Grüße
Marvin

Hallo Marvin,

danke für die schnelle Antwort.
Ich möchte nicht, daß mir jemand das ganze Script schreibt.
Dann würde ich ja nichts lernen.
Also als erstes habe ich eine Textdatei (Passwort)mit folgenden Inhalt erstellt:
user1, braun
user2, heiss
user3, nass
user4, kalt
und diese Datei im cgi-bin Verzeichnis abgelegt.
Dann habe ich eine HTML-Datei (passwort1.html)erstellt und im Verzeichnis htdocs abgelegt.
Hier das Script:

Abfrage Benutzername und Passwort
Benuzername:

Passwort:

Es wird alles dargestellt und ich kann die Eingaben machen, aber wenn ich den Login-Button betätige erscheint immer diese Fehlermeldung:

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator, admin@localhost and inform them of the time the error occurred, and anything you might have done that may have caused the error.

More information about this error may be available in the server error log.

Hier ist das Perlscript:
#!c:/perl/bin/perl.exe -w
use cgi
read(STDIN, $Daten, $ENV{‚CONTENT_LENGTH‘});
print „Content-type: text/html\n\n“;
print „“;
print „“;
print " Berechnung des CGI-Programms ";
print „\n“;
print „“;
print " Antwortseite des CGI-Programms ";
print " „;
print " $Daten“;
print " ";
$login = 0;
open (LESEN, ")
{
chomp($zeile);
my ($username, $userpasswort) = split(/,/, $zeile);
if ($name eq $username && $passwort eq $userpasswort)
{
$login = 1;
last;
}
}
close LESEN;
if ($login)
{
print „Sie werden eingeloggt!“;
}
else
{
print „Die eingegebenen Daten sind nicht korrekt. Sie werden nicht eingeloggt!“;
print „$name“;
}
print „“;
print „“;

Ich komme irgendwie nicht weiter.

Viele Grüße.

Carlson67

Hallo Carlson67,

More information about this error may be available in the
server error log.

Ehe wir uns hier ans analysieren machen, was sagt denn der server error log? Wäre ja hilfreich.

Viele Grüße
Marvin

Für Codeformatierungen gibt es hier den PRE-Tag:

Hier ist das Perlscript:

> #!c:/perl/bin/perl.exe -w

use strict;
use warnings;


> use cgi

my ($Daten, $zeile, $name, $login, $name,$passwort)={};

Mit diesen Modifikationen dürfte man ein Stück weiter kommen.
Und testweise könnte man Dateien im selben Verzeichnis wie passwort.html ablegen.

mfg M.L.

Hallo,

#!c:/perl/bin/perl.exe -w

use strict;
use warnings;

use cgi

my ($Daten, $zeile, $name, $login, $name,$passwort)={};

Mit diesen Modifikationen dürfte man ein Stück weiter kommen.

Ein bisschen. Jetzt stirbt es in Zeile 4 statt 2.
(ausser der Fragesteller hat ein cgi.pm installiert, standardmaessig wird aber nur CGI.pm mitgeliefert).

Gruesse,
Moritz

Hallo Marvin,

folgendes steht in der error-log:

[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Premature end of script headers: passwortscript.pl
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] syntax error at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 4, near „:“\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] „use“ not allowed in expression at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 4, at end of line\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$Daten“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 5.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$Daten“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 14.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$login“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 16.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$zeile“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 18.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$zeile“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 20.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$zeile“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 21.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$name“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 22.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$passwort“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 22.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$login“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 24.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$login“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 29.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Global symbol „$name“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 36.\r
[Thu Apr 05 14:43:00 2012] [error] [client 127.0.0.1] Execution of C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl aborted due to compilation errors.\r

Viele Grüße.

Carlson67

Hallo nochmal

Als weiteren Vorschlag könnte man den Inhalt von passwort.txt als __DATA__ in die Perl-Datei schreiben und auslesen. Allzu motivierend sah das Ergebnis aber nicht aus:

Antwortseite des CGI-Programms


name=user1&passwort=braun
Die eingegebenen Daten sind nicht korrekt. Sie werden nicht eingeloggt!

Noch die modifizierte passwort.pl zum Verbessern:

#!c:/perl/bin/perl.exe -w
use strict;
use warnings;
use cgi;
my ($Daten, $zeile, $name, $login, $name,$passwort,$LESEN)={};
read(STDIN, $Daten, $ENV{'CONTENT\_LENGTH'});
print "Content-type: text/html\n\n";
print "";
print "";
print " Berechnung des CGI-Programms ";
print "\n";
print "";
print " Antwortseite des CGI-Programms ";
print " ";
print "$Daten";
print " ";

#open ($LESEN, ")
{
chomp($zeile);
my ($username, $userpasswort) = split(/,/, $zeile);
if ($name eq $username && $passwort eq $userpasswort)
{
$login = 1;
last;
}
}
#close $LESEN;
if ($login)
{ 
print "Sie werden eingeloggt!";
}
else
{
print "Die eingegebenen Daten sind nicht korrekt. Sie werden nicht eingeloggt!";
print "$name";
}
print "";
print "";

\_\_DATA\_\_
user1, braun
user2, heiss
user3, nass
user4, kalt

mfg M.L.

Hallo,

habe noch ein bißchen rumgebastelt und bekomme jetzt keine Fehlermeldung mehr vom Server.
Ich habe aber den Eindruck, daß das CGI-Script die Passwortdaten nicht mit denen in der Datei vergleicht.
Wenn ich die Daten eingebe(z.B. user1 und braun) erhalte ich folgende Ausgabe zurück:

Antwortseite des CGI-Programms
name=user1&passwort=braun

Hier ist nochmal das CGI-Script:

#!/usr/bin/perl -w
use strict;
use warnings;
use CGI;

my ($Daten,$zeile, $name, $login, $passwort,$LESEN)={};
read(STDIN, $Daten, $ENV{‚CONTENT_LENGTH‘});
print „Content-type: text/html\n\n“;
print „“;
print „“;
print " Berechnung des CGI-Programms ";
print „\n“;
print „“;
print " Antwortseite des CGI-Programms ";
print " „;
print " $Daten“;
print " ";
$login = 0;
open (LESEN, ")
{
chomp($zeile);
my ($username, $userpasswort) = split(/,/, $zeile);
if ($name eq $username && $passwort eq $userpasswort)
{
$login = 1;
last;
}
}
close LESEN;
if ($login)
{
print „Sie werden eingeloggt!“;
}
else
{
print „Die eingegebenen Daten sind nicht korrekt. Sie werden nicht eingeloggt!“;
print „$name“;
}
print „“;
print „“;

Die Textdatei liegt im gleichen Verzeichnis wie das html-script.

Wo liegt der Fehler?

Viele Grüße und ein schönes Osterfest.

carlson67

Hallo carlson67,

Ich habe aber den Eindruck, daß das CGI-Script die
Passwortdaten nicht mit denen in der Datei vergleicht.

Verglichen wird schon, aber $name und $passwort sind ja ständig leer.

Wo liegt der Fehler?

Du liest den eingegebenen Namen und das Passwort zwar richtig in $Daten ein, weist sie aber nirgends $name und $passwort zu.
Wenn ich z.B. meinName und meinPasswort eingebe, dann steht in Daten sowas:

name=meinName&passwort=meinPasswort

Das musst Du noch auseinandernehmen und deinen Variablen zuweisen. Das sollte dir eigentlich nicht allzuschwer fallen, das Werkzeug dazu hast Du.
Trotzdem noch eine Bemerkung: Keine Ahnung, ob Du so vorgehen musst (Vorgaben von Lehrern, Dozenten o.ä.). Das ist ja alles auch nicht falsch, aber zumindest sehr umständlich. Wenn Du die Möglichkeit hast, solltest Du dich gleich mit dem objektorientierten Stil des CGI-Moduls vertraut machen. Das erleichtert die Arbeit ungemein, weil Du dann nicht mehr umständlich

print "Content-type: text/html\n\n";
print "";
print "";
...

schreiben musst, sondern viel kürzer

my $cgi = new CGI;
print $cgi-\>header(),
 $cgi-\>start\_html(),
 $cgi-\>h1('Hallo Welt!'),
 $cgi-\>end\_html();

Auch die Abfrage der eingegebenen Namen und Passwörter wird viel einfacher, weil Du die Methode param() benutzen kannst.
Eine Art „Kurzlehrgang“ dazu, mit dem Du aber schon ganz schön weit kommst, kannst Du z.B. hier durchlesen:
http://de.selfhtml.org/perl/module/cgi.htm

Viele Grüße und ein schönes Osterfest.

Danke gleichfalls und viele Grüße
Marvin

Hallo Marvin,

vielen Dank für die schnelle Antwort.
Objektorientiertes programmieren haben wir noch nicht durchgenommen.
Ich grübele die ganze Zeit darüber, was Du mit auseinandernehmen dieser Ausgabe meinst „name=user1&passwort=braun“.
Außerdem stehe ich im Moment völlig auf dem Schlauch wie ich die Variabeln zuweisen soll. Ist sehr wahrscheinlich absolut simpel, aber ich komme nicht drauf.
Wie kann ich die eingelesenen Daten denn $name und $passwort zuweisen?
Kannst Du mir bitte nochmal einen Tipp geben.
Habe leider eine Denkblockade.

Viele Grüße.

carlson67

Hallo carlson67,

Ich grübele die ganze Zeit darüber, was Du mit
auseinandernehmen dieser Ausgabe meinst
„name=user1&passwort=braun“

Dann überlege mal, wie deine Zeilen aus der Passwortdatei aussahen:

"user1,braun"

Wie hast Du die denn auseinandergenommen, oder besser gesagt „getrennt“, „gespalten“, „geteilt“?
genauso machst Du das mit dieser Zeile, nur daß Du hier zweimal „trennen“ musst, zuerst an der Stelle, wo das &-Zeichen steht und dann beim Gleichheitszeichen.

Wie kann ich die eingelesenen Daten denn $name und $passwort
zuweisen?

Wie hast Du denn $username und $userpasswort die Werte zugewiesen? Das ist der gleiche Mechanismus, aber mehr verrate ich wirklich nicht.

Habe leider eine Denkblockade.

Ich hoffe, das löst deine Denkblockade trotzdem etwas :wink:

Viele Grüße.
Marvin

Hallo Marvin,
vielen Dank für die Hilfe.
Ich bin langsam am verzweifeln, daß ich diese Probleme nicht lösen kann. Dabei scheint die Lösung total simpel zu sein.

In der Textdatei habe ich die Werte mit , getrennt.
Ich weiß aber nicht wie ich das bei der Ausgabe der Zeile(„name=user1&passwort=braun“) hinbekomme und wo ich was ändern muß.

Die Werte habe ich mit dieser Zeile zugewiesen:
my ($username, $userpasswort) = split(/,/, $zeile);
Wenn ich aber die Variabeln $username und $userpasswort durch $name und $passwort esetze oder die gleiche Zeile mit den Variabeln $name und $passwort ins script einfüge funktioniert es nicht mehr.
Finde leider überhaupt keinen Ansatz mehr.
Viele Grüße.

Carlson67

Hallo carlson67,

Ich bin langsam am verzweifeln, daß ich diese Probleme nicht
lösen kann. Dabei scheint die Lösung total simpel zu sein.

Kein Grund zum Verzweifeln, denn die Lösung ist tatsächlich simpel.

In der Textdatei habe ich die Werte mit , getrennt.

Ja, in der Textdatei sind die Werte mit Komma getrennt. Und dann hast Du den Befehl split benutzt. Der zweite Parameter war deine Zeile, die Du teilen wolltest und der erste Parameter war auch ein Komma

my ($username, $userpasswort) = split(/,/, $zeile);

Beide Male ein Komma , das kann doch kein Zufall sein :wink:

Ich weiß aber nicht wie ich das bei der Ausgabe der
Zeile(„name=user1&passwort=braun“) hinbekomme und wo ich was
ändern muß.

Und durch was sind diesmal die Werte getrennt? Also bitte, nimm deine Unterlagen und sieh nach, was die Parameter bei split bedeuten oder google danach.

Wenn ich aber die Variabeln $username und $userpasswort durch
$name und $passwort esetze oder die gleiche Zeile mit den
Variabeln $name und $passwort ins script einfüge funktioniert
es nicht mehr.

$name und $passwort ist schon mal gut, das willst Du ja haben. Aber Du musst noch mehr ersetzen. Deine gesuchten Daten stehen ja nicht mehr in der Variablen zeile, sondern wo?
Und dann musst Du ja mehrmals teilen (split), hatte ich ja schon gesagt. Aber warum, und an welchen Stellen?
Stell dir das ruhig bildlich vor: Du hast einen Stab und auf dem steht

name=user1&passwort=braun

geschrieben. An welchen Stellen (Zeichen) musst Du den der Reihe nach durchbrechen, durchsägen, damit Du zum Schluss nur noch zwei Stückchen in der Hand hast, auf dem einen soll nur user1 stehen und auf dem anderen braun?
Tja, und die Methode split ist sozusagen deine vollautomatische Säge, mit der Du das in Perl machst. Du musst ihr nur noch durch den ersten Parameter sagen, an welchen Stellen (Zeichen) sie durchsägen muss.
Ich hoffe, daß ich dich damit nicht noch mehr verwirrt habe, aber noch genauer hiesse die Lösung verraten.

Viele Grüße
Marvin

Hallo Marvin,

ich möchte mich erstmal für Deine Mühe und Geduld bedanken.
1.Ich habe mich nochmal durch meine Unterlagen gewühlt, bezüglich der Funktion „split“.
Die Zeile name=user1&passwort=braun soll ja an den Gleichheitszeichenund dem Und Zeichen getrennt werden.
Aber egal was ich auch eingebe es kommt immer als Ausgabe diese Zeile name=user1&passwort=braun und nicht user1 und braun.
2. Na klar die Daten sind nicht mehr in der Variable $zeile sondern in der Variable $Daten.
Die Zeile my ($username, $userpasswort) = split(/,/, $zeile);
habe ich nun dementsprechend abgeändert in
my ($name, $passwort) = split(/&/, $Daten); geändert und noch folgende Zeile eingefügt
my ($name, $passwort) = split(/=/, $Daten);
Aber ich weiß immer noch nicht wie die Werte aus $Daten den Variablen $name und $passwort zuweisen kann.
$name und $passwort scheinen immer noch leer zu sein.

Hier nochmal mein jetziges script:

#!/Perl/bin/perl.exe -w
use strict;
use warnings;
use cgi::Carp „fatalsToBrowser“;

my ($Daten, $zeile, $name, $login, $passwort, $Datei)={};
read(STDIN, $Daten, $ENV{‚CONTENT_LENGTH‘});

print „Content-type: text/html\n\n“;
print „“;
print „“;
print " Berechnung des CGI-Programms ";
print „\n“;
print „“;
print " Antwortseite des CGI-Programms ";
print " „;
print " $Daten“;
print " „;
$login = 0;
open ( Datei,“)
{
chomp($zeile);
my($name, $passwort) = split(/&/, $Daten);
my ($name, $passwort) = split(/=/, $Daten);
if ($name eq $username && $passwort eq $userpasswort)
{
$login = 1;
last;
}
}
close Datei;
if ($login)
{
print „Sie werden eingeloggt!“;
}
else
{
print „Die eingegebenen Daten sind nicht korrekt. Sie werden nicht eingeloggt!“;
print „$name“;
}
print „“;
print „“;

Der Server sendet mir immer folgende Fehlermeldung:

[Mon Apr 09 10:46:02 2012] [error] [client 127.0.0.1] Premature end of script headers: passwortscript.pl
[Mon Apr 09 10:46:02 2012] [error] [client 127.0.0.1] Global symbol „$username“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 25.\r
[Mon Apr 09 10:46:02 2012] [error] [client 127.0.0.1] Global symbol „$userpasswort“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 25.\r
[Mon Apr 09 10:46:02 2012] [error] [client 127.0.0.1] Execution of C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl aborted due to compilation errors.\r
[Mon Apr 09 10:48:26 2012] [error] [client 127.0.0.1] Premature end of script headers: passwortscript.pl
[Mon Apr 09 10:48:26 2012] [error] [client 127.0.0.1] Global symbol „$username“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 25.\r
[Mon Apr 09 10:48:26 2012] [error] [client 127.0.0.1] Global symbol „$userpasswort“ requires explicit package name at C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl line 25.\r
[Mon Apr 09 10:48:26 2012] [error] [client 127.0.0.1] Execution of C:\Apache Software Foundation\Apache2.2\cgi-bin\passwortscript.pl aborted due to compilation errors.\r

Es ist mir irgendwie schon peinlich, aber ich komme immer noch nicht auf die Lösung.

Viele Grüße.

Carlson67

Hallo Carlson67,

$name und $passwort scheinen immer noch leer zu sein.

„scheinen“ ist keine gute Grundlage fürs programmieren. Von so etwas soll man sich überzeugen. Füge

print $name

und

print $passwort

ein, dann siehst Du, ob die Variablen leer sind, oder welchen Inhalt sie haben.

my($name, $passwort) = split(/&/, $Daten);
my ($name, $passwort) = split(/=/, $Daten);

Das ist ja schon der richtige Weg, aber leider fehlt noch etwas. Überlege mal, was nach dem ersten Befehl

my($name, $passwort) = split(/&/, $Daten);

in $name und $passwort steht. Wäre gut, wenn Du allein durch nachdenken darauf kommen würdest. Aber wenn nicht, dann sieh einfach mit print nach (s.o.)
Du wirst dann merken, daß Du in $name und $passwort erstmal ein Zwischenergebnis hast, oder genaugenommen zwei Zwischenergebnisse. Deshalb ist es zu früh, dies dort schon $name und $passwort zuzuweisen. Aber wie gesagt, sieh dir die Ausgabe an, dann fällt dir hoffentlich etwas ein.
Außerdem solltest Du in deinen Unterlagen nachsehen, welchen Zweck my in Perl hat. Ich habe den Eindruck, daß Du das noch nicht verstanden hast.

Der Server sendet mir immer folgende Fehlermeldung:
[Mon Apr 09 10:46:02 2012] [error] [client 127.0.0.1]
Premature end of script headers: passwortscript.pl

Das habe ich jetzt nicht extra nachgesehen. Aber sowas kommt meistens von Syntaxfehlern, vergessene Semikolons am Ende der Zeile, schliessende Klammern zu wenig (zu jeder öffnenden Klammer muss ja genau auch eine schliessende existieren) o.ä.

Es ist mir irgendwie schon peinlich, aber ich komme immer noch
nicht auf die Lösung.

Ein Tipp von mir: Schreibe mal ein kleines Hilfsskript, ohne HTML und das ganze drumherum. Konzentriere dich darin nur auf das auseinandernehmen dieser Zeile und analysiere durch print, was nach jedem skript passiert.
Daß die zu untersuchende Zeile „name=user1&passwort=braun“ heisst, steht ja fest. Also kannst Du dein Hilfs- oder Testskript so anfangen:

my zeile = "name=user1&passwort=braun"
my($help1, $help2) = split(/&/, $zeile);
print $help1;
print $help2;
...

praktischerweise kommen da noch weitere Zeilen, aber das musst Du selbst rausfinden. Wenn Du dadurch erkannt hast, wie die weiteren Zeilen lauten müssen, damit zum Schluß in der Variablen $name user1 und in der Variablen $passwort braun stehen, wirfst Du alle jetzt unnützen Zeilen (also die mit print) wieder raus und fügst den Rest in dein Ursprungsskript ein.
Diese Methode, erst mal alles Drumherum wegzulassen und sich auf das eine Problem zu beschränken, ist eine Möglichkeit, Lösungen zu finden.

Viele Grüße
Marvin