#!/usr/bin/perl

# Guestbook program (version 1.14)
#
# Copyright 1998 Michael Chavel (chavel@aquilo.net)
# modified and extended by Alexander Mayer (mayera@in.tum.de)
# 
# You may use this program for PERSONAL, NON-PROFIT USE ONLY!
# The most recent version of this program and documentation can
# be found at http://www.aquilo.net

use 5.004;             # as written needs Perl 5.004 or later
use strict;            # enforce declarations and quoting
use CGI qw(:standard); # import shortcuts
use Fcntl qw(:flock);  # imports LOCK_EX, LOCK_SH, LOCK_NB
use Encode;

$| = 1; 

my (
    $URL, $GUESTFILE, $MAXSAVE, $PERPAGE, $BLOCKIMAGES, $CAPITALIZE,
    $TITLE, $WELCOME, $BGIMAGE, $LINKCOLOR, $BGCOLOR, $FGCOLOR, $FORMCOLOR, $ERRCOLOR,
    $HOURADJUST, $TZONE,        
    $new,                # new entry in the guestbook
    @entries,            # holds all entries
    $entry,              # one particular entry   
    $timestamp,          # date and time (adjustable for different timezones)
    $ip, $remotehost,    # IP, DNS address of message sender
    $link,               # email or URL of guest
    $formatted_message,  # message with HTML line breaks inserted
    $count,              # total number of messages
    $number,             # message being displayed   
    $page, $newpage,     # page number being displayed, new page to display
    $next, $remaining,   # number of previous messages on next page, remaining 
    $max,
    $sorry,              # error message regarding user entry
    $delete_pos,
    $add,
    $modified,
    $showemails
   );

### site defaults
$GUESTFILE = "data/guestbook/guestbook"; # name of guestbook file
$MAXSAVE = 400;                          # how many messages to save
$PERPAGE = 10;                           # how many messages per page
$BLOCKIMAGES = 1;                        # block inline images from messages
$CAPITALIZE = 1;                         # capitalize names
$TITLE = "Gästebuch";                    # page title 
$WELCOME = "Die Hall of Fame f&uuml;r Echte Helden";    # <H1>$WELCOME</H1>
$BGIMAGE = '';
$BGCOLOR = 'black';                    # overall background color
$FGCOLOR = '#eadcdc';                    # Vordergrundfarbe
$LINKCOLOR = 'red';                    # Linkfarbe
$FORMCOLOR = 'white';                  # background color for input form
$ERRCOLOR = 'red';                       # font color for error messages
$HOURADJUST = 0;                         # add this local hour 
$TZONE = 'CET';                          #  to display this time zone
#                                        #  automatically adjusts for
###                                      #  daylight savings (EST -> EDT, etc)

$delete_pos = -1;
$showemails = 0;
$add = "";
$modified = 0;
$ENV{'ENV'} = "";
$ENV{'PATH'} = "";
$ENV{'BASH_ENV'} = "";

print "Content-type: text/html\n\n";
print "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n";
print '<html><head><title>verunsicherung.de - G&auml;stebuch</title><link rel="stylesheet" media="all" type="text/css" href="/css/screen.css"><link rel="stylesheet" media="print" type="text/css" href="/css/print.css"><!--[if lte IE 6]> <style type="text/css">@import url(/css/ie6.css);</style> <![endif]--> <script src="/js/form.js" type="text/javascript"></script></head>';
print '<body><div id="headerbox"><a href="/index.html"><img
src="/layout/header.gif" alt="Notizen über die allgemeine
Verunsicherung"/></a></div><div id="menubox">';
print '<h1>aufgeschnappt</h1>
    <ul>
      <li><a href="/news">Nachrichten</a></li>
      <li><a href="/news/tourdaten.html">Konzerte</a></li>
      <li><a href="/news/tvradio.html">TV/Radio</a></li>
    </ul>
    <h1>gesammelt</h1>
    <ul>
      <li><a href="/diskografie">Alben</a></li>
      <li><a href="/diskografie/singles.html">Singles</a></li>
      <li><a href="/diskografie/videos.html">Videos</a></li>
      <li><a href="/diskografie/lieder.html">Lieder</a></li>
      <li><a href="/diskografie/keinelieder.html">Keine Lieder</a></li>
      <li><a
href="/diskografie/unreleased.html">Unveröffentlichtes</a></li>
      <li><a
href="/diskografie/compilations.html">Compilations</a></li>
      <li><a
href="/diskografie/covers.html">Coverversionen</a></li>
      <li><a
href="/diskografie/videoclips.html">Videoclips</a></li>
      <li><a href="/diskografie/suche.html">Suche in Liedtexten</a></li>
      <li><a href="/extra/disko_hilfe.html">Hilfe</a></li>
    </ul>
    <h1>geschrieben</h1>
    <ul>
      <li><a href="/biografie.html">Biografie</a></li>
      <li><a href="/faq.html">FAQ</a></li>
      <li><a href="/extra">Extra verunsichert</a></li>
    </ul>
    <h1>kommuniziert</h1>
    <ul>
      <li><a href="http://forum.verunsicherung.de">Forum</a></li>
      <li><a href="/umfrage">Umfragen</a></li>
      <li><a href="/datenautobahn.html">Links</a></li>
      <li><a
href="http://www.verunsicherung.de/gaestebuch">Gästebuch</a></li>
      <li><a href="/news/rss.xml">RSS</a>/<a href= "/news/atom.xml">Atom</a></li>
      <li><a href="http://twitter.com/_verunsicherung">Twitter</a></li>
      <li><a href="/impressum.html">Impressum</a></li>
    </ul>';
print '</div>';

print '<div id="mainbox">';

print "<h1>$WELCOME</h1>\n";

print '<p>Sendepause</p>';

exit 0;

$new = CGI->new();                         # get request
$URL = 'http://www.verunsicherung.de/gaestebuch';                # capture script URL
print '<p>Herzlich willkommen in meinem G&auml;stebuch! Hier k&ouml;nnt ';
print 'Ihr Eure Meinung &uuml;ber die Website kundtun, Kommentare zur ';
print 'EAV oder zu Gott und die Welt ablassen oder ganz einfach Euer Herz ';
print 'ausschütten. Echte Helden wissen: Die EAV hat auf jede Frage eine ';
print 'Antwort! Also keine Scheu und in das G&auml;stebuch eintragen:</p>';

spam_blacklist($new->param("name"));

if (($new->param("name") ne "") && (int($new->param("rfield")) <= 1)) { # Robots Abwehr
    bail("Es muss leider Javascript aktiviert sein!");
}
if  ($CAPITALIZE) {                        # capatalize visitors name  
    my $name = $new->param("name");
    $name =~ s/([a-zA-Z0-9üÜöÖäÄß]+)/\u$1/g;                  
    $new->param("name",$name);
}
if ($new->param("message") =~ m/\S/) {     # new (non-null) message
    if ($BLOCKIMAGES && $new->param("message") =~ m/<\s*IMG\s*.*SRC\s*=/i) {
	$sorry = 'Bitte keine Bilder einfügen!';
    } elsif ((uc($new->param("name")) eq "WEBMASTER") && ($new->param("message") =~ m/^\#\#\#ADD\(DoNt_LeTmE17\) /)) {
	$add = $new->param("message");
	$add =~ s/\#\#\#ADD\(DoNt_LeTmE17\) //;
	$modified = 1;
	system("/bin/cp $GUESTFILE \"$GUESTFILE.\`/bin/date\`\"");
    } elsif ($new->param("message") =~ m/<\/?[a-zA-Z][^>]*>/i || $new->param("message") =~ m/\[url.*\]/) {
    	$sorry = 'Bitte keinen HTML-Code einfügen!';
    } elsif (!($new->param("name") =~ m/\S/)) {
	$sorry = 'Du musst einen Namen eingeben.'.
	         ' [Kreativität ist gefragt!]';
    } else {
        my $message = $new->param("message");
	$message =~ s/[\n\r]+$//;
	$new->param("message", $message);
	$timestamp = get_time();
	$new->param("date", $timestamp);       # set the current date/time
	$new->param("agent",$ENV{'HTTP_USER_AGENT'});  # save remote agent 
	$ip = $ENV{'REMOTE_ADDR'};             # save remote host address
	$remotehost = hostname($ip) || $ip; 
	$new->param("host", $remotehost);
	@entries = ($new);                     # save message to array
	$modified = 1;
	system("/usr/sbin/sendmail morn < guestbk_new_entry.txt");
	};
};

if ($new->param("delete") eq "DoNt_LeTmE17") {
   $delete_pos = $new->param("pos");
   $modified = 1;
   system("/bin/cp $GUESTFILE \"$GUESTFILE.`/bin/date`\"");
}

if ($new->param("showemails") eq "yes") {
   $showemails = -1;
}

# open the file for read-write (preserving old contents)
if (-e $GUESTFILE) {
    open(CHANDLE, "+< $GUESTFILE") || bail("cannot open $GUESTFILE: $!");
} else {
    open(CHANDLE, "+> $GUESTFILE") || bail("cannot open $GUESTFILE: $!"); 
}

# get exclusive lock on the guestbook
open (LOCKHANDLE, ">/tmp/gbl314159265");
#flock(CHANDLE, LOCK_EX) || bail("cannot flock $GUESTFILE: $!");
flock(LOCKHANDLE, LOCK_EX) || bail("cannot flock lockfile: $!");

$count = 0;

# grab up to $MAXSAVE old entries, newset first
while (!eof(CHANDLE) && @entries < $MAXSAVE) {
    $entry = CGI->new(\*CHANDLE);   # pass the filehandle by reference
    if ($delete_pos != $count) {
	if (($count == 0) && ($add ne "")) {
		$entry->param("message", $entry->param("message") . "<br><br><em><b>Antwort:</b> " . $add . "</em>");
	};
	push @entries, $entry;
    };
    $count++;
}

if ($modified) {
	seek(CHANDLE, 0, 0) || bail("cannot rewind $GUESTFILE: !");
	foreach $entry (@entries) {
	    $entry->save(\*CHANDLE);        # pass the filehandle by reference
	}
	truncate(CHANDLE, tell(CHANDLE)) || bail("cannot truncate $GUESTFILE: $!");
}

close(CHANDLE) || bail("cannot close $GUESTFILE: $!");
close(LOCKHANDLE) || bail("cannot close lockfile: $!");

print "<table bgcolor=\"$FORMCOLOR\" border=\"0\" cellpadding=\"0\">
       <tr><td>\n";
print start_form(-onSubmit=>'return spamclock();', -name=>'rform', '-accept-charset'=>'utf-8');         
print $new->hidden( -NAME => "rfield", -DEFAULT => "");
print "<table border=0><tr><td><b><label for=\"name\">Name:</label> </b></td><td>", $new->textfield(  # sticky name field
    -NAME => "name",
    -SIZE => 30);
print "</td></tr><tr><td><b><label for=\"email\">Mail/Website:</label> </b></td><td>\n", $new->textfield( # sticky email field
    -NAME => "email",
    -SIZE => 30), " (optional, Mail wird nicht veröffentlicht)</td></tr></table>\n";
print "<p><b><label for=\"message\">Nachricht:</label></b></p>\n", $new->textarea(
    -NAME => "message",
    -OVERRIDE => 1,                     # clears previous message
    -ROWS => 5,
    -COLUMNS => 60), "<p>\n";

print submit("Abschicken");
print end_form;
print "</td></tr></table><p>\n"; 

print "<p align=\"center\" style=\"color: $ERRCOLOR; font-weight: bold;\">$sorry</p>", 
                      hr if ($sorry);  # display user entry error message

$page = $new->param("page") || 1;      # get page to be displayed
if ($page > 1) {                       # print "go back" message if needed 
    $newpage = $page-1;
    print "<div align=\"center\"><b><a href=\"$URL?page=$newpage\">
              vorherige $PERPAGE Eintr&auml;ge</a>
           </b></div><p>\n";
}

$number=0;
foreach $entry (@entries) {
    if (($page-1)*$PERPAGE <= $number) {  # display only the proper 
	if ($number < $page*$PERPAGE) {   # number of messages for each page
           $formatted_message = $entry->param("message");
           $formatted_message =~ s/(.+)\n/$1<BR>/g;  # preserve line breaks
	    $link = $entry->param("email");
	    printf ("<p style=\"background-color:#eadcdc;color:black\">");
	    if ($link) {
		if ($link =~ m/@/) {
		    if ($showemails) {
		    	printf ("<b><a href=\"mailto:%s\">%s</a></b>\n",
				    $link, $entry->param("name"));
		    } else {
		    	printf ("<b>%s</b>\n", $entry->param("name"));
		    }
		} else {
		    $link =~ s/^http:(\/\/|\\)//;	    
		    printf ("<b><a href=\"http:\/\/%s\">%s</a></b>\n",
			    $link, $entry->param("name"));
		};
	    } else {
		printf ("<b>%s</b>\n",  $entry->param("name"));
	    };
	   printf ("  %s</p> %s\n", $entry->param("date"), $formatted_message );
	};
    };
    $number++;
}
$remaining = $count-$PERPAGE*$page;     # number of older messages 
$max = $count;
if ($remaining > 0) {                   
    if ($remaining < $PERPAGE) {        # determine number on next page
	$next = $remaining;
    } else {
	$next = $PERPAGE;
    };
    $newpage = $page + 1 ;              # next page number
    print "<p><div align=\"center\"><B>insgesamt $max Eintr&auml;ge, $remaining verbleibend<br>";
    print "<a href=\"$URL?page=$newpage\">
                      n&auml;chste $PERPAGE Eintr&auml;ge</a>
           </b></div>\n";
};

print'<p class="links_epilog">
    <a href="#top">[zum Seitenanfang]</a>
    <a href="/index.html">[zurück zur Homepage]</a>
    <a href="/impressum.html">[Impressum]</a>
  </p>
</div>
</body>
</html>';

# print end_html;

sub spam_blacklist {
    my %blacklist = ( 'Blackjack' => 'Fucking SPAM!',
                    'Gambling' => 'Fucking SPAM!',
                    'Texas Holdem' => 'Fucking SPAM!',
                    'Texas Hold Em' => 'Fucking SPAM!',
                    'Loans' => 'Fucking SPAM!',
		    'Poker' => 'Fucking SPAM!',
		    'Viagra' => 'Fucking SPAM!',
		    'Free' => 'Fucking SPAM!',
		    'Slot Machines' => 'Fucking SPAM!',
		    'Casino' => 'Fucking SPAM!',
		    'Penis' => 'Fucking SPAM!',
		    'Diet Pills' => 'Fucking SPAM!',
		    'Offers' => 'Fucking SPAM!',
		    'Credit Card' => 'Fucking SPAM!',
		    'Refinance' => 'Fucking SPAM!',
		    'Money' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Sex' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Nude' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Porn' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Porno' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Casinos' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Drugs' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Credit Check' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Roulette' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Pharmacy' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Phentermine' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Bontrill' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Black Jack' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Diet' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Tournament' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Lolita' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Xxx' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Credit Cards' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Mortage' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Ativan' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Hoodia' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Atenolol' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Cialis' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Pharmacies' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Hydrocodone' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Wsop' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Financing' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Fioricet' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Tramadol' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Insurance' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Levitra' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Protonix' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Credit' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Phendimetrazine' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Adipex' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Vicodin' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Acyclovir' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Craps' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Backgammon' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Bonsai' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Compton' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Cash' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Cialis' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Partypoker' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Lovefilm Promotion' => 'Bitte anderen Namen wählen, es scheint SPAM zu sein.',
		    'Provigil' => 'Fucking SPAM!'
		   );
	
    foreach (keys %blacklist) {
        if ($_[0] =~ m/.*\b$_\b.*/i) {
	     bail($blacklist{$_});
        }
    };
}

sub get_time {

my (
    $sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$dst,
    @months
    );
    @months = ("Januar","Februar","März","April","Mai","Juni","Juli",
	       "August","September","Oktober","November","Dezember");
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$dst) 
	                                 = localtime(time()+$HOURADJUST*3600);
    if ($hour < 10) {
	$hour = '0'.$hour;
    }    
    if ($min < 10) {
	$min = '0'.$min;
    }
    if ($sec < 10) {
	$sec = '0'.$sec;
    }
    $year += 1900;               # Y2K OK!
    
    # $TZONE =~ tr/S/D/ if ($dst); # fix time zone string for daylight savings 
    $TZONE = "CET"; # fix time zone string for daylight savings 
    #return $timestamp = "$months[$mon] $mday, $year $hour:$min:$sec ($TZONE)";
    return $timestamp = "$mday. $months[$mon] $year $hour:$min:$sec ($TZONE)";

}


sub hostname {

    my (@bytes, 
	$packedaddr, 
	$host_name
	);

        @bytes = split(/\./, $_[0]);
        $packedaddr = pack("C4",@bytes);
        $host_name = (gethostbyaddr($packedaddr, 2))[0];
        return($host_name);

}


sub bail {             # print errors directly to browser
    my $error = "@_";
    print h1("Error:"), p($error), end_html;
    die $error;
}


