Приглашаем посетить
Соллогуб (sollogub.lit-info.ru)

WebLog

############################################
##                                        ##
##                 WebLog                 ##
##           by Darryl Burgdorf           ##
##       (e-mail burgdorf@awsd.com)       ##
##                                        ##
##         last modified: 5/24/97         ##
##           copyright (c) 1997           ##
##                                        ##
##    latest version is available from    ##
##        http://awsd.com/scripts/        ##
##                                        ##
############################################

# COPYRIGHT NOTICE:
#
# Copyright 1997 Darryl C. Burgdorf.  All Rights Reserved.
#
# This program may be used and modified free of charge by anyone, so
# long as this copyright notice and the header above remain intact.  By
# using this program you agree to indemnify Darryl C. Burgdorf from any
# liability.
#
# Selling the code for this program without prior written consent is
# expressly forbidden.  Obtain permission before redistributing this
# program over the Internet or in any other medium.  In all cases
# copyright and header must remain intact.

# VERSION HISTORY:
#
# 1.05  05/24/97  Added comma delineation to all numbers
#                 Added "record book" report
#                 Fixed new bug in "top" domain logging
# 1.04  05/03/97  Changed month/day logs from domains to sessions
#                 Added sessions to day-of-week log
#                 Allowed disabling of above sessions logging
#                 Allowed "details" log of only one day's accesses
#                 Enabled "top" domain logging even if domains off
#                 Added ability to log "second level" domains
#                 Fixed display bugs if no accesses on first day
#                 The typical selection of minor bug fixes
# 1.03  02/02/97  Added support for combined log files
#                 Added option to include file query information
#                 Corrected handling of zipped files
#                 Corrected bug in EOM report wrapping (Dec/Jan)
# 1.02  12/11/96  Added "running total" of user sessions
# 1.01  12/08/96  Added "user sessions" to details report
#                 Corrected day counting in details report
# 1.00  12/02/96  Initial "public" release

sub MainProg {
	&Initialize;
	&ReadOldFile;
	&ReadLog;
	&GetSessions;
	&PrintReport;
	if ($DetailsFile) { &PrintHostDetailsReport; }
}

sub Initialize {
	$version = "1.05";
	%MonthToNumber=
	  ('Jan','01','Feb','02','Mar','03',
	  'Apr','04','May','05','Jun','06',
	  'Jul','07','Aug','08','Sep','09',
	  'Oct','10','Nov','11','Dec','12');
	%NumberToMonth=
	  ('01','Jan','02','Feb','03','Mar',
	  '04','Apr','05','May','06','Jun',
	  '07','Jul','08','Aug','09','Sep',
	  '10','Oct','11','Nov','12','Dec');
	%RespEstimates=
	  ('200',180,'302',255,'304',98,'400',313,'401',281,
	  '403',268,'404',250,'500',485,'501',482);
	%DoWCounter=
	  (1,'Sun',2,'Mon',3,'Tue',4,'Wed',5,'Thu',6,'Fri',7,'Sat');
	$EndDate="0000 00 00 00 00 00";
	$StartDate="9999 99 99 99 99 99";
	$time=time;
	@days=(Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday);
	@shortdays=(Sun,Mon,Tue,Wed,Thu,Fri,Sat);
	@daybreaks=
	  ('(01|08|15|22|29)','(02|09|16|23|30)',
	  '(03|10|17|24|31)','(04|11|18|25|32)','(05|12|19|26|33)',
	  '(06|13|20|27|34)','(07|14|21|28|35)');
	@months=
	  (January,February,March,April,May,June,
	  July,August,September,October,November,December);
	@shortmonths=(Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec);
	($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
	  localtime($time-86400);
	$CurrDate="$days[$wday], $mday $months[$mon] 19$year";
	$CurrYear="19$year";
	$CurrMonth="$shortmonths[$mon]";
	$CurrDay="$shortdays[$wday]";
	if ($mday < 10) { $mday="0".$mday; }
	$CurrToday="$CurrYear $MonthToNumber{$CurrMonth} $mday";
	$DayBreaks="$daybreaks[$wday]";
	if(open(COUNTRIES,$CountriesFile)) {
		while(<COUNTRIES>) {
			($Code,$Description)=m#^(\w+)\s+(.*)$#;
			$Code=~tr/A-Z/a-z/;
			$CountryCode{$Code}=$Description;
		}
		close(COUNTRIES);
		$CountryCode{"xxx"}="Unresolved Domain";
	}
	$MonthCounter=0;
	$DayCounter=0;
	$DefaultPageName =
	  "(Welcome.html|welcome.html|index.html|index.shtml|README.html|index.cgi)";
}

sub ReadOldFile {
	$endTag="</PRE>";
	$InSegment=0;
	open (OLD,$ReportFile) || die "Error opening file: $ReportFile\n";
	OLDLINE: while (<OLD>) {
		chop;
		last OLDLINE if (m#</HTML>#oi);
		if (/<A NAME="(monthly|daily|dayofweek|hourly|records)">/oi) {
			$logsegment=$1;
			$InSegment=1;
			if ($logsegment ne 'records') {
				<OLD>;
				<OLD>;
				<OLD>;
			}
			next OLDLINE;
		} elsif (($mday ne "01") &&
		  (/<A NAME="(summary|files|404|topleveldomain|domains)">/oi)) {
			$logsegment=$1;
			$InSegment=1;
			if ($logsegment ne 'summary') {
				<OLD>;
				<OLD>;
				<OLD>;
			}
			next OLDLINE;
		}
		$InSegment=0 if ($_ eq $endTag);
		next OLDLINE if (!$InSegment);
		if ($logsegment eq "monthly") {
			($Accesses,$Bytes,$Domains,$Month) = 
			  m#^\s*([\d,]+)\s+([\d,]+)\s+([\d,]+|-)\s+(\w.{7})#o;
			$Accesses =~ s/,//g;
			$Bytes =~ s/,//g;
			$Domains =~ s/,//g;
			$MonthlyFilesCounter{$Month}=$Accesses;
			$MonthlyBytesCounter{$Month}=$Bytes;
			$MonthlySessionsCounter{$Month}=$Domains;
			$MonthlyTotalBytesCounter+=$Bytes;
			$MonthCounter++;
			$MonthlyCounter{$MonthCounter}=$Month;
			next OLDLINE;
		} elsif ($logsegment eq "daily") {
			($Accesses,$Bytes,$Domains,$Day,$Month) =
			  m#^\s*([\d,]+)\s+([\d,]+)\s+([\d,]+|-)\s+(\d\d)\s+(\w\w\w)#o;
			if ($Month ne "") {
				$Accesses =~ s/,//g;
				$Bytes =~ s/,//g;
				$Domains =~ s/,//g;
				$Year=$CurrYear;
				if (($Month =~ "(Nov|Dec)") &&
				  ($CurrMonth =~ "(Jan|Feb)")) {
					$Year=$Year-1;
				}
				$Today="$Year $MonthToNumber{$Month} $Day";
				$DayFilesCounter{$Today}=$Accesses;
				$BytesDay{$Today}=$Bytes;
				$DomainsDay{$Today}=$Domains;
				$DailyTotalBytesCounter+=$Bytes;
				$DayCounter++;
			}
			next OLDLINE;
		} elsif ($logsegment eq "dayofweek") {
			($Accesses,$Bytes,$Sessions,$Day) =
			  m#^\s*([\d,]+)\s+([\d,]+)\s+([\d,]+|-)\s+(\w\w\w)#o;
			$Accesses =~ s/,//g;
			$Bytes =~ s/,//g;
			$Sessions =~ s/,//g;
			unless ($Sessions) { $Sessions = 0; }
			$DoWFilesCounter{$Day}=$Accesses;
			$DoWBytesCounter{$Day}=$Bytes;
			$DoWTotalBytesCounter+=$Bytes;
			$DoWSessionsCounter{$Day}=$Sessions;
			next OLDLINE;
		} elsif ($logsegment eq "hourly") {
			($Accesses,$Bytes,$Hour) =
			  m#^\s*([\d,]+)\s+([\d,]+)\s+(\d\d)#o;
			$Accesses =~ s/,//g;
			$Bytes =~ s/,//g;
			$HourFilesCounter{$Hour}=$Accesses;
			$BytesHour{$Hour}=$Bytes;
			$HourlyTotalBytesCounter+=$Bytes;
			next OLDLINE;
		} elsif ($logsegment eq "records") {
			$line=$_;
			if ($line =~ m#Most Hits#o) {
				($RecordHits,$RecordHitsDate) =
				$line=~m#([\d,]*)\s\(([^)]*)\)#o;
				$RecordHits =~ s/,//g;
			} elsif ($line =~ m#Most Bytes#o) {
				($RecordBytes,$RecordBytesDate) =
				$line=~m#([\d,]*)\s\(([^)]*)\)#o;
				$RecordBytes =~ s/,//g;
			} elsif ($line =~ m#Most Visits#o) {
				($RecordVisits,$RecordVisitsDate) =
				$line=~m#([\d,]*)\s\(([^)]*)\)#o;
				$RecordVisits =~ s/,//g;
			}
			next OLDLINE;
		} elsif ($logsegment eq "summary") {
			$line=$_;
			if ($line =~ m#Period Covered#o) {
				($starthour,$startminute,$startsec,
				  $startday,$startmonth,$startyear)=
				  $line=~m#(\d\d):(\d\d):(\d\d) (\d\d) (\w\w\w)\w* (\d\d\d\d) to#o;
				($endhour,$endminute,$endsec,
				  $endday,$endmonth,$endyear)=
				  $line=~m#to (\d\d):(\d\d):(\d\d) (\d\d) (\w\w\w)\w* (\d\d\d\d)#o;
				next OLDLINE unless ($starthour);
				$StartDate=
				  "$startyear $MonthToNumber{$startmonth} $startday $starthour $startminute $startsec";
				$EndDate=
				  "$endyear $MonthToNumber{$endmonth} $endday $endhour $endminute $endsec";
			}
			next OLDLINE;
		} elsif ($logsegment eq "files") {
			($Hour,$Minute,$Second,$Day,$Month,$Year,
			  $Accesses,$Bytes,$FileName)=
			  m#^\s*(\d\d):(\d\d):(\d\d) (\d\d) (\w\w\w)\w* (\d\d\d\d) \s*([\d,]+)\s+([\d,]+)\s+(\S.*)#o;
			$Accesses =~ s/,//g;
			$Bytes =~ s/,//g;
			$TotalFilesCounter+=$Accesses;
			$TotalBytesCounter+=$Bytes;
			$HitsFileCounter{$FileName}=$Accesses;
			$BytesFileCounter{$FileName}=$Bytes;
			$LastAccessFile{$FileName}=
			  "$Year $MonthToNumber{$Month} $Day $Hour $Minute $Second";
			next OLDLINE;
		} elsif ($logsegment eq "404") {
			($Hour,$Minute,$Second,$Day,$Month,$Year,$Accesses,$Bytes,$FileName)=
			  m#^\s*(\d\d):(\d\d):(\d\d) (\d\d) (\w\w\w)\w* (\d\d\d\d) \s*([\d,]+)\s+([\d,]+)\s+(\S.*)#o;
			$Accesses =~ s/,//g;
			$Bytes =~ s/,//g;
			$fnfHitsFileCounter{$FileName}=$Accesses;
			$fnfBytesFileCounter{$FileName}=$Bytes;
			$fnfLastAccessFile{$FileName}="$Year $MonthToNumber{$Month} $Day $Hour $Minute $Second";
			next OLDLINE;
		} elsif ($logsegment eq "topleveldomain") {
			($Hour,$Minute,$Second,$Day,$Month,$Year,$Accesses,$Bytes,$TopDomain)=
			  m#^\s*(\d\d):(\d\d):(\d\d) (\d\d) (\w\w\w)\w* (\d\d\d\d) \s*([\d,]+)\s+([\d,]+)\s+(\w+)\s+=\s+#o;
			$Accesses =~ s/,//g;
			$Bytes =~ s/,//g;
			$TopDomainFilesCounter{$TopDomain}=$Accesses;
			$TopDomainBytesCounter{$TopDomain}=$Bytes;
			$TopDomainAccess{$TopDomain}="$Year $MonthToNumber{$Month} $Day $Hour $Minute $Second";
			next OLDLINE;
		} elsif ($logsegment eq "domains") {
			($Hour,$Minute,$Second,$Day,$Month,$Year,$Accesses,$Bytes,$Domain)=
			  m#^\s*(\d\d):(\d\d):(\d\d) (\d\d) (\w\w\w)\w* (\d\d\d\d) \s*([\d,]+)\s+([\d,]+)\s+(\S.*)#o;
			$Accesses =~ s/,//g;
			$Bytes =~ s/,//g;
			$DomainsFilesCounter{$Domain}=$Accesses;
			$DomainsBytesCounter{$Domain}=$Bytes;
			$LastAccessDomain{$Domain}="$Year $MonthToNumber{$Month} $Day $Hour $Minute $Second";
			next OLDLINE;
		}
		close OLD;
	}
}

sub ReadLog {
	if ($MonthlyCounter{$MonthCounter} ne "$CurrMonth $CurrYear") {
		$MonthCounter++;
		$MonthlyCounter{$MonthCounter}="$CurrMonth $CurrYear";
	}
	if (!($BytesDay{$CurrToday})) {
		$DayCounter++;
	}
	system ("gunzip -q $LogFile");
	open (LOGFILE,$LogFile) || die "Error opening file: $LogFile\n";
	while(<LOGFILE>) {
		chop;
		s/\s+/ /go;
		next if m/format\=\%/;
		if ($logtype eq "combined") {
			($Domain,$rfc931,$authuser,$TimeDate,$Request,$Status,$Bytes,$referer,$Agent) =
			  /^(\S+) (\S+) (\S+) \[(.+)\] \"(.+)\" (\S+) (\S+) \"(.+)\" \"(.+)\"/o;
		}
		else {
			($Domain,$rfc931,$authuser,$TimeDate,$Request,$Status,$Bytes) =
			  /^(\S+) (\S+) (\S+) \[(.+)\] \"(.+)\" (\S+) (\S+)/o;
		}
		next if (!($Domain && $rfc931 && $authuser && $TimeDate && $Request && $Status));
		($Method,$FileName,$Protocol)=split(/\s/,$Request,3);
		$Day="0$Day" if (length($Day) < 2);
		$FileName=~s#%7e#~#goi;
		unless ($IncludeQuery) {
			$FileName=~s#\?.*$##o;
		}
		$FileName=~s/#.*$//o;
		$FileName=~s/${DefaultPageName}$//o;
		next if (($IncludeOnlyDomain) && !($Domain=~m#$IncludeOnlyDomain#o));
		next if (($ExcludeDomain) && ($Domain=~m#$ExcludeDomain#o));
		next if (($IncludeOnlyRefsTo) && !($FileName=~m#$IncludeOnlyRefsTo#o));
		next if (($ExcludeRefsTo) && ($FileName=~m#$ExcludeRefsTo#o));
		($Day,$Month,$Year,$Hour,$Minute,$Second)=$TimeDate=~m#^(\d\d)/(\w\w\w)/(\d\d\d\d):(\d\d):(\d\d):(\d\d) #o;
		$FileName=~s#&#\&\;#go;
		$FileName=~s#<#\<\;#go;
		$FileName=~s#>#\>\;#go;
		$FileName=~s#"#\"#go;
		$Domain=~tr/A-Z/a-z/;
		$TrueDomain=$Domain;
		if ($PrintDomains eq "2") {
			if ($Domain =~ /\d$/) { $Domain = "Unresolved"; }
			elsif ($Domain =~ /([^.]*\.[^.]{3})$/) { $Domain = $1; }
			elsif ($Domain =~ /([^.]*\.[^.]*\.[^.]{2})$/) { $Domain = $1; }
			else { $Domain = "Unresolved"; }
		}
		$Bytes+=$RespEstimates{$Status};
		$HourFilesCounter{$Hour}++;
		$BytesHour{$Hour}+=$Bytes;
		$DoWFilesCounter{$CurrDay}++;
		$DoWBytesCounter{$CurrDay}+=$Bytes;
		$MonthlyFilesCounter{"$CurrMonth $CurrYear"}++;
		$MonthlyBytesCounter{"$CurrMonth $CurrYear"}+=$Bytes;
		$Today="$Year $MonthToNumber{$Month} $Day";
		$DayFilesCounter{$Today}++;
		$BytesDay{$Today}+=$Bytes;
		$Today="$Today $Hour $Minute $Second";
		$StartDate=$Today if ($Today lt $StartDate);
		$EndDate=$Today if ($Today gt $EndDate);
		$DomainsFilesCounter{$Domain}++;
		$DomainsBytesCounter{$Domain}+=$Bytes;
		if ($LastAccessDomain{$Domain} lt $Today) {
			$LastAccessDomain{$Domain}=$Today;
		}
		$TopDomain=&GetTopDomain($Domain);
		$TopDomainFilesCounter{$TopDomain}++;
		$TopDomainBytesCounter{$TopDomain}+=$Bytes;
		if ($TopDomainAccess{$TopDomain} lt $Today) {
			$TopDomainAccess{$TopDomain} = $Today;
		}
		$TotalBytesCounter+=$Bytes;
		$TotalFilesCounter++;
		$MonthlyTotalBytesCounter+=$Bytes;
		$DailyTotalBytesCounter+=$Bytes;
		$DoWTotalBytesCounter+=$Bytes;
		$HourlyTotalBytesCounter+=$Bytes;
		if ($Status==404) {
			$fnfHitsFileCounter{$FileName}++;
			$fnfBytesFileCounter{$FileName}+=$Bytes;
			if ($fnfLastAccessFile{$FileName} lt $Today) {
				$fnfLastAccessFile{$FileName}=$Today;
			}
			$HitsFileCounter{'Code 404 File Not Found'}++;
			$BytesFileCounter{'Code 404 File Not Found'}+=$Bytes;
			if ($LastAccessFile{'Code 404 File Not Found'} lt $Today) {
				$LastAccessFile{'Code 404 File Not Found'}=$Today;
			}
			$TodayErrors++;
		} else {
			$HitsFileCounter{$FileName}++;
			$BytesFileCounter{$FileName}+=$Bytes;
			if ($LastAccessFile{$FileName} lt $Today) {
				$LastAccessFile{$FileName}=$Today;
			}
			$TodayHits++;
			unless ($DetailsFilter && ($FileName=~m#$DetailsFilter#oi)) {
				if (($TrueDomain !~ /\./) && ($OrgDomain)) { $TrueDomain .= ".$OrgDomain"; }
				if ($TrueDomain =~ /.*$OrgDomain/) { $TodayLocal++; }
				$TodayPages++;
				$TodayDomains{$TopDomain}++;
				$TodayHosts{$TrueDomain}++;
				$TodayPages{$FileName}++;
				push (@Accesses, "$Hour $Minute $Second $TrueDomain $FileName");
			}
		}
	}
}

sub GetTopDomain {
	local($domname) = $_[0];
	($TopDomain)=($domname=~m#\.(\w+)$#o);
	$TopDomain=~tr/A-Z/a-z/;
	$TopDomain="xxx" if ($TopDomain > 0 || $TopDomain eq '');
	return $TopDomain;
}

sub PrintReport {
	open (REPORT,">$ReportFile");
	print REPORT "<HTML><HEAD><TITLE>Access Log: $SystemName</TITLE></HEAD>";
	print REPORT "<BODY BGCOLOR=\"#99ccff\" TEXT=\"#000000\">\n";
	print REPORT "<H1 ALIGN=CENTER>Access Log:<BR>$SystemName</H1>\n";
	print REPORT "<P ALIGN=CENTER><SMALL>This report was generated by ";
	print REPORT "<STRONG><A HREF=\"http://awsd.com/scripts/weblog/\">WebLog $version</A></STRONG></SMALL></P>\n";
	if ($DetailsFile) {
		print REPORT "<P ALIGN=CENTER>[ <STRONG><A HREF=\"$DetailsURL\">Access Details Report</A></STRONG> ]</P>\n";
	}
	print REPORT "<A NAME=\"index\"><HR></A><H2 ALIGN=CENTER>Index</H2>\n";
	print REPORT "<P><UL><LI><STRONG>Long-Term Statistics</STRONG></P><P><UL>\n";
	print REPORT "<LI><A HREF=\"#monthly\">Monthly Statistics</A>\n";
	print REPORT "<LI><A HREF=\"#daily\">Daily Statistics (Past Five Weeks)</A>\n";
	print REPORT "<LI><A HREF=\"#dayofweek\">Day of Week Statistics</A>\n";
	print REPORT "<LI><A HREF=\"#hourly\">Hourly Statistics</A>\n";
	print REPORT "<P><LI><A HREF=\"#records\">"Record Book"</A>\n";
	print REPORT "</UL></P><P><LI><STRONG>Statistics for The Current Month</STRONG></P><P><UL>\n";
	print REPORT "<LI><A HREF=\"#summary\">Current Month Summary</A><P>\n";
	if ($PrintTopNFiles) {
		print REPORT "<LI><A HREF=\"#topnfilesbyhits\">Top $PrintTopNFiles Files by Number of Hits</A>\n";
		print REPORT "<LI><A HREF=\"#topnfilesbyvolume\">Top $PrintTopNFiles Files by Volume</A>\n";
	}
	print REPORT "<LI><A HREF=\"#files\">Complete File Statistics</A><P>\n";
	if ($Print404) {
		if ($PrintTopNFiles) {
			print REPORT "<LI><A HREF=\"#topn404\">Top $PrintTopNFiles Most Frequently Requested 404 Files</A>\n";
		}
		print REPORT "<LI><A HREF=\"#404\">Complete 404 File Not Found Statistics</A><P>\n";
	}
	print REPORT "<LI><A HREF=\"#topleveldomain\">\"Top Level\" Domains</A>\n";
	if ($PrintDomains) {
		if ($PrintTopNDomains) {
			print REPORT "<LI><A HREF=\"#topnsitesbyhits\">Top $PrintTopNDomains Domains by Number of Hits</A>\n";
			print REPORT "<LI><A HREF=\"#topnsitesbyvolume\">Top $PrintTopNDomains Domains by Volume</A>\n";
		}
		print REPORT "<LI><A HREF=\"#domains\">Complete Domain Statistics</A>\n";
	}
	print REPORT "</UL></UL></P>\n";
	&PrintMonthlyReport;
	&PrintDailyReport;
	&PrintDayofWeekReport;
	&PrintHourlyReport;
	&PrintRecords;
	&PrintSummaryReport;
	if ($PrintTopNFiles) {
		&PrintTopNFilesByHitsReport;
		&PrintTopNFilesByVolumeReport;
	}
	&PrintFilesReport;
	if ($Print404) {
		if ($PrintTopNFiles) {
			&PrintTopN404Report;
		}
		&Print404Report;
	}
	&PrintTopLevelDomainsReport;
	if ($PrintDomains) {
		if ($PrintTopNDomains) {
			&PrintTopNDomainsByHitsReport;
			&PrintTopNDomainsByVolumeReport;
		}
		&PrintReversedDomainsReport;
	}
	print REPORT "<HR></BODY></HTML>\n";
	close REPORT;
}

sub PrintMonthlyReport {
	print REPORT "<A NAME=\"monthly\"><HR></A><H2 ALIGN=CENTER>Monthly Statistics</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "        Hits           Bytes      Visits      Month\n\n";
	$MonthlySessionsCounter{$MonthlyCounter{$MonthCounter}} = $MonthlySessionsCounter{$MonthlyCounter{$MonthCounter}} + $usersessions;
	foreach $key (1..$MonthCounter) {
		if ($MonthlyBytesCounter{$MonthlyCounter{$key}} < 1) {
			$MonthlyFilesCounter{$MonthlyCounter{$key}} = 0;
			$MonthlyBytesCounter{$MonthlyCounter{$key}} = 0;
			$MonthlySessionsCounter{$MonthlyCounter{$key}} = 0;
		}
		if ($NoSessions) { $MonthlySessionsCounter{$MonthlyCounter{$key}} = "-"; }
		printf REPORT "%12s%16s%12s%13s",&commas($MonthlyFilesCounter{$MonthlyCounter{$key}}),
		  &commas($MonthlyBytesCounter{$MonthlyCounter{$key}}),&commas($MonthlySessionsCounter{$MonthlyCounter{$key}}),
		  " $MonthlyCounter{$key}  ";
		if ($MonthlyTotalBytesCounter < 1) { $Percent=0; }
		else {
			$Percent=(($MonthlyBytesCounter{$MonthlyCounter{$key}}/$MonthlyTotalBytesCounter)*($MonthCounter*10))+.5;
		}
	&PrintBarGraph;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub PrintBarGraph {
	if ($GraphURL) {
		if ($Percent<5) {
			print REPORT "<IMG SRC=\"$GraphURL/bar1.gif\" HEIGHT=7 WIDTH=4 ALT=\"\">"x$Percent;
			$Percent=0;
		}
		else {
			print REPORT "<IMG SRC=\"$GraphURL/bar2.gif\" HEIGHT=7 WIDTH=20 ALT=\"\">";
			$Percent=$Percent-5;
		}
		if ($Percent<10) {
			print REPORT "<IMG SRC=\"$GraphURL/bar3.gif\" HEIGHT=7 WIDTH=4 ALT=\"\">"x$Percent;
			$Percent=0;
		}
		else {
			print REPORT "<IMG SRC=\"$GraphURL/bar4.gif\" HEIGHT=7 WIDTH=40 ALT=\"\">";
			$Percent=$Percent-10;
		}
		if ($Percent<10) {
			print REPORT "<IMG SRC=\"$GraphURL/bar5.gif\" HEIGHT=7 WIDTH=4 ALT=\"\">"x$Percent;
			$Percent=0;
		}
		else {
			print REPORT "<IMG SRC=\"$GraphURL/bar6.gif\" HEIGHT=7 WIDTH=40 ALT=\"\">";
			$Percent=$Percent-10;
		}
		print REPORT "<IMG SRC=\"$GraphURL/bar5.gif\" HEIGHT=7 WIDTH=4 ALT=\"\">"x$Percent;
	}
	print REPORT "\n";
}

sub PrintDailyReport {
	print REPORT "<A NAME=\"daily\"><HR></A><H2 ALIGN=CENTER>Daily Statistics (Past Five Weeks)</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "        Hits           Bytes      Visits       Date\n\n";
	$DayCount=$DayCounter;
	if ($DayCount > 35) { $DayCount=35; }
	if (! $DayFilesCounter{$CurrToday}) { $DayFilesCounter{$CurrToday}="0"; }
	foreach $key (sort keys(%DayFilesCounter)) {
		if ($DayCounter > 35) {
			$DayCounter=$DayCounter-1;
			$DailyTotalBytesCounter=$DailyTotalBytesCounter-$BytesDay{$key};
		}
		else {
			($Year,$Month,$Day)=split(/ /,$key);
			$Check = $DayCounter;
			if ($Check < 10) { $Check="0".$Check; }
			if ($Check=~$DayBreaks) { print REPORT "\n"; }
			if ($DayCounter eq 1) {
				$DomainsDay{$key}=$usersessions;
				$TodayBytes=$BytesDay{$key};
				$RecordDate = "$NumberToMonth{$Month} $Day, $Year";
				if ($DayFilesCounter{$key} > $RecordHits) {
					$RecordHits = $DayFilesCounter{$key};
					$RecordHitsDate = $RecordDate;
				}
				if ($BytesDay{$key} > $RecordBytes) {
					$RecordBytes = $BytesDay{$key};
					$RecordBytesDate = $RecordDate;
				}
				if ($DomainsDay{$key} > $RecordVisits) {
					$RecordVisits = $DomainsDay{$key};
					$RecordVisitsDate = $RecordDate;
				}
			}
			if ($DayCounter eq 0) { $DomainsDay{$key}=0; }
			$DayCounter=$DayCounter-1;
			if ($BytesDay{$key} < 1) {
				$DayFilesCounter{$key} = 0;
				$BytesDay{$key} = 0;
				$DomainsDay{$key} = 0;
			}
			if ($NoSessions) { $DomainsDay{$key} = "-"; }
			printf REPORT "%12s%16s%12s%13s",&commas($DayFilesCounter{$key}),&commas($BytesDay{$key}),&commas($DomainsDay{$key}),
			  "$Day $NumberToMonth{$Month}  ";
			if ($DailyTotalBytesCounter < 1) { $Percent=0; }
			else {
				$Percent=(($BytesDay{$key}/$DailyTotalBytesCounter)*($DayCount*10))+.5;
			}
			&PrintBarGraph;
		}
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub PrintDayofWeekReport {
	print REPORT "<A NAME=\"dayofweek\"><HR></A><H2 ALIGN=CENTER>Day of Week Statistics</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "        Hits           Bytes      Visits        Day\n\n";
	$DoWSessionsCounter{$CurrDay}+=$usersessions;
	foreach $key (1..7) {
		if ($DoWBytesCounter{$DoWCounter{$key}} < 1) {
			$DoWFilesCounter{$DoWCounter{$key}} = 0;
			$DoWBytesCounter{$DoWCounter{$key}} = 0;
			$DoWSessionsCounter{$DoWCounter{$key}} = 0;
		}
		if ($NoSessions) { $DoWSessionsCounter{$DoWCounter{$key}} = "-"; }
		printf REPORT "%12s%16s%12s%13s",&commas($DoWFilesCounter{$DoWCounter{$key}}),
		  &commas($DoWBytesCounter{$DoWCounter{$key}}),
		  &commas($DoWSessionsCounter{$DoWCounter{$key}}),"      $DoWCounter{$key}  ";
		if ($DoWTotalBytesCounter < 1) { $Percent=0; }
		else {
			$Percent=(($DoWBytesCounter{$DoWCounter{$key}}/$DoWTotalBytesCounter)*70)+.5;
		}
		&PrintBarGraph;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub PrintHourlyReport {
	print REPORT "<A NAME=\"hourly\"><HR></A><H2 ALIGN=CENTER>Hourly Statistics</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "        Hits           Bytes                   Hour\n\n";
	foreach $key (00..23) {
		if ($key<10) { $key="0".$key; }
		unless ($HourFilesCounter{$key}) { $HourFilesCounter{$key} = 0; }
		unless ($BytesHour{$key}) { $BytesHour{$key} = 0; }
		printf REPORT "%12s%16s%25s",&commas($HourFilesCounter{$key}),&commas($BytesHour{$key}),"                  $key  ";
		if ($HourlyTotalBytesCounter < 1) { $Percent=0; }
		else {
			$Percent=(($BytesHour{$key}/$HourlyTotalBytesCounter)*240)+.5;
		}
		&PrintBarGraph;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub PrintRecords {
	print REPORT "<A NAME=\"records\"><HR></A><H2 ALIGN=CENTER>"Record Book"</H2>\n";
	print REPORT "<P><STRONG>Most Hits:</STRONG> ";
	print REPORT &commas($RecordHits)," ($RecordHitsDate)\n";
	print REPORT "<P><STRONG>Most Bytes:</STRONG> ";
	print REPORT &commas($RecordBytes)," ($RecordBytesDate)\n";
	unless ($NoSessions) {
		print REPORT "<P><STRONG>Most Visits:</STRONG> ";
		print REPORT &commas($RecordVisits)," ($RecordVisitsDate)\n";
	}
	print REPORT "<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub PrintSummaryReport {
	print REPORT "<A NAME=\"summary\"><HR></A><H2 ALIGN=CENTER>Current Month Summary</H2>\n";
	print REPORT "<P><STRONG>Period Covered:</STRONG> ";
	unless ($StartDate eq "9999 99 99 99 99 99") {
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$StartDate);
		print REPORT "$Hour:$Minute:$Second $Day $NumberToMonth{$Month} $Year to ";
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$EndDate);
		print REPORT "$Hour:$Minute:$Second $Day $NumberToMonth{$Month} $Year";
	}
	print REPORT "\n";
	print REPORT "<P><STRONG>Total Files Transfered:</STRONG> ",&commas($TotalFilesCounter),"\n";
	print REPORT "<BR><STRONG>Total Bytes Transfered:</STRONG> ",&commas($TotalBytesCounter),"\n";
	unless ($NoSessions || ($MonthlySessionsCounter{$MonthlyCounter{$MonthCounter}}<1)) {
		print REPORT "<P><STRONG>User Sessions:</STRONG> ",&commas($MonthlySessionsCounter{$MonthlyCounter{$MonthCounter}}),"\n";
	}
	print REPORT "<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub commas {
	local($_)=@_;
	1 while s/(.*\d)(\d\d\d)/$1,$2/;
	$_;
}

sub PrintTopNFilesByHitsReport {
	print REPORT "<A NAME=\"topnfilesbyhits\"><HR></A><H2 ALIGN=CENTER>Top $PrintTopNFiles Files ";
	print REPORT "by Number of Hits</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Accessed               Hits           Bytes   File\n\n";
	$Counter=1;
	foreach $key (sort ByHitsFiles keys(%HitsFileCounter)) {
		last if ($Counter > $PrintTopNFiles);
		next if ($TopFileListFilter && ($key=~m#$TopFileListFilter#oi));
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$LastAccessFile{$key});
		$Month=$NumberToMonth{$Month};
		printf REPORT "%-21s%11s%16s   %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
		  &commas($HitsFileCounter{$key}),&commas($BytesFileCounter{$key}),$key;
		$Counter++;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub ByHitsFiles {
	$HitsFileCounter{$b}<=>$HitsFileCounter{$a};
}

sub PrintTopNFilesByVolumeReport {
	print REPORT "<A NAME=\"topnfilesbyvolume\"><HR></A><H2 ALIGN=CENTER>Top $PrintTopNFiles Files ";
	print REPORT "by Volume</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Accessed               Hits           Bytes   File\n\n";
	$Counter=1;
	foreach $key (sort ByVolumeFiles keys(%HitsFileCounter)) {
		last if ($Counter > $PrintTopNFiles);
		next if ($TopFileListFilter && ($key=~m#$TopFileListFilter#oi));
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$LastAccessFile{$key});
		$Month=$NumberToMonth{$Month};
		printf REPORT "%-21s%11s%16s   %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
		  &commas($HitsFileCounter{$key}),&commas($BytesFileCounter{$key}),$key;
		$Counter++;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub ByVolumeFiles {
	$BytesFileCounter{$b}<=>$BytesFileCounter{$a};
}

sub PrintFilesReport {
	print REPORT "<A NAME=\"files\"><HR></A><H2 ALIGN=CENTER>Complete File Statistics</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Accessed               Hits           Bytes   File\n\n";
	foreach $key (sort keys(%HitsFileCounter)) {
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$LastAccessFile{$key});
		$Month=$NumberToMonth{$Month};
		printf REPORT "%-21s%11s%16s   %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
		  &commas($HitsFileCounter{$key}),&commas($BytesFileCounter{$key}),$key;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub PrintTopN404Report {
	print REPORT "<A NAME=\"topn404\"><HR></A><H2 ALIGN=CENTER>Top $PrintTopNFiles Most Frequently Requested ";
	print REPORT "404 Files</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Accessed               Hits           Bytes   File\n\n";
	$Counter=1;
	foreach $key (sort ByfnfHitsFiles keys(%fnfHitsFileCounter)) {
		last if ($Counter > $PrintTopNFiles);
		next if ($TopFileListFilter && ($key=~m#$TopFileListFilter#oi));
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$fnfLastAccessFile{$key});
		$Month=$NumberToMonth{$Month};
		printf REPORT "%-21s%11s%16s   %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
		  &commas($fnfHitsFileCounter{$key}),&commas($fnfBytesFileCounter{$key}),$key;
		$Counter++;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub ByfnfHitsFiles {
	$fnfHitsFileCounter{$b}<=>$fnfHitsFileCounter{$a};
}

sub Print404Report {
	print REPORT "<A NAME=\"404\"><HR></A><H2 ALIGN=CENTER>Complete 404 File Not Found Statistics</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Accessed               Hits           Bytes   File\n\n";
	foreach $key (sort keys(%fnfHitsFileCounter)) {
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$fnfLastAccessFile{$key});
		$Month=$NumberToMonth{$Month};
		printf REPORT "%-21s%11s%16s   %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
		  &commas($fnfHitsFileCounter{$key}),&commas($fnfBytesFileCounter{$key}),$key;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub PrintTopLevelDomainsReport {
	print REPORT "<A NAME=\"topleveldomain\"><HR></A><H2 ALIGN=CENTER>\"Top Level\" Domains</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Accessed               Hits           Bytes   \"Top Level\" Domain\n\n";
	foreach $TopDomain (sort ByTopDomain keys(%TopDomainBytesCounter)) {
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$TopDomainAccess{$TopDomain});
		$Month=$NumberToMonth{$Month};
		unless ($TopDomainFilesCounter{$TopDomain}<1) {
			printf REPORT "%-21s%11s%16s   %-4s = %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
			  &commas($TopDomainFilesCounter{$TopDomain}),
			  &commas($TopDomainBytesCounter{$TopDomain}),$TopDomain,$CountryCode{$TopDomain};
		}
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub ByTopDomain {
	$TopDomainBytesCounter{$b}<=>$TopDomainBytesCounter{$a};
}

sub PrintTopNDomainsByHitsReport {
	print REPORT "<A NAME=\"topnsitesbyhits\"><HR></A><H2 ALIGN=CENTER>Top $PrintTopNDomains Domains ";
	print REPORT "by Number of Hits</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Access                 Hits           Bytes   Domain\n\n";
	$Counter=1;
	foreach $key (sort ByNDomains keys(%DomainsFilesCounter)) {
		last if ($Counter > $PrintTopNDomains);
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$LastAccessDomain{$key});
		$Month=$NumberToMonth{$Month};
		printf REPORT "%-21s%11s%16s   %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
		  &commas($DomainsFilesCounter{$key}),&commas($DomainsBytesCounter{$key}),$key;
		$Counter++;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub ByNDomains {
	$DomainsFilesCounter{$b}<=>$DomainsFilesCounter{$a};
}

sub PrintTopNDomainsByVolumeReport {
	print REPORT "<A NAME=\"topnsitesbyvolume\"><HR></A><H2 ALIGN=CENTER>Top $PrintTopNDomains Domains ";
	print REPORT "by Volume</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Access                 Hits           Bytes   Domain\n\n";
	$Counter=1;
	foreach $key (sort ByVolumeDomains keys(%DomainsFilesCounter)) {
		last if ($Counter > $PrintTopNDomains);
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$LastAccessDomain{$key});
		$Month=$NumberToMonth{$Month};
		printf REPORT "%-21s%11s%16s   %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
		  &commas($DomainsFilesCounter{$key}),&commas($DomainsBytesCounter{$key}),$key;
		$Counter++;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub ByVolumeDomains {
	$DomainsBytesCounter{$b}<=>$DomainsBytesCounter{$a};
}

sub PrintReversedDomainsReport {
	print REPORT "<A NAME=\"domains\"><HR></A><H2 ALIGN=CENTER>Complete Domain Statistics</H2>\n";
	print REPORT "<PRE>\n";
	print REPORT "Last Access                 Hits           Bytes   Domain\n\n";
	foreach $key (sort ByReversedSubDomain keys(%DomainsFilesCounter)) {
		($Year,$Month,$Day,$Hour,$Minute,$Second)=split(/ /,$LastAccessDomain{$key});
		$Month=$NumberToMonth{$Month};
		printf REPORT "%-21s%11s%16s   %-s\n","$Hour:$Minute:$Second $Day $Month $Year",
		  &commas($DomainsFilesCounter{$key}),&commas($DomainsBytesCounter{$key}),$key;
	}
	print REPORT "</PRE>\n<P ALIGN=CENTER><SMALL>[ <A HREF=\"#index\">Return to Index</A> ]</SMALL></P>\n\n";
}

sub ByReversedSubDomain {
	local(@adomains,@bdomains,$aisIP,$bisIP,$counter,$acounter,$bcounter,$result);
	$result=0;
	(@adomains)=split(/\./,$a);
	(@bdomains)=split(/\./,$b);
	$aisIP=$a=~m#^\d+\.\d+\.\d+\.\d+$#o;
	$bisIP=$b=~m#^\d+\.\d+\.\d+\.\d+$#o;
	if ($aisIP && (!$bisIP)) {
		$result=-1;
	} elsif ((!$aisIP) && $bisIP) {
		$result=1;
	} elsif ($aisIP && $bisIP) {
		$counter=0;
		while ((!$result) && ($counter < 4)) {
			$result=$adomains[$counter] <=> $bdomains[$counter];
			$counter++;
		}
	} elsif ((!$aisIP) && (!$bisIP)) {
		$acounter=$#adomains;
		$bcounter=$#bdomains;
		while ((!$result) && ($acounter>=0) && ($bcounter>=0)) {
			$result=$adomains[$acounter] cmp $bdomains[$bcounter];
			$acounter--;
			$bcounter--;
		}
		if (!$result) {
			$result=1 if ($acounter>=0);
			$result=-1 if ($bcounter>=0);
		}
	}
	$result;
}

sub GetSessions {
	if (!$TodayHits) { $TodayHits=0; }
	if (!$TodayErrors) { $TodayErrors=0; }
	$TodayOutside=0;
	$LocalPercent=0;
	$OutsidePercent=0;
	$TodayHosts=0;
	$TodayKB=0;
	$AveragePages=0;
	$usersessions=0;
	$sessionstime=0;
	unless ($TodayPages < 1 ) {
		@RevAccesses=reverse(@Accesses);
		undef @Accesses;
		foreach $entry (@RevAccesses) { 
			($hour,$minute,$second,$remote,$page)=split(" ",$entry);
			$visit=(($hour*3600)+($minute*60)+$second);
			$duration=0;
			if ($prevvisit{$remote}) { $duration=($prevvisit{$remote}-$visit); }
			$prevvisit{$remote}=$visit;
			if ($duration < 0) { $duration=$duration+86400; }
			if ($duration > 1800) { $duration=0; }
			if ($duration < 1) {
				$usersessions ++;
				$sessionstime=$sessionstime+30;
			}
			else {
				$sessionstime=$sessionstime+$duration;
			}
			$durminute=int($duration/60);
			$dursecond=$duration-($durminute*60);
			if ($durminute < 10) { $durminute="0".$durminute; }
			if ($dursecond < 10) { $dursecond="0".$dursecond; }
			push (@Accesses, "$hour $minute $second $durminute $dursecond $remote $page");
		}
	}
}

sub PrintHostDetailsReport {
	open (FILE,"$DetailsFile");
	@lines = <FILE>;
	close (FILE);
	foreach $line (@lines) {
		if ($line =~ m#DAYS=(\d+) SESSIONS=(\d+) TIME=(\d+)#o) {
			$totaldays=$1;
			$totalsessions=$2;
			$totaltime=$3;
			last;
		}
	}
	$totaldays++;
	open (REPORT,">$DetailsFile");
	print REPORT "<HTML><HEAD><TITLE>Access Details Report: $SystemName</TITLE></HEAD>";
	print REPORT "<BODY BGCOLOR=\"#99ccff\" TEXT=\"#000000\">\n";
	print REPORT "<H1 ALIGN=CENTER>Access Details:<BR>$SystemName</H1>\n";
	print REPORT "<P ALIGN=CENTER><SMALL>This report was generated by ";
	print REPORT "<STRONG><A HREF=\"http://awsd.com/scripts/weblog/\">WebLog $version</A></STRONG></SMALL></P>\n";
	print REPORT "<P ALIGN=CENTER>[ <STRONG><A HREF=\"$ReportURL\">Access Log</A></STRONG> ]</P><HR>\n";
	if ($DetailsDays<1) { $DetailsDays=1; }
	if ($DetailsDays>35) {$DetailsDays=35; }
	unless ($TodayPages < 1 ) {
		$TodayOutside=$TodayPages-$TodayLocal;
		$LocalPercent=int(($TodayLocal/$TodayPages)*1000+.5)/10;
		$OutsidePercent=int(($TodayOutside/$TodayPages)*1000+.5)/10;
		$TodayHosts=keys(%TodayHosts);
		$TodayKB=int(($TodayBytes/1024)+.5);
		$AveragePages=sprintf("%3.1f",$TodayPages/$TodayHosts);
		%hostlist=();
		$bdelim="s$;";
		$edelim="e$;";
		$pdelim="p$;";
		@RevAccesses=reverse(@Accesses);
		undef @Accesses;
		foreach $entry (@RevAccesses) { 
			($hour,$minute,$second,$durminute,$dursecond,$remote,$page)=split(" ",$entry);
			$duration=$durminute.":".$dursecond;
			if ($duration eq "00:00") { $duration="     "; }
			$timestring=$hour.":".$minute.":".$second;
			if ($hostlist{$remote}) {
				$hostlist{$remote}=
				  $hostlist{$remote}.$bdelim.$timestring.$pdelim.$duration.$pdelim.$page.$edelim;
			} else {
				$hostlist{$remote}=$bdelim.$timestring.$pdelim.$duration.$pdelim.$page.$edelim;
			}
		}
		$averagesession=$sessionstime/$usersessions;
		if ($averagesession > 3600) {
			$averagehour=int($averagesession/3600);
			$averagesession=$averagesession-($averagehour*3600);
		}
		$averageminute=int($averagesession/60);
		$averagesecond=int(($averagesession-($averageminute*60))+.5);
		if ($averageminute < 10) { $averageminute="0".$averageminute; }
		if ($averagesecond < 10) { $averagesecond="0".$averagesecond; }
		$averagesession=$averageminute.":".$averagesecond;
		if ($averagehour) { $averagesession=$averagehour.":".$averagesession; }
		$totalsessions=$totalsessions+$usersessions;
		$totaltime=$totaltime+$sessionstime;
	}
	$grandsession = 0;
	unless ($totalsessions < 1) {
		$grandsession=$totaltime/$totalsessions;
	}
	if ($grandsession > 3600) {
		$grandhour=int($grandsession/3600);
		$grandsession=$grandsession-($grandhour*3600);
	}
	$grandminute=int($grandsession/60);
	$grandsecond=int(($grandsession-($grandminute*60))+.5);
	if ($grandminute < 10) { $grandminute="0".$grandminute; }
	if ($grandsecond < 10) { $grandsecond="0".$grandsecond; }
	$grandsession=$grandminute.":".$grandsecond;
	if ($grandhour) { $grandsession=$grandhour.":".$grandsession; }
	print REPORT "<DAYS=$totaldays SESSIONS=$totalsessions TIME=$totaltime>\n";
	unless (($totalsessions<1) || ($totaldays<2)) {
		print REPORT "<H2 ALIGN=CENTER>Long-Term Overview</H2>\n";
		print REPORT "<P ALIGN=CENTER><EM>In the past <STRONG>";
		print REPORT &commas($totaldays),"</STRONG> days, ";
		print REPORT "there have been a total of <STRONG>";
		print REPORT &commas($totalsessions),"</STRONG> ";
		print REPORT "distinct "user sessions," ";
		print REPORT "with an apparent average length of ";
		print REPORT "<STRONG>$grandsession</STRONG>.</EM></P><HR>\n";
	}
	print REPORT "<H2 ALIGN=CENTER>Detailed List of ";
	if ($DetailsDays < 2) {
		print REPORT "Yesterday's Accesses</H2>\n";
	}
	else {
		print REPORT "Accesses In the Past $DetailsDays Days</H2>\n";
	}
	print REPORT "<DATESTAMP=\"$time\">\n";
	print REPORT "<H3 ALIGN=CENTER>$CurrDate</H3>\n";
	if ($TodayPages < 1 ) {
		print REPORT "<P ALIGN=CENTER><EM>No successful accesses.</EM></P>\n";
	} else {
		print REPORT "<P><EM>A total of <STRONG>",&commas($TodayPages),"</STRONG> pages were accessed ";
		print REPORT "by <STRONG>",&commas($TodayHosts),"</STRONG> unique hosts (which viewed an average ";
		print REPORT "of <STRONG>$AveragePages</STRONG> pages each). ";
		if ($OrgDomain) {
			print REPORT "Of those pages, <STRONG>",&commas($TodayLocal)," ";
			printf REPORT ("(%.4g%%)",$LocalPercent);
			print REPORT "</STRONG> were ";
			if ($OrgName) {
				print REPORT "viewed by $OrgName, ";
			} else {
				print REPORT "viewed internally, ";
			}
			print REPORT "and <STRONG>",&commas($TodayOutside)," ";
			printf REPORT ("(%.4g%%)",$OutsidePercent);
			print REPORT "</STRONG> by outside domains. ";
		}
		print REPORT "There were <STRONG>";
		print REPORT &commas($usersessions),"</STRONG> distinct "user sessions," ";
		print REPORT "with an apparent average length of <STRONG>$averagesession</STRONG>. ";
		print REPORT "There were a total of <STRONG>";
		print REPORT &commas($TodayHits),"</STRONG> hits and <STRONG>",&commas($TodayErrors),"</STRONG> errors ";
		print REPORT "related to $SystemName, consisting of <STRONG>";
		print REPORT &commas($TodayKB),"</STRONG> kilobytes of information.</EM></P>\n";
		@hosts=sort byDomain (keys %hostlist);
		$TopDomain="";
		$prevTD="###";
		print REPORT "<P><PRE>";
		foreach $host (@hosts) {
			$TopDomain=&GetTopDomain($host);
			if ($TopDomain ne $prevTD) {
				unless ($prevTD eq "###") { print REPORT "</DL>"; }
				$prevTD = $TopDomain;
				print REPORT "<STRONG>$CountryCode{$TopDomain}:";
				print REPORT "</STRONG>\n<DL>";
			}
			$entry=$hostlist{$host};
			$entry=~s/$bdelim/<DD>/g;
			$entry=~s/$pdelim/ -- /g;
			$entry=~s/$edelim/\n/g;
			print REPORT "<DT>$host\n";
			print REPORT "$entry";
		}
		print REPORT "</DL></PRE></P>\n";
	}
	$datestamp=0;
	foreach $line (@lines) {
		if ($line =~ m#DATESTAMP=\"(\d+)#o) {
			$datestamp=$1;
		}
		if (($time-$datestamp) < (($DetailsDays-.5)*86400)) {
			print REPORT $line;
		}
	}
	print REPORT "<DATESTAMP=\"000000000\">\n";
	print REPORT "</P><HR></BODY></HTML>\n";
	close REPORT;
}

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);
}

1;