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() { 749da6395dSAndreas Gohr $this->html_toc(); 75264f1744SAndreas Gohr echo '<h1>Access Statistics</h1>'; 76264f1744SAndreas Gohr $this->html_timeselect(); 77264f1744SAndreas Gohr 78264f1744SAndreas Gohr switch($this->opt){ 799da6395dSAndreas Gohr case 'country': 809da6395dSAndreas Gohr $this->html_country(); 819da6395dSAndreas Gohr break; 829da6395dSAndreas Gohr case 'page': 839da6395dSAndreas Gohr $this->html_page(); 849da6395dSAndreas Gohr break; 8575fa767dSAndreas Gohr case 'browser': 8675fa767dSAndreas Gohr $this->html_browser(); 8775fa767dSAndreas Gohr break; 88bd4217d3SAndreas Gohr case 'os': 89bd4217d3SAndreas Gohr $this->html_os(); 90bd4217d3SAndreas Gohr break; 919da6395dSAndreas Gohr case 'referer': 929da6395dSAndreas Gohr $this->html_referer(); 939da6395dSAndreas Gohr break; 94e7a2f1e0SAndreas Gohr case 'newreferer': 95e7a2f1e0SAndreas Gohr $this->html_newreferer(); 96e7a2f1e0SAndreas Gohr break; 97c73e16f1SAndreas Gohr case 'resolution': 98c73e16f1SAndreas Gohr $this->html_resolution(); 99c73e16f1SAndreas Gohr break; 10014d99ec0SAndreas Gohr default: 1019da6395dSAndreas Gohr $this->html_dashboard(); 10214d99ec0SAndreas Gohr } 10314d99ec0SAndreas Gohr } 10414d99ec0SAndreas Gohr 1059da6395dSAndreas Gohr function html_toc(){ 1069da6395dSAndreas Gohr echo '<div class="toc">'; 1079da6395dSAndreas Gohr echo '<div class="tocheader toctoggle" id="toc__header">'; 1089da6395dSAndreas Gohr echo 'Detailed Statistics'; 1099da6395dSAndreas Gohr echo '</div>'; 1109da6395dSAndreas Gohr echo '<div id="toc__inside">'; 1119da6395dSAndreas Gohr echo '<ul class="toc">'; 1129da6395dSAndreas Gohr 1139da6395dSAndreas Gohr echo '<li><div class="li">'; 1142507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=&f='.$this->from.'&t='.$this->to.'">Dashboard</a>'; 1159da6395dSAndreas Gohr echo '</div></li>'; 1169da6395dSAndreas Gohr 1179da6395dSAndreas Gohr echo '<li><div class="li">'; 1182507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'">Pages</a>'; 1199da6395dSAndreas Gohr echo '</div></li>'; 1209da6395dSAndreas Gohr 1219da6395dSAndreas Gohr echo '<li><div class="li">'; 1222507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=referer&f='.$this->from.'&t='.$this->to.'">Incoming Links</a>'; 1239da6395dSAndreas Gohr echo '</div></li>'; 1249da6395dSAndreas Gohr 1259da6395dSAndreas Gohr echo '<li><div class="li">'; 1262507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=newreferer&f='.$this->from.'&t='.$this->to.'">New Incoming Links</a>'; 127e7a2f1e0SAndreas Gohr echo '</div></li>'; 128e7a2f1e0SAndreas Gohr 129e7a2f1e0SAndreas Gohr echo '<li><div class="li">'; 1302507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=browser&f='.$this->from.'&t='.$this->to.'">Browsers</a>'; 13175fa767dSAndreas Gohr echo '</div></li>'; 13275fa767dSAndreas Gohr 13375fa767dSAndreas Gohr echo '<li><div class="li">'; 1342507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=os&f='.$this->from.'&t='.$this->to.'">Operating Systems</a>'; 135bd4217d3SAndreas Gohr echo '</div></li>'; 136bd4217d3SAndreas Gohr 137bd4217d3SAndreas Gohr echo '<li><div class="li">'; 1382507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=country&f='.$this->from.'&t='.$this->to.'">Countries</a>'; 1399da6395dSAndreas Gohr echo '</div></li>'; 1409da6395dSAndreas Gohr 141c73e16f1SAndreas Gohr echo '<li><div class="li">'; 142c73e16f1SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=resolution&f='.$this->from.'&t='.$this->to.'">Resolution</a>'; 143c73e16f1SAndreas Gohr echo '</div></li>'; 144c73e16f1SAndreas Gohr 1459da6395dSAndreas Gohr echo '</ul>'; 1469da6395dSAndreas Gohr echo '</div>'; 1479da6395dSAndreas Gohr echo '</div>'; 1489da6395dSAndreas Gohr } 1499da6395dSAndreas Gohr 1502507f8e0SAndreas Gohr function html_pager($limit,$next){ 1512507f8e0SAndreas Gohr echo '<div class="plg_stats_pager">'; 1522507f8e0SAndreas Gohr 1532507f8e0SAndreas Gohr if($this->start > 0){ 1542507f8e0SAndreas Gohr $go = max($this->start - $limit, 0); 1552507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="prev">previous page</a>'; 1562507f8e0SAndreas Gohr } 1572507f8e0SAndreas Gohr 1582507f8e0SAndreas Gohr if($next){ 1592507f8e0SAndreas Gohr $go = $this->start + $limit; 1602507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$this->from.'&t='.$this->to.'&s='.$go.'" class="next">next page</a>'; 1612507f8e0SAndreas Gohr } 1622507f8e0SAndreas Gohr echo '</div>'; 1632507f8e0SAndreas Gohr } 1642507f8e0SAndreas Gohr 165264f1744SAndreas Gohr /** 166264f1744SAndreas Gohr * Print the time selection menu 167264f1744SAndreas Gohr */ 16814d99ec0SAndreas Gohr function html_timeselect(){ 169264f1744SAndreas Gohr $now = date('Y-m-d'); 170264f1744SAndreas Gohr $yday = date('Y-m-d',time()-(60*60*24)); 171264f1744SAndreas Gohr $week = date('Y-m-d',time()-(60*60*24*7)); 172264f1744SAndreas Gohr $month = date('Y-m-d',time()-(60*60*24*30)); 17314d99ec0SAndreas Gohr 174264f1744SAndreas Gohr echo '<div class="plg_stats_timeselect">'; 175264f1744SAndreas Gohr echo '<span>Select the timeframe:</span>'; 176264f1744SAndreas Gohr echo '<ul>'; 177264f1744SAndreas Gohr 178264f1744SAndreas Gohr echo '<li>'; 1792507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$now.'&t='.$now.'">'; 180264f1744SAndreas Gohr echo 'today'; 181264f1744SAndreas Gohr echo '</a>'; 182264f1744SAndreas Gohr echo '</li>'; 183264f1744SAndreas Gohr 184264f1744SAndreas Gohr echo '<li>'; 1852507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$yday.'&t='.$yday.'">'; 186264f1744SAndreas Gohr echo 'yesterday'; 187264f1744SAndreas Gohr echo '</a>'; 188264f1744SAndreas Gohr echo '</li>'; 189264f1744SAndreas Gohr 190264f1744SAndreas Gohr echo '<li>'; 1912507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$week.'&t='.$now.'">'; 192264f1744SAndreas Gohr echo 'last 7 days'; 193264f1744SAndreas Gohr echo '</a>'; 194264f1744SAndreas Gohr echo '</li>'; 195264f1744SAndreas Gohr 196264f1744SAndreas Gohr echo '<li>'; 1972507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt='.$this->opt.'&f='.$month.'&t='.$now.'">'; 198264f1744SAndreas Gohr echo 'last 30 days'; 199264f1744SAndreas Gohr echo '</a>'; 200264f1744SAndreas Gohr echo '</li>'; 201264f1744SAndreas Gohr 202264f1744SAndreas Gohr echo '</ul>'; 203264f1744SAndreas Gohr 204264f1744SAndreas Gohr 205264f1744SAndreas Gohr echo '<form action="" method="get">'; 206264f1744SAndreas Gohr echo '<input type="hidden" name="do" value="admin" />'; 207264f1744SAndreas Gohr echo '<input type="hidden" name="page" value="statistics" />'; 208264f1744SAndreas Gohr echo '<input type="hidden" name="opt" value="'.$this->opt.'" />'; 209264f1744SAndreas Gohr echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />'; 210264f1744SAndreas Gohr echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />'; 211264f1744SAndreas Gohr echo '<input type="submit" value="go" class="button" />'; 21214d99ec0SAndreas Gohr echo '</form>'; 213264f1744SAndreas Gohr 214264f1744SAndreas Gohr echo '</div>'; 21514d99ec0SAndreas Gohr } 21614d99ec0SAndreas Gohr 21714d99ec0SAndreas Gohr 218f5f32cbfSAndreas Gohr /** 219f5f32cbfSAndreas Gohr * Print an introductionary screen 220f5f32cbfSAndreas Gohr */ 22114d99ec0SAndreas Gohr function html_dashboard(){ 2222812a751SAndreas Gohr echo '<p>This page gives you a quick overview on what is happening in your Wiki. For detailed lists 2232812a751SAndreas Gohr choose a topic from the list.</p>'; 2242812a751SAndreas Gohr 2252812a751SAndreas Gohr 226264f1744SAndreas Gohr echo '<div class="plg_stats_dashboard">'; 227264f1744SAndreas Gohr 2282812a751SAndreas Gohr // general info 2292812a751SAndreas Gohr echo '<div class="plg_stats_top">'; 2302812a751SAndreas Gohr $result = $this->sql_aggregate($this->tlimit); 2312812a751SAndreas Gohr echo '<ul>'; 2322812a751SAndreas Gohr echo '<li><span>'.$result['pageviews'].'</span> page views</li>'; 233*3c0acc14SAndreas Gohr echo '<li><span>'.$result['sessions'].'</span> visits (sessions)</li>'; 234*3c0acc14SAndreas Gohr echo '<li><span>'.$result['visitors'].'</span> unique visitors</li>'; 2352812a751SAndreas Gohr echo '<li><span>'.$result['users'].'</span> logged in users</li>'; 2362812a751SAndreas Gohr 2372812a751SAndreas Gohr echo '</ul>'; 2382812a751SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=trend&f='.$this->from.'&t='.$this->to.'" />'; 2392812a751SAndreas Gohr echo '</div>'; 2402812a751SAndreas Gohr 24114d99ec0SAndreas Gohr 24287d5e44bSAndreas Gohr // top pages today 243264f1744SAndreas Gohr echo '<div>'; 244264f1744SAndreas Gohr echo '<h2>Most popular pages</h2>'; 24595eb68e6SAndreas Gohr $result = $this->sql_pages($this->tlimit,$this->start,15); 2462812a751SAndreas Gohr $this->html_resulttable($result); 2472507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 248264f1744SAndreas Gohr echo '</div>'; 24987d5e44bSAndreas Gohr 25087d5e44bSAndreas Gohr // top referer today 251264f1744SAndreas Gohr echo '<div>'; 252e7a2f1e0SAndreas Gohr echo '<h2>Newest incoming links</h2>'; 253e7a2f1e0SAndreas Gohr $result = $this->sql_newreferer($this->tlimit,$this->start,15); 2542812a751SAndreas Gohr $this->html_resulttable($result); 2552507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=newreferer&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 256264f1744SAndreas Gohr echo '</div>'; 25754f6c432SAndreas Gohr 25854f6c432SAndreas Gohr // top countries today 259264f1744SAndreas Gohr echo '<div>'; 260264f1744SAndreas Gohr echo '<h2>Visitor\'s top countries</h2>'; 26195eb68e6SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&f='.$this->from.'&t='.$this->to.'" />'; 2622507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=country&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 263264f1744SAndreas Gohr echo '</div>'; 264264f1744SAndreas Gohr 265264f1744SAndreas Gohr echo '</div>'; 26614d99ec0SAndreas Gohr } 26714d99ec0SAndreas Gohr 2689da6395dSAndreas Gohr function html_country(){ 2699da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 2709da6395dSAndreas Gohr echo '<h2>Visitor\'s Countries</h2>'; 271bd4217d3SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&f='.$this->from.'&t='.$this->to.'" />'; 2729da6395dSAndreas Gohr $result = $this->sql_countries($this->tlimit,$this->start,150); 2732507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 2749da6395dSAndreas Gohr echo '</div>'; 2759da6395dSAndreas Gohr } 2769da6395dSAndreas Gohr 2779da6395dSAndreas Gohr function html_page(){ 2789da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 2799da6395dSAndreas Gohr echo '<h2>Popular Pages</h2>'; 2809da6395dSAndreas Gohr $result = $this->sql_pages($this->tlimit,$this->start,150); 2812507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 2829da6395dSAndreas Gohr echo '</div>'; 2839da6395dSAndreas Gohr } 2849da6395dSAndreas Gohr 28575fa767dSAndreas Gohr function html_browser(){ 28675fa767dSAndreas Gohr echo '<div class="plg_stats_full">'; 28775fa767dSAndreas Gohr echo '<h2>Browser Shootout</h2>'; 28875fa767dSAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browser&f='.$this->from.'&t='.$this->to.'" />'; 28975fa767dSAndreas Gohr $result = $this->sql_browsers($this->tlimit,$this->start,150,true); 2902507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 29175fa767dSAndreas Gohr echo '</div>'; 29275fa767dSAndreas Gohr } 29375fa767dSAndreas Gohr 294bd4217d3SAndreas Gohr function html_os(){ 295bd4217d3SAndreas Gohr echo '<div class="plg_stats_full">'; 296bd4217d3SAndreas Gohr echo '<h2>Operating Systems</h2>'; 297bd4217d3SAndreas Gohr $result = $this->sql_os($this->tlimit,$this->start,150,true); 2982507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 299bd4217d3SAndreas Gohr echo '</div>'; 300bd4217d3SAndreas Gohr } 301bd4217d3SAndreas Gohr 3029da6395dSAndreas Gohr function html_referer(){ 3039da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 3049da6395dSAndreas Gohr echo '<h2>Incoming Links</h2>'; 3052812a751SAndreas Gohr $result = $this->sql_aggregate($this->tlimit); 3062812a751SAndreas Gohr 3072812a751SAndreas Gohr $all = $result['search']+$result['external']+$result['direct']; 3082812a751SAndreas Gohr 30994023548SAndreas Gohr if($all){ 3102812a751SAndreas Gohr printf("<p>Of all %d external visits, %d (%.1f%%) were bookmarked (direct) accesses, 3112812a751SAndreas Gohr %d (%.1f%%) came from search engines and %d (%.1f%%) were referred through 3122812a751SAndreas Gohr links from other pages.</p>",$all,$result['direct'],(100*$result['direct']/$all), 3132812a751SAndreas Gohr $result['search'],(100*$result['search']/$all),$result['external'], 3142812a751SAndreas Gohr (100*$result['external']/$all)); 31594023548SAndreas Gohr } 3162812a751SAndreas Gohr 3179da6395dSAndreas Gohr $result = $this->sql_referer($this->tlimit,$this->start,150); 3182507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 3199da6395dSAndreas Gohr echo '</div>'; 3209da6395dSAndreas Gohr } 3219da6395dSAndreas Gohr 322e7a2f1e0SAndreas Gohr function html_newreferer(){ 323e7a2f1e0SAndreas Gohr echo '<div class="plg_stats_full">'; 324e7a2f1e0SAndreas Gohr echo '<h2>New Incoming Links</h2>'; 325e7a2f1e0SAndreas Gohr echo '<p>The following incoming links where first logged in the selected time frame, 326e7a2f1e0SAndreas Gohr and have never been seen before.</p>'; 327e7a2f1e0SAndreas Gohr 328e7a2f1e0SAndreas Gohr $result = $this->sql_newreferer($this->tlimit,$this->start,150); 3292507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 330e7a2f1e0SAndreas Gohr echo '</div>'; 331e7a2f1e0SAndreas Gohr } 332e7a2f1e0SAndreas Gohr 333c73e16f1SAndreas Gohr function html_resolution(){ 334c73e16f1SAndreas Gohr echo '<div class="plg_stats_full">'; 335c73e16f1SAndreas Gohr echo '<h2>Resolution</h2>'; 336c73e16f1SAndreas Gohr $result = $this->sql_resolution($this->tlimit,$this->start,150); 337c73e16f1SAndreas Gohr $this->html_resulttable($result,'',150); 338c73e16f1SAndreas Gohr 339c73e16f1SAndreas Gohr echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you 340c73e16f1SAndreas Gohr much about about the real size of their browser windows. The graphic below shows the size distribution of 341c73e16f1SAndreas Gohr the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged 342c73e16f1SAndreas Gohr in all browsers. Because users may resize their browser window while browsing your site the statistics may 343c73e16f1SAndreas Gohr be flawed. Take it with a grain of salt.</p>'; 344c73e16f1SAndreas Gohr 345c73e16f1SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=view&f='.$this->from.'&t='.$this->to.'" />'; 346c73e16f1SAndreas Gohr echo '</div>'; 347c73e16f1SAndreas Gohr } 3489da6395dSAndreas Gohr 3499da6395dSAndreas Gohr 35014d99ec0SAndreas Gohr /** 35114d99ec0SAndreas Gohr * Display a result in a HTML table 35214d99ec0SAndreas Gohr */ 3532507f8e0SAndreas Gohr function html_resulttable($result,$header='',$pager=0){ 35414d99ec0SAndreas Gohr echo '<table>'; 3552812a751SAndreas Gohr if(is_array($header)){ 35614d99ec0SAndreas Gohr echo '<tr>'; 35714d99ec0SAndreas Gohr foreach($header as $h){ 35814d99ec0SAndreas Gohr echo '<th>'.hsc($h).'</th>'; 35914d99ec0SAndreas Gohr } 36014d99ec0SAndreas Gohr echo '</tr>'; 3612812a751SAndreas Gohr } 36214d99ec0SAndreas Gohr 3632507f8e0SAndreas Gohr $count = 0; 36414d99ec0SAndreas Gohr foreach($result as $row){ 36514d99ec0SAndreas Gohr echo '<tr>'; 36614d99ec0SAndreas Gohr foreach($row as $k => $v){ 3672812a751SAndreas Gohr echo '<td class="plg_stats_X'.$k.'">'; 36814d99ec0SAndreas Gohr if($k == 'page'){ 36914d99ec0SAndreas Gohr echo '<a href="'.wl($v).'" class="wikilink1">'; 37014d99ec0SAndreas Gohr echo hsc($v); 37114d99ec0SAndreas Gohr echo '</a>'; 37214d99ec0SAndreas Gohr }elseif($k == 'url'){ 37354f6c432SAndreas Gohr $url = hsc($v); 37483b63546SAndreas Gohr $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); 3752812a751SAndreas Gohr if(strlen($url) > 45){ 3762812a751SAndreas Gohr $url = substr($url,0,30).' … '.substr($url,-15); 37754f6c432SAndreas Gohr } 37814d99ec0SAndreas Gohr echo '<a href="'.$v.'" class="urlextern">'; 37954f6c432SAndreas Gohr echo $url; 38014d99ec0SAndreas Gohr echo '</a>'; 38175fa767dSAndreas Gohr }elseif($k == 'browser'){ 38275fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 38375fa767dSAndreas Gohr echo $BrowsersHashIDLib[$v]; 38475fa767dSAndreas Gohr }elseif($k == 'bflag'){ 38575fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 38675fa767dSAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.$BrowsersHashIcon[$v].'.png" alt="'.hsc($v).'" />'; 387bd4217d3SAndreas Gohr }elseif($k == 'os'){ 388bd4217d3SAndreas Gohr if(empty($v)){ 389bd4217d3SAndreas Gohr echo 'unknown'; 390bd4217d3SAndreas Gohr }else{ 391bd4217d3SAndreas Gohr include_once(dirname(__FILE__).'/inc/operating_systems.php'); 392bd4217d3SAndreas Gohr echo $OSHashLib[$v]; 393bd4217d3SAndreas Gohr } 394bd4217d3SAndreas Gohr }elseif($k == 'osflag'){ 395bd4217d3SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.hsc($v).'.png" alt="'.hsc($v).'" />'; 39675fa767dSAndreas Gohr }elseif($k == 'cflag'){ 39775fa767dSAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; 39814d99ec0SAndreas Gohr }elseif($k == 'html'){ 39914d99ec0SAndreas Gohr echo $v; 40014d99ec0SAndreas Gohr }else{ 40114d99ec0SAndreas Gohr echo hsc($v); 40214d99ec0SAndreas Gohr } 40314d99ec0SAndreas Gohr echo '</td>'; 40414d99ec0SAndreas Gohr } 40514d99ec0SAndreas Gohr echo '</tr>'; 4062507f8e0SAndreas Gohr 4072507f8e0SAndreas Gohr if($pager && ($count == $pager)) break; 4082507f8e0SAndreas Gohr $count++; 40914d99ec0SAndreas Gohr } 41014d99ec0SAndreas Gohr echo '</table>'; 4112507f8e0SAndreas Gohr 4122507f8e0SAndreas Gohr if($pager) $this->html_pager($pager,count($result) > $pager); 4131878f16fSAndreas Gohr } 4141878f16fSAndreas Gohr 41595eb68e6SAndreas Gohr /** 41695eb68e6SAndreas Gohr * Create an image 41795eb68e6SAndreas Gohr */ 41895eb68e6SAndreas Gohr function img_build($img){ 41995eb68e6SAndreas Gohr include(dirname(__FILE__).'/inc/AGC.class.php'); 42095eb68e6SAndreas Gohr 42195eb68e6SAndreas Gohr switch($img){ 42295eb68e6SAndreas Gohr case 'country': 42395eb68e6SAndreas Gohr // build top countries + other 42495eb68e6SAndreas Gohr $result = $this->sql_countries($this->tlimit,$this->start,0); 42595eb68e6SAndreas Gohr $data = array(); 42695eb68e6SAndreas Gohr $top = 0; 42795eb68e6SAndreas Gohr foreach($result as $row){ 42895eb68e6SAndreas Gohr if($top < 7){ 42995eb68e6SAndreas Gohr $data[$row['country']] = $row['cnt']; 43095eb68e6SAndreas Gohr }else{ 43195eb68e6SAndreas Gohr $data['other'] += $row['cnt']; 43295eb68e6SAndreas Gohr } 43395eb68e6SAndreas Gohr $top++; 43495eb68e6SAndreas Gohr } 43595eb68e6SAndreas Gohr $pie = new AGC(300, 200); 43695eb68e6SAndreas Gohr $pie->setProp("showkey",true); 43795eb68e6SAndreas Gohr $pie->setProp("showval",false); 43895eb68e6SAndreas Gohr $pie->setProp("showgrid",false); 43995eb68e6SAndreas Gohr $pie->setProp("type","pie"); 44095eb68e6SAndreas Gohr $pie->setProp("keyinfo",1); 44195eb68e6SAndreas Gohr $pie->setProp("keysize",8); 44295eb68e6SAndreas Gohr $pie->setProp("keywidspc",-50); 44395eb68e6SAndreas Gohr $pie->setProp("key",array_keys($data)); 44495eb68e6SAndreas Gohr $pie->addBulkPoints(array_values($data)); 44595eb68e6SAndreas Gohr @$pie->graph(); 44695eb68e6SAndreas Gohr $pie->showGraph(); 44795eb68e6SAndreas Gohr break; 44875fa767dSAndreas Gohr case 'browser': 44975fa767dSAndreas Gohr // build top browsers + other 45075fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 45175fa767dSAndreas Gohr 45275fa767dSAndreas Gohr $result = $this->sql_browsers($this->tlimit,$this->start,0,false); 45375fa767dSAndreas Gohr $data = array(); 45475fa767dSAndreas Gohr $top = 0; 45575fa767dSAndreas Gohr foreach($result as $row){ 45675fa767dSAndreas Gohr if($top < 5){ 45775fa767dSAndreas Gohr $data[strip_tags($BrowsersHashIDLib[$row['ua_info']])] = $row['cnt']; 45875fa767dSAndreas Gohr }else{ 45975fa767dSAndreas Gohr $data['other'] += $row['cnt']; 46075fa767dSAndreas Gohr } 46175fa767dSAndreas Gohr $top++; 46275fa767dSAndreas Gohr } 46375fa767dSAndreas Gohr $pie = new AGC(300, 200); 46475fa767dSAndreas Gohr $pie->setProp("showkey",true); 46575fa767dSAndreas Gohr $pie->setProp("showval",false); 46675fa767dSAndreas Gohr $pie->setProp("showgrid",false); 46775fa767dSAndreas Gohr $pie->setProp("type","pie"); 46875fa767dSAndreas Gohr $pie->setProp("keyinfo",1); 46975fa767dSAndreas Gohr $pie->setProp("keysize",8); 47075fa767dSAndreas Gohr $pie->setProp("keywidspc",-50); 47175fa767dSAndreas Gohr $pie->setProp("key",array_keys($data)); 47275fa767dSAndreas Gohr $pie->addBulkPoints(array_values($data)); 47375fa767dSAndreas Gohr @$pie->graph(); 47475fa767dSAndreas Gohr $pie->showGraph(); 47575fa767dSAndreas Gohr break; 476c73e16f1SAndreas Gohr case 'view': 477c73e16f1SAndreas Gohr 478c73e16f1SAndreas Gohr $graph = new AGC(400, 200); 479c73e16f1SAndreas Gohr $graph->setColor('color',0,'blue'); 480c73e16f1SAndreas Gohr $graph->setColor('color',1,'red'); 481c73e16f1SAndreas Gohr $graph->setProp("showkey",true); 482c73e16f1SAndreas Gohr $graph->setProp("key",'view port width',0); 483c73e16f1SAndreas Gohr $graph->setProp("key",'view port height',1); 484c73e16f1SAndreas Gohr 485c73e16f1SAndreas Gohr $result = $this->sql_viewport($this->tlimit,0,0,true); 486c73e16f1SAndreas Gohr foreach($result as $row){ 487c73e16f1SAndreas Gohr $graph->addPoint($row['cnt'],$row['res_x'],0); 488c73e16f1SAndreas Gohr } 489c73e16f1SAndreas Gohr 490c73e16f1SAndreas Gohr $result = $this->sql_viewport($this->tlimit,0,0,false); 491c73e16f1SAndreas Gohr foreach($result as $row){ 492c73e16f1SAndreas Gohr $graph->addPoint($row['cnt'],$row['res_y'],1); 493c73e16f1SAndreas Gohr } 494c73e16f1SAndreas Gohr 495c73e16f1SAndreas Gohr @$graph->graph(); 496c73e16f1SAndreas Gohr $graph->showGraph(); 497c73e16f1SAndreas Gohr 498c73e16f1SAndreas Gohr break; 4992812a751SAndreas Gohr case 'trend': 5002812a751SAndreas Gohr $hours = ($this->from == $this->to); 5012812a751SAndreas Gohr $result = $this->sql_trend($this->tlimit,$hours); 5022812a751SAndreas Gohr $data1 = array(); 5032812a751SAndreas Gohr $data2 = array(); 5042812a751SAndreas Gohr 5052812a751SAndreas Gohr $graph = new AGC(400, 150); 5062812a751SAndreas Gohr $graph->setProp("type","bar"); 5072812a751SAndreas Gohr $graph->setProp("showgrid",false); 5082812a751SAndreas Gohr $graph->setProp("barwidth",.8); 50975fa767dSAndreas Gohr 5102812a751SAndreas Gohr $graph->setColor('color',0,'blue'); 5112812a751SAndreas Gohr $graph->setColor('color',1,'red'); 512*3c0acc14SAndreas Gohr $graph->setColor('color',2,'yellow'); 5132812a751SAndreas Gohr 5142812a751SAndreas Gohr if($hours){ 5152812a751SAndreas Gohr //preset $hours 5162812a751SAndreas Gohr for($i=0;$i<24;$i++){ 5172812a751SAndreas Gohr $data1[$i] = 0; 5182812a751SAndreas Gohr $data2[$i] = 0; 519*3c0acc14SAndreas Gohr $data3[$i] = 0; 5202812a751SAndreas Gohr $graph->setProp("scale",array(' 0h',' 4h',' 8h',' 12h',' 16h',' 20h',' 24h')); 5212812a751SAndreas Gohr } 5222812a751SAndreas Gohr }else{ 5232812a751SAndreas Gohr $graph->setProp("scale",array(next(array_keys($data1)),$this->to)); 5242812a751SAndreas Gohr } 5252812a751SAndreas Gohr 5262812a751SAndreas Gohr foreach($result as $row){ 5272812a751SAndreas Gohr $data1[$row['time']] = $row['pageviews']; 5282812a751SAndreas Gohr $data2[$row['time']] = $row['sessions']; 529*3c0acc14SAndreas Gohr $data3[$row['time']] = $row['visitors']; 5302812a751SAndreas Gohr } 5312812a751SAndreas Gohr 5322812a751SAndreas Gohr foreach($data1 as $key => $val){ 5332812a751SAndreas Gohr $graph->addPoint($val,$key,0); 5342812a751SAndreas Gohr } 5352812a751SAndreas Gohr foreach($data2 as $key => $val){ 5362812a751SAndreas Gohr $graph->addPoint($val,$key,1); 5372812a751SAndreas Gohr } 538*3c0acc14SAndreas Gohr foreach($data3 as $key => $val){ 539*3c0acc14SAndreas Gohr $graph->addPoint($val,$key,2); 540*3c0acc14SAndreas Gohr } 5412812a751SAndreas Gohr 5422812a751SAndreas Gohr @$graph->graph(); 5432812a751SAndreas Gohr $graph->showGraph(); 5442812a751SAndreas Gohr 54595eb68e6SAndreas Gohr default: 54695eb68e6SAndreas Gohr $this->sendGIF(); 54795eb68e6SAndreas Gohr } 54895eb68e6SAndreas Gohr } 54995eb68e6SAndreas Gohr 55095eb68e6SAndreas Gohr 5512812a751SAndreas Gohr /** 5522812a751SAndreas Gohr * Return some aggregated statistics 5532812a751SAndreas Gohr */ 5542812a751SAndreas Gohr function sql_aggregate($tlimit){ 5552812a751SAndreas Gohr $data = array(); 5562812a751SAndreas Gohr 5572812a751SAndreas Gohr $sql = "SELECT ref_type, COUNT(*) as cnt 5582812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5592812a751SAndreas Gohr WHERE $tlimit 5602812a751SAndreas Gohr AND ua_type = 'browser' 5612812a751SAndreas Gohr GROUP BY ref_type"; 5622812a751SAndreas Gohr $result = $this->runSQL($sql); 5632812a751SAndreas Gohr 5642812a751SAndreas Gohr foreach($result as $row){ 5652812a751SAndreas Gohr if($row['ref_type'] == 'search') $data['search'] = $row['cnt']; 5662812a751SAndreas Gohr if($row['ref_type'] == 'external') $data['external'] = $row['cnt']; 5672812a751SAndreas Gohr if($row['ref_type'] == 'internal') $data['internal'] = $row['cnt']; 5682812a751SAndreas Gohr if($row['ref_type'] == '') $data['direct'] = $row['cnt']; 5692812a751SAndreas Gohr } 5702812a751SAndreas Gohr 5712812a751SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as sessions, 5722812a751SAndreas Gohr COUNT(session) as views, 573*3c0acc14SAndreas Gohr COUNT(DISTINCT user) as users, 574*3c0acc14SAndreas Gohr COUNT(DISTINCT uid) as visitors 5752812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5762812a751SAndreas Gohr WHERE $tlimit 5772812a751SAndreas Gohr AND ua_type = 'browser'"; 5782812a751SAndreas Gohr $result = $this->runSQL($sql); 5792812a751SAndreas Gohr 58075fa767dSAndreas Gohr $data['users'] = max($result[0]['users'] - 1,0); // subtract empty user 5812812a751SAndreas Gohr $data['sessions'] = $result[0]['sessions']; 5822812a751SAndreas Gohr $data['pageviews'] = $result[0]['views']; 583*3c0acc14SAndreas Gohr $data['visitors'] = $result[0]['visitors']; 5842812a751SAndreas Gohr 5852812a751SAndreas Gohr $sql = "SELECT COUNT(id) as robots 5862812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5872812a751SAndreas Gohr WHERE $tlimit 5882812a751SAndreas Gohr AND ua_type = 'robot'"; 5892812a751SAndreas Gohr $result = $this->runSQL($sql); 5902812a751SAndreas Gohr $data['robots'] = $result[0]['robots']; 5912812a751SAndreas Gohr 5922812a751SAndreas Gohr return $data; 5932812a751SAndreas Gohr } 5942812a751SAndreas Gohr 595bd4217d3SAndreas Gohr /** 596bd4217d3SAndreas Gohr * standard statistics follow, only accesses made by browsers are counted 597bd4217d3SAndreas Gohr * for general stats like browser or OS only visitors not pageviews are counted 598bd4217d3SAndreas Gohr */ 5992812a751SAndreas Gohr function sql_trend($tlimit,$hours=false){ 6002812a751SAndreas Gohr if($hours){ 6012812a751SAndreas Gohr $sql = "SELECT HOUR(dt) as time, 6022812a751SAndreas Gohr COUNT(DISTINCT session) as sessions, 603*3c0acc14SAndreas Gohr COUNT(session) as pageviews, 604*3c0acc14SAndreas Gohr COUNT(DISTINCT uid) as visitors 6052812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 6062812a751SAndreas Gohr WHERE $tlimit 6072812a751SAndreas Gohr AND ua_type = 'browser' 6082812a751SAndreas Gohr GROUP BY HOUR(dt) 6092812a751SAndreas Gohr ORDER BY time"; 6102812a751SAndreas Gohr }else{ 6112812a751SAndreas Gohr $sql = "SELECT DATE(dt) as time, 6122812a751SAndreas Gohr COUNT(DISTINCT session) as sessions, 613*3c0acc14SAndreas Gohr COUNT(session) as pageviews, 614*3c0acc14SAndreas Gohr COUNT(DISTINCT uid) as visitors 6152812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 6162812a751SAndreas Gohr WHERE $tlimit 6172812a751SAndreas Gohr AND ua_type = 'browser' 6182812a751SAndreas Gohr GROUP BY DATE(dt) 6192812a751SAndreas Gohr ORDER BY time"; 6202812a751SAndreas Gohr } 6212812a751SAndreas Gohr return $this->runSQL($sql); 6222812a751SAndreas Gohr } 6232812a751SAndreas Gohr 62495eb68e6SAndreas Gohr function sql_pages($tlimit,$start=0,$limit=20){ 6252812a751SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, page 62695eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 62795eb68e6SAndreas Gohr WHERE $tlimit 62895eb68e6SAndreas Gohr AND ua_type = 'browser' 62995eb68e6SAndreas Gohr GROUP BY page 63095eb68e6SAndreas Gohr ORDER BY cnt DESC, page". 63195eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 63295eb68e6SAndreas Gohr return $this->runSQL($sql); 63395eb68e6SAndreas Gohr } 63495eb68e6SAndreas Gohr 63595eb68e6SAndreas Gohr function sql_referer($tlimit,$start=0,$limit=20){ 6362812a751SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, ref as url 63795eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 63895eb68e6SAndreas Gohr WHERE $tlimit 63995eb68e6SAndreas Gohr AND ua_type = 'browser' 64095eb68e6SAndreas Gohr AND ref_type = 'external' 64195eb68e6SAndreas Gohr GROUP BY ref_md5 64295eb68e6SAndreas Gohr ORDER BY cnt DESC, url". 64395eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 64495eb68e6SAndreas Gohr return $this->runSQL($sql); 64595eb68e6SAndreas Gohr } 64695eb68e6SAndreas Gohr 647e7a2f1e0SAndreas Gohr function sql_newreferer($tlimit,$start=0,$limit=20){ 648e7a2f1e0SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, ref as url 649e7a2f1e0SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 650e7a2f1e0SAndreas Gohr WHERE ua_type = 'browser' 651e7a2f1e0SAndreas Gohr AND ref_type = 'external' 652e7a2f1e0SAndreas Gohr GROUP BY ref_md5 653e7a2f1e0SAndreas Gohr HAVING DATE(MIN(dt)) >= DATE('".$this->from."') 654e7a2f1e0SAndreas Gohr AND DATE(MIN(dt)) <= DATE('".$this->to."') 655e7a2f1e0SAndreas Gohr ORDER BY cnt DESC, url". 656e7a2f1e0SAndreas Gohr $this->sql_limit($start,$limit); 657e7a2f1e0SAndreas Gohr return $this->runSQL($sql); 658e7a2f1e0SAndreas Gohr } 659e7a2f1e0SAndreas Gohr 66095eb68e6SAndreas Gohr function sql_countries($tlimit,$start=0,$limit=20){ 661bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country 66295eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A, 66395eb68e6SAndreas Gohr ".$this->getConf('db_prefix')."iplocation as B 66495eb68e6SAndreas Gohr WHERE $tlimit 66595eb68e6SAndreas Gohr AND A.ip = B.ip 66695eb68e6SAndreas Gohr GROUP BY B.country 66795eb68e6SAndreas Gohr ORDER BY cnt DESC, B.country". 66895eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 66995eb68e6SAndreas Gohr return $this->runSQL($sql); 67095eb68e6SAndreas Gohr } 67195eb68e6SAndreas Gohr 67275fa767dSAndreas Gohr function sql_browsers($tlimit,$start=0,$limit=20,$ext=true){ 67375fa767dSAndreas Gohr if($ext){ 67475fa767dSAndreas Gohr $sel = 'ua_info as bflag, ua_info as browser, ua_ver'; 67575fa767dSAndreas Gohr $grp = 'ua_info, ua_ver'; 67675fa767dSAndreas Gohr }else{ 67775fa767dSAndreas Gohr $grp = 'ua_info'; 67875fa767dSAndreas Gohr $sel = 'ua_info'; 67975fa767dSAndreas Gohr } 68075fa767dSAndreas Gohr 681bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel 68275fa767dSAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 68375fa767dSAndreas Gohr WHERE $tlimit 68475fa767dSAndreas Gohr AND ua_type = 'browser' 68575fa767dSAndreas Gohr GROUP BY $grp 68675fa767dSAndreas Gohr ORDER BY cnt DESC, ua_info". 68775fa767dSAndreas Gohr $this->sql_limit($start,$limit); 68875fa767dSAndreas Gohr return $this->runSQL($sql); 68975fa767dSAndreas Gohr } 69075fa767dSAndreas Gohr 691bd4217d3SAndreas Gohr function sql_os($tlimit,$start=0,$limit=20){ 692bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os 693bd4217d3SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 694bd4217d3SAndreas Gohr WHERE $tlimit 695bd4217d3SAndreas Gohr AND ua_type = 'browser' 696bd4217d3SAndreas Gohr GROUP BY os 697bd4217d3SAndreas Gohr ORDER BY cnt DESC, os". 698bd4217d3SAndreas Gohr $this->sql_limit($start,$limit); 699bd4217d3SAndreas Gohr return $this->runSQL($sql); 700bd4217d3SAndreas Gohr } 701bd4217d3SAndreas Gohr 702c73e16f1SAndreas Gohr function sql_resolution($tlimit,$start=0,$limit=20){ 703c73e16f1SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, CONCAT(screen_x,'x',screen_y) as res 704c73e16f1SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 705c73e16f1SAndreas Gohr WHERE $tlimit 706c73e16f1SAndreas Gohr AND ua_type = 'browser' 707c73e16f1SAndreas Gohr AND screen_x != 0 708c73e16f1SAndreas Gohr GROUP BY screen_x, screen_y 709c73e16f1SAndreas Gohr ORDER BY cnt DESC, screen_x". 710c73e16f1SAndreas Gohr $this->sql_limit($start,$limit); 711c73e16f1SAndreas Gohr return $this->runSQL($sql); 712c73e16f1SAndreas Gohr } 713c73e16f1SAndreas Gohr 714c73e16f1SAndreas Gohr function sql_viewport($tlimit,$start=0,$limit=20,$x=true){ 715c73e16f1SAndreas Gohr if($x){ 716c73e16f1SAndreas Gohr $col = 'view_x'; 717c73e16f1SAndreas Gohr $res = 'res_x'; 718c73e16f1SAndreas Gohr }else{ 719c73e16f1SAndreas Gohr $col = 'view_y'; 720c73e16f1SAndreas Gohr $res = 'res_y'; 721c73e16f1SAndreas Gohr } 722c73e16f1SAndreas Gohr 723c73e16f1SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, 724c73e16f1SAndreas Gohr ROUND($col/10)*10 as $res 725c73e16f1SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 726c73e16f1SAndreas Gohr WHERE $tlimit 727c73e16f1SAndreas Gohr AND ua_type = 'browser' 728c73e16f1SAndreas Gohr AND $col != 0 729c73e16f1SAndreas Gohr GROUP BY $res 730c73e16f1SAndreas Gohr ORDER BY cnt DESC, $res". 731c73e16f1SAndreas Gohr $this->sql_limit($start,$limit); 732c73e16f1SAndreas Gohr return $this->runSQL($sql); 733c73e16f1SAndreas Gohr } 734c73e16f1SAndreas Gohr 73575fa767dSAndreas Gohr 73695eb68e6SAndreas Gohr /** 73795eb68e6SAndreas Gohr * Builds a limit clause 73895eb68e6SAndreas Gohr */ 73995eb68e6SAndreas Gohr function sql_limit($start,$limit){ 74095eb68e6SAndreas Gohr $start = (int) $start; 74195eb68e6SAndreas Gohr $limit = (int) $limit; 74295eb68e6SAndreas Gohr if($limit){ 7432507f8e0SAndreas Gohr $limit += 1; 74495eb68e6SAndreas Gohr return " LIMIT $start,$limit"; 74595eb68e6SAndreas Gohr }elseif($start){ 74695eb68e6SAndreas Gohr return " OFFSET $start"; 74795eb68e6SAndreas Gohr } 74895eb68e6SAndreas Gohr return ''; 74995eb68e6SAndreas Gohr } 7501878f16fSAndreas Gohr 7511878f16fSAndreas Gohr /** 75214d99ec0SAndreas Gohr * Return a link to the DB, opening the connection if needed 7531878f16fSAndreas Gohr */ 75414d99ec0SAndreas Gohr function dbLink(){ 7551878f16fSAndreas Gohr // connect to DB if needed 7561878f16fSAndreas Gohr if(!$this->dblink){ 7571878f16fSAndreas Gohr $this->dblink = mysql_connect($this->getConf('db_server'), 7581878f16fSAndreas Gohr $this->getConf('db_user'), 7591878f16fSAndreas Gohr $this->getConf('db_password')); 7601878f16fSAndreas Gohr if(!$this->dblink){ 7611878f16fSAndreas Gohr msg('DB Error: connection failed',-1); 7621878f16fSAndreas Gohr return null; 7631878f16fSAndreas Gohr } 7641878f16fSAndreas Gohr // set utf-8 7651878f16fSAndreas Gohr if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){ 7661878f16fSAndreas Gohr msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1); 7671878f16fSAndreas Gohr return null; 7681878f16fSAndreas Gohr } 7691878f16fSAndreas Gohr } 77014d99ec0SAndreas Gohr return $this->dblink; 77114d99ec0SAndreas Gohr } 7721878f16fSAndreas Gohr 77314d99ec0SAndreas Gohr /** 77414d99ec0SAndreas Gohr * Simple function to run a DB query 77514d99ec0SAndreas Gohr */ 77614d99ec0SAndreas Gohr function runSQL($sql_string) { 77714d99ec0SAndreas Gohr $link = $this->dbLink(); 77814d99ec0SAndreas Gohr 77914d99ec0SAndreas Gohr $result = mysql_db_query($this->conf['db_database'],$sql_string,$link); 78094171ff3SAndreas Gohr if(!$result){ 7812812a751SAndreas Gohr msg('DB Error: '.mysql_error($link).' '.hsc($sql_string),-1); 7821878f16fSAndreas Gohr return null; 7831878f16fSAndreas Gohr } 7841878f16fSAndreas Gohr 7851878f16fSAndreas Gohr $resultarray = array(); 7861878f16fSAndreas Gohr 7871878f16fSAndreas Gohr //mysql_db_query returns 1 on a insert statement -> no need to ask for results 7881878f16fSAndreas Gohr if ($result != 1) { 7891878f16fSAndreas Gohr for($i=0; $i< mysql_num_rows($result); $i++) { 7901878f16fSAndreas Gohr $temparray = mysql_fetch_assoc($result); 7911878f16fSAndreas Gohr $resultarray[]=$temparray; 7921878f16fSAndreas Gohr } 7931878f16fSAndreas Gohr mysql_free_result($result); 7941878f16fSAndreas Gohr } 7951878f16fSAndreas Gohr 79614d99ec0SAndreas Gohr if (mysql_insert_id($link)) { 79714d99ec0SAndreas Gohr $resultarray = mysql_insert_id($link); //give back ID on insert 7981878f16fSAndreas Gohr } 7991878f16fSAndreas Gohr 8001878f16fSAndreas Gohr return $resultarray; 8011878f16fSAndreas Gohr } 8021878f16fSAndreas Gohr 8031878f16fSAndreas Gohr /** 80414d99ec0SAndreas Gohr * Returns a short name for a User Agent and sets type, version and os info 8051878f16fSAndreas Gohr */ 80614d99ec0SAndreas Gohr function ua_info($ua,&$type,&$ver,&$os){ 80714d99ec0SAndreas Gohr $ua = strtr($ua,' +','__'); 80814d99ec0SAndreas Gohr $ua = strtolower($ua); 80914d99ec0SAndreas Gohr 81014d99ec0SAndreas Gohr // common browsers 81114d99ec0SAndreas Gohr $regvermsie = '/msie([+_ ]|)([\d\.]*)/i'; 81214d99ec0SAndreas Gohr $regvernetscape = '/netscape.?\/([\d\.]*)/i'; 81314d99ec0SAndreas Gohr $regverfirefox = '/firefox\/([\d\.]*)/i'; 81414d99ec0SAndreas Gohr $regversvn = '/svn\/([\d\.]*)/i'; 81514d99ec0SAndreas Gohr $regvermozilla = '/mozilla(\/|)([\d\.]*)/i'; 81614d99ec0SAndreas Gohr $regnotie = '/webtv|omniweb|opera/i'; 81714d99ec0SAndreas Gohr $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i'; 81814d99ec0SAndreas Gohr 81914d99ec0SAndreas Gohr $name = ''; 82014d99ec0SAndreas Gohr # IE ? 82114d99ec0SAndreas Gohr if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){ 82214d99ec0SAndreas Gohr $type = 'browser'; 82314d99ec0SAndreas Gohr $ver = $m[2]; 82414d99ec0SAndreas Gohr $name = 'msie'; 82514d99ec0SAndreas Gohr } 82614d99ec0SAndreas Gohr # Firefox ? 82714d99ec0SAndreas Gohr elseif (preg_match($regverfirefox,$ua,$m)){ 82814d99ec0SAndreas Gohr $type = 'browser'; 82914d99ec0SAndreas Gohr $ver = $m[1]; 83014d99ec0SAndreas Gohr $name = 'firefox'; 83114d99ec0SAndreas Gohr } 83214d99ec0SAndreas Gohr # Subversion ? 83314d99ec0SAndreas Gohr elseif (preg_match($regversvn,$ua,$m)){ 83414d99ec0SAndreas Gohr $type = 'rcs'; 83514d99ec0SAndreas Gohr $ver = $m[1]; 83614d99ec0SAndreas Gohr $name = 'svn'; 83714d99ec0SAndreas Gohr } 83814d99ec0SAndreas Gohr # Netscape 6.x, 7.x ... ? 83914d99ec0SAndreas Gohr elseif (preg_match($regvernetscape,$ua,$m)){ 84014d99ec0SAndreas Gohr $type = 'browser'; 84114d99ec0SAndreas Gohr $ver = $m[1]; 84214d99ec0SAndreas Gohr $name = 'netscape'; 84314d99ec0SAndreas Gohr } 84414d99ec0SAndreas Gohr # Netscape 3.x, 4.x ... ? 84514d99ec0SAndreas Gohr elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){ 84614d99ec0SAndreas Gohr $type = 'browser'; 84714d99ec0SAndreas Gohr $ver = $m[2]; 84814d99ec0SAndreas Gohr $name = 'netscape'; 84914d99ec0SAndreas Gohr }else{ 85014d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/browsers.php'); 85114d99ec0SAndreas Gohr foreach($BrowsersSearchIDOrder as $regex){ 85214d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 85314d99ec0SAndreas Gohr // it's a browser! 85414d99ec0SAndreas Gohr $type = 'browser'; 85514d99ec0SAndreas Gohr $name = strtolower($regex); 85614d99ec0SAndreas Gohr break; 85714d99ec0SAndreas Gohr } 85814d99ec0SAndreas Gohr } 85914d99ec0SAndreas Gohr } 86014d99ec0SAndreas Gohr 86175fa767dSAndreas Gohr // check versions for Safari and Opera 86275fa767dSAndreas Gohr if($name == 'safari'){ 86375fa767dSAndreas Gohr if(preg_match('/safari\/([\d\.]*)/i',$ua,$match)){ 86475fa767dSAndreas Gohr $ver = $BrowsersSafariBuildToVersionHash[$match[1]]; 86575fa767dSAndreas Gohr } 86675fa767dSAndreas Gohr }elseif($name == 'opera'){ 86775fa767dSAndreas Gohr if(preg_match('/opera[\/ ]([\d\.]*)/i',$ua,$match)){ 86875fa767dSAndreas Gohr $ver = $match[1]; 86975fa767dSAndreas Gohr } 87075fa767dSAndreas Gohr } 87175fa767dSAndreas Gohr 87275fa767dSAndreas Gohr 87314d99ec0SAndreas Gohr // check OS for browsers 87414d99ec0SAndreas Gohr if($type == 'browser'){ 87514d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/operating_systems.php'); 87614d99ec0SAndreas Gohr foreach($OSSearchIDOrder as $regex){ 87714d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 87814d99ec0SAndreas Gohr $os = $OSHashID[$regex]; 87914d99ec0SAndreas Gohr break; 88014d99ec0SAndreas Gohr } 88114d99ec0SAndreas Gohr } 88214d99ec0SAndreas Gohr 88314d99ec0SAndreas Gohr } 88414d99ec0SAndreas Gohr 88514d99ec0SAndreas Gohr // are we done now? 88614d99ec0SAndreas Gohr if($name) return $name; 88714d99ec0SAndreas Gohr 88814d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/robots.php'); 88914d99ec0SAndreas Gohr foreach($RobotsSearchIDOrder as $regex){ 89014d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 89114d99ec0SAndreas Gohr // it's a robot! 89214d99ec0SAndreas Gohr $type = 'robot'; 89314d99ec0SAndreas Gohr return strtolower($regex); 89414d99ec0SAndreas Gohr } 89514d99ec0SAndreas Gohr } 89614d99ec0SAndreas Gohr 89714d99ec0SAndreas Gohr // dunno 8981878f16fSAndreas Gohr return ''; 8991878f16fSAndreas Gohr } 9001878f16fSAndreas Gohr 9011878f16fSAndreas Gohr /** 90214d99ec0SAndreas Gohr * 90314d99ec0SAndreas Gohr * @fixme: put search engine queries in seperate table here 90414d99ec0SAndreas Gohr */ 90514d99ec0SAndreas Gohr function log_search($referer,&$type){ 90614d99ec0SAndreas Gohr $referer = strtr($referer,' +','__'); 90714d99ec0SAndreas Gohr $referer = strtolower($referer); 90814d99ec0SAndreas Gohr 90914d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/search_engines.php'); 91014d99ec0SAndreas Gohr 91114d99ec0SAndreas Gohr foreach($SearchEnginesSearchIDOrder as $regex){ 91214d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$referer)){ 91314d99ec0SAndreas Gohr if(!$NotSearchEnginesKeys[$regex] || 91414d99ec0SAndreas Gohr !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$referer)){ 91514d99ec0SAndreas Gohr // it's a search engine! 91614d99ec0SAndreas Gohr $type = 'search'; 91714d99ec0SAndreas Gohr break; 91814d99ec0SAndreas Gohr } 91914d99ec0SAndreas Gohr } 92014d99ec0SAndreas Gohr } 92114d99ec0SAndreas Gohr if($type != 'search') return; // we're done here 92214d99ec0SAndreas Gohr 92314d99ec0SAndreas Gohr #fixme now do the keyword magic! 92414d99ec0SAndreas Gohr } 92514d99ec0SAndreas Gohr 92614d99ec0SAndreas Gohr /** 92714d99ec0SAndreas Gohr * Resolve IP to country/city 92814d99ec0SAndreas Gohr */ 92914d99ec0SAndreas Gohr function log_ip($ip){ 93014d99ec0SAndreas Gohr // check if IP already known and up-to-date 93114d99ec0SAndreas Gohr $sql = "SELECT ip 93214d99ec0SAndreas Gohr FROM ".$this->getConf('db_prefix')."iplocation 93314d99ec0SAndreas Gohr WHERE ip ='".addslashes($ip)."' 93414d99ec0SAndreas Gohr AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)"; 93514d99ec0SAndreas Gohr $result = $this->runSQL($sql); 93614d99ec0SAndreas Gohr if($result[0]['ip']) return; 93714d99ec0SAndreas Gohr 93814d99ec0SAndreas Gohr $http = new DokuHTTPClient(); 93914d99ec0SAndreas Gohr $http->timeout = 10; 94014d99ec0SAndreas Gohr $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip); 94114d99ec0SAndreas Gohr 94214d99ec0SAndreas Gohr if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){ 94314d99ec0SAndreas Gohr $country = addslashes(trim($match[1])); 94414d99ec0SAndreas Gohr $code = addslashes(strtolower(trim($match[2]))); 94514d99ec0SAndreas Gohr $city = addslashes(trim($match[3])); 94614d99ec0SAndreas Gohr $host = addslashes(gethostbyaddr($ip)); 94714d99ec0SAndreas Gohr $ip = addslashes($ip); 94814d99ec0SAndreas Gohr 94914d99ec0SAndreas Gohr $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation 95014d99ec0SAndreas Gohr SET ip = '$ip', 95114d99ec0SAndreas Gohr country = '$country', 95214d99ec0SAndreas Gohr code = '$code', 95314d99ec0SAndreas Gohr city = '$city', 95414d99ec0SAndreas Gohr host = '$host'"; 95514d99ec0SAndreas Gohr $this->runSQL($sql); 95614d99ec0SAndreas Gohr } 95714d99ec0SAndreas Gohr } 95814d99ec0SAndreas Gohr 95914d99ec0SAndreas Gohr /** 9601878f16fSAndreas Gohr * log a page access 9611878f16fSAndreas Gohr * 9621878f16fSAndreas Gohr * called from log.php 9631878f16fSAndreas Gohr */ 9641878f16fSAndreas Gohr function log_access(){ 96594171ff3SAndreas Gohr if(!$_REQUEST['p']) return; 96694171ff3SAndreas Gohr 96714d99ec0SAndreas Gohr # FIXME check referer against blacklist and drop logging for bad boys 96814d99ec0SAndreas Gohr 96914d99ec0SAndreas Gohr // handle referer 97014d99ec0SAndreas Gohr $referer = trim($_REQUEST['r']); 97114d99ec0SAndreas Gohr if($referer){ 97214d99ec0SAndreas Gohr $ref = addslashes($referer); 97314d99ec0SAndreas Gohr $ref_md5 = ($ref) ? md5($referer) : ''; 97414d99ec0SAndreas Gohr if(strpos($referer,DOKU_URL) === 0){ 97514d99ec0SAndreas Gohr $ref_type = 'internal'; 97614d99ec0SAndreas Gohr }else{ 97714d99ec0SAndreas Gohr $ref_type = 'external'; 97814d99ec0SAndreas Gohr $this->log_search($referer,$ref_type); 97914d99ec0SAndreas Gohr } 98014d99ec0SAndreas Gohr }else{ 98114d99ec0SAndreas Gohr $ref = ''; 98214d99ec0SAndreas Gohr $ref_md5 = ''; 98314d99ec0SAndreas Gohr $ref_type = ''; 98414d99ec0SAndreas Gohr } 98514d99ec0SAndreas Gohr 98614d99ec0SAndreas Gohr // handle user agent 98714d99ec0SAndreas Gohr $agent = trim($_SERVER['HTTP_USER_AGENT']); 98814d99ec0SAndreas Gohr 98914d99ec0SAndreas Gohr $ua = addslashes($agent); 99014d99ec0SAndreas Gohr $ua_type = ''; 99114d99ec0SAndreas Gohr $ua_ver = ''; 99214d99ec0SAndreas Gohr $os = ''; 99314d99ec0SAndreas Gohr $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os)); 99414d99ec0SAndreas Gohr 9951878f16fSAndreas Gohr $page = addslashes($_REQUEST['p']); 9961878f16fSAndreas Gohr $ip = addslashes($_SERVER['REMOTE_ADDR']); 9971878f16fSAndreas Gohr $sx = (int) $_REQUEST['sx']; 9981878f16fSAndreas Gohr $sy = (int) $_REQUEST['sy']; 9991878f16fSAndreas Gohr $vx = (int) $_REQUEST['vx']; 10001878f16fSAndreas Gohr $vy = (int) $_REQUEST['vy']; 100175fa767dSAndreas Gohr $js = (int) $_REQUEST['js']; 1002*3c0acc14SAndreas Gohr $uid = addslashes($_REQUEST['uid']); 10031878f16fSAndreas Gohr $user = addslashes($_SERVER['REMOTE_USER']); 10041878f16fSAndreas Gohr $session = addslashes(session_id()); 1005*3c0acc14SAndreas Gohr if(!$uid) $uid = $session; 10061878f16fSAndreas Gohr 100794171ff3SAndreas Gohr $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access 100875fa767dSAndreas Gohr SET dt = NOW(), 100975fa767dSAndreas Gohr page = '$page', 10101878f16fSAndreas Gohr ip = '$ip', 10111878f16fSAndreas Gohr ua = '$ua', 10121878f16fSAndreas Gohr ua_info = '$ua_info', 101314d99ec0SAndreas Gohr ua_type = '$ua_type', 101414d99ec0SAndreas Gohr ua_ver = '$ua_ver', 101514d99ec0SAndreas Gohr os = '$os', 10161878f16fSAndreas Gohr ref = '$ref', 101794171ff3SAndreas Gohr ref_md5 = '$ref_md5', 101814d99ec0SAndreas Gohr ref_type = '$ref_type', 10191878f16fSAndreas Gohr screen_x = '$sx', 10201878f16fSAndreas Gohr screen_y = '$sy', 10211878f16fSAndreas Gohr view_x = '$vx', 10221878f16fSAndreas Gohr view_y = '$vy', 102375fa767dSAndreas Gohr js = '$js', 10241878f16fSAndreas Gohr user = '$user', 1025*3c0acc14SAndreas Gohr session = '$session', 1026*3c0acc14SAndreas Gohr uid = '$uid'"; 10271878f16fSAndreas Gohr $ok = $this->runSQL($sql); 10281878f16fSAndreas Gohr if(is_null($ok)){ 10291878f16fSAndreas Gohr global $MSG; 10301878f16fSAndreas Gohr print_r($MSG); 10311878f16fSAndreas Gohr } 103214d99ec0SAndreas Gohr 103314d99ec0SAndreas Gohr // resolve the IP 103414d99ec0SAndreas Gohr $this->log_ip($_SERVER['REMOTE_ADDR']); 10351878f16fSAndreas Gohr } 10361878f16fSAndreas Gohr 10371878f16fSAndreas Gohr /** 10381878f16fSAndreas Gohr * Just send a 1x1 pixel blank gif to the browser 10391878f16fSAndreas Gohr * 10401878f16fSAndreas Gohr * @called from log.php 10411878f16fSAndreas Gohr * 10421878f16fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 10431878f16fSAndreas Gohr * @author Harry Fuecks <fuecks@gmail.com> 10441878f16fSAndreas Gohr */ 10451878f16fSAndreas Gohr function sendGIF(){ 10461878f16fSAndreas Gohr $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); 10471878f16fSAndreas Gohr header('Content-Type: image/gif'); 10481878f16fSAndreas Gohr header('Content-Length: '.strlen($img)); 10491878f16fSAndreas Gohr header('Connection: Close'); 10501878f16fSAndreas Gohr print $img; 10511878f16fSAndreas Gohr flush(); 10521878f16fSAndreas Gohr // Browser should drop connection after this 10531878f16fSAndreas Gohr // Thinks it's got the whole image 10541878f16fSAndreas Gohr } 10551878f16fSAndreas Gohr 10561878f16fSAndreas Gohr} 1057