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; 97*c73e16f1SAndreas Gohr case 'resolution': 98*c73e16f1SAndreas Gohr $this->html_resolution(); 99*c73e16f1SAndreas 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 141*c73e16f1SAndreas Gohr echo '<li><div class="li">'; 142*c73e16f1SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=resolution&f='.$this->from.'&t='.$this->to.'">Resolution</a>'; 143*c73e16f1SAndreas Gohr echo '</div></li>'; 144*c73e16f1SAndreas 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>'; 2332812a751SAndreas Gohr echo '<li><span>'.$result['sessions'].'</span> visitors (sessions)</li>'; 2342812a751SAndreas Gohr echo '<li><span>'.$result['users'].'</span> logged in users</li>'; 2352812a751SAndreas Gohr 2362812a751SAndreas Gohr echo '</ul>'; 2372812a751SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=trend&f='.$this->from.'&t='.$this->to.'" />'; 2382812a751SAndreas Gohr echo '</div>'; 2392812a751SAndreas Gohr 24014d99ec0SAndreas Gohr 24187d5e44bSAndreas Gohr // top pages today 242264f1744SAndreas Gohr echo '<div>'; 243264f1744SAndreas Gohr echo '<h2>Most popular pages</h2>'; 24495eb68e6SAndreas Gohr $result = $this->sql_pages($this->tlimit,$this->start,15); 2452812a751SAndreas Gohr $this->html_resulttable($result); 2462507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=page&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 247264f1744SAndreas Gohr echo '</div>'; 24887d5e44bSAndreas Gohr 24987d5e44bSAndreas Gohr // top referer today 250264f1744SAndreas Gohr echo '<div>'; 251e7a2f1e0SAndreas Gohr echo '<h2>Newest incoming links</h2>'; 252e7a2f1e0SAndreas Gohr $result = $this->sql_newreferer($this->tlimit,$this->start,15); 2532812a751SAndreas Gohr $this->html_resulttable($result); 2542507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=newreferer&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 255264f1744SAndreas Gohr echo '</div>'; 25654f6c432SAndreas Gohr 25754f6c432SAndreas Gohr // top countries today 258264f1744SAndreas Gohr echo '<div>'; 259264f1744SAndreas Gohr echo '<h2>Visitor\'s top countries</h2>'; 26095eb68e6SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&f='.$this->from.'&t='.$this->to.'" />'; 2612507f8e0SAndreas Gohr echo '<a href="?do=admin&page=statistics&opt=country&f='.$this->from.'&t='.$this->to.'" class="more">more</a>'; 262264f1744SAndreas Gohr echo '</div>'; 263264f1744SAndreas Gohr 264264f1744SAndreas Gohr echo '</div>'; 26514d99ec0SAndreas Gohr } 26614d99ec0SAndreas Gohr 2679da6395dSAndreas Gohr function html_country(){ 2689da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 2699da6395dSAndreas Gohr echo '<h2>Visitor\'s Countries</h2>'; 270bd4217d3SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&f='.$this->from.'&t='.$this->to.'" />'; 2719da6395dSAndreas Gohr $result = $this->sql_countries($this->tlimit,$this->start,150); 2722507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 2739da6395dSAndreas Gohr echo '</div>'; 2749da6395dSAndreas Gohr } 2759da6395dSAndreas Gohr 2769da6395dSAndreas Gohr function html_page(){ 2779da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 2789da6395dSAndreas Gohr echo '<h2>Popular Pages</h2>'; 2799da6395dSAndreas Gohr $result = $this->sql_pages($this->tlimit,$this->start,150); 2802507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 2819da6395dSAndreas Gohr echo '</div>'; 2829da6395dSAndreas Gohr } 2839da6395dSAndreas Gohr 28475fa767dSAndreas Gohr function html_browser(){ 28575fa767dSAndreas Gohr echo '<div class="plg_stats_full">'; 28675fa767dSAndreas Gohr echo '<h2>Browser Shootout</h2>'; 28775fa767dSAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browser&f='.$this->from.'&t='.$this->to.'" />'; 28875fa767dSAndreas Gohr $result = $this->sql_browsers($this->tlimit,$this->start,150,true); 2892507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 29075fa767dSAndreas Gohr echo '</div>'; 29175fa767dSAndreas Gohr } 29275fa767dSAndreas Gohr 293bd4217d3SAndreas Gohr function html_os(){ 294bd4217d3SAndreas Gohr echo '<div class="plg_stats_full">'; 295bd4217d3SAndreas Gohr echo '<h2>Operating Systems</h2>'; 296bd4217d3SAndreas Gohr $result = $this->sql_os($this->tlimit,$this->start,150,true); 2972507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 298bd4217d3SAndreas Gohr echo '</div>'; 299bd4217d3SAndreas Gohr } 300bd4217d3SAndreas Gohr 3019da6395dSAndreas Gohr function html_referer(){ 3029da6395dSAndreas Gohr echo '<div class="plg_stats_full">'; 3039da6395dSAndreas Gohr echo '<h2>Incoming Links</h2>'; 3042812a751SAndreas Gohr $result = $this->sql_aggregate($this->tlimit); 3052812a751SAndreas Gohr 3062812a751SAndreas Gohr $all = $result['search']+$result['external']+$result['direct']; 3072812a751SAndreas Gohr 30894023548SAndreas Gohr if($all){ 3092812a751SAndreas Gohr printf("<p>Of all %d external visits, %d (%.1f%%) were bookmarked (direct) accesses, 3102812a751SAndreas Gohr %d (%.1f%%) came from search engines and %d (%.1f%%) were referred through 3112812a751SAndreas Gohr links from other pages.</p>",$all,$result['direct'],(100*$result['direct']/$all), 3122812a751SAndreas Gohr $result['search'],(100*$result['search']/$all),$result['external'], 3132812a751SAndreas Gohr (100*$result['external']/$all)); 31494023548SAndreas Gohr } 3152812a751SAndreas Gohr 3169da6395dSAndreas Gohr $result = $this->sql_referer($this->tlimit,$this->start,150); 3172507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 3189da6395dSAndreas Gohr echo '</div>'; 3199da6395dSAndreas Gohr } 3209da6395dSAndreas Gohr 321e7a2f1e0SAndreas Gohr function html_newreferer(){ 322e7a2f1e0SAndreas Gohr echo '<div class="plg_stats_full">'; 323e7a2f1e0SAndreas Gohr echo '<h2>New Incoming Links</h2>'; 324e7a2f1e0SAndreas Gohr echo '<p>The following incoming links where first logged in the selected time frame, 325e7a2f1e0SAndreas Gohr and have never been seen before.</p>'; 326e7a2f1e0SAndreas Gohr 327e7a2f1e0SAndreas Gohr $result = $this->sql_newreferer($this->tlimit,$this->start,150); 3282507f8e0SAndreas Gohr $this->html_resulttable($result,'',150); 329e7a2f1e0SAndreas Gohr echo '</div>'; 330e7a2f1e0SAndreas Gohr } 331e7a2f1e0SAndreas Gohr 332*c73e16f1SAndreas Gohr function html_resolution(){ 333*c73e16f1SAndreas Gohr echo '<div class="plg_stats_full">'; 334*c73e16f1SAndreas Gohr echo '<h2>Resolution</h2>'; 335*c73e16f1SAndreas Gohr $result = $this->sql_resolution($this->tlimit,$this->start,150); 336*c73e16f1SAndreas Gohr $this->html_resulttable($result,'',150); 337*c73e16f1SAndreas Gohr 338*c73e16f1SAndreas Gohr echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you 339*c73e16f1SAndreas Gohr much about about the real size of their browser windows. The graphic below shows the size distribution of 340*c73e16f1SAndreas Gohr the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged 341*c73e16f1SAndreas Gohr in all browsers. Because users may resize their browser window while browsing your site the statistics may 342*c73e16f1SAndreas Gohr be flawed. Take it with a grain of salt.</p>'; 343*c73e16f1SAndreas Gohr 344*c73e16f1SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=view&f='.$this->from.'&t='.$this->to.'" />'; 345*c73e16f1SAndreas Gohr echo '</div>'; 346*c73e16f1SAndreas Gohr } 3479da6395dSAndreas Gohr 3489da6395dSAndreas Gohr 34914d99ec0SAndreas Gohr /** 35014d99ec0SAndreas Gohr * Display a result in a HTML table 35114d99ec0SAndreas Gohr */ 3522507f8e0SAndreas Gohr function html_resulttable($result,$header='',$pager=0){ 35314d99ec0SAndreas Gohr echo '<table>'; 3542812a751SAndreas Gohr if(is_array($header)){ 35514d99ec0SAndreas Gohr echo '<tr>'; 35614d99ec0SAndreas Gohr foreach($header as $h){ 35714d99ec0SAndreas Gohr echo '<th>'.hsc($h).'</th>'; 35814d99ec0SAndreas Gohr } 35914d99ec0SAndreas Gohr echo '</tr>'; 3602812a751SAndreas Gohr } 36114d99ec0SAndreas Gohr 3622507f8e0SAndreas Gohr $count = 0; 36314d99ec0SAndreas Gohr foreach($result as $row){ 36414d99ec0SAndreas Gohr echo '<tr>'; 36514d99ec0SAndreas Gohr foreach($row as $k => $v){ 3662812a751SAndreas Gohr echo '<td class="plg_stats_X'.$k.'">'; 36714d99ec0SAndreas Gohr if($k == 'page'){ 36814d99ec0SAndreas Gohr echo '<a href="'.wl($v).'" class="wikilink1">'; 36914d99ec0SAndreas Gohr echo hsc($v); 37014d99ec0SAndreas Gohr echo '</a>'; 37114d99ec0SAndreas Gohr }elseif($k == 'url'){ 37254f6c432SAndreas Gohr $url = hsc($v); 3732812a751SAndreas Gohr if(strlen($url) > 45){ 3742812a751SAndreas Gohr $url = substr($url,0,30).' … '.substr($url,-15); 37554f6c432SAndreas Gohr } 37614d99ec0SAndreas Gohr echo '<a href="'.$v.'" class="urlextern">'; 37754f6c432SAndreas Gohr echo $url; 37814d99ec0SAndreas Gohr echo '</a>'; 37975fa767dSAndreas Gohr }elseif($k == 'browser'){ 38075fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 38175fa767dSAndreas Gohr echo $BrowsersHashIDLib[$v]; 38275fa767dSAndreas Gohr }elseif($k == 'bflag'){ 38375fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 38475fa767dSAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.$BrowsersHashIcon[$v].'.png" alt="'.hsc($v).'" />'; 385bd4217d3SAndreas Gohr }elseif($k == 'os'){ 386bd4217d3SAndreas Gohr if(empty($v)){ 387bd4217d3SAndreas Gohr echo 'unknown'; 388bd4217d3SAndreas Gohr }else{ 389bd4217d3SAndreas Gohr include_once(dirname(__FILE__).'/inc/operating_systems.php'); 390bd4217d3SAndreas Gohr echo $OSHashLib[$v]; 391bd4217d3SAndreas Gohr } 392bd4217d3SAndreas Gohr }elseif($k == 'osflag'){ 393bd4217d3SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.hsc($v).'.png" alt="'.hsc($v).'" />'; 39475fa767dSAndreas Gohr }elseif($k == 'cflag'){ 39575fa767dSAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; 39614d99ec0SAndreas Gohr }elseif($k == 'html'){ 39714d99ec0SAndreas Gohr echo $v; 39814d99ec0SAndreas Gohr }else{ 39914d99ec0SAndreas Gohr echo hsc($v); 40014d99ec0SAndreas Gohr } 40114d99ec0SAndreas Gohr echo '</td>'; 40214d99ec0SAndreas Gohr } 40314d99ec0SAndreas Gohr echo '</tr>'; 4042507f8e0SAndreas Gohr 4052507f8e0SAndreas Gohr if($pager && ($count == $pager)) break; 4062507f8e0SAndreas Gohr $count++; 40714d99ec0SAndreas Gohr } 40814d99ec0SAndreas Gohr echo '</table>'; 4092507f8e0SAndreas Gohr 4102507f8e0SAndreas Gohr if($pager) $this->html_pager($pager,count($result) > $pager); 4111878f16fSAndreas Gohr } 4121878f16fSAndreas Gohr 41395eb68e6SAndreas Gohr /** 41495eb68e6SAndreas Gohr * Create an image 41595eb68e6SAndreas Gohr */ 41695eb68e6SAndreas Gohr function img_build($img){ 41795eb68e6SAndreas Gohr include(dirname(__FILE__).'/inc/AGC.class.php'); 41895eb68e6SAndreas Gohr 41995eb68e6SAndreas Gohr switch($img){ 42095eb68e6SAndreas Gohr case 'country': 42195eb68e6SAndreas Gohr // build top countries + other 42295eb68e6SAndreas Gohr $result = $this->sql_countries($this->tlimit,$this->start,0); 42395eb68e6SAndreas Gohr $data = array(); 42495eb68e6SAndreas Gohr $top = 0; 42595eb68e6SAndreas Gohr foreach($result as $row){ 42695eb68e6SAndreas Gohr if($top < 7){ 42795eb68e6SAndreas Gohr $data[$row['country']] = $row['cnt']; 42895eb68e6SAndreas Gohr }else{ 42995eb68e6SAndreas Gohr $data['other'] += $row['cnt']; 43095eb68e6SAndreas Gohr } 43195eb68e6SAndreas Gohr $top++; 43295eb68e6SAndreas Gohr } 43395eb68e6SAndreas Gohr $pie = new AGC(300, 200); 43495eb68e6SAndreas Gohr $pie->setProp("showkey",true); 43595eb68e6SAndreas Gohr $pie->setProp("showval",false); 43695eb68e6SAndreas Gohr $pie->setProp("showgrid",false); 43795eb68e6SAndreas Gohr $pie->setProp("type","pie"); 43895eb68e6SAndreas Gohr $pie->setProp("keyinfo",1); 43995eb68e6SAndreas Gohr $pie->setProp("keysize",8); 44095eb68e6SAndreas Gohr $pie->setProp("keywidspc",-50); 44195eb68e6SAndreas Gohr $pie->setProp("key",array_keys($data)); 44295eb68e6SAndreas Gohr $pie->addBulkPoints(array_values($data)); 44395eb68e6SAndreas Gohr @$pie->graph(); 44495eb68e6SAndreas Gohr $pie->showGraph(); 44595eb68e6SAndreas Gohr break; 44675fa767dSAndreas Gohr case 'browser': 44775fa767dSAndreas Gohr // build top browsers + other 44875fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 44975fa767dSAndreas Gohr 45075fa767dSAndreas Gohr $result = $this->sql_browsers($this->tlimit,$this->start,0,false); 45175fa767dSAndreas Gohr $data = array(); 45275fa767dSAndreas Gohr $top = 0; 45375fa767dSAndreas Gohr foreach($result as $row){ 45475fa767dSAndreas Gohr if($top < 5){ 45575fa767dSAndreas Gohr $data[strip_tags($BrowsersHashIDLib[$row['ua_info']])] = $row['cnt']; 45675fa767dSAndreas Gohr }else{ 45775fa767dSAndreas Gohr $data['other'] += $row['cnt']; 45875fa767dSAndreas Gohr } 45975fa767dSAndreas Gohr $top++; 46075fa767dSAndreas Gohr } 46175fa767dSAndreas Gohr $pie = new AGC(300, 200); 46275fa767dSAndreas Gohr $pie->setProp("showkey",true); 46375fa767dSAndreas Gohr $pie->setProp("showval",false); 46475fa767dSAndreas Gohr $pie->setProp("showgrid",false); 46575fa767dSAndreas Gohr $pie->setProp("type","pie"); 46675fa767dSAndreas Gohr $pie->setProp("keyinfo",1); 46775fa767dSAndreas Gohr $pie->setProp("keysize",8); 46875fa767dSAndreas Gohr $pie->setProp("keywidspc",-50); 46975fa767dSAndreas Gohr $pie->setProp("key",array_keys($data)); 47075fa767dSAndreas Gohr $pie->addBulkPoints(array_values($data)); 47175fa767dSAndreas Gohr @$pie->graph(); 47275fa767dSAndreas Gohr $pie->showGraph(); 47375fa767dSAndreas Gohr break; 474*c73e16f1SAndreas Gohr case 'view': 475*c73e16f1SAndreas Gohr 476*c73e16f1SAndreas Gohr $graph = new AGC(400, 200); 477*c73e16f1SAndreas Gohr $graph->setColor('color',0,'blue'); 478*c73e16f1SAndreas Gohr $graph->setColor('color',1,'red'); 479*c73e16f1SAndreas Gohr $graph->setProp("showkey",true); 480*c73e16f1SAndreas Gohr $graph->setProp("key",'view port width',0); 481*c73e16f1SAndreas Gohr $graph->setProp("key",'view port height',1); 482*c73e16f1SAndreas Gohr 483*c73e16f1SAndreas Gohr $result = $this->sql_viewport($this->tlimit,0,0,true); 484*c73e16f1SAndreas Gohr foreach($result as $row){ 485*c73e16f1SAndreas Gohr $graph->addPoint($row['cnt'],$row['res_x'],0); 486*c73e16f1SAndreas Gohr } 487*c73e16f1SAndreas Gohr 488*c73e16f1SAndreas Gohr $result = $this->sql_viewport($this->tlimit,0,0,false); 489*c73e16f1SAndreas Gohr foreach($result as $row){ 490*c73e16f1SAndreas Gohr $graph->addPoint($row['cnt'],$row['res_y'],1); 491*c73e16f1SAndreas Gohr } 492*c73e16f1SAndreas Gohr 493*c73e16f1SAndreas Gohr @$graph->graph(); 494*c73e16f1SAndreas Gohr $graph->showGraph(); 495*c73e16f1SAndreas Gohr 496*c73e16f1SAndreas Gohr break; 4972812a751SAndreas Gohr case 'trend': 4982812a751SAndreas Gohr $hours = ($this->from == $this->to); 4992812a751SAndreas Gohr $result = $this->sql_trend($this->tlimit,$hours); 5002812a751SAndreas Gohr $data1 = array(); 5012812a751SAndreas Gohr $data2 = array(); 5022812a751SAndreas Gohr 5032812a751SAndreas Gohr $graph = new AGC(400, 150); 5042812a751SAndreas Gohr $graph->setProp("type","bar"); 5052812a751SAndreas Gohr $graph->setProp("showgrid",false); 5062812a751SAndreas Gohr $graph->setProp("barwidth",.8); 50775fa767dSAndreas Gohr 5082812a751SAndreas Gohr $graph->setColor('color',0,'blue'); 5092812a751SAndreas Gohr $graph->setColor('color',1,'red'); 5102812a751SAndreas Gohr 5112812a751SAndreas Gohr if($hours){ 5122812a751SAndreas Gohr //preset $hours 5132812a751SAndreas Gohr for($i=0;$i<24;$i++){ 5142812a751SAndreas Gohr $data1[$i] = 0; 5152812a751SAndreas Gohr $data2[$i] = 0; 5162812a751SAndreas Gohr $graph->setProp("scale",array(' 0h',' 4h',' 8h',' 12h',' 16h',' 20h',' 24h')); 5172812a751SAndreas Gohr } 5182812a751SAndreas Gohr }else{ 5192812a751SAndreas Gohr $graph->setProp("scale",array(next(array_keys($data1)),$this->to)); 5202812a751SAndreas Gohr } 5212812a751SAndreas Gohr 5222812a751SAndreas Gohr foreach($result as $row){ 5232812a751SAndreas Gohr $data1[$row['time']] = $row['pageviews']; 5242812a751SAndreas Gohr $data2[$row['time']] = $row['sessions']; 5252812a751SAndreas Gohr } 5262812a751SAndreas Gohr 5272812a751SAndreas Gohr foreach($data1 as $key => $val){ 5282812a751SAndreas Gohr $graph->addPoint($val,$key,0); 5292812a751SAndreas Gohr } 5302812a751SAndreas Gohr foreach($data2 as $key => $val){ 5312812a751SAndreas Gohr $graph->addPoint($val,$key,1); 5322812a751SAndreas Gohr } 5332812a751SAndreas Gohr 5342812a751SAndreas Gohr @$graph->graph(); 5352812a751SAndreas Gohr $graph->showGraph(); 5362812a751SAndreas Gohr 53795eb68e6SAndreas Gohr default: 53895eb68e6SAndreas Gohr $this->sendGIF(); 53995eb68e6SAndreas Gohr } 54095eb68e6SAndreas Gohr } 54195eb68e6SAndreas Gohr 54295eb68e6SAndreas Gohr 5432812a751SAndreas Gohr /** 5442812a751SAndreas Gohr * Return some aggregated statistics 5452812a751SAndreas Gohr */ 5462812a751SAndreas Gohr function sql_aggregate($tlimit){ 5472812a751SAndreas Gohr $data = array(); 5482812a751SAndreas Gohr 5492812a751SAndreas Gohr $sql = "SELECT ref_type, COUNT(*) as cnt 5502812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5512812a751SAndreas Gohr WHERE $tlimit 5522812a751SAndreas Gohr AND ua_type = 'browser' 5532812a751SAndreas Gohr GROUP BY ref_type"; 5542812a751SAndreas Gohr $result = $this->runSQL($sql); 5552812a751SAndreas Gohr 5562812a751SAndreas Gohr foreach($result as $row){ 5572812a751SAndreas Gohr if($row['ref_type'] == 'search') $data['search'] = $row['cnt']; 5582812a751SAndreas Gohr if($row['ref_type'] == 'external') $data['external'] = $row['cnt']; 5592812a751SAndreas Gohr if($row['ref_type'] == 'internal') $data['internal'] = $row['cnt']; 5602812a751SAndreas Gohr if($row['ref_type'] == '') $data['direct'] = $row['cnt']; 5612812a751SAndreas Gohr } 5622812a751SAndreas Gohr 5632812a751SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as sessions, 5642812a751SAndreas Gohr COUNT(session) as views, 5652812a751SAndreas Gohr COUNT(DISTINCT user) as users 5662812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5672812a751SAndreas Gohr WHERE $tlimit 5682812a751SAndreas Gohr AND ua_type = 'browser'"; 5692812a751SAndreas Gohr $result = $this->runSQL($sql); 5702812a751SAndreas Gohr 57175fa767dSAndreas Gohr $data['users'] = max($result[0]['users'] - 1,0); // subtract empty user 5722812a751SAndreas Gohr $data['sessions'] = $result[0]['sessions']; 5732812a751SAndreas Gohr $data['pageviews'] = $result[0]['views']; 5742812a751SAndreas Gohr 5752812a751SAndreas Gohr $sql = "SELECT COUNT(id) as robots 5762812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5772812a751SAndreas Gohr WHERE $tlimit 5782812a751SAndreas Gohr AND ua_type = 'robot'"; 5792812a751SAndreas Gohr $result = $this->runSQL($sql); 5802812a751SAndreas Gohr $data['robots'] = $result[0]['robots']; 5812812a751SAndreas Gohr 5822812a751SAndreas Gohr return $data; 5832812a751SAndreas Gohr } 5842812a751SAndreas Gohr 585bd4217d3SAndreas Gohr /** 586bd4217d3SAndreas Gohr * standard statistics follow, only accesses made by browsers are counted 587bd4217d3SAndreas Gohr * for general stats like browser or OS only visitors not pageviews are counted 588bd4217d3SAndreas Gohr */ 5892812a751SAndreas Gohr function sql_trend($tlimit,$hours=false){ 5902812a751SAndreas Gohr if($hours){ 5912812a751SAndreas Gohr $sql = "SELECT HOUR(dt) as time, 5922812a751SAndreas Gohr COUNT(DISTINCT session) as sessions, 5932812a751SAndreas Gohr COUNT(session) as pageviews 5942812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5952812a751SAndreas Gohr WHERE $tlimit 5962812a751SAndreas Gohr AND ua_type = 'browser' 5972812a751SAndreas Gohr GROUP BY HOUR(dt) 5982812a751SAndreas Gohr ORDER BY time"; 5992812a751SAndreas Gohr }else{ 6002812a751SAndreas Gohr $sql = "SELECT DATE(dt) as time, 6012812a751SAndreas Gohr COUNT(DISTINCT session) as sessions, 6022812a751SAndreas Gohr COUNT(session) as pageviews 6032812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 6042812a751SAndreas Gohr WHERE $tlimit 6052812a751SAndreas Gohr AND ua_type = 'browser' 6062812a751SAndreas Gohr GROUP BY DATE(dt) 6072812a751SAndreas Gohr ORDER BY time"; 6082812a751SAndreas Gohr } 6092812a751SAndreas Gohr return $this->runSQL($sql); 6102812a751SAndreas Gohr } 6112812a751SAndreas Gohr 61295eb68e6SAndreas Gohr function sql_pages($tlimit,$start=0,$limit=20){ 6132812a751SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, page 61495eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 61595eb68e6SAndreas Gohr WHERE $tlimit 61695eb68e6SAndreas Gohr AND ua_type = 'browser' 61795eb68e6SAndreas Gohr GROUP BY page 61895eb68e6SAndreas Gohr ORDER BY cnt DESC, page". 61995eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 62095eb68e6SAndreas Gohr return $this->runSQL($sql); 62195eb68e6SAndreas Gohr } 62295eb68e6SAndreas Gohr 62395eb68e6SAndreas Gohr function sql_referer($tlimit,$start=0,$limit=20){ 6242812a751SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, ref as url 62595eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 62695eb68e6SAndreas Gohr WHERE $tlimit 62795eb68e6SAndreas Gohr AND ua_type = 'browser' 62895eb68e6SAndreas Gohr AND ref_type = 'external' 62995eb68e6SAndreas Gohr GROUP BY ref_md5 63095eb68e6SAndreas Gohr ORDER BY cnt DESC, url". 63195eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 63295eb68e6SAndreas Gohr return $this->runSQL($sql); 63395eb68e6SAndreas Gohr } 63495eb68e6SAndreas Gohr 635e7a2f1e0SAndreas Gohr function sql_newreferer($tlimit,$start=0,$limit=20){ 636e7a2f1e0SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, ref as url 637e7a2f1e0SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 638e7a2f1e0SAndreas Gohr WHERE ua_type = 'browser' 639e7a2f1e0SAndreas Gohr AND ref_type = 'external' 640e7a2f1e0SAndreas Gohr GROUP BY ref_md5 641e7a2f1e0SAndreas Gohr HAVING DATE(MIN(dt)) >= DATE('".$this->from."') 642e7a2f1e0SAndreas Gohr AND DATE(MIN(dt)) <= DATE('".$this->to."') 643e7a2f1e0SAndreas Gohr ORDER BY cnt DESC, url". 644e7a2f1e0SAndreas Gohr $this->sql_limit($start,$limit); 645e7a2f1e0SAndreas Gohr return $this->runSQL($sql); 646e7a2f1e0SAndreas Gohr } 647e7a2f1e0SAndreas Gohr 64895eb68e6SAndreas Gohr function sql_countries($tlimit,$start=0,$limit=20){ 649bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country 65095eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A, 65195eb68e6SAndreas Gohr ".$this->getConf('db_prefix')."iplocation as B 65295eb68e6SAndreas Gohr WHERE $tlimit 65395eb68e6SAndreas Gohr AND A.ip = B.ip 65495eb68e6SAndreas Gohr GROUP BY B.country 65595eb68e6SAndreas Gohr ORDER BY cnt DESC, B.country". 65695eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 65795eb68e6SAndreas Gohr return $this->runSQL($sql); 65895eb68e6SAndreas Gohr } 65995eb68e6SAndreas Gohr 66075fa767dSAndreas Gohr function sql_browsers($tlimit,$start=0,$limit=20,$ext=true){ 66175fa767dSAndreas Gohr if($ext){ 66275fa767dSAndreas Gohr $sel = 'ua_info as bflag, ua_info as browser, ua_ver'; 66375fa767dSAndreas Gohr $grp = 'ua_info, ua_ver'; 66475fa767dSAndreas Gohr }else{ 66575fa767dSAndreas Gohr $grp = 'ua_info'; 66675fa767dSAndreas Gohr $sel = 'ua_info'; 66775fa767dSAndreas Gohr } 66875fa767dSAndreas Gohr 669bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel 67075fa767dSAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 67175fa767dSAndreas Gohr WHERE $tlimit 67275fa767dSAndreas Gohr AND ua_type = 'browser' 67375fa767dSAndreas Gohr GROUP BY $grp 67475fa767dSAndreas Gohr ORDER BY cnt DESC, ua_info". 67575fa767dSAndreas Gohr $this->sql_limit($start,$limit); 67675fa767dSAndreas Gohr return $this->runSQL($sql); 67775fa767dSAndreas Gohr } 67875fa767dSAndreas Gohr 679bd4217d3SAndreas Gohr function sql_os($tlimit,$start=0,$limit=20){ 680bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os 681bd4217d3SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 682bd4217d3SAndreas Gohr WHERE $tlimit 683bd4217d3SAndreas Gohr AND ua_type = 'browser' 684bd4217d3SAndreas Gohr GROUP BY os 685bd4217d3SAndreas Gohr ORDER BY cnt DESC, os". 686bd4217d3SAndreas Gohr $this->sql_limit($start,$limit); 687bd4217d3SAndreas Gohr return $this->runSQL($sql); 688bd4217d3SAndreas Gohr } 689bd4217d3SAndreas Gohr 690*c73e16f1SAndreas Gohr function sql_resolution($tlimit,$start=0,$limit=20){ 691*c73e16f1SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, CONCAT(screen_x,'x',screen_y) as res 692*c73e16f1SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 693*c73e16f1SAndreas Gohr WHERE $tlimit 694*c73e16f1SAndreas Gohr AND ua_type = 'browser' 695*c73e16f1SAndreas Gohr AND screen_x != 0 696*c73e16f1SAndreas Gohr GROUP BY screen_x, screen_y 697*c73e16f1SAndreas Gohr ORDER BY cnt DESC, screen_x". 698*c73e16f1SAndreas Gohr $this->sql_limit($start,$limit); 699*c73e16f1SAndreas Gohr return $this->runSQL($sql); 700*c73e16f1SAndreas Gohr } 701*c73e16f1SAndreas Gohr 702*c73e16f1SAndreas Gohr function sql_viewport($tlimit,$start=0,$limit=20,$x=true){ 703*c73e16f1SAndreas Gohr if($x){ 704*c73e16f1SAndreas Gohr $col = 'view_x'; 705*c73e16f1SAndreas Gohr $res = 'res_x'; 706*c73e16f1SAndreas Gohr }else{ 707*c73e16f1SAndreas Gohr $col = 'view_y'; 708*c73e16f1SAndreas Gohr $res = 'res_y'; 709*c73e16f1SAndreas Gohr } 710*c73e16f1SAndreas Gohr 711*c73e16f1SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, 712*c73e16f1SAndreas Gohr ROUND($col/10)*10 as $res 713*c73e16f1SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 714*c73e16f1SAndreas Gohr WHERE $tlimit 715*c73e16f1SAndreas Gohr AND ua_type = 'browser' 716*c73e16f1SAndreas Gohr AND $col != 0 717*c73e16f1SAndreas Gohr GROUP BY $res 718*c73e16f1SAndreas Gohr ORDER BY cnt DESC, $res". 719*c73e16f1SAndreas Gohr $this->sql_limit($start,$limit); 720*c73e16f1SAndreas Gohr return $this->runSQL($sql); 721*c73e16f1SAndreas Gohr } 722*c73e16f1SAndreas Gohr 72375fa767dSAndreas Gohr 72495eb68e6SAndreas Gohr /** 72595eb68e6SAndreas Gohr * Builds a limit clause 72695eb68e6SAndreas Gohr */ 72795eb68e6SAndreas Gohr function sql_limit($start,$limit){ 72895eb68e6SAndreas Gohr $start = (int) $start; 72995eb68e6SAndreas Gohr $limit = (int) $limit; 73095eb68e6SAndreas Gohr if($limit){ 7312507f8e0SAndreas Gohr $limit += 1; 73295eb68e6SAndreas Gohr return " LIMIT $start,$limit"; 73395eb68e6SAndreas Gohr }elseif($start){ 73495eb68e6SAndreas Gohr return " OFFSET $start"; 73595eb68e6SAndreas Gohr } 73695eb68e6SAndreas Gohr return ''; 73795eb68e6SAndreas Gohr } 7381878f16fSAndreas Gohr 7391878f16fSAndreas Gohr /** 74014d99ec0SAndreas Gohr * Return a link to the DB, opening the connection if needed 7411878f16fSAndreas Gohr */ 74214d99ec0SAndreas Gohr function dbLink(){ 7431878f16fSAndreas Gohr // connect to DB if needed 7441878f16fSAndreas Gohr if(!$this->dblink){ 7451878f16fSAndreas Gohr $this->dblink = mysql_connect($this->getConf('db_server'), 7461878f16fSAndreas Gohr $this->getConf('db_user'), 7471878f16fSAndreas Gohr $this->getConf('db_password')); 7481878f16fSAndreas Gohr if(!$this->dblink){ 7491878f16fSAndreas Gohr msg('DB Error: connection failed',-1); 7501878f16fSAndreas Gohr return null; 7511878f16fSAndreas Gohr } 7521878f16fSAndreas Gohr // set utf-8 7531878f16fSAndreas Gohr if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){ 7541878f16fSAndreas Gohr msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1); 7551878f16fSAndreas Gohr return null; 7561878f16fSAndreas Gohr } 7571878f16fSAndreas Gohr } 75814d99ec0SAndreas Gohr return $this->dblink; 75914d99ec0SAndreas Gohr } 7601878f16fSAndreas Gohr 76114d99ec0SAndreas Gohr /** 76214d99ec0SAndreas Gohr * Simple function to run a DB query 76314d99ec0SAndreas Gohr */ 76414d99ec0SAndreas Gohr function runSQL($sql_string) { 76514d99ec0SAndreas Gohr $link = $this->dbLink(); 76614d99ec0SAndreas Gohr 76714d99ec0SAndreas Gohr $result = mysql_db_query($this->conf['db_database'],$sql_string,$link); 76894171ff3SAndreas Gohr if(!$result){ 7692812a751SAndreas Gohr msg('DB Error: '.mysql_error($link).' '.hsc($sql_string),-1); 7701878f16fSAndreas Gohr return null; 7711878f16fSAndreas Gohr } 7721878f16fSAndreas Gohr 7731878f16fSAndreas Gohr $resultarray = array(); 7741878f16fSAndreas Gohr 7751878f16fSAndreas Gohr //mysql_db_query returns 1 on a insert statement -> no need to ask for results 7761878f16fSAndreas Gohr if ($result != 1) { 7771878f16fSAndreas Gohr for($i=0; $i< mysql_num_rows($result); $i++) { 7781878f16fSAndreas Gohr $temparray = mysql_fetch_assoc($result); 7791878f16fSAndreas Gohr $resultarray[]=$temparray; 7801878f16fSAndreas Gohr } 7811878f16fSAndreas Gohr mysql_free_result($result); 7821878f16fSAndreas Gohr } 7831878f16fSAndreas Gohr 78414d99ec0SAndreas Gohr if (mysql_insert_id($link)) { 78514d99ec0SAndreas Gohr $resultarray = mysql_insert_id($link); //give back ID on insert 7861878f16fSAndreas Gohr } 7871878f16fSAndreas Gohr 7881878f16fSAndreas Gohr return $resultarray; 7891878f16fSAndreas Gohr } 7901878f16fSAndreas Gohr 7911878f16fSAndreas Gohr /** 79214d99ec0SAndreas Gohr * Returns a short name for a User Agent and sets type, version and os info 7931878f16fSAndreas Gohr */ 79414d99ec0SAndreas Gohr function ua_info($ua,&$type,&$ver,&$os){ 79514d99ec0SAndreas Gohr $ua = strtr($ua,' +','__'); 79614d99ec0SAndreas Gohr $ua = strtolower($ua); 79714d99ec0SAndreas Gohr 79814d99ec0SAndreas Gohr // common browsers 79914d99ec0SAndreas Gohr $regvermsie = '/msie([+_ ]|)([\d\.]*)/i'; 80014d99ec0SAndreas Gohr $regvernetscape = '/netscape.?\/([\d\.]*)/i'; 80114d99ec0SAndreas Gohr $regverfirefox = '/firefox\/([\d\.]*)/i'; 80214d99ec0SAndreas Gohr $regversvn = '/svn\/([\d\.]*)/i'; 80314d99ec0SAndreas Gohr $regvermozilla = '/mozilla(\/|)([\d\.]*)/i'; 80414d99ec0SAndreas Gohr $regnotie = '/webtv|omniweb|opera/i'; 80514d99ec0SAndreas Gohr $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i'; 80614d99ec0SAndreas Gohr 80714d99ec0SAndreas Gohr $name = ''; 80814d99ec0SAndreas Gohr # IE ? 80914d99ec0SAndreas Gohr if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){ 81014d99ec0SAndreas Gohr $type = 'browser'; 81114d99ec0SAndreas Gohr $ver = $m[2]; 81214d99ec0SAndreas Gohr $name = 'msie'; 81314d99ec0SAndreas Gohr } 81414d99ec0SAndreas Gohr # Firefox ? 81514d99ec0SAndreas Gohr elseif (preg_match($regverfirefox,$ua,$m)){ 81614d99ec0SAndreas Gohr $type = 'browser'; 81714d99ec0SAndreas Gohr $ver = $m[1]; 81814d99ec0SAndreas Gohr $name = 'firefox'; 81914d99ec0SAndreas Gohr } 82014d99ec0SAndreas Gohr # Subversion ? 82114d99ec0SAndreas Gohr elseif (preg_match($regversvn,$ua,$m)){ 82214d99ec0SAndreas Gohr $type = 'rcs'; 82314d99ec0SAndreas Gohr $ver = $m[1]; 82414d99ec0SAndreas Gohr $name = 'svn'; 82514d99ec0SAndreas Gohr } 82614d99ec0SAndreas Gohr # Netscape 6.x, 7.x ... ? 82714d99ec0SAndreas Gohr elseif (preg_match($regvernetscape,$ua,$m)){ 82814d99ec0SAndreas Gohr $type = 'browser'; 82914d99ec0SAndreas Gohr $ver = $m[1]; 83014d99ec0SAndreas Gohr $name = 'netscape'; 83114d99ec0SAndreas Gohr } 83214d99ec0SAndreas Gohr # Netscape 3.x, 4.x ... ? 83314d99ec0SAndreas Gohr elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){ 83414d99ec0SAndreas Gohr $type = 'browser'; 83514d99ec0SAndreas Gohr $ver = $m[2]; 83614d99ec0SAndreas Gohr $name = 'netscape'; 83714d99ec0SAndreas Gohr }else{ 83814d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/browsers.php'); 83914d99ec0SAndreas Gohr foreach($BrowsersSearchIDOrder as $regex){ 84014d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 84114d99ec0SAndreas Gohr // it's a browser! 84214d99ec0SAndreas Gohr $type = 'browser'; 84314d99ec0SAndreas Gohr $name = strtolower($regex); 84414d99ec0SAndreas Gohr break; 84514d99ec0SAndreas Gohr } 84614d99ec0SAndreas Gohr } 84714d99ec0SAndreas Gohr } 84814d99ec0SAndreas Gohr 84975fa767dSAndreas Gohr // check versions for Safari and Opera 85075fa767dSAndreas Gohr if($name == 'safari'){ 85175fa767dSAndreas Gohr if(preg_match('/safari\/([\d\.]*)/i',$ua,$match)){ 85275fa767dSAndreas Gohr $ver = $BrowsersSafariBuildToVersionHash[$match[1]]; 85375fa767dSAndreas Gohr } 85475fa767dSAndreas Gohr }elseif($name == 'opera'){ 85575fa767dSAndreas Gohr if(preg_match('/opera[\/ ]([\d\.]*)/i',$ua,$match)){ 85675fa767dSAndreas Gohr $ver = $match[1]; 85775fa767dSAndreas Gohr } 85875fa767dSAndreas Gohr } 85975fa767dSAndreas Gohr 86075fa767dSAndreas Gohr 86114d99ec0SAndreas Gohr // check OS for browsers 86214d99ec0SAndreas Gohr if($type == 'browser'){ 86314d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/operating_systems.php'); 86414d99ec0SAndreas Gohr foreach($OSSearchIDOrder as $regex){ 86514d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 86614d99ec0SAndreas Gohr $os = $OSHashID[$regex]; 86714d99ec0SAndreas Gohr break; 86814d99ec0SAndreas Gohr } 86914d99ec0SAndreas Gohr } 87014d99ec0SAndreas Gohr 87114d99ec0SAndreas Gohr } 87214d99ec0SAndreas Gohr 87314d99ec0SAndreas Gohr // are we done now? 87414d99ec0SAndreas Gohr if($name) return $name; 87514d99ec0SAndreas Gohr 87614d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/robots.php'); 87714d99ec0SAndreas Gohr foreach($RobotsSearchIDOrder as $regex){ 87814d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 87914d99ec0SAndreas Gohr // it's a robot! 88014d99ec0SAndreas Gohr $type = 'robot'; 88114d99ec0SAndreas Gohr return strtolower($regex); 88214d99ec0SAndreas Gohr } 88314d99ec0SAndreas Gohr } 88414d99ec0SAndreas Gohr 88514d99ec0SAndreas Gohr // dunno 8861878f16fSAndreas Gohr return ''; 8871878f16fSAndreas Gohr } 8881878f16fSAndreas Gohr 8891878f16fSAndreas Gohr /** 89014d99ec0SAndreas Gohr * 89114d99ec0SAndreas Gohr * @fixme: put search engine queries in seperate table here 89214d99ec0SAndreas Gohr */ 89314d99ec0SAndreas Gohr function log_search($referer,&$type){ 89414d99ec0SAndreas Gohr $referer = strtr($referer,' +','__'); 89514d99ec0SAndreas Gohr $referer = strtolower($referer); 89614d99ec0SAndreas Gohr 89714d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/search_engines.php'); 89814d99ec0SAndreas Gohr 89914d99ec0SAndreas Gohr foreach($SearchEnginesSearchIDOrder as $regex){ 90014d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$referer)){ 90114d99ec0SAndreas Gohr if(!$NotSearchEnginesKeys[$regex] || 90214d99ec0SAndreas Gohr !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$referer)){ 90314d99ec0SAndreas Gohr // it's a search engine! 90414d99ec0SAndreas Gohr $type = 'search'; 90514d99ec0SAndreas Gohr break; 90614d99ec0SAndreas Gohr } 90714d99ec0SAndreas Gohr } 90814d99ec0SAndreas Gohr } 90914d99ec0SAndreas Gohr if($type != 'search') return; // we're done here 91014d99ec0SAndreas Gohr 91114d99ec0SAndreas Gohr #fixme now do the keyword magic! 91214d99ec0SAndreas Gohr } 91314d99ec0SAndreas Gohr 91414d99ec0SAndreas Gohr /** 91514d99ec0SAndreas Gohr * Resolve IP to country/city 91614d99ec0SAndreas Gohr */ 91714d99ec0SAndreas Gohr function log_ip($ip){ 91814d99ec0SAndreas Gohr // check if IP already known and up-to-date 91914d99ec0SAndreas Gohr $sql = "SELECT ip 92014d99ec0SAndreas Gohr FROM ".$this->getConf('db_prefix')."iplocation 92114d99ec0SAndreas Gohr WHERE ip ='".addslashes($ip)."' 92214d99ec0SAndreas Gohr AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)"; 92314d99ec0SAndreas Gohr $result = $this->runSQL($sql); 92414d99ec0SAndreas Gohr if($result[0]['ip']) return; 92514d99ec0SAndreas Gohr 92614d99ec0SAndreas Gohr $http = new DokuHTTPClient(); 92714d99ec0SAndreas Gohr $http->timeout = 10; 92814d99ec0SAndreas Gohr $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip); 92914d99ec0SAndreas Gohr 93014d99ec0SAndreas Gohr if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){ 93114d99ec0SAndreas Gohr $country = addslashes(trim($match[1])); 93214d99ec0SAndreas Gohr $code = addslashes(strtolower(trim($match[2]))); 93314d99ec0SAndreas Gohr $city = addslashes(trim($match[3])); 93414d99ec0SAndreas Gohr $host = addslashes(gethostbyaddr($ip)); 93514d99ec0SAndreas Gohr $ip = addslashes($ip); 93614d99ec0SAndreas Gohr 93714d99ec0SAndreas Gohr $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation 93814d99ec0SAndreas Gohr SET ip = '$ip', 93914d99ec0SAndreas Gohr country = '$country', 94014d99ec0SAndreas Gohr code = '$code', 94114d99ec0SAndreas Gohr city = '$city', 94214d99ec0SAndreas Gohr host = '$host'"; 94314d99ec0SAndreas Gohr $this->runSQL($sql); 94414d99ec0SAndreas Gohr } 94514d99ec0SAndreas Gohr } 94614d99ec0SAndreas Gohr 94714d99ec0SAndreas Gohr /** 9481878f16fSAndreas Gohr * log a page access 9491878f16fSAndreas Gohr * 9501878f16fSAndreas Gohr * called from log.php 9511878f16fSAndreas Gohr */ 9521878f16fSAndreas Gohr function log_access(){ 95394171ff3SAndreas Gohr if(!$_REQUEST['p']) return; 95494171ff3SAndreas Gohr 95514d99ec0SAndreas Gohr # FIXME check referer against blacklist and drop logging for bad boys 95614d99ec0SAndreas Gohr 95714d99ec0SAndreas Gohr // handle referer 95814d99ec0SAndreas Gohr $referer = trim($_REQUEST['r']); 95914d99ec0SAndreas Gohr if($referer){ 96014d99ec0SAndreas Gohr $ref = addslashes($referer); 96114d99ec0SAndreas Gohr $ref_md5 = ($ref) ? md5($referer) : ''; 96214d99ec0SAndreas Gohr if(strpos($referer,DOKU_URL) === 0){ 96314d99ec0SAndreas Gohr $ref_type = 'internal'; 96414d99ec0SAndreas Gohr }else{ 96514d99ec0SAndreas Gohr $ref_type = 'external'; 96614d99ec0SAndreas Gohr $this->log_search($referer,$ref_type); 96714d99ec0SAndreas Gohr } 96814d99ec0SAndreas Gohr }else{ 96914d99ec0SAndreas Gohr $ref = ''; 97014d99ec0SAndreas Gohr $ref_md5 = ''; 97114d99ec0SAndreas Gohr $ref_type = ''; 97214d99ec0SAndreas Gohr } 97314d99ec0SAndreas Gohr 97414d99ec0SAndreas Gohr // handle user agent 97514d99ec0SAndreas Gohr $agent = trim($_SERVER['HTTP_USER_AGENT']); 97614d99ec0SAndreas Gohr 97714d99ec0SAndreas Gohr $ua = addslashes($agent); 97814d99ec0SAndreas Gohr $ua_type = ''; 97914d99ec0SAndreas Gohr $ua_ver = ''; 98014d99ec0SAndreas Gohr $os = ''; 98114d99ec0SAndreas Gohr $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os)); 98214d99ec0SAndreas Gohr 9831878f16fSAndreas Gohr $page = addslashes($_REQUEST['p']); 9841878f16fSAndreas Gohr $ip = addslashes($_SERVER['REMOTE_ADDR']); 9851878f16fSAndreas Gohr $sx = (int) $_REQUEST['sx']; 9861878f16fSAndreas Gohr $sy = (int) $_REQUEST['sy']; 9871878f16fSAndreas Gohr $vx = (int) $_REQUEST['vx']; 9881878f16fSAndreas Gohr $vy = (int) $_REQUEST['vy']; 98975fa767dSAndreas Gohr $js = (int) $_REQUEST['js']; 9901878f16fSAndreas Gohr $user = addslashes($_SERVER['REMOTE_USER']); 9911878f16fSAndreas Gohr $session = addslashes(session_id()); 9921878f16fSAndreas Gohr 99394171ff3SAndreas Gohr $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access 99475fa767dSAndreas Gohr SET dt = NOW(), 99575fa767dSAndreas Gohr page = '$page', 9961878f16fSAndreas Gohr ip = '$ip', 9971878f16fSAndreas Gohr ua = '$ua', 9981878f16fSAndreas Gohr ua_info = '$ua_info', 99914d99ec0SAndreas Gohr ua_type = '$ua_type', 100014d99ec0SAndreas Gohr ua_ver = '$ua_ver', 100114d99ec0SAndreas Gohr os = '$os', 10021878f16fSAndreas Gohr ref = '$ref', 100394171ff3SAndreas Gohr ref_md5 = '$ref_md5', 100414d99ec0SAndreas Gohr ref_type = '$ref_type', 10051878f16fSAndreas Gohr screen_x = '$sx', 10061878f16fSAndreas Gohr screen_y = '$sy', 10071878f16fSAndreas Gohr view_x = '$vx', 10081878f16fSAndreas Gohr view_y = '$vy', 100975fa767dSAndreas Gohr js = '$js', 10101878f16fSAndreas Gohr user = '$user', 10111878f16fSAndreas Gohr session = '$session'"; 10121878f16fSAndreas Gohr $ok = $this->runSQL($sql); 10131878f16fSAndreas Gohr if(is_null($ok)){ 10141878f16fSAndreas Gohr global $MSG; 10151878f16fSAndreas Gohr print_r($MSG); 10161878f16fSAndreas Gohr } 101714d99ec0SAndreas Gohr 101814d99ec0SAndreas Gohr // resolve the IP 101914d99ec0SAndreas Gohr $this->log_ip($_SERVER['REMOTE_ADDR']); 10201878f16fSAndreas Gohr } 10211878f16fSAndreas Gohr 10221878f16fSAndreas Gohr /** 10231878f16fSAndreas Gohr * Just send a 1x1 pixel blank gif to the browser 10241878f16fSAndreas Gohr * 10251878f16fSAndreas Gohr * @called from log.php 10261878f16fSAndreas Gohr * 10271878f16fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 10281878f16fSAndreas Gohr * @author Harry Fuecks <fuecks@gmail.com> 10291878f16fSAndreas Gohr */ 10301878f16fSAndreas Gohr function sendGIF(){ 10311878f16fSAndreas Gohr $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); 10321878f16fSAndreas Gohr header('Content-Type: image/gif'); 10331878f16fSAndreas Gohr header('Content-Length: '.strlen($img)); 10341878f16fSAndreas Gohr header('Connection: Close'); 10351878f16fSAndreas Gohr print $img; 10361878f16fSAndreas Gohr flush(); 10371878f16fSAndreas Gohr // Browser should drop connection after this 10381878f16fSAndreas Gohr // Thinks it's got the whole image 10391878f16fSAndreas Gohr } 10401878f16fSAndreas Gohr 10411878f16fSAndreas Gohr} 1042