#!/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=
" 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";
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.