xref: /plugin/statistics/admin.php (revision 94023548910e40a87fd810855e47daf1f98adb56)
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;
9714d99ec0SAndreas Gohr            default:
989da6395dSAndreas Gohr                $this->html_dashboard();
9914d99ec0SAndreas Gohr        }
10014d99ec0SAndreas Gohr    }
10114d99ec0SAndreas Gohr
1029da6395dSAndreas Gohr    function html_toc(){
1039da6395dSAndreas Gohr        echo '<div class="toc">';
1049da6395dSAndreas Gohr        echo '<div class="tocheader toctoggle" id="toc__header">';
1059da6395dSAndreas Gohr        echo 'Detailed Statistics';
1069da6395dSAndreas Gohr        echo '</div>';
1079da6395dSAndreas Gohr        echo '<div id="toc__inside">';
1089da6395dSAndreas Gohr        echo '<ul class="toc">';
1099da6395dSAndreas Gohr
1109da6395dSAndreas Gohr        echo '<li><div class="li">';
1119da6395dSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$this->start.'">Dashboard</a>';
1129da6395dSAndreas Gohr        echo '</div></li>';
1139da6395dSAndreas Gohr
1149da6395dSAndreas Gohr        echo '<li><div class="li">';
1159da6395dSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$this->start.'">Pages</a>';
1169da6395dSAndreas Gohr        echo '</div></li>';
1179da6395dSAndreas Gohr
1189da6395dSAndreas Gohr        echo '<li><div class="li">';
1199da6395dSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=referer&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$this->start.'">Incoming Links</a>';
1209da6395dSAndreas Gohr        echo '</div></li>';
1219da6395dSAndreas Gohr
1229da6395dSAndreas Gohr        echo '<li><div class="li">';
123e7a2f1e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$this->start.'">New Incoming Links</a>';
124e7a2f1e0SAndreas Gohr        echo '</div></li>';
125e7a2f1e0SAndreas Gohr
126e7a2f1e0SAndreas Gohr        echo '<li><div class="li">';
12775fa767dSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=browser&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$this->start.'">Browsers</a>';
12875fa767dSAndreas Gohr        echo '</div></li>';
12975fa767dSAndreas Gohr
13075fa767dSAndreas Gohr        echo '<li><div class="li">';
131bd4217d3SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=os&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$this->start.'">Operating Systems</a>';
132bd4217d3SAndreas Gohr        echo '</div></li>';
133bd4217d3SAndreas Gohr
134bd4217d3SAndreas Gohr        echo '<li><div class="li">';
1359da6395dSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=country&amp;f='.$this->from.'&amp;t='.$this->to.'&amp;s='.$this->start.'">Countries</a>';
1369da6395dSAndreas Gohr        echo '</div></li>';
1379da6395dSAndreas Gohr
1389da6395dSAndreas Gohr        echo '</ul>';
1399da6395dSAndreas Gohr        echo '</div>';
1409da6395dSAndreas Gohr        echo '</div>';
1419da6395dSAndreas Gohr    }
1429da6395dSAndreas Gohr
143264f1744SAndreas Gohr    /**
144264f1744SAndreas Gohr     * Print the time selection menu
145264f1744SAndreas Gohr     */
14614d99ec0SAndreas Gohr    function html_timeselect(){
147264f1744SAndreas Gohr        $now   = date('Y-m-d');
148264f1744SAndreas Gohr        $yday  = date('Y-m-d',time()-(60*60*24));
149264f1744SAndreas Gohr        $week  = date('Y-m-d',time()-(60*60*24*7));
150264f1744SAndreas Gohr        $month = date('Y-m-d',time()-(60*60*24*30));
15114d99ec0SAndreas Gohr
152264f1744SAndreas Gohr        echo '<div class="plg_stats_timeselect">';
153264f1744SAndreas Gohr        echo '<span>Select the timeframe:</span>';
154264f1744SAndreas Gohr        echo '<ul>';
155264f1744SAndreas Gohr
156264f1744SAndreas Gohr        echo '<li>';
15795eb68e6SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$now.'&amp;t='.$now.'&amp;s='.$this->start.'">';
158264f1744SAndreas Gohr        echo 'today';
159264f1744SAndreas Gohr        echo '</a>';
160264f1744SAndreas Gohr        echo '</li>';
161264f1744SAndreas Gohr
162264f1744SAndreas Gohr        echo '<li>';
16395eb68e6SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$yday.'&amp;t='.$yday.'&amp;s='.$this->start.'">';
164264f1744SAndreas Gohr        echo 'yesterday';
165264f1744SAndreas Gohr        echo '</a>';
166264f1744SAndreas Gohr        echo '</li>';
167264f1744SAndreas Gohr
168264f1744SAndreas Gohr        echo '<li>';
16995eb68e6SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$week.'&amp;t='.$now.'&amp;s='.$this->start.'">';
170264f1744SAndreas Gohr        echo 'last 7 days';
171264f1744SAndreas Gohr        echo '</a>';
172264f1744SAndreas Gohr        echo '</li>';
173264f1744SAndreas Gohr
174264f1744SAndreas Gohr        echo '<li>';
17595eb68e6SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$month.'&amp;t='.$now.'&amp;s='.$this->start.'">';
176264f1744SAndreas Gohr        echo 'last 30 days';
177264f1744SAndreas Gohr        echo '</a>';
178264f1744SAndreas Gohr        echo '</li>';
179264f1744SAndreas Gohr
180264f1744SAndreas Gohr        echo '</ul>';
181264f1744SAndreas Gohr
182264f1744SAndreas Gohr
183264f1744SAndreas Gohr        echo '<form action="" method="get">';
184264f1744SAndreas Gohr        echo '<input type="hidden" name="do" value="admin" />';
185264f1744SAndreas Gohr        echo '<input type="hidden" name="page" value="statistics" />';
186264f1744SAndreas Gohr        echo '<input type="hidden" name="opt" value="'.$this->opt.'" />';
18795eb68e6SAndreas Gohr        echo '<input type="hidden" name="s" value="'.$this->start.'" />';
188264f1744SAndreas Gohr        echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />';
189264f1744SAndreas Gohr        echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />';
190264f1744SAndreas Gohr        echo '<input type="submit" value="go" class="button" />';
19114d99ec0SAndreas Gohr        echo '</form>';
192264f1744SAndreas Gohr
193264f1744SAndreas Gohr        echo '</div>';
19414d99ec0SAndreas Gohr    }
19514d99ec0SAndreas Gohr
19614d99ec0SAndreas Gohr
197f5f32cbfSAndreas Gohr    /**
198f5f32cbfSAndreas Gohr     * Print an introductionary screen
199f5f32cbfSAndreas Gohr     */
20014d99ec0SAndreas Gohr    function html_dashboard(){
2012812a751SAndreas Gohr        echo '<p>This page gives you a quick overview on what is happening in your Wiki. For detailed lists
2022812a751SAndreas Gohr              choose a topic from the list.</p>';
2032812a751SAndreas Gohr
2042812a751SAndreas Gohr
205264f1744SAndreas Gohr        echo '<div class="plg_stats_dashboard">';
206264f1744SAndreas Gohr
2072812a751SAndreas Gohr        // general info
2082812a751SAndreas Gohr        echo '<div class="plg_stats_top">';
2092812a751SAndreas Gohr        $result = $this->sql_aggregate($this->tlimit);
2102812a751SAndreas Gohr        echo '<ul>';
2112812a751SAndreas Gohr        echo '<li><span>'.$result['pageviews'].'</span> page views</li>';
2122812a751SAndreas Gohr        echo '<li><span>'.$result['sessions'].'</span> visitors (sessions)</li>';
2132812a751SAndreas Gohr        echo '<li><span>'.$result['users'].'</span> logged in users</li>';
2142812a751SAndreas Gohr
2152812a751SAndreas Gohr        echo '</ul>';
2162812a751SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=trend&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
2172812a751SAndreas Gohr        echo '</div>';
2182812a751SAndreas Gohr
21914d99ec0SAndreas Gohr
22087d5e44bSAndreas Gohr        // top pages today
221264f1744SAndreas Gohr        echo '<div>';
222264f1744SAndreas Gohr        echo '<h2>Most popular pages</h2>';
22395eb68e6SAndreas Gohr        $result = $this->sql_pages($this->tlimit,$this->start,15);
2242812a751SAndreas Gohr        $this->html_resulttable($result);
225264f1744SAndreas Gohr        echo '</div>';
22687d5e44bSAndreas Gohr
22787d5e44bSAndreas Gohr        // top referer today
228264f1744SAndreas Gohr        echo '<div>';
229e7a2f1e0SAndreas Gohr        echo '<h2>Newest incoming links</h2>';
230e7a2f1e0SAndreas Gohr        $result = $this->sql_newreferer($this->tlimit,$this->start,15);
2312812a751SAndreas Gohr        $this->html_resulttable($result);
232264f1744SAndreas Gohr        echo '</div>';
23354f6c432SAndreas Gohr
23454f6c432SAndreas Gohr        // top countries today
235264f1744SAndreas Gohr        echo '<div>';
236264f1744SAndreas Gohr        echo '<h2>Visitor\'s top countries</h2>';
23795eb68e6SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
23895eb68e6SAndreas Gohr//        $result = $this->sql_countries($this->tlimit,$this->start,15);
23995eb68e6SAndreas Gohr//        $this->html_resulttable($result,array('','Countries','Count'));
240264f1744SAndreas Gohr        echo '</div>';
241264f1744SAndreas Gohr
242264f1744SAndreas Gohr        echo '</div>';
24314d99ec0SAndreas Gohr    }
24414d99ec0SAndreas Gohr
2459da6395dSAndreas Gohr    function html_country(){
2469da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
2479da6395dSAndreas Gohr        echo '<h2>Visitor\'s Countries</h2>';
248bd4217d3SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
2499da6395dSAndreas Gohr        $result = $this->sql_countries($this->tlimit,$this->start,150);
2502812a751SAndreas Gohr        $this->html_resulttable($result);
2519da6395dSAndreas Gohr        echo '</div>';
2529da6395dSAndreas Gohr    }
2539da6395dSAndreas Gohr
2549da6395dSAndreas Gohr    function html_page(){
2559da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
2569da6395dSAndreas Gohr        echo '<h2>Popular Pages</h2>';
2579da6395dSAndreas Gohr        $result = $this->sql_pages($this->tlimit,$this->start,150);
2582812a751SAndreas Gohr        $this->html_resulttable($result);
2599da6395dSAndreas Gohr        echo '</div>';
2609da6395dSAndreas Gohr    }
2619da6395dSAndreas Gohr
26275fa767dSAndreas Gohr    function html_browser(){
26375fa767dSAndreas Gohr        echo '<div class="plg_stats_full">';
26475fa767dSAndreas Gohr        echo '<h2>Browser Shootout</h2>';
26575fa767dSAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browser&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
26675fa767dSAndreas Gohr        $result = $this->sql_browsers($this->tlimit,$this->start,150,true);
26775fa767dSAndreas Gohr        $this->html_resulttable($result);
26875fa767dSAndreas Gohr        echo '</div>';
26975fa767dSAndreas Gohr    }
27075fa767dSAndreas Gohr
271bd4217d3SAndreas Gohr    function html_os(){
272bd4217d3SAndreas Gohr        echo '<div class="plg_stats_full">';
273bd4217d3SAndreas Gohr        echo '<h2>Operating Systems</h2>';
274bd4217d3SAndreas Gohr//        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browser&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
275bd4217d3SAndreas Gohr        $result = $this->sql_os($this->tlimit,$this->start,150,true);
276bd4217d3SAndreas Gohr        $this->html_resulttable($result);
277bd4217d3SAndreas Gohr        echo '</div>';
278bd4217d3SAndreas Gohr    }
279bd4217d3SAndreas Gohr
2809da6395dSAndreas Gohr    function html_referer(){
2819da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
2829da6395dSAndreas Gohr        echo '<h2>Incoming Links</h2>';
2832812a751SAndreas Gohr        $result = $this->sql_aggregate($this->tlimit);
2842812a751SAndreas Gohr
2852812a751SAndreas Gohr        $all    = $result['search']+$result['external']+$result['direct'];
2862812a751SAndreas Gohr
287*94023548SAndreas Gohr        if($all){
2882812a751SAndreas Gohr            printf("<p>Of all %d external visits, %d (%.1f%%) were bookmarked (direct) accesses,
2892812a751SAndreas Gohr                    %d (%.1f%%) came from search engines and %d (%.1f%%) were referred through
2902812a751SAndreas Gohr                    links from other pages.</p>",$all,$result['direct'],(100*$result['direct']/$all),
2912812a751SAndreas Gohr                    $result['search'],(100*$result['search']/$all),$result['external'],
2922812a751SAndreas Gohr                    (100*$result['external']/$all));
293*94023548SAndreas Gohr        }
2942812a751SAndreas Gohr
2959da6395dSAndreas Gohr        $result = $this->sql_referer($this->tlimit,$this->start,150);
2962812a751SAndreas Gohr        $this->html_resulttable($result);
2979da6395dSAndreas Gohr        echo '</div>';
2989da6395dSAndreas Gohr    }
2999da6395dSAndreas Gohr
300e7a2f1e0SAndreas Gohr    function html_newreferer(){
301e7a2f1e0SAndreas Gohr        echo '<div class="plg_stats_full">';
302e7a2f1e0SAndreas Gohr        echo '<h2>New Incoming Links</h2>';
303e7a2f1e0SAndreas Gohr        echo '<p>The following incoming links where first logged in the selected time frame,
304e7a2f1e0SAndreas Gohr              and have never been seen before.</p>';
305e7a2f1e0SAndreas Gohr
306e7a2f1e0SAndreas Gohr        $result = $this->sql_newreferer($this->tlimit,$this->start,150);
307e7a2f1e0SAndreas Gohr        $this->html_resulttable($result);
308e7a2f1e0SAndreas Gohr        echo '</div>';
309e7a2f1e0SAndreas Gohr    }
310e7a2f1e0SAndreas Gohr
3119da6395dSAndreas Gohr
3129da6395dSAndreas Gohr
31314d99ec0SAndreas Gohr    /**
31414d99ec0SAndreas Gohr     * Display a result in a HTML table
31514d99ec0SAndreas Gohr     */
3162812a751SAndreas Gohr    function html_resulttable($result,$header=''){
31714d99ec0SAndreas Gohr        echo '<table>';
3182812a751SAndreas Gohr        if(is_array($header)){
31914d99ec0SAndreas Gohr            echo '<tr>';
32014d99ec0SAndreas Gohr            foreach($header as $h){
32114d99ec0SAndreas Gohr                echo '<th>'.hsc($h).'</th>';
32214d99ec0SAndreas Gohr            }
32314d99ec0SAndreas Gohr            echo '</tr>';
3242812a751SAndreas Gohr        }
32514d99ec0SAndreas Gohr
32614d99ec0SAndreas Gohr        foreach($result as $row){
32714d99ec0SAndreas Gohr            echo '<tr>';
32814d99ec0SAndreas Gohr            foreach($row as $k => $v){
3292812a751SAndreas Gohr                echo '<td class="plg_stats_X'.$k.'">';
33014d99ec0SAndreas Gohr                if($k == 'page'){
33114d99ec0SAndreas Gohr                    echo '<a href="'.wl($v).'" class="wikilink1">';
33214d99ec0SAndreas Gohr                    echo hsc($v);
33314d99ec0SAndreas Gohr                    echo '</a>';
33414d99ec0SAndreas Gohr                }elseif($k == 'url'){
33554f6c432SAndreas Gohr                    $url = hsc($v);
3362812a751SAndreas Gohr                    if(strlen($url) > 45){
3372812a751SAndreas Gohr                        $url = substr($url,0,30).' &hellip; '.substr($url,-15);
33854f6c432SAndreas Gohr                    }
33914d99ec0SAndreas Gohr                    echo '<a href="'.$v.'" class="urlextern">';
34054f6c432SAndreas Gohr                    echo $url;
34114d99ec0SAndreas Gohr                    echo '</a>';
34275fa767dSAndreas Gohr                }elseif($k == 'browser'){
34375fa767dSAndreas Gohr                    include_once(dirname(__FILE__).'/inc/browsers.php');
34475fa767dSAndreas Gohr                    echo $BrowsersHashIDLib[$v];
34575fa767dSAndreas Gohr                }elseif($k == 'bflag'){
34675fa767dSAndreas Gohr                    include_once(dirname(__FILE__).'/inc/browsers.php');
34775fa767dSAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.$BrowsersHashIcon[$v].'.png" alt="'.hsc($v).'" />';
348bd4217d3SAndreas Gohr                }elseif($k == 'os'){
349bd4217d3SAndreas Gohr                    if(empty($v)){
350bd4217d3SAndreas Gohr                        echo 'unknown';
351bd4217d3SAndreas Gohr                    }else{
352bd4217d3SAndreas Gohr                        include_once(dirname(__FILE__).'/inc/operating_systems.php');
353bd4217d3SAndreas Gohr                        echo $OSHashLib[$v];
354bd4217d3SAndreas Gohr                    }
355bd4217d3SAndreas Gohr                }elseif($k == 'osflag'){
356bd4217d3SAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.hsc($v).'.png" alt="'.hsc($v).'" />';
35775fa767dSAndreas Gohr                }elseif($k == 'cflag'){
35875fa767dSAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />';
35914d99ec0SAndreas Gohr                }elseif($k == 'html'){
36014d99ec0SAndreas Gohr                    echo $v;
36114d99ec0SAndreas Gohr                }else{
36214d99ec0SAndreas Gohr                    echo hsc($v);
36314d99ec0SAndreas Gohr                }
36414d99ec0SAndreas Gohr                echo '</td>';
36514d99ec0SAndreas Gohr            }
36614d99ec0SAndreas Gohr            echo '</tr>';
36714d99ec0SAndreas Gohr        }
36814d99ec0SAndreas Gohr        echo '</table>';
3691878f16fSAndreas Gohr    }
3701878f16fSAndreas Gohr
37195eb68e6SAndreas Gohr    /**
37295eb68e6SAndreas Gohr     * Create an image
37395eb68e6SAndreas Gohr     */
37495eb68e6SAndreas Gohr    function img_build($img){
37595eb68e6SAndreas Gohr        include(dirname(__FILE__).'/inc/AGC.class.php');
37695eb68e6SAndreas Gohr
37795eb68e6SAndreas Gohr        switch($img){
37895eb68e6SAndreas Gohr            case 'country':
37995eb68e6SAndreas Gohr                // build top countries + other
38095eb68e6SAndreas Gohr                $result = $this->sql_countries($this->tlimit,$this->start,0);
38195eb68e6SAndreas Gohr                $data = array();
38295eb68e6SAndreas Gohr                $top = 0;
38395eb68e6SAndreas Gohr                foreach($result as $row){
38495eb68e6SAndreas Gohr                    if($top < 7){
38595eb68e6SAndreas Gohr                        $data[$row['country']] = $row['cnt'];
38695eb68e6SAndreas Gohr                    }else{
38795eb68e6SAndreas Gohr                        $data['other'] += $row['cnt'];
38895eb68e6SAndreas Gohr                    }
38995eb68e6SAndreas Gohr                    $top++;
39095eb68e6SAndreas Gohr                }
39195eb68e6SAndreas Gohr                $pie = new AGC(300, 200);
39295eb68e6SAndreas Gohr                $pie->setProp("showkey",true);
39395eb68e6SAndreas Gohr                $pie->setProp("showval",false);
39495eb68e6SAndreas Gohr                $pie->setProp("showgrid",false);
39595eb68e6SAndreas Gohr                $pie->setProp("type","pie");
39695eb68e6SAndreas Gohr                $pie->setProp("keyinfo",1);
39795eb68e6SAndreas Gohr                $pie->setProp("keysize",8);
39895eb68e6SAndreas Gohr                $pie->setProp("keywidspc",-50);
39995eb68e6SAndreas Gohr                $pie->setProp("key",array_keys($data));
40095eb68e6SAndreas Gohr                $pie->addBulkPoints(array_values($data));
40195eb68e6SAndreas Gohr                @$pie->graph();
40295eb68e6SAndreas Gohr                $pie->showGraph();
40395eb68e6SAndreas Gohr                break;
40475fa767dSAndreas Gohr            case 'browser':
40575fa767dSAndreas Gohr                // build top browsers + other
40675fa767dSAndreas Gohr                include_once(dirname(__FILE__).'/inc/browsers.php');
40775fa767dSAndreas Gohr
40875fa767dSAndreas Gohr                $result = $this->sql_browsers($this->tlimit,$this->start,0,false);
40975fa767dSAndreas Gohr                $data = array();
41075fa767dSAndreas Gohr                $top = 0;
41175fa767dSAndreas Gohr                foreach($result as $row){
41275fa767dSAndreas Gohr                    if($top < 5){
41375fa767dSAndreas Gohr                        $data[strip_tags($BrowsersHashIDLib[$row['ua_info']])] = $row['cnt'];
41475fa767dSAndreas Gohr                    }else{
41575fa767dSAndreas Gohr                        $data['other'] += $row['cnt'];
41675fa767dSAndreas Gohr                    }
41775fa767dSAndreas Gohr                    $top++;
41875fa767dSAndreas Gohr                }
41975fa767dSAndreas Gohr                $pie = new AGC(300, 200);
42075fa767dSAndreas Gohr                $pie->setProp("showkey",true);
42175fa767dSAndreas Gohr                $pie->setProp("showval",false);
42275fa767dSAndreas Gohr                $pie->setProp("showgrid",false);
42375fa767dSAndreas Gohr                $pie->setProp("type","pie");
42475fa767dSAndreas Gohr                $pie->setProp("keyinfo",1);
42575fa767dSAndreas Gohr                $pie->setProp("keysize",8);
42675fa767dSAndreas Gohr                $pie->setProp("keywidspc",-50);
42775fa767dSAndreas Gohr                $pie->setProp("key",array_keys($data));
42875fa767dSAndreas Gohr                $pie->addBulkPoints(array_values($data));
42975fa767dSAndreas Gohr                @$pie->graph();
43075fa767dSAndreas Gohr                $pie->showGraph();
43175fa767dSAndreas Gohr                break;
4322812a751SAndreas Gohr            case 'trend':
4332812a751SAndreas Gohr                $hours  = ($this->from == $this->to);
4342812a751SAndreas Gohr                $result = $this->sql_trend($this->tlimit,$hours);
4352812a751SAndreas Gohr                $data1   = array();
4362812a751SAndreas Gohr                $data2   = array();
4372812a751SAndreas Gohr
4382812a751SAndreas Gohr                $graph = new AGC(400, 150);
4392812a751SAndreas Gohr                $graph->setProp("type","bar");
4402812a751SAndreas Gohr                $graph->setProp("showgrid",false);
4412812a751SAndreas Gohr                $graph->setProp("barwidth",.8);
44275fa767dSAndreas Gohr
4432812a751SAndreas Gohr                $graph->setColor('color',0,'blue');
4442812a751SAndreas Gohr                $graph->setColor('color',1,'red');
4452812a751SAndreas Gohr
4462812a751SAndreas Gohr                if($hours){
4472812a751SAndreas Gohr                    //preset $hours
4482812a751SAndreas Gohr                    for($i=0;$i<24;$i++){
4492812a751SAndreas Gohr                        $data1[$i] = 0;
4502812a751SAndreas Gohr                        $data2[$i] = 0;
4512812a751SAndreas Gohr                        $graph->setProp("scale",array(' 0h','   4h','   8h','    12h','    16h','    20h','    24h'));
4522812a751SAndreas Gohr                    }
4532812a751SAndreas Gohr                }else{
4542812a751SAndreas Gohr                    $graph->setProp("scale",array(next(array_keys($data1)),$this->to));
4552812a751SAndreas Gohr                }
4562812a751SAndreas Gohr
4572812a751SAndreas Gohr                foreach($result as $row){
4582812a751SAndreas Gohr                    $data1[$row['time']] = $row['pageviews'];
4592812a751SAndreas Gohr                    $data2[$row['time']] = $row['sessions'];
4602812a751SAndreas Gohr                }
4612812a751SAndreas Gohr
4622812a751SAndreas Gohr                foreach($data1 as $key => $val){
4632812a751SAndreas Gohr                    $graph->addPoint($val,$key,0);
4642812a751SAndreas Gohr                }
4652812a751SAndreas Gohr                foreach($data2 as $key => $val){
4662812a751SAndreas Gohr                    $graph->addPoint($val,$key,1);
4672812a751SAndreas Gohr                }
4682812a751SAndreas Gohr
4692812a751SAndreas Gohr                @$graph->graph();
4702812a751SAndreas Gohr                $graph->showGraph();
4712812a751SAndreas Gohr
47295eb68e6SAndreas Gohr            default:
47395eb68e6SAndreas Gohr                $this->sendGIF();
47495eb68e6SAndreas Gohr        }
47595eb68e6SAndreas Gohr    }
47695eb68e6SAndreas Gohr
47795eb68e6SAndreas Gohr
4782812a751SAndreas Gohr    /**
4792812a751SAndreas Gohr     * Return some aggregated statistics
4802812a751SAndreas Gohr     */
4812812a751SAndreas Gohr    function sql_aggregate($tlimit){
4822812a751SAndreas Gohr        $data = array();
4832812a751SAndreas Gohr
4842812a751SAndreas Gohr        $sql = "SELECT ref_type, COUNT(*) as cnt
4852812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
4862812a751SAndreas Gohr                 WHERE $tlimit
4872812a751SAndreas Gohr                   AND ua_type = 'browser'
4882812a751SAndreas Gohr              GROUP BY ref_type";
4892812a751SAndreas Gohr        $result = $this->runSQL($sql);
4902812a751SAndreas Gohr
4912812a751SAndreas Gohr        foreach($result as $row){
4922812a751SAndreas Gohr            if($row['ref_type'] == 'search')   $data['search']   = $row['cnt'];
4932812a751SAndreas Gohr            if($row['ref_type'] == 'external') $data['external'] = $row['cnt'];
4942812a751SAndreas Gohr            if($row['ref_type'] == 'internal') $data['internal'] = $row['cnt'];
4952812a751SAndreas Gohr            if($row['ref_type'] == '')         $data['direct']   = $row['cnt'];
4962812a751SAndreas Gohr        }
4972812a751SAndreas Gohr
4982812a751SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as sessions,
4992812a751SAndreas Gohr                       COUNT(session) as views,
5002812a751SAndreas Gohr                       COUNT(DISTINCT user) as users
5012812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
5022812a751SAndreas Gohr                 WHERE $tlimit
5032812a751SAndreas Gohr                   AND ua_type = 'browser'";
5042812a751SAndreas Gohr        $result = $this->runSQL($sql);
5052812a751SAndreas Gohr
50675fa767dSAndreas Gohr        $data['users']     = max($result[0]['users'] - 1,0); // subtract empty user
5072812a751SAndreas Gohr        $data['sessions']  = $result[0]['sessions'];
5082812a751SAndreas Gohr        $data['pageviews'] = $result[0]['views'];
5092812a751SAndreas Gohr
5102812a751SAndreas Gohr        $sql = "SELECT COUNT(id) as robots
5112812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
5122812a751SAndreas Gohr                 WHERE $tlimit
5132812a751SAndreas Gohr                   AND ua_type = 'robot'";
5142812a751SAndreas Gohr        $result = $this->runSQL($sql);
5152812a751SAndreas Gohr        $data['robots'] = $result[0]['robots'];
5162812a751SAndreas Gohr
5172812a751SAndreas Gohr        return $data;
5182812a751SAndreas Gohr    }
5192812a751SAndreas Gohr
520bd4217d3SAndreas Gohr    /**
521bd4217d3SAndreas Gohr     * standard statistics follow, only accesses made by browsers are counted
522bd4217d3SAndreas Gohr     * for general stats like browser or OS only visitors not pageviews are counted
523bd4217d3SAndreas Gohr     */
5242812a751SAndreas Gohr    function sql_trend($tlimit,$hours=false){
5252812a751SAndreas Gohr        if($hours){
5262812a751SAndreas Gohr            $sql = "SELECT HOUR(dt) as time,
5272812a751SAndreas Gohr                           COUNT(DISTINCT session) as sessions,
5282812a751SAndreas Gohr                           COUNT(session) as pageviews
5292812a751SAndreas Gohr                      FROM ".$this->getConf('db_prefix')."access as A
5302812a751SAndreas Gohr                     WHERE $tlimit
5312812a751SAndreas Gohr                       AND ua_type = 'browser'
5322812a751SAndreas Gohr                  GROUP BY HOUR(dt)
5332812a751SAndreas Gohr                  ORDER BY time";
5342812a751SAndreas Gohr        }else{
5352812a751SAndreas Gohr            $sql = "SELECT DATE(dt) as time,
5362812a751SAndreas Gohr                           COUNT(DISTINCT session) as sessions,
5372812a751SAndreas Gohr                           COUNT(session) as pageviews
5382812a751SAndreas Gohr                      FROM ".$this->getConf('db_prefix')."access as A
5392812a751SAndreas Gohr                     WHERE $tlimit
5402812a751SAndreas Gohr                       AND ua_type = 'browser'
5412812a751SAndreas Gohr                  GROUP BY DATE(dt)
5422812a751SAndreas Gohr                  ORDER BY time";
5432812a751SAndreas Gohr        }
5442812a751SAndreas Gohr        return $this->runSQL($sql);
5452812a751SAndreas Gohr    }
5462812a751SAndreas Gohr
54795eb68e6SAndreas Gohr    function sql_pages($tlimit,$start=0,$limit=20){
5482812a751SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, page
54995eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
55095eb68e6SAndreas Gohr                 WHERE $tlimit
55195eb68e6SAndreas Gohr                   AND ua_type = 'browser'
55295eb68e6SAndreas Gohr              GROUP BY page
55395eb68e6SAndreas Gohr              ORDER BY cnt DESC, page".
55495eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
55595eb68e6SAndreas Gohr        return $this->runSQL($sql);
55695eb68e6SAndreas Gohr    }
55795eb68e6SAndreas Gohr
55895eb68e6SAndreas Gohr    function sql_referer($tlimit,$start=0,$limit=20){
5592812a751SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, ref as url
56095eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
56195eb68e6SAndreas Gohr                 WHERE $tlimit
56295eb68e6SAndreas Gohr                   AND ua_type = 'browser'
56395eb68e6SAndreas Gohr                   AND ref_type = 'external'
56495eb68e6SAndreas Gohr              GROUP BY ref_md5
56595eb68e6SAndreas Gohr              ORDER BY cnt DESC, url".
56695eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
56795eb68e6SAndreas Gohr        return $this->runSQL($sql);
56895eb68e6SAndreas Gohr    }
56995eb68e6SAndreas Gohr
570e7a2f1e0SAndreas Gohr    function sql_newreferer($tlimit,$start=0,$limit=20){
571e7a2f1e0SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, ref as url
572e7a2f1e0SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
573e7a2f1e0SAndreas Gohr                 WHERE ua_type = 'browser'
574e7a2f1e0SAndreas Gohr                   AND ref_type = 'external'
575e7a2f1e0SAndreas Gohr              GROUP BY ref_md5
576e7a2f1e0SAndreas Gohr                HAVING DATE(MIN(dt)) >= DATE('".$this->from."')
577e7a2f1e0SAndreas Gohr                   AND DATE(MIN(dt)) <= DATE('".$this->to."')
578e7a2f1e0SAndreas Gohr              ORDER BY cnt DESC, url".
579e7a2f1e0SAndreas Gohr              $this->sql_limit($start,$limit);
580e7a2f1e0SAndreas Gohr        return $this->runSQL($sql);
581e7a2f1e0SAndreas Gohr    }
582e7a2f1e0SAndreas Gohr
58395eb68e6SAndreas Gohr    function sql_countries($tlimit,$start=0,$limit=20){
584bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country
58595eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A,
58695eb68e6SAndreas Gohr                       ".$this->getConf('db_prefix')."iplocation as B
58795eb68e6SAndreas Gohr                 WHERE $tlimit
58895eb68e6SAndreas Gohr                   AND A.ip = B.ip
58995eb68e6SAndreas Gohr              GROUP BY B.country
59095eb68e6SAndreas Gohr              ORDER BY cnt DESC, B.country".
59195eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
59295eb68e6SAndreas Gohr        return $this->runSQL($sql);
59395eb68e6SAndreas Gohr    }
59495eb68e6SAndreas Gohr
59575fa767dSAndreas Gohr    function sql_browsers($tlimit,$start=0,$limit=20,$ext=true){
59675fa767dSAndreas Gohr        if($ext){
59775fa767dSAndreas Gohr            $sel = 'ua_info as bflag, ua_info as browser, ua_ver';
59875fa767dSAndreas Gohr            $grp = 'ua_info, ua_ver';
59975fa767dSAndreas Gohr        }else{
60075fa767dSAndreas Gohr            $grp = 'ua_info';
60175fa767dSAndreas Gohr            $sel = 'ua_info';
60275fa767dSAndreas Gohr        }
60375fa767dSAndreas Gohr
604bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel
60575fa767dSAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
60675fa767dSAndreas Gohr                 WHERE $tlimit
60775fa767dSAndreas Gohr                   AND ua_type = 'browser'
60875fa767dSAndreas Gohr              GROUP BY $grp
60975fa767dSAndreas Gohr              ORDER BY cnt DESC, ua_info".
61075fa767dSAndreas Gohr              $this->sql_limit($start,$limit);
61175fa767dSAndreas Gohr        return $this->runSQL($sql);
61275fa767dSAndreas Gohr    }
61375fa767dSAndreas Gohr
614bd4217d3SAndreas Gohr    function sql_os($tlimit,$start=0,$limit=20){
615bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os
616bd4217d3SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
617bd4217d3SAndreas Gohr                 WHERE $tlimit
618bd4217d3SAndreas Gohr                   AND ua_type = 'browser'
619bd4217d3SAndreas Gohr              GROUP BY os
620bd4217d3SAndreas Gohr              ORDER BY cnt DESC, os".
621bd4217d3SAndreas Gohr              $this->sql_limit($start,$limit);
622bd4217d3SAndreas Gohr        return $this->runSQL($sql);
623bd4217d3SAndreas Gohr    }
624bd4217d3SAndreas Gohr
62575fa767dSAndreas Gohr
62695eb68e6SAndreas Gohr    /**
62795eb68e6SAndreas Gohr     * Builds a limit clause
62895eb68e6SAndreas Gohr     */
62995eb68e6SAndreas Gohr    function sql_limit($start,$limit){
63095eb68e6SAndreas Gohr        $start = (int) $start;
63195eb68e6SAndreas Gohr        $limit = (int) $limit;
63295eb68e6SAndreas Gohr        if($limit){
63395eb68e6SAndreas Gohr            return " LIMIT $start,$limit";
63495eb68e6SAndreas Gohr        }elseif($start){
63595eb68e6SAndreas Gohr            return " OFFSET $start";
63695eb68e6SAndreas Gohr        }
63795eb68e6SAndreas Gohr        return '';
63895eb68e6SAndreas Gohr    }
6391878f16fSAndreas Gohr
6401878f16fSAndreas Gohr    /**
64114d99ec0SAndreas Gohr     * Return a link to the DB, opening the connection if needed
6421878f16fSAndreas Gohr     */
64314d99ec0SAndreas Gohr    function dbLink(){
6441878f16fSAndreas Gohr        // connect to DB if needed
6451878f16fSAndreas Gohr        if(!$this->dblink){
6461878f16fSAndreas Gohr            $this->dblink = mysql_connect($this->getConf('db_server'),
6471878f16fSAndreas Gohr                                          $this->getConf('db_user'),
6481878f16fSAndreas Gohr                                          $this->getConf('db_password'));
6491878f16fSAndreas Gohr            if(!$this->dblink){
6501878f16fSAndreas Gohr                msg('DB Error: connection failed',-1);
6511878f16fSAndreas Gohr                return null;
6521878f16fSAndreas Gohr            }
6531878f16fSAndreas Gohr            // set utf-8
6541878f16fSAndreas Gohr            if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){
6551878f16fSAndreas Gohr                msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1);
6561878f16fSAndreas Gohr                return null;
6571878f16fSAndreas Gohr            }
6581878f16fSAndreas Gohr        }
65914d99ec0SAndreas Gohr        return $this->dblink;
66014d99ec0SAndreas Gohr    }
6611878f16fSAndreas Gohr
66214d99ec0SAndreas Gohr    /**
66314d99ec0SAndreas Gohr     * Simple function to run a DB query
66414d99ec0SAndreas Gohr     */
66514d99ec0SAndreas Gohr    function runSQL($sql_string) {
66614d99ec0SAndreas Gohr        $link = $this->dbLink();
66714d99ec0SAndreas Gohr
66814d99ec0SAndreas Gohr        $result = mysql_db_query($this->conf['db_database'],$sql_string,$link);
66994171ff3SAndreas Gohr        if(!$result){
6702812a751SAndreas Gohr            msg('DB Error: '.mysql_error($link).' '.hsc($sql_string),-1);
6711878f16fSAndreas Gohr            return null;
6721878f16fSAndreas Gohr        }
6731878f16fSAndreas Gohr
6741878f16fSAndreas Gohr        $resultarray = array();
6751878f16fSAndreas Gohr
6761878f16fSAndreas Gohr        //mysql_db_query returns 1 on a insert statement -> no need to ask for results
6771878f16fSAndreas Gohr        if ($result != 1) {
6781878f16fSAndreas Gohr            for($i=0; $i< mysql_num_rows($result); $i++) {
6791878f16fSAndreas Gohr                $temparray = mysql_fetch_assoc($result);
6801878f16fSAndreas Gohr                $resultarray[]=$temparray;
6811878f16fSAndreas Gohr            }
6821878f16fSAndreas Gohr            mysql_free_result($result);
6831878f16fSAndreas Gohr        }
6841878f16fSAndreas Gohr
68514d99ec0SAndreas Gohr        if (mysql_insert_id($link)) {
68614d99ec0SAndreas Gohr            $resultarray = mysql_insert_id($link); //give back ID on insert
6871878f16fSAndreas Gohr        }
6881878f16fSAndreas Gohr
6891878f16fSAndreas Gohr        return $resultarray;
6901878f16fSAndreas Gohr    }
6911878f16fSAndreas Gohr
6921878f16fSAndreas Gohr    /**
69314d99ec0SAndreas Gohr     * Returns a short name for a User Agent and sets type, version and os info
6941878f16fSAndreas Gohr     */
69514d99ec0SAndreas Gohr    function ua_info($ua,&$type,&$ver,&$os){
69614d99ec0SAndreas Gohr        $ua = strtr($ua,' +','__');
69714d99ec0SAndreas Gohr        $ua = strtolower($ua);
69814d99ec0SAndreas Gohr
69914d99ec0SAndreas Gohr        // common browsers
70014d99ec0SAndreas Gohr        $regvermsie     = '/msie([+_ ]|)([\d\.]*)/i';
70114d99ec0SAndreas Gohr        $regvernetscape = '/netscape.?\/([\d\.]*)/i';
70214d99ec0SAndreas Gohr        $regverfirefox  = '/firefox\/([\d\.]*)/i';
70314d99ec0SAndreas Gohr        $regversvn      = '/svn\/([\d\.]*)/i';
70414d99ec0SAndreas Gohr        $regvermozilla  = '/mozilla(\/|)([\d\.]*)/i';
70514d99ec0SAndreas Gohr        $regnotie       = '/webtv|omniweb|opera/i';
70614d99ec0SAndreas Gohr        $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i';
70714d99ec0SAndreas Gohr
70814d99ec0SAndreas Gohr        $name = '';
70914d99ec0SAndreas Gohr        # IE ?
71014d99ec0SAndreas Gohr        if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){
71114d99ec0SAndreas Gohr            $type = 'browser';
71214d99ec0SAndreas Gohr            $ver  = $m[2];
71314d99ec0SAndreas Gohr            $name = 'msie';
71414d99ec0SAndreas Gohr        }
71514d99ec0SAndreas Gohr        # Firefox ?
71614d99ec0SAndreas Gohr        elseif (preg_match($regverfirefox,$ua,$m)){
71714d99ec0SAndreas Gohr            $type = 'browser';
71814d99ec0SAndreas Gohr            $ver  = $m[1];
71914d99ec0SAndreas Gohr            $name = 'firefox';
72014d99ec0SAndreas Gohr        }
72114d99ec0SAndreas Gohr        # Subversion ?
72214d99ec0SAndreas Gohr        elseif (preg_match($regversvn,$ua,$m)){
72314d99ec0SAndreas Gohr            $type = 'rcs';
72414d99ec0SAndreas Gohr            $ver  = $m[1];
72514d99ec0SAndreas Gohr            $name = 'svn';
72614d99ec0SAndreas Gohr        }
72714d99ec0SAndreas Gohr        # Netscape 6.x, 7.x ... ?
72814d99ec0SAndreas Gohr        elseif (preg_match($regvernetscape,$ua,$m)){
72914d99ec0SAndreas Gohr            $type = 'browser';
73014d99ec0SAndreas Gohr            $ver  = $m[1];
73114d99ec0SAndreas Gohr            $name = 'netscape';
73214d99ec0SAndreas Gohr        }
73314d99ec0SAndreas Gohr        # Netscape 3.x, 4.x ... ?
73414d99ec0SAndreas Gohr        elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){
73514d99ec0SAndreas Gohr            $type = 'browser';
73614d99ec0SAndreas Gohr            $ver  = $m[2];
73714d99ec0SAndreas Gohr            $name = 'netscape';
73814d99ec0SAndreas Gohr        }else{
73914d99ec0SAndreas Gohr            include(dirname(__FILE__).'/inc/browsers.php');
74014d99ec0SAndreas Gohr            foreach($BrowsersSearchIDOrder as $regex){
74114d99ec0SAndreas Gohr                if(preg_match('/'.$regex.'/',$ua)){
74214d99ec0SAndreas Gohr                    // it's a browser!
74314d99ec0SAndreas Gohr                    $type = 'browser';
74414d99ec0SAndreas Gohr                    $name = strtolower($regex);
74514d99ec0SAndreas Gohr                    break;
74614d99ec0SAndreas Gohr                }
74714d99ec0SAndreas Gohr            }
74814d99ec0SAndreas Gohr        }
74914d99ec0SAndreas Gohr
75075fa767dSAndreas Gohr        // check versions for Safari and Opera
75175fa767dSAndreas Gohr        if($name == 'safari'){
75275fa767dSAndreas Gohr            if(preg_match('/safari\/([\d\.]*)/i',$ua,$match)){
75375fa767dSAndreas Gohr                $ver = $BrowsersSafariBuildToVersionHash[$match[1]];
75475fa767dSAndreas Gohr            }
75575fa767dSAndreas Gohr        }elseif($name == 'opera'){
75675fa767dSAndreas Gohr            if(preg_match('/opera[\/ ]([\d\.]*)/i',$ua,$match)){
75775fa767dSAndreas Gohr                $ver = $match[1];
75875fa767dSAndreas Gohr            }
75975fa767dSAndreas Gohr        }
76075fa767dSAndreas Gohr
76175fa767dSAndreas Gohr
76214d99ec0SAndreas Gohr        // check OS for browsers
76314d99ec0SAndreas Gohr        if($type == 'browser'){
76414d99ec0SAndreas Gohr            include(dirname(__FILE__).'/inc/operating_systems.php');
76514d99ec0SAndreas Gohr            foreach($OSSearchIDOrder as $regex){
76614d99ec0SAndreas Gohr                if(preg_match('/'.$regex.'/',$ua)){
76714d99ec0SAndreas Gohr                    $os = $OSHashID[$regex];
76814d99ec0SAndreas Gohr                    break;
76914d99ec0SAndreas Gohr                }
77014d99ec0SAndreas Gohr            }
77114d99ec0SAndreas Gohr
77214d99ec0SAndreas Gohr        }
77314d99ec0SAndreas Gohr
77414d99ec0SAndreas Gohr        // are we done now?
77514d99ec0SAndreas Gohr        if($name) return $name;
77614d99ec0SAndreas Gohr
77714d99ec0SAndreas Gohr        include(dirname(__FILE__).'/inc/robots.php');
77814d99ec0SAndreas Gohr        foreach($RobotsSearchIDOrder as $regex){
77914d99ec0SAndreas Gohr            if(preg_match('/'.$regex.'/',$ua)){
78014d99ec0SAndreas Gohr                    // it's a robot!
78114d99ec0SAndreas Gohr                    $type = 'robot';
78214d99ec0SAndreas Gohr                    return strtolower($regex);
78314d99ec0SAndreas Gohr            }
78414d99ec0SAndreas Gohr        }
78514d99ec0SAndreas Gohr
78614d99ec0SAndreas Gohr        // dunno
7871878f16fSAndreas Gohr        return '';
7881878f16fSAndreas Gohr    }
7891878f16fSAndreas Gohr
7901878f16fSAndreas Gohr    /**
79114d99ec0SAndreas Gohr     *
79214d99ec0SAndreas Gohr     * @fixme: put search engine queries in seperate table here
79314d99ec0SAndreas Gohr     */
79414d99ec0SAndreas Gohr    function log_search($referer,&$type){
79514d99ec0SAndreas Gohr        $referer = strtr($referer,' +','__');
79614d99ec0SAndreas Gohr        $referer = strtolower($referer);
79714d99ec0SAndreas Gohr
79814d99ec0SAndreas Gohr        include(dirname(__FILE__).'/inc/search_engines.php');
79914d99ec0SAndreas Gohr
80014d99ec0SAndreas Gohr        foreach($SearchEnginesSearchIDOrder as $regex){
80114d99ec0SAndreas Gohr            if(preg_match('/'.$regex.'/',$referer)){
80214d99ec0SAndreas Gohr                if(!$NotSearchEnginesKeys[$regex] ||
80314d99ec0SAndreas Gohr                   !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$referer)){
80414d99ec0SAndreas Gohr                    // it's a search engine!
80514d99ec0SAndreas Gohr                    $type = 'search';
80614d99ec0SAndreas Gohr                    break;
80714d99ec0SAndreas Gohr                }
80814d99ec0SAndreas Gohr            }
80914d99ec0SAndreas Gohr        }
81014d99ec0SAndreas Gohr        if($type != 'search') return; // we're done here
81114d99ec0SAndreas Gohr
81214d99ec0SAndreas Gohr        #fixme now do the keyword magic!
81314d99ec0SAndreas Gohr    }
81414d99ec0SAndreas Gohr
81514d99ec0SAndreas Gohr    /**
81614d99ec0SAndreas Gohr     * Resolve IP to country/city
81714d99ec0SAndreas Gohr     */
81814d99ec0SAndreas Gohr    function log_ip($ip){
81914d99ec0SAndreas Gohr        // check if IP already known and up-to-date
82014d99ec0SAndreas Gohr        $sql = "SELECT ip
82114d99ec0SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."iplocation
82214d99ec0SAndreas Gohr                 WHERE ip ='".addslashes($ip)."'
82314d99ec0SAndreas Gohr                   AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)";
82414d99ec0SAndreas Gohr        $result = $this->runSQL($sql);
82514d99ec0SAndreas Gohr        if($result[0]['ip']) return;
82614d99ec0SAndreas Gohr
82714d99ec0SAndreas Gohr        $http = new DokuHTTPClient();
82814d99ec0SAndreas Gohr        $http->timeout = 10;
82914d99ec0SAndreas Gohr        $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip);
83014d99ec0SAndreas Gohr
83114d99ec0SAndreas Gohr        if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){
83214d99ec0SAndreas Gohr            $country = addslashes(trim($match[1]));
83314d99ec0SAndreas Gohr            $code    = addslashes(strtolower(trim($match[2])));
83414d99ec0SAndreas Gohr            $city    = addslashes(trim($match[3]));
83514d99ec0SAndreas Gohr            $host    = addslashes(gethostbyaddr($ip));
83614d99ec0SAndreas Gohr            $ip      = addslashes($ip);
83714d99ec0SAndreas Gohr
83814d99ec0SAndreas Gohr            $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation
83914d99ec0SAndreas Gohr                        SET ip = '$ip',
84014d99ec0SAndreas Gohr                            country = '$country',
84114d99ec0SAndreas Gohr                            code    = '$code',
84214d99ec0SAndreas Gohr                            city    = '$city',
84314d99ec0SAndreas Gohr                            host    = '$host'";
84414d99ec0SAndreas Gohr            $this->runSQL($sql);
84514d99ec0SAndreas Gohr        }
84614d99ec0SAndreas Gohr    }
84714d99ec0SAndreas Gohr
84814d99ec0SAndreas Gohr    /**
8491878f16fSAndreas Gohr     * log a page access
8501878f16fSAndreas Gohr     *
8511878f16fSAndreas Gohr     * called from log.php
8521878f16fSAndreas Gohr     */
8531878f16fSAndreas Gohr    function log_access(){
85494171ff3SAndreas Gohr        if(!$_REQUEST['p']) return;
85594171ff3SAndreas Gohr
85614d99ec0SAndreas Gohr        # FIXME check referer against blacklist and drop logging for bad boys
85714d99ec0SAndreas Gohr
85814d99ec0SAndreas Gohr        // handle referer
85914d99ec0SAndreas Gohr        $referer = trim($_REQUEST['r']);
86014d99ec0SAndreas Gohr        if($referer){
86114d99ec0SAndreas Gohr            $ref     = addslashes($referer);
86214d99ec0SAndreas Gohr            $ref_md5 = ($ref) ? md5($referer) : '';
86314d99ec0SAndreas Gohr            if(strpos($referer,DOKU_URL) === 0){
86414d99ec0SAndreas Gohr                $ref_type = 'internal';
86514d99ec0SAndreas Gohr            }else{
86614d99ec0SAndreas Gohr                $ref_type = 'external';
86714d99ec0SAndreas Gohr                $this->log_search($referer,$ref_type);
86814d99ec0SAndreas Gohr            }
86914d99ec0SAndreas Gohr        }else{
87014d99ec0SAndreas Gohr            $ref      = '';
87114d99ec0SAndreas Gohr            $ref_md5  = '';
87214d99ec0SAndreas Gohr            $ref_type = '';
87314d99ec0SAndreas Gohr        }
87414d99ec0SAndreas Gohr
87514d99ec0SAndreas Gohr        // handle user agent
87614d99ec0SAndreas Gohr        $agent   = trim($_SERVER['HTTP_USER_AGENT']);
87714d99ec0SAndreas Gohr
87814d99ec0SAndreas Gohr        $ua      = addslashes($agent);
87914d99ec0SAndreas Gohr        $ua_type = '';
88014d99ec0SAndreas Gohr        $ua_ver  = '';
88114d99ec0SAndreas Gohr        $os      = '';
88214d99ec0SAndreas Gohr        $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os));
88314d99ec0SAndreas Gohr
8841878f16fSAndreas Gohr        $page    = addslashes($_REQUEST['p']);
8851878f16fSAndreas Gohr        $ip      = addslashes($_SERVER['REMOTE_ADDR']);
8861878f16fSAndreas Gohr        $sx      = (int) $_REQUEST['sx'];
8871878f16fSAndreas Gohr        $sy      = (int) $_REQUEST['sy'];
8881878f16fSAndreas Gohr        $vx      = (int) $_REQUEST['vx'];
8891878f16fSAndreas Gohr        $vy      = (int) $_REQUEST['vy'];
89075fa767dSAndreas Gohr        $js      = (int) $_REQUEST['js'];
8911878f16fSAndreas Gohr        $user    = addslashes($_SERVER['REMOTE_USER']);
8921878f16fSAndreas Gohr        $session = addslashes(session_id());
8931878f16fSAndreas Gohr
89494171ff3SAndreas Gohr        $sql  = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access
89575fa767dSAndreas Gohr                    SET dt       = NOW(),
89675fa767dSAndreas Gohr                        page     = '$page',
8971878f16fSAndreas Gohr                        ip       = '$ip',
8981878f16fSAndreas Gohr                        ua       = '$ua',
8991878f16fSAndreas Gohr                        ua_info  = '$ua_info',
90014d99ec0SAndreas Gohr                        ua_type  = '$ua_type',
90114d99ec0SAndreas Gohr                        ua_ver   = '$ua_ver',
90214d99ec0SAndreas Gohr                        os       = '$os',
9031878f16fSAndreas Gohr                        ref      = '$ref',
90494171ff3SAndreas Gohr                        ref_md5  = '$ref_md5',
90514d99ec0SAndreas Gohr                        ref_type = '$ref_type',
9061878f16fSAndreas Gohr                        screen_x = '$sx',
9071878f16fSAndreas Gohr                        screen_y = '$sy',
9081878f16fSAndreas Gohr                        view_x   = '$vx',
9091878f16fSAndreas Gohr                        view_y   = '$vy',
91075fa767dSAndreas Gohr                        js       = '$js',
9111878f16fSAndreas Gohr                        user     = '$user',
9121878f16fSAndreas Gohr                        session  = '$session'";
9131878f16fSAndreas Gohr        $ok = $this->runSQL($sql);
9141878f16fSAndreas Gohr        if(is_null($ok)){
9151878f16fSAndreas Gohr            global $MSG;
9161878f16fSAndreas Gohr            print_r($MSG);
9171878f16fSAndreas Gohr        }
91814d99ec0SAndreas Gohr
91914d99ec0SAndreas Gohr        // resolve the IP
92014d99ec0SAndreas Gohr        $this->log_ip($_SERVER['REMOTE_ADDR']);
9211878f16fSAndreas Gohr    }
9221878f16fSAndreas Gohr
9231878f16fSAndreas Gohr    /**
9241878f16fSAndreas Gohr     * Just send a 1x1 pixel blank gif to the browser
9251878f16fSAndreas Gohr     *
9261878f16fSAndreas Gohr     * @called from log.php
9271878f16fSAndreas Gohr     *
9281878f16fSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
9291878f16fSAndreas Gohr     * @author Harry Fuecks <fuecks@gmail.com>
9301878f16fSAndreas Gohr     */
9311878f16fSAndreas Gohr    function sendGIF(){
9321878f16fSAndreas Gohr        $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7');
9331878f16fSAndreas Gohr        header('Content-Type: image/gif');
9341878f16fSAndreas Gohr        header('Content-Length: '.strlen($img));
9351878f16fSAndreas Gohr        header('Connection: Close');
9361878f16fSAndreas Gohr        print $img;
9371878f16fSAndreas Gohr        flush();
9381878f16fSAndreas Gohr        // Browser should drop connection after this
9391878f16fSAndreas Gohr        // Thinks it's got the whole image
9401878f16fSAndreas Gohr    }
9411878f16fSAndreas Gohr
9421878f16fSAndreas Gohr}
943