#!/usr/bin/perl -w

# Starburst CMS | Perl Content Management System by Kirsle #
# -------------------------------------------------------- #
# To configure your site, access /index.cgi?p=setup in     #
# your web browser.                                        #

use strict;
use warnings;
use CGI;
use CGI::Carp qw(fatalsToBrowser);
use URI::Escape;
use Digest::MD5 qw(md5_hex);
use Data::Dumper;
use lib "./lib";
use Time::Format qw(time_format);
use Time::Local;
use Time::Zone;
use lib "/home/rivescript/glib";
use Cuvou::Traffic;
use Cuvou::BanBots;
our $root  = {
	# Base for pvt data. If you change this, also change it below at the
	# require statements.
	base    => "./sb-pvt",
	version => '0.01',
	header  => 0,       # 1 = the HTTP headers were already sent
	conf    => {},      # Main configuration data.
	me      => 'guest', # Our username (default=guest)
	auth    => 0,       # 1 = we're logged in, 0 = otherwise
	users   => {},      # Loaded user(s) information.
	cookie  => {},      # Loaded cookies.
	meta    => {},      # Header fields on pages.
	content => '',      # Eventual page contents.
	perl    => '',      # Any embedded Perl code in the pages.
};
our $cgi   = new CGI;
our $query = {
	p => 'index',
};

$root->{traffic} = new Cuvou::Traffic (
	cgi    => $cgi,
	domain => 'http:\/\/(www\.|vps\.|dev\.|local\.)rivescript\.(org|net|com)',
);
if ($root->{traffic}->cookie) {
	$root->{header} = 1;
}
$root->{stats} = $root->{traffic}->query();

# Define a fallback CGI::Carp failure page.
sub panic {
	my $msg = shift;
	if ($root->{header} == 0) {
		print "Content-Type: text/html\n\n";
	}
	print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" "
		. "\"http://www.w3.org/TR/html4/strict.dtd\">\n"
		. "<html>\n"
		. "<head>\n"
		. "<title>500 Internal Server Error</title>\n"
		. "<style type=\"text/css\">\n"
		. "body {\n"
		. " background-color: #FFFFFF;\n"
		. " font-family: Verdana,Arial,Helvetica,sans-serif;\n"
		. " font-size: small;\n"
		. " color: #000000;\n"
		. "}\n"
		. "h1 {\n"
		. " display: block;\n"
		. " font-size: xx-large;\n"
		. " font-weight: bold;\n"
		. " color: #000000;\n"
		. " margin-top: 0px;\n"
		. " margin-bottom: 20px\n"
		. "}\n"
		. "pre {\n"
		. " font-family: \"Lucida Console\",\"DejaVu LGC Sans Mono\","
		. "\"Bitstream Vera Sans Mono\",monospace;\n"
		. " font-size: small;\n"
		. " color: #000000;\n"
		. " display: block;\n"
		. " border: 1px dashed #999999;\n"
		. " padding: 5px\n"
		. "}\n"
		. "</style>\n"
		. "</head>\n"
		. "<body>\n"
		. "<h1>Internal Server Error</h1>\n\n"
		. "This page has generated an error. The text of the error is "
		. "as follows:<p>\n\n"
		. "<pre>$msg</pre><p>\n\n"
		. "Furthermore, there was no 500 Internal Server Error page to "
		. "handle this error.\n"
		. "<hr>\n"
		. "Starburst CMS\n"
		. "</body>\n"
		. "</html>";
	exit(0);
}
CGI::Carp::set_message (sub {
	$root->{header} = 1;
	&panic(shift);
});

# Load additional source files.
require "./sb-pvt/inc/config.lib";
require "./sb-pvt/inc/cgi.lib";
require "./sb-pvt/inc/users.lib";
require "./sb-pvt/inc/methods.lib";
require "./sb-pvt/inc/blog.lib";
require "./sb-pvt/inc/photos.lib";
require "./sb-pvt/inc/comments.lib";

# Load our configuration.
$root->{conf} = &readConfig("site.conf");

# Make sure the theme template exists (if not, it's pointless to continue).
if (!-f "$root->{base}/skin/template.html") {
	&panic("Theme template file not found ("
		. "!-f $root->{base}/skin/template.html)");
}

# Run preliminary CGI things.
&doQuery();    # Process the query string.
&getCookies(); # Load any cookies.
&checkAuth();  # Check if we're logged in.

################################################################################
## Attempt to get a page for the user.                                        ##
################################################################################

# Validate the requested page.
my $page = $query->{p} || 'index';
if ($page =~ /[^A-Za-z0-9\.\-]/) {
	$page = 400;
}
if (!-f "$root->{base}/pages/$page\.txt") {
	$page = 404;
}

# Read the page.
if (-f "$root->{base}/pages/$page\.txt") {
	# Wait if the file is being written to.
	&waitLock("$root->{base}/pages/$page\.txt");
	open (READ, "$root->{base}/pages/$page\.txt");
	my @data = <READ>;
	close (READ);
	chomp @data;

	# Read in the data.
	my $inHeader = 1;
	my $inPerl = 0;
	foreach my $line (@data) {
		if ($inHeader) {
			$line =~ s/^\s+//ig;
			$line =~ s/\s+$//ig;
			if (length $line == 0) {
				# End of headers.
				$inHeader = 0;
			}
			else {
				# Collect this header.
				my ($name,$value) = split(/\s*?:\s*?/, $line, 2);
				$name = &normalize($name);
				$value =~ s/^\s+//g;
				$value =~ s/\s+$//g;
				$name =~ s/^\s+//g;
				$name =~ s/\s+$//g;
				$root->{meta}->{$name} = $value;
			}
			next;
		}
		else {
			if ($line =~ /<perl>/i) {
				$inPerl = 1;
				next;
			}
			elsif ($line =~ /<\/perl>/i) {
				$inPerl = 0;
				next;
			}
			if ($inPerl) {
				$root->{perl} .= "$line\n";
			}
			else {
				$root->{content} .= "$line\n";
			}
		}
	}

	# Any perl code?
	if (length $root->{perl}) {
		# Execute it.
		eval ($root->{perl});
		if ($@) {
			&panic($@);
		}
	}
}
else {
	$root->{meta}->{title} = '404 Not Found';
	$root->{content} = "<h1>404 Page Not Found</h1>\n\n"
		. "The page you requested was not found. Furthermore, there was "
		. "no 404 Error Page to handle this error.";
}

# Load the template.
&waitLock("$root->{base}/skin/template.html");
open (READ, "$root->{base}/skin/template.html");
my @templ = <READ>;
close (READ);
chomp @templ;

# Process the page.
my $html = join ("\n",@templ);

# Run substitutions.
$html =~ s/\$content/$root->{content}/ig;
$html = &filters($html);

$html =~ s/\$hitsTTL/$root->{stats}->{hits_total}/ig;
$html =~ s/\$hitsTDY/$root->{stats}->{hits_today}/ig;
$html =~ s/\$uniqTTL/$root->{stats}->{unique_total}/ig;
$html =~ s/\$uniqTDY/$root->{stats}->{unique_today}/ig;

# Print the page.
if ($root->{header} == 0) {
	print "Content-Type: text/html\n\n";
}
print $html;
