11878f16fSAndreas Gohr<?php 21878f16fSAndreas Gohr/** 31878f16fSAndreas Gohr * statistics plugin 41878f16fSAndreas Gohr * 51878f16fSAndreas Gohr * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 61878f16fSAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 71878f16fSAndreas Gohr */ 81878f16fSAndreas Gohr 91878f16fSAndreas Gohr// must be run within Dokuwiki 101878f16fSAndreas Gohrif(!defined('DOKU_INC')) die(); 111878f16fSAndreas Gohr 121878f16fSAndreas Gohrif(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 131878f16fSAndreas Gohrrequire_once(DOKU_PLUGIN.'admin.php'); 141878f16fSAndreas Gohr 151878f16fSAndreas Gohr/** 161878f16fSAndreas Gohr * All DokuWiki plugins to extend the admin function 171878f16fSAndreas Gohr * need to inherit from this class 181878f16fSAndreas Gohr */ 191878f16fSAndreas Gohrclass admin_plugin_statistics extends DokuWiki_Admin_Plugin { 201878f16fSAndreas Gohr var $dblink = null; 21264f1744SAndreas Gohr var $opt = ''; 22264f1744SAndreas Gohr var $from = ''; 23264f1744SAndreas Gohr var $to = ''; 24*95eb68e6SAndreas Gohr var $start = ''; 25264f1744SAndreas Gohr var $tlimit = ''; 261878f16fSAndreas Gohr 271878f16fSAndreas Gohr /** 281878f16fSAndreas Gohr * return some info 291878f16fSAndreas Gohr */ 301878f16fSAndreas Gohr function getInfo(){ 311878f16fSAndreas Gohr return confToHash(dirname(__FILE__).'/info.txt'); 321878f16fSAndreas Gohr } 331878f16fSAndreas Gohr 341878f16fSAndreas Gohr /** 351878f16fSAndreas Gohr * Access for managers allowed 361878f16fSAndreas Gohr */ 371878f16fSAndreas Gohr function forAdminOnly(){ 381878f16fSAndreas Gohr return false; 391878f16fSAndreas Gohr } 401878f16fSAndreas Gohr 411878f16fSAndreas Gohr /** 421878f16fSAndreas Gohr * return sort order for position in admin menu 431878f16fSAndreas Gohr */ 441878f16fSAndreas Gohr function getMenuSort() { 4514d99ec0SAndreas Gohr return 150; 461878f16fSAndreas Gohr } 471878f16fSAndreas Gohr 481878f16fSAndreas Gohr /** 491878f16fSAndreas Gohr * handle user request 501878f16fSAndreas Gohr */ 511878f16fSAndreas Gohr function handle() { 52264f1744SAndreas Gohr $this->opt = preg_replace('/[^a-z]+/','',$_REQUEST['opt']); 53*95eb68e6SAndreas Gohr 54*95eb68e6SAndreas Gohr $this->start = (int) $_REQUEST['s']; 55*95eb68e6SAndreas Gohr 56264f1744SAndreas Gohr // fixme add better sanity checking here: 57264f1744SAndreas Gohr $this->from = preg_replace('/[^\d\-]+/','',$_REQUEST['f']); 58264f1744SAndreas Gohr $this->to = preg_replace('/[^\d\-]+/','',$_REQUEST['t']); 59264f1744SAndreas Gohr if(!$this->from) $this->from = date('Y-m-d'); 60264f1744SAndreas Gohr if(!$this->to) $this->to = date('Y-m-d'); 61264f1744SAndreas Gohr 62264f1744SAndreas Gohr //setup limit clause 63264f1744SAndreas Gohr if($this->from != $this->to){ 64264f1744SAndreas Gohr $this->tlimit = "DATE(A.dt) >= DATE('".$this->from."') AND DATE(A.dt) <= DATE('".$this->to."')"; 65264f1744SAndreas Gohr }else{ 66264f1744SAndreas Gohr $this->tlimit = "DATE(A.dt) = DATE('".$this->from."')"; 67264f1744SAndreas Gohr } 681878f16fSAndreas Gohr } 691878f16fSAndreas Gohr 701878f16fSAndreas Gohr /** 7194171ff3SAndreas Gohr * fixme build statistics here 721878f16fSAndreas Gohr */ 731878f16fSAndreas Gohr function html() { 7414d99ec0SAndreas Gohr // fixme build a navigation menu in a TOC here 7514d99ec0SAndreas Gohr 76264f1744SAndreas Gohr echo '<h1>Access Statistics</h1>'; 77264f1744SAndreas Gohr $this->html_timeselect(); 78264f1744SAndreas Gohr 79264f1744SAndreas Gohr switch($this->opt){ 8014d99ec0SAndreas Gohr 8114d99ec0SAndreas Gohr default: 8214d99ec0SAndreas Gohr echo $this->html_dashboard(); 8314d99ec0SAndreas Gohr } 8414d99ec0SAndreas Gohr } 8514d99ec0SAndreas Gohr 86264f1744SAndreas Gohr /** 87264f1744SAndreas Gohr * Print the time selection menu 88264f1744SAndreas Gohr */ 8914d99ec0SAndreas Gohr function html_timeselect(){ 90264f1744SAndreas Gohr $now = date('Y-m-d'); 91264f1744SAndreas Gohr $yday = date('Y-m-d',time()-(60*60*24)); 92264f1744SAndreas Gohr $week = date('Y-m-d',time()-(60*60*24*7)); 93264f1744SAndreas Gohr $month = date('Y-m-d',time()-(60*60*24*30)); 9414d99ec0SAndreas Gohr 95264f1744SAndreas Gohr echo '<div class="plg_stats_timeselect">'; 96264f1744SAndreas Gohr echo '<span>Select the timeframe:</span>'; 97264f1744SAndreas Gohr echo '<ul>'; 98264f1744SAndreas Gohr 99264f1744SAndreas Gohr echo '<li>'; 100*95eb68e6SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$now.'&t='.$now.'&s='.$this->start.'">'; 101264f1744SAndreas Gohr echo 'today'; 102264f1744SAndreas Gohr echo '</a>'; 103264f1744SAndreas Gohr echo '</li>'; 104264f1744SAndreas Gohr 105264f1744SAndreas Gohr echo '<li>'; 106*95eb68e6SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$yday.'&t='.$yday.'&s='.$this->start.'">'; 107264f1744SAndreas Gohr echo 'yesterday'; 108264f1744SAndreas Gohr echo '</a>'; 109264f1744SAndreas Gohr echo '</li>'; 110264f1744SAndreas Gohr 111264f1744SAndreas Gohr echo '<li>'; 112*95eb68e6SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$week.'&t='.$now.'&s='.$this->start.'">'; 113264f1744SAndreas Gohr echo 'last 7 days'; 114264f1744SAndreas Gohr echo '</a>'; 115264f1744SAndreas Gohr echo '</li>'; 116264f1744SAndreas Gohr 117264f1744SAndreas Gohr echo '<li>'; 118*95eb68e6SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$month.'&t='.$now.'&s='.$this->start.'">'; 119264f1744SAndreas Gohr echo 'last 30 days'; 120264f1744SAndreas Gohr echo '</a>'; 121264f1744SAndreas Gohr echo '</li>'; 122264f1744SAndreas Gohr 123264f1744SAndreas Gohr echo '</ul>'; 124264f1744SAndreas Gohr 125264f1744SAndreas Gohr 126264f1744SAndreas Gohr echo '<form action="" method="get">'; 127264f1744SAndreas Gohr echo '<input type="hidden" name="do" value="admin" />'; 128264f1744SAndreas Gohr echo '<input type="hidden" name="page" value="statistics" />'; 129264f1744SAndreas Gohr echo '<input type="hidden" name="opt" value="'.$this->opt.'" />'; 130*95eb68e6SAndreas Gohr echo '<input type="hidden" name="s" value="'.$this->start.'" />'; 131264f1744SAndreas Gohr echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />'; 132264f1744SAndreas Gohr echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />'; 133264f1744SAndreas Gohr echo '<input type="submit" value="go" class="button" />'; 13414d99ec0SAndreas Gohr echo '</form>'; 135264f1744SAndreas Gohr 136264f1744SAndreas Gohr echo '</div>'; 13714d99ec0SAndreas Gohr } 13814d99ec0SAndreas Gohr 13914d99ec0SAndreas Gohr 140f5f32cbfSAndreas Gohr /** 141f5f32cbfSAndreas Gohr * Print an introductionary screen 142f5f32cbfSAndreas Gohr * 143f5f32cbfSAndreas Gohr * @fixme the sql statements probably need to go into their own functions 144f5f32cbfSAndreas Gohr * to be reused in the syntax plugins to follow 145f5f32cbfSAndreas Gohr */ 14614d99ec0SAndreas Gohr function html_dashboard(){ 147264f1744SAndreas Gohr echo '<div class="plg_stats_dashboard">'; 148264f1744SAndreas Gohr 14914d99ec0SAndreas Gohr 15087d5e44bSAndreas Gohr // top pages today 151264f1744SAndreas Gohr echo '<div>'; 152264f1744SAndreas Gohr echo '<h2>Most popular pages</h2>'; 153*95eb68e6SAndreas Gohr $result = $this->sql_pages($this->tlimit,$this->start,15); 15487d5e44bSAndreas Gohr $this->html_resulttable($result,array('Pages','Count')); 155264f1744SAndreas Gohr echo '</div>'; 15687d5e44bSAndreas Gohr 15787d5e44bSAndreas Gohr // top referer today 158264f1744SAndreas Gohr echo '<div>'; 159264f1744SAndreas Gohr echo '<h2>Top incoming links</h2>'; 160*95eb68e6SAndreas Gohr $result = $this->sql_referer($this->tlimit,$this->start,15); 16187d5e44bSAndreas Gohr $this->html_resulttable($result,array('Incoming Links','Count')); 162264f1744SAndreas Gohr echo '</div>'; 16354f6c432SAndreas Gohr 16454f6c432SAndreas Gohr // top countries today 165264f1744SAndreas Gohr echo '<div>'; 166264f1744SAndreas Gohr echo '<h2>Visitor\'s top countries</h2>'; 167*95eb68e6SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&f='.$this->from.'&t='.$this->to.'" />'; 168*95eb68e6SAndreas Gohr// $result = $this->sql_countries($this->tlimit,$this->start,15); 169*95eb68e6SAndreas Gohr// $this->html_resulttable($result,array('','Countries','Count')); 170264f1744SAndreas Gohr echo '</div>'; 171264f1744SAndreas Gohr 172264f1744SAndreas Gohr echo '</div>'; 17314d99ec0SAndreas Gohr } 17414d99ec0SAndreas Gohr 17514d99ec0SAndreas Gohr /** 17614d99ec0SAndreas Gohr * Display a result in a HTML table 17714d99ec0SAndreas Gohr */ 17814d99ec0SAndreas Gohr function html_resulttable($result,$header){ 17914d99ec0SAndreas Gohr echo '<table>'; 18014d99ec0SAndreas Gohr echo '<tr>'; 18114d99ec0SAndreas Gohr foreach($header as $h){ 18214d99ec0SAndreas Gohr echo '<th>'.hsc($h).'</th>'; 18314d99ec0SAndreas Gohr } 18414d99ec0SAndreas Gohr echo '</tr>'; 18514d99ec0SAndreas Gohr 18614d99ec0SAndreas Gohr foreach($result as $row){ 18714d99ec0SAndreas Gohr echo '<tr>'; 18814d99ec0SAndreas Gohr foreach($row as $k => $v){ 18914d99ec0SAndreas Gohr echo '<td class="stats_'.$k.'">'; 19014d99ec0SAndreas Gohr if($k == 'page'){ 19114d99ec0SAndreas Gohr echo '<a href="'.wl($v).'" class="wikilink1">'; 19214d99ec0SAndreas Gohr echo hsc($v); 19314d99ec0SAndreas Gohr echo '</a>'; 19414d99ec0SAndreas Gohr }elseif($k == 'url'){ 19554f6c432SAndreas Gohr $url = hsc($v); 19654f6c432SAndreas Gohr if(strlen($url) > 50){ 19754f6c432SAndreas Gohr $url = substr($url,0,30).' … '.substr($url,-20); 19854f6c432SAndreas Gohr } 19914d99ec0SAndreas Gohr echo '<a href="'.$v.'" class="urlextern">'; 20054f6c432SAndreas Gohr echo $url; 20114d99ec0SAndreas Gohr echo '</a>'; 20214d99ec0SAndreas Gohr }elseif($k == 'html'){ 20314d99ec0SAndreas Gohr echo $v; 204f5f32cbfSAndreas Gohr }elseif($k == 'cflag'){ 205*95eb68e6SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12"/>'; 20614d99ec0SAndreas Gohr }else{ 20714d99ec0SAndreas Gohr echo hsc($v); 20814d99ec0SAndreas Gohr } 20914d99ec0SAndreas Gohr echo '</td>'; 21014d99ec0SAndreas Gohr } 21114d99ec0SAndreas Gohr echo '</tr>'; 21214d99ec0SAndreas Gohr } 21314d99ec0SAndreas Gohr echo '</table>'; 2141878f16fSAndreas Gohr } 2151878f16fSAndreas Gohr 216*95eb68e6SAndreas Gohr /** 217*95eb68e6SAndreas Gohr * Create an image 218*95eb68e6SAndreas Gohr */ 219*95eb68e6SAndreas Gohr function img_build($img){ 220*95eb68e6SAndreas Gohr include(dirname(__FILE__).'/inc/AGC.class.php'); 221*95eb68e6SAndreas Gohr 222*95eb68e6SAndreas Gohr switch($img){ 223*95eb68e6SAndreas Gohr case 'country': 224*95eb68e6SAndreas Gohr // build top countries + other 225*95eb68e6SAndreas Gohr $result = $this->sql_countries($this->tlimit,$this->start,0); 226*95eb68e6SAndreas Gohr $data = array(); 227*95eb68e6SAndreas Gohr $top = 0; 228*95eb68e6SAndreas Gohr foreach($result as $row){ 229*95eb68e6SAndreas Gohr if($top < 7){ 230*95eb68e6SAndreas Gohr $data[$row['country']] = $row['cnt']; 231*95eb68e6SAndreas Gohr }else{ 232*95eb68e6SAndreas Gohr $data['other'] += $row['cnt']; 233*95eb68e6SAndreas Gohr } 234*95eb68e6SAndreas Gohr $top++; 235*95eb68e6SAndreas Gohr } 236*95eb68e6SAndreas Gohr $pie = new AGC(300, 200); 237*95eb68e6SAndreas Gohr $pie->setProp("showkey",true); 238*95eb68e6SAndreas Gohr $pie->setProp("showval",false); 239*95eb68e6SAndreas Gohr $pie->setProp("showgrid",false); 240*95eb68e6SAndreas Gohr $pie->setProp("type","pie"); 241*95eb68e6SAndreas Gohr $pie->setProp("keyinfo",1); 242*95eb68e6SAndreas Gohr $pie->setProp("keysize",8); 243*95eb68e6SAndreas Gohr $pie->setProp("keywidspc",-50); 244*95eb68e6SAndreas Gohr $pie->setProp("key",array_keys($data)); 245*95eb68e6SAndreas Gohr $pie->addBulkPoints(array_values($data)); 246*95eb68e6SAndreas Gohr @$pie->graph(); 247*95eb68e6SAndreas Gohr $pie->showGraph(); 248*95eb68e6SAndreas Gohr break; 249*95eb68e6SAndreas Gohr default: 250*95eb68e6SAndreas Gohr $this->sendGIF(); 251*95eb68e6SAndreas Gohr } 252*95eb68e6SAndreas Gohr } 253*95eb68e6SAndreas Gohr 254*95eb68e6SAndreas Gohr 255*95eb68e6SAndreas Gohr function sql_pages($tlimit,$start=0,$limit=20){ 256*95eb68e6SAndreas Gohr $sql = "SELECT page, COUNT(*) as cnt 257*95eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 258*95eb68e6SAndreas Gohr WHERE $tlimit 259*95eb68e6SAndreas Gohr AND ua_type = 'browser' 260*95eb68e6SAndreas Gohr GROUP BY page 261*95eb68e6SAndreas Gohr ORDER BY cnt DESC, page". 262*95eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 263*95eb68e6SAndreas Gohr return $this->runSQL($sql); 264*95eb68e6SAndreas Gohr } 265*95eb68e6SAndreas Gohr 266*95eb68e6SAndreas Gohr function sql_referer($tlimit,$start=0,$limit=20){ 267*95eb68e6SAndreas Gohr $sql = "SELECT ref as url, COUNT(*) as cnt 268*95eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 269*95eb68e6SAndreas Gohr WHERE $tlimit 270*95eb68e6SAndreas Gohr AND ua_type = 'browser' 271*95eb68e6SAndreas Gohr AND ref_type = 'external' 272*95eb68e6SAndreas Gohr GROUP BY ref_md5 273*95eb68e6SAndreas Gohr ORDER BY cnt DESC, url". 274*95eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 275*95eb68e6SAndreas Gohr return $this->runSQL($sql); 276*95eb68e6SAndreas Gohr } 277*95eb68e6SAndreas Gohr 278*95eb68e6SAndreas Gohr function sql_countries($tlimit,$start=0,$limit=20){ 279*95eb68e6SAndreas Gohr $sql = "SELECT B.code AS cflag, B.country, COUNT(*) as cnt 280*95eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A, 281*95eb68e6SAndreas Gohr ".$this->getConf('db_prefix')."iplocation as B 282*95eb68e6SAndreas Gohr WHERE $tlimit 283*95eb68e6SAndreas Gohr AND A.ip = B.ip 284*95eb68e6SAndreas Gohr GROUP BY B.country 285*95eb68e6SAndreas Gohr ORDER BY cnt DESC, B.country". 286*95eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 287*95eb68e6SAndreas Gohr return $this->runSQL($sql); 288*95eb68e6SAndreas Gohr } 289*95eb68e6SAndreas Gohr 290*95eb68e6SAndreas Gohr /** 291*95eb68e6SAndreas Gohr * Builds a limit clause 292*95eb68e6SAndreas Gohr */ 293*95eb68e6SAndreas Gohr function sql_limit($start,$limit){ 294*95eb68e6SAndreas Gohr $start = (int) $start; 295*95eb68e6SAndreas Gohr $limit = (int) $limit; 296*95eb68e6SAndreas Gohr if($limit){ 297*95eb68e6SAndreas Gohr return " LIMIT $start,$limit"; 298*95eb68e6SAndreas Gohr }elseif($start){ 299*95eb68e6SAndreas Gohr return " OFFSET $start"; 300*95eb68e6SAndreas Gohr } 301*95eb68e6SAndreas Gohr return ''; 302*95eb68e6SAndreas Gohr } 3031878f16fSAndreas Gohr 3041878f16fSAndreas Gohr /** 30514d99ec0SAndreas Gohr * Return a link to the DB, opening the connection if needed 3061878f16fSAndreas Gohr */ 30714d99ec0SAndreas Gohr function dbLink(){ 3081878f16fSAndreas Gohr // connect to DB if needed 3091878f16fSAndreas Gohr if(!$this->dblink){ 3101878f16fSAndreas Gohr $this->dblink = mysql_connect($this->getConf('db_server'), 3111878f16fSAndreas Gohr $this->getConf('db_user'), 3121878f16fSAndreas Gohr $this->getConf('db_password')); 3131878f16fSAndreas Gohr if(!$this->dblink){ 3141878f16fSAndreas Gohr msg('DB Error: connection failed',-1); 3151878f16fSAndreas Gohr return null; 3161878f16fSAndreas Gohr } 3171878f16fSAndreas Gohr // set utf-8 3181878f16fSAndreas Gohr if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){ 3191878f16fSAndreas Gohr msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1); 3201878f16fSAndreas Gohr return null; 3211878f16fSAndreas Gohr } 3221878f16fSAndreas Gohr } 32314d99ec0SAndreas Gohr return $this->dblink; 32414d99ec0SAndreas Gohr } 3251878f16fSAndreas Gohr 32614d99ec0SAndreas Gohr /** 32714d99ec0SAndreas Gohr * Simple function to run a DB query 32814d99ec0SAndreas Gohr */ 32914d99ec0SAndreas Gohr function runSQL($sql_string) { 33014d99ec0SAndreas Gohr $link = $this->dbLink(); 33114d99ec0SAndreas Gohr 33214d99ec0SAndreas Gohr $result = mysql_db_query($this->conf['db_database'],$sql_string,$link); 33394171ff3SAndreas Gohr if(!$result){ 33414d99ec0SAndreas Gohr msg('DB Error: '.mysql_error($link),-1); 3351878f16fSAndreas Gohr return null; 3361878f16fSAndreas Gohr } 3371878f16fSAndreas Gohr 3381878f16fSAndreas Gohr $resultarray = array(); 3391878f16fSAndreas Gohr 3401878f16fSAndreas Gohr //mysql_db_query returns 1 on a insert statement -> no need to ask for results 3411878f16fSAndreas Gohr if ($result != 1) { 3421878f16fSAndreas Gohr for($i=0; $i< mysql_num_rows($result); $i++) { 3431878f16fSAndreas Gohr $temparray = mysql_fetch_assoc($result); 3441878f16fSAndreas Gohr $resultarray[]=$temparray; 3451878f16fSAndreas Gohr } 3461878f16fSAndreas Gohr mysql_free_result($result); 3471878f16fSAndreas Gohr } 3481878f16fSAndreas Gohr 34914d99ec0SAndreas Gohr if (mysql_insert_id($link)) { 35014d99ec0SAndreas Gohr $resultarray = mysql_insert_id($link); //give back ID on insert 3511878f16fSAndreas Gohr } 3521878f16fSAndreas Gohr 3531878f16fSAndreas Gohr return $resultarray; 3541878f16fSAndreas Gohr } 3551878f16fSAndreas Gohr 3561878f16fSAndreas Gohr /** 35714d99ec0SAndreas Gohr * Returns a short name for a User Agent and sets type, version and os info 3581878f16fSAndreas Gohr */ 35914d99ec0SAndreas Gohr function ua_info($ua,&$type,&$ver,&$os){ 36014d99ec0SAndreas Gohr $ua = strtr($ua,' +','__'); 36114d99ec0SAndreas Gohr $ua = strtolower($ua); 36214d99ec0SAndreas Gohr 36314d99ec0SAndreas Gohr // common browsers 36414d99ec0SAndreas Gohr $regvermsie = '/msie([+_ ]|)([\d\.]*)/i'; 36514d99ec0SAndreas Gohr $regvernetscape = '/netscape.?\/([\d\.]*)/i'; 36614d99ec0SAndreas Gohr $regverfirefox = '/firefox\/([\d\.]*)/i'; 36714d99ec0SAndreas Gohr $regversvn = '/svn\/([\d\.]*)/i'; 36814d99ec0SAndreas Gohr $regvermozilla = '/mozilla(\/|)([\d\.]*)/i'; 36914d99ec0SAndreas Gohr $regnotie = '/webtv|omniweb|opera/i'; 37014d99ec0SAndreas Gohr $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i'; 37114d99ec0SAndreas Gohr 37214d99ec0SAndreas Gohr $name = ''; 37314d99ec0SAndreas Gohr # IE ? 37414d99ec0SAndreas Gohr if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){ 37514d99ec0SAndreas Gohr $type = 'browser'; 37614d99ec0SAndreas Gohr $ver = $m[2]; 37714d99ec0SAndreas Gohr $name = 'msie'; 37814d99ec0SAndreas Gohr } 37914d99ec0SAndreas Gohr # Firefox ? 38014d99ec0SAndreas Gohr elseif (preg_match($regverfirefox,$ua,$m)){ 38114d99ec0SAndreas Gohr $type = 'browser'; 38214d99ec0SAndreas Gohr $ver = $m[1]; 38314d99ec0SAndreas Gohr $name = 'firefox'; 38414d99ec0SAndreas Gohr } 38514d99ec0SAndreas Gohr # Subversion ? 38614d99ec0SAndreas Gohr elseif (preg_match($regversvn,$ua,$m)){ 38714d99ec0SAndreas Gohr $type = 'rcs'; 38814d99ec0SAndreas Gohr $ver = $m[1]; 38914d99ec0SAndreas Gohr $name = 'svn'; 39014d99ec0SAndreas Gohr } 39114d99ec0SAndreas Gohr # Netscape 6.x, 7.x ... ? 39214d99ec0SAndreas Gohr elseif (preg_match($regvernetscape,$ua,$m)){ 39314d99ec0SAndreas Gohr $type = 'browser'; 39414d99ec0SAndreas Gohr $ver = $m[1]; 39514d99ec0SAndreas Gohr $name = 'netscape'; 39614d99ec0SAndreas Gohr } 39714d99ec0SAndreas Gohr # Netscape 3.x, 4.x ... ? 39814d99ec0SAndreas Gohr elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){ 39914d99ec0SAndreas Gohr $type = 'browser'; 40014d99ec0SAndreas Gohr $ver = $m[2]; 40114d99ec0SAndreas Gohr $name = 'netscape'; 40214d99ec0SAndreas Gohr }else{ 40314d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/browsers.php'); 40414d99ec0SAndreas Gohr foreach($BrowsersSearchIDOrder as $regex){ 40514d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 40614d99ec0SAndreas Gohr // it's a browser! 40714d99ec0SAndreas Gohr $type = 'browser'; 40814d99ec0SAndreas Gohr $name = strtolower($regex); 40914d99ec0SAndreas Gohr break; 41014d99ec0SAndreas Gohr } 41114d99ec0SAndreas Gohr } 41214d99ec0SAndreas Gohr } 41314d99ec0SAndreas Gohr 41414d99ec0SAndreas Gohr // check OS for browsers 41514d99ec0SAndreas Gohr if($type == 'browser'){ 41614d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/operating_systems.php'); 41714d99ec0SAndreas Gohr foreach($OSSearchIDOrder as $regex){ 41814d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 41914d99ec0SAndreas Gohr $os = $OSHashID[$regex]; 42014d99ec0SAndreas Gohr break; 42114d99ec0SAndreas Gohr } 42214d99ec0SAndreas Gohr } 42314d99ec0SAndreas Gohr 42414d99ec0SAndreas Gohr } 42514d99ec0SAndreas Gohr 42614d99ec0SAndreas Gohr // are we done now? 42714d99ec0SAndreas Gohr if($name) return $name; 42814d99ec0SAndreas Gohr 42914d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/robots.php'); 43014d99ec0SAndreas Gohr foreach($RobotsSearchIDOrder as $regex){ 43114d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 43214d99ec0SAndreas Gohr // it's a robot! 43314d99ec0SAndreas Gohr $type = 'robot'; 43414d99ec0SAndreas Gohr return strtolower($regex); 43514d99ec0SAndreas Gohr } 43614d99ec0SAndreas Gohr } 43714d99ec0SAndreas Gohr 43814d99ec0SAndreas Gohr // dunno 4391878f16fSAndreas Gohr return ''; 4401878f16fSAndreas Gohr } 4411878f16fSAndreas Gohr 4421878f16fSAndreas Gohr /** 44314d99ec0SAndreas Gohr * 44414d99ec0SAndreas Gohr * @fixme: put search engine queries in seperate table here 44514d99ec0SAndreas Gohr */ 44614d99ec0SAndreas Gohr function log_search($referer,&$type){ 44714d99ec0SAndreas Gohr $referer = strtr($referer,' +','__'); 44814d99ec0SAndreas Gohr $referer = strtolower($referer); 44914d99ec0SAndreas Gohr 45014d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/search_engines.php'); 45114d99ec0SAndreas Gohr 45214d99ec0SAndreas Gohr foreach($SearchEnginesSearchIDOrder as $regex){ 45314d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$referer)){ 45414d99ec0SAndreas Gohr if(!$NotSearchEnginesKeys[$regex] || 45514d99ec0SAndreas Gohr !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$referer)){ 45614d99ec0SAndreas Gohr // it's a search engine! 45714d99ec0SAndreas Gohr $type = 'search'; 45814d99ec0SAndreas Gohr break; 45914d99ec0SAndreas Gohr } 46014d99ec0SAndreas Gohr } 46114d99ec0SAndreas Gohr } 46214d99ec0SAndreas Gohr if($type != 'search') return; // we're done here 46314d99ec0SAndreas Gohr 46414d99ec0SAndreas Gohr #fixme now do the keyword magic! 46514d99ec0SAndreas Gohr } 46614d99ec0SAndreas Gohr 46714d99ec0SAndreas Gohr /** 46814d99ec0SAndreas Gohr * Resolve IP to country/city 46914d99ec0SAndreas Gohr */ 47014d99ec0SAndreas Gohr function log_ip($ip){ 47114d99ec0SAndreas Gohr // check if IP already known and up-to-date 47214d99ec0SAndreas Gohr $sql = "SELECT ip 47314d99ec0SAndreas Gohr FROM ".$this->getConf('db_prefix')."iplocation 47414d99ec0SAndreas Gohr WHERE ip ='".addslashes($ip)."' 47514d99ec0SAndreas Gohr AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)"; 47614d99ec0SAndreas Gohr $result = $this->runSQL($sql); 47714d99ec0SAndreas Gohr if($result[0]['ip']) return; 47814d99ec0SAndreas Gohr 47914d99ec0SAndreas Gohr $http = new DokuHTTPClient(); 48014d99ec0SAndreas Gohr $http->timeout = 10; 48114d99ec0SAndreas Gohr $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip); 48214d99ec0SAndreas Gohr 48314d99ec0SAndreas Gohr if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){ 48414d99ec0SAndreas Gohr $country = addslashes(trim($match[1])); 48514d99ec0SAndreas Gohr $code = addslashes(strtolower(trim($match[2]))); 48614d99ec0SAndreas Gohr $city = addslashes(trim($match[3])); 48714d99ec0SAndreas Gohr $host = addslashes(gethostbyaddr($ip)); 48814d99ec0SAndreas Gohr $ip = addslashes($ip); 48914d99ec0SAndreas Gohr 49014d99ec0SAndreas Gohr $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation 49114d99ec0SAndreas Gohr SET ip = '$ip', 49214d99ec0SAndreas Gohr country = '$country', 49314d99ec0SAndreas Gohr code = '$code', 49414d99ec0SAndreas Gohr city = '$city', 49514d99ec0SAndreas Gohr host = '$host'"; 49614d99ec0SAndreas Gohr $this->runSQL($sql); 49714d99ec0SAndreas Gohr } 49814d99ec0SAndreas Gohr } 49914d99ec0SAndreas Gohr 50014d99ec0SAndreas Gohr /** 5011878f16fSAndreas Gohr * log a page access 5021878f16fSAndreas Gohr * 5031878f16fSAndreas Gohr * called from log.php 5041878f16fSAndreas Gohr */ 5051878f16fSAndreas Gohr function log_access(){ 50694171ff3SAndreas Gohr if(!$_REQUEST['p']) return; 50794171ff3SAndreas Gohr 50814d99ec0SAndreas Gohr # FIXME check referer against blacklist and drop logging for bad boys 50914d99ec0SAndreas Gohr 51014d99ec0SAndreas Gohr // handle referer 51114d99ec0SAndreas Gohr $referer = trim($_REQUEST['r']); 51214d99ec0SAndreas Gohr if($referer){ 51314d99ec0SAndreas Gohr $ref = addslashes($referer); 51414d99ec0SAndreas Gohr $ref_md5 = ($ref) ? md5($referer) : ''; 51514d99ec0SAndreas Gohr if(strpos($referer,DOKU_URL) === 0){ 51614d99ec0SAndreas Gohr $ref_type = 'internal'; 51714d99ec0SAndreas Gohr }else{ 51814d99ec0SAndreas Gohr $ref_type = 'external'; 51914d99ec0SAndreas Gohr $this->log_search($referer,$ref_type); 52014d99ec0SAndreas Gohr } 52114d99ec0SAndreas Gohr }else{ 52214d99ec0SAndreas Gohr $ref = ''; 52314d99ec0SAndreas Gohr $ref_md5 = ''; 52414d99ec0SAndreas Gohr $ref_type = ''; 52514d99ec0SAndreas Gohr } 52614d99ec0SAndreas Gohr 52714d99ec0SAndreas Gohr // handle user agent 52814d99ec0SAndreas Gohr $agent = trim($_SERVER['HTTP_USER_AGENT']); 52914d99ec0SAndreas Gohr 53014d99ec0SAndreas Gohr $ua = addslashes($agent); 53114d99ec0SAndreas Gohr $ua_type = ''; 53214d99ec0SAndreas Gohr $ua_ver = ''; 53314d99ec0SAndreas Gohr $os = ''; 53414d99ec0SAndreas Gohr $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os)); 53514d99ec0SAndreas Gohr 5361878f16fSAndreas Gohr $page = addslashes($_REQUEST['p']); 5371878f16fSAndreas Gohr $ip = addslashes($_SERVER['REMOTE_ADDR']); 5381878f16fSAndreas Gohr $sx = (int) $_REQUEST['sx']; 5391878f16fSAndreas Gohr $sy = (int) $_REQUEST['sy']; 5401878f16fSAndreas Gohr $vx = (int) $_REQUEST['vx']; 5411878f16fSAndreas Gohr $vy = (int) $_REQUEST['vy']; 5421878f16fSAndreas Gohr $user = addslashes($_SERVER['REMOTE_USER']); 5431878f16fSAndreas Gohr $session = addslashes(session_id()); 5441878f16fSAndreas Gohr 54594171ff3SAndreas Gohr $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access 5461878f16fSAndreas Gohr SET page = '$page', 5471878f16fSAndreas Gohr ip = '$ip', 5481878f16fSAndreas Gohr ua = '$ua', 5491878f16fSAndreas Gohr ua_info = '$ua_info', 55014d99ec0SAndreas Gohr ua_type = '$ua_type', 55114d99ec0SAndreas Gohr ua_ver = '$ua_ver', 55214d99ec0SAndreas Gohr os = '$os', 5531878f16fSAndreas Gohr ref = '$ref', 55494171ff3SAndreas Gohr ref_md5 = '$ref_md5', 55514d99ec0SAndreas Gohr ref_type = '$ref_type', 5561878f16fSAndreas Gohr screen_x = '$sx', 5571878f16fSAndreas Gohr screen_y = '$sy', 5581878f16fSAndreas Gohr view_x = '$vx', 5591878f16fSAndreas Gohr view_y = '$vy', 5601878f16fSAndreas Gohr user = '$user', 5611878f16fSAndreas Gohr session = '$session'"; 5621878f16fSAndreas Gohr $ok = $this->runSQL($sql); 5631878f16fSAndreas Gohr if(is_null($ok)){ 5641878f16fSAndreas Gohr global $MSG; 5651878f16fSAndreas Gohr print_r($MSG); 5661878f16fSAndreas Gohr } 56714d99ec0SAndreas Gohr 56814d99ec0SAndreas Gohr // resolve the IP 56914d99ec0SAndreas Gohr $this->log_ip($_SERVER['REMOTE_ADDR']); 5701878f16fSAndreas Gohr } 5711878f16fSAndreas Gohr 5721878f16fSAndreas Gohr /** 5731878f16fSAndreas Gohr * Just send a 1x1 pixel blank gif to the browser 5741878f16fSAndreas Gohr * 5751878f16fSAndreas Gohr * @called from log.php 5761878f16fSAndreas Gohr * 5771878f16fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 5781878f16fSAndreas Gohr * @author Harry Fuecks <fuecks@gmail.com> 5791878f16fSAndreas Gohr */ 5801878f16fSAndreas Gohr function sendGIF(){ 5811878f16fSAndreas Gohr $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); 5821878f16fSAndreas Gohr header('Content-Type: image/gif'); 5831878f16fSAndreas Gohr header('Content-Length: '.strlen($img)); 5841878f16fSAndreas Gohr header('Connection: Close'); 5851878f16fSAndreas Gohr print $img; 5861878f16fSAndreas Gohr flush(); 5871878f16fSAndreas Gohr // Browser should drop connection after this 5881878f16fSAndreas Gohr // Thinks it's got the whole image 5891878f16fSAndreas Gohr } 5901878f16fSAndreas Gohr 5911878f16fSAndreas Gohr} 592