<?php  ### visitcount04.php ### 12.07.2009 ###

# zählt die Requests und merkt sich die IP der Requestoren für die Dauer der
# COUNTER_LOCKTIME. In dieser Zeit wird ein erneuter Request derselen IP 
# nicht gezählt. Ein erneuter Request wird auch nach Ablauf von COUNTER_LOCKTIME
# nicht gezählt, wenn zwischendurch kein Request mit einer abweichenden IP
# eingetroffen ist.
#
# Hinweis:
# IPs als Grundlage für die Client-Erkennung zu benutzen ist keine saubere
# Methode. Durch NAT, Proxies und automatische Lastverteilungen, sowie
# Anonymisierungsdienste können die IPs nicht einem bestimmten Client zugeordnet
# werden. Für die Funktionsweise dieses Zählers ist die Genauigkeit aber 
# hinreichend.


define('COUNTER_LOCKTIME', 3600);

## Counterfile entweder als '.htcounter.dat' oder außerhalb der Document_Root
#$counterfile = rtrim($_SERVER['DOCUMENT_ROOT'],'/').'/../data/counter.dat';   
$counterfile = '.htcounter.dat';   

## Counterfile anlegen, wenn nicht vorhanden.
touch($counterfile);

#------------------------------------------------------------------------------
function visitcount($filename, $time, $retrigger = true, $clean = true)
{
    
    $fh = fopen($filename, 'rb+');

    if (!$fh) return false;
    if (!flock($fh, LOCK_EX))
    {
        fclose($fh);
        return false;
    }
    
    $userabort = ignore_user_abort("1");

    ## Defaults für das Array

    $_data = array();
    $_data['time'] = array();
    $_data['time'][$_SERVER['REMOTE_ADDR']]  = $time;
    $_data['count'] = 1;
    $_data['lastIP'] = $_SERVER['REMOTE_ADDR'];


    $filesize = filesize($filename);

    if ($filesize > 0)
    {
        $filedata = fread($fh, $filesize);
        
        if (false === ($_data = unserialize($filedata))
             or !isset($_data['time'], $_data['count'], $_data['lastIP']))
        {
            $_data = array();
            $_data['time'] = array();
            $_data['time'][$_SERVER['REMOTE_ADDR']]  = $time;
            $_data['count'] = 1;
            $_data['lastIP'] = $_SERVER['REMOTE_ADDR'];            
        }
        else
        {
            ## Nur berücksichtigen, wenn die Requestor-IP noch 
            ## nicht in der Liste der letzten Requests steht 

            if (!isset($_data['time'][$_SERVER['REMOTE_ADDR']])) 
            {    

                ## IP in Liste eintragen  

                $_data['time'][$_SERVER['REMOTE_ADDR']] = $time;
                
                ## nur zählen, wenn zwischendurch ein Request 
                ## von einer anderen IP eingetroffen ist

                if ($_data['lastIP'] != $_SERVER['REMOTE_ADDR'])   #
                {
                    $_data['count']++; 
                }    
            }
            elseif ($_data['time'][$_SERVER['REMOTE_ADDR']] + COUNTER_LOCKTIME < $time)            
            {
                $_data['time'][$_SERVER['REMOTE_ADDR']] = $time;

                if ($_data['lastIP'] != $_SERVER['REMOTE_ADDR'])
                {
                    $_data['count']++;
                }    
            }
            elseif ($retrigger)
            {
                $_data['time'][$_SERVER['REMOTE_ADDR']] = $time;                
            }
            else
            {
                ## ignore visit
            }
            
            if ($clean)
            {
                foreach ($_data['time'] as $ip => $lasttime)
                {
                    if($time - $lasttime > COUNTER_LOCKTIME)
                    {
                        unset($_data['time'][$ip]);
                    }
                }
            }
        }
    }    

    $useronline = count($_data['time']); 
    $filedata = serialize($_data);
    fseek($fh, 0, SEEK_SET);
    fwrite($fh, $filedata);
    ftruncate($fh, strlen($filedata));
    fclose($fh);
    
    ignore_user_abort("$userabort");
    
    $_result = array('visitors'=>$_data['count'], 'useronline'=>$useronline);
    
    return $_result;

}
#------------------------------------------------------------------------------

function writetext($text, $font)
{
    // content-type für das Bild setzen
    header("Content-type: image/gif");

    // Das leere Bild im Speicher erzeugen
    $im = imagecreatetruecolor(200, 20);

    // Ein paar Farben festlegen
    $white = imagecolorallocate($im, 255, 255, 255);
    $grey  = imagecolorallocate($im, 128, 128, 128);
    $black = imagecolorallocate($im, 0, 0, 0  );
    $blue  = imagecolorallocate($im, 0, 0, 255);
    $red   = imagecolorallocate($im, 255, 0, 0);    
    
    // Das leere Bild mit rotem Hintertgrund füllen
    imagefilledrectangle($im, 0, 0, 199, 19, $red);
    
    // Das rote Bild innen weiß füllen
    imagefilledrectangle($im, 1, 1, 198, 18, $white);

    // Einen Schatten hinter den Text legen
    imagettftext($im, 13, 0, 10, 17, $grey, $font, $text);

    // Den Text ins Bild einsetzen
    imagettftext($im, 13, 0, 9, 16, $blue, $font, $text);

    // Das Bild ausgeben. imagegif() erzeugt einen schärferen Text als imagejpeg()
    imagegif($im);
    imagedestroy($im);
}

#==============================================================================
# php main
#==============================================================================


$font = './ARIAL.TTF';
#$font = 'C:/WINNT/Fonts/GLACIERN.TTF';


if (false !== ($_result = visitcount($counterfile, time() )))
{
   $text = "Online:{$_result['useronline']}  Visits:{$_result['visitors']}";      
}
else
{
   $text = "bitworks Deutschland";
}

if (!isset($_GET['noshow'])) 
{
    writetext($text, $font);
}
else
{
    header("Content-type: image/gif");
    readfile('1pix.gif');
}

?>
