#!/usr/bin/perl

$version = 0.02;
$this = "changeweb.cgi";

$path = "/var/lib/changetrack/";

@months =
("","January","February","March","April","May","June","July","August","September","October","November","December");
# couldn't be zero-based because I want the months to be all true.
# Also I think there's some other reason it didn't work.

use Text::ParseWords;
use Time::Local;

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

$| = 1;  # flush STDOUT

open(STDERR,">&STDOUT");
# let the web user see any errors.

$args = $ENV{QUERY_STRING};

# translate ampersands to semicolons, so we can be W3C compliant.
while($args =~ m/&/) { $args =~ s/&/;/; }

$args = $args . ";";
@ARGV = quotewords(";",0,$args); 
%things = {};

foreach $arg (@ARGV)
	{
	$arg = $arg . "=";
	($thing,$value) = quotewords("=",0,$arg);
	if(!$value) {$value=1;}
	$things{$thing} = $value;
	}

$year = $things{"year"}; if(!$year) {$year = 1999;}
$month= $things{"month"};if(!$month){$month= 1;}
$day  = $things{"day"};  if(!$day)  {$day  = 1;} elsif($day > 31) {$day = 31;}

$file = $things{"file"};
while($file =~ m/\.\./) {$file =~ s/\.\.//;}

$sort = $things{"sort"}; if(!$sort || $sort == 1) {$sort = "";} # deals with 'sort=' url problem

$date = timelocal(0,0,0,$day,$month-1,$year-1900); 

# feel free to add other groups of servers to monitor.
# note that each needs to have the same setup as the current ones;
# that should be cleaned up.

if($file)
	{
	$file =~ s/\.history//;	
	$title = $file;
	$file .= ".history";	
	while($title =~ m/:/) {$title =~ s/:/\//}
	$title = $title;
	}
else
	{
	$title = "Changetrack: $months[$month] $day, $year";
	}
print "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">
<html>
<head>
  $title

$title
  
  "; 

print "
 ";
# needs to be a table to be in one line. 

print "
	Since:
	
	$year";

@i = localtime;

$currentyear = $i[5] + 1900;

if($file) {$localfile = "file=$file";}

for($i = 1999; $i <= $currentyear; $i++)
	{
	print "$i";	
	}
print "";	
print " ";
print "
 ";
	
# table to keep arrows in place 
	print "	
	";

	for($i=1; $i <= 12; $i++)
		{	
		if($i == $month)
			{
			print "<option value=$i SELECTED>$months[$i]\n";

			}
		else
			{
			print "<option value=$i>$months[$i]\n";	
			}
		}
	print "</select>";
print " ";
print "
 \n";
                        # table to put arrows above each other

if($month < 12)         # month 'up' arrow 
  {
	# not into next year; increment month
	print "";
  }
else
  {
 	# next year; month -> Jan 
	print "";
  }
#print "";
print "+";
print "";
print "
 ";

if($month > 1)                                    # month 'down' arrow 
  {
	print "";
  }
else  
  {
	print "";
	}
#print "";
print "-";
print "";
print "

";
print "

";

print " ";
print "
 ";
print "";
print " ";
print "
 ";

@lens = (0,31,29,31,30,31,30,31,31,30,31,30,31); # Easiest to just assume Feb is always long.
$monlen = $lens[$month]; 
if($day < $monlen)
	{print "";}
else
	{
 	if($month < 12)
		{print "";}
	else
    {print "";}
	}
#print "";
print "+";
print "";
print "
 ";
if($day > 1)
	{print "";}
else
	{
	if($month > 1)
		{print "";}
	else
		{print "";}
	}	
#print "";
print "-";
print "";
print "

";
print "

";

print " ";
print "";
print "";	
print "

\n";

@i = stat "$path/etc:shutdownlog.history"; 
($i,$i,$i,$bootday,$bootmonth,$bootyear,$i,$i,$i) = localtime($i[9]);
$bootmonth++; $bootyear += 1900; 

print "
";

if($file)
	{
	open(FILE,"$path/$file") or die "Can't open $path/$file:
$!\n";
	print "<pre>";
	$found = 0;
	if(($month >= 1) && ($month <= 12))
		{
		while(<FILE>)
	 		{
	    $line = $_;
	    if(substr($line,0,2) ne "  ")
	     	{
	     	$fyear = substr($line,36,4);
				$fmonth= substr($line,20,3);
				$fday  = substr($line,24,2);	

				if(!$fday || !$fmonth || !$fyear)
					{
					next;	
					}

				# this is for reading from the file.
				($fmonth =~ s/Jan/1/) || ($fmonth =~
s/Feb/2/) || ($fmonth =~ s/Mar/3/) ||
					($fmonth =~ s/Apr/4/) || ($fmonth =~
s/May/5/) || ($fmonth =~ s/Jun/6/) ||
	        ($fmonth =~ s/Jul/7/) || ($fmonth =~ s/Aug/8/) || ($fmonth
=~ s/Sep/9/) ||
	        ($fmonth =~ s/Oct/10/)|| ($fmonth =~ s/Nov/11/)|| ($fmonth
=~ s/Dec/12/);

				$fdate =
timelocal(0,0,0,$fday,$fmonth-1,$fyear-1900); 
				if($fdate >= $date)
					{
	        print $line;
	        $found++;
	        last;   
					}
				}
      }       
    }

	if(!$found) {print "No changes since that date.\n";}

	while(<FILE>)
    {
    print $_;       
    }
	close(FILE);
	print "</pre>"; 
	}
else
	{	
	print "
\n";
	print "\n";

	$selectedc = "#b0b0b0";

	if(!$sort)
		{
		print "<td bgcolor=\"$selectedc\">";
		print "<center>[--]";
		}
	else
		{
		print "<td><center>";
		print "<a
href=\"$this?day=$day;month=$month;year=$year\">[--]
";
		}	
	print "
\n";
	
	if($sort eq "name")
		{
		print "<td bgcolor=\"$selectedc\">";
		print "<center>Filename";
		}
	else
		{
		print "<td>";
		print "<center><a
href=\"$this?day=$day;month=$month;year=$year;sort=name\">Filename";
		}	
	print "
\n";
	
	if($sort eq "size")
		{
		print "<td bgcolor=\"$selectedc\">";
		print "<center>Log Size";
		}
	else
		{	
		print "<td>";
		print "<center><a
href=\"$this?day=$day;month=$month;year=$year;sort=size\">Log Size";
		}	
	print "
\n";
	
	if($sort eq "date")
		{
		print "<td bgcolor=\"$selectedc\">";
		print "<center>Date Modified";
		}
	else
		{
		print "<td><center>";
		print "<a
href=\"$this?day=$day;month=$month;year=$year;sort=date\">Date Modified";
		}	
	print "

\n";	

	# There is no file, so show the directory listing.
	chdir("$path");
	open(LS,"ls *.history |") or die "Can't open ls $path: $!\n";

	$j = 1;
	@files = ();
	while(<LS>)
		{
		# list the files
		chomp;	
		$cname = $_;
		$hname = $_;
		@finfo = stat $cname;
		@fmdate = localtime($finfo[9]);
		$fyear = $fmdate[5] + 1900;
		$fmonth= $fmdate[4] + 1; 
		$fday  = $fmdate[3];
		$filesize = $finfo[7];

		$fdate = $finfo[9];
		$fdate = substr($fdate,0,10)." ".substr($fdate,-4,4);

		if(($month < 1) || ($month > 12)) {$fyear = 65535}
		#while($hname =~ m/:/) {$hname =~ s/:/\//;}
		$hname =~ s/.history$//;

		if($finfo[9] >= $date)
			{
			if($sort eq "size")
				{
				$line = "$filesize\t$cname\t$fdate\t$j\t";
				}
			elsif($sort eq "date")
				{
				$line = "$fdate\t$filesize\t$cname\t$j\t";

				}
			else
				{
				# name or invalid	
				$line = "$cname\t$filesize\t$fdate\t$j\t";

				}
			@files = (@files,$line);	
			}
		else
			{
			next;	
			# we can ignore this file.	
			}

		while($hname =~ m/:/) {$hname =~ s/:/\//;}
		$hname =~ s/\.history$//;
		$j++;	
		}

	if($sort)
		{
		if($sort eq "name")
			{@files = sort @files;}
		else
			{
			# descending numeric sort	
			# shows largest/newest files first.	
			sub numerically {$b <=> $a}	
			@files = sort numerically @files;	
			}
		}
	
	# extract everything from the list, and print it. 
	$j = 0;
	foreach $file (@files)
		{
		if($j%10 < 5)
			{
			$color = "#ffffff"; 	
			$hcolor= "#e4e4e4";	
			}
		else
			{
			$color = "#ddddff";
			$hcolor= "#ddddff";	
			}
		$j++;

		if($sort eq "size")
			{
			($fsize,$fname,$fdate,$fnum) =
quotewords("\t",0,$file);	
			}
		elsif($sort eq "date")
			{
			($fdate,$fsize,$fname,$fnum) =
quotewords("\t",0,$file);	
			}
		else
			{
			# name or invalid	
			($fname,$fsize,$fdate,$fnum) =
quotewords("\t",0,$file);
			}

		$fdate = scalar localtime($fdate);
		$fdate = substr($fdate,0,11) . substr($fdate,-4,4); 

		$hname = $fname;
		while($hname =~ m/:/) {$hname =~ s/:/\//;}
		$hname =~ s/\.history$//;
		$fname = "<a
href=\"$this?file=$fname;day=$day;month=$month;year=$year;sort=$sort\">$hname";

		print "<tr bgcolor=\"$color\">";
		if($sort eq "name")
			{
		  print "<td>$fnum</td><td
bgcolor=\"$hcolor\">$fname $fsize $fdate";  
			}
		elsif($sort eq "size")
			{
      print " $fnum $fname $fsize $fdate";  
			}
		elsif($sort eq "date")
			{
      print " $fnum $fname $fsize $fdate";  
			}
		else
			{
			print " $fnum $fname $fsize $fdate";
			}
		print "
\n";
		}

	print "</table>";
	if($month > 0 && $month < 13) {print "$j files modified since
$months[$month] $day, $year.";}
	close(LS);
	}

print "

 Copyright © 2003 Cameron Morland
Verbatim copying and distribution of this entire article is permitted in any medium, provided this notice is preserved.

";
