#!/usr/bin/perl -w

#   CGIForum - discussion board written in PERL
#   Copyright (C) 2000-2003 Markus Triska
#
#   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.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, write to the Free Software
#   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
#
#   Contact me via triska@gmx.at



use strict;

use Time::Local;
use CGI;

# Don't change these values here -  Use "cgiforum.conf" instead.
# This way, you can simply replace "cgiforum.pl" when upgrading.

my $basedir = '../cgiforum/';
my $period_new = 2;
my $default_day_limit = 30;
my $default_headline = 'None';
my $default_author = 'Anonymous';
my %start_entries = ();
my $doload_text = 0;
my $only_registered = 0;
my $allow_registration = 1;

my @entryrelations = ();
my %EntryInfo = ();
my $thesection = '';
my @ShortWeekDays = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun');
my %FullWeekDay = (
	Mon => 'Monday', Tue => 'Tuesday', Wed => 'Wednesday',
	Thu => 'Thursday', Fri => 'Friday', Sat => 'Saturday',
	Sun => 'Sunday'
);

my %NumMonth = (
	Jan => "01", Feb => "02", Mar => "03", Apr => "04", May => "05",
	Jun => "06", Jul => "07", Aug => "08", Sep => "09", Oct => "10",
	Nov => "11", Dec => "12"
);
my %DateTime = ();

my $cgi = new CGI;


sub filterUserInput
{
	my $string = shift;

	# This code was contributed by b0iler@hotmail.com . Many thanks!
	$string =~ s/([\&;\`'\|\"*\?\~\^\(\)\[\]\{\}\$\n\r])/\\$1/g; #meta characters
	$string =~ s/\0//g; #null byte
	$string =~ s/\.\.//g; #then ..

	return $string;
}


sub EncDec
{
	my @args = split //, shift();
	my $retval = '';
	for (my $stringpos = 0; $stringpos <= $#args; $stringpos++) {
		$retval .= chr(ord($args[$stringpos]) ^ 0x12);
	}
	return $retval;
}

sub NumDaysOld
{
	# how many days is the currently loaded entry old?
	my $newstime = timelocal(0, 0, 0, $DateTime{'day'}, $DateTime{'month'} - 1, $DateTime{'year'} - 1900);
	my $ltime = localtime;
	if (substr ($ltime, 8, 1) eq ' ') {
		substr ($ltime, 8, 1) = '0';
	}
	my ($weekday, $monthstr, $day, $Time, $year) = split (/ /, $ltime);
	my $nummonth = $NumMonth{$monthstr};
	my $currenttime = timelocal(0, 0, 0, $day, $nummonth - 1, $year - 1900);
	my $diff = $currenttime - $newstime;
	my $seconds = $diff % 60;
	$diff = ($diff - $seconds) / 60;
	my $minutes = $diff % 60;
	$diff = ($diff - $minutes) / 60;
	my $hours = $diff % 24;
	$diff = ($diff - $hours) / 24;
	my $days = $diff % 7;
	my $weeks = ($diff - $days)  / 7;
	return ($days + $weeks * 7);
}

sub IsInsideDateLimits
{
	my $youngerthanstart = 0;
	my $olderthanend = 0;
	if (($EntryInfo{'start'} == -1) || ($EntryInfo{'start'} == 0) || (NumDaysOld() <= $EntryInfo{'start'})) {
		$youngerthanstart = 1;
	}

	if (NumDaysOld() >= $EntryInfo{'end'}) {
		$olderthanend = 1;
	}
	if ($youngerthanstart && $olderthanend) { return 1; }

	return 0;
}

sub FillDateTime
{
	my $ltime = shift;
	if (!$ltime) {
		$ltime = localtime;
	}

	if (substr ($ltime, 8, 1) eq ' ') {
		substr ($ltime, 8, 1) = '0';
	}

	my ($weekday, $monthstr, $day, $Time, $year) = split (/ /, $ltime);
	$DateTime{'weekday'} = $FullWeekDay{ (substr $weekday, 0, 3)};
	$DateTime{'time'} = $Time;
	$DateTime{'day'} = $day;
	$DateTime{'monthstr'} = $monthstr;
	$DateTime{'month'} = $NumMonth{$monthstr};
	$DateTime{'year'} = $year;
	$DateTime{'hour'} = substr $Time, 0, 2;     # 16:03:22
	$DateTime{'minute'} = substr $Time, 3, 2;
	$DateTime{'second'} = substr $Time, 6, 2;
	$DateTime{'newsdate'} = $year . $NumMonth{$monthstr} . $day;

}

sub GetEntryTimeInfo
{
	my ($section, $entrynumber) = @_;
	my $entrypath = $basedir . "sections/$section/entries/$entrynumber";
	my $infoline = "||";
	if (-e "$entrypath.inf") {
		open ENTRYINFO, "<$entrypath.inf";
		$infoline = <ENTRYINFO>;
		close ENTRYINFO;
	}
	chomp $infoline;
	my ($author, $time, $email) = split /\|/, $infoline;
	FillDateTime($time);
}

sub FillEntryInfo
{
	my ($section, $entrynumber, $loadtext) = @_;
	$EntryInfo{'entrynumber'} = $entrynumber;

	my $entrypath = $basedir . "sections/$section/entries/$entrynumber";

	if ($loadtext) {
		$EntryInfo{'text'} = FileToScalar("$entrypath.msg");
	}

	my $headlinefile = $basedir . "sections/" . $section;
	if ($entrynumber == 0) {
		$headlinefile .= "/section.txt";
	} else {
		$headlinefile .= "/entries/" . $entrynumber . ".hdl";
	}
	my $headline = '';
	if (-e "$headlinefile") {
		open HDL, "<$headlinefile";
		$headline = <HDL>;
		close HDL;
	}
	if (!$headline) { $headline = $default_headline; }
	chomp $headline;
	$EntryInfo{'headline'} = $headline;

	GetEntryTimeInfo($section, $entrynumber);

	my $infoline = '||';
	if (-e "$entrypath.inf") {
		open ENTRYINFO, "<$entrypath.inf";
		$infoline = <ENTRYINFO>;
		chomp $infoline;
		close ENTRYINFO;
	}

	my ($author, $time, $email) = split /\|/, $infoline;
	my $authornum = 0;
	if ($author =~ /^REGISTERED/) {
		($authornum = $author) =~ s/REGISTERED//;
		chomp $authornum;
		open AUTHOR, "<$basedir". "users/" . "$authornum.syn";
		$author = <AUTHOR>;
		if (!$author) { $author = $default_author; }
		close AUTHOR;
		chomp $author;
	}
	if ($email =~ /seeeml/) {
		open EMAIL, "<$basedir" . "users/" . "$authornum.eml";
		$email = <EMAIL>;
		if (!$email) { $email = " "; }
		close EMAIL;
		chomp $email;
	}

	if (!$author) { $author = $default_author; }
	$EntryInfo{'author'} = $author;
	$EntryInfo{'email'} = $email;

	my $numhits = 0;
	# Prior to version 1.04, no "cnt"-file was written by default.
	if (-e "$entrypath.cnt") {
		open COUNT, "<$entrypath.cnt";
		$numhits = <COUNT>;
		close COUNT;
	 	chomp $numhits;
	}
	$EntryInfo{'numhits'} = $numhits;
}


my $level = 0;
sub GetChildren
{
	my ($currentthread, $control) = @_;

	my @children = ();
	$level += 1;
	foreach my $entry (grep (/\|$currentthread\n/, @entryrelations)) {
		my $is_hidden = 0;
		my ($child, $parent) = split /\|/, $entry;
			# $parent now equals to $currentthread, not used
		if (!-e "$basedir/sections/$thesection/entries/$child.del") {
			# Before 1.06, we did this:
			# if ($level == 1) {
				# check if this (base) thread should be displayed
				# GetEntryTimeInfo($thesection, $child);
				# if (!IsInsideDateLimits()) { next; }
			# }
			# Many thanks to John S. Jacob for contributing a
			# better solution!

			# Add entry if within date limits
			GetEntryTimeInfo($thesection, $child);
			if (IsInsideDateLimits()) {
				push @children, "$child\|$level";
			} else {
				$is_hidden = 1;
				$level -= 1;
			}
			if ($control ne 'nonrecursive') {
				push @children, GetChildren($child, $control);
			}
			if ($is_hidden) {
				$level += 1;
			}
		}
	}
	$level -= 1;
	return @children;
}

sub substSpecialChars
{
	my $string = shift;

	#$string =~ s/ä/\&auml\;/g; $string =~ s/Ä/\&Auml\;/g;
	#$string =~ s/ö/\&ouml\;/g; $string =~ s/Ö/\&Ouml\;/g;
	#$string =~ s/ü/\&uuml\;/g; $string =~ s/Ü/\&Uuml\;/g;

	$string =~ s/\n/\<BR\>/g;
	#$string =~ s/ß/\&szlig\;/g;

	# If you do not want "<" and ">" to be interpreted as HTML-tag markers,
	# uncomment the following two lines.
	# $string =~ s/</\&lt\;/g;
	# $string =~ s/>/\&gt\;/g;

	# Please add more special characters!

	return $string;
}


sub SubstRefVars
{
	my $template = shift;
	while ($template =~ /\#\#.*?\#\#/) {
		(my $refvar = $template) =~ s/.*?\#\#(.*?)\#\#.*/$1/;
		chomp $refvar;
		my $referredvar = '';
		if (exists $EntryInfo{"$refvar"}) {
			$referredvar = $EntryInfo{"$refvar"};
		} elsif ( exists $DateTime{"$refvar"} ) {
			$referredvar = $DateTime{"$refvar"};
		} else {
			$referredvar = "Warning...could NOT substitute $refvar";
		}
		if ($referredvar) {
			$referredvar = substSpecialChars($referredvar);
		}
		$template =~ s/\#\#.*?\#\#/$referredvar/;
	}
	return $template;
}

sub FileToScalar
{
	my $file = pop;
	my $scalar = '';
	if (!-e $file) {
		print "<b><font color=\"\#FF0000\"> Warning - file $file was not found. Please install it. It is included in this package of CGIForum. </font></b>";
		$scalar = " ";
	} else {
		open FILE, "<$file";
		while (<FILE>) {
			$scalar .= $_;
		}
		close FILE;
	}
	return $scalar;
}

sub LoadTemplate
{
	my ($section, $file) = @_;
	my $templatefile = CheckHTMLOverride($section, $file);
	my $template = FileToScalar($templatefile);
	$template =~ s/\n//g;
	return $template;
}


sub PrintEntries
{
	my ($section, $startthread, $recursive) = @_;
	my $db = $basedir . "sections/" . $section . "/entries/entries.db";
	if (-e $db && ($#entryrelations == -1)) {
		# @entryrelations could already be read in if we are called by
		# ShowEntry(). In this case, the list is already "optimized".
		my $thestartentry = $startthread;
		if (($startthread == 0) && ($EntryInfo{'start'} == $default_day_limit)) {
			$thestartentry = $start_entries{$section} || 0;
		}

		open ENTRYBASE, "<$db";
		while (<ENTRYBASE>) {
			my ($child, $parent) = split /\|/;
			if ($child >= $thestartentry) {
				push @entryrelations, $_;
			}
		}
		close ENTRYBASE;
	}

	# Reverse sort all level _1_ entries (children of "0") when
	# printing whole section
	if (($startthread == 0) && ($#entryrelations >= 0)) {
		my $lastswapped = $#entryrelations + 1;
		my $index = 0;
		while ($index < $lastswapped) {
			if ($entryrelations[$index] =~ /\|0\n/)  {
				# find last level-1-entry in list
				$lastswapped -= 1;
				while ($lastswapped >= $index) {
					if ($entryrelations[$lastswapped] =~ /\|0\n/) {
						last;
					}
					$lastswapped--;
				}

				# and swap them
				my $tempentry = $entryrelations[$index];
				$entryrelations[$index] = $entryrelations[$lastswapped];
				$entryrelations[$lastswapped] = $tempentry;
			}
			$index++;
		}
	}

	my @entriestree = GetChildren($startthread, $recursive);
	if ($startthread == 0) {
		# Uncomment this to have everything in one large "base-thread"
		# unshift @entriestree, "$startthread\|0";
	} else {
		unshift @entriestree, "$startthread\|0";
	}


	my $parent_template = LoadTemplate($section, "parententry.tpl");
	my $parent_active = LoadTemplate($section, "parententry.tpa");
	my $parent_end = LoadTemplate($section, "parententry.end");

	my $normal_template = LoadTemplate($section, "normalentry.tpl");
	my $normal_active = LoadTemplate($section, "normalentry.tpa");

	my $parent_new_template = LoadTemplate($section, "parententry_new.tpl");
	my $parent_new_active = LoadTemplate($section, "parententry_new.tpa");
	my $normal_new_template = LoadTemplate($section, "normalentry_new.tpl");
	my $normal_new_active = LoadTemplate($section, "normalentry_new.tpa");

	my $lastlevel = 0;
	for (my $index = 0; $index <= $#entriestree; $index++) {
		my ($number, $level) = split /\|/, $entriestree[$index];
		if ($level < $lastlevel) {
			my $numopenparents = $lastlevel - $level;
			while ($numopenparents > 0) {
				print SubstRefVars($parent_end);
				$numopenparents--;
			}
		}
		$lastlevel = $level;
		my $isparent = 0;
		my $nextentry = $entriestree[$index + 1];
		if ($nextentry) {
			my ($nextnumber, $nextlevel) = split /\|/, $nextentry;
			if ($nextlevel > $level) { $isparent = 1; }
		}

		FillEntryInfo($section, $number, $doload_text);
		print "\n\n";
		if ($isparent) {
			if (NumDaysOld() <= $period_new) {
				if ($EntryInfo{'topmost'} == $number) {
					print SubstRefVars($parent_new_active);
				} else {
					print SubstRefVars($parent_new_template);
				}
			} else {
				if ($EntryInfo{'topmost'} == $number) {
					print SubstRefVars($parent_active)
				} else {
					print SubstRefVars($parent_template);
				}
			}
		} else {
			if (NumDaysOld() <= $period_new) {
				if ($EntryInfo{'topmost'} == $number) {
					print SubstRefVars($normal_new_active);
				} else {
					print SubstRefVars($normal_new_template);
				}
			} else {
				if ($EntryInfo{'topmost'} == $number) {
					print SubstRefVars($normal_active);
				} else {
					print SubstRefVars($normal_template);
				}
			}
		}
	}
 	while ($lastlevel > 0) {
		print SubstRefVars($parent_end);
		$lastlevel--;
	}
}

sub getLatestEntry
{
	my $entriesfile = shift;
	my $latestentry = 0;
	if (-e $entriesfile) {
		open ENTRIES, "<$entriesfile";
		while (<ENTRIES>) {
			$latestentry++;
		}
		close ENTRIES;
	}
	return $latestentry;
}


sub ShowEntry
{
	my ($section, $entrynumber) = @_;
	my $db = $basedir . "sections/" . $section . "/entries/entries.db";

	my $latestentry = getLatestEntry($db);
	if ($entrynumber !~ /^\d+$/) { $entrynumber = 0; }
	if ($entrynumber > $latestentry) { $entrynumber = $latestentry; }
	FillEntryInfo($section, $entrynumber, 1);
	# Save this headline - we may need it later.
	$EntryInfo{'clickedheadline'} = $EntryInfo{'headline'};

	OutputHTMLFile($section, 'forum.hdr');
	OutputHTMLFile($section, 'navigation.tpl');
	OutputHTMLFile($section, 'fullentry.tpl');

	# We used to do a
	#	 PrintEntries($section, $entrynumber, 'recursive');
	# here.
	# I think it is more useful to display every entry with the same
	# (topmost) parent as the currently displayed entry instead. This
	# facilitates browsing through entries when you have not visited the
	# site for some time. So we wind up through @entryrelations until we
	# find a thread with "0" as parent.
	if (-e $db) {
		open ENTRYBASE, "<$db";
	 	@entryrelations = <ENTRYBASE>;
		close ENTRYBASE;

		my $topparent = $entrynumber;
		my $nextparent = $topparent;
		my $index = $entrynumber - 1;
		do {
			my $entry = $entryrelations[$index];
			chomp $entry;
			if ($entry =~ /$topparent\|/) {
				(my $child, $nextparent) = split /\|/, $entry;
				if ($nextparent > 0) {
					$topparent = $nextparent;
				}
			}
			$index--;
		} while (($nextparent > 0) && ($index >= 0));
		# It's safe to cut of all entries up to, but not including,
		# this topmost parent (child of "0"). They would only slow down
		# determining the relations.
		@entryrelations = @entryrelations[++$index..$#entryrelations];
		$EntryInfo{'topmost'} = $entrynumber;
		PrintEntries($section, $topparent, 'recursive');
	}

	# Restore the original headline
	$EntryInfo{'headline'} = $EntryInfo{'clickedheadline'};
	OutputHTMLFile($section, 'addentry.tpl');
	OutputHTMLFile($section, 'forum.end');

	# Prior to version 1.04, no "cnt"-file was written by default.
	my $numhits = 0;
	if (-e $basedir . "sections/$section/entries/$entrynumber.cnt") {
		open COUNT, "<$basedir" . "sections/$section/entries/$entrynumber.cnt";
		$numhits = <COUNT>;
		close COUNT;
		chomp $numhits;
	}
	$numhits++;
	open COUNT, ">$basedir" . "sections/$section/entries/$entrynumber.cnt";
	print COUNT $numhits;
	close COUNT;

}

sub WriteEntry
{
	my $section = $thesection;
	my $parent = filterUserInput($cgi->param('parent'));
	if ($parent !~ /^\d+$/) {
		# How insane must a brain be to try these things ??
		# To all you phreakers: Stop wasting your time and program
		# something useful yourself.
		$parent = 0;
	}

	my $email = $cgi->param('email');
	my $author = $cgi->param('author');
	my $password = $cgi->param('password');

	my $text = $cgi->param('text');
	my $headline = $cgi->param('headline');


	my $entryinfo = '';

	my $authornum = -1;
	if (-e $basedir . "users/users.db") {
		open USERS, "<$basedir" . "users/users.db";
		while (<USERS>) {
			my ($usernum, $name) = split /\|/;
			if (!$name) { next; }
			chomp $name; chomp $author;
			if ($name eq $author) {
				$authornum = $usernum;
				last;
			}
		}
		close USERS;
	}
	if ($authornum >= 0) {

		open PW, "<$basedir" . "users/$authornum.pwl";
		my $savedpw = <PW>;
		close PW;
		$savedpw = EncDec($savedpw);
		if ($savedpw ne $password) {
			OutputHTMLFile($section, "usr/wrongpw.html");
			return;
		}
		open EMAIL, "<$basedir" . "users/$authornum.eml";
		my $registeredemail = <EMAIL>;
		if (!$registeredemail) { $registeredemail = " "; }
		close EMAIL;


		if ((!$email) || ($registeredemail eq $email)) {
			$email = "seeeml";
		}
		$entryinfo = "REGISTERED$authornum\|" . localtime() ."\|$email";
	} else {
		if ($only_registered) {
			OutputHTMLFile($section, 'usr/notregistered.html');
			return;
		}
		$entryinfo = "$author\|" . localtime() . "|$email";
	}

	my $entriesfile = "$basedir" . "sections\/$section\/entries/entries.db";
	my $latestentry = getLatestEntry($entriesfile);
	my $thisentry = $latestentry + 1;
	if ($parent > $latestentry) {
		# see above
		$parent = $latestentry;
	}

	open ENTRIES, ">>$entriesfile";
	print ENTRIES "$thisentry\|$parent\n";
	close ENTRIES;

	open INF,">$basedir"."sections\/$section\/entries\/$thisentry\.inf";
	print INF "$entryinfo\n";
	close INF;

	open MSG, ">$basedir" . "sections/$section/entries/$thisentry.msg";
	print MSG $text;
	close MSG;

	open HDL, ">$basedir" . "sections/$section/entries/$thisentry.hdl";
	print HDL $headline;
	close HDL;

	open CNT, ">$basedir" . "sections/$section/entries/$thisentry.cnt";
	print CNT "0";
	close CNT;

	FillEntryInfo($section, $thisentry, 1);
	OutputHTMLFile($section, "usr/entrysent.html");
}

sub CheckHTMLOverride
{
	my ($section, $file) = @_;
	if (!-e $basedir . "sections/$section/html/$file") {
		return $basedir . "html/$file";
	} else {
		return $basedir . "sections/$section/html/$file";
	}
}

sub OutputHTMLFile
{
	my ($section, $file) = @_;
	my $filename = CheckHTMLOverride($section, $file);
	if (-e $filename) {
		open HTMLFILE, "<$filename";
		while (<HTMLFILE>) {
			if ($_) { print SubstRefVars($_); }
		}
		close HTMLFILE;
	} else {
		print "File $filename does not exist!";
	}
}

sub ShowSection
{
	my $section = shift();
	OutputHTMLFile($section, 'forum.hdr');
	$EntryInfo{'topmost'} = 0;
	PrintEntries($section, 0, 'recursive');
	OutputHTMLFile($section, 'searchsection.tpl');
	OutputHTMLFile($section, 'newentry.tpl');
	OutputHTMLFile($section, 'forum.end');
}

sub DoSearch
{
	my $section = shift();
	my $searchstring = $cgi->param("searchstring");
	OutputHTMLFile($section, 'forum.hdr');
	my $normal_template = LoadTemplate($section, "normalentry.tpl");
	my $path = $basedir . "sections/$section/entries";

	my @sortedentries = ();
	foreach my $entry (<$path/*.msg>) {
		(my $entrynum = $entry) =~ s/.*\/(.*)\.msg/$1/;
		if (!-e "$path/$entrynum.del") {
			my $hdl = FileToScalar("$path/$entrynum.hdl");
			if ($hdl =~ /$searchstring/i) {
				push @sortedentries, $entrynum;
			} else {
				my $msg = FileToScalar("$entry");
				if ($msg =~ m/$searchstring/i) {
					push @sortedentries, $entrynum;
				}
			}
		}
	}
	@sortedentries = sort {$b <=> $a} @sortedentries;

	foreach my $entrynum (@sortedentries) {
		FillEntryInfo($section, $entrynum, 0);
		print SubstRefVars($normal_template);
	}
	OutputHTMLFile($section, 'navigation.tpl');
}

sub AddUser
{
	if ($allow_registration == 0) {
		OutputHTMLFile($thesection, 'usr/notallowed.html');
		return;
	}

	my $newuser = $cgi->param('name');
	my $newemail = $cgi->param('email');
	my $newpw = $cgi->param('newpw');
	my $retypedpw = $cgi->param('retpw');

	my $lastip = " ";
	if (-e $basedir . "users/lastip") {
		open LASTIP, "<$basedir" . "users/lastip";
		$lastip = <LASTIP>;
		chomp $lastip;
		close LASTIP;
	}

	# Comment this out to prohibit multiple messages from one IP. To make
	# this feature useful, one should also implement a timeout.
	# if ($lastip eq $ENV{'REMOTE_ADDR'}) {
	# 	OutputHTMLFile("none", 'usr/onepip.html');
	# 	return;
	# }


	chomp $newuser;
	my $authornum = -1;
	my $lastusernum = -1;

	if (-e $basedir . "users/users.db") {
		open USERS, "<$basedir" . "users/users.db";
		while (<USERS>) {
			my ($usernum, $name) = split /\|/;
			chomp $name;
			if ($name eq $newuser) {
				$authornum = $usernum;
			}
			$lastusernum = $usernum;
		}
		close USERS;
	}
	if ($authornum >= 0) {
		OutputHTMLFile($thesection, 'usr/notfree.html');
		return;
	}

	if ($newpw ne $retypedpw) {
		OutputHTMLFile($thesection, 'usr/nopwmatch.html');
		return;
	}

	my $newusernum = $lastusernum + 1;
	open USERS, ">>$basedir" . "users/users.db";
	print USERS "$newusernum\|$newuser\n";
	close USERS;

	open EMAIL, ">>$basedir" . "users/$newusernum.eml";
	print EMAIL "$newemail";
	close EMAIL;

	my $encpw = EncDec($newpw);
	open PW, ">$basedir" . "users/$newusernum.pwl";
	print PW "$encpw";
	close PW;

	# Write username also in separate file
	open SYNTAX, ">$basedir" . "users/$newusernum.syn";
	print SYNTAX "$newuser";
	close SYNTAX;

	open LASTIP, ">$basedir" . "users/lastip";
	print LASTIP "$ENV{'REMOTE_ADDR'}";
	close LASTIP;

	OutputHTMLFile($thesection, "usr/registered.html");
}


print "Content-type: text/html\n\n";

# Load configuration file

open CONF, "<cgiforum.conf";
while (<CONF>) {
	s/\r//g;
	chomp;
	my ($variable, $value) = split /=/, $_;
	if ($variable =~ /basedir/i) {
		$basedir = $value;
		if (substr($basedir, -1, 1) ne '/') {
			$basedir .= '/';
		}
	} elsif ($variable =~ /period\_new/i) {
		$period_new = $value;
	} elsif ($variable =~ /default_day_limit/i) {
		$default_day_limit = $value;
	} elsif ($variable =~ /default_author/i) {
		$default_author = $value;
		if (!$default_author) { $default_author = ' '; }
	} elsif ($variable =~ /default_headline/i) {
		$default_headline = $value;
		if (!$default_headline) { $default_headline = ' '; }
	} elsif ($variable =~ /start_entry/i) {
		(my $sec = $variable) =~ s/start_entry_(.*)/$1/;
		$start_entries{$sec} = $value;
	} elsif ($variable =~ /load_text/i) {
		$doload_text = $value;
		if (!$doload_text) { $doload_text = 0; }
	} elsif ($variable =~ /only_registered/i) {
		$only_registered = $value;
		if (!$only_registered) { $only_registered = 0; }
	} elsif ($variable =~ /allow_registration/i) {
		$allow_registration = $value;
		if (!$allow_registration) { $allow_registration = 0; }
	}
}
close CONF;


$thesection = $cgi->param('thesection') || 'default';
$thesection = filterUserInput($thesection);  # Security measure
# I have written "A Comment on Bugtracking" on this issue:
# http://triskam.virtualave.net/bugtracking.html

# Load weekday-names
if (!(-e "$basedir" . "sections/$thesection/html/wdays")) {
	open WDAYS, "<$basedir" . "html/wdays";
} else {
	open WDAYS, "<$basedir" . "sections/$thesection/html/wdays";
}
my $counter = 0;
while (<WDAYS>) {
	chomp;
	$FullWeekDay{$ShortWeekDays[$counter]} = $_;
	$counter++;
}

close WDAYS;


$EntryInfo{'basedir'} = $basedir;
$EntryInfo{'section'} = $thesection;

$EntryInfo{'end'} = $cgi->param('end') || 0;
$EntryInfo{'start'} = $cgi->param('start') || 0;
if ($EntryInfo{'start'} == 0) {
	if ($EntryInfo{'end'} == 0) {
		$EntryInfo{'start'} = $default_day_limit;
	}
}


if ((!$cgi->param('action')) || ($cgi->param('action') eq 'showsection')) {
	ShowSection($thesection);
} elsif ($cgi->param('action') eq "addentry") {
	WriteEntry();
} elsif ($cgi->param('action') eq "showentry") {
	ShowEntry($thesection, filterUserInput($cgi->param('entry')))
} elsif ($cgi->param('action') eq "adduser") {
	AddUser();
} elsif ($cgi->param('action') eq "search") {
	DoSearch($thesection);
}

