#!/usr/local/bin/perl
# -------------------------------------------------------------------------------
# Name: Bacon (Food of the gods)
# Written by: Justin Robinson
# Purpose: Create a report of webtraffic.
$version = "1.071999";
# -------------------------------------------------------------------------------
# This program may be freely used and modified, provided the above header lines
# are kept intact.
# -------------------------------------------------------------------------------
# How to install Bacon:
#	1 - put the bacon.pl file into your webserver's cgi-bin directory.
#	2 - Add these lines to your httpd.conf
#		LogFormat "%h|%t|%T|http://%V%U|%>s|%b|%{Referer}i|%{User-Agent}i|%V" bacon
#		CustomLog /var/log/httpd-bacon.log bacon
#	3 - Fix permissions
#               touch /var/log/httpd-bacon.log
#		chown <httpd-daemon user> /var/log/httpd-bacon.log
#		chmod 600 /var/log/httpd-bacon.log
#		mkdir /var/log/weblogs
#		chown <httpd-daemon user> /var/log/weblogs
#		chmod 700 /var/log/weblogs
#	4 - Restart httpd
#		kill -HUP `cat /var/run/httpd.pid`
#
#
# Any questions please contact me at:
# jmrobins@samurai.ruin.org
# -------------------------------------------------------------------------------

print "Content-type: text/html\n\n";
use CGI qw(:standard escapeHTML);

# -- User-changeable varaiables ------
  $logdir    = "/var/log/";
  $outlogdir = "/var/log/weblogs/";
  $logfile   = "${logdir}httpd-bacon.log";
  $bgcolor    = "White";
  $text       = "Black";
  $link       = "Blue";
  $vlink      = "Purple";
  $background = "";
# ------------------------------------



# ---------------------------
# Do NOT Edit below this line
# ---------------------------



$server_name = $ENV{'SERVER_NAME'};
$request_uri = $ENV{'SCRIPT_NAME'};
  $script    = "http://${server_name}${request_uri}";


 $remote_host = 0;
   $date_time = 1;
$elapsed_time = 2;
         $url = 3;
 $result_code = 4;
       $bytes = 5;
     $referer = 6;
     $browser = 7;
$virtual_host = 8;
 $number_hits = 9;


&update_logfiles();
&output_html_header();
&output_form();
&display_virtual_host if (param('VirtualHost'));
&display_urlhit_detail if (param('DISPLAY_URLHIT_DETAIL'));
&display_hosthit_detail if (param('DISPLAY_HOSTHIT_DETAIL'));
&output_html_footer();








# ------------- Subroutines ----------------------------------------------------------------------------------------------------

sub update_logfiles {
  open logfile, "$logfile" or die "could not open file: $logfile: $!\n";
  foreach (<logfile>) {
    s/^\s*(.*?)\s*$/$1/;
    (@values) = split /\|/;
    next if ($values[$url] =~ /^.*${request_uri}.*$/);
    open savefile, ">>${outlogdir}$values[${virtual_host}]" or die "Could not open file: ${outlogdir}$values[${virtual_host}]: $!\n";
    print savefile "$_\n";
    close savefile;
  }
  close logfile;
  open logfile, ">${logfile}" or die "Could not open file: ${logfile}: $!\n";
  close logfile;
}



sub output_html_header {
  print "
    <html>
      <head>
        <title>
          WebStats
        </title>
      </head>
      <body bgcolor=\"${bgcolor}\" text=\"$text\" link=\"$link\" vlink=\"$vlink\" background=\"$background\">
  ";
}



sub output_form {
  print "
        <form name=HostSelect action=\"${script}\" method=POST>
          <select name=\"VirtualHost\">
";
  opendir weblogs, "${outlogdir}";
  (@entries) = sort readdir weblogs;
  closedir weblogs;
  foreach (@entries) {
    next if (/^\./);
      print "            <option value=\"${_}\">${_}\n";
  }
  print "          </select>
          <input type=submit name=\"Submit\" value=\"Show Entries\">
        </form>
        <br><br>
  ";
}




sub display_virtual_host {
  $virthost = param('VirtualHost');
  print "
        <center>
          <table width=75% border=0>
            <tr>
              <td align=center width=100%>
                <hr>
              </td>
            </tr>
            <tr>
              <td align=left width=100%>
                <font size=4 color=Black>
                  Displaying Statistics for:       
                </font>
                <font size=4 color=Red>
                  ${virthost}
                </font>
              </td>
            </tr>
            <tr>
              <td align=center width=100%>
                <hr>
              </td>
            </tr>
          </table>
          <table width=70% border=0>
            <tr>
              <td align=center width=40%>
                <b>
                  Web Address (URL)
                </b>
              </td>
              <td align=center width=20%>
                <b>
                  Bytes Transfered
                </b>
              </td>
              <td align=center width=20%>
                <b>
                  Time taken (seconds)
                </b>
              </td>
              <td align=center width=20%>
                <b>
                  Number of Hits
                </b>
              </td>
            </tr>

            <tr>
              <td align=center width=40%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
            </tr>
  ";

  $skipped_graphics = 0;
  $filename = param('VirtualHost');
  open logfile, "${outlogdir}${filename}" or die "Could not open file: ${outlogdir}${filename}: $!";
  foreach (<logfile>) {
    (@values) = split /\|/;
    (@oldvalues) = split /\|/, $myhash{$values[$url]};
    if ($values[$url] =~ /\.(gif|jpg|jpeg)$/i) {
      unless (param('SHOW_GRAPHICS')) {
        $skipped_graphics++;
        next;
      }
    }

    $values[$bytes] = 0 unless ($values[$bytes] =~ /^\d+$/);
    $values[$elapsed_time] = 0 unless ($values[$elapsed_time] =~ /^\d+$/);

    $values[$elapsed_time] += $oldvalues[$elapsed_time];
    $values[$bytes] += $oldvalues[$bytes];
    $values[$number_hits] = $oldvalues[$number_hits] + 1;

    $myhash{$values[$url]} = "\|\|$values[$elapsed_time]\|$values[$url]\|\|$values[$bytes]\|\|\|\|$values[$number_hits]";
  }
  close logfile;

  for $family (sort keys %myhash) {
    $myhash{$family} =~ s/^\s*(.*?)\s*$/$1/;
    (@values) = split /\|/, $myhash{$family};
    print "
           <tr>
              <td align=left width=40%>
                <a href=\"$values[$url]\">$values[$url]</a>
              </td>
              <td align=center width=20%>
                $values[$bytes]
              </td>
              <td align=center width=20%>
                $values[$elapsed_time]
              </td>
              <td align=center width=20%>
                <a href=\"${script}?DISPLAY_URLHIT_DETAIL=1&URL=$values[$url]&VIRTUAL_HOST=${filename}\">$values[$number_hits]
              </td>
           </tr>
    ";
    $total_bytes += $values[$bytes];
    $total_time += $values[$elapsed_time];
    $total_hits += $values[$number_hits];
  }
#  close logfile;

  print "
            <tr>
              <td align=center width=40%>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
            </tr>

            <tr>
              <td align=right width=40%>
                <font color=Red>
                  Totals:
                </font>
              </td>
              <td align=center width=20%>
                <font color=Red>
                  ${total_bytes}
                </font>
              </td>
              <td align=center width=20%>
                <font color=Red>
                  ${total_time}
                </font>
              </td>
              <td align=center width=20%>
                <font color=Red>
                  ${total_hits}
                </font>
              </td>
          </tr>
        </table>
      </center>
  ";

  if ($skipped_graphics) {
    print "
      <center>
        <font color=blue>
          <a href=\"${script}?VirtualHost=${virthost}&SHOW_GRAPHICS=1\">Display image files (${skipped_graphics})</a>
        </font>
      </center>
    ";
  }

  if (param('SHOW_GRAPHICS')) {
    print "
      <center>
        <font color=blue>
          <a href=\"${script}?VirtualHost=${virthost}\">Hide image files</a>
        </font>
      </center>
    ";
  }
}



sub display_urlhit_detail {
  $detail = param('URL');
  $virthost = param('VIRTUAL_HOST');
  print "
        <center>
          <table width=50% border=0>
            <tr>
              <td align=center width=100%>
                <hr>
              </td>
            </tr>
            <tr>
              <td align=left width=100%>
                <font size=4 color=Black>
                  Displaying URL hit-data for:
                </font>
                <font size=4 color=Red>
                  ${detail}
                </font>
              </td>
            </tr>
            <tr>
              <td align=center width=100%>
                <hr>
              </td>
            </tr>
          </table>
          <table width=50% border=0>
  ";

  $filename = param('VIRTUAL_HOST');
  open logfile, "${outlogdir}${filename}" or print "Could not open file: ${outlogdir}${filename}: $!";
  foreach (<logfile>) {
    s/^\s*(.*?)\s*$/$1/;
    (@values) = split /\|/;
    $myhash{$values[$remote_host]} = "$values[$url]" if ($values[$url] eq param('URL'));
  }
 
  for $family (sort keys %myhash) {
    print "
            <tr>
              <td align=left width=100%>
                <a href=\"${script}?DISPLAY_HOSTHIT_DETAIL=1&REMOTE_HOST=${family}&VIRTUAL_HOST=$filename\">${family}</a>
              </td>
            </tr>
    ";
  }
  close logfile;
  print "
              </td>
            </tr>
          </table>
          <hr width=50%>
        </center>
  ";

}



sub display_hosthit_detail {
  $detail = param('REMOTE_HOST');
  $virthost = param('VIRTUAL_HOST');
  print "
        <center>
          <table width=75% border=0>
            <tr>
              <td align=center width=100%>
                <hr>
              </td>
            </tr>
            <tr>
              <td align=left width=100%>
                <font size=4 color=Black>
                  Displaying Host hit-data for:
                </font>
                <font size=4 color=Red>
                  ${detail}
                </font>
              </td>
            </tr>
            <tr>
              <td align=center width=100%>
                <hr>
              </td>
            </tr>
          </table>
          <table width=70% border=0>
            <tr>
              <td align=center width=40%>
                <b>
                  Web Address (URL)
                </b>
              </td>
              <td align=center width=20%>
                <b>
                  Bytes Transfered
                </b>
              </td>
              <td align=center width=20%>
                <b>
                  Time taken (seconds)
                </b>
              </td>
              <td align=center width=20%>
                <b>
                  Number of Hits
                </b>
              </td>
            </tr>

            <tr>
              <td align=center width=40%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
            </tr>
  ";

  $skipped_graphics = 0;
  $filename = param('VIRTUAL_HOST');
  open logfile, "${outlogdir}${filename}" or die "Could not open file: ${outlogdir}${filename}: $!";
  foreach (<logfile>) {
    (@values) = split /\|/;
    next unless ($values[$remote_host] eq param('REMOTE_HOST'));
    if ($values[$url] =~ /\.(gif|jpg|jpeg)$/i) {
      unless (param('SHOW_GRAPHICS')) {
        $skipped_graphics++;
        next;
      }
    }

    (@oldvalues) = split /\|/, $myhash{$values[$url]};
    $values[$elapsed_time] += $oldvalues[$elapsed_time];
    $values[$byes] += $oldvalues[$bytes];
    $values[$number_hits] = $oldvalues[$number_hits] + 1;
    $myhash{$values[$url]} = "\|\|$values[$elapsed_time]\|$values[$url]\|\|$values[$bytes]\|\|\|\|$values[$number_hits]";
  }
  close logfile;

#  foreach (@logs) {
  for $family (sort keys %myhash) {
    $myhash{$family} =~ s/^\s*(.*?)\s*$/$1/;
    (@values) = split /\|/, $myhash{$family};
    print "
           <tr>
              <td align=left width=40%>
                <a href=\"$values[$url]\">$values[$url]</a>
              </td>
              <td align=center width=20%>
                $values[$bytes]
              </td>
              <td align=center width=20%>
                $values[$elapsed_time]
              </td>
              <td align=center width=20%>
                <a href=\"${script}?DISPLAY_URLHIT_DETAIL=1&VIRTUAL_HOST=${filename}&URL=$values[$url]\">$values[$number_hits]
              </td>
           </tr>
    ";
    $total_bytes += $values[$bytes];
    $total_time += $values[$elapsed_time];
    $total_hits += $values[$number_hits];
  }
#  close logfile;

  print "
            <tr>
              <td align=center width=40%>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
              <td align=center width=20%>
                <hr>
              </td>
            </tr>

            <tr>
              <td align=right width=40%>
                <font color=Red>
                  Totals:
                </font>
              </td>
              <td align=center width=20%>
                <font color=Red>
                  ${total_bytes}
                </font>
              </td>
              <td align=center width=20%>
                <font color=Red>
                  ${total_time}
                </font>
              </td>
              <td align=center width=20%>
                <font color=Red>
                  ${total_hits}
                </font>
              </td>
          </tr>
        </table>
      </center>
  ";

  if ($skipped_graphics) {
    print "
      <center>
        <font color=blue>
          <a href=\"${script}?DISPLAY_HOSTHIT_DETAIL=1&VIRTUAL_HOST=${filename}&REMOTE_HOST=${detail}&SHOW_GRAPHICS=1\">Display image files (${skipped_graphics})</a>
        </font>
      </center>
    ";
  }

  if (param('SHOW_GRAPHICS')) {
    print "
      <center>
        <font color=blue>
          <a href=\"${script}?DISPLAY_HOSTHIT_DETAIL=1&VIRTUAL_HOST=${filename}&REMOTE_HOST=${detail}\">Hide image files</a>
        </font>
      </center>
    ";
  }
}



sub output_html_footer {
  print "
        <center>
          <hr width=75%>
        </center>
        <br><br>
        <i>
          Written by: <a href=\"mailto:jmrobins\@samurai.ruin.org\">Justin Robinson</a><br>
          Last Revision: ${version}
        </i>
      </body>
    </html>
  ";
}
