#!/opt/perl/bin/perl
#
$versn = "1.0 - 04 MAR 99" ;             # Code version and modify date
#
# Find each archived log file and rollup its main values
#
#   logrollup "domain.name"
#
# Expected input filenames are in the directory:
#   /opt/web/web-domain.name/htdocs/Private/wwwstats/stats-XXXX/
# Where XXXX is the year. They have filenames of the form:
#   Mmm.wwwclientstats.html
# Where Mmm is the month
#
# This code copyright 1998-99 by
# D. W. Eaton, Artronic Development, Phoenix, AZ -- dwe@arde.com
#
# This software is made freely available under the provisions of the Perl
# "Artistic" license:  http://language.perl.com/misc/Artistic.html
#
# This code is not supported and is not warranteed to perform any particular
# function. Contact dwe@arde.com for aditional information.
# If you find bugs or make enhancements, it would be appreciated if you
# sent them on to the author at dwe@arde.com.

require "ctime.pl" ;
#
$true = 1;  # truth values
$false = 0;
# --------------------------------------------------------
# Configurable values:
$webroot = "/opt/web";      # Root of all Web sites on disk
$clientpfx = "web-";        # Prefix on client Web directories
$reportpath = "/htdocs/Private/wwwstats"; # Path to wwwstat reports
#$logmatch = "client";       # special identifier in wwwstats for files   
# To match all report files, use this rather than the line above:
$logmatch = "wwwstat";       # special identifier in wwwstats for files
$reportfile = "history.html"; # Name of the generated history rollup file
$debugme   = "no";          # Set to "yes" to just re-name old file
$endsect = "</PRE>";        # Characters flaging end of section
#
# These lines must match those in the pre-computed stats file
# (e.g. from wwwstat-2.0)
%validentries = (
  'Requests Received During Summary Period' , 'req',
  'Bytes Transmitted During Summary Period' , 'byt',
  'Pages Transmitted During Summary Period' , 'pgs',
  'Average Requests Received Daily' , 'avreq',
  'Average Bytes Transmitted Daily' , 'avbyt',
  'Average Pages Transmitted Daily' , 'avpgs',
# Next two lines are for handling wwwstat-1.0 reports:
  'Files Transmitted During Summary Period', 'req',
  'Average Files Transmitted Daily', 'avreq'
 );

%name_months = ('Jan','01', 'Feb','02', 'Mar','03', 'Apr','04',
 'May','05', 'Jun','06', 'Jul','07','Aug','08', 'Sep','09',
 'Oct','10', 'Nov','11', 'Dec', '12');

# ---- end normal configuration items --------------------

# ---- logic ---------------------------------------------
# Get the one command-line arguments that should have been passed:
$numargs = scalar (@ARGV) ;
if ($numargs == 1)
{
 $client = shift (@ARGV) ;
}
else
{
 print "Error: should have 1 argument, domain.name - found $numargs\n";
 exit (1);
}

# Snatch current date info
$submitdate = time ;
$submitdate = ctime($submitdate) ;
$submitdate =~ s/\n//g ;

# Build path to wwwstats reports
$dirname = "$webroot/$clientpfx" . $client . $reportpath;

# Look for all matching file names
$matchpat = "stats-";       # Prefix of year-specific log directories
($matches,$dirlist) = &getls($dirname,$matchpat);

# Cycle through each name found
while ($dirlist)
{
 # Split each entry
 ($nextdir,$dirlist) = split ("\n",$dirlist,2);
 $thisyear = $nextdir;
 $thisyear =~ s/^.*\-//;

 $matchpat = $logmatch; # special identifier for the files
 ($matches,$filelist) = &getls($nextdir,$matchpat);

 while ($filelist)
 {
  ($nextfile,$filelist) = split ("\n",$filelist,2);
  $thismon = $nextfile;
  $thismon =~ s/^.*\///;
  $thismon =~ s/\..*$//;
  $thislabel = "$thisyear-$thismon";
  $thiskey = "$thisyear-$name_months{$thismon}";

  $results = &read_next_file($nextfile);
  if ($results)
  {
   # If we had results, build an output line
   $results .= " | $thislabel";
   $resultlines{$thiskey} = $results;
  }
 }
}

# Now build the real output
$outcontent .= "<\!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n";
$outcontent .= "<HTML><HEAD>\n";
$outcontent .= "<TITLE>World Wide Web Historical Statistics for ";
$outcontent .= "client report of $client</TITLE>\n";
$outcontent .= "</HEAD><BODY>\n";
$outcontent .= "<H1>World Wide Web Access Statistics for ";
$outcontent .= "client report of $client</H1>\n";
$outcontent .= "<EM>Last updated: $submitdate</EM>\n";

$outcontent .= "<H2><A NAME=\"Historical\">Historical Section</A></H2>\n";
$outcontent .= "<PRE>\n";
$outcontent .= "  Requests  Total Bytes  Pages    Req/Day    Bytes/Day Pg/Day | Year-Month\n";
$outcontent .= "---------- ------------ ------ ---------- ------------ ------   ----------\n";

foreach $key (sort keys %resultlines)
{
 $outcontent .= "$resultlines{$key}\n";
}
$outcontent .= "</PRE>\n";
$outcontent .= "</BODY></HTML>\n";

$changed = $true; # Signal to output this file (incase we need to check)

# -- -- -- save new file -- -- --
$thisfile = $dirname . "/" . $reportfile;
if ($changed)
{
 # Write to alt file until we know it all got there:
 if (open (MYFILE, ">$thisfile.new"))
 {
  print MYFILE "$outcontent" ;
  close (MYFILE) ;
 }
 else
 {
  # Wanted to write file but couldn't
  &err_msg ("Can't create new file $thisfile.new:  $!\n") ;
  exit (0) ;
 }
 # -- -- -- end save new file -- -- --

 # Get rid of old one and rename this one:
 if ($debugme eq "yes")
 {
  # Rename orig file (rather than just delete it):
  unlink ("$thisfile.bak") ;
  rename ("$thisfile", "$thisfile.bak") ;
 }
 else
 {
  # Just get rid of old file:
  unlink ("$thisfile") ;
 }
 rename ("$thisfile.new", "$thisfile") ;
 if ($debugme eq "yes")
 {
  print "Updated file $thisfile\n";
 }
}
else
{
 print "File $thisfile not changed\n";
}
#
exit (0) ;
### END.

# --------------------------- subroutines ----------------------------
# Get list of contents of directory
# (subject to optional pattern match)
#   ($results,$textresults) = &getls("newdir"[,"pattern"])
# where $results:
#     0 = directory not found or not opened or no pattern matches found
#    +n = count of the matches
# and $textresults:
#  null = directory not found or not opened or no pattern matches found
#  text = actual matches, one per line
sub getls
{
 local ($newdir,$newpatt) = @_;
 local ($name,$results,$textresults);

 $results = 0;
 $textresults = "";

 if (! opendir (DIR, $newdir))
 {
  print "Cannot open directory '$newdir'\n" ;
  return (0) ;
 }

 while (defined($name = readdir (DIR)))
 {
  # Scan each file in turn ...
  if ($newpatt)
  {
   next unless ($name =~ /$newpatt/) ;
  }
  $results++;
  $textresults .= "$newdir/$name\n";
 }
 closedir (DIR) ;
 return ($results,$textresults);
}

$errmsg = '' ;

#
# ---------------- read file -----------------
# $results = &read_next_file("thisfilename");
#
sub read_next_file
{
 my ($thisfile) = @_ ;
 my ($errmsg,$outcontent,$needmore,$insection,$lineno);
 my ($longdesc,$value);
 my ($unknown,$key,$line);

 $errmsg = "";
 $outcontent = ""; # Initialize to no output content
 foreach $key (keys %validentries)
 {
  $varname = $validentries{$key};
  $$varname = 0; # initialize
 }
 $unknown = 0;

 if (open (MYFILE, "<$thisfile"))
 {
   $lineno = 0;
   $needmore = $true;
   while (($line = <MYFILE>) && $needmore)
   {
    $lineno++;
    chomp($line);

    if ($insection)
    {
     if ($line =~ /$endsect/)
     {
      # Guess we are done
      $insection = $false;
      $needmore = $false;
     }
     elsif ($line =~ /\s+\d+$/)
     {
      # Found another data line
      ($longdesc,$value) = split ("  ",$line,2);
      if ($validentries{$longdesc})
      {
       $varname = $validentries{$longdesc};
      }
      else
      {
       # Oops, found an unexpected line
       print STDERR "Unexpected summary line: $longdesc $value\n";
       $varname = "unknown";
      }
      $value =~ s/\s+//; # Strip leading blanks
      $$varname = $value;
     }
    }
    elsif ($line =~ /Totals for Summary Period/)
    {
     $insection = $true;
    }
    else
    {
     # Just ignore all others:
    }
   }
   close (MYFILE);
 }
 else
 {
   $errmsg .= " (can't open file '$thisfile')" ;
 }
 if ($errmsg)
 {
  &err_msg ("$errmsg\n") ;
  exit (1) ;
 }

 # Build final output:
 if ($req || $byt || $pgs || $avreq || $avbyt || $avpgs)
 {
  $outcontent = sprintf ("%10.0f %12.0f %6.0f %10.0f %12.0f %6.0f",$req,$byt,$pgs,$avreq,$avbyt,$avpgs);
 }
 return ($outcontent);

}
# ---------------- file read -----------------

# --------------------
#
# Tell user that an error has occurred
sub err_msg
{
   local ($msg) = @_ ;

   print "Error found by $0 version $vernum --\n";
   print "<P>$msg<P>\n" ;
}
#---------------------
