#!/usr/bin/perl # #CGI schreibt in temp file und versendet eintagungs E-Mail # # # #lindenstrasse ############################################################################ # # (c) Markus Wolf, 1998 # ############################################################################ # # guests.cgi # COPYRIGHT NOTICE # Copyright 1998 Markus Wolf # All Rights Reserved. # EMail: perl@perl-archiv.de # URL : http://www.perl-archiv.de # # guests.cgi darf von jedermann kostenlos benutzt und geändert werden, solange # dieser Copyright-Verweis und die restlichen Kommentare erhalten bleiben. Mit # dem Einsatz dieses Skripts akzeptieren Sie, daß Markus Wolf von jeglicher # Haftung und Gewährleistung hinsichtlich des Einsatzes befreit ist. # # Der Verkauf dieses Skripts, auch in modifizierter Form, ist ohne vorherige # Absprache ausdrücklich untersagt. # (Mit anderen Worten: Bitte fragen Sie mich, bevor Sie versuchen, mit meinem # Skript Geld zu verdienen.) # # Um dieses Skript über das Internet oder irgendein anderes Medium # weiterzuverbreiten, benötigen Sie vorher meine Erlaubnis. In jeden Fall # müssen der Copyright-Verweis und die restlichen Kommentare erhalten bleiben. # ############################################################################ # # -Adminmodus zum Löschen von Einträgen # -FileLocking # -keine Reloadmöglichkeit # -Eingabenpüfung # -Design der Einträge über Schablone # -Seitenweise Anzeige (unterschreitet nie den angegebenen Wert, dh auf # der letzten Seite erscheinen mind. die in der $anzan angegebenen # Einträge, die Anzahl der vorherigen Seiten wird über den Modulo # berechnet. Es steht also nie nur ein einzelner Eintrag auf einer # Seite. Ist gerade für mein Layout wichtig. # # -Mehr fällt mir nun nicht mehr ein. Für Anregungen bin ich aber # jederzeit offen. # ########################################################################### # # Bitte nicht vergessen mir # die URL durchzugeben, wo das Script läuft. # # Einbindung : http://mein.server.de/guests.cgi?show ODER # http://mein.server.de/guests.cgi # # Löschenmod : http://mein.server.de/cgi-bin/guests.cgi?admin # # Ein Datenfile muß nicht bestehen. Wird mit dem ersten Eintrag # angelegt. # ############################################################################ # # Bei Problemen oder Anpassungen helfe ich gerne, aber zuerst mal die # FAQ auf meiner Seite anschauen und die Anleitung genau durchlesen. # ############################################################################ #Ermittlung und Wechsel in das aktuelle Verzeichnis (CGI) $base_dir = rindex ($0, "\\") ; $base_dir = rindex ($0, "/") if ($base_dir < 0) ; $script_dir = substr( $0, 0, $base_dir) ; chdir($script_dir) ; ############################################################################ #Variablendefinition ############################################################################ #Ausgabepuffer auschalten, Ausgabe beginnt sofort, nicht erst nach #Beendigung des Scripts $| = 1 ; #Datenverzeichnis für CGI (ausgehend vom CGI-Verzeichnis) $data_dir = "./data" ; #Gästebuch-Datenfile $dat_file = "$data_dir/gaeste.txt" ; $dat_file1 = "$data_dir/gaeste_tmp.txt" ; #Schablone für das HTML-Design der Einträge $html_templ = "$data_dir/gast.tmpl" ; #Name und WWW-Adresse des GÄSTEBUCH-Scriptes $cgi_www="http://18uhr40.de/guests1/guests.cgi" ; #Grafikpfad-absolut (URL) $pic_dir="http://18uhr40.de/guests1/pics" ; #Schriftart $font = "Verdana,Arial,Helv" ; #Titel des Gästebuches $title="18Uhr40 Lindenstraßen Gästebuch" ; #Anzeige pro Seite (alles auf eine Seite: 100000 :-)) ) $anzen=30 ; $anzan=$anzen ; #max. Länge (in Zeichen)für Gästebucheintrag (0 für keine Begrenzung) $max_length=100 ; #Restanzeigeberechnung, dh die in $anzen spezifierte Anzahl #pro Seite wird mind. eingehalten, dh ist von Vorteil, wenn #man nicht möchte, da zB auf der letzten Seite nur ein Eintrag #steht. Man allerdings fast keinen Einfluß auf die angezeigte #Menge. ZB werden bei $anzen=20 erst ab dem 40 Eintrag 2 Seiten #angezeigt. (1=ja / 0=nein) $rest_show=1 ; #File-Locking 0 für nein (WinXX)/1 für ja $lock=1 ; #Zeitverschiebung in Stunden (-/+ möglich) $zeitverH=0 ; #Mail an Admin bei neuem Eintrag #1=ja / 0=nein $adminmail=1 ; #Für Mailfunktion #0=Mail verschicken per sendmail #1=Mail in Datenverzeichnis schreiben $offline=0 ; #Mailprogramm (nur Unix) #$mailprog = "/usr/sbin/exim" ; $mailprog = "/usr/sbin/sendmail" ; #Mailempfänger $webmaster = "gaestebuch\@18uhr40.de" ; #Paßwort für den Admin(Lösch)modus (unbedingt ändern) $pw = "hvbijkpjigtzrtzgjbknliz876876e54gvjbl" ; ############################################################################ #Programmablauf ############################################################################ @para = split(/&/ , $ENV{'QUERY_STRING'}) ; $para[0]="" if !$para[0] ; $para[1]=0 if !$para[1] ; if ($para[0] eq "show" || $para[0] eq "admin") { &read_data() ; &htmlhead ; &show($para[1]) ; &htmlfoot ; } elsif ($para[0] eq "form") { &read_data() ; &htmlhead ; &sign_form() ; } elsif ($para[0] eq "new") { &datum_zeit() ; &new() ; print "Location: $cgi_www?show\n\n" ; } elsif ($para[0] eq "del") { &del() ; print "Location: $cgi_www?show&$FM{'showid'}\n\n" ; } elsif ($para[0] eq "redir") { &redir() ; } else { &read_data() ; &htmlhead ; &show('0') ; &htmlfoot ; } ############################################################################ # Unterprogramme ############################################################################ ############################################################################ #Datendatei einlesen #Bei dieser Art der Anzeige arbeite ich nicht sequentiell, dh daß das #ganze Datenfile eingelesen und dann verarbeitet wird. Bei vielen #virtuellen Servern ist ein CGI-Wrapper installiert, der den Speicher #pro CGI-Script auf eine bestimmte Größe beschränkt (zB 500kb), daher #arbeitet das Gästebuch bei einer Größe von über zB 500kb nicht mehr. #Auskunft gibt hierüber der Provider. ############################################################################ sub read_data { my @guest_set ; my $line ; open (DAT , "<$dat_file") ; while ($line=) { push ( @guest_set , $line ) ; } close(DAT) ; foreach $line (@guest_set) { push ( @guest , [ split(/\|/ , $line) ] ) ; } #Umkehrung der Reihenfolge @guest=reverse @guest if ($para[0] ne "del") ; #Anzahl der Einträge $guests = $#guest+1 ; #Berechnung der Anzeigeanzahl &rest_show if ($rest_show==1) ; } ############################################################################ #Ausgabe der Einträge #Hier wird die Anzeige der einzelnen Einträge gesteuert. Das Aussehen eines #Eintrages wird über die beiliegende Schablone gesteuert. ############################################################################ sub show { my $anzeige_von=$_[0] ; my $x=0 ; my @html ; my $html="" ; my $html_tmp="" ; open (HTML , "<$html_templ") ; @html= ; close(HTML) ; $html = join(/ / , @html) ; #Admin-Modus print "
" if ($para[0] eq "admin") ; #Ausgabe der Einträge: #Hier kann das Design der einzelnen Einträge geändert werden for $x ($anzeige_von .. $anzeige_von+$anzan-1) { $html_tmp=$html ; last if($x == $guests) ; if($guest[$x][4] =~ /http:\/\/.*\./) { $hp="$guest[$x][4]"; } else { $hp=""; } if($guest[$x][2] =~ /.*\@.*\..*/) { $em="$guest[$x][2]"; } else { $em=""; } if ($para[0] eq "admin") { $html_tmp =~ s// /ig ; } $html_tmp =~ s//$guest[$x][1]/ig ; $html_tmp =~ s//$guest[$x][3]/ig ; $html_tmp =~ s//$em/ig ; $html_tmp =~ s//$hp/ig ; $html_tmp =~ s//$font/ig ; $html_tmp =~ s//$guest[$x][5]/ig ; $html_tmp =~ s//$pic_dir/ig ; print $html_tmp ; } #Admin-Modus print "
Paßwort:     

" if ($para[0] eq "admin") ; } ############################################################################ #Neuer Eintrag #Hier wird der neue Einrag aus dem Formular ausgelesen und auf #Sonderzeichen gecheckt. Es wird nur eine Leerzeile erlaubt, die anderen #werden rausgeworfen. HTML-Tags werden als solche (nachher #sichtbar) geschrieben. Geprüft wird auf die Felder NAME und #KOMMENTAR. ############################################################################ sub new { my $guest="" ; my $buffer="" ; my @paare="" ; my $paar="" ; my $val1="" ; my $val2="" ; my $key="" ; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @paare = split(/&/, $buffer); foreach $paar (@paare){ ($val1, $val2) = split(/=/, $paar); $val1 =~ tr/+/ /; $val1 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $val2 =~ tr/+/ /; $val2 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $val2 =~ s/<([^>]|\n)*>/ /g; $FM{$val1} = $val2; } if ((!$FM{'name'} || !$FM{'com'}) || ($FM{'com'} && length($max_length)>$max_length && $max_length > 0 )) { &er_form() ; } else { foreach $key (keys %FM) { $FM{$key} =~ s/\&/\&\;/g; $FM{$key} =~ s/"/\"\;/g; $FM{$key} =~ s/\cM\n/
/g; $FM{$key} =~ s/\n\cM/
/g; $FM{$key} =~ s/\cM/
/g; $FM{$key} =~ s/\n/
/g; $FM{$key} =~ s/\s+/ /g; $FM{$key} =~ s/\s+/ /g; $FM{$key} =~ s/^\s+//g; $FM{$key} =~ s/\s+$//g; } $guest = "$datsort\|$FM{'name'}\|$FM{'email'}\|$FM{'com'}\|$FM{'url'}\|$ndate\|" ; open (DATNEW , ">>$dat_file1") ; &LockFile(DATNEW); print DATNEW "$guest\n" ; close (DATNEW) ; &send_mail() if $adminmail==1 ; } } ############################################################################ #Fehlerausgabe bei nicht ausgefüllten Feldern des Formulars #Sollten nicht alle notwendigen Felder (Name, Kommentar) ausgefüllt #werden, wird das Formular geladen und mit einer Fehlermarkierung an #den fehlenden Feldern wieder ausgegeben. WICHTIG - die Kommentare #innerhalb des HTML-Formulars müssen für diese Funktion drinbleiben ############################################################################ sub er_form { #Hier kann man die Markierung der fehlenden Felder angeben, kann auch eine Grafik sein my $errmark=" X<\/b><\/font> " ; $x_hinweis = "Ihr müßt mindestens die mit einem $errmark markierten Felder ausfüllen." ; $x_name = $errmark if (!$FM{'name'}) ; $x_text = $errmark if (!$FM{'com'}) ; $x_laenge = "Maximal zulässige Länge von $max_length Zeichen überschritten!
 
" if (length($FM{'com'}) > $max_length && $max_length>0) ; &read_data() ; &htmlhead ; &sign_form() ; exit ; } ############################################################################ #Löschen eines Eintrages im Adminmodus #Über den Admin-Aufruf mit dem Parameter ADMIN, können einzelne #Einträge gelöscht werden. -> dies ist die Löschfunktion ############################################################################ sub del { my $buffer="" ; my @paare="" ; my $paar ; my $val1 ; my $val2 ; my $x=0; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @paare = split(/&/, $buffer); foreach $paar (@paare){ ($val1, $val2) = split(/=/, $paar); $val1 =~ tr/+/ /; $val1 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $val2 =~ tr/+/ /; $val2 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $FM{$val1} = $val2; } if ($FM{'pw'} eq $pw && $FM{'del'}) { &read_data() ; open (DAT , "> $dat_file") ; &LockFile(DAT); for $x (0...$guests-1) { if ($FM{'del'} ne $guest[$x][0]) { print DAT "$guest[$x][0]|$guest[$x][1]|$guest[$x][2]|$guest[$x][3]|$guest[$x][4]|$guest[$x][5]|\n" ; } } close(DAT) ; } #Für den Fall, dass das Script einfach mit DEL aufgerufen wird $FM{'showid'}="0" if !$FM{'showid'} ; } ############################################################################ #Ausgabe des HTML-Kopfes #incl. der Drop-Liste für die schnelle Erreichung der Eintragsseiten. ############################################################################ sub htmlhead { my $ix=0 ; my $ix2=0 ; my $ix3=0 ; print "Content-Type: text/html\n\n" ; print <<"EOM"; $title
18Uhr40.de Logo
Lindenstraßen Vorschau auf http://18Uhr40.de
 
$title
 
EOM } ############################################################################ #Ausgabe des HTML-Fusses #incl. seitenweise Anzeige der Einträge. Die Anzahl pro Seite kann über #den Parameter $anzan am Beginn gesteuert werden. ############################################################################ sub htmlfoot { my $anzeige_zurueck = $para[1]-$anzan ; my $anzeige_weiter = $para[1]+$anzan ; my $anzeige_von = $para[1]+1 ; my $anzeige_bis = $para[1]+$anzan ; print <<"EOM" ;
EOM if($anzeige_zurueck >= 0) { if ($para[0] eq "admin") { print <<"EOM" ; Vorherige $anzan ... EOM } else { print <<"EOM" ; Vorherige $anzan ... EOM } } else { print <<"EOM" ;   EOM } if ($anzeige_weiter>$guests) { $anzeige_bis=$guests ; } print <<"EOM" ; $anzeige_von-$anzeige_bis \| $guests Einträge EOM if($anzeige_weiter<$guests) { if ($para[0] eq "admin") { print <<"EOM" ; Nächste $anzan ... EOM } else { print <<"EOM" ; Nächste $anzan ... EOM } } else { print <<"EOM" ;   EOM } print <<"EOM" ;


  EOM exit; } ############################################################################ #Bestimmung des aktuellen Datums und der Uhrzeit für den Eintrag #Diese Form der Ermittlung ist Jahr 2000 fähig ($year = 1900+$year). #Über den Parameter $zeitverH kann eine Zeitverschiebung für US-Server #eingegeben werden. ############################################################################ sub datum_zeit { my $time = time; my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($time+($zeitverH*3600)); $mon = $mon+1; if ($min < 10) { $min = "0$min"; } if ($hour < 10) { $hour = "0$hour"; } if ($mon < 10) { $mon = "0$mon"; } if ($mday < 10) { $mday = "0$mday"; } $year = 1900+$year; $ndate1 = "$mday.$mon.$year "; $ndate = $ndate1."- $hour\:$min"; $datsort = "$year$mon$mday$hour$min$sec" ; } ############################################################################ #File-Sperre #für gemeinsamen File-Zugriff #->nur Unix ############################################################################ sub LockFile { local(*DATEI=@_) ; if ($lock==1) { flock(DATEI,2); } } ############################################################################ #Admin-Mail verschicken #Auf Wunsch wird dem Admin eine Mail mit dem neuen Gästebucheintrag #geschickt. Die Steuerung erfolgt über einen Parameter an Anfang des #Scripts -> $offline und $adminmail # #Geht nur mit Unix, für NT ist diese Form nur bedingt geeignet. #Es gibt zwar 1:1 Umsetzungen des Unix-Sendmails für NT, diese #werden aber nur sehr sehr selten eingestzt, da sie im Vergleich zu #BLAT etwas kosten. ############################################################################ sub send_mail { if($offline==1) { open(MAIL,">$data_dir/mail.txt") ; } else { open(MAIL,"|$mailprog -t") ; } print MAIL "To: $webmaster\n"; #print MAIL "From: $FM{'email'} ($FM{'name'})\n"; print MAIL "From: gaestebuch\@18uhr40.de \n"; print MAIL "Subject: neuer Lindenstrasse Gaestebuch-Eintrag\n\n"; print MAIL "------------------------------------------\n"; print MAIL "$FM{'name'}\n"; #print MAIL "$FM{'email'}\n"; #print MAIL "$FM{'url'}\n"; print MAIL "$ndate\n"; print MAIL "------------------------------------------\n"; print MAIL "$FM{'com'}\n"; print MAIL "------------------------------------------\n"; print MAIL "Eintragen unter:\n"; print MAIL "http://18uhr40.de/cgi-bin/eintragen.cgi\n"; #print MAIL "\n"; print MAIL "Austragen unter:\n"; print MAIL "http://18uhr40.de/cgi-bin/austragen.cgi\n"; #print MAIL "------------------------------------------\n"; print MAIL "Eintragen/Austragen unter:\n"; print MAIL "http://18uhr40.de/gast.htm\n"; print MAIL "------------------------------------------\n"; print MAIL "IP-Adresse:\t\t\"$ENV{'REMOTE_ADDR'}\"\n"; print MAIL "Der verwendete Browser: $ENV{'HTTP_USER_AGENT'}"; print MAIL "------------------------------------------\n"; close (MAIL); } ############################################################################# #Berechnung der tatsächlichen Anzeige pro Seite (rekursive Funktion - hier #nur etwas ändern, wenn man genau weis, was das für Auswirkungen haben #kann. Unter Umständen kann man damit den Rechnung abschissen!) ############################################################################# sub rest_show { if ( $guests%$anzan < $anzen && $guests >= $anzan) { $anzan++ ; &rest_show() ; } } ############################################################################# #Ausgabe des Eintragsformulares ############################################################################# sub sign_form { $FM{'url'}="http://" unless $FM{'url'} ; $FM{'com'} =~ s/\n//g ; $x_hinweis="" if ($FM{'name'} && $FM{'com'}) ; print <<"EOM" ; Hier könnt Ihr Euch in meinem Gästebuch verewigen.



EOM if ($x_hinweis) { print <<"EOM" ; EOM } print <<"EOM" ;

 Fehler:
 
  $x_hinweis
 Name: $x_name
 Text:
$x_text
$x_laenge




  EOM } ############################################################################# # Umleitung ############################################################################# sub redir { my $link=shift ; read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'}); @paare = split(/&/, $buffer); foreach $paar (@paare){ ($val1, $val2) = split(/=/, $paar); $val1 =~ tr/+/ /; $val1 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $val2 =~ tr/+/ /; $val2 =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $val2 =~ s/<([^>]|\n)*>/ /g; $FM{$val1} = $val2; } $link=$FM{'links'} ; print "Location: $link\n\n"; } ############################################################################# # ENDE #############################################################################