#!/usr/bin/perl
# counter.cgi -- counts Web page hits
# the first line of this script may have to be changed
# if your system's Perl interpreter is not located in /usr/bin/perl
# Written by P. Lutus Ashland, Oregon lutusp@arachnoid.com 2/21/96
# This is a cute, small, serviceable hits counter program. It uses the x-bitmap format
# which is monochrome. It won't look very good if the textcolor and background are the same color
# and the browser is made by Netscape. Every other place and browser, OK.
#
# Call the counter like this: You are Visitor Number
# Ownername can have particular web page designators attached to it like this: Ownername_mypagename
# This allows you to count pages independently.
# The directory in which counter.cgi is stored must have world read, write and execute access.
# The file counter.cgi must have world execute access.
# $min_width is the minimum number of digits to print --
# the program will always print more as the number grows larger
$min_width = 2;
# set $collect_stats = 1 if you want to log the origins of accesses
# in a file named Ownername.log
$collect_stats = 1;
$countname = "counter_dat"; # a default name for the counter file
# This is a reasonable character set, sort of blocky but OK
$counter_width = 16;
$counter_height = 20;
@dig_arr = (
'0x00', '0x00', '0x00', '0x00', '0xFC', '0x0F', '0xFA', '0x17', '0xF6', '0x1B', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0x06', '0x18', '0x00', '0x00', '0x06', '0x18', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0xF6', '0x1B', '0xFA', '0x17', '0xFC', '0x0F', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0x00', '0x00', '0x00', '0x10', '0x00', '0x18', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x18', '0x00', '0x00', '0x00', '0x18', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x18', '0x00', '0x10', '0x00', '0x00', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0xFC', '0x0F', '0xF8', '0x17', '0xF0', '0x1B', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0xF0', '0x1B', '0xF8', '0x07', '0xF6', '0x03', '0x0E', '0x00', '0x0E', '0x00', '0x0E', '0x00', '0x0E', '0x00', '0xF6', '0x03', '0xFA', '0x07', '0xFC', '0x0F', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0xFC', '0x0F', '0xF8', '0x17', '0xF0', '0x1B', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0xF0', '0x1B', '0xF8', '0x07', '0xF0', '0x1B', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0xF0', '0x1B', '0xF8', '0x17', '0xFC', '0x0F', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0x00', '0x00', '0x02', '0x10', '0x06', '0x18', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0xF6', '0x1B', '0xF8', '0x07', '0xF0', '0x1B', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x18', '0x00', '0x10', '0x00', '0x00', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0xFC', '0x0F', '0xFA', '0x07', '0xF6', '0x03', '0x0E', '0x00', '0x0E', '0x00', '0x0E', '0x00', '0x0E', '0x00', '0xF6', '0x03', '0xF8', '0x07', '0xF0', '0x1B', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0xF0', '0x1B', '0xF8', '0x17', '0xFC', '0x0F', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0xFC', '0x0F', '0xFA', '0x07', '0xF6', '0x03', '0x0E', '0x00', '0x0E', '0x00', '0x0E', '0x00', '0x0E', '0x00', '0xF6', '0x03', '0xF8', '0x07', '0xF6', '0x1B', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0xF6', '0x1B', '0xFA', '0x17', '0xFC', '0x0F', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0xFC', '0x0F', '0xF8', '0x17', '0xF0', '0x1B', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x18', '0x00', '0x00', '0x00', '0x18', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x18', '0x00', '0x10', '0x00', '0x00', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0xFC', '0x0F', '0xFA', '0x17', '0xF6', '0x1B', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0xF6', '0x1B', '0xF8', '0x07', '0xF6', '0x1B', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0xF6', '0x1B', '0xFA', '0x17', '0xFC', '0x0F', '0x00', '0x00',
'0x00', '0x00', '0x00', '0x00', '0xFC', '0x0F', '0xFA', '0x17', '0xF6', '0x1B', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0x0E', '0x1C', '0xF6', '0x1B', '0xF8', '0x07', '0xF0', '0x1B', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0x00', '0x1C', '0xF0', '0x1B', '0xF8', '0x17', '0xFC', '0x0F', '0x00', '0x00',
);
@digits = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0); # So? Anything is possible!
@envname = (
'REMOTE_ADDR',
'REMOTE_HOST',
'HTTP_REFERER',
'HTTP_USER_AGENT',
'HTTP_ACCEPT',
);
if ($ENV{COMSPEC} ne '') { # most definitely MSDOS, so use those old funky names
@envname = keys(%ENV);
}
if ($ENV{'QUERY_STRING'} ne '') {
$countname = $ENV{'QUERY_STRING'}; # get the file name from counter.cgi?ownername construct
}
unless (-e $countname) { # unless this file already exists
open (COUNT,">$countname"); # directory has to have world write permission for this to work
print COUNT "0\n";
close COUNT;
}
$count = 0; # now get and increment the counter
open (COUNT,$countname) || die "Content-type:text/plain\n\nCan't open $countname!\n";
$count = ;
close COUNT;
$count++;
open (COUNT,">$countname"); # I don't lock access so this might break or not count right in busy sites
print COUNT "$count\n"; # but locking has problems of its own ...
close COUNT;
if ($collect_stats) { # owner want to collect data on logons
$logname = $countname . ".log";
unless (-e $logname) { # unless this file already exists
open (LOG,">$logname"); # directory has to have world write permission for this to work
print LOG "Count\tTime";
foreach $envlbl (@envname) {
print LOG "\t$envlbl";
}
print LOG "\n";
close LOG;
} # done initializing stats file
open (LOG,">>$logname"); # now enter this stat record
$tim = &readtime;
print LOG "$count\t$tim";
foreach $envlbl (@envname) {
print LOG "\t$ENV{$envlbl}";
}
print LOG "\n";
close LOG;
} # end of collect_stats block
$size = &fill_digits($count); # now show the actual count
&print_digits($size);
exit;
sub fill_digits {
$q = @_[0];
$i = 0;
do {
$digits[$i++] = $q % 10;
$q = int($q/10);
}
while(($q != 0) || ($i < $min_width)); # force width to be at least $min_width
$i = $i; # make it the return value
}
sub print_digits {
$width = @_[0];
$cw = $width * $counter_width;
$chh = $counter_height * 2;
print "Content-type:image/x-xbitmap\n\n";
print "#define counter_width $cw\n";
print "#define counter_height $counter_height\n";
print "static unsigned char counter_bits[] = {\n";
$start = 1;
for($i=0;$i<$chh;$i=$i + 2) {
for($j=$width-1;$j>=0;$j--) {
for($k=0;$k<2;$k++) {
if ($start == 0) {
print",";
}
print "$dig_arr[($digits[$j]*$chh)+$i+$k]";
$start = 0;
}
}
print "\n";
}
print "};\n";
}
sub readtime {
local ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
sprintf ("%2.0f/%02.0f/%04.0f %2.0f:%02.0f:%02.0f",$mon+1,$mday,($year > 50)?$year+1900:year+2000,$hour,$min,$sec); # to the stack
}