#!/usr/bin/perl

############################################################################
#
#   (c) Philip Chinery, 2001
#
############################################################################
#
# guestbook.pl 1.2
# COPYRIGHT NOTICE                                                           
# Copyright 2001 Philip Chinery     
# All Rights Reserved.                     
# eMail: philip@chinery.de 
# URL  : http://www.sector7g.de.vu                                        
#                                                                            
# Das Gästebuch darf von jedem kostenlos benutzt und geändert werden, solange
# dieser Copyright-Verweis und die restlichen Kommentare erhalten bleiben. Mit
# dem Einsatz dieses Skripts akzeptieren Sie, daß Philip Chinery 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.
#
############################################################################
#
# In diesem Script muß normalerweise nichts geändert werden.
#
############################################################################

require "settings.pl";

##############################################
#
# ToDo: Admin Konfiguration per WebInterface
# Badword Filter, Duplikate finden, Autowrap
# PageBar, Umlaute codieren
#
##############################################

$admin = 0;
$passwd = &GetPasswd;

my @entry;
my $num_entries;
my $first_entry;
my $page;
my @data;
my $content;
my $fix_entries_per_page = $entries_per_page;

# Flock detection.
# Flock is not supported by Windows Machines.
my $useflock = 1;
if ($ENV{"OS"} =~ /Windows/gi) {$useflock = 0;}

my @template = &ReadTemplate("page.htmlt");
my $glob_tmpl = "@template";

&GetFormInput;

if ($field{'passwd'})
{
    if (&CheckPasswd($field{'passwd'}))
    {
        $admin = 1;
    }
    else
    {
    	print "Content-type: text/html\n\n";
    	print "Falsches Passwort:$field{'passwd'}";
    	
    	exit 0;
    }
}
	
if ($field{'cwrite'})
{
    $cwrite = $field{'cwrite'} ;	 
    $Name = $field{'Name'} ;	 
    $EMail = $field{'EMail'} ;	 
    $Homepage = $field{'Homepage'} ;	 
    $Text = $field{'Text'} ;
    $ip = $ENV{'REMOTE_ADDR'};
    $time = &GetTimeSpec;

    &CheckForm;
    
    &SaveData;
	
    $page = 1;
	$first_entry = 1 + (($page-1) * $entries_per_page);
	$content = &ShowEntries;
	&ShowPage ("$content", 1);
}
elsif ($field{'action'} eq "submit")
{
    &PrintSubmitForm
}

elsif ($field{'action'} eq "view")
{
    $page = $field{'page'};
	$first_entry = 1 + (($page-1) * $entries_per_page);
	$content = &ShowEntries;
    &ShowPage ("$content");
}

elsif ($field{'action'} eq "admin")
{
    &ShowLoginForm;
}

elsif ($field{'action'} eq "changepasswd")
{
	&QueryChangePasswd($field{'passwd'});
}

elsif ($field{'action'} eq "execchangepasswd")
{
	&ChangePasswd($field{'old_passwd'}, $field{'new_passwd1'});
}

elsif ($field{'action'} eq "delete")
{
	&QueryDeleteEntry($field{'entry'}, $field{'passwd'});
}

elsif ($field{'action'} eq "execdelete")
{
	&ChangeEntry($field{'entry'}, "delete")
}

elsif ($field{'action'} eq "comment")
{
	&QueryCommentEntry($field{'entry'}, $field{'passwd'});
}

elsif ($field{'action'} eq "writecomment")
{
	&ChangeEntry($field{'entry'}, "comment", $field{'Comment'})
}

else
{
	$page = 1;
	$first_entry = 1 + (($page-1) * $entries_per_page);
	$content = &ShowEntries;
	&ShowPage ("$content");
}

###############################################################################
##
##  Begin Subroutines
##
###############################################################################

sub ChangeEntry
{
	my $di = 0;
	my @emptyarray;
	my @tarray;
	my @temparray;
	
	&GetData("norev");

    $entry_nr = $_[0] - 1; #$num_entries - ($_[0]);
	if ($_[1] eq "delete"){$num_entries--;}

	foreach $entryline (@data)
	{
	if ($di != $entry_nr)
	{
    	push (@tarray,$entryline)
	}
	else
	{
	if ($_[1] eq "comment")
	{
	   @entry = split /\|/, $entryline;
       $_[2] =~ s/\n/&nbsp;<br>/g;
       $_[2] =~ tr/|/ /;
	   $entry[$field_comment] = "$_[2]\n";
	   $entryline = join "\|", @entry;
	   $entryline = $entryline;
       push (@tarray,$entryline)
	}
	}
	
	$di++;
	}
	
	@data = @tarray;
	@tarray = 0;
	
	&SaveAll;

	for ($i = $#data ; $i >= 0; --$i)
	{
	push @temparray, $data[$i];
	}
	
	@data = @temparray;
	
    $page = 1;
	$first_entry = 1 + (($page-1) * $entries_per_page);
	$content = &ShowEntries(1);
	&ShowPage ("$content");
}

sub QueryChangePasswd
{
    my $adminline1 = "";
    my $adminline2 = "";
    my $adminline3 = "";

	$adminline1 = "Passwort ändern:";
	
	$adminline2 .= "<input type=hidden name=\"action\" value=\"execchangepasswd\"><input type=hidden name=\"entry\" value=\"$_[0]\"><input type=hidden name=\"passwd\" value=\"$_[1]\">";
	$adminline2 .= "<table><tr><td width=98><font size=-1>Altes Passwort:</font></td><td><input type=password name=\"old_passwd\"></td></tr><tr><td><font size=-1>Neues Passwort:</font></td><td><input type=password name=\"new_passwd1\"></td></tr><tr><td><font size=-1>Wiederholung:</font></td><td><input type=password name=\"new_passwd2\"></tr></table>";
	
	$adminline3 = "<input value=\"Abschicken\" type=submit name=\"submit\">";
	
	&ShowAdminPage($adminline1, $adminline2, $adminline3);
}

sub QueryDeleteEntry
{
	my $adminline1 = "";
    my $adminline2 = "";
    my $adminline3 = "";

	$adminline1 = "Eintrag löschen:";
	
	$adminline2 = "Soll der Eintrag $_[0] wirklich gelöscht werden?";
	
	$adminline3 = "<a href=\"$guestbook_name?action=execdelete&entry=$_[0]&passwd=$_[1]\" class=link2>Ja</a>&nbsp;&nbsp;<a href=\"$guestbook_name?passwd=$_[1]\" class=link2>Nein</a>";
	
	&ShowAdminPage($adminline1, $adminline2, $adminline3);
}

sub QueryCommentEntry
{
    my $adminline1 = "";
    my $adminline2 = "";
    my $adminline3 = "";

	$adminline1 = "Kommentar eingeben:";
	
	$adminline2 .= "<input type=hidden name=\"action\" value=\"writecomment\"><input type=hidden name=\"entry\" value=\"$_[0]\"><input type=hidden name=\"passwd\" value=\"$_[1]\">";
	$adminline2 .= "Kommentar: <textarea rows=6 cols=40 name=\"Comment\" wrap=physical></textarea>";
	
	$adminline3 = "<input value=\"Eintragen\" type=submit name=\"submit\">";
	
	&ShowAdminPage($adminline1, $adminline2, $adminline3);
}

sub ShowLoginForm
{
    my $adminline1 = "";
    my $adminline2 = "";
    my $adminline3 = "";

	$adminline1 = "Passwort eingeben:";
	
	$adminline2 .= "Passwort: <input type=\"password\" name=\"passwd\">";
	
	$adminline3 = "<input value=\"Absenden\" type=submit name=\"submit\">";
	
	&ShowAdminPage($adminline1, $adminline2, $adminline3);
}

sub SaveAll
{
    unless(open (DATA, "> $data_file")) { &ShowError("$data_file"); };
	
	if ($useflock)
    {
        flock(DATA, 2) ;
        seek(DATA, 0, 2) ;
    }
    foreach $line (@data)
	{
    print DATA "$line" ;
    }
	if ($useflock) { flock(DATA, 8) ; }
    close (DATA) ;
}

sub CheckPasswd
{
	#$_[0] = "geheim";	
	my $enc_pass = $_[0];

	if (substr($passwd,0,2) ne substr($_[0],0,2))
	{
	$enc_pass = crypt($_[0], $passwd); #substr($passwd,0,2));
	}
	#print "Content-type: text/html\n\n";
	#print "pass:$passwd\n$enc_pass\n$_[0]\n";
	if ($enc_pass eq $passwd)
	{
	return 1;
	}
	else
	{
	return 0;
	}
}

sub GetPasswd
{
    my @admin_pass = &ReadTemplate("../../passwd.txt");
	return $admin_pass[0];
}

sub ChangePasswd
{
    $new_passwd = crypt($_[1], substr($passwd,0,2));
	$passwd = $new_passwd;
    unless(open(PASS,">passwd.txt")) { &ShowError("passwd.txt"); };
    if ($useflock)
    {
        flock(PASS, 2) ;
        seek(PASS, 0, 2) ;
    }
    print PASS "$new_passwd";
    if ($useflock){flock(PASS, 8);}
    close(PASS);
	print "Location:$guestbook_name?passwd=$new_passwd \n\n";
}

sub ShowAdminPage
{
	my @template = &ReadTemplate("admin.htmlt");
    
	foreach $row (@template)
	{
    	$row =~ s/\[ADMINLINE1\]/$_[0]/g;
    	$row =~ s/\[ADMINLINE2\]/$_[1]/g;
    	$row =~ s/\[ADMINLINE3\]/$_[2]/g;
	}
 print "Pragma: no-cache\n";
 print "Expires: now\n";
 print "Content-type: text/html\n\n";
	print "@template";
	
}

sub ShowPage
{
    my $body = $_[0];
    my $pagetmpl = $glob_tmpl;
	my $row;
	my $admin_data;
	my $start_backlink;
	my $end_backlink;
	my $start_nextlink;
	my $end_nextlink;
	
	if ($page == 1)
	{
    	$start_backlink = "";
    	$end_backlink = "";
	}
	else
	{
    	if ($admin){
		$start_backlink = "<a href=\"$guestbook_name?action=view&passwd=$passwd&page=".($page - 1)."\" class=link1>";
		}
		else{
		$start_backlink = "<a href=\"$guestbook_name?action=view&page=".($page - 1)."\" class=link1>";
		}
    	$end_backlink = "<\/a>";
	}
	
	$entrymax = ($page * $fix_entries_per_page) + 1;
	if (($num_entries >= $entrymax) && ($entrymax >= 0))
	{
    	if ($admin){
		$start_nextlink = "<a href=\"$guestbook_name?action=view&passwd=$passwd&page=".($page + 1)."\" class=link1>";
		}
		else{
		$start_nextlink = "<a href=\"$guestbook_name?action=view&page=".($page + 1)."\" class=link1>";
		}
    	$end_nextlink = "<\/a>";
	}
	
    $pagetmpl =~ s/\[GBNAME\]/$guestbook_title/g;
    $pagetmpl =~ s/\[NUMENTRIES\]/$num_entries/g;
	$pagetmpl =~ s/\[SUBMITHREF\]/$guestbook_name\?action=submit/g;
	$pagetmpl =~ s/\[PAGENUMBER\]/$page/g;
	$pagetmpl =~ s/\[STARTBACKLINK\]/$start_backlink/g;
	$pagetmpl =~ s/\[ENDBACKLINK\]/$end_backlink/g;
	$pagetmpl =~ s/\[STARTNEXTLINK\]/$start_nextlink/g;
	$pagetmpl =~ s/\[ENDNEXTLINK\]/$end_nextlink/g;
	if ($_[1]){$pagetmpl =~ s/\[THANXMSG\]/$thanx_msg/g;}
	else {$pagetmpl =~ s/\[THANXMSG\]/\&nbsp;/g;}
	if ($admin){
	$admin_data = "<br><a href=$guestbook_name?action=changepasswd&passwd=$passwd class=link1>Passwort ändern</a>";
	}
	$pagetmpl =~ s/\[ADMINDATA\]/$admin_data/g;
	
	$pagetmpl =~ s/\[DATA\].*?\[ENDDATA\]/$body/s;
	
 print "Pragma: no-cache\n";
 print "Expires: now\n";
 print "Content-type: text/html\n\n";
	print "$pagetmpl";
}

sub ShowEntries
{
    if (!$_[0])
	{
	&GetData;
	}
    
	my $i;
	my $rev_i;
	my $admin_bar;
	my @entry;
	my @template = &ReadTemplate("page.htmlt");
	my $tmpl = "@template";
	my $comtmpl;
	my $ttemplate;
	my $tcommenttemplate;

	$tmpl =~ s/.*\[DATA\]//s ;
	$tmpl =~ s/\[ENDDATA\].*//s ;
	
	$comtmpl = $tmpl;
	
	$comtmpl =~ s/.*\[COMMENTSPACE\]//s ;
	$comtmpl =~ s/\[ENDCOMMENTSPACE\].*//s ;

	
	if ($first_entry == 0) {$first_entry = 1};
	if (($num_entries - ($first_entry-1)) < $entries_per_page) {$entries_per_page = ($num_entries - ($first_entry-1))}
	for ($i = $first_entry ; $i < ($first_entry + $entries_per_page); ++$i)
    {
        $line=$data[$i - 1];
		chomp $line;
		
		@entry = split /\|/,$line;
		
		$ttemplate = $tmpl;
		$tcommenttemplate = $comtmpl;
		

    	$rev_i = $num_entries - $i + 1;
		$ttemplate =~ s/\[ENTRYNUMBER\]/$rev_i/g;
    	$ttemplate =~ s/\[NAME\]/$entry[$field_name]/g;
    	$ttemplate =~ s/\[EMAIL\]/$entry[$field_email]/g;
    	$datetime="";
		if ($show_time){$datetime = &GetTime($entry[$field_time]);}
    	$datetime .= " ".&GetDate($entry[$field_time]);
		$ttemplate =~ s/\[TIME\]/$datetime/g;
    	
		if ($admin)
		{
    		$admin_bar = "<a href=$guestbook_name?action=delete&entry=$rev_i&passwd=$passwd class=link2>Löschen<\/a>&nbsp;&nbsp;<a href=$guestbook_name?action=comment&entry=$rev_i&passwd=$passwd class=link2>Kommentar<\/a>";
			$ttemplate =~ s/\[IP\]/$entry[$field_ip]/g;
		}
		else
		{
			$ttemplate =~ s/\[IP\]//g;
		}
			
		$ttemplate =~ s/\[ADMINBAR\]/$admin_bar/g;
		
		if ( length( $entry[$field_homepage] ) > 9) {
		$ttemplate =~ s/\[HOMEPAGE\]/$entry[$field_homepage]/g;}
		else {
		$ttemplate =~ s/\[HOMEPAGE\]//g;}
    	
		$ttemplate =~ s/\[TEXT\]/$entry[$field_text]/g;
    	if ($entry[$field_comment])
		{
            $mycomment = $entry[$field_comment];
			$tcommenttemplate =~ s/\[COMMENT\]/$mycomment/g;
			}
		else
		{$tcommenttemplate="";		}
		$ttemplate =~ s/\[COMMENTSPACE\].*\[ENDCOMMENTSPACE\]/$tcommenttemplate/s;
		
		$content .= "$ttemplate";
    }
	return $content;
}

sub ReadTemplate
{
    my @content;
	unless(open(TEMPLATE,"<$template_dir\/$desgin_nr\/$_[0]")) { &ShowError("$template_dir\/$design_nr\/$_[0]"); }
    while(<TEMPLATE>)
    {
        push(@content,$_);
	}
    close(TEMPLATE);
	return @content;
}

sub PrintSubmitForm
{
 my @content = &ReadTemplate("submit.htmlt");
 print "Pragma: no-cache\n";
 print "Expires: now\n";
	print "Content-type: text/html\n\n";
	print "@content";
}

sub GetTime
{
    my @ltime;
	my $retval;
	
	@ltime = localtime($_[0]);
	
	if (length($ltime[1]) < 2) {$ltime[1] = "0".$ltime[1]}
	$retval = $ltime[2].":$ltime[1]";
	
	return $retval;
}

sub GetDate
{
    my @ltime;
	my $retval;
	
	@ltime = localtime($_[0]);
	$retval = "$ltime[3].".($ltime[4]+1).".".($ltime[5] + 1900);
	
	return $retval;
}

sub GetData
{
	my @array;
	my $i;

    unless(open(DATA,"<$data_file")) { &ShowError("$data_file"); }
    while(<DATA>)
    {
        $num_entries++;
        push(@data,$_);
	}
    close(DATA);

	if ($_[0] ne "norev")
	{
	for ($i = $#data ; $i >= 0; --$i)
	{
	push @array, $data[$i];
	}
	
	@data = @array;
	}
}

sub RegExps
{
    $myText = $_[0];
    if($kill_html == 1) {
    $myText =~ s/<([^>]|\n)*>//g;
	}
   
    if($kill_html == 2) {
    $myText =~ s/</&lt;/g;
    $myText =~ s/>/&gt;/g;
	}
	
    if ($kill_java) {
	$Text =~ s/<script>(.|\n)*<\/script>//g;
	}
    $myText       =~ s/\n/&nbsp;<br>/g;
    $myText       =~ tr/|/ /;
    $myText       =~ s/\t/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/g;
    $myText		=~ s/\cM//g;
    
    return $myText;
}

sub SaveData
{
    $Name = &RegExps($Name);
    $EMail = &RegExps($EMail);
    $Homepage = &RegExps($Homepage);
    $Text = &RegExps($Text);
    
    my $thisentry = "";
    
    $entry[$field_name] = "$Name";
    $entry[$field_email] = "$EMail";
    $entry[$field_homepage] = "$Homepage";
    $entry[$field_time] = time;
    $entry[$field_ip] = "$ip";
    $entry[$field_text] = "$Text";
    $entry[$field_comment] = "";
    
    unless(open (DATA, ">> $data_file")) { &ShowError("$data_file"); };
    
    if ($useflock)
    {
        flock(DATA, 2) ;
        seek(DATA, 0, 2) ;
    }
    $thisentry = join "\|", @entry;
    
    print DATA "$thisentry\n" ;
    if ($useflock) { flock(DATA, 8) ; }
    
    close (DATA) ;
    
    if ($send_admin_mail) {&SendAdminMail}
    if (($email) && ($send_user_mail)) {&SendUserMail}
}

sub CheckForm { 
    $message = "" ;
    $found_err = "" ;
    
    $errmsg = "<p>Das Feld 'Name' muss ausgefüllt werden.</p>\n" ;
    
    if ($Name eq "") {
    	$message = $message.$errmsg ;
    	$found_err = 1 ; }
    
    
    $errmsg = "<p>Na ohne Text geht es nich, ne?</p>\n" ;
    
    if ($Text eq "") {
    	$message = $message.$errmsg ;
    	$found_err = 1 ; }
    
    if ($found_err) {
    	&PrintError; }
    
    return 1 ; 
}

sub PrintError { 
    print "Content-type: text/html\n\n";
    print $message ;
    
    exit 0 ;
    return 1 ; 
}

sub GetTimeSpec { 
	$now		= time;
	$date		= localtime($now);
	
    $now = $now + (3600 * $time_offset);

    return $now; 
}

sub GetFormInput {

	(*fval) = @_ if @_ ;

	local ($buf);
	if ($ENV{'REQUEST_METHOD'} eq 'POST') {
		read(STDIN,$buf,$ENV{'CONTENT_LENGTH'});
	}
	else {
		$buf=$ENV{'QUERY_STRING'};
	}

	if ($buf eq "") {
			return 0 ;
		}

	else {
 		@fval=split(/&/,$buf);
		foreach $i (0 .. $#fval){
			($name,$val)=split (/=/,$fval[$i],2);
			$val=~tr/+/ /;
			$val=~ s/%(..)/pack("c",hex($1))/ge;
			$name=~tr/+/ /;
			$name=~ s/%(..)/pack("c",hex($1))/ge;

			if (!defined($field{$name})) {
				$field{$name}=$val;
			}
			else {
				$field{$name} .= ",$val";
				
				#if you want multi-selects to goto into an array change to:
				#$field{$name} .= "\0$val";
			}


		   }
		}
	return 1;
}

sub ShowError
{
    print "Content-type: text/html\n\n";
	print "Fehler beim öfnnen von $_[0]\n";
	exit 0;
}

sub SendAdminMail { 
    $recip = $admin_mail ;
    
    open (MAIL, "|$mail_prog -t");
    print MAIL "To: $recip\n";
    print MAIL "Reply-to: $guestbook_mail\n";
    print MAIL "From: $guestbook_mail\n";
    print MAIL "Subject: $mail_subject\n";
    print MAIL "\n\n";
    print MAIL "Hey, du hast einen neuen Gästebucheintrag:\n";
    print MAIL "Name:     ".$Name."\n";
    print MAIL "eMail:    ".$EMail."\n";
    print MAIL "Homepage: ".$Homepage."\n";
    print MAIL "\n" ;
    print MAIL "".$Text."\n" ;
    print MAIL " \n" ;
    print MAIL "------------ \n" ;
    print MAIL "http://".$ENV{"SERVER_NAME"}.$ENV{"SCRIPT_NAME"}."\n" ;
    print MAIL "\n\n";
    close (MAIL);
}

sub SendUserMail { 
    $recip = $EMail ;
    
    open (MAIL, "|$mail_prog -t");
    print MAIL "To: $recip\n";
    print MAIL "Reply-to: $guestbook_mail\n";
    print MAIL "From: $guestbook_mail\n";
    print MAIL "Subject: $thanx_msg_mail\n";
    print MAIL "\n\n";
    print MAIL "$thanx_msg_full\n" ;
    print MAIL "\n\n";
    close (MAIL);
    
    return 1 ; 
}








