chmod a+rw .htlog >ls -las .ht* 3 -rw-rw-rw- 1 user gst 0 Jan 11 19:03 .htlog 2) create a file called .htaccess in your public_html directory and add the following lines to it: ############################################## #process all html-files with php SetHandler application/x-httpd-php3 #don't show files beginning with ".ht" Order allow,deny Deny from all ############################################## 3) See the settings section below 4) copy this script to a file on your website. (say /home/user/public_html/logs/hic.php) 5) access this script with your browser (http://www.server.com/~user/logs/hic.php) to see that it works and to get the last instruction. Which is... 6) When including your pages to be counted with the HIngo Counter use at the end of your HTML-file. *********************************************************************/ /****************** settings *****************************************/ //Specify which file we may use (must be world writable, chmod a+rw .htlog) $logfile = "/home/username/public_html/logs/.htlog"; //You may specify a password needed to see the stats $reqpasswd = ""; //If you're not interested in seeing what browser people use //turn this to "no" to reduce the filesize of the log $logagents = "no"; //This should be a directory where the script has write permission $lockdir = '/tmp'; /*******************known bugs*************************************** 1) Despite my best efforts, the locking mechanism still doesn't seem to work. For some reason or another, the log will reset itself at random intervals. Should fix it such that: - The logging part writes in append mode a file similar to apache's logfile - The analyzing/gouping/everything is done from this log when you ask to view the stats. This should be safer, since the file is never re-written, only appended. As a bonus this will of course be more efficient (except for the rare occasions when you are actually viewing the stats). Now that I think of it, why didn't we do it like this in the first place? ***************************************************************************/ /********************begin script*************************************/ //Make a name for a file we will use as a lock. //The intent is that this is somewhat unique $lockfile = str_replace('/', '-', $logfile); $lockfile = $lockdir . '/' . $lockfile . '.lock'; //Check if lock exists, and if it does, wait for half a second and try again //Just in case something is wrong, if we've stopped for 2 seconds, just //forget about counting and skip this $stopper = 0; while($stopper < 4){ if (file_exists($lockfile)) { sleep(0.5); $stopper++; }else{ //Create a file that indicates a lock on the logfile touch($lockfile); //Now read the file, increment counters, and write back to it if($fp = fopen($logfile, "r") ){ list($allstats, $setup) = unserialize(fread($fp, filesize($logfile))); fclose($fp); } /* $allstats is an array of format $allstats[$SCRIPT_NAME => "Hits" => $++, "RemoteHost" => (name or ip => (hits=> $++, Agent => $agent ), "Referer" => ($referer => $++)] $setup contains additional info $setup["StartDate" => unixtimestamp] */ //Set a start-date, if not set already if(!$setup["StartDate"]>0){ $setup["StartDate"] = time(); } //Increment counters. If the array didn't exist in the file //(the file was empty) it seems to create itself now $allstats[$SCRIPT_NAME]["hits"]++; if($REMOTE_HOST){ $allstats[$SCRIPT_NAME]["RemoteHost"][$REMOTE_HOST]["hits"] = $allstats[$SCRIPT_NAME]["RemoteHost"][$REMOTE_HOST]["hits"] + 1; }else{ $allstats[$SCRIPT_NAME]["RemoteHost"][$REMOTE_ADDR]["hits"] = $allstats[$SCRIPT_NAME]["RemoteHost"][$REMOTE_ADDR]["hits"] + 1; } if($HTTP_REFERER){ $allstats[$SCRIPT_NAME]["Referer"][$HTTP_REFERER] = $allstats[$SCRIPT_NAME]["Referer"][$HTTP_REFERER] + 1; } if($HTTP_USER_AGENT && $logagents == "yes"){ if($REMOTE_HOST){ $allstats[$SCRIPT_NAME]["RemoteHost"][$REMOTE_HOST][$HTTP_USER_AGENT] = $allstats[$SCRIPT_NAME]["RemoteHost"][$REMOTE_HOST][$HTTP_USER_AGENT] + 1; }else{ $allstats[$SCRIPT_NAME]["RemoteHost"][$REMOTE_ADDR][$HTTP_USER_AGENT] = $allstats[$SCRIPT_NAME]["RemoteHost"][$REMOTE_ADDR][$HTTP_USER_AGENT] + 1; } } //write back to the file $fp = fopen($logfile, "w"); fwrite($fp, serialize(array($allstats, $setup))); fclose($fp); //We're done, release the lock unlink($lockfile); //we're done. break out of the loop $stopper = 100; } //if/else } //while //The user is accessing this page: //show statistics if(basename($SCRIPT_NAME) == "hic.php"){ print "

HIngo's Counter: hic.php $version

"; if($reqpasswd != $passwd){ ?>
HIngo's Counter use "; print '
<?php include('.$SCRIPT_FILENAME.');?>
'; print "at the end of your HTML-file.
\n"; //Maintenance section******************************* if(file_exists($lockfile)){ ?>

Note: When I just looked, it seems like the file where our statistics are stored was locked. This probably means, that somebody was being counted at that exact moment.

However, if the lock persists, it might also mean that something really has locked up, and nothing is being counted anymore. If you wan't to force the lock to be released, ">click here.


Problem: Could not release the lock. For now, no visitors will be counted.


"; } } print "Homepage access statistics during "; print date("Y-M-d", $setup["StartDate"])." to ".date("Y-M-d")."\n
\n"; //First we'll extract some info from $allstats //Count hosts and agents $agents = array(); $hosts = array(); $referers = array(); $refperpage = array(); reset($allstats); //traverse through pages while(list($key, $val) = each($allstats)){ $h = $val["RemoteHost"]; reset($h); //traverse through remote hosts while(list($k, $v) = each($h)){ //count the hits for RemoteHost $hosts[$k] = $hosts[$k] + $v["hits"]; //traverse through the agents of this host while(list($kk, $vv) = each($v)){ $agents[$kk] = $agents[$kk] + $vv; } } //count the referers //reset() would complain for a null-value, so we use if() //with $agents it didn't matter, because they're togehter //with the "hits" entry, that always exists if($r = $val["Referer"]){ reset($r); while(list($k, $v) = each($r)){ $referers[$k] = $referers[$k] + $v; $refperpage[$key][$k] = $v; } } } //the "hits" entry is not an agent, but interesting to know $allhits = $agents["hits"]; unset($agents["hits"]); //Now it's time to tell the results //Hits/page //Function used to sort the $allstats-array function allcmp($a, $b){ return $b["hits"]-$a["hits"]; } uasort($allstats, "allcmp"); //Table with hits/file print "\n"; print "\n"; reset($allstats); while(list($key, $val) = each($allstats)){ $hits=$val["hits"]; $uniq = count($val["RemoteHost"]); print "\n"; } print ""; print "\n"; print "
Page:Hits:Unique Hosts:
$key$hits$uniq
ALL PAGES$allhits".sizeof($hosts)."
\n"; //hits/hosts arsort($hosts); print "

Hits from different hosts:

"; print "\n"; print "\n"; reset($hosts); while( list($key, $val) = each($hosts) ){ print "\n"; } print "
Remote host address:Visits:
$key$val
\n"; //hits/different referers arsort($referers); print "

Referers (Where the people are coming from):

"; print "\n"; print "\n"; reset($referers); while( list($key, $val) = each($referers) ){ print ''; print "\n"; } print "
Referer:Hits:
' . chunk_split($key) . '$val
\n"; //From where did they come to each page: print "

Referers/page (From where did they come to this page. Or how do they move on my page.)

"; print "\n"; print "\n"; ksort($refperpage); reset($refperpage); while(list($key, $val) = each($refperpage)){ print '\n"; } print "
Page (Total hits):Hits/ Referers:
' . $key . " (" . $allstats[$key]["hits"] . ")
    \n"; $refs = $refperpage[$key]; arsort($refs); reset($refs); while(list($k, $v) = each($refs)){ print '
  • ' . $v . ': ' . chunk_split($k) . "
  • \n"; } print "
\n"; //hits/agents if agents are counted if($agents){ arsort($agents); print "

Browser popularity contest

"; print "\n"; print "\n"; reset($agents); while( list($key, $val) = each($agents) ){ print "\n"; } print "
Browser:Visits:
$key$val
\n"; } //Ok. Let's draw some pivot's //function to easily dump the arrays (debugging) /**********************************************************************/ function print_array($array) { if(gettype($array)=="array") { echo ""; } else { echo $array; } }// end of print_array() /*********************************************************************/ // print_array($allstats); // print_array($agents); // print_array($hosts); // print_array($referers); // print_array($refperpage); /********************************************************************/ print ""; } /*****************end of hic.php**************************************/