#!/usr/bin/perl
##!e:/perl/bin/perl.exe

# Written by Nigel Peck, MIS Web Design
# e: nigel@miswebdesign.com
# m: 07789 417 351
# w: http://www.miswebdesign.com/
#
# Copyright Seb Schmoller 2004

use strict;
use XML::LibXML;
use CGI;
use IO::AtomicFile;

sub build_dom (\$\$\$);
sub commit_changes ($$\$);
sub error ($);

my $query = new CGI;
$CGI::DISABLE_UPLOADS = 1;

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

my $lasterror;

my $data_file = "/home/sebs/pageviews/data_file.xml";
#my $data_file = "c:/web/www.schmoller.net/pageviews/data.xml";

my $template = "/home/sebs/pageviews/index_template.html";
#my $template = "c:/web/www.schmoller.net/index_template.html";

my $data;

build_dom($data, $data_file, $lasterror)
	|| error($lasterror);

my $insert = {};

foreach my $page ( $data->findnodes('//page') ) {
	my $location = $page->getAttribute('location');
	my $views = $page->getAttribute('views');
	my $starttime = $page->getAttribute('starttime');
	
	my $timediff = time - $starttime;
	my $months = int($timediff / 2592000) + 1;
	my $average = $views / $months;
	
	$insert->{'l' . $location} = $views;
	$insert->{'l' . $location . 'a'} = int($average);
}

open(TEMPLATE, "$template") || error "Failed to open template : $template : $!\n";
while(<TEMPLATE>) { print parse_line($_, $insert); }
close(TEMPLATE);

##########################
#      COMMON SUBS       #
##########################

sub error ($) {
	my ($errormsg) = @_;
	print "<h2>Error</h2>\n";
	print "<p>Please note the information below, this was the cause of the error.</p>\n";
	print "<p>" . $errormsg . "</p>\n";
	die;
}

##########################
#       DOM STUFF        #
##########################

sub build_dom (\$\$\$) {
	my ($doc, $config, $errormsg) = @_;
	
	my $parser = XML::LibXML->new();
	$parser->validation(0);
	$parser->expand_entities(1);
	$parser->keep_blanks(0);
	$parser->pedantic_parser(0);
	$parser->load_ext_dtd(0);
	$parser->complete_attributes(1);
	
	eval { $$doc = $parser->parse_file( $$config ) };
	if ($@) { $$errormsg = "build_dom error: " . $@ . "\n"; return 0; }
	else { return 1; }
}

sub commit_changes ($$\$) {
	my ($doc, $file, $errormsg) = @_;
	my $fh;
	unless ($fh = IO::AtomicFile->open($file,"w"))	{ $$errormsg = "Couldn't open filehandle to $file : $!";
							  return 0; }
	
	eval	{ $doc->toFH($fh, 1) };
	if ($@) { $fh->delete();
		  $$errormsg = "commit_changes error with $file : " . $@ . "\n";
		  return 0;
	} elsif ( not $fh->close() )	{ $$errormsg = "Couldn't write file $file";
	} else { return 1 }
}

sub parse_line {
	$_ = shift; my $insert = shift;
	s/&sb([\w-]+?);/$insert->{$1}/g;
	return $_;
}
