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 = ''; 2495eb68e6SAndreas 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']); 5395eb68e6SAndreas Gohr 5495eb68e6SAndreas Gohr $this->start = (int) $_REQUEST['s']; 5595eb68e6SAndreas 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() { 74*9da6395dSAndreas Gohr $this->html_toc(); 75264f1744SAndreas Gohr echo '<h1>Access Statistics</h1>'; 76264f1744SAndreas Gohr $this->html_timeselect(); 77264f1744SAndreas Gohr 78264f1744SAndreas Gohr switch($this->opt){ 79*9da6395dSAndreas Gohr case 'country': 80*9da6395dSAndreas Gohr $this->html_country(); 81*9da6395dSAndreas Gohr break; 82*9da6395dSAndreas Gohr case 'page': 83*9da6395dSAndreas Gohr $this->html_page(); 84*9da6395dSAndreas Gohr break; 85*9da6395dSAndreas Gohr case 'referer': 86*9da6395dSAndreas Gohr $this->html_referer(); 87*9da6395dSAndreas Gohr break; 8814d99ec0SAndreas Gohr default: 89*9da6395dSAndreas Gohr $this->html_dashboard(); 9014d99ec0SAndreas Gohr } 9114d99ec0SAndreas Gohr } 9214d99ec0SAndreas Gohr 93*9da6395dSAndreas Gohr function html_toc(){ 94*9da6395dSAndreas Gohr echo '<div class="toc">'; 95*9da6395dSAndreas Gohr echo '<div class="tocheader toctoggle" id="toc__header">'; 96*9da6395dSAndreas Gohr echo 'Detailed Statistics'; 97*9da6395dSAndreas Gohr echo '</div>'; 98*9da6395dSAndreas Gohr echo '<div id="toc__inside">'; 99*9da6395dSAndreas Gohr echo '<ul class="toc">'; 100*9da6395dSAndreas Gohr 101*9da6395dSAndreas Gohr echo '<li><div class="li">'; 102*9da6395dSAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=&f='.$this->from.'&t='.$this->to.'&s='.$this->start.'">Dashboard</a>'; 103*9da6395dSAndreas Gohr echo '</div></li>'; 104*9da6395dSAndreas Gohr 105*9da6395dSAndreas Gohr echo '<li><div class="li">'; 106*9da6395dSAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'&s='.$this->start.'">Pages</a>'; 107*9da6395dSAndreas Gohr echo '</div></li>'; 108*9da6395dSAndreas Gohr 109*9da6395dSAndreas Gohr echo '<li><div class="li">'; 110*9da6395dSAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=referer&f='.$this->from.'&t='.$this->to.'&s='.$this->start.'">Incoming Links</a>'; 111*9da6395dSAndreas Gohr echo '</div></li>'; 112*9da6395dSAndreas Gohr 113*9da6395dSAndreas Gohr echo '<li><div class="li">'; 114*9da6395dSAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=country&f='.$this->from.'&t='.$this->to.'&s='.$this->start.'">Countries</a>'; 115*9da6395dSAndreas Gohr echo '</div></li>'; 116*9da6395dSAndreas Gohr 117*9da6395dSAndreas Gohr echo '</ul>'; 118*9da6395dSAndreas Gohr echo '</div>'; 119*9da6395dSAndreas Gohr echo '</div>'; 120*9da6395dSAndreas Gohr } 121*9da6395dSAndreas Gohr 122264f1744SAndreas Gohr /** 123264f1744SAndreas Gohr * Print the time selection menu 124264f1744SAndreas Gohr */ 12514d99ec0SAndreas Gohr function html_timeselect(){ 126264f1744SAndreas Gohr $now = date('Y-m-d'); 127264f1744SAndreas Gohr $yday = date('Y-m-d',time()-(60*60*24)); 128264f1744SAndreas Gohr $week = date('Y-m-d',time()-(60*60*24*7)); 129264f1744SAndreas Gohr $month = date('Y-m-d',time()-(60*60*24*30)); 13014d99ec0SAndreas Gohr 131264f1744SAndreas Gohr echo '<div class="plg_stats_timeselect">'; 132264f1744SAndreas Gohr echo '<span>Select the timeframe:</span>'; 133264f1744SAndreas Gohr echo '<ul>'; 134264f1744SAndreas Gohr 135264f1744SAndreas Gohr echo '<li>'; 13695eb68e6SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$now.'&t='.$now.'&s='.$this->start.'">'; 137264f1744SAndreas Gohr echo 'today'; 138264f1744SAndreas Gohr echo '</a>'; 139264f1744SAndreas Gohr echo '</li>'; 140264f1744SAndreas Gohr 141264f1744SAndreas Gohr echo '<li>'; 14295eb68e6SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$yday.'&t='.$yday.'&s='.$this->start.'">'; 143264f1744SAndreas Gohr echo 'yesterday'; 144264f1744SAndreas Gohr echo '</a>'; 145264f1744SAndreas Gohr echo '</li>'; 146264f1744SAndreas Gohr 147264f1744SAndreas Gohr echo '<li>'; 14895eb68e6SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$week.'&t='.$now.'&s='.$this->start.'">'; 149264f1744SAndreas Gohr echo 'last 7 days'; 150264f1744SAndreas Gohr echo '</a>'; 151264f1744SAndreas Gohr echo '</li>'; 152264f1744SAndreas Gohr 153264f1744SAndreas Gohr echo '<li>'; 15495eb68e6SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$month.'&t='.$now.'&s='.$this->start.'">'; 155264f1744SAndreas Gohr echo 'last 30 days'; 156264f1744SAndreas Gohr echo '</a>'; 157264f1744SAndreas Gohr echo '</li>'; 158264f1744SAndreas Gohr 159264f1744SAndreas Gohr echo '</ul>'; 160264f1744SAndreas Gohr 161264f1744SAndreas Gohr 162264f1744SAndreas Gohr echo '<form action="" method="get">'; 163264f1744SAndreas Gohr echo '<input type="hidden" name="do" value="admin" />'; 164264f1744SAndreas Gohr echo '<input type="hidden" name="page" value="statistics" />'; 165264f1744SAndreas Gohr echo '<input type="hidden" name="opt" value="'.$this->opt.'" />'; 16695eb68e6SAndreas Gohr echo '<input type="hidden" name="s" value="'.$this->start.'" />'; 167264f1744SAndreas Gohr echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />'; 168264f1744SAndreas Gohr echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />'; 169264f1744SAndreas Gohr echo '<input type="submit" value="go" class="button" />'; 17014d99ec0SAndreas Gohr echo '</form>'; 171264f1744SAndreas Gohr 172264f1744SAndreas Gohr echo '</div>'; 17314d99ec0SAndreas Gohr } 17414d99ec0SAndreas Gohr 17514d99ec0SAndreas Gohr 176f5f32cbfSAndreas Gohr /** 177f5f32cbfSAndreas Gohr * Print an introductionary screen 178f5f32cbfSAndreas Gohr */ 17914d99ec0SAndreas Gohr function html_dashboard(){ 180264f1744SAndreas Gohr echo '<div class="plg_stats_dashboard">'; 181264f1744SAndreas Gohr 18214d99ec0SAndreas Gohr 18387d5e44bSAndreas Gohr // top pages today 184264f1744SAndreas Gohr echo '<div>'; 185264f1744SAndreas Gohr echo '<h2>Most popular pages</h2>'; 18695eb68e6SAndreas Gohr $result = $this->sql_pages($this->tlimit,$this->start,15); 18787d5e44bSAndreas Gohr $this->html_resulttable($result,array('Pages','Count')); 188264f1744SAndreas Gohr echo '</div>'; 18987d5e44bSAndreas Gohr 19087d5e44bSAndreas Gohr // top referer today 191264f1744SAndreas Gohr echo '<div>'; 192264f1744SAndreas Gohr echo '<h2>Top incoming links</h2>'; 19395eb68e6SAndreas Gohr $result = $this->sql_referer($this->tlimit,$this->start,15); 19487d5e44bSAndreas Gohr $this->html_resulttable($result,array('Incoming Links','Count')); 195264f1744SAndreas Gohr echo '</div>'; 19654f6c432SAndreas Gohr 19754f6c432SAndreas Gohr // top countries today 198264f1744SAndreas Gohr echo '<div>'; 199264f1744SAndreas Gohr echo '<h2>Visitor\'s top countries</h2>'; 20095eb68e6SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&f='.$this->from.'&t='.$this->to.'" />'; 20195eb68e6SAndreas Gohr// $result = $this->sql_countries($this->tlimit,$this->start,15); 20295eb68e6SAndreas Gohr// $this->html_resulttable($result,array('','Countries','Count')); 203264f1744SAndreas Gohr echo '</div>'; 204264f1744SAndreas Gohr 205264f1744SAndreas Gohr echo '</div>'; 20614d99ec0SAndreas Gohr } 20714d99ec0SAndreas Gohr 208*9da6395dSAndreas Gohr function html_country(){ 209*9da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 210*9da6395dSAndreas Gohr echo '<h2>Visitor\'s Countries</h2>'; 211*9da6395dSAndreas Gohr $result = $this->sql_countries($this->tlimit,$this->start,150); 212*9da6395dSAndreas Gohr $this->html_resulttable($result,array('','Countries','Count')); 213*9da6395dSAndreas Gohr echo '</div>'; 214*9da6395dSAndreas Gohr } 215*9da6395dSAndreas Gohr 216*9da6395dSAndreas Gohr function html_page(){ 217*9da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 218*9da6395dSAndreas Gohr echo '<h2>Popular Pages</h2>'; 219*9da6395dSAndreas Gohr $result = $this->sql_pages($this->tlimit,$this->start,150); 220*9da6395dSAndreas Gohr $this->html_resulttable($result,array('Page','Count')); 221*9da6395dSAndreas Gohr echo '</div>'; 222*9da6395dSAndreas Gohr } 223*9da6395dSAndreas Gohr 224*9da6395dSAndreas Gohr function html_referer(){ 225*9da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 226*9da6395dSAndreas Gohr echo '<h2>Incoming Links</h2>'; 227*9da6395dSAndreas Gohr $result = $this->sql_referer($this->tlimit,$this->start,150); 228*9da6395dSAndreas Gohr $this->html_resulttable($result,array('Incoming Link','Count')); 229*9da6395dSAndreas Gohr echo '</div>'; 230*9da6395dSAndreas Gohr } 231*9da6395dSAndreas Gohr 232*9da6395dSAndreas Gohr 233*9da6395dSAndreas Gohr 23414d99ec0SAndreas Gohr /** 23514d99ec0SAndreas Gohr * Display a result in a HTML table 23614d99ec0SAndreas Gohr */ 23714d99ec0SAndreas Gohr function html_resulttable($result,$header){ 23814d99ec0SAndreas Gohr echo '<table>'; 23914d99ec0SAndreas Gohr echo '<tr>'; 24014d99ec0SAndreas Gohr foreach($header as $h){ 24114d99ec0SAndreas Gohr echo '<th>'.hsc($h).'</th>'; 24214d99ec0SAndreas Gohr } 24314d99ec0SAndreas Gohr echo '</tr>'; 24414d99ec0SAndreas Gohr 24514d99ec0SAndreas Gohr foreach($result as $row){ 24614d99ec0SAndreas Gohr echo '<tr>'; 24714d99ec0SAndreas Gohr foreach($row as $k => $v){ 24814d99ec0SAndreas Gohr echo '<td class="stats_'.$k.'">'; 24914d99ec0SAndreas Gohr if($k == 'page'){ 25014d99ec0SAndreas Gohr echo '<a href="'.wl($v).'" class="wikilink1">'; 25114d99ec0SAndreas Gohr echo hsc($v); 25214d99ec0SAndreas Gohr echo '</a>'; 25314d99ec0SAndreas Gohr }elseif($k == 'url'){ 25454f6c432SAndreas Gohr $url = hsc($v); 25554f6c432SAndreas Gohr if(strlen($url) > 50){ 25654f6c432SAndreas Gohr $url = substr($url,0,30).' … '.substr($url,-20); 25754f6c432SAndreas Gohr } 25814d99ec0SAndreas Gohr echo '<a href="'.$v.'" class="urlextern">'; 25954f6c432SAndreas Gohr echo $url; 26014d99ec0SAndreas Gohr echo '</a>'; 26114d99ec0SAndreas Gohr }elseif($k == 'html'){ 26214d99ec0SAndreas Gohr echo $v; 263f5f32cbfSAndreas Gohr }elseif($k == 'cflag'){ 26495eb68e6SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12"/>'; 26514d99ec0SAndreas Gohr }else{ 26614d99ec0SAndreas Gohr echo hsc($v); 26714d99ec0SAndreas Gohr } 26814d99ec0SAndreas Gohr echo '</td>'; 26914d99ec0SAndreas Gohr } 27014d99ec0SAndreas Gohr echo '</tr>'; 27114d99ec0SAndreas Gohr } 27214d99ec0SAndreas Gohr echo '</table>'; 2731878f16fSAndreas Gohr } 2741878f16fSAndreas Gohr 27595eb68e6SAndreas Gohr /** 27695eb68e6SAndreas Gohr * Create an image 27795eb68e6SAndreas Gohr */ 27895eb68e6SAndreas Gohr function img_build($img){ 27995eb68e6SAndreas Gohr include(dirname(__FILE__).'/inc/AGC.class.php'); 28095eb68e6SAndreas Gohr 28195eb68e6SAndreas Gohr switch($img){ 28295eb68e6SAndreas Gohr case 'country': 28395eb68e6SAndreas Gohr // build top countries + other 28495eb68e6SAndreas Gohr $result = $this->sql_countries($this->tlimit,$this->start,0); 28595eb68e6SAndreas Gohr $data = array(); 28695eb68e6SAndreas Gohr $top = 0; 28795eb68e6SAndreas Gohr foreach($result as $row){ 28895eb68e6SAndreas Gohr if($top < 7){ 28995eb68e6SAndreas Gohr $data[$row['country']] = $row['cnt']; 29095eb68e6SAndreas Gohr }else{ 29195eb68e6SAndreas Gohr $data['other'] += $row['cnt']; 29295eb68e6SAndreas Gohr } 29395eb68e6SAndreas Gohr $top++; 29495eb68e6SAndreas Gohr } 29595eb68e6SAndreas Gohr $pie = new AGC(300, 200); 29695eb68e6SAndreas Gohr $pie->setProp("showkey",true); 29795eb68e6SAndreas Gohr $pie->setProp("showval",false); 29895eb68e6SAndreas Gohr $pie->setProp("showgrid",false); 29995eb68e6SAndreas Gohr $pie->setProp("type","pie"); 30095eb68e6SAndreas Gohr $pie->setProp("keyinfo",1); 30195eb68e6SAndreas Gohr $pie->setProp("keysize",8); 30295eb68e6SAndreas Gohr $pie->setProp("keywidspc",-50); 30395eb68e6SAndreas Gohr $pie->setProp("key",array_keys($data)); 30495eb68e6SAndreas Gohr $pie->addBulkPoints(array_values($data)); 30595eb68e6SAndreas Gohr @$pie->graph(); 30695eb68e6SAndreas Gohr $pie->showGraph(); 30795eb68e6SAndreas Gohr break; 30895eb68e6SAndreas Gohr default: 30995eb68e6SAndreas Gohr $this->sendGIF(); 31095eb68e6SAndreas Gohr } 31195eb68e6SAndreas Gohr } 31295eb68e6SAndreas Gohr 31395eb68e6SAndreas Gohr 31495eb68e6SAndreas Gohr function sql_pages($tlimit,$start=0,$limit=20){ 31595eb68e6SAndreas Gohr $sql = "SELECT page, COUNT(*) as cnt 31695eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 31795eb68e6SAndreas Gohr WHERE $tlimit 31895eb68e6SAndreas Gohr AND ua_type = 'browser' 31995eb68e6SAndreas Gohr GROUP BY page 32095eb68e6SAndreas Gohr ORDER BY cnt DESC, page". 32195eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 32295eb68e6SAndreas Gohr return $this->runSQL($sql); 32395eb68e6SAndreas Gohr } 32495eb68e6SAndreas Gohr 32595eb68e6SAndreas Gohr function sql_referer($tlimit,$start=0,$limit=20){ 32695eb68e6SAndreas Gohr $sql = "SELECT ref as url, COUNT(*) as cnt 32795eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 32895eb68e6SAndreas Gohr WHERE $tlimit 32995eb68e6SAndreas Gohr AND ua_type = 'browser' 33095eb68e6SAndreas Gohr AND ref_type = 'external' 33195eb68e6SAndreas Gohr GROUP BY ref_md5 33295eb68e6SAndreas Gohr ORDER BY cnt DESC, url". 33395eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 33495eb68e6SAndreas Gohr return $this->runSQL($sql); 33595eb68e6SAndreas Gohr } 33695eb68e6SAndreas Gohr 33795eb68e6SAndreas Gohr function sql_countries($tlimit,$start=0,$limit=20){ 33895eb68e6SAndreas Gohr $sql = "SELECT B.code AS cflag, B.country, COUNT(*) as cnt 33995eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A, 34095eb68e6SAndreas Gohr ".$this->getConf('db_prefix')."iplocation as B 34195eb68e6SAndreas Gohr WHERE $tlimit 34295eb68e6SAndreas Gohr AND A.ip = B.ip 34395eb68e6SAndreas Gohr GROUP BY B.country 34495eb68e6SAndreas Gohr ORDER BY cnt DESC, B.country". 34595eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 34695eb68e6SAndreas Gohr return $this->runSQL($sql); 34795eb68e6SAndreas Gohr } 34895eb68e6SAndreas Gohr 34995eb68e6SAndreas Gohr /** 35095eb68e6SAndreas Gohr * Builds a limit clause 35195eb68e6SAndreas Gohr */ 35295eb68e6SAndreas Gohr function sql_limit($start,$limit){ 35395eb68e6SAndreas Gohr $start = (int) $start; 35495eb68e6SAndreas Gohr $limit = (int) $limit; 35595eb68e6SAndreas Gohr if($limit){ 35695eb68e6SAndreas Gohr return " LIMIT $start,$limit"; 35795eb68e6SAndreas Gohr }elseif($start){ 35895eb68e6SAndreas Gohr return " OFFSET $start"; 35995eb68e6SAndreas Gohr } 36095eb68e6SAndreas Gohr return ''; 36195eb68e6SAndreas Gohr } 3621878f16fSAndreas Gohr 3631878f16fSAndreas Gohr /** 36414d99ec0SAndreas Gohr * Return a link to the DB, opening the connection if needed 3651878f16fSAndreas Gohr */ 36614d99ec0SAndreas Gohr function dbLink(){ 3671878f16fSAndreas Gohr // connect to DB if needed 3681878f16fSAndreas Gohr if(!$this->dblink){ 3691878f16fSAndreas Gohr $this->dblink = mysql_connect($this->getConf('db_server'), 3701878f16fSAndreas Gohr $this->getConf('db_user'), 3711878f16fSAndreas Gohr $this->getConf('db_password')); 3721878f16fSAndreas Gohr if(!$this->dblink){ 3731878f16fSAndreas Gohr msg('DB Error: connection failed',-1); 3741878f16fSAndreas Gohr return null; 3751878f16fSAndreas Gohr } 3761878f16fSAndreas Gohr // set utf-8 3771878f16fSAndreas Gohr if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){ 3781878f16fSAndreas Gohr msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1); 3791878f16fSAndreas Gohr return null; 3801878f16fSAndreas Gohr } 3811878f16fSAndreas Gohr } 38214d99ec0SAndreas Gohr return $this->dblink; 38314d99ec0SAndreas Gohr } 3841878f16fSAndreas Gohr 38514d99ec0SAndreas Gohr /** 38614d99ec0SAndreas Gohr * Simple function to run a DB query 38714d99ec0SAndreas Gohr */ 38814d99ec0SAndreas Gohr function runSQL($sql_string) { 38914d99ec0SAndreas Gohr $link = $this->dbLink(); 39014d99ec0SAndreas Gohr 39114d99ec0SAndreas Gohr $result = mysql_db_query($this->conf['db_database'],$sql_string,$link); 39294171ff3SAndreas Gohr if(!$result){ 39314d99ec0SAndreas Gohr msg('DB Error: '.mysql_error($link),-1); 3941878f16fSAndreas Gohr return null; 3951878f16fSAndreas Gohr } 3961878f16fSAndreas Gohr 3971878f16fSAndreas Gohr $resultarray = array(); 3981878f16fSAndreas Gohr 3991878f16fSAndreas Gohr //mysql_db_query returns 1 on a insert statement -> no need to ask for results 4001878f16fSAndreas Gohr if ($result != 1) { 4011878f16fSAndreas Gohr for($i=0; $i< mysql_num_rows($result); $i++) { 4021878f16fSAndreas Gohr $temparray = mysql_fetch_assoc($result); 4031878f16fSAndreas Gohr $resultarray[]=$temparray; 4041878f16fSAndreas Gohr } 4051878f16fSAndreas Gohr mysql_free_result($result); 4061878f16fSAndreas Gohr } 4071878f16fSAndreas Gohr 40814d99ec0SAndreas Gohr if (mysql_insert_id($link)) { 40914d99ec0SAndreas Gohr $resultarray = mysql_insert_id($link); //give back ID on insert 4101878f16fSAndreas Gohr } 4111878f16fSAndreas Gohr 4121878f16fSAndreas Gohr return $resultarray; 4131878f16fSAndreas Gohr } 4141878f16fSAndreas Gohr 4151878f16fSAndreas Gohr /** 41614d99ec0SAndreas Gohr * Returns a short name for a User Agent and sets type, version and os info 4171878f16fSAndreas Gohr */ 41814d99ec0SAndreas Gohr function ua_info($ua,&$type,&$ver,&$os){ 41914d99ec0SAndreas Gohr $ua = strtr($ua,' +','__'); 42014d99ec0SAndreas Gohr $ua = strtolower($ua); 42114d99ec0SAndreas Gohr 42214d99ec0SAndreas Gohr // common browsers 42314d99ec0SAndreas Gohr $regvermsie = '/msie([+_ ]|)([\d\.]*)/i'; 42414d99ec0SAndreas Gohr $regvernetscape = '/netscape.?\/([\d\.]*)/i'; 42514d99ec0SAndreas Gohr $regverfirefox = '/firefox\/([\d\.]*)/i'; 42614d99ec0SAndreas Gohr $regversvn = '/svn\/([\d\.]*)/i'; 42714d99ec0SAndreas Gohr $regvermozilla = '/mozilla(\/|)([\d\.]*)/i'; 42814d99ec0SAndreas Gohr $regnotie = '/webtv|omniweb|opera/i'; 42914d99ec0SAndreas Gohr $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i'; 43014d99ec0SAndreas Gohr 43114d99ec0SAndreas Gohr $name = ''; 43214d99ec0SAndreas Gohr # IE ? 43314d99ec0SAndreas Gohr if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){ 43414d99ec0SAndreas Gohr $type = 'browser'; 43514d99ec0SAndreas Gohr $ver = $m[2]; 43614d99ec0SAndreas Gohr $name = 'msie'; 43714d99ec0SAndreas Gohr } 43814d99ec0SAndreas Gohr # Firefox ? 43914d99ec0SAndreas Gohr elseif (preg_match($regverfirefox,$ua,$m)){ 44014d99ec0SAndreas Gohr $type = 'browser'; 44114d99ec0SAndreas Gohr $ver = $m[1]; 44214d99ec0SAndreas Gohr $name = 'firefox'; 44314d99ec0SAndreas Gohr } 44414d99ec0SAndreas Gohr # Subversion ? 44514d99ec0SAndreas Gohr elseif (preg_match($regversvn,$ua,$m)){ 44614d99ec0SAndreas Gohr $type = 'rcs'; 44714d99ec0SAndreas Gohr $ver = $m[1]; 44814d99ec0SAndreas Gohr $name = 'svn'; 44914d99ec0SAndreas Gohr } 45014d99ec0SAndreas Gohr # Netscape 6.x, 7.x ... ? 45114d99ec0SAndreas Gohr elseif (preg_match($regvernetscape,$ua,$m)){ 45214d99ec0SAndreas Gohr $type = 'browser'; 45314d99ec0SAndreas Gohr $ver = $m[1]; 45414d99ec0SAndreas Gohr $name = 'netscape'; 45514d99ec0SAndreas Gohr } 45614d99ec0SAndreas Gohr # Netscape 3.x, 4.x ... ? 45714d99ec0SAndreas Gohr elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){ 45814d99ec0SAndreas Gohr $type = 'browser'; 45914d99ec0SAndreas Gohr $ver = $m[2]; 46014d99ec0SAndreas Gohr $name = 'netscape'; 46114d99ec0SAndreas Gohr }else{ 46214d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/browsers.php'); 46314d99ec0SAndreas Gohr foreach($BrowsersSearchIDOrder as $regex){ 46414d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 46514d99ec0SAndreas Gohr // it's a browser! 46614d99ec0SAndreas Gohr $type = 'browser'; 46714d99ec0SAndreas Gohr $name = strtolower($regex); 46814d99ec0SAndreas Gohr break; 46914d99ec0SAndreas Gohr } 47014d99ec0SAndreas Gohr } 47114d99ec0SAndreas Gohr } 47214d99ec0SAndreas Gohr 47314d99ec0SAndreas Gohr // check OS for browsers 47414d99ec0SAndreas Gohr if($type == 'browser'){ 47514d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/operating_systems.php'); 47614d99ec0SAndreas Gohr foreach($OSSearchIDOrder as $regex){ 47714d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 47814d99ec0SAndreas Gohr $os = $OSHashID[$regex]; 47914d99ec0SAndreas Gohr break; 48014d99ec0SAndreas Gohr } 48114d99ec0SAndreas Gohr } 48214d99ec0SAndreas Gohr 48314d99ec0SAndreas Gohr } 48414d99ec0SAndreas Gohr 48514d99ec0SAndreas Gohr // are we done now? 48614d99ec0SAndreas Gohr if($name) return $name; 48714d99ec0SAndreas Gohr 48814d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/robots.php'); 48914d99ec0SAndreas Gohr foreach($RobotsSearchIDOrder as $regex){ 49014d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 49114d99ec0SAndreas Gohr // it's a robot! 49214d99ec0SAndreas Gohr $type = 'robot'; 49314d99ec0SAndreas Gohr return strtolower($regex); 49414d99ec0SAndreas Gohr } 49514d99ec0SAndreas Gohr } 49614d99ec0SAndreas Gohr 49714d99ec0SAndreas Gohr // dunno 4981878f16fSAndreas Gohr return ''; 4991878f16fSAndreas Gohr } 5001878f16fSAndreas Gohr 5011878f16fSAndreas Gohr /** 50214d99ec0SAndreas Gohr * 50314d99ec0SAndreas Gohr * @fixme: put search engine queries in seperate table here 50414d99ec0SAndreas Gohr */ 50514d99ec0SAndreas Gohr function log_search($referer,&$type){ 50614d99ec0SAndreas Gohr $referer = strtr($referer,' +','__'); 50714d99ec0SAndreas Gohr $referer = strtolower($referer); 50814d99ec0SAndreas Gohr 50914d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/search_engines.php'); 51014d99ec0SAndreas Gohr 51114d99ec0SAndreas Gohr foreach($SearchEnginesSearchIDOrder as $regex){ 51214d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$referer)){ 51314d99ec0SAndreas Gohr if(!$NotSearchEnginesKeys[$regex] || 51414d99ec0SAndreas Gohr !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$referer)){ 51514d99ec0SAndreas Gohr // it's a search engine! 51614d99ec0SAndreas Gohr $type = 'search'; 51714d99ec0SAndreas Gohr break; 51814d99ec0SAndreas Gohr } 51914d99ec0SAndreas Gohr } 52014d99ec0SAndreas Gohr } 52114d99ec0SAndreas Gohr if($type != 'search') return; // we're done here 52214d99ec0SAndreas Gohr 52314d99ec0SAndreas Gohr #fixme now do the keyword magic! 52414d99ec0SAndreas Gohr } 52514d99ec0SAndreas Gohr 52614d99ec0SAndreas Gohr /** 52714d99ec0SAndreas Gohr * Resolve IP to country/city 52814d99ec0SAndreas Gohr */ 52914d99ec0SAndreas Gohr function log_ip($ip){ 53014d99ec0SAndreas Gohr // check if IP already known and up-to-date 53114d99ec0SAndreas Gohr $sql = "SELECT ip 53214d99ec0SAndreas Gohr FROM ".$this->getConf('db_prefix')."iplocation 53314d99ec0SAndreas Gohr WHERE ip ='".addslashes($ip)."' 53414d99ec0SAndreas Gohr AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)"; 53514d99ec0SAndreas Gohr $result = $this->runSQL($sql); 53614d99ec0SAndreas Gohr if($result[0]['ip']) return; 53714d99ec0SAndreas Gohr 53814d99ec0SAndreas Gohr $http = new DokuHTTPClient(); 53914d99ec0SAndreas Gohr $http->timeout = 10; 54014d99ec0SAndreas Gohr $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip); 54114d99ec0SAndreas Gohr 54214d99ec0SAndreas Gohr if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){ 54314d99ec0SAndreas Gohr $country = addslashes(trim($match[1])); 54414d99ec0SAndreas Gohr $code = addslashes(strtolower(trim($match[2]))); 54514d99ec0SAndreas Gohr $city = addslashes(trim($match[3])); 54614d99ec0SAndreas Gohr $host = addslashes(gethostbyaddr($ip)); 54714d99ec0SAndreas Gohr $ip = addslashes($ip); 54814d99ec0SAndreas Gohr 54914d99ec0SAndreas Gohr $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation 55014d99ec0SAndreas Gohr SET ip = '$ip', 55114d99ec0SAndreas Gohr country = '$country', 55214d99ec0SAndreas Gohr code = '$code', 55314d99ec0SAndreas Gohr city = '$city', 55414d99ec0SAndreas Gohr host = '$host'"; 55514d99ec0SAndreas Gohr $this->runSQL($sql); 55614d99ec0SAndreas Gohr } 55714d99ec0SAndreas Gohr } 55814d99ec0SAndreas Gohr 55914d99ec0SAndreas Gohr /** 5601878f16fSAndreas Gohr * log a page access 5611878f16fSAndreas Gohr * 5621878f16fSAndreas Gohr * called from log.php 5631878f16fSAndreas Gohr */ 5641878f16fSAndreas Gohr function log_access(){ 56594171ff3SAndreas Gohr if(!$_REQUEST['p']) return; 56694171ff3SAndreas Gohr 56714d99ec0SAndreas Gohr # FIXME check referer against blacklist and drop logging for bad boys 56814d99ec0SAndreas Gohr 56914d99ec0SAndreas Gohr // handle referer 57014d99ec0SAndreas Gohr $referer = trim($_REQUEST['r']); 57114d99ec0SAndreas Gohr if($referer){ 57214d99ec0SAndreas Gohr $ref = addslashes($referer); 57314d99ec0SAndreas Gohr $ref_md5 = ($ref) ? md5($referer) : ''; 57414d99ec0SAndreas Gohr if(strpos($referer,DOKU_URL) === 0){ 57514d99ec0SAndreas Gohr $ref_type = 'internal'; 57614d99ec0SAndreas Gohr }else{ 57714d99ec0SAndreas Gohr $ref_type = 'external'; 57814d99ec0SAndreas Gohr $this->log_search($referer,$ref_type); 57914d99ec0SAndreas Gohr } 58014d99ec0SAndreas Gohr }else{ 58114d99ec0SAndreas Gohr $ref = ''; 58214d99ec0SAndreas Gohr $ref_md5 = ''; 58314d99ec0SAndreas Gohr $ref_type = ''; 58414d99ec0SAndreas Gohr } 58514d99ec0SAndreas Gohr 58614d99ec0SAndreas Gohr // handle user agent 58714d99ec0SAndreas Gohr $agent = trim($_SERVER['HTTP_USER_AGENT']); 58814d99ec0SAndreas Gohr 58914d99ec0SAndreas Gohr $ua = addslashes($agent); 59014d99ec0SAndreas Gohr $ua_type = ''; 59114d99ec0SAndreas Gohr $ua_ver = ''; 59214d99ec0SAndreas Gohr $os = ''; 59314d99ec0SAndreas Gohr $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os)); 59414d99ec0SAndreas Gohr 5951878f16fSAndreas Gohr $page = addslashes($_REQUEST['p']); 5961878f16fSAndreas Gohr $ip = addslashes($_SERVER['REMOTE_ADDR']); 5971878f16fSAndreas Gohr $sx = (int) $_REQUEST['sx']; 5981878f16fSAndreas Gohr $sy = (int) $_REQUEST['sy']; 5991878f16fSAndreas Gohr $vx = (int) $_REQUEST['vx']; 6001878f16fSAndreas Gohr $vy = (int) $_REQUEST['vy']; 6011878f16fSAndreas Gohr $user = addslashes($_SERVER['REMOTE_USER']); 6021878f16fSAndreas Gohr $session = addslashes(session_id()); 6031878f16fSAndreas Gohr 60494171ff3SAndreas Gohr $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access 6051878f16fSAndreas Gohr SET page = '$page', 6061878f16fSAndreas Gohr ip = '$ip', 6071878f16fSAndreas Gohr ua = '$ua', 6081878f16fSAndreas Gohr ua_info = '$ua_info', 60914d99ec0SAndreas Gohr ua_type = '$ua_type', 61014d99ec0SAndreas Gohr ua_ver = '$ua_ver', 61114d99ec0SAndreas Gohr os = '$os', 6121878f16fSAndreas Gohr ref = '$ref', 61394171ff3SAndreas Gohr ref_md5 = '$ref_md5', 61414d99ec0SAndreas Gohr ref_type = '$ref_type', 6151878f16fSAndreas Gohr screen_x = '$sx', 6161878f16fSAndreas Gohr screen_y = '$sy', 6171878f16fSAndreas Gohr view_x = '$vx', 6181878f16fSAndreas Gohr view_y = '$vy', 6191878f16fSAndreas Gohr user = '$user', 6201878f16fSAndreas Gohr session = '$session'"; 6211878f16fSAndreas Gohr $ok = $this->runSQL($sql); 6221878f16fSAndreas Gohr if(is_null($ok)){ 6231878f16fSAndreas Gohr global $MSG; 6241878f16fSAndreas Gohr print_r($MSG); 6251878f16fSAndreas Gohr } 62614d99ec0SAndreas Gohr 62714d99ec0SAndreas Gohr // resolve the IP 62814d99ec0SAndreas Gohr $this->log_ip($_SERVER['REMOTE_ADDR']); 6291878f16fSAndreas Gohr } 6301878f16fSAndreas Gohr 6311878f16fSAndreas Gohr /** 6321878f16fSAndreas Gohr * Just send a 1x1 pixel blank gif to the browser 6331878f16fSAndreas Gohr * 6341878f16fSAndreas Gohr * @called from log.php 6351878f16fSAndreas Gohr * 6361878f16fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 6371878f16fSAndreas Gohr * @author Harry Fuecks <fuecks@gmail.com> 6381878f16fSAndreas Gohr */ 6391878f16fSAndreas Gohr function sendGIF(){ 6401878f16fSAndreas Gohr $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); 6411878f16fSAndreas Gohr header('Content-Type: image/gif'); 6421878f16fSAndreas Gohr header('Content-Length: '.strlen($img)); 6431878f16fSAndreas Gohr header('Connection: Close'); 6441878f16fSAndreas Gohr print $img; 6451878f16fSAndreas Gohr flush(); 6461878f16fSAndreas Gohr // Browser should drop connection after this 6471878f16fSAndreas Gohr // Thinks it's got the whole image 6481878f16fSAndreas Gohr } 6491878f16fSAndreas Gohr 6501878f16fSAndreas Gohr} 651