home *** CD-ROM | disk | FTP | other *** search
/ Internet 1996 World Exposition / park.org.s3.amazonaws.com.7z / park.org.s3.amazonaws.com / Japan / LOGS / accesswatch.pl < prev    next >
Perl Script  |  2017-09-21  |  38KB  |  1,105 lines

  1. #!/usr/local/bin/perl
  2. # -*- Perl -*-
  3. # CONFIG: Change the first line to indicate the Perl binary on your system.
  4. #          Try "whereis perl" or "find / -name perl -print"
  5.  
  6. ###############################################################################
  7. ##                                                                           ##
  8. ##     AccessWatch v1.32 - Access accounting for World Wide Web sites        ##
  9. ##      Copyright (C) 1994-1996 by David G. Maher. All rights reserved.      ##
  10. ##      <URL:http://www.eg.bucknell.edu/~dmaher/accesswatch/>                ##
  11. ##                                                                           ##
  12. ##     Contact Information:                                                  ##
  13. ##        Dave Maher <dmaher@bucknell.edu>                                   ##
  14. ##        C-0500 Bucknell University, Lewisburg, PA 17837 USA                ##
  15. ##        <URL:http://www.eg.bucknell.edu/~dmaher/>                          ##
  16. ##                                                                           ##
  17. ##     Please read the included license agreement (readme.txt) before        ##
  18. ##      using this program. Your use of this software indicates your         ##
  19. ##      acceptance of the license agreement and warranty.                    ##
  20. ##                                                                           ##
  21. ##     If you wish to modify this code, mail <dmaher@bucknell.edu>.          ##
  22. ##                                                                           ##
  23. ###############################################################################
  24.  
  25. ###############################################################################
  26. ########## Credits and thanks for great ideas #################################
  27. ###############################################################################
  28. ##                                                                           ##
  29. ## A huge thank you to Paul Blackman <ictinus@lake.canberra.edu.au> for      ##
  30. ##   his work on hourly server statistics, including a table of hourly       ##
  31. ##   accesses/hour.                                                          ##
  32. ##                                                                           ##
  33. ## Thanks to Jeff Boulter <boulter@bucknell.edu> for access error exclusion  ##
  34. ##   code, and for his many suggestions and debugging help.                  ##
  35. ##                                                                           ##
  36. ## Many thanks for suggestions and code tweaks:                              ##
  37. ##      Chris Brown <cwb3@ra.msstate.edu>                                    ##
  38. ##      Ron Gery    <rong@halcyon.com>                                       ##
  39. ##                                                                           ##
  40. ###############################################################################
  41.  
  42. # *** File configuration ***
  43.  
  44. ($base=$0) =~ s/[A-z0-9,\.,\-]*$//;  # if you have trouble, define $base as
  45.                                      #  the full directory pathname that 
  46.                                      #  contains the accesswatch script.
  47.  
  48. require $base.'accesswatch.cfg' || die "Configuration file not found: $!\n"; 
  49.  
  50. foreach (@ARGV) {
  51.     $verbose = 1 
  52.     if (/v/);   # turn on -v command line switch
  53.     $verbose = 0    
  54.     if (/q/);   # turn on -q command line switch
  55. }
  56.  
  57. $summarylink = $ARGV[0] . ".html";                 # Summary information link
  58. $detailslink = "details.html";               # Access details link
  59.  
  60. $summaryfile = $base.$summarylink;           # Summary Information file
  61. $detailsfile = $base.$detailslink;           # Access details file
  62.  
  63. $domaincodes = $base.'lib/domain.desc';      # Location of domaincodes database
  64. $pagedescriptions = $base.'lib/page.desc';   # Text description of urls
  65.  
  66. # *** Graphics files ***
  67.  
  68. local(%horizbar) = ( 0, "img/blueblock.gif",
  69.              1, "img/redblock.gif"
  70.            );
  71.  
  72. local(%vertbar) = ( -1,  "img/clearvert.gif",
  73.              0,  "img/brwnvert.gif",
  74.              1,  "img/ltgnvert.gif",
  75.              2,  "img/pinkvert.gif",
  76.              3,  "img/cyanvert.gif",
  77.              4,  "img/orgvert.gif",
  78.              5,  "img/purpvert.gif",
  79.              6,  "img/yellvert.gif",
  80.              7,  "img/grnvert.gif",
  81.              8,  "img/bluevert.gif",
  82.              9,  "img/redvert.gif"
  83.           );
  84.  
  85. # *** Other options ***
  86.  
  87. $truncate =  1;   # Truncate extra path info for page demand list if too long.
  88. $toolong  = 50;   # If you want to truncate, how *many* characters is too long?
  89.  
  90. ###############################################################################
  91. ########     NO MODIFICATIONS MAY BE MADE TO THE FOLLOWING CODE        ########
  92. ########            WITHOUT THE CONSENT OF THE AUTHOR                  ########
  93. ###############################################################################
  94.  
  95. # *** Data structures and counters ***
  96.  
  97. local(@accesses);        # contains entire list of page accesses
  98.  
  99. local(%domains, %pages, %hosts);# contain list of domain extensions, pages,
  100.                                 #  and unique hosts, and associates each
  101.                                 #  with the appropriate count.
  102.  
  103. local(%pageDesc, %domainDesc);  # lists of page urls/domaincodes with 
  104.                                 # corresponding descriptions
  105.  
  106. local(%stat) = (
  107.      'accesses',       '0', # count of pages served
  108.      'serverCount',    '0', # server hits
  109.      'hits',           '0', # total subdirectory hits
  110.      'localCount',     '0', # number of accesses from local machines
  111.      'errors',         '0', # number of answers > 400 from server
  112.      'redirect',       '0', # number of redirects  
  113.      'size',           '0', # number of bytes transmitted
  114.  
  115.      'uniqueHosts',    '0', # computed by UpdateStatArray
  116.      'hostPageAverage','0', # computed by UpdateStatArray
  117.      'serverLoad',     '0', # computed by UpdateStatArray
  118.      'localPercent',   '0', # computed by UpdateStatArray
  119.      'outsidePercent', '0', # computed by UpdateStatArray
  120.      'outsideCount',   '0', # computed by UpdateStatArray
  121.      'accessesPerHour','0', # computed by UpdateStatArray
  122.      'accessesPerDay', '0', # computed by UpdateStatArray
  123.      
  124.          'hr00',           '-1', # accesses in hour 0
  125.      'hr01',           '-1', # accesses in hour 1
  126.      'hr02',           '-1', # accesses in hour 2
  127.      'hr03',           '-1', # accesses in hour 3
  128.      'hr04',           '-1', # accesses in hour 4
  129.      'hr05',           '-1', # accesses in hour 5
  130.      'hr06',           '-1', # accesses in hour 6
  131.      'hr07',           '-1', # accesses in hour 7
  132.      'hr08',           '-1', # accesses in hour 8
  133.      'hr09',           '-1', # accesses in hour 9
  134.      'hr10',       '-1', # accesses in hour 10
  135.      'hr11',       '-1', # accesses in hour 11
  136.      'hr12',       '-1', # accesses in hour 12
  137.      'hr13',       '-1', # accesses in hour 13
  138.      'hr14',       '-1', # accesses in hour 14
  139.      'hr15',       '-1', # accesses in hour 15
  140.      'hr16',       '-1', # accesses in hour 16
  141.      'hr17',       '-1', # accesses in hour 17
  142.      'hr18',       '-1', # accesses in hour 18
  143.      'hr19',       '-1', # accesses in hour 19
  144.      'hr20',       '-1', # accesses in hour 20
  145.      'hr21',       '-1', # accesses in hour 21
  146.      'hr22',       '-1', # accesses in hour 22
  147.      'hr23',       '-1', # accesses in hour 23
  148.      'maxhouraccess',  '0', # maximum accesses per hour
  149.      'minhouraccess',  '0', # minimum accesses per hour
  150.      );
  151.  
  152. local($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst);
  153. local($startTime);
  154. local(@mnths, @longmonths);
  155.  
  156. $version = "1.32"; # Do not touch this line, even if you hack at the code!
  157.  
  158. ##############################################################################
  159.  
  160. &Main;
  161.  
  162. #-----------------------------------------------------------------------------#
  163. #  AccessWatch function - Main
  164. #    Purpose  : Coordinates everything else...
  165. #-----------------------------------------------------------------------------#
  166. sub Main {
  167.     $startTime = time;
  168.     #$currdate = &SetDateInfo; # returns Day/Mon/Year
  169.     $currdate = $accessDate; # returns Day/Mon/Year
  170.  
  171.     print "AccessWatch v$version for date $currdate starting.\n" if $verbose;
  172.     print "log file is $accessLog\n" ;
  173.     &ProcessLog;
  174.     &PrepareSummaryPage;
  175.     &PrepareHostDetailsPage;
  176.     print "Finished - Output is in $summarylink.\n" if $verbose;
  177.     exit 0;
  178. }
  179.  
  180. #-----------------------------------------------------------------------------#
  181. #  AccessWatch function - ProcessLog
  182. #    Purpose  : Scans through access log and picks out the appropriate accesses
  183. #-----------------------------------------------------------------------------#
  184. sub ProcessLog {
  185.     
  186.     $| = 1; print "Parsing access log..." if $verbose; $| = 0;
  187.     
  188.     local($remote, $dash1, $dash2, $date, $tz, 
  189.       $method, $page, $protocol, $protnum1, $size);
  190.  
  191.     open (LOG, "<$accessLog") || die "Couldn't open $accessLog\n";
  192.     
  193.     &FastSearch;          # position pointer at start of day using a fast search
  194.  
  195.     while (<LOG>) {        
  196.       # start at the current date and push all access relevant info into lists
  197.     if ($verbose && $stat{'serverCount'} % 50 == 1) {
  198.         $| = 1;
  199.         print ".";
  200.         $| = 0;
  201.     }
  202.     if (/$currdate/i) {
  203.         chomp;
  204.         # Un-Webify plus signs and %-encoding
  205.         tr/+/ /;
  206.         tr/ //s;
  207.         s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
  208.         $stat{'serverCount'}++;
  209.  
  210.         if (/$includeURL/i && (! /$excludeURL/i || $excludeURL eq "")) {
  211.         ($remote, $dash1, $dash2, $date, $tz, 
  212.          $method, $page, $protocol, $protnum1, $size)
  213.             = split(/ /);
  214.         $page =~ s/(.*)\?.*/$1/;
  215.         $date =~ s/\[//;
  216.         local($date, $hour, $min, $sec) = split(":", $date);
  217.  
  218.         $stat{'hits'}++;
  219.         $stat{'size'} += $size/1000;
  220.  
  221.         if ($protnum1 < 400 && !($protnum1 eq "302")) {
  222.             &RecordStats($hour, $min, $sec, $remote, $page);
  223.         }
  224.         else { 
  225.             if ($protnum1 eq "302") { $stat{'redirect'}++; }
  226.             else { $stat{'errors'}++; }
  227.         }
  228.         }                
  229.         elsif (/$includeURL/i) {
  230.         $stat{'hits'}++;
  231.         ($remote, $dash1, $dash2, $date, $tz, 
  232.          $method, $page, $protocol, $protnum1, $size)
  233.             = split(/ /);
  234.         $stat{'size'} += $size/1000 if ($size =~ /^\d.*/);
  235.         }
  236.     }
  237.     }                
  238.     close (LOG);
  239.     print " done.\n" if $verbose;
  240. }
  241.  
  242. #-----------------------------------------------------------------------------#
  243. #  AccessWatch function - SetDateInfo
  244. #    Purpose  : Sets global date variables, returns Day/Month/Year as specified
  245. #                by log standards.
  246. #-----------------------------------------------------------------------------#
  247. sub SetDateInfo {
  248.     #get current date and return as string (day/month/year)...
  249.     @mnths = ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 
  250.           'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
  251.     @longmonths = ('January', 'February', 'March', 'April', 'May', 
  252.            'June', 'July', 'August', 'September', 'October', 
  253.            'November', 'December');
  254.     ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  255.     $year = "19$year";
  256.     $mday = "0$mday" if ($mday < 10);
  257.  
  258.     return "$mday/$mnths[$mon]/$year";
  259. }
  260.  
  261. #-----------------------------------------------------------------------------#
  262. #  AccessWatch function - PrintSummaryPage
  263. #    Purpose  : Coordinates construction of summary interface.
  264. #-----------------------------------------------------------------------------#
  265. sub PrintSummaryPage {
  266.  
  267.     &UpdateStatArray;
  268.  
  269.     if ($stat{'accesses'} eq "0") { 
  270.     print OUT <<EOM;
  271. <CENTER><H2>No accesses have been made to $siteName.</H2></CENTER>
  272. EOM
  273.     return; 
  274.     }
  275.  
  276.     &PrintStatsParagraph;
  277.  
  278.     print OUT <<EOM;
  279. <CENTER>
  280. EOM
  281.     &PrintTableSummaryStats;
  282.     &PrintTableHourlyStats;  # Added with much help from Paul Blackman
  283.     &PrintTablePageStats;
  284.     &PrintTableDomainStats;
  285.     &PrintTableHostStats;
  286.  
  287. print OUT <<EOM;
  288. </CENTER>
  289. <P>
  290. EOM
  291.  
  292. }
  293.  
  294. #-----------------------------------------------------------------------------#
  295. #  AccessWatch function - FastSearch
  296. #    Purpose  : Scans quickly from the bottom of the access log to start
  297. #                   of the current day.
  298. #-----------------------------------------------------------------------------#
  299. sub FastSearch {
  300.     # parses through access log from the bottom up for speed, searching
  301.     #  for the start of the current day...
  302.     #local($avgday) = 10000 * $hour + 1000;
  303.     local($avgday) = 10000 * 24 + 1000;
  304.     local($logsize) = (-s LOG);
  305.     local($logoffset) = 0;
  306.     local($jumps) = 0;
  307.  
  308.     $logoffset = $logsize - $avgday if ($logsize > $avgday);
  309.  
  310.     #print "avgday=$avgday logsize=$logsize logoffset=$logoffset hour=$hour\n" ;
  311.  
  312.     seek (LOG, $logoffset, 0);
  313.     <LOG>;
  314.     $_=<LOG>;
  315.     while (/$currdate/i && $logoffset > 0 && <LOG>) {
  316.     $jumps++;
  317.     # print "$_\n";
  318.     $logoffset = $logoffset - 5000;
  319.     $logoffset = 0 if ($logoffset <= 0);
  320.     seek (LOG, $logoffset, 0);
  321.     <LOG>;
  322.     $_=<LOG>;
  323.     }
  324.     # print "***Jumps = $jumps***\n";
  325. }
  326.  
  327. #-----------------------------------------------------------------------------#
  328. #  AccessWatch function - PrepareSummaryPage
  329. #    Purpose  : Opens summary file, calls functions to write data, closes, and 
  330. #                   sets the appropriate permissions.
  331. #-----------------------------------------------------------------------------#
  332. sub PrepareSummaryPage {
  333.     $| = 1; print "Preparing Summary... " if $verbose; $| = 0;
  334.     open (OUT, ">$summaryfile") || die "Couldn't open $summaryfile\n";
  335.  
  336.     &PrintHeader;
  337.     &PrintSummaryPage;
  338.     &PrintFooter;
  339.     close (OUT);
  340.     chmod (0644, $summaryfile);
  341.     print "done.\n" if $verbose;
  342. }    
  343.  
  344. #-----------------------------------------------------------------------------#
  345. #  AccessWatch function - PrepareHostDetailsPage
  346. #    Purpose  : Opens host details file, calls functions to write data, closes,
  347. #                   and sets the appropriate permissions.
  348. #-----------------------------------------------------------------------------#
  349. sub PrepareHostDetailsPage {
  350.     if ($details) {
  351.     open (OUT, ">$detailsfile") || die "No $detailsfile\n";
  352.     &PrintHeader;
  353.     &PrintHostDetailsList;
  354.     &PrintFooter;
  355.     close (OUT);
  356.     chmod 0644, $detailsfile;
  357.     }
  358. }
  359.  
  360. #-----------------------------------------------------------------------------#
  361. #  AccessWatch function - RecordStats
  362. #    Purpose  : Takes a single access as input, and updates the appropriate
  363. #                   counters and arrays.
  364. #-----------------------------------------------------------------------------#
  365. sub RecordStats {
  366.     #tally server information, such as domain extensions, total accesses,
  367.     # and page information
  368.     
  369.     local($hour, $minute, $second, $remote, $page) = @_;
  370.     if ($remote !~ /\./) { $remote .= ".$orgdomain"; }
  371.       #takes care of those internal accesses that do not get fully 
  372.       # qualified in the log name -> name.orgname.ext
  373.     local($domainExt) = &GetDomainExtension($remote, 1);
  374.  
  375.     $stat{'accesses'}++;    
  376.     $domains{$domainExt}++;
  377.     $hosts{$remote}++;
  378.     $pages{$page}++;
  379.     $stat{"hr".$hour}++;
  380.  
  381.     push (@accesses, "$hour $min $sec $remote $page");
  382.  
  383. }
  384.  
  385. #-----------------------------------------------------------------------------#
  386. #  AccessWatch function - GetDomainExtension
  387. #    Purpose  : Takes a hostname as input, and returns the domain suffix. If
  388. #                   second argument is set to true, then it counts accesses
  389. #                   from the local domain.
  390. #-----------------------------------------------------------------------------#
  391. sub GetDomainExtension {
  392.     local($domainExt) = $_[0];
  393.     local($shouldCount) = $_[1];
  394.     
  395.     $stat{'localCount'}++ if ($domainExt =~ /.*$orgdomain/ && $shouldCount);
  396.     $domainExt =~ s/.*\.//g;
  397.     $domainExt = "ip address" if ($domainExt =~ /[0-9].*/);
  398.     $domainExt =~ tr/[A-Z]/[a-z]/;
  399.  
  400.     return $domainExt;
  401.  
  402. }
  403.  
  404. #-----------------------------------------------------------------------------#
  405. #  AccessWatch function - DescribeDomain
  406. #    Purpose  : Takes a domain extension as a parameter, and returns a detailed
  407. #                   description as specified in the domain descriptions file 
  408. #                   provided. Caches file into memory if used more than once.
  409. #-----------------------------------------------------------------------------#
  410. sub DescribeDomain {
  411.  
  412.     local($description) = "Unknown"; # Default domain description
  413.     local($domain) = $_[0];          # Domain extension (passed parameter)
  414.  
  415.     if ($domain ne "ip address") {
  416.     if (!(keys %domainDesc)) {
  417.         open (CODES, "<$domaincodes") ||
  418.         die "Couldn't open $domaincodes\n";
  419.         while (<CODES>) {
  420.             chomp;
  421.             chop;
  422.             ($code, $description) = split('   ');
  423.             $code =~ tr/[A-Z]/[a-z]/;
  424.             $domainDesc{$code} = $description;
  425.         }    
  426.         close(CODES);
  427.     }
  428.     if ($domainDesc{$domain}) {
  429.         $description = $domainDesc{$domain}; 
  430.     }
  431.     }
  432.     return $description;
  433. }                
  434.  
  435. #-----------------------------------------------------------------------------#
  436. #  AccessWatch function - DescribePage
  437. #    Purpose  : Takes a virtual URL as a parameter, and returns a detailed
  438. #                   description as specified in the page descriptions file 
  439. #                   provided. Caches file into memory if used more than once.
  440. #-----------------------------------------------------------------------------#
  441. sub DescribePage {
  442.  
  443.     local($url) = $_[0];
  444.     local($description) = $url;
  445.  
  446.     if (!(keys %pageDesc)) {
  447.     open (DESC, "<$pagedescriptions") || 
  448.         die "Couldn't open $pagedescriptions...";
  449.     while (<DESC>) { 
  450.         chomp;
  451.         /(\S+)\s+\"(.*)\"/;
  452.         $pageDesc{$1} = $2;
  453.     }
  454.     close(DESC);
  455.     }
  456.     if ($pageDesc{$url}) {
  457.     $description = $pageDesc{$url};
  458.     }
  459.  
  460.     if ($truncate && length($url) > $toolong && $description eq $url) {
  461.         $description = reverse $url;
  462.     while (length($description) > $toolong) { chop $description; }
  463.     $description = "..." . reverse $description;
  464.     }
  465.     return $description;
  466. }                
  467.  
  468. #-----------------------------------------------------------------------------#
  469. #  AccessWatch sort routine - byDomain
  470. #    Purpose  : Sort subroutine for sorting an array by domain suffix.
  471. #-----------------------------------------------------------------------------#
  472. sub byDomain { 
  473.     local($aHost) = "";
  474.     local($bHost) = "";
  475.     local(@aTemp, @bTemp) = ();
  476.     if ($a =~ /[^0-9].*\.[^0-9].*/) { 
  477.     @aTemp = reverse split(/\./, $a); 
  478.     foreach (@aTemp) { $aHost .= $_ };
  479.     }
  480.     else {
  481.     $aHost = "zzzzzzz".$a;
  482.     }
  483.     if ($b =~ /[^0-9].*\.[^0-9].*/) { 
  484.     @bTemp = reverse split(/\./, $b);
  485.     foreach (@bTemp) { $bHost .= $_ };
  486.     }
  487.     else {
  488.     $bHost = "zzzzzzz".$b;
  489.     }
  490.     return ($aHost cmp $bHost);
  491. }
  492.  
  493. #-----------------------------------------------------------------------------#
  494. #  AccessWatch function - PrintHostDetailsList
  495. #    Purpose  : Prints list of all accesses on server - date and page, sorted
  496. #                   remote host.
  497. #-----------------------------------------------------------------------------#
  498. sub PrintHostDetailsList {
  499.  
  500.     local(%hostlist) = ();
  501.     local($bdelim) = "s$;";    
  502.     local($edelim) = "e$;";
  503.     local($pdelim) = "p$;";
  504.  
  505.     print OUT <<EOM;
  506. <H1>Access Details</H1>
  507. <DL>
  508. EOM
  509.  
  510.     foreach $entry (@accesses) { 
  511.     local($hour, $minute, $second, $remote, $page) = split(" ", $entry);
  512.     local($timestring) = $hour.":".$minute.":".$second;
  513.     if ($hostlist{$remote}) {
  514.         $hostlist{$remote} = 
  515.         $hostlist{$remote}.$bdelim.$timestring.$pdelim.$page.$edelim;
  516.     }
  517.     else {
  518.         $hostlist{$remote} = 
  519.         $bdelim.$timestring.$pdelim.$page.$edelim;
  520.     }
  521.     }
  522.     
  523.     local(@hosts) = sort byDomain (keys %hostlist);
  524.  
  525.     local($domainExt) = "";    
  526.     local($prevdomainExt) = "###";    
  527.     local($domainDesc) = "";    
  528.  
  529.     foreach $host (@hosts) {
  530.     $domainExt = &GetDomainExtension($host, 0);
  531.     if ($domainExt ne $prevdomainExt) {
  532.         $domainDesc = &DescribeDomain($domainExt);
  533.         $prevdomainExt = $domainExt;
  534.         print OUT "</DL>\n<H3>$domainDesc<HR></H3>\n<DL>\n"
  535.     }
  536.     local($entry) = $hostlist{$host};
  537.     $entry =~ s/$bdelim/<DD>/g;
  538.     $entry =~ s/$pdelim/ /g;
  539.     $entry =~ s/$edelim/\n/g;
  540.     
  541.     print OUT "<DT><B>$host</B>\n";
  542.     print OUT "$entry";
  543.     }               
  544.     print OUT <<EOM;
  545. </DL>
  546. <P>
  547. EOM
  548.  
  549. }    
  550.  
  551. sub byReverseNumber { $b <=> $a; }
  552.  
  553. #-----------------------------------------------------------------------------#
  554. #  AccessWatch function - PrintStatsParagraph
  555. #    Purpose  : Prints nice summary of crucial information
  556. #-----------------------------------------------------------------------------#
  557. sub PrintStatsParagraph {
  558.     #prints summary of gathered access statistics, with graphical 
  559.     # representation of percentage of hits according to domain
  560.  
  561.     print OUT "<H2>Daily Access Statistics";
  562.     print OUT "<HR SIZE=3 WIDTH=40% ALIGN=LEFT></H2>\n";
  563.  
  564.     print OUT <<EOM;
  565. On $currdate, there have been a total of <B>$stat{'accesses'}</B>
  566. accesses by <B>$stat{'uniqueHosts'}</B> unique hosts viewing an average of <B>$stat{'hostPageAverage'}</B> pages related to <B><I>$siteName.</I></B>
  567. EOM
  568.  
  569.     print OUT "Of these, ";
  570.     printf OUT ("<B>$stat{'localCount'} (%.3g%%)</B>", $stat{'localPercent'});
  571.     print OUT " have been from $orgname, and ";
  572.     printf OUT ("<B>%d (%.3g%%)</B>", $stat{'outsideCount'}, 
  573.         $stat{'outsidePercent'});
  574.  
  575. print OUT <<EOM;
  576.  have been from outside hosts.<BR>
  577. There have been a total of <B>$stat{'hits'}</B> hits and <B>$stat{'errors'}</B> errors related 
  578. to <B><I>$siteName</I></B>, accounting for 
  579. EOM
  580.     printf OUT ("<B>%.3g%%</B> of total server hits and consisting of ", $stat{'serverLoad'});
  581.  
  582.     printf OUT ("<B>%d</B> kilobytes of information. ", $stat{'size'});
  583.  
  584.     # printf OUT ("There have been <B>%3.1f</B>", $stat{'accessesPerHour'});
  585.     # print OUT " accesses per hour, and at this rate, <B><I>$siteName</I></B> will get ";
  586.     # printf OUT ("<B>%d</B>", $stat{'accessesPerDay'});
  587.     # print OUT " accesses today.<P>\n";
  588.     print OUT "<P>\n";
  589.  
  590. }
  591.  
  592. #-----------------------------------------------------------------------------#
  593. #  AccessWatch function - UpdateStatArray
  594. #    Purpose  : Computes statistics based on accumulated counters.
  595. #-----------------------------------------------------------------------------#
  596. sub UpdateStatArray {    
  597.  
  598.     # variable descriptions and computations
  599.      # $stat{'count'} = absolute number of accesses
  600.      # $stat{'hits'} = number of page related hits on server
  601.      # $stat{'servercount'} =total  number of hits on server
  602.      # $siteName = description of page
  603.      # $serverload - % of server hits related to page
  604.      # $stat{'localcount'} - number of accesses from within organization
  605.      # $outside - number of accesses from outside hosts
  606.      # $pctlocal - % of accesses from within organization
  607.  
  608.     $stat{'serverLoad'} = 0;
  609.     $stat{'localPercent'} = 0;
  610.     $stat{'outsidePercent'} = 0;
  611.     $stat{'outsideCount'} = $stat{'accesses'} - $stat{'localCount'};
  612.     $stat{'accessesPerHour'} = 0;
  613.  
  614.     $stat{'serverLoad'} =  $stat{'hits'} / $stat{'serverCount'} * 100 
  615.     if ($stat{'serverCount'} > 0);
  616.     $stat{'localPercent'} = $stat{'localCount'} / $stat{'accesses'} * 100 
  617.     if ($stat{'accesses'} > 0);
  618.     $stat{'outsidePercent'} = $stat{'outsideCount'} / $stat{'accesses'} * 100 
  619.     if ($stat{'accesses'} > 0);
  620. $hour = 24;
  621. $min = 0;
  622.     $stat{'accessesPerHour'} = ($stat{'accesses'} / (($hour * 60) + $min)) * 60
  623.     if ($hour * 60 + $min > 0);
  624.  
  625.     $stat{'accessesPerDay'} = $stat{'accessesPerHour'} * 24;
  626.     $stat{'uniqueHosts'} = keys %hosts;
  627.     
  628.     $stat{'hostPageAverage'} = 
  629.     sprintf("%3.1f", $stat{'accesses'}/$stat{'uniqueHosts'})
  630.         if ($stat{'uniqueHosts'} != 0);
  631.  
  632.     $stat{'accessesPerHour'} = sprintf("%3.1f", $stat{'accessesPerHour'});
  633.     $stat{'accessesPerDay'} = sprintf("%d", $stat{'accessesPerDay'});
  634.  
  635.     $stat{'maxhouraccess'} = 0;
  636.     $stat{'minhouraccess'} = 0;
  637.  
  638.     foreach $hournum ('00'..'23') {
  639.     $stat{'maxhouraccess'} = $stat{"hr".$hournum}
  640.          if ($stat{"hr".$hournum} > $stat{'maxhouraccess'});        
  641.     $stat{'minhouraccess'} = $stat{"hr".$hournum}
  642.          if (($stat{'minhouraccess'} == 0 ||
  643.           $stat{"hr".$hournum} < $stat{'minhouraccess'}) && 
  644.          $stat{"hr".$hournum} != -1);        
  645.     }
  646. }
  647.  
  648. #-----------------------------------------------------------------------------#
  649. #  AccessWatch function - PrintTableDomainStats
  650. #    Purpose  : Prints table of domains, sorted by number of accesses.
  651. #-----------------------------------------------------------------------------#
  652. sub PrintTableDomainStats {
  653.  
  654.     return if ($maxDomainsToList == 0);
  655.  
  656.     print OUT <<EOM;
  657. <TABLE BORDER=1 WIDTH=100%>
  658. <TR><TH COLSPAN=5><HR SIZE=5>Accesses by Domain
  659. <HR SIZE=5></TH></TR>
  660. <TR><TH>Domain </TH><TH>Description </TH>
  661. <TH>Count </TH><TH>% of total</TH></TR>
  662. EOM
  663.  
  664.     local(@countOrderList) = sort byReverseNumber values %domains;
  665.     local(@domainOrder) = ();
  666.  
  667.     local($domainCount) = $maxDomainsToList - 1;
  668.     $domainCount = $#countOrderList 
  669.     if ($maxDomainsToList == -1 || 
  670.         ($maxDomainsToList - 1) > $#countOrderList);
  671.  
  672.     while (@countOrderList) {
  673.     while (local($tag, $value) = (each %domains)) {
  674.         if ($countOrderList[0] == $value) {
  675.         push (@domainOrder, $tag);
  676.         shift @countOrderList;
  677.         }
  678.     }
  679.     }
  680.  
  681.     local(@favDomains) = @domainOrder[0..$domainCount];
  682.     local(@othDomains) = @domainOrder[@favDomains..$#domainOrder];
  683.  
  684.     foreach (@favDomains) {
  685.     local($Mdomain) = $_;
  686.     local($Mcount) = $domains{$_};
  687.  
  688.     $Mdomain =~ tr/[A-Z]/[a-z]/;
  689.  
  690.  
  691.     print OUT "<TR><TD><DT>$Mdomain</A> </TD>";
  692.     local($description) = &DescribeDomain($Mdomain);
  693.     print OUT "<TD>$description </TD>";
  694.     print OUT "<TD ALIGN=RIGHT>$Mcount </TD>";
  695.  
  696.     $pct = 0.00;
  697.     $pct = $Mcount / $stat{'accesses'} * 100 if ($stat{'accesses'} > 0);
  698.  
  699.     printf OUT ("<TD ALIGN=RIGHT> %3.2f</TD>\n", $pct);
  700.         print OUT "<TD ALIGN=LEFT>";
  701.     &PrintBarHoriz($pct,0);
  702.         print OUT "</TD></TR>\n";
  703.     }
  704.  
  705.     print OUT "<TR><TD COLSPAN=5><B>Also, hosts from the following domains visited:</B> " if (@othDomains);
  706.  
  707.     foreach (@othDomains) {
  708.     tr/[A-Z]/[a-z]/;
  709.     local($description) = &DescribeDomain($_);
  710.     if (@othDomains) {
  711.         print OUT "$description ($domains{$_}), ";
  712.     }
  713.     else {
  714.         print OUT "and $description ($domains{$_}).";
  715.     }
  716.     }
  717.     print OUT "</TD></TR>\n</TABLE><P>\n";
  718. }
  719.  
  720. #-----------------------------------------------------------------------------#
  721. #  AccessWatch function - PrintTableHostStats
  722. #    Purpose  : Prints table of hosts, sorted by number of accesses.
  723. #-----------------------------------------------------------------------------#
  724. sub PrintTableHostStats {
  725.  
  726.     return if ($maxHostsToList == 0);
  727.  
  728.     print OUT <<EOM;
  729. <TABLE BORDER=1 WIDTH=100%>
  730. <TR><TH COLSPAN=4><HR SIZE=5>Most Frequent Accesses by Host<HR SIZE=5></TH></TR>
  731. <TR><TH>Host </TH><TH>Count </TH><TH>% of total</TH></TR>
  732. EOM
  733.     
  734.     local(@countOrderList) = sort byReverseNumber values %hosts;
  735.     local(@hostOrder) = ();
  736.  
  737.     local($hostCount) = $maxHostsToList - 1;
  738.     $hostCount = $#countOrderList 
  739.     if ($maxHostsToList == -1 || 
  740.         ($maxHostsToList - 1) > $#countOrderList);
  741.  
  742.     while (@countOrderList) {
  743.     while (local($tag, $value) = (each %hosts)) {
  744.         if ($countOrderList[0] == $value) {
  745.         push (@hostOrder, $tag);
  746.         shift @countOrderList;
  747.         }
  748.     }
  749.     }
  750.  
  751.     local(@favHosts) = @hostOrder[0..$hostCount];
  752.  
  753.     foreach (@favHosts) {
  754.     local($Mhost) = $_;
  755.     local($Mcount) = $hosts{$_};
  756.  
  757.     print OUT "<TR><TD><DT>$Mhost</A> </TD>";
  758.     print OUT "<TD ALIGN=RIGHT>$Mcount </TD>";
  759.  
  760.     $pct = 0.00;
  761.     $pct = $Mcount / $stat{'accesses'} * 100 if ($stat{'accesses'} > 0);
  762.  
  763.     printf OUT ("<TD ALIGN=RIGHT> %3.2f</TD>\n", $pct);
  764.         print OUT "<TD ALIGN=LEFT>";
  765.     &PrintBarHoriz($pct,0);
  766.         print OUT "</TD></TR>\n";
  767.     }
  768.     print OUT <<EOM if ($details && $stat{'accesses'} ne "0");
  769. <TR><TD COLSPAN=4><DT><B>Access Details:</B> <I>A <A HREF="$detailslink">list</A> of individual accesses, sorted by host</I></TD></TR>
  770. EOM
  771.     print OUT "</TABLE><P>\n";
  772. }
  773.  
  774. #-----------------------------------------------------------------------------#
  775. #  AccessWatch function - PrintTablePageStats
  776. #    Purpose  : Prints table of pages, sorted by number of accesses.
  777. #-----------------------------------------------------------------------------#
  778. sub PrintTablePageStats {
  779.     # outputs a table of pages accessed, ranked in order of demand
  780.     
  781.     return if ($maxPagesToList == 0);
  782.  
  783.     print OUT <<EOM;
  784. <TABLE BORDER=1 WIDTH=100%>
  785. <TR><TH COLSPAN=5><HR SIZE=5>Page Demand<HR SIZE=5></TH></TR>
  786. <TR><TD ALIGN=CENTER COLSPAN=5>Of the <B>$stat{'uniqueHosts'}</B> hosts that visited today, each traversed an average of <B>$stat{'hostPageAverage'}</B> pages.</TD></TR>
  787. <TR><TH COLSPAN=2>Page Location </TH><TH>Accesses </TH><TH>\% of total</TH></TR>
  788. EOM
  789.  
  790.     local(@countOrderList) = sort byReverseNumber values %pages;
  791.     local(@pageOrder) = ();
  792.  
  793.     local($pageCount) = $maxPagesToList - 1;
  794.     $pageCount = $#countOrderList if ($maxPagesToList == -1 || 
  795.                      ($maxPagesToList - 1) > $#countOrderList);
  796.  
  797.     while (@countOrderList) {    
  798.     while (local($tag, $value) = (each %pages)) {
  799.         if ($countOrderList[0] == $value) {
  800.         push (@pageOrder, $tag);
  801.         shift @countOrderList;
  802.         }
  803.     }
  804.     }
  805.  
  806.     local(@favPages) = @pageOrder[0..$pageCount];
  807.  
  808.     foreach (@favPages) {
  809.     local($Mpage) = $_;
  810.     local($Mcount) = $pages{$_};
  811.  
  812.     local($pct) = 0.00;
  813.     $pct = $Mcount / $stat{'accesses'} * 100 if ($stat{'accesses'} > 0);
  814.  
  815.     print OUT "<TR><TD COLSPAN=2><DT><A HREF=\"$Mpage\">";
  816.  
  817.     local($description) = &DescribePage($Mpage);
  818.  
  819.     print OUT "$description </A></TD>";
  820.     
  821.     print OUT "<TD ALIGN=RIGHT>$Mcount </TD>\n";
  822.     printf OUT ("<TD ALIGN=RIGHT> %3.2f</TD>\n", $pct);
  823.         print OUT "<TD ALIGN=LEFT>";
  824.     &PrintBarHoriz($pct,0);
  825.         print OUT "</TD></TR>\n";
  826.     }
  827.     print OUT "</TABLE><P>\n";
  828. }
  829.  
  830. #-----------------------------------------------------------------------------#
  831. #  AccessWatch function - PrintTableHourlyStats
  832. #    Purpose  : Prints bar graph of accesses over the course of the current
  833. #                   day. Thanks very much to Paul Blackman for his work on
  834. #                   this function. 
  835. #-----------------------------------------------------------------------------#
  836. sub PrintTableHourlyStats {
  837.  
  838. local($hourBar) = "img/hourbar.gif";
  839. local($hour, $pct);
  840.  
  841.     print OUT <<EOM;
  842. <TABLE BORDER=1 WIDTH=100%>
  843. <TR><TH COLSPAN=3><HR SIZE=5>Hourly Statistics<HR SIZE=5></TH></TR>
  844. <TR>
  845. EOM
  846.     print OUT "<TD ROWSPAN=11>";
  847.     foreach $hour ('00'..'23') {
  848.     if ($stat{'hr'.$hour} > 0.9*$stat{'maxhouraccess'}) {
  849.         &PrintBarVert($stat{'hr'.$hour}, 9);
  850.     }
  851.     elsif ($stat{'hr'.$hour} > 0.8*$stat{'maxhouraccess'}) {
  852.         &PrintBarVert($stat{'hr'.$hour}, 8);
  853.     }
  854.     elsif ($stat{'hr'.$hour} > 0.7*$stat{'maxhouraccess'}) {
  855.         &PrintBarVert($stat{'hr'.$hour}, 7);
  856.     }
  857.     elsif ($stat{'hr'.$hour} > 0.6*$stat{'maxhouraccess'}) {
  858.         &PrintBarVert($stat{'hr'.$hour}, 6);
  859.     }
  860.     elsif ($stat{'hr'.$hour} > 0.5*$stat{'maxhouraccess'}) {
  861.         &PrintBarVert($stat{'hr'.$hour}, 5);
  862.     }
  863.     elsif ($stat{'hr'.$hour} > 0.4*$stat{'maxhouraccess'}) {
  864.         &PrintBarVert($stat{'hr'.$hour}, 4);
  865.     }
  866.     elsif ($stat{'hr'.$hour} > 0.3*$stat{'maxhouraccess'}) {
  867.         &PrintBarVert($stat{'hr'.$hour}, 3);
  868.     }
  869.     elsif ($stat{'hr'.$hour} > 0.2*$stat{'maxhouraccess'}) {
  870.         &PrintBarVert($stat{'hr'.$hour}, 2);
  871.     }
  872.     elsif ($stat{'hr'.$hour} > 0.1*$stat{'maxhouraccess'}) {
  873.         &PrintBarVert($stat{'hr'.$hour}, 1);
  874.     }
  875.     elsif ($stat{'hr'.$hour} > 0) {
  876.         &PrintBarVert($stat{'hr'.$hour}, 0); 
  877.     }
  878.     else { 
  879.         &PrintBarVert(1, -1, $hour); 
  880.     }
  881.     }
  882.  
  883.     print OUT <<EOM;
  884. <BR>
  885. <IMG SRC="$hourBar" WIDTH=288 HEIGHT=22 BORDER=0 HSPACE=0 VSPACE=0 ALT="">
  886. </TD>
  887. <TD COLSPAN=2><TABLE BORDER=1 WIDTH=100%>
  888. <TR><TH ALIGN=RIGHT>Avg Accesses/Hour</TH><TD ALIGN=RIGHT>$stat{'accessesPerHour'}</TD></TR>
  889. <TR><TH ALIGN=RIGHT>Max Accesses/Hour</TH><TD ALIGN=RIGHT>$stat{'maxhouraccess'}</TD></TR>
  890. <TR><TH ALIGN=RIGHT>Min Accesses/Hour</TH><TD ALIGN=RIGHT>$stat{'minhouraccess'}</TD></TR>
  891. <TR><TH ALIGN=RIGHT>Accesses/Day</TH><TD ALIGN=RIGHT>$stat{'accessesPerDay'}</TD></TR>
  892. </TABLE></TD></TR>
  893. EOM
  894.  
  895.     foreach $pct (0..9) {
  896.     $img = 9 - $pct;
  897.     print OUT "<TR><TD ALIGN=LEFT><IMG SRC=\"$vertbar{$img}\" HEIGHT=8 WIDTH=10 BORDER=1 ALT=\"\"> > ";
  898.     printf OUT ("%d%%</TD>", (9 - $pct)*10);
  899.     printf OUT ("<TD ALIGN=RIGHT>%d accesses</TD></TR>\n", (1 - $pct/10) * $stat{'maxhouraccess'});
  900.     }
  901.  
  902.     print OUT <<EOM;
  903. </TABLE><P>
  904. EOM
  905.  
  906. }
  907.  
  908. #-----------------------------------------------------------------------------#
  909. #  AccessWatch function - PrintBarVert
  910. #    Purpose  : Prints a vertical bar with height as specified by argument.
  911. #-----------------------------------------------------------------------------#
  912. sub PrintBarVert {
  913.     local($pct) = $_[0];
  914.     local($colorbar) = $vertbar{$_[1]};
  915.  
  916.     local($scale) = 0;
  917.     $scale = $pct/$stat{'maxhouraccess'} * 200 if ($stat{'maxhouraccess'});
  918.  
  919.     print OUT "<IMG SRC=\"$colorbar\" ";
  920.     printf OUT ("HEIGHT=%d WIDTH=10 BORDER=1 ALT=\"\">", $scale);
  921. }
  922.  
  923. #-----------------------------------------------------------------------------#
  924. #  AccessWatch function - PrintBarHoriz
  925. #    Purpose  : Prints a horizontal bar with width as specified by argument.
  926. #-----------------------------------------------------------------------------#
  927. sub PrintBarHoriz {
  928.     local($pct) = $_[0];
  929.     local($colorbar) = $horizbar{$_[1]};
  930.     local($scale) = 1;
  931.  
  932.     $scale = ($pct*8)/log $pct + 1 if ($pct > 0);
  933.     print OUT "<IMG SRC=\"$colorbar\" ALT=\"";
  934.     print OUT "*" x ($pct/3 + 1) . "\" ";
  935.     printf OUT ("HEIGHT=15 WIDTH=%d BORDER=1>", $scale);
  936. }
  937.  
  938. #-----------------------------------------------------------------------------#
  939. #  AccessWatch function - PrintTableSummaryStats
  940. #    Purpose  : Prints a table which contains general statistics.
  941. #-----------------------------------------------------------------------------#
  942. sub PrintTableSummaryStats {
  943.  
  944.     print OUT <<EOM;
  945. <TABLE BORDER=1 WIDTH=100%>
  946. <TR><TH COLSPAN=4><HR SIZE=5>Summary Statistics<HR SIZE=5></TH></TR>
  947. <TR><TH> </TH><TH>Count</TH><TH>% of total</TH><TH> </TH></TR>
  948. <TR><TH ALIGN=RIGHT><DT>Accesses from $orgname </TH>
  949. <TD ALIGN=RIGHT>$stat{'localCount'} </TD>
  950. EOM
  951.  
  952.     printf OUT ("<TD ALIGN=RIGHT>%.3g%%</TD>", $stat{'localPercent'});
  953.     print OUT "<TD ALIGN=LEFT>";
  954.     &PrintBarHoriz($stat{'localPercent'}/2,0);
  955.     print OUT "</TD>";
  956.     print OUT <<EOM;
  957. </TR>
  958. <TR><TH ALIGN=RIGHT><DT>Outside Accesses </TH>
  959. <TD ALIGN=RIGHT>$stat{'outsideCount'} </TD>
  960. EOM
  961.  
  962.     printf OUT ("<TD ALIGN=RIGHT>%.3g%%</TD>", $stat{'outsidePercent'});
  963.     print OUT "<TD ALIGN=LEFT>";
  964.     &PrintBarHoriz($stat{'outsidePercent'}/2,0);
  965.     print OUT "</TD>";
  966.     print OUT <<EOM;
  967. </TR>
  968. <TR><TH ALIGN=RIGHT><DT>Total Page Accesses</TH>
  969. <TD ALIGN=RIGHT>$stat{'accesses'} </TD><TD ALIGN=RIGHT>100%</TD>
  970. EOM
  971.     print OUT "<TD ALIGN=LEFT>";
  972.     &PrintBarHoriz(50,1);
  973.     print OUT "</TD>";
  974.  
  975. print OUT <<EOM;
  976. </TR>
  977. <TR><TD COLSPAN=4> </TD></TR>
  978. <TR><TH ALIGN=RIGHT><DT>Total hits related to page </TH>
  979. <TD ALIGN=RIGHT>$stat{'hits'} </TD>
  980. EOM
  981.  
  982.     printf OUT ("<TD ALIGN=RIGHT>%.3g%%</TD>", $stat{'serverLoad'});
  983.     print OUT "<TD ALIGN=LEFT>";
  984.     &PrintBarHoriz($stat{'serverLoad'}/2,0);
  985.     print OUT "</TD>";
  986.     print OUT <<EOM;
  987. </TR>
  988. <TR><TH ALIGN=RIGHT><DT>Total hits on server </TH>
  989. <TD ALIGN=RIGHT>$stat{'serverCount'} </TD>
  990. <TD ALIGN=RIGHT>100%</TD>
  991. EOM
  992.     print OUT "<TD ALIGN=LEFT>";
  993.     &PrintBarHoriz(50,1);
  994.     print OUT "</TD>";
  995.     print OUT <<EOM;
  996. </TR>
  997. </TABLE><P>
  998. EOM
  999.  
  1000. }
  1001.  
  1002. #-----------------------------------------------------------------------------#
  1003. #  AccessWatch function - PrintHeader 
  1004. #    Purpose  : Creates HTML header for page and sends it to OUT.
  1005. #-----------------------------------------------------------------------------#
  1006. sub PrintHeader {
  1007.     # *** Do not modify or remove the call to this function. ***
  1008.     # Purpose: creates an HTML header for the page
  1009.     
  1010.     local($totalTime) = time - $startTime;
  1011.  
  1012.     print OUT <<EOM;        
  1013. <HTML>
  1014. <HEAD>
  1015. <TITLE>$siteName - AccessWatch Summary</TITLE>
  1016. <LINK REV=MADE HREF="mailto:dmaher\@bucknell.edu">
  1017. <!-- This page was generated by AccessWatch v$version - Copyright $year David G. Maher. All rights reserved. Removal of this line is against applicable copyright laws. -->
  1018. </HEAD>
  1019. <BODY $bodyArgs>
  1020. <TABLE BORDER=0 WIDTH=100%>
  1021. <TR>
  1022. <TD><A HREF="http://www.eg.bucknell.edu/~dmaher/accesswatch/"><IMG WIDTH=123 HEIGHT=102 SRC="img/accesswatch.gif" BORDER=0 ALT="AccessWatch"></A></TD>
  1023. <TD ALIGN=RIGHT><H2>Accesses for $siteName<BR>
  1024. $longmonths[$mon] $mday, $year</H2>
  1025. <B>Last updated : <KBD>
  1026. EOM
  1027.     &PrintTimeString($hour, $min, $sec);
  1028.  
  1029. print OUT <<EOM;
  1030. </B>
  1031. <H5><I>AccessWatch took $totalTime seconds to gather current data</I></H5>
  1032. </TD></TR>
  1033. </TABLE>
  1034. <HR>
  1035.  
  1036. EOM
  1037. }
  1038.  
  1039. #------------------------------------------------------------------------------
  1040. #  AccessWatch function - PrintFooter 
  1041. #    Purpose  : Creates HTML footer for page and sends it to OUT.
  1042. #    Note     : *** Do not modify this function, or remove its call. ***
  1043. #------------------------------------------------------------------------------
  1044. sub PrintFooter {
  1045.  
  1046.     local($fSiteName) = $siteName;
  1047.     $fSiteName =~ tr/ /+/;
  1048.     $fSiteName = "Unknown" if ($fSiteName eq "");
  1049.  
  1050.     print OUT <<EOM;
  1051. <HR>
  1052. $customFooter<BR CLEAR=BOTH>
  1053. <TABLE BORDER=1 CELLPADDING=5 WIDTH=100%>
  1054. <TR>
  1055. <TD><A HREF="http://www.eg.bucknell.edu/~dmaher/accesswatch/"><IMG HSPACE=0 VSPACE=0 WIDTH=51 HEIGHT=52 BORDER=0 SRC="img/aw_icon.gif" ALT="AccessWatch"></A></TD>
  1056. <TD>
  1057. This page was produced by <I><A HREF="http://www.eg.bucknell.edu/~dmaher/accesswatch/">AccessWatch v$version</A></I>,
  1058. a WWW utility written by
  1059. <A HREF="http://www.eg.bucknell.edu/~dmaher/">Dave Maher</A>
  1060. <A HREF="mailto:dmaher\@bucknell.edu">
  1061. <dmaher\@bucknell.edu></A>
  1062. Copyright ©$year All Rights Reserved.
  1063. </TD>
  1064. </TR>
  1065. </TABLE>
  1066.  
  1067. <IMG SRC="http://www.eg.bucknell.edu/cgi-bin/dmaher/accesscount.gif?$version,$fSiteName" WIDTH=1 HEIGHT=1 ALT="">
  1068. </BODY>
  1069. </HTML>
  1070. EOM
  1071. }
  1072.  
  1073. #-----------------------------------------------------------------------------#
  1074. #  AccessWatch function - PrintTimeString
  1075. #    Purpose  : Creates formatted string of text and sends to OUT.
  1076. #    Arguments: 3 integers - The hour, minute, and seconds.
  1077. #-----------------------------------------------------------------------------#
  1078. sub PrintTimeString {
  1079.     local($pm);
  1080.     local($hour, $min, $sec) = ($_[0], $_[1], $_[2]);
  1081.  
  1082.     if ($hour > 12) { 
  1083.     $pm = $hour - 12;
  1084.     print OUT "$pm:"; 
  1085.     }
  1086.     elsif ($hour == 0) {
  1087.     print OUT "12:";
  1088.     }
  1089.     elsif ($hour == 12) {
  1090.     $pm = 12;
  1091.     print OUT "$pm:";
  1092.     }
  1093.     else { print OUT "$hour:"; }
  1094.     if ($min > 9) { print OUT "$min:"; }               
  1095.     else { print OUT "0$min:"; }
  1096.     if ($sec > 9) { print OUT "$sec"; }               
  1097.     else { print OUT "0$sec"; }
  1098.     if ($pm) { print OUT "</KBD> p.m."; }
  1099.     else { print OUT "</KBD> a.m."; }
  1100. }
  1101.  
  1102. __END__
  1103.  
  1104.  
  1105.