#!C:\perl\bin

require "common.pl";

# PLEASE READ ALL THE INSTRUCTIONS BELOW.
# 
# CORRECT THE perl ENGINE LOCATION IN FIRST LINE ABOVE,
# THEN CUSTOMIZE THESE FOUR ASSIGNMENTS:
$rec_dir = "hitcount"; # Use relative path.
@referers = ('www.rainbowtel.net/~bryants/', ); # Domains to use this script.
$graphics_dir = "../graphics/"; # Use relative path.
$notify = "the webmaster"; # Whom to notify in case of problems.
$gmtPlusMinus = -21600; # Depends on where you live.

# **************** DON'T CHANGE ANYTHING FROM HERE ON DOWN. *************
# 
# This script keeps a record of hits to specified pages, including
# the name of the page that referred the user to your page. Once
# each month, actually the first time a page is hit each month,
# past records will be archived to keep the record from growing
# too large. You can check the archives using the report form
# (see below).
# 
# (Note: the first time a record file is archived will be the second
# time the page is hit, so your first archive will have one record
# in it. That's the way it goes.)
# 
# Files in this shipment:
#   hitcount.pl (this file)
#   trans.gif   (the graphic, 1x1 clear)
# 
# INSTRUCTIONS:
# 1. Create directories if needed. Note path of existing directories.
# 2. Customize files (including adding tags to your existing pages).
# 3. Upload files into directories.
# 4. Set directory and file permissions.
# 5. Test.
# 
# ---------------------
# DIRECTORIES AND FILES
# ---------------------
# Suggested directory/file structure (and permissions when relevant):
# /cgi-bin/ (0755)
#    |  file hitcount.pl (0755)
#    |
#    -- hitcount/ (0777) (name can be customized in hitcount.pl and hitreprt.pl)
#                [file hitcount.txt will be created automatically.]
# 
# /public_h/
#    |  file index.html (and others) containing hit tag*
#    |  file hitreprt.htm
#    |
#    -- graphics/ (can be customized in hitcount.pl and hitreprt.pl)
#                file trans.gif (a 1x1 pixel, transparent .GIF)
# 
# Note: Copy all files as ASCII except the graphic, trans.gif.
# 
# ------------------------------------
# TAG TO INSERT IN YOUR EXISTING PAGES
# ------------------------------------
# After you customize this tag (see just below), copy it
# INTO THE BODY of each file you want to track. (Delete
# the "# " at the beginning of each line!)
# 
# <script language="JavaScript">
# hit_record="hitcount";
# newReferrer=new String(document.referrer);
# newReferrer=newReferrer.replace(/\=/g,"[EQ]");
# newReferrer=newReferrer.replace(/\+/g,"[PL]");
# newReferrer=newReferrer.replace(/\&/g,"[AA]");
# newReferrer=newReferrer.replace(/\|/g,"[PP]");
# newReferrer=newReferrer.replace(/\ /g,"[SP]");
# document.write("<img src=\"http://www.rainbowtel.net/~bryants/cgi/hitcount.pl?referrer="+newReferrer+"&hit_record="+hit_record+"\" height=\"1\" width=\"1\">");
# </script>
# 
# BEFORE THIS TAG WILL WORK you'll have to make this customization:
#    * http://www.rainbowtel.net/cgi/hitcount.pl
#      will need to be changed to your
#      cgi path, probably
#         http://www.your-isp.com/~your_logon/cgi-bin/hitcount.pl
# 
# And this customization is optional:
#    * hit_record="hitcount";
#      If you want to name the record
#      file differently, change the word
#      in quotes and hitcount.pl will
#      create the file automatically the
#      first time it registers a hit. All
#      you have to do is change it to
#      something like:
#         hit_record="anything";
#      and hitcount.pl will create
#      "anything.txt" for you.
#         You can name this field
#      differently in each .HTM page if
#      you wish. Then each page will have
#      its own tracking. This might make
#      it easier to review the records.
# 
# ---------------------------
# CODE FOR CHECKING YOUR HITS
# ---------------------------
# You can copy the text below into another file, delete the 
# hash and space ("# ") at the start of each line, and
# tailor the tags according to the instructions. This is to
# report on who's hit your pages, so a suggested filename is
# hitreprt.htm. But name it whatever you like.
# 
# (Copy from "<html>" to "</html>".)
# 
# <html>
# <head>
# <title>Hit Counter Reports</title>
# </head>
# <body bgcolor="FFFFFF">
# <!-- INSTRUCTIONS:
# 1.  First, correct the URL of your cgi directory everyplace it
#     occurs below. Yours will probably look like this:
#        http://www.your-isp.com/~yourlogon/cgi-bin/hitcount.pl... (etc.)
# 2. Duplicate the first tag as needed, from "<p>Click..." to
#    "...active record.</p>" Edit each copy of that tag to specify
#    the file to open, i.e.:
#       rec_file=tapdance.txt
#    and to display a good description of the record, i.e.:
#        for the June 2002 St. Vitus School of Dance page hits.
# NOTE: The second tag needs only one display, since it's customized by
#    changing the filename in the text field at run time. If you want,
#    however, you can make several copies of the tag and change the
#    default filename that appears in the text blank by changing
#    the "hitcount.02e" to whatever you want for each copy. This could
#    save time typing if you maintain several record files.
# // -->
# 
# <h2>Hit counter reports:</h2>
# email
# <!-- CURRENTLY ACTIVE RECORD -->
# <p>Click <A HREF="http://www.rainbowtel.net/~bryants/cgi/hitcount.pl?report=yes&rec_file=hitcount.txt">here</A> for the currently active record.</p>
# 
# <!-- SELECTION FORM FOR PAST MONTHLY ARCHIVES -->
# <p><form method=post action="http://www.rainbowtel.net/~bryants/cgi/hitcount.pl" enctype="application/x-www-form-urlencoded">
# <input name="report" type="hidden" value="yes">
# Archive to view: <input name="rec_file" type="text" value="hitcount.02f" cols=12 size="12" align=left>
# &nbsp;<input name="submit" type="submit" value="view hits">
# </form>
# <br>
# &nbsp;&nbsp;&nbsp;<font size="-1"><i><b>Note:</b> Lower case. 8.3 characters max. Extension: 2-digit year + month letter (a=January, b=February...)</i></font></p>
# 
# </body>
# </html>
# 
# **************** END OF INSTRUCTIONS. *********************

sub parse_form_data
{
    local (*FORM_DATA) = @_;

    local ($request_method, $query_string, @key_value_pairs,
           $key_value, $key, $value);

    $request_method = $ENV{'REQUEST_METHOD'};

    if ($request_method eq "GET") {
        $query_string = $ENV{'QUERY_STRING'};
    } elsif ($request_method eq "POST") {
        read (STDIN, $query_string, $ENV{'CONTENT_LENGTH'});
    } else {
        &return_error ("Server uses unsupported method.");
    }

    @key_value_pairs = split (/&/, $query_string);

    foreach $key_value (@key_value_pairs) {
        ($key, $value) = split (/=/, $key_value);
        $value =~ tr/+/ /;
        $value =~ s/%([\dA-Fa-f][\dA-Fa-f])/pack ("C", hex ($1))/eg;

        if (defined($FORM_DATA{$key})) {
            $FORM_DATA{$key} = join ("\0", $FORM_DATA{$key}, $value);
        } else {
            $FORM_DATA{$key} = $value;
        }
    }
}

sub date_time
	{
	($which,$z) = ($_[0],"a");
	my($sec,$min,$hour,$mday,$mon,$year);
	if (!$which)
		{ 
		($min,$hour) = (gmtime(time + $gmtPlusMinus))[1,2];
		if ($hour > 11)
			{$z = "p";}
		if ($hour > 12)
			{$hour = $hour - 12;}
		return sprintf("%02d-%02d$z",$hour,$min);
		}
	elsif ($which)
		{
		($sec,$min,$hour,$mday,$mon,$year) = (gmtime(time + $gmtPlusMinus));
		if ($year > 99)
			{$year = 2000 + ($year - 100);}
		elsif ($year < 100)
			{$year = "19$year";}
		return sprintf("%02d\/%02d\/%04d %02d:%02d",$mon + 1,$mday,$year,$hour,$min);
		}
	}

sub sendFile
	{
	my $File = $_[0];
	my $type = $_[1];
	my $size = 0;
	if ( open(FILE, $File))
		{
		$size = ( -s $File);
		print "Content-type: $type\n";
		print "Content-length: $size\n\n";
		print <FILE>;
		close (FILE);
		}
	}

sub archive_extension
	{
	my($sec,$min,$hour,$mday,$mon,$year);
	($sec,$min,$hour,$mday,$mon,$year) = (gmtime(time + $gmtPlusMinus));
	if ($mon == 0)
		{
		$mon = 11;
		--$year;
		}
	else
		{
		--$mon;
		}
	if ($year > 99)
		{$year = $year - 100;}
	return sprintf("%02d%c", $year, $mon + 97);
	}

$exclusive_lock = 2;
$unlock_lock = 8;
&parse_form_data(*form_data);

my $ok_referer = 0;
if ($ENV{'HTTP_REFERER'})
	{
	foreach $referer (@referers)
		{
		if ($ENV{'HTTP_REFERER'} =~ m|\Ahttps?://([^/]*)$referer|i)
			{
			$ok_referer = 1;

			$referer_filename = $ENV{'HTTP_REFERER'};
			$referer_filename =~ s/\\/\//g;
			@all = split(/\// , $referer_filename);
			$page_hit = $all[$#all];
			last;
			}
		}
	}
if ($ok_referer == 0)
	{
	return_error("You're not allowed to reference this script.");
	}

if ($form_data{'report'} eq "yes")
	{
	$rec_file = $form_data{'rec_file'};
	if (!$rec_file)
		{
		$rec_file = "hitcount.txt";
		}
	$rec_pathname = $rec_dir . "/" . $rec_file;

	print "Content-type: text/html", "\n\n";
	print "<HTTP>\n<HEAD>\n<TITLE>Hit Counter Report -- " . $rec_file . "</TITLE>\n";
	print "</HEAD>\n";
	print "<BODY>\n";
	print "<H3>Hit Counter Report -- " . $rec_file . "</H3>\n";
	print "<TABLE WIDTH=\"100%\" BORDER=1>\n";

	my $total_hits = 0;
	open (REC_FN, "<" . $rec_pathname) or $total_hits++;
	while (<REC_FN>)
		{
		$total_hits++;
#		print "<tr>";
		print "<tr><td><font size=\"-1\">";
		chomp($_);
		@fields = split(/\|/, $_);
		foreach $field (@fields)
			{
			$field =~ s/\[PP]/\|/g;
			$field =~ s/\[SP]/\ /g;
			$field =~ s/\[EQ]/\=/g;
			$field =~ s/\[PL]/\+/g;
			$field =~ s/\[AA]/\&/g;
#			print "<TD><font size=\"-1\">$field</font></TD>\n";
			print "$field<br>\n";
			}
#		print "</tr>\n";
		print "</font></td></tr>\n";
		}
	print "</table>\n";
	$total_hits--;
	print "<h3>Total hits: $total_hits</h3>\n";
	print "</body>\n</http>\n";
	close (REC_FN);
	}
else
	{
	$referrer = $form_data{'referrer'}; # The double "r" is the page that referred to our page.

	$hit_record = $form_data{'hit_record'};
	if (!$hit_record)
		{
		$hit_record = "hitcount";
		}

	$rec_file = $rec_dir . "/" . $hit_record . ".txt";
	$arch_file = $rec_dir . "/" . $hit_record . "." . archive_extension();
	$new_file = $rec_dir . "/" . $hit_record . ".new";

	# IF THE MONTH HAS CHANGED (i.e., IF NO LAST MONTH ARCHIVE,
	# THEN MAKE ONE AND START WITH A FRESH rec_file.
	if (!(-e "$arch_file"))
		{
		rename ($rec_file, $arch_file);
		open (TEMPHANDLE, ">" . $rec_file) or die "Can't create a rec file!";
		flock (TEMPHANDLE, $exclusive_lock);
		print TEMPHANDLE "<B>date/time</B>|<B>page hit</B>|<B>user URL</B>|<B>user's ISP</B>|<B>page that sent user here</B>\n";
		flock (TEMPHANDLE, $unlock_lock);
		close (TEMPHANDLE);
		}

	if ($no_remote_host =~ /(\|$ENV{'REMOTE_HOST'}\||\|$ENV{'REMOTE_ADDR'}\|)/i)
		{
		return 0;
		}
	if (($ENV{'REMOTE_ADDR'} eq $ENV{'REMOTE_HOST'} || !$ENV{'REMOTE_HOST'}) && $ENV{'REMOTE_ADDR'} =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/)
		{
		$pk = pack('C4', $1, $2, $3, $4);
		$cnvrt = (gethostbyaddr($pk, 2))[0];
		if ($cnvrt) {$ENV{'REMOTE_HOST'} = $cnvrt;}
		}

# CREATE A RECORD FILE IF THIS IS THE FIRST HIT...
	if (!(-e "$rec_file"))
		{
		open (TEMPHANDLE, ">" . $rec_file) or die "Can't create a rec file!";
		flock (TEMPHANDLE, $exclusive_lock);
		print TEMPHANDLE "<B>date/time</B>|<B>page hit</B>|<B>user URL</B>|<B>user's ISP</B>|<B>page that sent user here</B>\n";
		flock (TEMPHANDLE, $unlock_lock);
		close (TEMPHANDLE);
		}

	if ((-r $rec_file) && (-w $rec_file))
		{
		open (STORE, ">>" . $rec_file);
		flock (STORE, $exclusive_lock);
		print STORE date_time(1)."|$page_hit|$ENV{'REMOTE_ADDR'}|$ENV{'REMOTE_HOST'}|$referrer\n";
		flock (STORE, $unlock_lock);
		close (STORE);
		}

	&sendFile($graphics_dir."trans.gif", "image/gif");
	}

1;
