#!/usr/bin/perl -w # Name : Perl Web Access Log # Author : Terrence Ma # Email : terrence@terrence.com # Web : http://www.terrence.com # Date : V2.1 07/25/2002, V1.0 08/14/1998 # Modified : http://www.perlguy.com ############################################################################################# # This script logs visitors to web pages. It can be used as either a SSI, or # # can be called from a link. To use as a SSI, the $SSI variable must be set to 1. # # Conversly, to have it be called from links, have $SSI set to 0. # # To call this script from a link it should have this syntax: # # Click Here # # # # After the logging is done, it will redirect to the page you have after the ?dest= # # Log format can be changed, but by default it is like: # # # # Date - IP - Host - Browser - Where they are going - Where they came from # ############################################################################################# # This script may be modified at will. If you do anything cool with it, please let me know. # # Do not sell this script without my permission and always leave the comments. # # Kevin Meltzer 3/12/97 kmeltz@cris.com | www.ctcom.com/~kmeltz # ############################################################################################# use 5; use Fcntl qw(:DEFAULT :flock); # imports LOCK_EX, LOCK_SH, LOCK_NB # Set variables $SSI = 1; # 0 - Used from link # 1 - Used as Server Side Include # 2 - Used from tag # Path to your log/tmp file, must be chmod 666 $logfile = "/virtual/customer/terrence.com/htdocs/log/logger.txt"; $tmpfile = "/virtual/customer/terrence.com/htdocs/log/logger.tmp"; $ymindexfile = "/virtual/customer/terrence.com/htdocs/log/logyrmon.txt"; $browserdeny = "webcollage"; $ip = $ENV{'REMOTE_ADDR'}; $browser = $ENV{'HTTP_USER_AGENT'}; $referer = $ENV{'HTTP_REFERER'}; $here = $ENV{'DOCUMENT_URI'}; @digits = split (/\./, $ip); $address = pack ("C4", @digits); $host = gethostbyaddr ($address, 2); # From Link if ($SSI eq 0) { &parse_query; &clean; $dest = $query{'dest'}; &write_file; &redirect; } # From SSI if (($SSI eq 1) && !($browser =~ /$browserdeny/)) { &write_file; } # From tag if ($SSI eq 2) { &parse_query; &clean; $this = $query{'dest'}; &write_file; &show_img; } ################################################ # Parse the query then clean it up for our uses ################################################ sub parse_query { @query_strings = split("&", $ENV{"QUERY_STRING"}); foreach $q (@query_strings) { ($attr, $val) = split("=", $q); $query{$attr} = $query{$attr}." ".$val; } } sub clean { if ($query{'dest'} =~ /\/$/) { chop($query{'dest'}); } #$query{'dest'} =~ s/http\:\/\///g; #$query{'dest'} =~ s/\//_\|_/g; } ################################################ # Go! ################################################ sub redirect { print "Location: $dest\n\n"; } ################################################ # Write information to the log ################################################ sub write_file { # get $date, $time, $yrmon_now &date; # step 1 # read $ymindexfile # if ($yrmon_now ne $yrmon_old) # update $ymindexfile # copy $logfile to $yrmonoldfile # gzip $yrmonoldfile # empty $logfile, $tmpfile # read $ymindexfile open(YMINDEXFILE, "< $ymindexfile") || die "Can't read $ymindexfile: $!"; flock(YMINDEXFILE, LOCK_SH) || die "Can't lock filename: $!"; $yrmon_old = ; chomp($yrmon_old); close(YMINDEXFILE); if ($yrmon_now ne $yrmon_old) { # update $ymindexfile open(YMINDEXFILE, "> $ymindexfile") || die "Can't write to $ymindexfile: $!"; flock(YMINDEXFILE, LOCK_EX) || die "Can't lock filename: $!"; print(YMINDEXFILE "$yrmon_now\n"); close(YMINDEXFILE); # copy $logfile to $yrmonoldfile $yrmonoldfile = "/virtual/customer/terrence.com/htdocs/log/" . $yrmon_old . ".txt"; open(LOG, "< $logfile") || die "Can't open $logfile: $!"; flock(LOG, LOCK_SH) || die "Can't lock filename: $!"; open(YRMONOLDFILE, "> $yrmonoldfile") || die "Can't write to $yrmonoldfile: $!"; flock(YRMONOLDFILE, LOCK_EX) || die "Can't lock filename: $!"; while () { (print YRMONOLDFILE $_) || die "Can't write to $yrmonoldfile: $!";} close(YRMONOLDFILE); close(LOG); # gzip $yrmonoldfile `/bin/gzip $yrmonoldfile`; # empty $logfile, $tmpfile open(LOG, "> $logfile") || die "Can't write to $logfile: $!"; flock(LOG, LOCK_EX) || die "Can't lock filename: $!"; close(LOG); open(TMP, "> $tmpfile") || die "Can't write to $tmpfile: $!"; flock(TMP, LOCK_EX) || die "Can't lock filename: $!"; close(TMP); } # step 2 # write $tmpfile at top open(LOG, "< $logfile") || die "Can't open $logfile: $!"; flock(LOG, LOCK_SH) || die "Can't lock filename: $!"; open(TMP, "> $tmpfile") || die "Can't write to $tmpfile: $!"; flock(TMP, LOCK_EX) || die "Can't lock filename: $!"; if ($SSI eq 0) { print TMP "$date - $ip - $host - $browser - $dest - $referer\n";} elsif ($SSI eq 1) { print TMP "$date.$time - $host - $browser - $referer\n";} else { print TMP "$date - $ip - $host - $browser - $this - $referer\n";} while () { (print TMP $_) || die "Can't write to $tmpfile: $!"; } close(TMP); close(LOG); # step 3 # copy $tmpfile to $logfile open(TMP, "< $tmpfile") || die "Can't open $tmpfile: $!"; flock(TMP, LOCK_SH) || die "Can't lock filename: $!"; open(LOG, "> $logfile") || die "Can't write to $logfile: $!"; flock(LOG, LOCK_EX) || die "Can't lock filename: $!"; while () { (print LOG $_) || die "Can't write to $logfile: $!"; } close(LOG); close(TMP); } ################################################# # Get date and time ################################################# sub date { # if ($year >= 100) { # $year = $year % 100; # if ($year >= 10) {$year = "20".$year;} # else {$year = "200".$year;}; # }; # # $year = $year + 1900; # @months = ("01","02","03","04","05","06","07","08","09","10","11","12"); # if ($mday == 0) {$mday = "00";} # elsif ($mday < 10) {$mday = "0".$mday;}; # $date = "$months[$mon]/$mday/$year"; # # if ($hour == 0) {$hour = "00";} # elsif ($hour < 10) {$hour = "0".$hour;}; # if ($min == 0) {$min = "00";} # elsif ($min < 10) {$min = "0".$min;}; # if ($sec == 0) {$sec = "00";} # elsif ($sec < 10) {$sec = "0".$sec;}; # $time = $hour . ":" . $min . ":" . $sec; ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $year = $year + 1900; @months = ("01","02","03","04","05","06","07","08","09","10","11","12"); if ($mday < 10) {$mday = "0".$mday;}; $date = "$months[$mon]/$mday/$year"; # See http://www.terrence.com/perl/clock/clock.txt for CST/CDT if ($hour < 10) {$hour = "0".$hour;}; if ($min < 10) {$min = "0".$min;}; if ($sec < 10) {$sec = "0".$sec;}; $time = $hour . ":" . $min . ":" . $sec . "." . (($isdst == 0) ? "CST" : "CDT"); $yrmon_now = $year . $months[$mon]; } ################################################# # Subroutine to return a 1-pixel transparent gif ################################################# sub show_img { $! = 1; $| = 1; print "Content-type: image/gif\n\nGIF89a\1\0\1\0\200\0\0\0\0\0\0\0\0!\371\4\1\0\0\0\0,\0\0\0\0\1\0\1\0\0\2\2D\1\0\n"; }