Gaestebuch
azrael
- cgi
0 Frank Schönmann0 Fokuhila0 Frank Schönmann0 AlexBausW0 azrael0 AlexBausW0 azrael0 Klaus Mock
0 Fokuhila
#!/usr/bin/perl -w
use Fcntl qw(:DEFAULT :flock);
$Zeit_Berichtigung = +3.25;
$date = localtime(time+($Zeit_Berichtigung*3600));
chop($date);
&parse_form;
$in{'Kommentar'} =~ s/<script//img;
$in{'Kommentar'} =~ s/<style//img;
$in{'username'} =~ s/\n//mg;
$in{'username'} =~ s/\r//mg;
$in{'email'} =~ s/</</mg;
$in{'email'} =~ s/\n//mg;
$in{'email'} =~ s/\r//mg;
print "Content-type: text/html\n\n";
if ($in{'email'} !~m/.*@.*..*/i)
{
print "<html>\n<head><title>Fehler</title>\n</head>\n<Body BACKGROUND="http://www.8ung.at/hellofweb/gfx/rk.jpg" text="ff9900" LINK="#f76809" VLINK="#f76809" ALINK="#f76809">\n<p><center><h3>Du musst eine richtige E-Mail Adresse eingeben.</h3></center></p>\n";
exit;
}
elsif ($in{'username'} eq "") {
print "<html>\n<head><title>Fehler</title>\n</head>\n<Body BACKGROUND="http://www.8ung.at/hellofweb/gfx/rk.jpg" text="ff9900" LINK="#f76809" VLINK="#f76809"
ALINK="#f76809">\n<p><center><h3>Bitte einen Namen eingeben</h3></center></p>\n";
}
elsif ($in{'Kommentar'} eq "") {
print "<html>\n<head><title>Fehler</title>\n</head>\n<Body BACKGROUND="http://www.8ung.at/hellofweb/gfx/rk.jpg" text="ff9900" LINK="#f76809" VLINK="#f76809"
ALINK="#f76809">\n<p><center><h3>Na, Text braeuchten wir schon</h3></center></p>\n";
}
else {
&start;
}
sub start {
print "<HTML>\n";
print "<head><title>Neueintrag in das Gästebuch</title></head>\n";
print "<body background="http://www.8ung.at/hellofweb/gfx/rk.jpg" text="ff9900" link="#FF6600" vlink="#FF6600" alink="#FF6600" bgproperties="fixed">\n";
print "<blockquote><center>\n";
print "<H2>Neueintrag in das Gästebuch</H2>\n";
print "am $date<p>\n";
print "<HR size="1">\n";
print "</center><p>\n";
print "Wir haben von Ihnen folgende Angaben erhalten:<p> \n";
print "<ul> \n";
print "<li>Name: <b>$in{'username'}</b></li>\n";
print "<li>E-Mail Adresse: <b>$in{'email'}</b></li>\n";
print "<li>Webseite: <b>$in{'website'}</b></li>\n";
print "<li>Kommentar:<br></li>\n";
print "<b>$in{'Kommentar'}</b>\n";
print "</ul><p>\n";
print "<HR size="1">\n";
print "Vielen Dank für Ihren Eintrag in unserem <a href="http://www.1blubba1.f2s.com/gaestebuch.html">Gaestebuch</a></p></blockquote>\n";
&gaestebuch;
print "</BODY>\n";
print "</HTML>\n";
}
sub gaestebuch {
$outfile = "/web/sites/195/12azra21/www.1blubba1.f2s.com/gaestebuch.html";
open(FILE,"$outfile") or die "\Datei $outfile konnte nicht geoeffnet werden\n";
@LINES=<FILE>;
close(FILE);
$SIZE=@LINES;
open(OUTFILE,">$outfile") or die "\Datei $outfile konnte nicht geoeffnet werden\n";
flock(OUTFILE, LOCK_EX) or die "\Cannot lock $outfile\n";
for ($i=0;$i<=$SIZE;$i++) {
$_=$LINES[$i];
if (/<!--begin-->/) {
print OUTFILE "
<p>Am $date schrieb <b>$in{'username'}</b> (E-Mail: <a href=mailto:$in{'email'}>$in{'email'}</a>) das folgende in unser Gästebuch.</p>
<p>Kommentar:<br>
<b>$in{'Kommentar'}</b></p>\n
<p>Homepage: <a href="$in{'website'}">$in{'website'}</a></p>\n
<p><div align="right"><font size="-2">IP: $ENV{'REMOTE_ADDR'}</font></div></p>
<hr size="1">\n
";
close(OUTFILE); }
}
}
sub parse_form {
local ($buffer, @pairs, $pair, $name, $value);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
}
else
{
$buffer = $ENV{'QUERY_STRING'};
}
@pairs = split(/&/, $buffer);
foreach $pair (@pairs)
{
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
$value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$in{$name} = $value;
}
}
---------------------------------------------------
also, wieso wird hier die gaestebuch.html mit dem Eintrag ueberschrieben, statt den Gaestebucheintrag hinter das <!--begin-->
zu schreiben ? mit >>$outfile statt >$outfile wuerde ja das abschließende </body></html> am ende der gaestebuch.html an der falschen stelle sein, da die Eintraege einfach an das ende der datei angehaengt werden wuerden, aber wieso wird die gaestebuch.html mit >$outfile gerade ersetzt ?
das ist auch der Teil vom code, den ich von matt's Gaestebuch uebernommen habe und eigentlich sehe ich hier auch keinen Fehler :(
mfg: <a href="http://www.8ung.at/hellofweb">azrael</a>
http://www.1blubba1.f2s.com/gaestebuch.html
hi!
[viel Müll gelöscht...]
also, wieso wird hier die gaestebuch.html mit dem Eintrag
ueberschrieben, statt den Gaestebucheintrag hinter das <!--
begin--> zu schreiben ? mit >>$outfile statt >$outfile wuerde ja
das abschließende </body></html> am ende der gaestebuch.html an
der falschen stelle sein, da die Eintraege einfach an das ende der
datei angehaengt werden wuerden, aber wieso wird die
gaestebuch.html mit >$outfile gerade ersetzt ?
Siehe dazu perldoc -f open und das Archiv. Die FAQ zu lesen, kann
auch nicht schaden.
bye, Frank!
[...]
also, wieso wird hier die gaestebuch.html mit dem Eintrag ueberschrieben, statt den Gaestebucheintrag hinter das <!--begin-->
for ($i=0;$i<=$SIZE;$i++) {
$_=$LINES[$i];
if (/<!--begin-->/) {
Dieser reguläre Ausdruck prüft nur, ob <!--begin--> vorhanden ist. Wenn ja, wird sofort losgeschrieben.
print OUTFILE "
zu schreiben ? mit >>$outfile statt >$outfile wuerde ja das abschließende </body></html> am ende der gaestebuch.html an der falschen stelle sein, da die Eintraege einfach an das ende der datei angehaengt werden wuerden, aber wieso wird die gaestebuch.html mit >$outfile gerade ersetzt ?
Schau doch die Argument an, die du open() übergibst! Da steht weder ">$outfile", noch ">>$outfile", sondern
"open(FILE,"$outfile")
Du hast also den Modus zum Öffnen der Datei nicht spezifiziert. Wolltest du aber! Siehe hierzu </selfhtml/tgcj.htm>.
Hier ein sinnvoller Regexp:
s/<!--begin-->/&eintrag<!--begin-->/ while (OUTFILE);
sub eintrag {
return <<"FERTIG";
<p>
Am $date schrieb <b>$in{'username'}</b>
(E-Mail: <a href=mailto:$in{'email'}>$in{'email'}</a>)
das folgende in unser Gästebuch.
</p><p>
Kommentar:<br>
<b>$in{'Kommentar'}</b>
</p><p>
Homepage: <a href="$in{'website'}">$in{'website'}</a>
</p><p>
<div align="right">
<font size="-2">IP: $ENV{'REMOTE_ADDR'}</font>
</div>
</p>
<hr size=1>
FERTIG
}
[...]
So, und jetzt muss ich dir doch (so leid es mir tut) einen kleinen Anschiss erteilen: Warum zum Hacker benutzt du weder CGI.pm noch Hier-Dokumente?! Mit CGI.pm wäre alles _viel_ einfacher. Du könntest dir u.a. die Subroutine &parse_form sparen. Und &eintrag wäre auch übersichtlicher:
sub eintrag {
my $eintrag = '';
$eintrag .= p(
"Am $date schrieb", # Variableninterpolation
b( param('username') ),
'(E-Mail:',
a({ -href => "mailto:param('email')" },# Variableninterpolation
param('email')
),
'das Folgende in unser Gästebuch:'
);# Der erste Absatz ist jetzt fertig.
$eintrag .= p(
'Kommentar'. #Stringverkettung
br(). #Stringverkettung
'Kommentar:'.#Stringverkettung
br(). #Stringverkettung
b( param('Kommentar') )
);# Zweiter Absatz ist fertig.
$eintrag .= p(
'Homepage:',
a({ -href => $param('website) },
$param('website)
)
);# dritter Absatz ist fertig.
$eintrag .= p(
div({ -align => 'right' },
font({ -size => 2 },
'IP:',
$ENV{'REMOTE_ADDR'}
)# Ende des font-Tags
)# Ende des div-TAgs
);# Ende des dritten Absatzes.
$eintrag .= hr({ size => 1 });
return $eintrag;
}
mfg: <a href="http://www.8ung.at/hellofweb">azrael</a>
Hell of Web ;-) :-o
hi!
Schau doch die Argument an, die du open() übergibst! Da steht
weder ">$outfile", noch ">>$outfile", sondern"open(FILE,"$outfile")
Du hast also den Modus zum Öffnen der Datei nicht spezifiziert.
Wolltest du aber! Siehe hierzu </selfhtml/tgcj.htm>.
perldoc -f open:
[...]
If MODE is "'<'" or nothing, the file is opened for input.
[...]
bye, Frank!
Hallo Fokuhila,
[...]
if (/<!--begin-->/) {
Dieser reguläre Ausdruck prüft nur, ob <!--begin--> vorhanden ist. Wenn ja, wird sofort losgeschrieben.
Das ist ja imho prinzipiell beabsichtigt, also bei <!--begin--> den neuen Eintrag einfügen.
Hier ein sinnvoller Regexp:
s/<!--begin-->/&eintrag<!--begin-->/ while (OUTFILE);
OUTFILE muss zum Lesen _und_ Schreiben offen sein
Kannst Du vielleicht näher erläutern _wie_ Du das genau zum Laufen gebracht hast? Bei mir funzt das nicht ;)
(perl meckert: "Bareword found in conditional ...")
Gruß Alex
hi!
s/<!--begin-->/&eintrag<!--begin-->/ while (OUTFILE);
OUTFILE muss zum Lesen _und_ Schreiben offen sein
Kannst Du vielleicht näher erläutern _wie_ Du das genau zum Laufen
gebracht hast? Bei mir funzt das nicht ;)
(perl meckert: "Bareword found in conditional ...")
Ich vermute, in der Zeile müsste es <OUTFILE> heißen. So macht es
nämlich wenig Sinn, da Perl das AFAIK als String betrachten müsste;
und der Ausdruck wäre dann immer wahr.
bye, Frank!
Hallo Frank,
s/<!--begin-->/&eintrag<!--begin-->/ while (OUTFILE);
OUTFILE muss zum Lesen _und_ Schreiben offen sein
Kannst Du vielleicht näher erläutern _wie_ Du das genau zum Laufen
gebracht hast? Bei mir funzt das nicht ;)
(perl meckert: "Bareword found in conditional ...")
Ich vermute, in der Zeile müsste es <OUTFILE> heißen. So macht es
nämlich wenig Sinn, da Perl das AFAIK als String betrachten müsste;
und der Ausdruck wäre dann immer wahr.
Daraufhin habe ich natürlich alles mögliche versucht, weil ich dachte ich hätte was verpasst :) Aber ich habe es nur wie folgt fertig gebracht, in dieselbe Datei den neuen Eintrag verlustfrei zu schreiben:
open FILE, "+<gbook.html" or die $!;
my @file = <FILE>;
seek FILE, 0,0;
truncate FILE, 0;
print FILE map { s/<!--begin-->/&eintrag.'<!--begin-->'/e; $_ } @file;
close FILE or die $!;
Alles (ich bin mir aber nicht sicher, ob ich alles probiert habe ;) andere funktioniert zumindest auf Win95 nicht.
Gruß Alex
[...]
also, wieso wird hier die gaestebuch.html mit dem Eintrag ueberschrieben, statt den Gaestebucheintrag hinter das <!--begin-->
for ($i=0;$i<=$SIZE;$i++) {
$_=$LINES[$i];
if (/<!--begin-->/) {
Dieser reguläre Ausdruck prüft nur, ob <!--begin--> vorhanden ist. Wenn ja, wird sofort losgeschrieben.
print OUTFILE "
hallo,
und genau das macht es eben nicht - ich kapiere einfach nicht wieso
hier:
open(OUTFILE, ">$outfile") or die "\Datei $outfile konnte nicht geoeffnet werden\n";
flock(OUTFILE, LOCK_EX) or die "\Cannot lock $outfile\n";
for ($i=0;$i<=$SIZE;$i++) {
$_=$LINES[$i];
if (/<!--begin-->/) {
mit dem open(OUTFILE, ">$outfile") die gaestebuch.html durch den eintrag ersetzt wird, obwohl er ja erst beim <!--begin--> anfangen sollte, bzw. mit open(OUTFILE, ">>$outfile") bewirkt es immerhin noch das richtige und setzt den Eintrag an den schluß der .html datei
die frage bleibt aber, wieso mit Hilfe von >$outfile die .html datei ersetzt wird obwohl die eintraege eben erst ab dem begin eingesetzt werden sollten
mfg: azrael
Hallo Azrael,
for ($i=0;$i<=$SIZE;$i++) {
Das ist C-like, aber kein Perl ;) Besser ist:
foreach (@LINES) { # wobei @LINES klein geschrieben werden sollte: perldoc perlstyle
Dann kannst Du Dir nämlich:
$_=$LINES[$i];
sparen, da das aktuelle Element von @LINES automagisch in $_ referenziert wird.
if (/<!--begin-->/) {
mit dem open(OUTFILE, ">$outfile") die gaestebuch.html durch den eintrag ersetzt wird, obwohl er ja erst beim <!--begin--> anfangen sollte, bzw. mit open(OUTFILE, ">>$outfile") bewirkt es immerhin noch das richtige und setzt den Eintrag an den schluß der .html datei
die frage bleibt aber, wieso mit Hilfe von >$outfile die .html datei ersetzt wird obwohl die eintraege eben erst ab dem begin eingesetzt werden sollten
Das hört sich so an, als ob Du den neuen Eintrag ins Gästebuch schreibst, wenn der Ausdruck trifft, aber nichst in die Datei schreibst für all die anderen Zeilen des eingelesenen Gästebuchs, die Du natürlich auch wieder zurückschreiben musst (open F, ">file" löscht Dir die Datei)
Füge nach dem if()-Block ein 'else { print; }' ein, dann sollte der alte Inhalt in die Datei zurückgeschrieben werden. Du musst aber dran denken, auch <!--begin--> wieder neu zu schreiben, sonst ist Deine Marke weg und nichts geht mehr :)
Gruß Alex
jup, das ganze laeuft jetzt - danke ;)
nun kann ich ja den code mal ein wenig "verschoenern"
mfg: azrael
Hallo,
for ($i=0;$i<=$SIZE;$i++) {
Das ist C-like, aber kein Perl ;) Besser ist:
Aber da Perl eine Sprache mit vielen Möglichkeiten ist, spricht auch gegen diese Variante nichts Bedeutendes;-)
(Ich mache es aber heute auch anders, außer wenn ich beispielsweise in zwei Arrays gleichzeitig arbeite oder es sonst irgendwie mehr Sinn ergibt.)
Nun aber zum eigentlichen Problem von azrael, wobei ich einige Vereinfachungen vorgenommen habe, um die Struktur klarer werden zu lassen. Es fehlen z.B. die ganzen my's und flock's.
Die Doku von open ist ja mehrfach zitiert worden, aber trotzdem nochmals in Kürze. mit ">$outfile" wird die Datei vollkommen neu geschrieben, während ">>$outfile" dafür sorgt, daß am Ende der Datei angefügt wird. Da Du aber irgendwo in der Datei etwas einfügen willst, mußt Du zwangsläufig die ganze Datei neu schreiben.
Anscheinend willst Du _nach_ der ersten Zeile, welche "<!--begin-->" _enthält_ einfügen.[1]
Jetzt hast Du zwei Möglichkeiten, entweder Du fügst bereits beim Lesen ein, oder aber erst beim Schreiben:
1.)
open(IN,$outfile) or die "aufmochn get nix";
while(<IN>)
{
push @lines,$_;
push @lines,$eintrag if /<!--begin-->/;
}
close IN;
open(OUT,">$outfile");
print OUT,@lines;
close OUT;
2.)
open(IN,$outfile) or die "aufmochn get nix";
@lines = <IN>;
close IN;
open(OUT,">$outfile");
foreach (@lines)
{
print;
print $eintrag if /<!--begin-->/;
}
close OUT;
Welche der beiden Varianten gewählt wird, ist eigentlich egal. Die erstere braucht geringfügig mehr Speicher, solange der neue Eintrag nicht riesig ist, hat aber den Vorteil, daß die Daten eventuell bereits für eine Weiterbearbeitung dem neuen Dateiinhalt entspricht, und daher auch keine Sonderbehandlung für die eventuelle Ausgabe zum Client nötig ist.
Natürlich kann das alles auch anders geschrieben werden, aber ich denke so ist es durchaus auch perlish:-)
Grüße
Klaus
[1] Das bedeutet aber nicht, daß in dieser Zeile nur "<!--begin-->" steht, aber das wäre jetzt Haarspalterei, ich möchte nur darauf hingewiesen haben.
[...]
also, wieso wird hier die gaestebuch.html mit dem Eintrag ueberschrieben, statt den Gaestebucheintrag hinter das <!--begin-->
for ($i=0;$i<=$SIZE;$i++) {
$_=$LINES[$i];
if (/<!--begin-->/) {
Dieser reguläre Ausdruck prüft nur, ob <!--begin--> vorhanden ist. Wenn ja, wird sofort losgeschrieben.
print OUTFILE "
hallo,
Moment, damit wir nicht aneinander vorbeireden: Mit sofort losschreiben meine ich nciht an der Stelle, an der eine Übereinstimmung mit dem Muster gefunden wurde. Die Stelle mit der Musterübereinstimmung ist Perl gar nicht bekannt! Du müsstest wenn schon den s-Operator anstatt dem m-Operator benutzen. Wenn du einen Regex aufbaust, ohne ein m vornedran zu stellen, denkt sich Perl einfach eines dazu. Du benutzt also m. Natürlich ist es mit m möglich, $_ zu ändern.
und genau das macht es eben nicht - ich kapiere einfach nicht wieso
hier:
open(OUTFILE, ">$outfile") or die "\Datei $outfile konnte nicht geoeffnet werden\n";
flock(OUTFILE, LOCK_EX) or die "\Cannot lock $outfile\n";
Lass mal kurz die Lock()-erei. Befassen wir uns mit der zu lesenden Datei und schreiben wir (bis alles klappt) auf STDOUT!
for ($i=0;$i<=$SIZE;$i++) {
$_=$LINES[$i];
if (/<!--begin-->/) {
Ich hab da eine Alternative im Sinn. Wie wäre es denn mit map()? Schön perlig, ne?
@zeilen = map {
if ( m(<!--begin-->) ){
&eintrag
.$_;
} else {
$_
}
} (<INFILE>);
print <STDOUT> @zeilen;
print <OUTFILE> map {
if ( m(<!--begin-->) ){
&eintrag
.$_;
} else {
$_
}
} (<INFILE>);
So viel Code auf so wenig Raum kann aber schnell in die Hose gehen. Am besten lässt du es in kleinen Portiönchen. Die passen gut in jeweils eine Subroutine.
die frage bleibt aber, wieso mit Hilfe von >$outfile die .html datei ersetzt wird obwohl die eintraege eben erst ab dem begin eingesetzt werden sollten
Nochmal: Perl hat sich die Stelle mit der Musterübereinstimmung nicht gemerkt und beachtet Sie folglich nicht, während du $_ manipulierst.
Noch ein Tipp: öffne die Datei (anders als in Selfhtml beschrieben) ohne >, >> oder < am Anfang! Einfach open( "DATEI", "./$dateiname"); Dann ist sie zugleich zum Lesen und Schreiben offen, und $_ lässt sich besser "kneten".
Gruß Fokuhila
P.S. den "Anschiss" nehm ich zurück, falls das noch geht.
hi!
Ich hab da eine Alternative im Sinn. Wie wäre es denn mit map()?
Schön perlig, ne?
Als perlig würde ich das nun nicht unbedingt bezeichnen... ;)
@zeilen = map {
if ( m(<!--begin-->) ){
&eintrag
.$_;
} else {
$_
}
} (<INFILE>);
Wieso keine bedingte Zuweisung? Ist doch viel hübscher (und perliger
als obiges):
@zeilen = map { (/<!--begin-->/) ? &eintrag.$_ : $_; } <INFILE>;
print <STDOUT> @zeilen;
print STDOUT @zeilen;
print <OUTFILE> map {
print OUTFILE map {
Noch ein Tipp: öffne die Datei (anders als in Selfhtml
beschrieben) ohne >, >> oder < am Anfang! Einfach open( "DATEI",
"./$dateiname"); Dann ist sie zugleich zum Lesen und Schreiben
offen, und $_ lässt sich besser "kneten".
Nein, perldoc -f open:
[...]
If MODE is "'<'" or nothing, the file is opened for input.
[...]
bye, Frank!
hi!
Ich hab da eine Alternative im Sinn. Wie wäre es denn mit map()?
Schön perlig, ne?
Als perlig würde ich das nun nicht unbedingt bezeichnen... ;)
@zeilen = map {
if ( m(<!--begin-->) ){
&eintrag
.$_;
} else {
$_
}
} (<INFILE>);
Wieso keine bedingte Zuweisung? Ist doch viel hübscher (und perliger
als obiges):
@zeilen = map { (/<!--begin-->/) ? &eintrag.$_ : $_; } <INFILE>;
Das ist in der Tat schicker. Man sollte das aber ein Bischen auf die Streckbank legen, finde ich:
@zeilen = map {
(/<!--begin-->/) ?
&eintrag.$_ :
$_
} (<INFILE>);
Man sollte
@zeilen = map {
if ( m(<!--begin-->) ){
&eintrag
.$_;
} else {
$_
}
} (<INFILE>);
gelesen haben, um
@zeilen = map { (/<!--begin-->/) ? &eintrag.$_ : $_; } <INFILE>;
zu verstehen.
[…] Einfach open( "DATEI", "./$dateiname"); Dann ist sie
zugleich zum Lesen und Schreiben offen, […].
Nein, perldoc -f open:
[...]
If MODE is "'<'" or nothing, the file is opened for input.
[...]
Ok, Irrtum vom Amt.