xref: /plugin/statistics/admin.php (revision 83b63546251597b424c2351297d54c4968caf1b5)
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&amp;page=statistics&amp;opt=&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=referer&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=browser&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=os&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=country&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=resolution&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;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&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;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&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$now.'&amp;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&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$yday.'&amp;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&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$week.'&amp;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&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$month.'&amp;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&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;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&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;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&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
2612507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=country&amp;f='.$this->from.'&amp;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&amp;f='.$this->from.'&amp;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&amp;f='.$this->from.'&amp;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&amp;f='.$this->from.'&amp;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).' &hellip; '.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