xref: /plugin/statistics/admin.php (revision 2507f8e043d11a789de9fff599741c0207aa7e2f)
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">';
111*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=&amp;f='.$this->from.'&amp;t='.$this->to.'">Dashboard</a>';
1129da6395dSAndreas Gohr        echo '</div></li>';
1139da6395dSAndreas Gohr
1149da6395dSAndreas Gohr        echo '<li><div class="li">';
115*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'">Pages</a>';
1169da6395dSAndreas Gohr        echo '</div></li>';
1179da6395dSAndreas Gohr
1189da6395dSAndreas Gohr        echo '<li><div class="li">';
119*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=referer&amp;f='.$this->from.'&amp;t='.$this->to.'">Incoming Links</a>';
1209da6395dSAndreas Gohr        echo '</div></li>';
1219da6395dSAndreas Gohr
1229da6395dSAndreas Gohr        echo '<li><div class="li">';
123*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'">New Incoming Links</a>';
124e7a2f1e0SAndreas Gohr        echo '</div></li>';
125e7a2f1e0SAndreas Gohr
126e7a2f1e0SAndreas Gohr        echo '<li><div class="li">';
127*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=browser&amp;f='.$this->from.'&amp;t='.$this->to.'">Browsers</a>';
12875fa767dSAndreas Gohr        echo '</div></li>';
12975fa767dSAndreas Gohr
13075fa767dSAndreas Gohr        echo '<li><div class="li">';
131*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=os&amp;f='.$this->from.'&amp;t='.$this->to.'">Operating Systems</a>';
132bd4217d3SAndreas Gohr        echo '</div></li>';
133bd4217d3SAndreas Gohr
134bd4217d3SAndreas Gohr        echo '<li><div class="li">';
135*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=country&amp;f='.$this->from.'&amp;t='.$this->to.'">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
143*2507f8e0SAndreas Gohr    function html_pager($limit,$next){
144*2507f8e0SAndreas Gohr        echo '<div class="plg_stats_pager">';
145*2507f8e0SAndreas Gohr
146*2507f8e0SAndreas Gohr        if($this->start > 0){
147*2507f8e0SAndreas Gohr            $go = max($this->start - $limit, 0);
148*2507f8e0SAndreas 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>';
149*2507f8e0SAndreas Gohr        }
150*2507f8e0SAndreas Gohr
151*2507f8e0SAndreas Gohr        if($next){
152*2507f8e0SAndreas Gohr            $go = $this->start + $limit;
153*2507f8e0SAndreas 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>';
154*2507f8e0SAndreas Gohr        }
155*2507f8e0SAndreas Gohr        echo '</div>';
156*2507f8e0SAndreas Gohr    }
157*2507f8e0SAndreas Gohr
158264f1744SAndreas Gohr    /**
159264f1744SAndreas Gohr     * Print the time selection menu
160264f1744SAndreas Gohr     */
16114d99ec0SAndreas Gohr    function html_timeselect(){
162264f1744SAndreas Gohr        $now   = date('Y-m-d');
163264f1744SAndreas Gohr        $yday  = date('Y-m-d',time()-(60*60*24));
164264f1744SAndreas Gohr        $week  = date('Y-m-d',time()-(60*60*24*7));
165264f1744SAndreas Gohr        $month = date('Y-m-d',time()-(60*60*24*30));
16614d99ec0SAndreas Gohr
167264f1744SAndreas Gohr        echo '<div class="plg_stats_timeselect">';
168264f1744SAndreas Gohr        echo '<span>Select the timeframe:</span>';
169264f1744SAndreas Gohr        echo '<ul>';
170264f1744SAndreas Gohr
171264f1744SAndreas Gohr        echo '<li>';
172*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$now.'&amp;t='.$now.'">';
173264f1744SAndreas Gohr        echo 'today';
174264f1744SAndreas Gohr        echo '</a>';
175264f1744SAndreas Gohr        echo '</li>';
176264f1744SAndreas Gohr
177264f1744SAndreas Gohr        echo '<li>';
178*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$yday.'&amp;t='.$yday.'">';
179264f1744SAndreas Gohr        echo 'yesterday';
180264f1744SAndreas Gohr        echo '</a>';
181264f1744SAndreas Gohr        echo '</li>';
182264f1744SAndreas Gohr
183264f1744SAndreas Gohr        echo '<li>';
184*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$week.'&amp;t='.$now.'">';
185264f1744SAndreas Gohr        echo 'last 7 days';
186264f1744SAndreas Gohr        echo '</a>';
187264f1744SAndreas Gohr        echo '</li>';
188264f1744SAndreas Gohr
189264f1744SAndreas Gohr        echo '<li>';
190*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$month.'&amp;t='.$now.'">';
191264f1744SAndreas Gohr        echo 'last 30 days';
192264f1744SAndreas Gohr        echo '</a>';
193264f1744SAndreas Gohr        echo '</li>';
194264f1744SAndreas Gohr
195264f1744SAndreas Gohr        echo '</ul>';
196264f1744SAndreas Gohr
197264f1744SAndreas Gohr
198264f1744SAndreas Gohr        echo '<form action="" method="get">';
199264f1744SAndreas Gohr        echo '<input type="hidden" name="do" value="admin" />';
200264f1744SAndreas Gohr        echo '<input type="hidden" name="page" value="statistics" />';
201264f1744SAndreas Gohr        echo '<input type="hidden" name="opt" value="'.$this->opt.'" />';
202264f1744SAndreas Gohr        echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />';
203264f1744SAndreas Gohr        echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />';
204264f1744SAndreas Gohr        echo '<input type="submit" value="go" class="button" />';
20514d99ec0SAndreas Gohr        echo '</form>';
206264f1744SAndreas Gohr
207264f1744SAndreas Gohr        echo '</div>';
20814d99ec0SAndreas Gohr    }
20914d99ec0SAndreas Gohr
21014d99ec0SAndreas Gohr
211f5f32cbfSAndreas Gohr    /**
212f5f32cbfSAndreas Gohr     * Print an introductionary screen
213f5f32cbfSAndreas Gohr     */
21414d99ec0SAndreas Gohr    function html_dashboard(){
2152812a751SAndreas Gohr        echo '<p>This page gives you a quick overview on what is happening in your Wiki. For detailed lists
2162812a751SAndreas Gohr              choose a topic from the list.</p>';
2172812a751SAndreas Gohr
2182812a751SAndreas Gohr
219264f1744SAndreas Gohr        echo '<div class="plg_stats_dashboard">';
220264f1744SAndreas Gohr
2212812a751SAndreas Gohr        // general info
2222812a751SAndreas Gohr        echo '<div class="plg_stats_top">';
2232812a751SAndreas Gohr        $result = $this->sql_aggregate($this->tlimit);
2242812a751SAndreas Gohr        echo '<ul>';
2252812a751SAndreas Gohr        echo '<li><span>'.$result['pageviews'].'</span> page views</li>';
2262812a751SAndreas Gohr        echo '<li><span>'.$result['sessions'].'</span> visitors (sessions)</li>';
2272812a751SAndreas Gohr        echo '<li><span>'.$result['users'].'</span> logged in users</li>';
2282812a751SAndreas Gohr
2292812a751SAndreas Gohr        echo '</ul>';
2302812a751SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=trend&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
2312812a751SAndreas Gohr        echo '</div>';
2322812a751SAndreas Gohr
23314d99ec0SAndreas Gohr
23487d5e44bSAndreas Gohr        // top pages today
235264f1744SAndreas Gohr        echo '<div>';
236264f1744SAndreas Gohr        echo '<h2>Most popular pages</h2>';
23795eb68e6SAndreas Gohr        $result = $this->sql_pages($this->tlimit,$this->start,15);
2382812a751SAndreas Gohr        $this->html_resulttable($result);
239*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
240264f1744SAndreas Gohr        echo '</div>';
24187d5e44bSAndreas Gohr
24287d5e44bSAndreas Gohr        // top referer today
243264f1744SAndreas Gohr        echo '<div>';
244e7a2f1e0SAndreas Gohr        echo '<h2>Newest incoming links</h2>';
245e7a2f1e0SAndreas Gohr        $result = $this->sql_newreferer($this->tlimit,$this->start,15);
2462812a751SAndreas Gohr        $this->html_resulttable($result);
247*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
248264f1744SAndreas Gohr        echo '</div>';
24954f6c432SAndreas Gohr
25054f6c432SAndreas Gohr        // top countries today
251264f1744SAndreas Gohr        echo '<div>';
252264f1744SAndreas Gohr        echo '<h2>Visitor\'s top countries</h2>';
25395eb68e6SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
254*2507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=country&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
255264f1744SAndreas Gohr        echo '</div>';
256264f1744SAndreas Gohr
257264f1744SAndreas Gohr        echo '</div>';
25814d99ec0SAndreas Gohr    }
25914d99ec0SAndreas Gohr
2609da6395dSAndreas Gohr    function html_country(){
2619da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
2629da6395dSAndreas Gohr        echo '<h2>Visitor\'s Countries</h2>';
263bd4217d3SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
2649da6395dSAndreas Gohr        $result = $this->sql_countries($this->tlimit,$this->start,150);
265*2507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
2669da6395dSAndreas Gohr        echo '</div>';
2679da6395dSAndreas Gohr    }
2689da6395dSAndreas Gohr
2699da6395dSAndreas Gohr    function html_page(){
2709da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
2719da6395dSAndreas Gohr        echo '<h2>Popular Pages</h2>';
2729da6395dSAndreas Gohr        $result = $this->sql_pages($this->tlimit,$this->start,150);
273*2507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
2749da6395dSAndreas Gohr        echo '</div>';
2759da6395dSAndreas Gohr    }
2769da6395dSAndreas Gohr
27775fa767dSAndreas Gohr    function html_browser(){
27875fa767dSAndreas Gohr        echo '<div class="plg_stats_full">';
27975fa767dSAndreas Gohr        echo '<h2>Browser Shootout</h2>';
28075fa767dSAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browser&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
28175fa767dSAndreas Gohr        $result = $this->sql_browsers($this->tlimit,$this->start,150,true);
282*2507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
28375fa767dSAndreas Gohr        echo '</div>';
28475fa767dSAndreas Gohr    }
28575fa767dSAndreas Gohr
286bd4217d3SAndreas Gohr    function html_os(){
287bd4217d3SAndreas Gohr        echo '<div class="plg_stats_full">';
288bd4217d3SAndreas Gohr        echo '<h2>Operating Systems</h2>';
289bd4217d3SAndreas Gohr        $result = $this->sql_os($this->tlimit,$this->start,150,true);
290*2507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
291bd4217d3SAndreas Gohr        echo '</div>';
292bd4217d3SAndreas Gohr    }
293bd4217d3SAndreas Gohr
2949da6395dSAndreas Gohr    function html_referer(){
2959da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
2969da6395dSAndreas Gohr        echo '<h2>Incoming Links</h2>';
2972812a751SAndreas Gohr        $result = $this->sql_aggregate($this->tlimit);
2982812a751SAndreas Gohr
2992812a751SAndreas Gohr        $all    = $result['search']+$result['external']+$result['direct'];
3002812a751SAndreas Gohr
30194023548SAndreas Gohr        if($all){
3022812a751SAndreas Gohr            printf("<p>Of all %d external visits, %d (%.1f%%) were bookmarked (direct) accesses,
3032812a751SAndreas Gohr                    %d (%.1f%%) came from search engines and %d (%.1f%%) were referred through
3042812a751SAndreas Gohr                    links from other pages.</p>",$all,$result['direct'],(100*$result['direct']/$all),
3052812a751SAndreas Gohr                    $result['search'],(100*$result['search']/$all),$result['external'],
3062812a751SAndreas Gohr                    (100*$result['external']/$all));
30794023548SAndreas Gohr        }
3082812a751SAndreas Gohr
3099da6395dSAndreas Gohr        $result = $this->sql_referer($this->tlimit,$this->start,150);
310*2507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
3119da6395dSAndreas Gohr        echo '</div>';
3129da6395dSAndreas Gohr    }
3139da6395dSAndreas Gohr
314e7a2f1e0SAndreas Gohr    function html_newreferer(){
315e7a2f1e0SAndreas Gohr        echo '<div class="plg_stats_full">';
316e7a2f1e0SAndreas Gohr        echo '<h2>New Incoming Links</h2>';
317e7a2f1e0SAndreas Gohr        echo '<p>The following incoming links where first logged in the selected time frame,
318e7a2f1e0SAndreas Gohr              and have never been seen before.</p>';
319e7a2f1e0SAndreas Gohr
320e7a2f1e0SAndreas Gohr        $result = $this->sql_newreferer($this->tlimit,$this->start,150);
321*2507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
322e7a2f1e0SAndreas Gohr        echo '</div>';
323e7a2f1e0SAndreas Gohr    }
324e7a2f1e0SAndreas Gohr
3259da6395dSAndreas Gohr
3269da6395dSAndreas Gohr
32714d99ec0SAndreas Gohr    /**
32814d99ec0SAndreas Gohr     * Display a result in a HTML table
32914d99ec0SAndreas Gohr     */
330*2507f8e0SAndreas Gohr    function html_resulttable($result,$header='',$pager=0){
33114d99ec0SAndreas Gohr        echo '<table>';
3322812a751SAndreas Gohr        if(is_array($header)){
33314d99ec0SAndreas Gohr            echo '<tr>';
33414d99ec0SAndreas Gohr            foreach($header as $h){
33514d99ec0SAndreas Gohr                echo '<th>'.hsc($h).'</th>';
33614d99ec0SAndreas Gohr            }
33714d99ec0SAndreas Gohr            echo '</tr>';
3382812a751SAndreas Gohr        }
33914d99ec0SAndreas Gohr
340*2507f8e0SAndreas Gohr        $count = 0;
34114d99ec0SAndreas Gohr        foreach($result as $row){
34214d99ec0SAndreas Gohr            echo '<tr>';
34314d99ec0SAndreas Gohr            foreach($row as $k => $v){
3442812a751SAndreas Gohr                echo '<td class="plg_stats_X'.$k.'">';
34514d99ec0SAndreas Gohr                if($k == 'page'){
34614d99ec0SAndreas Gohr                    echo '<a href="'.wl($v).'" class="wikilink1">';
34714d99ec0SAndreas Gohr                    echo hsc($v);
34814d99ec0SAndreas Gohr                    echo '</a>';
34914d99ec0SAndreas Gohr                }elseif($k == 'url'){
35054f6c432SAndreas Gohr                    $url = hsc($v);
3512812a751SAndreas Gohr                    if(strlen($url) > 45){
3522812a751SAndreas Gohr                        $url = substr($url,0,30).' &hellip; '.substr($url,-15);
35354f6c432SAndreas Gohr                    }
35414d99ec0SAndreas Gohr                    echo '<a href="'.$v.'" class="urlextern">';
35554f6c432SAndreas Gohr                    echo $url;
35614d99ec0SAndreas Gohr                    echo '</a>';
35775fa767dSAndreas Gohr                }elseif($k == 'browser'){
35875fa767dSAndreas Gohr                    include_once(dirname(__FILE__).'/inc/browsers.php');
35975fa767dSAndreas Gohr                    echo $BrowsersHashIDLib[$v];
36075fa767dSAndreas Gohr                }elseif($k == 'bflag'){
36175fa767dSAndreas Gohr                    include_once(dirname(__FILE__).'/inc/browsers.php');
36275fa767dSAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.$BrowsersHashIcon[$v].'.png" alt="'.hsc($v).'" />';
363bd4217d3SAndreas Gohr                }elseif($k == 'os'){
364bd4217d3SAndreas Gohr                    if(empty($v)){
365bd4217d3SAndreas Gohr                        echo 'unknown';
366bd4217d3SAndreas Gohr                    }else{
367bd4217d3SAndreas Gohr                        include_once(dirname(__FILE__).'/inc/operating_systems.php');
368bd4217d3SAndreas Gohr                        echo $OSHashLib[$v];
369bd4217d3SAndreas Gohr                    }
370bd4217d3SAndreas Gohr                }elseif($k == 'osflag'){
371bd4217d3SAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.hsc($v).'.png" alt="'.hsc($v).'" />';
37275fa767dSAndreas Gohr                }elseif($k == 'cflag'){
37375fa767dSAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />';
37414d99ec0SAndreas Gohr                }elseif($k == 'html'){
37514d99ec0SAndreas Gohr                    echo $v;
37614d99ec0SAndreas Gohr                }else{
37714d99ec0SAndreas Gohr                    echo hsc($v);
37814d99ec0SAndreas Gohr                }
37914d99ec0SAndreas Gohr                echo '</td>';
38014d99ec0SAndreas Gohr            }
38114d99ec0SAndreas Gohr            echo '</tr>';
382*2507f8e0SAndreas Gohr
383*2507f8e0SAndreas Gohr            if($pager && ($count == $pager)) break;
384*2507f8e0SAndreas Gohr            $count++;
38514d99ec0SAndreas Gohr        }
38614d99ec0SAndreas Gohr        echo '</table>';
387*2507f8e0SAndreas Gohr
388*2507f8e0SAndreas Gohr        if($pager) $this->html_pager($pager,count($result) > $pager);
3891878f16fSAndreas Gohr    }
3901878f16fSAndreas Gohr
39195eb68e6SAndreas Gohr    /**
39295eb68e6SAndreas Gohr     * Create an image
39395eb68e6SAndreas Gohr     */
39495eb68e6SAndreas Gohr    function img_build($img){
39595eb68e6SAndreas Gohr        include(dirname(__FILE__).'/inc/AGC.class.php');
39695eb68e6SAndreas Gohr
39795eb68e6SAndreas Gohr        switch($img){
39895eb68e6SAndreas Gohr            case 'country':
39995eb68e6SAndreas Gohr                // build top countries + other
40095eb68e6SAndreas Gohr                $result = $this->sql_countries($this->tlimit,$this->start,0);
40195eb68e6SAndreas Gohr                $data = array();
40295eb68e6SAndreas Gohr                $top = 0;
40395eb68e6SAndreas Gohr                foreach($result as $row){
40495eb68e6SAndreas Gohr                    if($top < 7){
40595eb68e6SAndreas Gohr                        $data[$row['country']] = $row['cnt'];
40695eb68e6SAndreas Gohr                    }else{
40795eb68e6SAndreas Gohr                        $data['other'] += $row['cnt'];
40895eb68e6SAndreas Gohr                    }
40995eb68e6SAndreas Gohr                    $top++;
41095eb68e6SAndreas Gohr                }
41195eb68e6SAndreas Gohr                $pie = new AGC(300, 200);
41295eb68e6SAndreas Gohr                $pie->setProp("showkey",true);
41395eb68e6SAndreas Gohr                $pie->setProp("showval",false);
41495eb68e6SAndreas Gohr                $pie->setProp("showgrid",false);
41595eb68e6SAndreas Gohr                $pie->setProp("type","pie");
41695eb68e6SAndreas Gohr                $pie->setProp("keyinfo",1);
41795eb68e6SAndreas Gohr                $pie->setProp("keysize",8);
41895eb68e6SAndreas Gohr                $pie->setProp("keywidspc",-50);
41995eb68e6SAndreas Gohr                $pie->setProp("key",array_keys($data));
42095eb68e6SAndreas Gohr                $pie->addBulkPoints(array_values($data));
42195eb68e6SAndreas Gohr                @$pie->graph();
42295eb68e6SAndreas Gohr                $pie->showGraph();
42395eb68e6SAndreas Gohr                break;
42475fa767dSAndreas Gohr            case 'browser':
42575fa767dSAndreas Gohr                // build top browsers + other
42675fa767dSAndreas Gohr                include_once(dirname(__FILE__).'/inc/browsers.php');
42775fa767dSAndreas Gohr
42875fa767dSAndreas Gohr                $result = $this->sql_browsers($this->tlimit,$this->start,0,false);
42975fa767dSAndreas Gohr                $data = array();
43075fa767dSAndreas Gohr                $top = 0;
43175fa767dSAndreas Gohr                foreach($result as $row){
43275fa767dSAndreas Gohr                    if($top < 5){
43375fa767dSAndreas Gohr                        $data[strip_tags($BrowsersHashIDLib[$row['ua_info']])] = $row['cnt'];
43475fa767dSAndreas Gohr                    }else{
43575fa767dSAndreas Gohr                        $data['other'] += $row['cnt'];
43675fa767dSAndreas Gohr                    }
43775fa767dSAndreas Gohr                    $top++;
43875fa767dSAndreas Gohr                }
43975fa767dSAndreas Gohr                $pie = new AGC(300, 200);
44075fa767dSAndreas Gohr                $pie->setProp("showkey",true);
44175fa767dSAndreas Gohr                $pie->setProp("showval",false);
44275fa767dSAndreas Gohr                $pie->setProp("showgrid",false);
44375fa767dSAndreas Gohr                $pie->setProp("type","pie");
44475fa767dSAndreas Gohr                $pie->setProp("keyinfo",1);
44575fa767dSAndreas Gohr                $pie->setProp("keysize",8);
44675fa767dSAndreas Gohr                $pie->setProp("keywidspc",-50);
44775fa767dSAndreas Gohr                $pie->setProp("key",array_keys($data));
44875fa767dSAndreas Gohr                $pie->addBulkPoints(array_values($data));
44975fa767dSAndreas Gohr                @$pie->graph();
45075fa767dSAndreas Gohr                $pie->showGraph();
45175fa767dSAndreas Gohr                break;
4522812a751SAndreas Gohr            case 'trend':
4532812a751SAndreas Gohr                $hours  = ($this->from == $this->to);
4542812a751SAndreas Gohr                $result = $this->sql_trend($this->tlimit,$hours);
4552812a751SAndreas Gohr                $data1   = array();
4562812a751SAndreas Gohr                $data2   = array();
4572812a751SAndreas Gohr
4582812a751SAndreas Gohr                $graph = new AGC(400, 150);
4592812a751SAndreas Gohr                $graph->setProp("type","bar");
4602812a751SAndreas Gohr                $graph->setProp("showgrid",false);
4612812a751SAndreas Gohr                $graph->setProp("barwidth",.8);
46275fa767dSAndreas Gohr
4632812a751SAndreas Gohr                $graph->setColor('color',0,'blue');
4642812a751SAndreas Gohr                $graph->setColor('color',1,'red');
4652812a751SAndreas Gohr
4662812a751SAndreas Gohr                if($hours){
4672812a751SAndreas Gohr                    //preset $hours
4682812a751SAndreas Gohr                    for($i=0;$i<24;$i++){
4692812a751SAndreas Gohr                        $data1[$i] = 0;
4702812a751SAndreas Gohr                        $data2[$i] = 0;
4712812a751SAndreas Gohr                        $graph->setProp("scale",array(' 0h','   4h','   8h','    12h','    16h','    20h','    24h'));
4722812a751SAndreas Gohr                    }
4732812a751SAndreas Gohr                }else{
4742812a751SAndreas Gohr                    $graph->setProp("scale",array(next(array_keys($data1)),$this->to));
4752812a751SAndreas Gohr                }
4762812a751SAndreas Gohr
4772812a751SAndreas Gohr                foreach($result as $row){
4782812a751SAndreas Gohr                    $data1[$row['time']] = $row['pageviews'];
4792812a751SAndreas Gohr                    $data2[$row['time']] = $row['sessions'];
4802812a751SAndreas Gohr                }
4812812a751SAndreas Gohr
4822812a751SAndreas Gohr                foreach($data1 as $key => $val){
4832812a751SAndreas Gohr                    $graph->addPoint($val,$key,0);
4842812a751SAndreas Gohr                }
4852812a751SAndreas Gohr                foreach($data2 as $key => $val){
4862812a751SAndreas Gohr                    $graph->addPoint($val,$key,1);
4872812a751SAndreas Gohr                }
4882812a751SAndreas Gohr
4892812a751SAndreas Gohr                @$graph->graph();
4902812a751SAndreas Gohr                $graph->showGraph();
4912812a751SAndreas Gohr
49295eb68e6SAndreas Gohr            default:
49395eb68e6SAndreas Gohr                $this->sendGIF();
49495eb68e6SAndreas Gohr        }
49595eb68e6SAndreas Gohr    }
49695eb68e6SAndreas Gohr
49795eb68e6SAndreas Gohr
4982812a751SAndreas Gohr    /**
4992812a751SAndreas Gohr     * Return some aggregated statistics
5002812a751SAndreas Gohr     */
5012812a751SAndreas Gohr    function sql_aggregate($tlimit){
5022812a751SAndreas Gohr        $data = array();
5032812a751SAndreas Gohr
5042812a751SAndreas Gohr        $sql = "SELECT ref_type, COUNT(*) as cnt
5052812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
5062812a751SAndreas Gohr                 WHERE $tlimit
5072812a751SAndreas Gohr                   AND ua_type = 'browser'
5082812a751SAndreas Gohr              GROUP BY ref_type";
5092812a751SAndreas Gohr        $result = $this->runSQL($sql);
5102812a751SAndreas Gohr
5112812a751SAndreas Gohr        foreach($result as $row){
5122812a751SAndreas Gohr            if($row['ref_type'] == 'search')   $data['search']   = $row['cnt'];
5132812a751SAndreas Gohr            if($row['ref_type'] == 'external') $data['external'] = $row['cnt'];
5142812a751SAndreas Gohr            if($row['ref_type'] == 'internal') $data['internal'] = $row['cnt'];
5152812a751SAndreas Gohr            if($row['ref_type'] == '')         $data['direct']   = $row['cnt'];
5162812a751SAndreas Gohr        }
5172812a751SAndreas Gohr
5182812a751SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as sessions,
5192812a751SAndreas Gohr                       COUNT(session) as views,
5202812a751SAndreas Gohr                       COUNT(DISTINCT user) as users
5212812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
5222812a751SAndreas Gohr                 WHERE $tlimit
5232812a751SAndreas Gohr                   AND ua_type = 'browser'";
5242812a751SAndreas Gohr        $result = $this->runSQL($sql);
5252812a751SAndreas Gohr
52675fa767dSAndreas Gohr        $data['users']     = max($result[0]['users'] - 1,0); // subtract empty user
5272812a751SAndreas Gohr        $data['sessions']  = $result[0]['sessions'];
5282812a751SAndreas Gohr        $data['pageviews'] = $result[0]['views'];
5292812a751SAndreas Gohr
5302812a751SAndreas Gohr        $sql = "SELECT COUNT(id) as robots
5312812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
5322812a751SAndreas Gohr                 WHERE $tlimit
5332812a751SAndreas Gohr                   AND ua_type = 'robot'";
5342812a751SAndreas Gohr        $result = $this->runSQL($sql);
5352812a751SAndreas Gohr        $data['robots'] = $result[0]['robots'];
5362812a751SAndreas Gohr
5372812a751SAndreas Gohr        return $data;
5382812a751SAndreas Gohr    }
5392812a751SAndreas Gohr
540bd4217d3SAndreas Gohr    /**
541bd4217d3SAndreas Gohr     * standard statistics follow, only accesses made by browsers are counted
542bd4217d3SAndreas Gohr     * for general stats like browser or OS only visitors not pageviews are counted
543bd4217d3SAndreas Gohr     */
5442812a751SAndreas Gohr    function sql_trend($tlimit,$hours=false){
5452812a751SAndreas Gohr        if($hours){
5462812a751SAndreas Gohr            $sql = "SELECT HOUR(dt) as time,
5472812a751SAndreas Gohr                           COUNT(DISTINCT session) as sessions,
5482812a751SAndreas Gohr                           COUNT(session) as pageviews
5492812a751SAndreas Gohr                      FROM ".$this->getConf('db_prefix')."access as A
5502812a751SAndreas Gohr                     WHERE $tlimit
5512812a751SAndreas Gohr                       AND ua_type = 'browser'
5522812a751SAndreas Gohr                  GROUP BY HOUR(dt)
5532812a751SAndreas Gohr                  ORDER BY time";
5542812a751SAndreas Gohr        }else{
5552812a751SAndreas Gohr            $sql = "SELECT DATE(dt) as time,
5562812a751SAndreas Gohr                           COUNT(DISTINCT session) as sessions,
5572812a751SAndreas Gohr                           COUNT(session) as pageviews
5582812a751SAndreas Gohr                      FROM ".$this->getConf('db_prefix')."access as A
5592812a751SAndreas Gohr                     WHERE $tlimit
5602812a751SAndreas Gohr                       AND ua_type = 'browser'
5612812a751SAndreas Gohr                  GROUP BY DATE(dt)
5622812a751SAndreas Gohr                  ORDER BY time";
5632812a751SAndreas Gohr        }
5642812a751SAndreas Gohr        return $this->runSQL($sql);
5652812a751SAndreas Gohr    }
5662812a751SAndreas Gohr
56795eb68e6SAndreas Gohr    function sql_pages($tlimit,$start=0,$limit=20){
5682812a751SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, page
56995eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
57095eb68e6SAndreas Gohr                 WHERE $tlimit
57195eb68e6SAndreas Gohr                   AND ua_type = 'browser'
57295eb68e6SAndreas Gohr              GROUP BY page
57395eb68e6SAndreas Gohr              ORDER BY cnt DESC, page".
57495eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
57595eb68e6SAndreas Gohr        return $this->runSQL($sql);
57695eb68e6SAndreas Gohr    }
57795eb68e6SAndreas Gohr
57895eb68e6SAndreas Gohr    function sql_referer($tlimit,$start=0,$limit=20){
5792812a751SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, ref as url
58095eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
58195eb68e6SAndreas Gohr                 WHERE $tlimit
58295eb68e6SAndreas Gohr                   AND ua_type = 'browser'
58395eb68e6SAndreas Gohr                   AND ref_type = 'external'
58495eb68e6SAndreas Gohr              GROUP BY ref_md5
58595eb68e6SAndreas Gohr              ORDER BY cnt DESC, url".
58695eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
58795eb68e6SAndreas Gohr        return $this->runSQL($sql);
58895eb68e6SAndreas Gohr    }
58995eb68e6SAndreas Gohr
590e7a2f1e0SAndreas Gohr    function sql_newreferer($tlimit,$start=0,$limit=20){
591e7a2f1e0SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, ref as url
592e7a2f1e0SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
593e7a2f1e0SAndreas Gohr                 WHERE ua_type = 'browser'
594e7a2f1e0SAndreas Gohr                   AND ref_type = 'external'
595e7a2f1e0SAndreas Gohr              GROUP BY ref_md5
596e7a2f1e0SAndreas Gohr                HAVING DATE(MIN(dt)) >= DATE('".$this->from."')
597e7a2f1e0SAndreas Gohr                   AND DATE(MIN(dt)) <= DATE('".$this->to."')
598e7a2f1e0SAndreas Gohr              ORDER BY cnt DESC, url".
599e7a2f1e0SAndreas Gohr              $this->sql_limit($start,$limit);
600e7a2f1e0SAndreas Gohr        return $this->runSQL($sql);
601e7a2f1e0SAndreas Gohr    }
602e7a2f1e0SAndreas Gohr
60395eb68e6SAndreas Gohr    function sql_countries($tlimit,$start=0,$limit=20){
604bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country
60595eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A,
60695eb68e6SAndreas Gohr                       ".$this->getConf('db_prefix')."iplocation as B
60795eb68e6SAndreas Gohr                 WHERE $tlimit
60895eb68e6SAndreas Gohr                   AND A.ip = B.ip
60995eb68e6SAndreas Gohr              GROUP BY B.country
61095eb68e6SAndreas Gohr              ORDER BY cnt DESC, B.country".
61195eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
61295eb68e6SAndreas Gohr        return $this->runSQL($sql);
61395eb68e6SAndreas Gohr    }
61495eb68e6SAndreas Gohr
61575fa767dSAndreas Gohr    function sql_browsers($tlimit,$start=0,$limit=20,$ext=true){
61675fa767dSAndreas Gohr        if($ext){
61775fa767dSAndreas Gohr            $sel = 'ua_info as bflag, ua_info as browser, ua_ver';
61875fa767dSAndreas Gohr            $grp = 'ua_info, ua_ver';
61975fa767dSAndreas Gohr        }else{
62075fa767dSAndreas Gohr            $grp = 'ua_info';
62175fa767dSAndreas Gohr            $sel = 'ua_info';
62275fa767dSAndreas Gohr        }
62375fa767dSAndreas Gohr
624bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel
62575fa767dSAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
62675fa767dSAndreas Gohr                 WHERE $tlimit
62775fa767dSAndreas Gohr                   AND ua_type = 'browser'
62875fa767dSAndreas Gohr              GROUP BY $grp
62975fa767dSAndreas Gohr              ORDER BY cnt DESC, ua_info".
63075fa767dSAndreas Gohr              $this->sql_limit($start,$limit);
63175fa767dSAndreas Gohr        return $this->runSQL($sql);
63275fa767dSAndreas Gohr    }
63375fa767dSAndreas Gohr
634bd4217d3SAndreas Gohr    function sql_os($tlimit,$start=0,$limit=20){
635bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os
636bd4217d3SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
637bd4217d3SAndreas Gohr                 WHERE $tlimit
638bd4217d3SAndreas Gohr                   AND ua_type = 'browser'
639bd4217d3SAndreas Gohr              GROUP BY os
640bd4217d3SAndreas Gohr              ORDER BY cnt DESC, os".
641bd4217d3SAndreas Gohr              $this->sql_limit($start,$limit);
642bd4217d3SAndreas Gohr        return $this->runSQL($sql);
643bd4217d3SAndreas Gohr    }
644bd4217d3SAndreas Gohr
64575fa767dSAndreas Gohr
64695eb68e6SAndreas Gohr    /**
64795eb68e6SAndreas Gohr     * Builds a limit clause
64895eb68e6SAndreas Gohr     */
64995eb68e6SAndreas Gohr    function sql_limit($start,$limit){
65095eb68e6SAndreas Gohr        $start = (int) $start;
65195eb68e6SAndreas Gohr        $limit = (int) $limit;
65295eb68e6SAndreas Gohr        if($limit){
653*2507f8e0SAndreas Gohr            $limit += 1;
65495eb68e6SAndreas Gohr            return " LIMIT $start,$limit";
65595eb68e6SAndreas Gohr        }elseif($start){
65695eb68e6SAndreas Gohr            return " OFFSET $start";
65795eb68e6SAndreas Gohr        }
65895eb68e6SAndreas Gohr        return '';
65995eb68e6SAndreas Gohr    }
6601878f16fSAndreas Gohr
6611878f16fSAndreas Gohr    /**
66214d99ec0SAndreas Gohr     * Return a link to the DB, opening the connection if needed
6631878f16fSAndreas Gohr     */
66414d99ec0SAndreas Gohr    function dbLink(){
6651878f16fSAndreas Gohr        // connect to DB if needed
6661878f16fSAndreas Gohr        if(!$this->dblink){
6671878f16fSAndreas Gohr            $this->dblink = mysql_connect($this->getConf('db_server'),
6681878f16fSAndreas Gohr                                          $this->getConf('db_user'),
6691878f16fSAndreas Gohr                                          $this->getConf('db_password'));
6701878f16fSAndreas Gohr            if(!$this->dblink){
6711878f16fSAndreas Gohr                msg('DB Error: connection failed',-1);
6721878f16fSAndreas Gohr                return null;
6731878f16fSAndreas Gohr            }
6741878f16fSAndreas Gohr            // set utf-8
6751878f16fSAndreas Gohr            if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){
6761878f16fSAndreas Gohr                msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1);
6771878f16fSAndreas Gohr                return null;
6781878f16fSAndreas Gohr            }
6791878f16fSAndreas Gohr        }
68014d99ec0SAndreas Gohr        return $this->dblink;
68114d99ec0SAndreas Gohr    }
6821878f16fSAndreas Gohr
68314d99ec0SAndreas Gohr    /**
68414d99ec0SAndreas Gohr     * Simple function to run a DB query
68514d99ec0SAndreas Gohr     */
68614d99ec0SAndreas Gohr    function runSQL($sql_string) {
68714d99ec0SAndreas Gohr        $link = $this->dbLink();
68814d99ec0SAndreas Gohr
68914d99ec0SAndreas Gohr        $result = mysql_db_query($this->conf['db_database'],$sql_string,$link);
69094171ff3SAndreas Gohr        if(!$result){
6912812a751SAndreas Gohr            msg('DB Error: '.mysql_error($link).' '.hsc($sql_string),-1);
6921878f16fSAndreas Gohr            return null;
6931878f16fSAndreas Gohr        }
6941878f16fSAndreas Gohr
6951878f16fSAndreas Gohr        $resultarray = array();
6961878f16fSAndreas Gohr
6971878f16fSAndreas Gohr        //mysql_db_query returns 1 on a insert statement -> no need to ask for results
6981878f16fSAndreas Gohr        if ($result != 1) {
6991878f16fSAndreas Gohr            for($i=0; $i< mysql_num_rows($result); $i++) {
7001878f16fSAndreas Gohr                $temparray = mysql_fetch_assoc($result);
7011878f16fSAndreas Gohr                $resultarray[]=$temparray;
7021878f16fSAndreas Gohr            }
7031878f16fSAndreas Gohr            mysql_free_result($result);
7041878f16fSAndreas Gohr        }
7051878f16fSAndreas Gohr
70614d99ec0SAndreas Gohr        if (mysql_insert_id($link)) {
70714d99ec0SAndreas Gohr            $resultarray = mysql_insert_id($link); //give back ID on insert
7081878f16fSAndreas Gohr        }
7091878f16fSAndreas Gohr
7101878f16fSAndreas Gohr        return $resultarray;
7111878f16fSAndreas Gohr    }
7121878f16fSAndreas Gohr
7131878f16fSAndreas Gohr    /**
71414d99ec0SAndreas Gohr     * Returns a short name for a User Agent and sets type, version and os info
7151878f16fSAndreas Gohr     */
71614d99ec0SAndreas Gohr    function ua_info($ua,&$type,&$ver,&$os){
71714d99ec0SAndreas Gohr        $ua = strtr($ua,' +','__');
71814d99ec0SAndreas Gohr        $ua = strtolower($ua);
71914d99ec0SAndreas Gohr
72014d99ec0SAndreas Gohr        // common browsers
72114d99ec0SAndreas Gohr        $regvermsie     = '/msie([+_ ]|)([\d\.]*)/i';
72214d99ec0SAndreas Gohr        $regvernetscape = '/netscape.?\/([\d\.]*)/i';
72314d99ec0SAndreas Gohr        $regverfirefox  = '/firefox\/([\d\.]*)/i';
72414d99ec0SAndreas Gohr        $regversvn      = '/svn\/([\d\.]*)/i';
72514d99ec0SAndreas Gohr        $regvermozilla  = '/mozilla(\/|)([\d\.]*)/i';
72614d99ec0SAndreas Gohr        $regnotie       = '/webtv|omniweb|opera/i';
72714d99ec0SAndreas Gohr        $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i';
72814d99ec0SAndreas Gohr
72914d99ec0SAndreas Gohr        $name = '';
73014d99ec0SAndreas Gohr        # IE ?
73114d99ec0SAndreas Gohr        if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){
73214d99ec0SAndreas Gohr            $type = 'browser';
73314d99ec0SAndreas Gohr            $ver  = $m[2];
73414d99ec0SAndreas Gohr            $name = 'msie';
73514d99ec0SAndreas Gohr        }
73614d99ec0SAndreas Gohr        # Firefox ?
73714d99ec0SAndreas Gohr        elseif (preg_match($regverfirefox,$ua,$m)){
73814d99ec0SAndreas Gohr            $type = 'browser';
73914d99ec0SAndreas Gohr            $ver  = $m[1];
74014d99ec0SAndreas Gohr            $name = 'firefox';
74114d99ec0SAndreas Gohr        }
74214d99ec0SAndreas Gohr        # Subversion ?
74314d99ec0SAndreas Gohr        elseif (preg_match($regversvn,$ua,$m)){
74414d99ec0SAndreas Gohr            $type = 'rcs';
74514d99ec0SAndreas Gohr            $ver  = $m[1];
74614d99ec0SAndreas Gohr            $name = 'svn';
74714d99ec0SAndreas Gohr        }
74814d99ec0SAndreas Gohr        # Netscape 6.x, 7.x ... ?
74914d99ec0SAndreas Gohr        elseif (preg_match($regvernetscape,$ua,$m)){
75014d99ec0SAndreas Gohr            $type = 'browser';
75114d99ec0SAndreas Gohr            $ver  = $m[1];
75214d99ec0SAndreas Gohr            $name = 'netscape';
75314d99ec0SAndreas Gohr        }
75414d99ec0SAndreas Gohr        # Netscape 3.x, 4.x ... ?
75514d99ec0SAndreas Gohr        elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){
75614d99ec0SAndreas Gohr            $type = 'browser';
75714d99ec0SAndreas Gohr            $ver  = $m[2];
75814d99ec0SAndreas Gohr            $name = 'netscape';
75914d99ec0SAndreas Gohr        }else{
76014d99ec0SAndreas Gohr            include(dirname(__FILE__).'/inc/browsers.php');
76114d99ec0SAndreas Gohr            foreach($BrowsersSearchIDOrder as $regex){
76214d99ec0SAndreas Gohr                if(preg_match('/'.$regex.'/',$ua)){
76314d99ec0SAndreas Gohr                    // it's a browser!
76414d99ec0SAndreas Gohr                    $type = 'browser';
76514d99ec0SAndreas Gohr                    $name = strtolower($regex);
76614d99ec0SAndreas Gohr                    break;
76714d99ec0SAndreas Gohr                }
76814d99ec0SAndreas Gohr            }
76914d99ec0SAndreas Gohr        }
77014d99ec0SAndreas Gohr
77175fa767dSAndreas Gohr        // check versions for Safari and Opera
77275fa767dSAndreas Gohr        if($name == 'safari'){
77375fa767dSAndreas Gohr            if(preg_match('/safari\/([\d\.]*)/i',$ua,$match)){
77475fa767dSAndreas Gohr                $ver = $BrowsersSafariBuildToVersionHash[$match[1]];
77575fa767dSAndreas Gohr            }
77675fa767dSAndreas Gohr        }elseif($name == 'opera'){
77775fa767dSAndreas Gohr            if(preg_match('/opera[\/ ]([\d\.]*)/i',$ua,$match)){
77875fa767dSAndreas Gohr                $ver = $match[1];
77975fa767dSAndreas Gohr            }
78075fa767dSAndreas Gohr        }
78175fa767dSAndreas Gohr
78275fa767dSAndreas Gohr
78314d99ec0SAndreas Gohr        // check OS for browsers
78414d99ec0SAndreas Gohr        if($type == 'browser'){
78514d99ec0SAndreas Gohr            include(dirname(__FILE__).'/inc/operating_systems.php');
78614d99ec0SAndreas Gohr            foreach($OSSearchIDOrder as $regex){
78714d99ec0SAndreas Gohr                if(preg_match('/'.$regex.'/',$ua)){
78814d99ec0SAndreas Gohr                    $os = $OSHashID[$regex];
78914d99ec0SAndreas Gohr                    break;
79014d99ec0SAndreas Gohr                }
79114d99ec0SAndreas Gohr            }
79214d99ec0SAndreas Gohr
79314d99ec0SAndreas Gohr        }
79414d99ec0SAndreas Gohr
79514d99ec0SAndreas Gohr        // are we done now?
79614d99ec0SAndreas Gohr        if($name) return $name;
79714d99ec0SAndreas Gohr
79814d99ec0SAndreas Gohr        include(dirname(__FILE__).'/inc/robots.php');
79914d99ec0SAndreas Gohr        foreach($RobotsSearchIDOrder as $regex){
80014d99ec0SAndreas Gohr            if(preg_match('/'.$regex.'/',$ua)){
80114d99ec0SAndreas Gohr                    // it's a robot!
80214d99ec0SAndreas Gohr                    $type = 'robot';
80314d99ec0SAndreas Gohr                    return strtolower($regex);
80414d99ec0SAndreas Gohr            }
80514d99ec0SAndreas Gohr        }
80614d99ec0SAndreas Gohr
80714d99ec0SAndreas Gohr        // dunno
8081878f16fSAndreas Gohr        return '';
8091878f16fSAndreas Gohr    }
8101878f16fSAndreas Gohr
8111878f16fSAndreas Gohr    /**
81214d99ec0SAndreas Gohr     *
81314d99ec0SAndreas Gohr     * @fixme: put search engine queries in seperate table here
81414d99ec0SAndreas Gohr     */
81514d99ec0SAndreas Gohr    function log_search($referer,&$type){
81614d99ec0SAndreas Gohr        $referer = strtr($referer,' +','__');
81714d99ec0SAndreas Gohr        $referer = strtolower($referer);
81814d99ec0SAndreas Gohr
81914d99ec0SAndreas Gohr        include(dirname(__FILE__).'/inc/search_engines.php');
82014d99ec0SAndreas Gohr
82114d99ec0SAndreas Gohr        foreach($SearchEnginesSearchIDOrder as $regex){
82214d99ec0SAndreas Gohr            if(preg_match('/'.$regex.'/',$referer)){
82314d99ec0SAndreas Gohr                if(!$NotSearchEnginesKeys[$regex] ||
82414d99ec0SAndreas Gohr                   !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$referer)){
82514d99ec0SAndreas Gohr                    // it's a search engine!
82614d99ec0SAndreas Gohr                    $type = 'search';
82714d99ec0SAndreas Gohr                    break;
82814d99ec0SAndreas Gohr                }
82914d99ec0SAndreas Gohr            }
83014d99ec0SAndreas Gohr        }
83114d99ec0SAndreas Gohr        if($type != 'search') return; // we're done here
83214d99ec0SAndreas Gohr
83314d99ec0SAndreas Gohr        #fixme now do the keyword magic!
83414d99ec0SAndreas Gohr    }
83514d99ec0SAndreas Gohr
83614d99ec0SAndreas Gohr    /**
83714d99ec0SAndreas Gohr     * Resolve IP to country/city
83814d99ec0SAndreas Gohr     */
83914d99ec0SAndreas Gohr    function log_ip($ip){
84014d99ec0SAndreas Gohr        // check if IP already known and up-to-date
84114d99ec0SAndreas Gohr        $sql = "SELECT ip
84214d99ec0SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."iplocation
84314d99ec0SAndreas Gohr                 WHERE ip ='".addslashes($ip)."'
84414d99ec0SAndreas Gohr                   AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)";
84514d99ec0SAndreas Gohr        $result = $this->runSQL($sql);
84614d99ec0SAndreas Gohr        if($result[0]['ip']) return;
84714d99ec0SAndreas Gohr
84814d99ec0SAndreas Gohr        $http = new DokuHTTPClient();
84914d99ec0SAndreas Gohr        $http->timeout = 10;
85014d99ec0SAndreas Gohr        $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip);
85114d99ec0SAndreas Gohr
85214d99ec0SAndreas Gohr        if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){
85314d99ec0SAndreas Gohr            $country = addslashes(trim($match[1]));
85414d99ec0SAndreas Gohr            $code    = addslashes(strtolower(trim($match[2])));
85514d99ec0SAndreas Gohr            $city    = addslashes(trim($match[3]));
85614d99ec0SAndreas Gohr            $host    = addslashes(gethostbyaddr($ip));
85714d99ec0SAndreas Gohr            $ip      = addslashes($ip);
85814d99ec0SAndreas Gohr
85914d99ec0SAndreas Gohr            $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation
86014d99ec0SAndreas Gohr                        SET ip = '$ip',
86114d99ec0SAndreas Gohr                            country = '$country',
86214d99ec0SAndreas Gohr                            code    = '$code',
86314d99ec0SAndreas Gohr                            city    = '$city',
86414d99ec0SAndreas Gohr                            host    = '$host'";
86514d99ec0SAndreas Gohr            $this->runSQL($sql);
86614d99ec0SAndreas Gohr        }
86714d99ec0SAndreas Gohr    }
86814d99ec0SAndreas Gohr
86914d99ec0SAndreas Gohr    /**
8701878f16fSAndreas Gohr     * log a page access
8711878f16fSAndreas Gohr     *
8721878f16fSAndreas Gohr     * called from log.php
8731878f16fSAndreas Gohr     */
8741878f16fSAndreas Gohr    function log_access(){
87594171ff3SAndreas Gohr        if(!$_REQUEST['p']) return;
87694171ff3SAndreas Gohr
87714d99ec0SAndreas Gohr        # FIXME check referer against blacklist and drop logging for bad boys
87814d99ec0SAndreas Gohr
87914d99ec0SAndreas Gohr        // handle referer
88014d99ec0SAndreas Gohr        $referer = trim($_REQUEST['r']);
88114d99ec0SAndreas Gohr        if($referer){
88214d99ec0SAndreas Gohr            $ref     = addslashes($referer);
88314d99ec0SAndreas Gohr            $ref_md5 = ($ref) ? md5($referer) : '';
88414d99ec0SAndreas Gohr            if(strpos($referer,DOKU_URL) === 0){
88514d99ec0SAndreas Gohr                $ref_type = 'internal';
88614d99ec0SAndreas Gohr            }else{
88714d99ec0SAndreas Gohr                $ref_type = 'external';
88814d99ec0SAndreas Gohr                $this->log_search($referer,$ref_type);
88914d99ec0SAndreas Gohr            }
89014d99ec0SAndreas Gohr        }else{
89114d99ec0SAndreas Gohr            $ref      = '';
89214d99ec0SAndreas Gohr            $ref_md5  = '';
89314d99ec0SAndreas Gohr            $ref_type = '';
89414d99ec0SAndreas Gohr        }
89514d99ec0SAndreas Gohr
89614d99ec0SAndreas Gohr        // handle user agent
89714d99ec0SAndreas Gohr        $agent   = trim($_SERVER['HTTP_USER_AGENT']);
89814d99ec0SAndreas Gohr
89914d99ec0SAndreas Gohr        $ua      = addslashes($agent);
90014d99ec0SAndreas Gohr        $ua_type = '';
90114d99ec0SAndreas Gohr        $ua_ver  = '';
90214d99ec0SAndreas Gohr        $os      = '';
90314d99ec0SAndreas Gohr        $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os));
90414d99ec0SAndreas Gohr
9051878f16fSAndreas Gohr        $page    = addslashes($_REQUEST['p']);
9061878f16fSAndreas Gohr        $ip      = addslashes($_SERVER['REMOTE_ADDR']);
9071878f16fSAndreas Gohr        $sx      = (int) $_REQUEST['sx'];
9081878f16fSAndreas Gohr        $sy      = (int) $_REQUEST['sy'];
9091878f16fSAndreas Gohr        $vx      = (int) $_REQUEST['vx'];
9101878f16fSAndreas Gohr        $vy      = (int) $_REQUEST['vy'];
91175fa767dSAndreas Gohr        $js      = (int) $_REQUEST['js'];
9121878f16fSAndreas Gohr        $user    = addslashes($_SERVER['REMOTE_USER']);
9131878f16fSAndreas Gohr        $session = addslashes(session_id());
9141878f16fSAndreas Gohr
91594171ff3SAndreas Gohr        $sql  = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access
91675fa767dSAndreas Gohr                    SET dt       = NOW(),
91775fa767dSAndreas Gohr                        page     = '$page',
9181878f16fSAndreas Gohr                        ip       = '$ip',
9191878f16fSAndreas Gohr                        ua       = '$ua',
9201878f16fSAndreas Gohr                        ua_info  = '$ua_info',
92114d99ec0SAndreas Gohr                        ua_type  = '$ua_type',
92214d99ec0SAndreas Gohr                        ua_ver   = '$ua_ver',
92314d99ec0SAndreas Gohr                        os       = '$os',
9241878f16fSAndreas Gohr                        ref      = '$ref',
92594171ff3SAndreas Gohr                        ref_md5  = '$ref_md5',
92614d99ec0SAndreas Gohr                        ref_type = '$ref_type',
9271878f16fSAndreas Gohr                        screen_x = '$sx',
9281878f16fSAndreas Gohr                        screen_y = '$sy',
9291878f16fSAndreas Gohr                        view_x   = '$vx',
9301878f16fSAndreas Gohr                        view_y   = '$vy',
93175fa767dSAndreas Gohr                        js       = '$js',
9321878f16fSAndreas Gohr                        user     = '$user',
9331878f16fSAndreas Gohr                        session  = '$session'";
9341878f16fSAndreas Gohr        $ok = $this->runSQL($sql);
9351878f16fSAndreas Gohr        if(is_null($ok)){
9361878f16fSAndreas Gohr            global $MSG;
9371878f16fSAndreas Gohr            print_r($MSG);
9381878f16fSAndreas Gohr        }
93914d99ec0SAndreas Gohr
94014d99ec0SAndreas Gohr        // resolve the IP
94114d99ec0SAndreas Gohr        $this->log_ip($_SERVER['REMOTE_ADDR']);
9421878f16fSAndreas Gohr    }
9431878f16fSAndreas Gohr
9441878f16fSAndreas Gohr    /**
9451878f16fSAndreas Gohr     * Just send a 1x1 pixel blank gif to the browser
9461878f16fSAndreas Gohr     *
9471878f16fSAndreas Gohr     * @called from log.php
9481878f16fSAndreas Gohr     *
9491878f16fSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
9501878f16fSAndreas Gohr     * @author Harry Fuecks <fuecks@gmail.com>
9511878f16fSAndreas Gohr     */
9521878f16fSAndreas Gohr    function sendGIF(){
9531878f16fSAndreas Gohr        $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7');
9541878f16fSAndreas Gohr        header('Content-Type: image/gif');
9551878f16fSAndreas Gohr        header('Content-Length: '.strlen($img));
9561878f16fSAndreas Gohr        header('Connection: Close');
9571878f16fSAndreas Gohr        print $img;
9581878f16fSAndreas Gohr        flush();
9591878f16fSAndreas Gohr        // Browser should drop connection after this
9601878f16fSAndreas Gohr        // Thinks it's got the whole image
9611878f16fSAndreas Gohr    }
9621878f16fSAndreas Gohr
9631878f16fSAndreas Gohr}
964