#!/usr/local/bin/perl
#
# $Id: access-summary.pl,v 1.16 1996/10/01 12:00:00 Iain Lea (iain@sbs.de)
#   Read CHANGES file for a detailed list of all modifications.
#
# $Id: access-summary.pl,v 1.14 1996/02/21 21:29:31 wessels Exp $
#
# This file is under RCS control in
#   $Source: /O1/Cache_Central/Scripts/RCS/access-summary.pl,v $
#

$me = $0;
@F = split('/', $me); pop @F;
$medir = join ('/', @F);

push (@INC, $medir);

require 'squid-logs.pl';
require 'getopts.pl';

@NLANR_names = ('IT','PB','UC','BO','SV','SD','localhost');
$HowSort = 'BYTES';

$UDP_TOTAL_COUNT = 0;
$TCP_TOTAL_COUNT = 0;
$TCP_TOTAL_BYTES = 0;

$TopN = 25;
$PortNum = 8080;
$ImgDir = '/img';
$HostName = `hostname`;
$Colorize = 1;
$NoCruft = 0;
$Verbose = 0;

$MaxHeight = 250;
$Url = 'http://www.sbs.de/~iain/squid-stats/';
$ScriptName = 'oops-stats';
$Version = 'v1.4/DEMOS';

# Colorize domain hit rates. Defaults are 25/40/55/70/85%
$HitColor1 = 'lightgreen';
$HitColor2 = 'lightblue';
$HitColor3 = 'lightyellow';
$HitColor4 = 'orange';
$HitColor5 = 'red';
$HitPercent1 = 25;
$HitPercent2 = 40;
$HitPercent3 = 55;
$HitPercent4 = 70;
$HitPercent5 = 85;

&ReadCmdLine ($me);

$FIRST = -1;

while (<>) {
	chop;
	next if (/^#/);
	($longkey,$val) = split;
	($cat,$key,$cs,$tag) = split(/\|/, $longkey);
	next if ($tag eq 'TCP_DONE');	# so this might work on older summaries
	${$cat}{$key}{$cs}{$tag} += $val;


	if ($cat eq 'TO') {	# TOTAL, special case
		$TCP_TOTAL_COUNT += $val if ($key eq 'TCP' && $cs eq 'REQUESTS');
		$UDP_TOTAL_COUNT += $val if ($key eq 'UDP' && $cs eq 'REQUESTS');
		$TCP_TOTAL_BYTES += $val if ($key eq 'TCP' && $cs eq 'BYTES');
		next;
	}

	if ($cat eq 'TIMESTAMP') {	# TIMESTAMP, special case
		$FIRST = $val if ($FIRST == -1);
		$FIRST = $val if ($key eq 'FIRST' && $FIRST > $val);
		$LAST = $val if ($key eq 'LAST' && $LAST < $val);
		next;
	}

	${$cat}{$key}{$cs}{'ALL'} += $val
		if (($tag =~ /^TCP_/ || $tag =~ /^UDP_/) && ($cs eq 'COUNT'));
	${$cat}{$key}{$cs}{'ALL'} += $val
		if ($tag =~ /^TCP_/ && ($cs eq 'BYTES'));

	if($cat eq 'CL') {
	    ${TCL}{$key}{$cs}{$tag} += $val;
	    ${TCL}{$key}{$cs}{'ALL'} += $val
		    if (($tag =~ /^TCP_/ || $tag =~ /^UDP_/) && ($cs eq 'COUNT'));
	    ${TCL}{$key}{$cs}{'ALL'} += $val
		    if ($tag =~ /^TCP_/ && ($cs eq 'BYTES'));
	}
}


sub xsort {
	local($href) = @_;
	local(@keys) = keys %{$href};
	sort { ${$href}{$b}{$HowSort}{ALL} <=> ${$href}{$a}{$HowSort}{ALL} } @keys;
}

sub aksort {
	local($href,$AK) = @_;	#	AK = "all-key"
	local(@keys) = keys %{$href};
	sort { ${$href}{$b}{COUNT}{$AK} <=> ${$href}{$a}{COUNT}{$AK} } @keys;
}

sub clsort {
	local($href) = @_;
	local(@keys) = keys %{$href};
	local(@keys1) = ();
	local(@keys2) = ();
	local($key);
	local($fqdn);
	local($x);
	foreach $key (@keys) {
		$fqdn = &fqdn($key);
		if (grep(/$fqdn/, @NLANR_names)) {
			push (@keys1, $key);
		} else {
			push (@keys2, $key);
		}
	}
##        @keys1 = sort { ${$href}{$b}{COUNT}{ALL} <=> ${$href}{$a}{COUNT}{ALL} } @keys1;
##        @keys2 = sort { ${$href}{$b}{COUNT}{ALL} <=> ${$href}{$a}{COUNT}{ALL} } @keys2;
	@keys1 = sort { ${$href}{$b}{$HowSort}{ALL} <=> ${$href}{$a}{$HowSort}{ALL} } @keys1;
	@keys2 = sort { ${$href}{$b}{$HowSort}{ALL} <=> ${$href}{$a}{$HowSort}{ALL} } @keys2;
	#print "RETURNING ", join (' ', (@keys1, 'BREAK', @keys2)), "\n";
	(@keys1, 'BREAK', @keys2);
}

# Top Client list sort
sub tclsort {
	local($href) = @_;
	local(@keys) = keys %{$href};
	local(@keys1) = ();
	local(@keys2) = ();
	local($key);
	local($fqdn, $tfqdn);
	local($x);

	foreach $key (@keys) {
	    $tfqdn = $fqdn = &fqdn($key);
	    my ($first) = 0;

	    if (grep(/$fqdn/, @NLANR_names)) {
		    $first = 1;
	    } else {
		    $first = 0;
	    }

	    $tfqdn =~ s/^[0-9,a-z,A-Z]+\.//;
	    if($first) {
		    push (@keys1, $tfqdn) if(! $keysall{$tfqdn});
	    } else {
		    push (@keys2, $tfqdn) if(! $keysall{$tfqdn});
	    }
	    $keysall{$tfqdn} = 1; # Only once!

	    foreach $k (keys %{${$href}{$key}{COUNT}}) {
		 ${$href}{$tfqdn}{COUNT}{$k} += ${$href}{$key}{COUNT}{$k};
	    }

	    foreach $k (keys %{${$href}{$key}{BYTES}}) {
		${$href}{$tfqdn}{BYTES}{$k} += ${$href}{$key}{BYTES}{$k};
	    }
	    undef ${$href}{$key} ;
	}
	undef @keysall;

##        @keys1 = sort { ${$href}{$b}{COUNT}{ALL} <=> ${$href}{$a}{COUNT}{ALL} } @keys1;
##        @keys2 = sort { ${$href}{$b}{COUNT}{ALL} <=> ${$href}{$a}{COUNT}{ALL} } @keys2;
#        @keys1 = sort { ${$href}{$b}{$HowSort}{ALL} <=> ${$href}{$a}{$HowSort}{ALL} } @keys1;

	@keys1 = sort { ${$href}{$b}{$HowSort}{ALL} <=> ${$href}{$a}{$HowSort}{ALL} } @keys1;
	@keys2 = sort { ${$href}{$b}{$HowSort}{ALL} <=> ${$href}{$a}{$HowSort}{ALL} } @keys2;

	#print "RETURNING ", join (' ', (@keys1, 'BREAK', @keys2)), "\n";
	(@keys1, 'BREAK', @keys2);
}

if ($HtmlFormat) {
	&html_format_output ($Title);
} else {
	&ascii_format_output;
}
exit 0;

##############################################################################

sub ascii_format_output
{
	print "FIRST ACCESS: ", &strtime($FIRST), "\n";
	print " LAST ACCESS: ", &strtime($LAST), "\n";
	print "\n";

	&table_table('Method', 'SUMMARY OF REQUEST METHOD USAGE', \%ME,
		\&xsort,undef,undef,0,0,0);
	&table_table('Protocol', 'SUMMARY OF PROTOCOL USAGE', \%PR,
		\&xsort,undef,undef,0,0,0);
	&table_table('Client',   'SUMMARY OF CLIENT USAGE',   \%CL,
		\&clsort,\&rev_fqdn,$TopN,0,0,0);
	&table_table('Server',   'SUMMARY OF SERVER USAGE',   \%SE,
		\&xsort,\&rev_server,$TopN,0,0,0);
	&table_table('Type',     'SUMMARY OF URL TYPES',      \%TY,
		\&xsort,undef,undef,0,0,0);
	&table_table('Domain',   'SUMMARY OF URL TOP-LEVEL DOMAINS', \%DO,
		\&xsort,\&top_domain_name,undef,0,0,0);

	&utilization_table('Client',   'CLIENT UTILIZATION', \%CL,
		undef,\&rev_fqdn,undef);

	&list_top('URL', "TOP $TopN HTTP Requests", \%UR,
		\&aksort, undef, $TopN, 'ALLTCP');
	&list_top('URL', "TOP $TopN ICP Requests",  \%UR,
		\&aksort, undef, $TopN, 'ALLUDP');
	&list_top('Target', "TOP $TopN CONNECT Requests",  \%CN,
		\&aksort, undef, $TopN, 'ALL');

	&list_top('URL', "TOP $TopN DENIED Requests",  \%DUR,
		\&aksort, undef, $TopN, 'ALL');

	&print_chart(\%TI, 'Request Distribution, combined HTTP and ICP, per half hour', 'ALL');
}

sub html_format_output
{
	my ($Title) = @_;
	my ($Date) = `date +%Y%m%d`;
	
	$BegTime = &strtime($FIRST);
	$EndTime = &strtime($LAST);

	print <<EOT
<html>
<head>
<title>Squid Statistics for $HostName:$PortNum</title>
</head>
<body>
<a name="00">
<h2>Squid Statistics for $HostName:$PortNum</h2>
<hr>
<p>
<ol>
<li><a href="#01">Summary of Request Method Usage</a>
<li><a href="#02">Summary of Protocol Usage</a>
<li><a href="#03">Summary of Client Usage</a>
<li><a href="#04">Summary of Top Client Usage</a>
<li><a href="#05">Summary of Server Usage</a>
<li><a href="#06">Summary of URL Types</a>
<li><a href="#07">Summary of URL Top-Level Domains</a>
<li><a href="#08">Client Utilization</a>
<li><a href="#09">Top $TopN HTTP Requests</a>
<li><a href="#10">Top $TopN ICP Requests</a>
<li><a href="#11">Top $TopN CONNECT Requests</a>
<li><a href="#12">Top $TopN DENIED Requests</a>
</ol>
<hr>
<p>
EOT
;
	&print_chart_html(\%TI, 'Request Distribution, combined HTTP and ICP, per half hour', 'ALL');
	print "<p>\n<hr>\n<p>\n";
	print "<a name=\"01\">\n";
	&table_table('Method', '1. Summary of Request Method Usage', \%ME,
		\&xsort,undef,undef,0,0,0);
	print "<a name=\"02\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&table_table('Protocol', '2. Summary of Protocol Usage', \%PR,
		\&xsort,undef,undef,0,0,0);
	print "<a name=\"03\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&table_table('Client',   '3. Summary of Client Usage',   \%CL,
		\&clsort,\&rev_fqdn,0,0,0,0);
#WAS                \&clsort,\&rev_fqdn,$TopN,0,0,0);
#####
	print "<a name=\"04\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";

	&table_table('Client',   '4. Summary of Top Client Usage', \%TCL,
		\&tclsort,\&rev_fqdn,0,0,0,0);
#####
	print "<a name=\"05\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&table_table('Server',   '5. Summary of Server Usage',   \%SE,
		\&xsort,\&rev_server,$TopN,1,0,0);
	print "<a name=\"06\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&table_table('Type',     '6. Summary of URL Types',      \%TY,
		\&xsort,undef,undef,0,0,0);
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<a name=\"07\">\n";
	print "<p>\n<hr>\n<p>\n";
	&table_table('Domain',   '7. Summary of URL Top-Level Domains', \%DO,
		\&xsort,\&top_domain_name,undef,0,$Colorize,1);
	print "<a name=\"08\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&utilization_table('Client',   '8. Client Utilization', \%CL,
		undef,\&rev_fqdn,undef);
	print "<a name=\"09\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&list_top('URL', "9. Top $TopN HTTP Requests", \%UR,
		\&aksort, undef, $TopN, 'ALLTCP');
	print "<a name=\"10\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&list_top('URL', "10. Top $TopN ICP Requests",  \%UR,
		\&aksort, undef, $TopN, 'ALLUDP');
	print "<a name=\"11\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&list_top('Target', "11. Top $TopN CONNECT Requests",  \%CN,
		\&aksort, undef, $TopN, 'ALL');
	print "<a href=\"#00\">Goto Top</a>\n";
# DENIED
	print "<a name=\"12\">\n";
	print "<a href=\"#00\">Goto Top</a>\n";
	print "<p>\n<hr>\n<p>\n";
	&list_top('URL', "12. Top $TopN DENIED Requests",  \%DUR,
		\&aksort, undef, $TopN, 'ALL');
	print "<a href=\"#00\">Goto Top</a>\n";

	print <<EOT
<p>
<hr>
Generated on $Date by 
<a href="$Url">$ScriptName $Version</a>. 
Copyright &copy; 1996 
<a href="mailto:iain\@sbs.de">Iain Lea</a>;
<P>
Porting for Oops, Changes copyright &copy; 1999
<A HREF="mailto:andy\@demos.su">Andrew A. Vasilyev</A>;
</body>
</html>
EOT
;
}

sub table_table {
	local($name,$title,$hash,$sortproc,$keyprint,$N,$makeurl,$Colorize,$BoldDomain) = @_;
	local($h1);
	
	if ($HtmlFormat) {
		if ($Colorize) {
		print <<EOT
<table border=2 width=100%>
<td align="center" bgcolor=$HitColor1><strong>&gt;= $HitPercent1% Hits</strong></td>
<td align="center" bgcolor=$HitColor2><strong>&gt;= $HitPercent2% Hits</strong></td>
<td align="center" bgcolor=$HitColor3><strong>&gt;= $HitPercent3% Hits</strong></td>
<td align="center" bgcolor=$HitColor4><strong>&gt;= $HitPercent4% Hits</strong></td>
<td align="center" bgcolor=$HitColor5><strong>&gt;= $HitPercent5% Hits</strong></td>
</table>
<p>
EOT
;		}
		print <<EOT
<table border=2 width=100%>
<caption><h2>$title</h2></caption>
<th rowspan=2>$name<th colspan=3>UDP COUNTS<th colspan=3>TCP COUNTS<th colspan=3>TCP BYTES
<tr>
<th>counts<th>%all<th>%hit<th>counts<th>%all<th>%hit<th>Mbytes<th>%all<th>%hit
EOT
;
	} else {
		print "\n", &center($title), "\n\n";
		&table_header($name);
		&table_dashes();
	}

	foreach $p (&{$sortproc}($hash)) {
		#print "p='$p'\n";
		if ($p eq 'BREAK') {
			&table_dashes() if !$HtmlFormat;
			next;
		}
		$h1 = \%{${$hash}{$p}};
		&print_counts($h1, $keyprint,$makeurl,$Colorize,$BoldDomain);
		last if (--$N == 0);
	}

	if ($HtmlFormat) {
		print "</table>\n";
	} else {
		&table_dashes();
		print "\n";
	}
	
	1;
}

sub list_top {
	local($name,$title,$hash,$sortproc,$keyprint,$N,$AK) = @_;
	local($h1);
	local($p);
	local($v);

	if ($HtmlFormat) {
		print <<EOT
<table border=2 width=100%>
<caption><h2>$title</h2></caption>
<th>Hits<th>$name
EOT
;
	} else {
		print "\n", &center($title), "\n\n";
	}

	foreach $p (&{$sortproc}($hash,$AK)) {
		$h1 = \%{${$hash}{$p}};
		$v = ${$h1}{COUNT}{$AK};
		last unless ($v > 0);

		if ($HtmlFormat) {
			if ($name eq "URL") {
				print "<tr>\n<td align=\"right\">$v<td><a href=\"$p\">$p</a>\n";
			} elsif ($name eq "Target") {
				print "<tr>\n<td align=\"right\">$v<td><a href=\"https://$p/\">https://$p/</a>\n";
			} else {
				print "<tr>\n<td align=\"right\">$v<td>$p\n";
			}
		} else {
			printf "%6d %-72.72s\n", $v, $p;
		}

		last if (--$N == 0);
	}
	if ($HtmlFormat) {
		print "</table>\n";
	} else {
		print "\n";
	}

	1;
}

sub print_chart {
	local($hashref,$title,$AK) = @_;
	local($max) = 1;
	local(%TOD);
	print "\n\n", &center($title), "\n\n";
	foreach $i ( 0..47 ) {
		$TOD{$i} = ${$hashref}{$i}{COUNT}{$AK};
        	$max = $TOD{$i} if ($TOD{$i} > $max);
	}
	$factor = 10 / $max;
	print "\t           +------------------------------------------------+\n";
	for ($r=9; $r>=0; $r--) {
        	$l = ($r / $factor) + 1;
        	$h = ($r+1) / $factor;
        	printf "\t%5d-%5d|", $l, $h;
        	foreach $i ( 0..47 ) {
                	print (($TOD{$i} * $factor > $r) ? '#' : ' ');
        	}
        	print "|\n";
	}
	print "\t  Counts   /------------------------------------------------+\n";
	print "\t       Hour 0 1 2 3 4 5 6 7 8 9 10  12  14  16  18  20  22   \n";
	1;
}

sub print_chart_html {
	local($hashref,$title,$AK) = @_;
	local($max) = 1;
	local(%TOD);
	local($Width) = 8; # 10
	local(@ReqsPercent);
	local($ReqsTotal) = $TCP_TOTAL_COUNT + $UDP_TOTAL_COUNT;
	
	print <<EOT
<table border=2 width=100%>
<caption><h2>Statistics from [$BegTime] to [$EndTime]</h2></caption>
<tr><th>$title</th><th></th><th>Requests</th></tr>
<tr>
<td rowspan=12>
EOT
;
	foreach $i ( 0..47 ) {
		$TOD{$i} = ${$hashref}{$i}{COUNT}{$AK};
        	$max = $TOD{$i} if ($TOD{$i} > $max);
	}
	$ReqPerPix = $max / $MaxHeight;
#	print STDERR "IL: Max=[$max] Height=[$MaxHeight] Req/Pix=[$ReqPerPix]\n";
	
	foreach $i ( 0..47 ) {
		$Reqs = ${$hashref}{$i}{COUNT}{$AK};
		$Height = int ($Reqs / $ReqPerPix);
		$Height = 1 if $Height < 1;

#		printf STDERR "TOD=[%5d] Pix=[%5d]\n",  $Reqs, $Height;

		$Percent = ($Reqs / $max) * 100;
		$Image = "$ImgDir/000-000.gif" if ($Percent == 0);
		$Image = "$ImgDir/000-010.gif" if ($Percent > 0);
		$Image = "$ImgDir/010-020.gif" if ($Percent > 10);
		$Image = "$ImgDir/020-030.gif" if ($Percent > 20);
		$Image = "$ImgDir/030-040.gif" if ($Percent > 30);
		$Image = "$ImgDir/040-050.gif" if ($Percent > 40);
		$Image = "$ImgDir/050-060.gif" if ($Percent > 50);
		$Image = "$ImgDir/060-070.gif" if ($Percent > 60);
		$Image = "$ImgDir/070-080.gif" if ($Percent > 70);
		$Image = "$ImgDir/080-090.gif" if ($Percent > 80);
		$Image = "$ImgDir/090-100.gif" if ($Percent > 90);

		print "<img src=\"$Image\" border=0 width=$Width height=$Height>";
	}

	foreach $i (0 .. 9) {
		$ReqsPercent[$i] = int(($max / 10) * ($i+1));
	}
	
	$BarWidth = $Width * 48;
	
	print <<EOT
<br>
<img src="$ImgDir/ampm-bar.gif" width=$BarWidth height=22 border=0 hspace=0 vspace=0>
</td>
<td><strong>Total<strong></td>
<td align="right">$ReqsTotal</td>
</tr>
<tr>
<td><img src="$ImgDir/090-100.gif" width=10 height=10> &gt 90%</td>
<td align="right">$ReqsPercent[9]</td>
</tr>
<tr>
<td><img src="$ImgDir/080-090.gif" width=10 height=10> &gt 80%</td>
<td align="right">$ReqsPercent[8]</td>
</tr>
<tr>
<td><img src="$ImgDir/070-080.gif" width=10 height=10> &gt 70%</td>
<td align="right">$ReqsPercent[7]</td>
</tr>
<tr>
<td><img src="$ImgDir/060-070.gif" width=10 height=10> &gt 60%</td>
<td align="right">$ReqsPercent[6]</td>
</tr>
<tr>
<td><img src="$ImgDir/050-060.gif" width=10 height=10> &gt 50%</td>
<td align="right">$ReqsPercent[5]</td>
</tr>
<tr>
<td><img src="$ImgDir/040-050.gif" width=10 height=10> &gt 40%</td>
<td align="right">$ReqsPercent[4]</td>
</tr>
<tr>
<td><img src="$ImgDir/030-040.gif" width=10 height=10> &gt 30%</td>
<td align="right">$ReqsPercent[3]</td>
</tr>
<tr>
<td><img src="$ImgDir/020-030.gif" width=10 height=10> &gt 20%</td>
<td align="right">$ReqsPercent[2]</td>
</tr>
<tr>
<td><img src="$ImgDir/010-020.gif" width=10 height=10> &gt 10%</td>
<td align="right">$ReqsPercent[1]</td>
</tr>
<tr>
<td><img src="$ImgDir/000-010.gif" width=10 height=10> &gt 0%</td>
<td align="right">$ReqsPercent[0]</td>
</tr>
</table>
EOT
;
	1;
}

sub utilization_table {
	local($name,$title,$hash,$sortproc,$keyprint,$N) = @_;
	local($h1);
	local(@CLIENTS);
	local($C);
	local(%UTIL);
	local(%HITRATE);
	local(%RATIO);

	if ($HtmlFormat) {
		print <<EOT
<table border=2 width=100%>
<caption><h2>$title</h2></caption>
<th>Client<th>Hitrate<th>HTTP:ICP Ratio<th>Utilization
EOT
;
		$TDL = "<td>";
		$TDR = "<td align=\"right\">";
		$TR = "<tr>";
	} else {
		print "\n", &center($title), "\n\n";
		printf "%-23.23s %7s + %14s = %s\n",
			'Client',
			'Hitrate',
			'HTTP:ICP Ratio',
			'Utilization';
		printf "%-23.23s %7s   %14s   %s\n", '-'x23,'-'x6,'-'x14,'-'x11;
	}

	@CLIENTS = keys %{$hash};
	foreach $C (@CLIENTS) {
		$h1 = \%{${$hash}{$C}};
		$UTIL{$C} = &utilization($h1,\$hitrate,\$ratio);
		$HITRATE{$C} = $hitrate;
		$RATIO{$C} = $ratio;
	}
	foreach $C (sort {$UTIL{$b} <=> $UTIL{$a}} @CLIENTS) {
		printf "$TR\n$TDL%-23.23s $TDR%7.2f + $TDR%14.2f = $TDR%11.2f\n",
			&{$keyprint}($C),
			$HITRATE{$C},
			$RATIO{$C},
			$UTIL{$C};
	}

	if ($HtmlFormat) {
		print "</table>\n";
	} else {
		print "\n";
	}

	1;
}

##############################################################################

sub print_counts {
	local($hashref, $keyprint, $makeurl, $Colorize, $BoldDomain) = @_;
	local($TCP_count) = 0;
	local($TCP_hitrate) = 0;
	local($TCP_allrate) = 0;
	local($THC) = 0;
	local($TCP_size) = 0;
	local($TCP_savings) = 0;
	local($TCP_sizerate) = 0;
	local($THS) = 0;
	local($UDP_count) = 0;
	local($UDP_hitrate) = 0;
	local($UDP_allrate) = 0;
	local($UHC) = 0;
	local($url);
	
	foreach $k (keys %{${$hashref}{COUNT}}) {
		$v=${$hashref}{COUNT}{$k};
		$TCP_count += $v if ($k =~ /^TCP_/);
		$THC += $v if ($k eq 'TCP_HIT' || $k eq 'TCP_REFRESH_HIT');
		$UDP_count += $v if ($k =~ /^UDP_/);
		$UHC += $v if ($k eq 'UDP_HIT' || $k eq 'UDP_REFRESH_HIT');
	}

	foreach $k (keys %{${$hashref}{BYTES}}) {
		$v=${$hashref}{BYTES}{$k};
		$TCP_size += $v if ($k =~ /^TCP_/);
		$THS += $v if ($k eq 'TCP_HIT' || $k eq 'TCP_REFRESH_HIT');
	}

	$UDP_hitrate = $UHC / $UDP_count if ($UDP_count);
	$UDP_allrate = $UDP_count / $UDP_TOTAL_COUNT;

	$TCP_hitrate = $THC / $TCP_count if ($TCP_count);
	$TCP_allrate = $TCP_count / $TCP_TOTAL_COUNT;

	$TCP_savings = $THS / $TCP_size if ($TCP_size);
	$TCP_sizerate = $TCP_size / $TCP_TOTAL_BYTES;

	if ($HtmlFormat) {
		$Color = '';
		if ($Colorize) {
			$HitPercent = int ($TCP_savings * 100 + 0.5);
			if ($HitPercent >= $HitPercent5) {
				$Color = "bgcolor=$HitColor5";
			} elsif ($HitPercent >= $HitPercent4) {
				$Color = "bgcolor=$HitColor4";
			} elsif ($HitPercent >= $HitPercent3) {
				$Color = "bgcolor=$HitColor3";
			} elsif ($HitPercent >= $HitPercent2) {
				$Color = "bgcolor=$HitColor2";
			} elsif ($HitPercent >= $HitPercent1) {
				$Color = "bgcolor=$HitColor1";
			}
		}
		$TDL = "<td $Color>";
		$TDR = "<td $Color align=\"right\">";
		$LF = "<tr>\n";

		$p = &{$keyprint}($p) if (defined($keyprint));
		if ($BoldDomain) {
			$p =~ /^([A-z]*) (.*)/;
			if ($2 ne "") {
				$p = "<b>$1</b> $2";
			} elsif ($1 ne "") {
				$p = "$1";
			}
# print STDERR "[$1] [$2] $p\n" if ($1 eq '');
		}
	} else {
		$TDL = $TDR = "";
		$LF = "\n";
		$p = &{$keyprint}($p) if (defined($keyprint));
	}

	$url = rev_server($p);
	
	print "$LF";
	if ($makeurl) {
		printf "$TDL<a href=\"%s/\">%s/</a> ", $url, $url;
	} else {
		printf "$TDL%s ", $p;
	}
	printf "$TDR%7d ", $UDP_count;
	printf "$TDR%4s ", &percent($UDP_allrate);
	printf "$TDR%4s ", &percent($UDP_hitrate);
	printf "$TDR%7d ", $TCP_count;
	printf "$TDR%4s ", &percent($TCP_allrate);
	printf "$TDR%4s ", &percent($TCP_hitrate);
	printf "$TDR%8.2f ", $TCP_size / 1000000;
	printf "$TDR%4s ", &percent($TCP_sizerate);
	printf "$TDR%4s ", &percent($TCP_savings);
}

sub utilization {
	local($hashref, $hitref, $ratioref) = @_;
	local($TCP_count) = 0;
	local($TCP_hitrate) = 0;
	local($THC) = 0;
	local($UDP_count) = 0;
	local($UDP_TCP_ratio) = 0.8;

	foreach $k (keys %{${$hashref}{COUNT}}) {
		$v=${$hashref}{COUNT}{$k};
		$TCP_count += $v if ($k =~ /^TCP_/);
		$THC += $v if ($k eq 'TCP_HIT' || $k eq 'TCP_REFRESH_HIT');
		$UDP_count += $v if ($k =~ /^UDP_/);
	}

	$TCP_hitrate = $THC / $TCP_count if ($TCP_count);
	$UDP_TCP_ratio = $TCP_count / $UDP_count if ($UDP_count);
	${$hitref} = $TCP_hitrate if $hitref;
	${$ratioref} = $UDP_TCP_ratio if $ratioref;
	$TCP_hitrate + $UDP_TCP_ratio;
}

sub sortbyCS {
	local($A) = $TCP_HIT_CS{$a} + $TCP_DONE_CS{$a};
	local($B) = $TCP_HIT_CS{$b} + $TCP_DONE_CS{$b};
	$B <=> $A;
}

sub sortby_ALL_SC {
	$ALL_SC{$b} <=> $ALL_SC{$a};
}

sub sortby_ALL_PC {
	$ALL_PC{$b} <=> $ALL_PC{$a};
}

sub sortby_ALL_XC {
	$ALL_XC{$b} <=> $ALL_XC{$a};
}


sub table_dashes {
printf "%s %s-%s-%s %s-%s-%s %s-%s-%s\n", '-'x23,
	'-'x7,'-'x4,'-'x4,
	'-'x7,'-'x4,'-'x4,
	'-'x8,'-'x4,'-'x4;
}

sub table_header {
	local($_) = @_;
	local($lead) = 23 + 1;
	print ' 'x$lead;
	print '    UDP COUNTS        TCP COUNTS          TCP BYTES' . "\n";

	print $_;
	print ' 'x($lead - length);
	print ' counts %all %hit  counts %all %hit   Mbytes %all %hit' . "\n";
}

sub rev_server {
	local($_) = @_;
	local($proto);
	local($name);
	local(@F);
        if (/([^:]+):\/\/([^:]+)(.*)/) {
                $proto = $1;
                $name = $2;
                $port = $3;
                unless ($name =~ /^[0-9\.]+$/) {
                        @F = split(/\./, $name);
                        $name = join ('.', reverse @F);
                }
                $_ = $proto . '://' . $name . $port;
        }
	$_;
}

sub ReadCmdLine
{
	my ($ProgName) = @_;
	
	&Getopts('cChHi:m:n:p:v');

	$HtmlFormat = $opt_H if (defined($opt_H));
	$ImgDir = $opt_i if (defined($opt_i));
	$HostName = $opt_m if (defined($opt_m));
	$TopN = $opt_n if (defined($opt_n));
	$PortNum = $opt_p if (defined($opt_p));
	$Colorize = 0 if (defined($opt_C));
	$NoCruft = 1 if (defined($opt_c));
	$Verbose = 1 if (defined($opt_v));

	if ($opt_h) { 
		print <<EOT
Create HTML statistics from Squid Internet Object Cache access logfile.
Copyright 1996 Iain Lea (iain\@sbs.de).     NOTE: Use at your own risk.

Usage: $ProgName [options] < summary.log > summary.html
       -h       help
       -c       don't print images or /cgi-bin/ URL's in Top $TopN listings
       -C       don't colorize hit-rates in domain table
       -i dir   image directory for gif's
       -m host  hostname to use in html
       -n num   number of URL's to list     
       -p num   port number (default: $PortNum)
       -v       verbose

EOT
;
		exit 1;
	}	
}
