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>'; 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 332c73e16f1SAndreas Gohr function html_resolution(){ 333c73e16f1SAndreas Gohr echo '<div class="plg_stats_full">'; 334c73e16f1SAndreas Gohr echo '<h2>Resolution</h2>'; 335c73e16f1SAndreas Gohr $result = $this->sql_resolution($this->tlimit,$this->start,150); 336c73e16f1SAndreas Gohr $this->html_resulttable($result,'',150); 337c73e16f1SAndreas Gohr 338c73e16f1SAndreas Gohr echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you 339c73e16f1SAndreas Gohr much about about the real size of their browser windows. The graphic below shows the size distribution of 340c73e16f1SAndreas Gohr the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged 341c73e16f1SAndreas Gohr in all browsers. Because users may resize their browser window while browsing your site the statistics may 342c73e16f1SAndreas Gohr be flawed. Take it with a grain of salt.</p>'; 343c73e16f1SAndreas Gohr 344c73e16f1SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=view&f='.$this->from.'&t='.$this->to.'" />'; 345c73e16f1SAndreas Gohr echo '</div>'; 346c73e16f1SAndreas 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); 373*83b63546SAndreas Gohr $url = preg_replace('/^https?:\/\/(www\.)?/','',$url); 3742812a751SAndreas Gohr if(strlen($url) > 45){ 3752812a751SAndreas Gohr $url = substr($url,0,30).' … '.substr($url,-15); 37654f6c432SAndreas Gohr } 37714d99ec0SAndreas Gohr echo '<a href="'.$v.'" class="urlextern">'; 37854f6c432SAndreas Gohr echo $url; 37914d99ec0SAndreas Gohr echo '</a>'; 38075fa767dSAndreas Gohr }elseif($k == 'browser'){ 38175fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 38275fa767dSAndreas Gohr echo $BrowsersHashIDLib[$v]; 38375fa767dSAndreas Gohr }elseif($k == 'bflag'){ 38475fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 38575fa767dSAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.$BrowsersHashIcon[$v].'.png" alt="'.hsc($v).'" />'; 386bd4217d3SAndreas Gohr }elseif($k == 'os'){ 387bd4217d3SAndreas Gohr if(empty($v)){ 388bd4217d3SAndreas Gohr echo 'unknown'; 389bd4217d3SAndreas Gohr }else{ 390bd4217d3SAndreas Gohr include_once(dirname(__FILE__).'/inc/operating_systems.php'); 391bd4217d3SAndreas Gohr echo $OSHashLib[$v]; 392bd4217d3SAndreas Gohr } 393bd4217d3SAndreas Gohr }elseif($k == 'osflag'){ 394bd4217d3SAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.hsc($v).'.png" alt="'.hsc($v).'" />'; 39575fa767dSAndreas Gohr }elseif($k == 'cflag'){ 39675fa767dSAndreas Gohr echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />'; 39714d99ec0SAndreas Gohr }elseif($k == 'html'){ 39814d99ec0SAndreas Gohr echo $v; 39914d99ec0SAndreas Gohr }else{ 40014d99ec0SAndreas Gohr echo hsc($v); 40114d99ec0SAndreas Gohr } 40214d99ec0SAndreas Gohr echo '</td>'; 40314d99ec0SAndreas Gohr } 40414d99ec0SAndreas Gohr echo '</tr>'; 4052507f8e0SAndreas Gohr 4062507f8e0SAndreas Gohr if($pager && ($count == $pager)) break; 4072507f8e0SAndreas Gohr $count++; 40814d99ec0SAndreas Gohr } 40914d99ec0SAndreas Gohr echo '</table>'; 4102507f8e0SAndreas Gohr 4112507f8e0SAndreas Gohr if($pager) $this->html_pager($pager,count($result) > $pager); 4121878f16fSAndreas Gohr } 4131878f16fSAndreas Gohr 41495eb68e6SAndreas Gohr /** 41595eb68e6SAndreas Gohr * Create an image 41695eb68e6SAndreas Gohr */ 41795eb68e6SAndreas Gohr function img_build($img){ 41895eb68e6SAndreas Gohr include(dirname(__FILE__).'/inc/AGC.class.php'); 41995eb68e6SAndreas Gohr 42095eb68e6SAndreas Gohr switch($img){ 42195eb68e6SAndreas Gohr case 'country': 42295eb68e6SAndreas Gohr // build top countries + other 42395eb68e6SAndreas Gohr $result = $this->sql_countries($this->tlimit,$this->start,0); 42495eb68e6SAndreas Gohr $data = array(); 42595eb68e6SAndreas Gohr $top = 0; 42695eb68e6SAndreas Gohr foreach($result as $row){ 42795eb68e6SAndreas Gohr if($top < 7){ 42895eb68e6SAndreas Gohr $data[$row['country']] = $row['cnt']; 42995eb68e6SAndreas Gohr }else{ 43095eb68e6SAndreas Gohr $data['other'] += $row['cnt']; 43195eb68e6SAndreas Gohr } 43295eb68e6SAndreas Gohr $top++; 43395eb68e6SAndreas Gohr } 43495eb68e6SAndreas Gohr $pie = new AGC(300, 200); 43595eb68e6SAndreas Gohr $pie->setProp("showkey",true); 43695eb68e6SAndreas Gohr $pie->setProp("showval",false); 43795eb68e6SAndreas Gohr $pie->setProp("showgrid",false); 43895eb68e6SAndreas Gohr $pie->setProp("type","pie"); 43995eb68e6SAndreas Gohr $pie->setProp("keyinfo",1); 44095eb68e6SAndreas Gohr $pie->setProp("keysize",8); 44195eb68e6SAndreas Gohr $pie->setProp("keywidspc",-50); 44295eb68e6SAndreas Gohr $pie->setProp("key",array_keys($data)); 44395eb68e6SAndreas Gohr $pie->addBulkPoints(array_values($data)); 44495eb68e6SAndreas Gohr @$pie->graph(); 44595eb68e6SAndreas Gohr $pie->showGraph(); 44695eb68e6SAndreas Gohr break; 44775fa767dSAndreas Gohr case 'browser': 44875fa767dSAndreas Gohr // build top browsers + other 44975fa767dSAndreas Gohr include_once(dirname(__FILE__).'/inc/browsers.php'); 45075fa767dSAndreas Gohr 45175fa767dSAndreas Gohr $result = $this->sql_browsers($this->tlimit,$this->start,0,false); 45275fa767dSAndreas Gohr $data = array(); 45375fa767dSAndreas Gohr $top = 0; 45475fa767dSAndreas Gohr foreach($result as $row){ 45575fa767dSAndreas Gohr if($top < 5){ 45675fa767dSAndreas Gohr $data[strip_tags($BrowsersHashIDLib[$row['ua_info']])] = $row['cnt']; 45775fa767dSAndreas Gohr }else{ 45875fa767dSAndreas Gohr $data['other'] += $row['cnt']; 45975fa767dSAndreas Gohr } 46075fa767dSAndreas Gohr $top++; 46175fa767dSAndreas Gohr } 46275fa767dSAndreas Gohr $pie = new AGC(300, 200); 46375fa767dSAndreas Gohr $pie->setProp("showkey",true); 46475fa767dSAndreas Gohr $pie->setProp("showval",false); 46575fa767dSAndreas Gohr $pie->setProp("showgrid",false); 46675fa767dSAndreas Gohr $pie->setProp("type","pie"); 46775fa767dSAndreas Gohr $pie->setProp("keyinfo",1); 46875fa767dSAndreas Gohr $pie->setProp("keysize",8); 46975fa767dSAndreas Gohr $pie->setProp("keywidspc",-50); 47075fa767dSAndreas Gohr $pie->setProp("key",array_keys($data)); 47175fa767dSAndreas Gohr $pie->addBulkPoints(array_values($data)); 47275fa767dSAndreas Gohr @$pie->graph(); 47375fa767dSAndreas Gohr $pie->showGraph(); 47475fa767dSAndreas Gohr break; 475c73e16f1SAndreas Gohr case 'view': 476c73e16f1SAndreas Gohr 477c73e16f1SAndreas Gohr $graph = new AGC(400, 200); 478c73e16f1SAndreas Gohr $graph->setColor('color',0,'blue'); 479c73e16f1SAndreas Gohr $graph->setColor('color',1,'red'); 480c73e16f1SAndreas Gohr $graph->setProp("showkey",true); 481c73e16f1SAndreas Gohr $graph->setProp("key",'view port width',0); 482c73e16f1SAndreas Gohr $graph->setProp("key",'view port height',1); 483c73e16f1SAndreas Gohr 484c73e16f1SAndreas Gohr $result = $this->sql_viewport($this->tlimit,0,0,true); 485c73e16f1SAndreas Gohr foreach($result as $row){ 486c73e16f1SAndreas Gohr $graph->addPoint($row['cnt'],$row['res_x'],0); 487c73e16f1SAndreas Gohr } 488c73e16f1SAndreas Gohr 489c73e16f1SAndreas Gohr $result = $this->sql_viewport($this->tlimit,0,0,false); 490c73e16f1SAndreas Gohr foreach($result as $row){ 491c73e16f1SAndreas Gohr $graph->addPoint($row['cnt'],$row['res_y'],1); 492c73e16f1SAndreas Gohr } 493c73e16f1SAndreas Gohr 494c73e16f1SAndreas Gohr @$graph->graph(); 495c73e16f1SAndreas Gohr $graph->showGraph(); 496c73e16f1SAndreas Gohr 497c73e16f1SAndreas Gohr break; 4982812a751SAndreas Gohr case 'trend': 4992812a751SAndreas Gohr $hours = ($this->from == $this->to); 5002812a751SAndreas Gohr $result = $this->sql_trend($this->tlimit,$hours); 5012812a751SAndreas Gohr $data1 = array(); 5022812a751SAndreas Gohr $data2 = array(); 5032812a751SAndreas Gohr 5042812a751SAndreas Gohr $graph = new AGC(400, 150); 5052812a751SAndreas Gohr $graph->setProp("type","bar"); 5062812a751SAndreas Gohr $graph->setProp("showgrid",false); 5072812a751SAndreas Gohr $graph->setProp("barwidth",.8); 50875fa767dSAndreas Gohr 5092812a751SAndreas Gohr $graph->setColor('color',0,'blue'); 5102812a751SAndreas Gohr $graph->setColor('color',1,'red'); 5112812a751SAndreas Gohr 5122812a751SAndreas Gohr if($hours){ 5132812a751SAndreas Gohr //preset $hours 5142812a751SAndreas Gohr for($i=0;$i<24;$i++){ 5152812a751SAndreas Gohr $data1[$i] = 0; 5162812a751SAndreas Gohr $data2[$i] = 0; 5172812a751SAndreas Gohr $graph->setProp("scale",array(' 0h',' 4h',' 8h',' 12h',' 16h',' 20h',' 24h')); 5182812a751SAndreas Gohr } 5192812a751SAndreas Gohr }else{ 5202812a751SAndreas Gohr $graph->setProp("scale",array(next(array_keys($data1)),$this->to)); 5212812a751SAndreas Gohr } 5222812a751SAndreas Gohr 5232812a751SAndreas Gohr foreach($result as $row){ 5242812a751SAndreas Gohr $data1[$row['time']] = $row['pageviews']; 5252812a751SAndreas Gohr $data2[$row['time']] = $row['sessions']; 5262812a751SAndreas Gohr } 5272812a751SAndreas Gohr 5282812a751SAndreas Gohr foreach($data1 as $key => $val){ 5292812a751SAndreas Gohr $graph->addPoint($val,$key,0); 5302812a751SAndreas Gohr } 5312812a751SAndreas Gohr foreach($data2 as $key => $val){ 5322812a751SAndreas Gohr $graph->addPoint($val,$key,1); 5332812a751SAndreas Gohr } 5342812a751SAndreas Gohr 5352812a751SAndreas Gohr @$graph->graph(); 5362812a751SAndreas Gohr $graph->showGraph(); 5372812a751SAndreas Gohr 53895eb68e6SAndreas Gohr default: 53995eb68e6SAndreas Gohr $this->sendGIF(); 54095eb68e6SAndreas Gohr } 54195eb68e6SAndreas Gohr } 54295eb68e6SAndreas Gohr 54395eb68e6SAndreas Gohr 5442812a751SAndreas Gohr /** 5452812a751SAndreas Gohr * Return some aggregated statistics 5462812a751SAndreas Gohr */ 5472812a751SAndreas Gohr function sql_aggregate($tlimit){ 5482812a751SAndreas Gohr $data = array(); 5492812a751SAndreas Gohr 5502812a751SAndreas Gohr $sql = "SELECT ref_type, COUNT(*) as cnt 5512812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5522812a751SAndreas Gohr WHERE $tlimit 5532812a751SAndreas Gohr AND ua_type = 'browser' 5542812a751SAndreas Gohr GROUP BY ref_type"; 5552812a751SAndreas Gohr $result = $this->runSQL($sql); 5562812a751SAndreas Gohr 5572812a751SAndreas Gohr foreach($result as $row){ 5582812a751SAndreas Gohr if($row['ref_type'] == 'search') $data['search'] = $row['cnt']; 5592812a751SAndreas Gohr if($row['ref_type'] == 'external') $data['external'] = $row['cnt']; 5602812a751SAndreas Gohr if($row['ref_type'] == 'internal') $data['internal'] = $row['cnt']; 5612812a751SAndreas Gohr if($row['ref_type'] == '') $data['direct'] = $row['cnt']; 5622812a751SAndreas Gohr } 5632812a751SAndreas Gohr 5642812a751SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as sessions, 5652812a751SAndreas Gohr COUNT(session) as views, 5662812a751SAndreas Gohr COUNT(DISTINCT user) as users 5672812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5682812a751SAndreas Gohr WHERE $tlimit 5692812a751SAndreas Gohr AND ua_type = 'browser'"; 5702812a751SAndreas Gohr $result = $this->runSQL($sql); 5712812a751SAndreas Gohr 57275fa767dSAndreas Gohr $data['users'] = max($result[0]['users'] - 1,0); // subtract empty user 5732812a751SAndreas Gohr $data['sessions'] = $result[0]['sessions']; 5742812a751SAndreas Gohr $data['pageviews'] = $result[0]['views']; 5752812a751SAndreas Gohr 5762812a751SAndreas Gohr $sql = "SELECT COUNT(id) as robots 5772812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5782812a751SAndreas Gohr WHERE $tlimit 5792812a751SAndreas Gohr AND ua_type = 'robot'"; 5802812a751SAndreas Gohr $result = $this->runSQL($sql); 5812812a751SAndreas Gohr $data['robots'] = $result[0]['robots']; 5822812a751SAndreas Gohr 5832812a751SAndreas Gohr return $data; 5842812a751SAndreas Gohr } 5852812a751SAndreas Gohr 586bd4217d3SAndreas Gohr /** 587bd4217d3SAndreas Gohr * standard statistics follow, only accesses made by browsers are counted 588bd4217d3SAndreas Gohr * for general stats like browser or OS only visitors not pageviews are counted 589bd4217d3SAndreas Gohr */ 5902812a751SAndreas Gohr function sql_trend($tlimit,$hours=false){ 5912812a751SAndreas Gohr if($hours){ 5922812a751SAndreas Gohr $sql = "SELECT HOUR(dt) as time, 5932812a751SAndreas Gohr COUNT(DISTINCT session) as sessions, 5942812a751SAndreas Gohr COUNT(session) as pageviews 5952812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 5962812a751SAndreas Gohr WHERE $tlimit 5972812a751SAndreas Gohr AND ua_type = 'browser' 5982812a751SAndreas Gohr GROUP BY HOUR(dt) 5992812a751SAndreas Gohr ORDER BY time"; 6002812a751SAndreas Gohr }else{ 6012812a751SAndreas Gohr $sql = "SELECT DATE(dt) as time, 6022812a751SAndreas Gohr COUNT(DISTINCT session) as sessions, 6032812a751SAndreas Gohr COUNT(session) as pageviews 6042812a751SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 6052812a751SAndreas Gohr WHERE $tlimit 6062812a751SAndreas Gohr AND ua_type = 'browser' 6072812a751SAndreas Gohr GROUP BY DATE(dt) 6082812a751SAndreas Gohr ORDER BY time"; 6092812a751SAndreas Gohr } 6102812a751SAndreas Gohr return $this->runSQL($sql); 6112812a751SAndreas Gohr } 6122812a751SAndreas Gohr 61395eb68e6SAndreas Gohr function sql_pages($tlimit,$start=0,$limit=20){ 6142812a751SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, page 61595eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 61695eb68e6SAndreas Gohr WHERE $tlimit 61795eb68e6SAndreas Gohr AND ua_type = 'browser' 61895eb68e6SAndreas Gohr GROUP BY page 61995eb68e6SAndreas Gohr ORDER BY cnt DESC, page". 62095eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 62195eb68e6SAndreas Gohr return $this->runSQL($sql); 62295eb68e6SAndreas Gohr } 62395eb68e6SAndreas Gohr 62495eb68e6SAndreas Gohr function sql_referer($tlimit,$start=0,$limit=20){ 6252812a751SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, ref as url 62695eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 62795eb68e6SAndreas Gohr WHERE $tlimit 62895eb68e6SAndreas Gohr AND ua_type = 'browser' 62995eb68e6SAndreas Gohr AND ref_type = 'external' 63095eb68e6SAndreas Gohr GROUP BY ref_md5 63195eb68e6SAndreas Gohr ORDER BY cnt DESC, url". 63295eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 63395eb68e6SAndreas Gohr return $this->runSQL($sql); 63495eb68e6SAndreas Gohr } 63595eb68e6SAndreas Gohr 636e7a2f1e0SAndreas Gohr function sql_newreferer($tlimit,$start=0,$limit=20){ 637e7a2f1e0SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, ref as url 638e7a2f1e0SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 639e7a2f1e0SAndreas Gohr WHERE ua_type = 'browser' 640e7a2f1e0SAndreas Gohr AND ref_type = 'external' 641e7a2f1e0SAndreas Gohr GROUP BY ref_md5 642e7a2f1e0SAndreas Gohr HAVING DATE(MIN(dt)) >= DATE('".$this->from."') 643e7a2f1e0SAndreas Gohr AND DATE(MIN(dt)) <= DATE('".$this->to."') 644e7a2f1e0SAndreas Gohr ORDER BY cnt DESC, url". 645e7a2f1e0SAndreas Gohr $this->sql_limit($start,$limit); 646e7a2f1e0SAndreas Gohr return $this->runSQL($sql); 647e7a2f1e0SAndreas Gohr } 648e7a2f1e0SAndreas Gohr 64995eb68e6SAndreas Gohr function sql_countries($tlimit,$start=0,$limit=20){ 650bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country 65195eb68e6SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A, 65295eb68e6SAndreas Gohr ".$this->getConf('db_prefix')."iplocation as B 65395eb68e6SAndreas Gohr WHERE $tlimit 65495eb68e6SAndreas Gohr AND A.ip = B.ip 65595eb68e6SAndreas Gohr GROUP BY B.country 65695eb68e6SAndreas Gohr ORDER BY cnt DESC, B.country". 65795eb68e6SAndreas Gohr $this->sql_limit($start,$limit); 65895eb68e6SAndreas Gohr return $this->runSQL($sql); 65995eb68e6SAndreas Gohr } 66095eb68e6SAndreas Gohr 66175fa767dSAndreas Gohr function sql_browsers($tlimit,$start=0,$limit=20,$ext=true){ 66275fa767dSAndreas Gohr if($ext){ 66375fa767dSAndreas Gohr $sel = 'ua_info as bflag, ua_info as browser, ua_ver'; 66475fa767dSAndreas Gohr $grp = 'ua_info, ua_ver'; 66575fa767dSAndreas Gohr }else{ 66675fa767dSAndreas Gohr $grp = 'ua_info'; 66775fa767dSAndreas Gohr $sel = 'ua_info'; 66875fa767dSAndreas Gohr } 66975fa767dSAndreas Gohr 670bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel 67175fa767dSAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 67275fa767dSAndreas Gohr WHERE $tlimit 67375fa767dSAndreas Gohr AND ua_type = 'browser' 67475fa767dSAndreas Gohr GROUP BY $grp 67575fa767dSAndreas Gohr ORDER BY cnt DESC, ua_info". 67675fa767dSAndreas Gohr $this->sql_limit($start,$limit); 67775fa767dSAndreas Gohr return $this->runSQL($sql); 67875fa767dSAndreas Gohr } 67975fa767dSAndreas Gohr 680bd4217d3SAndreas Gohr function sql_os($tlimit,$start=0,$limit=20){ 681bd4217d3SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os 682bd4217d3SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 683bd4217d3SAndreas Gohr WHERE $tlimit 684bd4217d3SAndreas Gohr AND ua_type = 'browser' 685bd4217d3SAndreas Gohr GROUP BY os 686bd4217d3SAndreas Gohr ORDER BY cnt DESC, os". 687bd4217d3SAndreas Gohr $this->sql_limit($start,$limit); 688bd4217d3SAndreas Gohr return $this->runSQL($sql); 689bd4217d3SAndreas Gohr } 690bd4217d3SAndreas Gohr 691c73e16f1SAndreas Gohr function sql_resolution($tlimit,$start=0,$limit=20){ 692c73e16f1SAndreas Gohr $sql = "SELECT COUNT(DISTINCT session) as cnt, CONCAT(screen_x,'x',screen_y) as res 693c73e16f1SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 694c73e16f1SAndreas Gohr WHERE $tlimit 695c73e16f1SAndreas Gohr AND ua_type = 'browser' 696c73e16f1SAndreas Gohr AND screen_x != 0 697c73e16f1SAndreas Gohr GROUP BY screen_x, screen_y 698c73e16f1SAndreas Gohr ORDER BY cnt DESC, screen_x". 699c73e16f1SAndreas Gohr $this->sql_limit($start,$limit); 700c73e16f1SAndreas Gohr return $this->runSQL($sql); 701c73e16f1SAndreas Gohr } 702c73e16f1SAndreas Gohr 703c73e16f1SAndreas Gohr function sql_viewport($tlimit,$start=0,$limit=20,$x=true){ 704c73e16f1SAndreas Gohr if($x){ 705c73e16f1SAndreas Gohr $col = 'view_x'; 706c73e16f1SAndreas Gohr $res = 'res_x'; 707c73e16f1SAndreas Gohr }else{ 708c73e16f1SAndreas Gohr $col = 'view_y'; 709c73e16f1SAndreas Gohr $res = 'res_y'; 710c73e16f1SAndreas Gohr } 711c73e16f1SAndreas Gohr 712c73e16f1SAndreas Gohr $sql = "SELECT COUNT(*) as cnt, 713c73e16f1SAndreas Gohr ROUND($col/10)*10 as $res 714c73e16f1SAndreas Gohr FROM ".$this->getConf('db_prefix')."access as A 715c73e16f1SAndreas Gohr WHERE $tlimit 716c73e16f1SAndreas Gohr AND ua_type = 'browser' 717c73e16f1SAndreas Gohr AND $col != 0 718c73e16f1SAndreas Gohr GROUP BY $res 719c73e16f1SAndreas Gohr ORDER BY cnt DESC, $res". 720c73e16f1SAndreas Gohr $this->sql_limit($start,$limit); 721c73e16f1SAndreas Gohr return $this->runSQL($sql); 722c73e16f1SAndreas Gohr } 723c73e16f1SAndreas Gohr 72475fa767dSAndreas Gohr 72595eb68e6SAndreas Gohr /** 72695eb68e6SAndreas Gohr * Builds a limit clause 72795eb68e6SAndreas Gohr */ 72895eb68e6SAndreas Gohr function sql_limit($start,$limit){ 72995eb68e6SAndreas Gohr $start = (int) $start; 73095eb68e6SAndreas Gohr $limit = (int) $limit; 73195eb68e6SAndreas Gohr if($limit){ 7322507f8e0SAndreas Gohr $limit += 1; 73395eb68e6SAndreas Gohr return " LIMIT $start,$limit"; 73495eb68e6SAndreas Gohr }elseif($start){ 73595eb68e6SAndreas Gohr return " OFFSET $start"; 73695eb68e6SAndreas Gohr } 73795eb68e6SAndreas Gohr return ''; 73895eb68e6SAndreas Gohr } 7391878f16fSAndreas Gohr 7401878f16fSAndreas Gohr /** 74114d99ec0SAndreas Gohr * Return a link to the DB, opening the connection if needed 7421878f16fSAndreas Gohr */ 74314d99ec0SAndreas Gohr function dbLink(){ 7441878f16fSAndreas Gohr // connect to DB if needed 7451878f16fSAndreas Gohr if(!$this->dblink){ 7461878f16fSAndreas Gohr $this->dblink = mysql_connect($this->getConf('db_server'), 7471878f16fSAndreas Gohr $this->getConf('db_user'), 7481878f16fSAndreas Gohr $this->getConf('db_password')); 7491878f16fSAndreas Gohr if(!$this->dblink){ 7501878f16fSAndreas Gohr msg('DB Error: connection failed',-1); 7511878f16fSAndreas Gohr return null; 7521878f16fSAndreas Gohr } 7531878f16fSAndreas Gohr // set utf-8 7541878f16fSAndreas Gohr if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){ 7551878f16fSAndreas Gohr msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1); 7561878f16fSAndreas Gohr return null; 7571878f16fSAndreas Gohr } 7581878f16fSAndreas Gohr } 75914d99ec0SAndreas Gohr return $this->dblink; 76014d99ec0SAndreas Gohr } 7611878f16fSAndreas Gohr 76214d99ec0SAndreas Gohr /** 76314d99ec0SAndreas Gohr * Simple function to run a DB query 76414d99ec0SAndreas Gohr */ 76514d99ec0SAndreas Gohr function runSQL($sql_string) { 76614d99ec0SAndreas Gohr $link = $this->dbLink(); 76714d99ec0SAndreas Gohr 76814d99ec0SAndreas Gohr $result = mysql_db_query($this->conf['db_database'],$sql_string,$link); 76994171ff3SAndreas Gohr if(!$result){ 7702812a751SAndreas Gohr msg('DB Error: '.mysql_error($link).' '.hsc($sql_string),-1); 7711878f16fSAndreas Gohr return null; 7721878f16fSAndreas Gohr } 7731878f16fSAndreas Gohr 7741878f16fSAndreas Gohr $resultarray = array(); 7751878f16fSAndreas Gohr 7761878f16fSAndreas Gohr //mysql_db_query returns 1 on a insert statement -> no need to ask for results 7771878f16fSAndreas Gohr if ($result != 1) { 7781878f16fSAndreas Gohr for($i=0; $i< mysql_num_rows($result); $i++) { 7791878f16fSAndreas Gohr $temparray = mysql_fetch_assoc($result); 7801878f16fSAndreas Gohr $resultarray[]=$temparray; 7811878f16fSAndreas Gohr } 7821878f16fSAndreas Gohr mysql_free_result($result); 7831878f16fSAndreas Gohr } 7841878f16fSAndreas Gohr 78514d99ec0SAndreas Gohr if (mysql_insert_id($link)) { 78614d99ec0SAndreas Gohr $resultarray = mysql_insert_id($link); //give back ID on insert 7871878f16fSAndreas Gohr } 7881878f16fSAndreas Gohr 7891878f16fSAndreas Gohr return $resultarray; 7901878f16fSAndreas Gohr } 7911878f16fSAndreas Gohr 7921878f16fSAndreas Gohr /** 79314d99ec0SAndreas Gohr * Returns a short name for a User Agent and sets type, version and os info 7941878f16fSAndreas Gohr */ 79514d99ec0SAndreas Gohr function ua_info($ua,&$type,&$ver,&$os){ 79614d99ec0SAndreas Gohr $ua = strtr($ua,' +','__'); 79714d99ec0SAndreas Gohr $ua = strtolower($ua); 79814d99ec0SAndreas Gohr 79914d99ec0SAndreas Gohr // common browsers 80014d99ec0SAndreas Gohr $regvermsie = '/msie([+_ ]|)([\d\.]*)/i'; 80114d99ec0SAndreas Gohr $regvernetscape = '/netscape.?\/([\d\.]*)/i'; 80214d99ec0SAndreas Gohr $regverfirefox = '/firefox\/([\d\.]*)/i'; 80314d99ec0SAndreas Gohr $regversvn = '/svn\/([\d\.]*)/i'; 80414d99ec0SAndreas Gohr $regvermozilla = '/mozilla(\/|)([\d\.]*)/i'; 80514d99ec0SAndreas Gohr $regnotie = '/webtv|omniweb|opera/i'; 80614d99ec0SAndreas Gohr $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i'; 80714d99ec0SAndreas Gohr 80814d99ec0SAndreas Gohr $name = ''; 80914d99ec0SAndreas Gohr # IE ? 81014d99ec0SAndreas Gohr if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){ 81114d99ec0SAndreas Gohr $type = 'browser'; 81214d99ec0SAndreas Gohr $ver = $m[2]; 81314d99ec0SAndreas Gohr $name = 'msie'; 81414d99ec0SAndreas Gohr } 81514d99ec0SAndreas Gohr # Firefox ? 81614d99ec0SAndreas Gohr elseif (preg_match($regverfirefox,$ua,$m)){ 81714d99ec0SAndreas Gohr $type = 'browser'; 81814d99ec0SAndreas Gohr $ver = $m[1]; 81914d99ec0SAndreas Gohr $name = 'firefox'; 82014d99ec0SAndreas Gohr } 82114d99ec0SAndreas Gohr # Subversion ? 82214d99ec0SAndreas Gohr elseif (preg_match($regversvn,$ua,$m)){ 82314d99ec0SAndreas Gohr $type = 'rcs'; 82414d99ec0SAndreas Gohr $ver = $m[1]; 82514d99ec0SAndreas Gohr $name = 'svn'; 82614d99ec0SAndreas Gohr } 82714d99ec0SAndreas Gohr # Netscape 6.x, 7.x ... ? 82814d99ec0SAndreas Gohr elseif (preg_match($regvernetscape,$ua,$m)){ 82914d99ec0SAndreas Gohr $type = 'browser'; 83014d99ec0SAndreas Gohr $ver = $m[1]; 83114d99ec0SAndreas Gohr $name = 'netscape'; 83214d99ec0SAndreas Gohr } 83314d99ec0SAndreas Gohr # Netscape 3.x, 4.x ... ? 83414d99ec0SAndreas Gohr elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){ 83514d99ec0SAndreas Gohr $type = 'browser'; 83614d99ec0SAndreas Gohr $ver = $m[2]; 83714d99ec0SAndreas Gohr $name = 'netscape'; 83814d99ec0SAndreas Gohr }else{ 83914d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/browsers.php'); 84014d99ec0SAndreas Gohr foreach($BrowsersSearchIDOrder as $regex){ 84114d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 84214d99ec0SAndreas Gohr // it's a browser! 84314d99ec0SAndreas Gohr $type = 'browser'; 84414d99ec0SAndreas Gohr $name = strtolower($regex); 84514d99ec0SAndreas Gohr break; 84614d99ec0SAndreas Gohr } 84714d99ec0SAndreas Gohr } 84814d99ec0SAndreas Gohr } 84914d99ec0SAndreas Gohr 85075fa767dSAndreas Gohr // check versions for Safari and Opera 85175fa767dSAndreas Gohr if($name == 'safari'){ 85275fa767dSAndreas Gohr if(preg_match('/safari\/([\d\.]*)/i',$ua,$match)){ 85375fa767dSAndreas Gohr $ver = $BrowsersSafariBuildToVersionHash[$match[1]]; 85475fa767dSAndreas Gohr } 85575fa767dSAndreas Gohr }elseif($name == 'opera'){ 85675fa767dSAndreas Gohr if(preg_match('/opera[\/ ]([\d\.]*)/i',$ua,$match)){ 85775fa767dSAndreas Gohr $ver = $match[1]; 85875fa767dSAndreas Gohr } 85975fa767dSAndreas Gohr } 86075fa767dSAndreas Gohr 86175fa767dSAndreas Gohr 86214d99ec0SAndreas Gohr // check OS for browsers 86314d99ec0SAndreas Gohr if($type == 'browser'){ 86414d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/operating_systems.php'); 86514d99ec0SAndreas Gohr foreach($OSSearchIDOrder as $regex){ 86614d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 86714d99ec0SAndreas Gohr $os = $OSHashID[$regex]; 86814d99ec0SAndreas Gohr break; 86914d99ec0SAndreas Gohr } 87014d99ec0SAndreas Gohr } 87114d99ec0SAndreas Gohr 87214d99ec0SAndreas Gohr } 87314d99ec0SAndreas Gohr 87414d99ec0SAndreas Gohr // are we done now? 87514d99ec0SAndreas Gohr if($name) return $name; 87614d99ec0SAndreas Gohr 87714d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/robots.php'); 87814d99ec0SAndreas Gohr foreach($RobotsSearchIDOrder as $regex){ 87914d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$ua)){ 88014d99ec0SAndreas Gohr // it's a robot! 88114d99ec0SAndreas Gohr $type = 'robot'; 88214d99ec0SAndreas Gohr return strtolower($regex); 88314d99ec0SAndreas Gohr } 88414d99ec0SAndreas Gohr } 88514d99ec0SAndreas Gohr 88614d99ec0SAndreas Gohr // dunno 8871878f16fSAndreas Gohr return ''; 8881878f16fSAndreas Gohr } 8891878f16fSAndreas Gohr 8901878f16fSAndreas Gohr /** 89114d99ec0SAndreas Gohr * 89214d99ec0SAndreas Gohr * @fixme: put search engine queries in seperate table here 89314d99ec0SAndreas Gohr */ 89414d99ec0SAndreas Gohr function log_search($referer,&$type){ 89514d99ec0SAndreas Gohr $referer = strtr($referer,' +','__'); 89614d99ec0SAndreas Gohr $referer = strtolower($referer); 89714d99ec0SAndreas Gohr 89814d99ec0SAndreas Gohr include(dirname(__FILE__).'/inc/search_engines.php'); 89914d99ec0SAndreas Gohr 90014d99ec0SAndreas Gohr foreach($SearchEnginesSearchIDOrder as $regex){ 90114d99ec0SAndreas Gohr if(preg_match('/'.$regex.'/',$referer)){ 90214d99ec0SAndreas Gohr if(!$NotSearchEnginesKeys[$regex] || 90314d99ec0SAndreas Gohr !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$referer)){ 90414d99ec0SAndreas Gohr // it's a search engine! 90514d99ec0SAndreas Gohr $type = 'search'; 90614d99ec0SAndreas Gohr break; 90714d99ec0SAndreas Gohr } 90814d99ec0SAndreas Gohr } 90914d99ec0SAndreas Gohr } 91014d99ec0SAndreas Gohr if($type != 'search') return; // we're done here 91114d99ec0SAndreas Gohr 91214d99ec0SAndreas Gohr #fixme now do the keyword magic! 91314d99ec0SAndreas Gohr } 91414d99ec0SAndreas Gohr 91514d99ec0SAndreas Gohr /** 91614d99ec0SAndreas Gohr * Resolve IP to country/city 91714d99ec0SAndreas Gohr */ 91814d99ec0SAndreas Gohr function log_ip($ip){ 91914d99ec0SAndreas Gohr // check if IP already known and up-to-date 92014d99ec0SAndreas Gohr $sql = "SELECT ip 92114d99ec0SAndreas Gohr FROM ".$this->getConf('db_prefix')."iplocation 92214d99ec0SAndreas Gohr WHERE ip ='".addslashes($ip)."' 92314d99ec0SAndreas Gohr AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)"; 92414d99ec0SAndreas Gohr $result = $this->runSQL($sql); 92514d99ec0SAndreas Gohr if($result[0]['ip']) return; 92614d99ec0SAndreas Gohr 92714d99ec0SAndreas Gohr $http = new DokuHTTPClient(); 92814d99ec0SAndreas Gohr $http->timeout = 10; 92914d99ec0SAndreas Gohr $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip); 93014d99ec0SAndreas Gohr 93114d99ec0SAndreas Gohr if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){ 93214d99ec0SAndreas Gohr $country = addslashes(trim($match[1])); 93314d99ec0SAndreas Gohr $code = addslashes(strtolower(trim($match[2]))); 93414d99ec0SAndreas Gohr $city = addslashes(trim($match[3])); 93514d99ec0SAndreas Gohr $host = addslashes(gethostbyaddr($ip)); 93614d99ec0SAndreas Gohr $ip = addslashes($ip); 93714d99ec0SAndreas Gohr 93814d99ec0SAndreas Gohr $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation 93914d99ec0SAndreas Gohr SET ip = '$ip', 94014d99ec0SAndreas Gohr country = '$country', 94114d99ec0SAndreas Gohr code = '$code', 94214d99ec0SAndreas Gohr city = '$city', 94314d99ec0SAndreas Gohr host = '$host'"; 94414d99ec0SAndreas Gohr $this->runSQL($sql); 94514d99ec0SAndreas Gohr } 94614d99ec0SAndreas Gohr } 94714d99ec0SAndreas Gohr 94814d99ec0SAndreas Gohr /** 9491878f16fSAndreas Gohr * log a page access 9501878f16fSAndreas Gohr * 9511878f16fSAndreas Gohr * called from log.php 9521878f16fSAndreas Gohr */ 9531878f16fSAndreas Gohr function log_access(){ 95494171ff3SAndreas Gohr if(!$_REQUEST['p']) return; 95594171ff3SAndreas Gohr 95614d99ec0SAndreas Gohr # FIXME check referer against blacklist and drop logging for bad boys 95714d99ec0SAndreas Gohr 95814d99ec0SAndreas Gohr // handle referer 95914d99ec0SAndreas Gohr $referer = trim($_REQUEST['r']); 96014d99ec0SAndreas Gohr if($referer){ 96114d99ec0SAndreas Gohr $ref = addslashes($referer); 96214d99ec0SAndreas Gohr $ref_md5 = ($ref) ? md5($referer) : ''; 96314d99ec0SAndreas Gohr if(strpos($referer,DOKU_URL) === 0){ 96414d99ec0SAndreas Gohr $ref_type = 'internal'; 96514d99ec0SAndreas Gohr }else{ 96614d99ec0SAndreas Gohr $ref_type = 'external'; 96714d99ec0SAndreas Gohr $this->log_search($referer,$ref_type); 96814d99ec0SAndreas Gohr } 96914d99ec0SAndreas Gohr }else{ 97014d99ec0SAndreas Gohr $ref = ''; 97114d99ec0SAndreas Gohr $ref_md5 = ''; 97214d99ec0SAndreas Gohr $ref_type = ''; 97314d99ec0SAndreas Gohr } 97414d99ec0SAndreas Gohr 97514d99ec0SAndreas Gohr // handle user agent 97614d99ec0SAndreas Gohr $agent = trim($_SERVER['HTTP_USER_AGENT']); 97714d99ec0SAndreas Gohr 97814d99ec0SAndreas Gohr $ua = addslashes($agent); 97914d99ec0SAndreas Gohr $ua_type = ''; 98014d99ec0SAndreas Gohr $ua_ver = ''; 98114d99ec0SAndreas Gohr $os = ''; 98214d99ec0SAndreas Gohr $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os)); 98314d99ec0SAndreas Gohr 9841878f16fSAndreas Gohr $page = addslashes($_REQUEST['p']); 9851878f16fSAndreas Gohr $ip = addslashes($_SERVER['REMOTE_ADDR']); 9861878f16fSAndreas Gohr $sx = (int) $_REQUEST['sx']; 9871878f16fSAndreas Gohr $sy = (int) $_REQUEST['sy']; 9881878f16fSAndreas Gohr $vx = (int) $_REQUEST['vx']; 9891878f16fSAndreas Gohr $vy = (int) $_REQUEST['vy']; 99075fa767dSAndreas Gohr $js = (int) $_REQUEST['js']; 9911878f16fSAndreas Gohr $user = addslashes($_SERVER['REMOTE_USER']); 9921878f16fSAndreas Gohr $session = addslashes(session_id()); 9931878f16fSAndreas Gohr 99494171ff3SAndreas Gohr $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access 99575fa767dSAndreas Gohr SET dt = NOW(), 99675fa767dSAndreas Gohr page = '$page', 9971878f16fSAndreas Gohr ip = '$ip', 9981878f16fSAndreas Gohr ua = '$ua', 9991878f16fSAndreas Gohr ua_info = '$ua_info', 100014d99ec0SAndreas Gohr ua_type = '$ua_type', 100114d99ec0SAndreas Gohr ua_ver = '$ua_ver', 100214d99ec0SAndreas Gohr os = '$os', 10031878f16fSAndreas Gohr ref = '$ref', 100494171ff3SAndreas Gohr ref_md5 = '$ref_md5', 100514d99ec0SAndreas Gohr ref_type = '$ref_type', 10061878f16fSAndreas Gohr screen_x = '$sx', 10071878f16fSAndreas Gohr screen_y = '$sy', 10081878f16fSAndreas Gohr view_x = '$vx', 10091878f16fSAndreas Gohr view_y = '$vy', 101075fa767dSAndreas Gohr js = '$js', 10111878f16fSAndreas Gohr user = '$user', 10121878f16fSAndreas Gohr session = '$session'"; 10131878f16fSAndreas Gohr $ok = $this->runSQL($sql); 10141878f16fSAndreas Gohr if(is_null($ok)){ 10151878f16fSAndreas Gohr global $MSG; 10161878f16fSAndreas Gohr print_r($MSG); 10171878f16fSAndreas Gohr } 101814d99ec0SAndreas Gohr 101914d99ec0SAndreas Gohr // resolve the IP 102014d99ec0SAndreas Gohr $this->log_ip($_SERVER['REMOTE_ADDR']); 10211878f16fSAndreas Gohr } 10221878f16fSAndreas Gohr 10231878f16fSAndreas Gohr /** 10241878f16fSAndreas Gohr * Just send a 1x1 pixel blank gif to the browser 10251878f16fSAndreas Gohr * 10261878f16fSAndreas Gohr * @called from log.php 10271878f16fSAndreas Gohr * 10281878f16fSAndreas Gohr * @author Andreas Gohr <andi@splitbrain.org> 10291878f16fSAndreas Gohr * @author Harry Fuecks <fuecks@gmail.com> 10301878f16fSAndreas Gohr */ 10311878f16fSAndreas Gohr function sendGIF(){ 10321878f16fSAndreas Gohr $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); 10331878f16fSAndreas Gohr header('Content-Type: image/gif'); 10341878f16fSAndreas Gohr header('Content-Length: '.strlen($img)); 10351878f16fSAndreas Gohr header('Connection: Close'); 10361878f16fSAndreas Gohr print $img; 10371878f16fSAndreas Gohr flush(); 10381878f16fSAndreas Gohr // Browser should drop connection after this 10391878f16fSAndreas Gohr // Thinks it's got the whole image 10401878f16fSAndreas Gohr } 10411878f16fSAndreas Gohr 10421878f16fSAndreas Gohr} 1043