<?php
error_reporting
(E_NOTICE);
/*

==============================================================================

    SAIX Live Userstats Script

==============================================================================

    This script will insert your current connection statistics into SAIX's
     'ADSL User Statistics' page.  This is useful if you want to display
     real time statistics in utilities such as Minimeter.

==============================================================================

<VirtualHost *>
    DocumentRoot /var/www/html/userstats/
    ServerName userstats.adsl.saix.net
    ErrorLog logs/userstats.adsl.saix.net-error_log
    CustomLog logs/userstats.adsl.saix.net-access_log common
    Alias /icons/ "/var/www/html/userstats/icons/"
</VirtualHost>

AddType image/vnd.microsoft.icon .ico

<Directory "/var/www/html/userstats">
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-l
    RewriteRule . /userstats.php [L]
    RewriteRule ^$ /userstats.php [L]
</Directory>

*/

$ppp_interface 'ppp0';
$ppp_pid_file '/var/run/pppoe-adsl.pid.pppd';

$host "userstats.adsl.saix.net";
$path $_SERVER["REQUEST_URI"];

$fp fsockopen($host80$errno$errstr30);

if (!
$fp) {
    echo 
"$errstr ($errno)\n";
} else {

    if ((
$path == "/") || ($path == "/perl/") || (substr($path07) == "/perl/?") || (substr($path014) == "/perl/index.pl"))
    {
        
$sysuptime file('/proc/uptime');
        
$sysuptime explode(" "$sysuptime[0]);

        
$pppdpid file($ppp_pid_file);
        
$pppdstat file('/proc/'.trim($pppdpid[0]).'/stat');
        
$pppdstat explode(" "$pppdstat[0]);

        if (
count($pppdstat) > 20)
        {
            
$pppduptime $pppdstat[21];
            
$pppdage = (int)$sysuptime[0] - (int)($pppduptime 100);
        }
        else
        {
            
$pppdage 0;
        }

        
$pppstart time() - $pppdage;
        
$today mktime(050);
        if (
$pppstart $today)
        {
            
$pppstart $today;
            
$pppdage time() - $today;
        }

        
$request strstr($path'?');
        
$thismonth date('\?\Y\E\A\R\=Y\;\M\O\N\T\H\=m'$pppstart);
        if (
$request == '')
        {
            
$request $thismonth;
            
$path "/perl/index.pl" $request;
        }
    }

    
$auth Null;
    
$auth_username Null;
    foreach (
apache_request_headers() as $header => $value)
    {
        if (
$header == "Authorization")
        {
            
$auth explode(' '$value);
            
$auth $auth[1];
        }
    }
    if (
$auth != Null)
    {
        
$auth explode(':'base64_decode($auth));
        
$auth_username $auth[0];
    }

    
$allow_auth 1;
    if (
substr($path015) == "/perl/logout.pl")
    {
        
$allow_auth 0;
        
$request strstr($path'?');
        if (
$request != '?id='.$auth_username)
        {
            
header("Location: /");
            exit();
        }
        else
        {
            
$path '/';
        }
    }

    
$out "GET $path HTTP/1.0\r\n";
    
$out .= "Host: $host\r\n";

    foreach (
apache_request_headers() as $header => $value)
    {
        if ((
$header != "Host") && ($header != "Connection") && (($header != "Authorization") || ($allow_auth == 1))) {
            
$out .= "$header$value\r\n";
        }
    }

    
$out .= "\r\n";

    
fwrite($fp$out);

    
$buffer '';
    while (!
feof($fp)) {
        
$buffer .= fgets($fp128);
    }

    
fclose($fp);

    
$headers substr($buffer0strpos($buffer"\r\n\r\n"));
    
$buffer substr($bufferstrpos($buffer"\r\n\r\n") + 4);

    foreach (
explode("\r\n"$headers) as $header)
    {
        
header($header);
    }

    if ((
$path == "/") || (substr($path06) == "/perl/"))
    {
        
$rows 0;
        if ((
substr($path07) == "/perl/?") || (substr($path014) == "/perl/index.pl"))
        {
            if (
$request == $thismonth)
            {
                
$pppstats explode("\n", `/usr/sbin/pppstats $ppp_interface 2>&1`);
                
$pppstats preg_split("/ +/"trim($pppstats[1]));

                
$basestats explode("\n", `/bin/cat /var/run/$ppp_interface.pppstats 2>&1`);
                
$basestats preg_split("/ +/"trim($basestats[1]));

                if ((
count($pppstats) > 6) && (count($basestats) > 6))
                {
                    
$pppin $pppstats[0] - $basestats[0];
                    
$pppout $pppstats[6] - $basestats[6];

                    
$pattern "/<th>Combined \(Bytes\)<\/th><tr><td>([0-9\.]*+)<\/td><td>([0-9]*+)<\/td><td>([0-9 ]*+)<\/td><td>([0-9 ]*+)<\/td><td>([0-9 ]*+)<\/td>/";

                    
$buffer preg_replace_callback($pattern"replace_numbers"$buffer);
                }
            }

            
$links  '<li><a href="/perl/logout.pl?id='.$auth_username.'">Logout</a></li>';
            
$buffer preg_replace("#</ul>#"$links "\\0"$buffer);

            
$buffer preg_replace_callback("#Daily.*</table>#""add_session_table_bars"$buffer);
            
$days $rows;
            
$rows = -3;
            
$buffer preg_replace_callback("#Cumulative.*</table>#""add_session_table_bars"$buffer);
        }
        else if ((
substr($path016) == "/perl/history.pl") || (substr($path018) == "/perl/sessions.pl?"))
        {
            
$buffer preg_replace_callback("#<table.*</table>#""add_history_table_bars"$buffer);
        }

        
$buffer preg_replace("#(href=)(/[^>]*+)#""\\1'\\2'"$buffer); # HTML Validation Fix
        
$buffer preg_replace("#&[lg]t(?!;)#""\\0;"$buffer); # HTML Validation Fix
        
$buffer str_replace('</div></body></html></div>''</div></div></body></html>'$buffer); # HTML Validation Fix
    
}

    echo 
$buffer;
}

function 
add_session_table_bars($matches)
{
    
$data $matches[0];
    
$data preg_replace("#(?<!<tr>|</th>)<th>.*</th>#""<tr>\\0</tr>"$data); # HTML Validation Fix
    
return preg_replace_callback("#(<td>(.[^<]*+)</td><td>(.[^<]*+)</td><td>.[^<]*+</td>)(</tr>)#""add_session_row_bars"$data);
}

function 
add_session_row_bars($matches)
{
    return 
$matches[1] . make_row_bars(str_replace(' '''$matches[2]), str_replace(' '''$matches[3])) . $matches[4] . "\n";
}

function 
add_history_table_bars($matches)
{
    global 
$days$rows$histories$histid;
    
$histories = array();
    
$histid 'a';
    
$details preg_replace_callback("#(<td[^>]*+>(.[^<]*+)</td><td[^>]*+>(.[^<]*+)</td><td[^>]*+>(.[^<]*+)</td><td[^>]*+>(.[^<]*+)</td><td[^>]*+>(.[^<]*+)</td>)(</tr>)#""add_history_row_bars"$matches[0]);
    
$summary "<table cellspacing='1'><tr><th>ID</th><th>Sessions</th><th>Online Time (Seconds)</th><th>Upload (Bytes)</th><th>Download (Bytes)</th><th>Combined (Bytes)</th></tr>";
    
$duration 0;
    foreach (
$histories as $history)
    {
        
$summary .=
            
"<tr><td>" $history['id'] .
            
"</td><td title='"join(",\n",$history['ips']) . "'>" $history['rows'] .
            
"</td><td>" $history['duration'] .
            
"</td><td>" number_format($history['upload'], 0'.'' ') .
            
"</td><td>" number_format($history['download'], 0'.'' ') .
            
"</td><td>" number_format($history['upload'] + $history['download'], 0'.'' ') .
            
"</td></tr>";
        
$duration += $history['duration'];
    }
    
$summary .= "</table>";
    
$days $duration 129600 count($histories);
    
$rows = -count($histories)-1;
    
$summary preg_replace_callback("#(<td>(.[^<]*+)</td><td>(.[^<]*+)</td><td>.[^<]*+</td>)(</tr>)#""add_session_row_bars"$summary);
    return 
"<h3>Summary:</h3>".$summary."<h3>Details:</h3>".$details;
}

function 
add_history_row_bars($matches)
{
    global 
$rows,$histories,$histid;
    
$end strtotime($matches[2]);
    
$duration $matches[3];
    
$start $end $duration;
    
$ip $matches[4];
    
$upload str_replace(' '''$matches[5]);
    
$download str_replace(' '''$matches[6]);

    
$foundkey Null;
    foreach (
$histories as $key=>$history)
    {
        if (
$history['lastip'] == $ip)
        {
            
$foundkey $key;
            break;
        }
    }
    if (
$foundkey === Null)
    {
        foreach (
$histories as $key=>$history)
        {
            if ((
$start $history['end']) && (substr($history['lastip'], 0strpos($history['lastip'], '.'strpos($history['lastip'], '.') + 1)) == substr($ip0strpos($ip'.'strpos($ip'.') + 1))))
            {
                
$foundkey $key;
                break;
            }
        }
    }
    if (
$foundkey === Null)
    {
        foreach (
$histories as $key=>$history)
        {
            if (((
$start 420) > $history['end']) && (substr($history['lastip'], 0strpos($history['lastip'], '.'strpos($history['lastip'], '.') + 1)) == substr($ip0strpos($ip'.'strpos($ip'.') + 1))))
            {
                
$foundkey $key;
                break;
            }
        }
    }
    if (
$foundkey === Null)
    {
        
$histories[] = array('id'=>$histid,'ips'=>array(),'rows'=>0,'duration'=>0,'upload'=>0,'download'=>0);
        
$histid++;
        
end($histories);
        
$foundkey key($histories);
    }
    
$history $histories[$foundkey];
    
$history['end'] = $end;
    
$history['lastip'] = $ip;
    if (!
in_array($ip$history['ips'])) $history['ips'][] = $ip;
    
$history['rows'] += 1;
    
$history['duration'] += $duration;
    
$history['upload'] += $upload;
    
$history['download'] += $download;
    
$histories[$foundkey] = $history;
    return 
$matches[1] . "<td>".$history['id']."</td>" make_row_bars($upload$download) . $matches[7] . "\n";
}

function 
make_row_bars($upload$download)
{
    global 
$rows$days;
    
$rows++;
    
$factor 25000000;
    if (
$rows && $days 0$factor *= $days;
    
$td "<td style='text-align:left'>";
    
$td .= "<img style='width: " round($upload $factor2) . "em; height: 1.2em;' src='/icons/green.gif' alt='upload'/>";
    
$td .= "<img style='width: " round($download $factor2) . "em; height: 1.2em;' src='/icons/blue.gif' alt='download'/>";
    
$td .= "</td>";
    return 
$td;
}

function 
replace_numbers($matches)
{
    global 
$pppdage$pppout$pppin;
    
$data preg_replace_callback("/<td>([0-9 ]*+)<\/td>/""replace_number"$matches[0]);
    
$data .= '</tr><tr>';
    
$data .= strstr($matches[0], '<td');
    
$data .= '</tr><tr>';
    
$data .= '<td>today</td>';
    
$data .= '<td>'.$pppdage.'</td>';
    
$data .= '<td>'.fmt($pppout).'</td>';
    
$data .= '<td>'.fmt($pppin).'</td>';
    
$data .= '<td>'.fmt($pppout+$pppin).'</td>';
    return 
$data;
}

function 
replace_number($matches)
{
    global 
$tagindex$pppdage$pppout$pppin;
    
$tagindex++;
    
$val str_replace(' '''$matches[1]);
    switch (
$tagindex) {
    case 
1// Sessions
        
$val number_format($val $pppdage 86400,2,'.','');
        break;
    case 
2// Online Time (Seconds)
        
$val $val $pppdage;
        break;
    case 
3// Upload (Bytes)
        
$val $val $pppout;
        break;
    case 
4// Download (Bytes)
        
$val $val $pppin;
        break;
    case 
5// Combined (Bytes)
        
$val $val $pppout $pppin;
        break;
    }
    if (
$tagindex 3)
    {
        return 
"<td>".$val."</td>";
    }
    else
    {
        return 
"<td>".fmt($val)."</td>";
    }
}

function 
fmt($number)
{
    return 
number_format($number0'.'' ');
}

?>