#!/usr/bin/perl
# -*- Perl -*-
# CONFIG: Change the first line to indicate the Perl binary on your system.
# Try "whereis perl" or "find / -name perl -print"
###############################################################################
## ##
## AccessWatch v1.33 - Access accounting for World Wide Web sites ##
## Copyright (C) 1994-1996 by David G. Maher. All rights reserved. ##
## ##
## ##
## Contact Information: ##
## Dave Maher ##
## PO Box 150 Fairfax, VA 22030-0150 ##
## ##
## ##
## Please direct comments to: ##
## ##
## ##
## Please read the included license agreement (readme.txt) before ##
## using this program. Your use of this software indicates your ##
## acceptance of the license agreement and warranty. ##
## ##
## If you wish to modify this code, mail . ##
## ##
###############################################################################
###############################################################################
########## Credits and thanks for great ideas #################################
###############################################################################
## ##
## A huge thank you to Paul Blackman for ##
## his work on hourly server statistics, including a table of hourly ##
## accesses/hour. ##
## ##
## Thanks to Jeff Boulter for access error ##
## exclusion code, and for his many suggestions and debugging help. ##
## ##
## Many thanks for suggestions and code tweaks: ##
## Chris Brown ##
## Ron Gery ##
## ##
###############################################################################
# *** File configuration ***
($base=$0) =~ s/[A-z0-9,\.,\-]*$//; # if you have trouble, define $base as
# the full directory pathname that
# contains the accesswatch script.
require $base.'accesswatch.cfg' || die "Configuration file not found: $!\n";
foreach (@ARGV) {
$verbose = 1
if (/v/); # turn on -v command line switch
$verbose = 0
if (/q/); # turn on -q command line switch
}
$summarylink = "current.html"; # Summary information link
$detailslink = "details.html"; # Access details link
$summaryfile = $base.$summarylink; # Summary Information file
$detailsfile = $base.$detailslink; # Access details file
$domaincodes = $base.'lib/domain.desc'; # Location of domaincodes database
$pagedescriptions = $base.'lib/page.desc'; # Text description of urls
# *** Graphics files ***
local(%horizbar) = ( 0, "img/blueblock.gif",
1, "img/redblock.gif"
);
local(%vertbar) = ( -1, "img/clearvert.gif",
0, "img/brwnvert.gif",
1, "img/ltgnvert.gif",
2, "img/pinkvert.gif",
3, "img/cyanvert.gif",
4, "img/orgvert.gif",
5, "img/purpvert.gif",
6, "img/yellvert.gif",
7, "img/grnvert.gif",
8, "img/bluevert.gif",
9, "img/redvert.gif"
);
# *** Other options ***
$truncate = 1; # Truncate extra path info for page demand list if too long.
$toolong = 50; # If you want to truncate, how *many* characters is too long?
###############################################################################
######## NO MODIFICATIONS MAY BE MADE TO THE FOLLOWING CODE ########
######## WITHOUT THE CONSENT OF THE AUTHOR ########
###############################################################################
# *** Data structures and counters ***
local(@accesses); # contains entire list of page accesses
local(%domains, %pages, %hosts);# contain list of domain extensions, pages,
# and unique hosts, and associates each
# with the appropriate count.
local(%pageDesc, %domainDesc); # lists of page urls/domaincodes with
# corresponding descriptions
local(%stat) = (
'accesses', '0', # count of pages served
'serverCount', '0', # server hits
'hits', '0', # total subdirectory hits
'localCount', '0', # number of accesses from local machines
'errors', '0', # number of answers > 400 from server
'redirect', '0', # number of redirects
'size', '0', # number of bytes transmitted
'uniqueHosts', '0', # computed by UpdateStatArray
'hostPageAverage','0', # computed by UpdateStatArray
'serverLoad', '0', # computed by UpdateStatArray
'localPercent', '0', # computed by UpdateStatArray
'outsidePercent', '0', # computed by UpdateStatArray
'outsideCount', '0', # computed by UpdateStatArray
'accessesPerHour','0', # computed by UpdateStatArray
'accessesPerDay', '0', # computed by UpdateStatArray
'hr00', '-1', # accesses in hour 0
'hr01', '-1', # accesses in hour 1
'hr02', '-1', # accesses in hour 2
'hr03', '-1', # accesses in hour 3
'hr04', '-1', # accesses in hour 4
'hr05', '-1', # accesses in hour 5
'hr06', '-1', # accesses in hour 6
'hr07', '-1', # accesses in hour 7
'hr08', '-1', # accesses in hour 8
'hr09', '-1', # accesses in hour 9
'hr10', '-1', # accesses in hour 10
'hr11', '-1', # accesses in hour 11
'hr12', '-1', # accesses in hour 12
'hr13', '-1', # accesses in hour 13
'hr14', '-1', # accesses in hour 14
'hr15', '-1', # accesses in hour 15
'hr16', '-1', # accesses in hour 16
'hr17', '-1', # accesses in hour 17
'hr18', '-1', # accesses in hour 18
'hr19', '-1', # accesses in hour 19
'hr20', '-1', # accesses in hour 20
'hr21', '-1', # accesses in hour 21
'hr22', '-1', # accesses in hour 22
'hr23', '-1', # accesses in hour 23
'maxhouraccess', '0', # maximum accesses per hour
'minhouraccess', '0', # minimum accesses per hour
);
local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
local($startTime);
local(@mnths, @longmonths);
$version = "1.33"; # Do not touch this line, even if you hack at the code!
##############################################################################
&Main;
#-----------------------------------------------------------------------------#
# AccessWatch function - Main
# Purpose : Coordinates everything else...
#-----------------------------------------------------------------------------#
sub Main {
$startTime = time;
$currdate = &SetDateInfo; # returns Day/Mon/Year
print "AccessWatch v$version starting.\n" if $verbose;
&ProcessLog;
&PrepareSummaryPage;
&PrepareHostDetailsPage;
print "Finished - Output is in $summarylink.\n" if $verbose;
exit 0;
}
#-----------------------------------------------------------------------------#
# AccessWatch function - ProcessLog
# Purpose : Scans through access log and picks out the appropriate accesses
#-----------------------------------------------------------------------------#
sub ProcessLog {
$| = 1; print "Parsing access log..." if $verbose; $| = 0;
local($remote, $dash1, $dash2, $date, $tz,
$method, $page, $protocol, $protnum1, $size);
open (LOG, "<$accessLog") || die "Couldn't open $accessLog\n";
# &FastSearch; # position pointer at start of day using a fast search
while () {
# start at the current date and push all access relevant info into lists
if ($verbose && $stat{'serverCount'} % 50 == 1) {
$| = 1;
print ".";
$| = 0;
}
#if (/$currdate/i) {
chomp;
# Un-Webify plus signs and %-encoding
tr/+/ /;
tr/ //s;
s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
$stat{'serverCount'}++;
if (/$includeURL/i && (! /$excludeURL/i || $excludeURL eq "")) {
($remote, $dash1, $dash2, $date, $tz,
$method, $page, $protocol, $protnum1, $size)
= split(/ /);
$page =~ s/(.*)\?.*/$1/;
$date =~ s/\[//;
local($date, $hour, $min, $sec) = split(":", $date);
$stat{'hits'}++;
# $stat{'size'} += $size/1000;
$stat{'size'} += $size;
if ($protnum1 < 400 && !($protnum1 eq "302")) {
&RecordStats($date, $hour, $min, $sec, $remote, $page);
}
else {
if ($protnum1 eq "302") { $stat{'redirect'}++; }
else { $stat{'errors'}++; }
}
}
elsif (/$includeURL/i) {
$stat{'hits'}++;
($remote, $dash1, $dash2, $date, $tz,
$method, $page, $protocol, $protnum1, $size)
= split(/ /);
$stat{'size'} += $size if ($size =~ /^\d.*/);
# $stat{'size'} += $size/1000 if ($size =~ /^\d.*/);
}
}
# }
close (LOG);
print " done.\n" if $verbose;
}
#-----------------------------------------------------------------------------#
# AccessWatch function - SetDateInfo
# Purpose : Sets global date variables, returns Day/Month/Year as specified
# by log standards.
#-----------------------------------------------------------------------------#
sub SetDateInfo {
#get current date and return as string (day/month/year)...
@mnths = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
@longmonths = ('January', 'February', 'March', 'April', 'May',
'June', 'July', 'August', 'September', 'October',
'November', 'December');
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
$year = "19$year";
$mday = "0$mday" if ($mday < 10);
return "$mday/$mnths[$mon]/$year";
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintSummaryPage
# Purpose : Coordinates construction of summary interface.
#-----------------------------------------------------------------------------#
sub PrintSummaryPage {
&UpdateStatArray;
if ($stat{'accesses'} eq "0") {
print OUT <
No accesses have been made to $siteName.
EOM
return;
}
&PrintStatsParagraph;
print OUT <
EOM
&PrintTableSummaryStats;
&PrintTableHourlyStats; # Added with much help from Paul Blackman
&PrintTablePageStats;
&PrintTableDomainStats;
&PrintTableHostStats;
print OUT <
EOM
}
#-----------------------------------------------------------------------------#
# AccessWatch function - FastSearch
# Purpose : Scans quickly from the bottom of the access log to start
# of the current day.
#-----------------------------------------------------------------------------#
sub FastSearch {
# parses through access log from the bottom up for speed, searching
# for the start of the current day...
local($avgday) = 10000 * $hour + 1000;
local($logsize) = (-s LOG);
local($logoffset) = 0;
local($jumps) = 0;
$logoffset = $logsize - $avgday if ($logsize > $avgday);
seek (LOG, $logoffset, 0);
;
$_=;
while (/$currdate/i && $logoffset > 0 && ) {
$jumps++;
# print "$_\n";
$logoffset = $logoffset - 5000;
$logoffset = 0 if ($logoffset <= 0);
seek (LOG, $logoffset, 0);
;
$_=;
}
# print "***Jumps = $jumps***\n";
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrepareSummaryPage
# Purpose : Opens summary file, calls functions to write data, closes, and
# sets the appropriate permissions.
#-----------------------------------------------------------------------------#
sub PrepareSummaryPage {
$| = 1; print "Preparing Summary... " if $verbose; $| = 0;
open (OUT, ">$summaryfile") || die "Couldn't open $summaryfile\n";
&PrintHeader;
&PrintSummaryPage;
&PrintFooter;
close (OUT);
chmod (0644, $summaryfile);
print "done.\n" if $verbose;
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrepareHostDetailsPage
# Purpose : Opens host details file, calls functions to write data, closes,
# and sets the appropriate permissions.
#-----------------------------------------------------------------------------#
sub PrepareHostDetailsPage {
if ($details) {
open (OUT, ">$detailsfile") || die "No $detailsfile\n";
&PrintHeader;
&PrintHostDetailsList;
&PrintFooter;
close (OUT);
chmod 0644, $detailsfile;
}
}
#-----------------------------------------------------------------------------#
# AccessWatch function - RecordStats
# Purpose : Takes a single access as input, and updates the appropriate
# counters and arrays.
#-----------------------------------------------------------------------------#
sub RecordStats {
#tally server information, such as domain extensions, total accesses,
# and page information
local($date, $hour, $minute, $second, $remote, $page) = @_;
$remote =~ tr/[A-Z]/[a-z]/;
if ($remote !~ /\./) { $remote .= ".$orgdomain"; }
#takes care of those internal accesses that do not get fully
# qualified in the log name -> name.orgname.ext
local($domainExt) = &GetDomainExtension($remote, 1);
$stat{'accesses'}++;
$domains{$domainExt}++;
$hosts{$remote}++;
$pages{$page}++;
$stat{"hr".$hour}++;
push (@accesses, "$date $hour $min $sec $remote $page") if $details;
}
#-----------------------------------------------------------------------------#
# AccessWatch function - GetDomainExtension
# Purpose : Takes a hostname as input, and returns the domain suffix. If
# second argument is set to true, then it counts accesses
# from the local domain.
#-----------------------------------------------------------------------------#
sub GetDomainExtension {
local($domainExt) = $_[0];
local($shouldCount) = $_[1];
$stat{'localCount'}++ if ($domainExt =~ /.*$orgdomain/ && $shouldCount);
$domainExt =~ s/.*\.//g;
$domainExt = "ip address" if ($domainExt =~ /[0-9].*/);
$domainExt =~ tr/[A-Z]/[a-z]/;
return $domainExt;
}
#-----------------------------------------------------------------------------#
# AccessWatch function - DescribeDomain
# Purpose : Takes a domain extension as a parameter, and returns a detailed
# description as specified in the domain descriptions file
# provided. Caches file into memory if used more than once.
#-----------------------------------------------------------------------------#
sub DescribeDomain {
local($description) = "Unknown"; # Default domain description
local($domain) = $_[0]; # Domain extension (passed parameter)
if ($domain ne "ip address") {
if (!(keys %domainDesc)) {
open (CODES, "<$domaincodes") ||
die "Couldn't open $domaincodes\n";
while () {
chomp;
($code, $description) = split(' ');
$code =~ tr/[A-Z]/[a-z]/;
$domainDesc{$code} = $description;
}
close(CODES);
}
if ($domainDesc{$domain}) {
$description = $domainDesc{$domain};
}
}
return $description;
}
#-----------------------------------------------------------------------------#
# AccessWatch function - DescribePage
# Purpose : Takes a virtual URL as a parameter, and returns a detailed
# description as specified in the page descriptions file
# provided. Caches file into memory if used more than once.
#-----------------------------------------------------------------------------#
sub DescribePage {
local($url) = $_[0];
local($description) = $url;
if (!(keys %pageDesc)) {
open (DESC, "<$pagedescriptions") ||
die "Couldn't open $pagedescriptions...";
while () {
chomp;
/(\S+)\s+\"(.*)\"/;
$pageDesc{$1} = $2;
}
close(DESC);
}
if ($pageDesc{$url}) {
$description = $pageDesc{$url};
}
if ($truncate && length($url) > $toolong && $description eq $url) {
$description = reverse $url;
while (length($description) > $toolong) { chop $description; }
$description = "..." . reverse $description;
}
return $description;
}
#-----------------------------------------------------------------------------#
# AccessWatch sort routine - byDomain
# Purpose : Sort subroutine for sorting an array by domain suffix.
#-----------------------------------------------------------------------------#
sub byDomain {
local($aHost) = "";
local($bHost) = "";
local(@aTemp, @bTemp) = ();
if ($a =~ /[^0-9].*\.[^0-9].*/) {
@aTemp = reverse split(/\./, $a);
foreach (@aTemp) { $aHost .= $_ };
}
else {
$aHost = "zzzzzzz".$a;
}
if ($b =~ /[^0-9].*\.[^0-9].*/) {
@bTemp = reverse split(/\./, $b);
foreach (@bTemp) { $bHost .= $_ };
}
else {
$bHost = "zzzzzzz".$b;
}
return ($aHost cmp $bHost);
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintHostDetailsList
# Purpose : Prints list of all accesses on server - date and page, sorted
# remote host.
#-----------------------------------------------------------------------------#
sub PrintHostDetailsList {
local(%hostlist) = ();
local($bdelim) = "s$;";
local($edelim) = "e$;";
local($pdelim) = "p$;";
print OUT <Access Details
EOM
}
sub byReverseNumber { $b <=> $a; }
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintStatsParagraph
# Purpose : Prints nice summary of crucial information
#-----------------------------------------------------------------------------#
sub PrintStatsParagraph {
#prints summary of gathered access statistics, with graphical
# representation of percentage of hits according to domain
print OUT "
Monthly Access Statistics";
print OUT "
\n";
$TotalAccess=&commas($stat{'accesses'});
$TotalHosts=&commas($stat{'uniqueHosts'});
print OUT <$TotalAccess
accesses by $TotalHosts unique hosts viewing an average of $stat{'hostPageAverage'} pages related to $siteName.
EOM
print OUT "Of these, ";
printf OUT ("$stat{'localCount'} (%.3g%%)", $stat{'localPercent'});
print OUT " have been from $orgname, and ";
$TotalOuts=&commas($stat{'outsideCount'});
print OUT "$TotalOuts ";
printf OUT ("(%.3g%%)", $stat{'outsidePercent'});
$TotalHits=&commas($stat{'hits'});
print OUT <
There have been a total of $TotalHits hits and $stat{'errors'} errors related
to $siteName, accounting for
EOM
printf OUT ("%.3g%% of total server hits and consisting of ", $stat{'serverLoad'});
$TotalBytes=&commas($stat{'size'});
print OUT " $TotalBytes bytes of information.
";
# Following lines removede to convert to monthly stats
# printf OUT ("There have been %3.1f", $stat{'accessesPerHour'});
# print OUT " accesses per hour, and at this rate, $siteName will get ";
# printf OUT ("%d", $stat{'accessesPerDay'});
# print OUT " accesses today.
\n";
}
#-----------------------------------------------------------------------------#
# commas function -
# Purpose : insert appropriate commas
#-----------------------------------------------------------------------------#
sub commas
{
local ($_) =@_;
1 while s/(.*\d)(\d\d\d)/$1,$2/;
$_;
}
#-----------------------------------------------------------------------------#
# AccessWatch function - UpdateStatArray
# Purpose : Computes statistics based on accumulated counters.
#-----------------------------------------------------------------------------#
sub UpdateStatArray {
# variable descriptions and computations
# $stat{'count'} = absolute number of accesses
# $stat{'hits'} = number of page related hits on server
# $stat{'servercount'} =total number of hits on server
# $siteName = description of page
# $serverload - % of server hits related to page
# $stat{'localcount'} - number of accesses from within organization
# $outside - number of accesses from outside hosts
# $pctlocal - % of accesses from within organization
$stat{'serverLoad'} = 0;
$stat{'localPercent'} = 0;
$stat{'outsidePercent'} = 0;
$stat{'outsideCount'} = $stat{'accesses'} - $stat{'localCount'};
$stat{'accessesPerHour'} = 0;
$stat{'serverLoad'} = $stat{'hits'} / $stat{'serverCount'} * 100
if ($stat{'serverCount'} > 0);
$stat{'localPercent'} = $stat{'localCount'} / $stat{'accesses'} * 100
if ($stat{'accesses'} > 0);
$stat{'outsidePercent'} = $stat{'outsideCount'} / $stat{'accesses'} * 100
if ($stat{'accesses'} > 0);
$stat{'accessesPerHour'} = ($stat{'accesses'} / (($hour * 60) + $min)) * 60
if ($hour * 60 + $min > 0);
$stat{'accessesPerDay'} = $stat{'accessesPerHour'} * 24;
$stat{'uniqueHosts'} = keys %hosts;
$stat{'hostPageAverage'} =
sprintf("%3.1f", $stat{'accesses'}/$stat{'uniqueHosts'})
if ($stat{'uniqueHosts'} != 0);
$stat{'accessesPerHour'} = sprintf("%3.1f", $stat{'accessesPerHour'});
$stat{'accessesPerDay'} = sprintf("%d", $stat{'accessesPerDay'});
$stat{'maxhouraccess'} = 0;
$stat{'minhouraccess'} = 0;
foreach $hournum ('00'..'23') {
$stat{'maxhouraccess'} = $stat{"hr".$hournum}
if ($stat{"hr".$hournum} > $stat{'maxhouraccess'});
$stat{'minhouraccess'} = $stat{"hr".$hournum}
if (($stat{'minhouraccess'} == 0 ||
$stat{"hr".$hournum} < $stat{'minhouraccess'}) &&
$stat{"hr".$hournum} != -1);
}
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintTableDomainStats
# Purpose : Prints table of domains, sorted by number of accesses.
#-----------------------------------------------------------------------------#
sub PrintTableDomainStats {
return if ($maxDomainsToList == 0);
print OUT <
";
local($description) = &DescribeDomain($Mdomain);
print OUT "
$description
";
print OUT "
$Mcount
";
$pct = 0.00;
$pct = $Mcount / $stat{'accesses'} * 100 if ($stat{'accesses'} > 0);
printf OUT ("
%3.2f
\n", $pct);
print OUT "
";
&PrintBarHoriz($pct,0);
print OUT "
\n";
}
print OUT "
Also, hosts from the following domains visited: " if (@othDomains);
foreach (@othDomains) {
tr/[A-Z]/[a-z]/;
local($description) = &DescribeDomain($_);
if ($#othDomains) {
print OUT "$description ($domains{$_}), ";
}
else {
print OUT "and $description ($domains{$_}).";
}
shift(@othDomains);
}
print OUT "
\n
\n";
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintTableHostStats
# Purpose : Prints table of hosts, sorted by number of accesses.
#-----------------------------------------------------------------------------#
sub PrintTableHostStats {
return if ($maxHostsToList == 0);
print OUT <
";
$pct = 0.00;
$pct = $Mcount / $stat{'accesses'} * 100 if ($stat{'accesses'} > 0);
printf OUT ("
%3.2f
\n", $pct);
print OUT "
";
&PrintBarHoriz($pct,0);
print OUT "
\n";
}
print OUT <
Access Details:A list of individual accesses, sorted by host
EOM
print OUT "
\n";
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintTablePageStats
# Purpose : Prints table of pages, sorted by number of accesses.
#-----------------------------------------------------------------------------#
sub PrintTablePageStats {
# outputs a table of pages accessed, ranked in order of demand
return if ($maxPagesToList == 0);
print OUT <
Page Demand
Of the $stat{'uniqueHosts'} hosts that visited this month, each traversed an average of $stat{'hostPageAverage'} pages.
\n";
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintTableHourlyStats
# Purpose : Prints bar graph of accesses over the course of the current
# day. Thanks very much to Paul Blackman for his work on
# this function.
#-----------------------------------------------------------------------------#
sub PrintTableHourlyStats {
local($hourBar) = "img/hourbar.gif";
local($hour, $pct);
print OUT <
\n", (1 - $pct/10) * $stat{'maxhouraccess'});
}
print OUT <
EOM
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintBarVert
# Purpose : Prints a vertical bar with height as specified by argument.
#-----------------------------------------------------------------------------#
sub PrintBarVert {
local($pct) = $_[0];
local($colorbar) = $vertbar{$_[1]};
local($scale) = 0;
$scale = $pct/$stat{'maxhouraccess'} * 200 if ($stat{'maxhouraccess'});
print OUT "", $scale);
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintBarHoriz
# Purpose : Prints a horizontal bar with width as specified by argument.
#-----------------------------------------------------------------------------#
sub PrintBarHoriz {
local($pct) = $_[0];
local($colorbar) = $horizbar{$_[1]};
local($scale) = 1;
$scale = ($pct*8)/log $pct + 1 if ($pct > 0);
print OUT "", $scale);
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintTableSummaryStats
# Purpose : Prints a table which contains general statistics.
#-----------------------------------------------------------------------------#
sub PrintTableSummaryStats {
print OUT <
Summary Statistics
Count
% of total
Accesses from $orgname
$stat{'localCount'}
EOM
printf OUT ("
%.3g%%
", $stat{'localPercent'});
print OUT "
";
&PrintBarHoriz($stat{'localPercent'}/2,0);
print OUT "
";
print OUT <
Outside Accesses
$stat{'outsideCount'}
EOM
printf OUT ("
%.3g%%
", $stat{'outsidePercent'});
print OUT "
";
&PrintBarHoriz($stat{'outsidePercent'}/2,0);
print OUT "
";
print OUT <
Total Page Accesses
$stat{'accesses'}
100%
EOM
print OUT "
";
&PrintBarHoriz(50,1);
print OUT "
";
print OUT <
Total hits related to page
$stat{'hits'}
EOM
printf OUT ("
%.3g%%
", $stat{'serverLoad'});
print OUT "
";
&PrintBarHoriz($stat{'serverLoad'}/2,0);
print OUT "
";
print OUT <
Total hits on server
$stat{'serverCount'}
100%
EOM
print OUT "
";
&PrintBarHoriz(50,1);
print OUT "
";
print OUT <
EOM
}
#-----------------------------------------------------------------------------#
# AccessWatch function - PrintHeader
# Purpose : Creates HTML header for page and sends it to OUT.
#-----------------------------------------------------------------------------#
sub PrintHeader {
# *** Do not modify or remove the call to this function. ***
# Purpose: creates an HTML header for the page
local($totalTime) = time - $startTime;
print OUT <$siteName - AccessWatch Summary
Accesses for $siteName
$longmonths[$mon] $mday, $year
AccessWatch took $totalTime seconds to gather current data
EOM
}
#------------------------------------------------------------------------------
# AccessWatch function - PrintFooter
# Purpose : Creates HTML footer for page and sends it to OUT.
# Note : *** Do not modify this function, or remove its call. ***
#------------------------------------------------------------------------------
sub PrintFooter {
local($fSiteName) = $siteName;
$fSiteName =~ tr/ /+/;
$fSiteName = "Unknown" if ($fSiteName eq "");
print OUT <
$customFooter