#!/usr/local/bin/perl

# ***************************************************************************
#                                JMK Guestbook
#                             -------------------
#    begin                : Somewhere in time
#    copyright            : (C) 1999 by Dimitris Batis
#    email                : bat_geor@mail.hol.gr
# ***************************************************************************
#
# ***************************************************************************
# *                                                                         *
# *   This program is free software; you can redistribute it and/or modify  *
# *   it under the terms of the GNU General Public License as published by  *
# *   the Free Software Foundation; either version 2 of the License, or     *
# *   (at your option) any later version.                                   *
# *                                                                         *
# ***************************************************************************

# JMK Guestbook
# Look at README for information

# GLOBAL VARIABLES

# Base directory.
$basedir = "http://www.mydomain.com/";

#This script
$script = "jguestbook.pl";

# The e-mail adress of the webmaster
$webmaster = "webmaster\@mysite.com.";

# Allow visitor to use HTML tags in any field, it this variable is set to 1
$allow_tags = 0;

# The data directory. It is better that you give the whole path without the
# / at the end
$datadir = "/usr/local/httpd/cgi-bin";

# If the variable below is set to 1, then bad words are blocked
$blockbadwords = 1;

# If you want to receive an e-mail each time a new entry is signed, set
# this variable to 1 and the second to the path of SENDMAIL server. The
# third variable should contain your e-mail adress
$send_me_mail = 1;
$sendmail = "/usr/sbin/sendmail";
$email = "my\@internet.adress.com";

# How much entries to show in each page
$numofentries = 20;

# Version of script
$version = "1.0.2";

# MAIN PROGRAM

# Since everything we send is HTML, declare the content type from here
print "Content-Type: text/html\n\n";

# Print the template of the document
&buildtemplate;

# Get arguments
$buffer = "";
&getargs;
&splitargs;

# Now that we've got the arguments, let's process them.
if($buffer eq "view" || $buffer eq "") {
	&viewentries; # View the guestbook
}
elsif($buffer eq "sign") {
	&signform; # Show the form to sign the guestbook
}
elsif($buffer =~ m/viewfrom\=/ig) {
		$start = $FORM{'viewfrom'};
		&viewspecifiedentries; # Show a specified region of entries
}
elsif($buffer =~ m/submitted\=/ig) {
		&processform; # Process the form that was sent
}
elsif($buffer =~ m/confirm\=/ig) {
		&submitform; # Confirm that the sent form is correct.
}
else {
	# Show error that something went wrong
	&showerror("processing the submitted form.");
}

exit; # Actually, it should never reach here

# Build templaet
# Builds the main structure of the document
sub buildtemplate {
# As we print the text below over and over again, let's put it in one function
# so that we don't write the same stuff in each function.

	open(FILE, "$datadir/template.htm") || &showerror("opening the template");
	@template = <FILE>;
	close(FILE);

# We must get all parts before <---# Sep #---> and make it the header and the rest
# will become the end

	$header = "";
	$headerend = "";
	$temp = 0;

	foreach $line (@template) {
		if($temp == 0) {
			if($line eq "<---# Sep #--->\n") {
				$temp = 1;
			}
			else {
				$header = $header . $line;
			}
		}
		else {
				$headerend = $headerend . $line;
		}
	}

# At this point, let's print the header, since everything below needs it
	print "$header";

}

# Getargs. This command takes the arguments of a script and stores them in a variable,
# no matter which method (POST/GET) was used
sub getargs {
	if ( $ENV{'REQUEST_METHOD'} eq 'GET' ) {
		$buffer = $ENV{'QUERY_STRING'};
	}
  	elsif ( $ENV{'REQUEST_METHOD'} eq 'POST' ) {
		read(STDIN,$buffer ,$ENV{'CONTENT_LENGTH'});
	}
	else {
		&showerror("Request method");
	}
}

sub splitargs {
	@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;
		$name =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
		$value =~ s/~!/ ~!/g;
		$name =~ s/~!/ ~!/g;
		$name =~ s/<([^>]|\n)*>//g unless $allow_tags == 1;
		$value =~ s/<([^>]|\n)*>//g unless $allow_tags == 1;
		$value =~ s/<!--#(.|\n)*-->//g;
		$name =~ s/<!--#(.|\n)*-->//g;
		$value =~ s/<(.*href.*>|\/a)>//ig unless $allow_tags == 1;
		$value =~ s/(<.*?h\d.*?>|<.*?\/h.*?>)//mig;
		$value =~ s/`//g;
		$name =~ s/`//g;
		$value =~ s/\&/\&amp\;/g;
		$value =~ s/"/\&quot\;/g;
		$value =~ s/</\&lt\;/g;
		$value =~ s/>/\&gt\;/g;
		$value =~ s/\n/ /g;
		$FORM{$name} = $value;

	} # With the script above, any HTML tags are removed.

}

# Show form to sign the guestbook
sub signform {
	print "<P>Complete the fields below to sign our guestbook. If a field is marked with an asterisk (*), it means ";
	print "that it is nessecary to complete that field. All other fields are optional.<BR>";
	if($allow_tags != 1) {
		print "The comment field must NOT contain any HTML tags.\n";
	}

	print "<FORM METHOD=POST ACTION=\"$script\">\n";
	print "<INPUT TYPE=HIDDEN NAME=\"submitted\" VALUE=\"yes\">\n";
	print "<P><CENTER><TABLE BORDER=0 CELLSPACING=3 CELLPADDING=2>\n";
	print "<TR><TD ALIGN=LEFT><B>Name:</B>*</TD><TD><INPUT TYPE=TEXT NAME=name SIZE=40></TD></TR>\n";
	print "<TR><TD ALIGN=LEFT><B>E-mail:</B>*</TD><TD><INPUT TYPE=TEXT NAME=email SIZE=40></TD></TR>\n";
	print "<TR><TD ALIGN=LEFT><B>URL:</B></TD><TD><INPUT TYPE=TEXT NAME=url SIZE=40 VALUE=\"http:\/\/\"></TD></TR>\n";
	print "<TR><TD ALIGN=LEFT><B>City:</B></TD><TD><INPUT TYPE=TEXT NAME=city SIZE=15></TD></TR>\n";
	print "<TR><TD ALIGN=LEFT><B>Country:</B></TD><TD><INPUT TYPE=TEXT NAME=country SIZE=15></TD></TR>\n";

	print "<TR><TD ALIGN=LEFT VALIGN=TOP><B>Comments:</B>*</TD>";
	print "<TD><TEXTAREA NAME=comments COLS=40 ROWS=8>Put your comment here</TEXTAREA></TD></TR>\n";

	print "<TR><TD ALIGN=CENTER COLSPAN=2><INPUT TYPE=SUBMIT VALUE=\"Submit\">&nbsp;&nbsp;&nbsp;";
	print "<INPUT TYPE=RESET VALUE=\"Reset form\"></TD></TR>\n";
	print "</TABLE></CENTER>\n";

	print "$headerend";

	exit;

}

# Process the form that was sent
sub processform {

	&no_name unless $FORM{'name'};
	&no_email unless $FORM{'email'};
	&no_comments unless $FORM{'comments'};
	&no_comments if($FORM{'comments'} eq "Put your comment here");

# Check if @ was on e-mail adress, else return that no valid adress was used.
    if ($FORM{'email'} !~ /^[^\@]*[\@][^\@]*?\.[^\@]*$/g) {
        &no_valid_email;
    }


# If URL = http://, set it to NONE
	if($FORM{'url'} eq "http://") {
		$FORM{'url'} = "";
	}

# Check for bad words, if blocking is used
	if($blockbadwords == 1) {
		open(BADWORDS, "$datadir/badwords.txt") || &showerror("opening bad word list.");
		@badentries = <BADWORDS>;
		close(BADWORDS);

		foreach $word(@badentries) {
			chop($word);

			if ($FORM{'name'} =~ m/$word(\.| |\!|\,|\?|\-)/ig) {
				&bad_word_used($word);
			}
			if ($FORM{'comments'} =~ m/$word(\.| |\,|\!|\?|\-)/ig) {
				&bad_word_used($word);
			}
			if ($FORM{'city'} =~ m/$word(\.| |\!|\,|\?|\-)/ig) {
				&bad_word_used($word);
			}
			if ($FORM{'country'} =~ m/$word(\.| |\!|\,|\?|\-)/ig) {
				&bad_word_used($word);
			}
		}
	}

# Show confirmation message

	print "<P>Below is what you want to submit. If everything is OK, click the OK button. If not, you can ";
	print "<A HREF=\"$script?sign\">return back</A> and re-submit.\n";
	print "<HR>";
	print "<TABLE BORDER=0 CELLSPACING=3 CELLPADDING=2>\n";
	print "<TR><TD ALIGN=LEFT><B>Name:</B></TD><TD ALIGN=LEFT>$FORM{'name'}</TD></TR>\n";
	print "<TR><TD ALIGN=LEFT><B>E-mail:</B></TD><TD ALIGN=LEFT>$FORM{'email'}</TD></TR>\n";
	print "<TR><TD ALIGN=LEFT><B>Home page:</B></TD><TD ALIGN=LEFT>$FORM{'url'}</TD></TR>\n";
	print "<TR><TD ALIGN=LEFT><B>City:</B></TD><TD ALIGN=LEFT>$FORM{'city'}</TD></TR>\n";
	print "<TR><TD ALIGN=LEFT><B>Country:</B></TD><TD ALIGN=LEFT>$FORM{'country'}</TD></TR>\n";
	print "<TR><TD ALIGN=LEFT VALIGN=TOP><B>Comments:</B></TD><TD ALIGN=LEFT>$FORM{'comments'}</TD></TR>\n";
	print "<TR><TD ALIGN=CENTER COLSPAN=2>\n";
	print "<FORM METHOD=POST ACTION=\"$script\">\n";
	print "<INPUT TYPE=HIDDEN NAME=confirm VALUE=yes>\n";
	print "<INPUT TYPE=HIDDEN NAME=name VALUE=\"$FORM{'name'}\">\n";
	print "<INPUT TYPE=HIDDEN NAME=email VALUE=\"$FORM{'email'}\">\n";
	print "<INPUT TYPE=HIDDEN NAME=url VALUE=\"$FORM{'url'}\">\n";
	print "<INPUT TYPE=HIDDEN NAME=city VALUE=\"$FORM{'city'}\">\n";
	print "<INPUT TYPE=HIDDEN NAME=country VALUE=\"$FORM{'country'}\">\n";
	print "<INPUT TYPE=HIDDEN NAME=comments VALUE=\"$FORM{'comments'}\">\n";
	print "<INPUT TYPE=SUBMIT VALUE=\"Ok, go ahead!\">\n";
	print "</FORM>\n";
	print "</TR></TABLE>\n";
	print "$headerend";

	exit;
}

# Save form into start of data file
sub submitform {

# Get current date
	&make_date;

# First, read the datafile and save everything temporarily, if file exists
	unless (! -e "$datadir/guestbook.txt") {
		open(DATAFILE, "$datadir/guestbook.txt") || &showerror("opening the data file to read/write on it");
		@temp = <DATAFILE>;
		close (DATAFILE);
	}

# Open the file to write at it
	open(DATAFILE, ">$datadir/guestbook.txt") || &showerror("opening the data file to write on it");

	print DATAFILE "$FORM{'name'}-##-$FORM{'email'}-##-$FORM{'url'}-##-$FORM{'city'}-##-$FORM{'country'}-##-$thisdate-##-$FORM{'comments'}\n";

	foreach $line(@temp) {
		print DATAFILE "$line";
	}

	close(DATAFILE);

# If send_me_mail is set to 1, an e-mail is sent to you with the submission
	if($send_me_mail == 1) {
		if(-x $sendmail) {
			open(SM, "|$sendmail $email");

			print SM "From: $email\n";
			print SM "Subject: Guestbook Signed ($thisdate)\n\n";
			print SM "Hello. This is JMK Guestbook Notification message to tell you that\n";
			print SM "someone has signed your guestbook. Here is the data sent:\n\n";
			print SM "Name: $FORM{'name'}\n";
			print SM "E-mail: $FORM{'email'}\n";
			print SM "URL: $FORM{'url'}\n";
			print SM "City: $FORM{'city'}, Country: $FORM{'country'}\n";
			print SM "Comments: $FORM{'comments'}\n\n";
			
			print SM "Thank you for using JMK Guestbook.";

			close(SM);
		}
		else {
			print "Error occured with using SENDMAIL. Please contact our <A HREF=\"mailto:$webmaster\">webmaster</A> about this.<BR><BR>";

		}

	}

	&thanks; # Thank the user

	exit;
}


# View entries. This will show as many entries as numofentries is and then make a link
# to another page, which will show the rest of the entries.
sub viewentries {

# First, let's show a message to tell others to sign the guestbook
	print "<H2>Signing my guestbook:</H2>\n";
	print "<P>You are welcome to sign my guestbook and tell me your comments about my site and my art.\n";
	print "<BR>To sign the guestbook, press <A HREF=\"$script?sign\">in this link</A>.\n";

	print "<HR>\n";
	print "<H2>Read the guestbook:";

# Open data file
	open(FILE, "$datadir/guestbook.txt") || &showerror("finding the data file.");
	@entries = <FILE>;
	close(FILE);

# Let's see how many entries
	$entries = 0;
	foreach $line(@entries) {
		$entries++;
	}

	print " (Total: $entries entries)</H2>";

# Local variables
	$entries = 0;

# Now, let's create the entries.
	foreach $line(@entries) {
		$entries++; # entries becomes entries+1
	# Split
		($nam, $email, $url, $city, $country, $date, $comments) = split(/-##-/, $line);

		print "<TABLE BORDER=2 CELLSPACING=2 CELLPADDING=2 WIDTH=80%>\n";
		print "<TR>\n";
		print "<TD ALIGN=LEFT COLSPAN=2><B>Name:</B>\n";
		print "<A HREF=\"mailto:$email\">$nam</A></TD>";

		print "<TR>\n";
		print "<TD ALIGN=LEFT COLSPAN=2><B>Sent at:</B>\n";
		print "$date</TD>";

		unless($url eq "") {
			print "<TR>\n";
			print "<TD ALIGN=LEFT COLSPAN=2><B>Homepage:</B>\n";
			print "<A HREF=\"$url\">$url</A></TD>";
		}
		unless($city eq "") {
			print "<TR>\n";
			print "<TD ALIGN=LEFT COLSPAN=2><B>City:</B>\n";
			print "$city</TD>";
		}
		unless($country eq "") {
			print "<TR>\n";
			print "<TD ALIGN=LEFT COLSPAN=2><B>Country:</B>\n";
			print "$country</TD>";
		}
			print "<TR>\n";
			print "<TD ALIGN=LEFT WIDTH=20%><B>Comments:</B></TD>\n";
			print "<TD ALIGN=LEFT>$comments</TD>";

			print "</TABLE><P><HR><P>";

		if($entries == $numofentries) {
			$go = $numofentries +1;
			print "<H2 ALIGN=CENTER><A HREF=\"$script?viewfrom=$go\">Next $numofentries entries</A></H2>";
			print "$headerend";
			exit;
		}

	}

# End document

	print "$headerend";

}

sub viewspecifiedentries {

	$end = $start + $numofentries -1;
	print "<H2>Entries $start to $end</H2>\n";
	print "<A HREF=\"$script?sign\">If you want to sign our form, click here</A>.<HR><P>\n";

# Open data file
	open(FILE, "$datadir/guestbook.txt") || &showerror("finding the data file.");
	@entries = <FILE>;
	close(FILE);

	$entries = 0;

# Now, let's create the entries.
	foreach $line(@entries) {
		$entries++; # entries becomes entries+1

		if($entries >= $start) {
	# Split
			($nam, $email, $url, $city, $country, $date, $comments) = split(/-##-/, $line);

			print "<TABLE BORDER=2 CELLSPACING=2 CELLPADDING=2 WIDTH=80%>\n";
			print "<TR>\n";
			print "<TD ALIGN=LEFT COLSPAN=2><B>Name:</B>\n";
			print "<A HREF=\"mailto:$email\">$nam</A></TD>";

			print "<TR>\n";
			print "<TD ALIGN=LEFT COLSPAN=2><B>Sent at:</B>\n";
			print "$date</TD>";

			unless($url eq "") {
				print "<TR>\n";
				print "<TD ALIGN=LEFT COLSPAN=2><B>Homepage:</B>\n";
				print "<A HREF=\"$url\">$url</A></TD>";
			}
			unless($city eq "") {
				print "<TR>\n";
				print "<TD ALIGN=LEFT COLSPAN=2><B>City:</B>\n";
				print "$city</TD>";
			}
			unless($country eq "") {
				print "<TR>\n";
				print "<TD ALIGN=LEFT COLSPAN=2><B>Country:</B>\n";
				print "$country</TD>";
			}
				print "<TR>\n";
				print "<TD ALIGN=LEFT WIDTH=20%><B>Comments:</B></TD>\n";
				print "<TD ALIGN=LEFT>$comments</TD>";

				print "</TABLE><P><HR><P>";

			if($entries == $end) {
				$go = $numofentries +1;
				if($start == 1) {
					print "<H2 ALIGN=CENTER><A HREF=\"$script?viewfrom=$go\">Next $numofentries entries</A></H2>";
				}
				else {
					$start -= $numofentries;
					if($start < 0) { $start = 1; } # This should never occur
					print "<H2 ALIGN=CENTER><A HREF=\"$script?viewfrom=$start\">Previous $numofentries entries</A>";
					print " - <A HREF=\"$script?viewfrom=$end\">Next $numofentries entries</A></H2>";
				}
				print "$headerend";
				exit;
			}
		}
	}

# End document

	$start -= $numofentries;
	print "<H2 ALIGN=CENTER><A HREF=\"$script?viewfrom=$start\">Previous $numofentries entries</A></H2>";
	print "$headerend";

}


# If no name was given.
sub no_name {

	print "<P>You haven't written your name. <A HREF=\"$script?sign\">Go back</A> and re-complete the form.";

	print "$headerend";

	exit;
}

# If no e-mail adress was given.
sub no_email {

	print "<P>You haven't written your e-mail adress. <A HREF=\"$script?sign\">Go back</A> and re-complete the form.";
	print "$headerend";

	exit;
}

# If e-mail adress wasn't valid, i.e. hadn't the @ symbol.
sub no_valid_email {

	print "<P>The e-mail address you gave is not valid (you gave $FORM{'email'}).";
	print " <A HREF=\"$script?sign\">Go back</A> and re-complete the form.";
	print "$headerend";

	exit;
}

# If no comments were given.
sub no_comments {

	print "<P>You haven't written any comments! <A HREF=\"$script?sign\">Go back</A> and re-complete the form.";
	print "$headerend";

	exit;
}

sub bad_word_used {

	print "<P>You used a word that was impolite ($_[0]). Please, write your comments in a more polite manner.<BR>";
	print "<A HREF=\"$script?sign\">Go back</A> and re-complete the form.";
	print "$headerend";

	exit;
}

# Make current date and time
sub make_date {
    @months = (0,'January','February','March','April','May','June','July',
	       'August','September','October','November','December');
    ($thissec,$thismin,$thishour,$mday,$mon,$thisyear,$t,$t,$t) = localtime(time);
    $mon++;
    $thisyear += 1900;
    $thisdate = "$thishour:$thismin:$thissec, $mday $months[$mon] $thisyear";

}

# Show 'thank you' message
sub thanks {
	print "<H3 ALIGN=CENTER>Thank you!</H3>\n";
	print "<P>Thank you for signing my guestbook! Your comments are very appreciated and I will enjoy reading them.";
	print "<P>Now, you can go back to the <A HREF=\"$basedir/main.htm\">main page</A>, or continue browsing ";
	print "the <A HREF=\"$script?view\">guestbook</A>.";

	print "$headerend";
	exit;
}


# If an error occured, this command is called
sub showerror {

	print "<P><B>ERROR:</B> In $_[0].\n";
	print "The parameters that were given are: \"$buffer\".\n";
	print "<P>Please, contact our <A HREF=\"mailto:$webmaster\">webmaster</A> and notify him of the problem";
	print ", so that it is fixed as soon as possible. Thank you.";
	print "$headerend";

	exit;
}
