xref: /plugin/statistics/admin.php (revision 12dcdeccf0eb5d2ff8215ea607d8c2e87d471fef)
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;
97e25286daSAndreas Gohr            case 'outlinks':
98e25286daSAndreas Gohr                $this->html_outlinks();
99e25286daSAndreas Gohr                break;
100c73e16f1SAndreas Gohr            case 'resolution':
101c73e16f1SAndreas Gohr                $this->html_resolution();
102c73e16f1SAndreas Gohr                break;
103*12dcdeccSAndreas Gohr            case 'searchphrases':
104*12dcdeccSAndreas Gohr                $this->html_searchphrases();
105*12dcdeccSAndreas Gohr                break;
106*12dcdeccSAndreas Gohr            case 'searchwords':
107*12dcdeccSAndreas Gohr                $this->html_searchwords();
108*12dcdeccSAndreas Gohr                break;
109*12dcdeccSAndreas Gohr            case 'searchengines':
110*12dcdeccSAndreas Gohr                $this->html_searchengines();
111*12dcdeccSAndreas Gohr                break;
11214d99ec0SAndreas Gohr            default:
1139da6395dSAndreas Gohr                $this->html_dashboard();
11414d99ec0SAndreas Gohr        }
11514d99ec0SAndreas Gohr    }
11614d99ec0SAndreas Gohr
1179da6395dSAndreas Gohr    function html_toc(){
1189da6395dSAndreas Gohr        echo '<div class="toc">';
1199da6395dSAndreas Gohr        echo '<div class="tocheader toctoggle" id="toc__header">';
1209da6395dSAndreas Gohr        echo 'Detailed Statistics';
1219da6395dSAndreas Gohr        echo '</div>';
1229da6395dSAndreas Gohr        echo '<div id="toc__inside">';
1239da6395dSAndreas Gohr        echo '<ul class="toc">';
1249da6395dSAndreas Gohr
1259da6395dSAndreas Gohr        echo '<li><div class="li">';
1262507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=&amp;f='.$this->from.'&amp;t='.$this->to.'">Dashboard</a>';
1279da6395dSAndreas Gohr        echo '</div></li>';
1289da6395dSAndreas Gohr
1299da6395dSAndreas Gohr        echo '<li><div class="li">';
1302507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'">Pages</a>';
1319da6395dSAndreas Gohr        echo '</div></li>';
1329da6395dSAndreas Gohr
1339da6395dSAndreas Gohr        echo '<li><div class="li">';
1342507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=referer&amp;f='.$this->from.'&amp;t='.$this->to.'">Incoming Links</a>';
1359da6395dSAndreas Gohr        echo '</div></li>';
1369da6395dSAndreas Gohr
1379da6395dSAndreas Gohr        echo '<li><div class="li">';
1382507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'">New Incoming Links</a>';
139e7a2f1e0SAndreas Gohr        echo '</div></li>';
140e7a2f1e0SAndreas Gohr
141e7a2f1e0SAndreas Gohr        echo '<li><div class="li">';
142e25286daSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=outlinks&amp;f='.$this->from.'&amp;t='.$this->to.'">Outgoing Links</a>';
143e25286daSAndreas Gohr        echo '</div></li>';
144e25286daSAndreas Gohr
145e25286daSAndreas Gohr        echo '<li><div class="li">';
146*12dcdeccSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchphrases&amp;f='.$this->from.'&amp;t='.$this->to.'">Search Phrases</a>';
147*12dcdeccSAndreas Gohr        echo '</div></li>';
148*12dcdeccSAndreas Gohr
149*12dcdeccSAndreas Gohr        echo '<li><div class="li">';
150*12dcdeccSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchwords&amp;f='.$this->from.'&amp;t='.$this->to.'">Search Words</a>';
151*12dcdeccSAndreas Gohr        echo '</div></li>';
152*12dcdeccSAndreas Gohr
153*12dcdeccSAndreas Gohr        echo '<li><div class="li">';
154*12dcdeccSAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=searchengines&amp;f='.$this->from.'&amp;t='.$this->to.'">Search Engines</a>';
155*12dcdeccSAndreas Gohr        echo '</div></li>';
156*12dcdeccSAndreas Gohr
157*12dcdeccSAndreas Gohr
158*12dcdeccSAndreas Gohr        echo '<li><div class="li">';
1592507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=browser&amp;f='.$this->from.'&amp;t='.$this->to.'">Browsers</a>';
16075fa767dSAndreas Gohr        echo '</div></li>';
16175fa767dSAndreas Gohr
16275fa767dSAndreas Gohr        echo '<li><div class="li">';
1632507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=os&amp;f='.$this->from.'&amp;t='.$this->to.'">Operating Systems</a>';
164bd4217d3SAndreas Gohr        echo '</div></li>';
165bd4217d3SAndreas Gohr
166bd4217d3SAndreas Gohr        echo '<li><div class="li">';
1672507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=country&amp;f='.$this->from.'&amp;t='.$this->to.'">Countries</a>';
1689da6395dSAndreas Gohr        echo '</div></li>';
1699da6395dSAndreas Gohr
170c73e16f1SAndreas Gohr        echo '<li><div class="li">';
171c73e16f1SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=resolution&amp;f='.$this->from.'&amp;t='.$this->to.'">Resolution</a>';
172c73e16f1SAndreas Gohr        echo '</div></li>';
173c73e16f1SAndreas Gohr
1749da6395dSAndreas Gohr        echo '</ul>';
1759da6395dSAndreas Gohr        echo '</div>';
1769da6395dSAndreas Gohr        echo '</div>';
1779da6395dSAndreas Gohr    }
1789da6395dSAndreas Gohr
1792507f8e0SAndreas Gohr    function html_pager($limit,$next){
1802507f8e0SAndreas Gohr        echo '<div class="plg_stats_pager">';
1812507f8e0SAndreas Gohr
1822507f8e0SAndreas Gohr        if($this->start > 0){
1832507f8e0SAndreas Gohr            $go = max($this->start - $limit, 0);
1842507f8e0SAndreas 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>';
1852507f8e0SAndreas Gohr        }
1862507f8e0SAndreas Gohr
1872507f8e0SAndreas Gohr        if($next){
1882507f8e0SAndreas Gohr            $go = $this->start + $limit;
1892507f8e0SAndreas 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>';
1902507f8e0SAndreas Gohr        }
1912507f8e0SAndreas Gohr        echo '</div>';
1922507f8e0SAndreas Gohr    }
1932507f8e0SAndreas Gohr
194264f1744SAndreas Gohr    /**
195264f1744SAndreas Gohr     * Print the time selection menu
196264f1744SAndreas Gohr     */
19714d99ec0SAndreas Gohr    function html_timeselect(){
198264f1744SAndreas Gohr        $now   = date('Y-m-d');
199264f1744SAndreas Gohr        $yday  = date('Y-m-d',time()-(60*60*24));
200264f1744SAndreas Gohr        $week  = date('Y-m-d',time()-(60*60*24*7));
201264f1744SAndreas Gohr        $month = date('Y-m-d',time()-(60*60*24*30));
20214d99ec0SAndreas Gohr
203264f1744SAndreas Gohr        echo '<div class="plg_stats_timeselect">';
204264f1744SAndreas Gohr        echo '<span>Select the timeframe:</span>';
205264f1744SAndreas Gohr        echo '<ul>';
206264f1744SAndreas Gohr
207264f1744SAndreas Gohr        echo '<li>';
2082507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$now.'&amp;t='.$now.'">';
209264f1744SAndreas Gohr        echo 'today';
210264f1744SAndreas Gohr        echo '</a>';
211264f1744SAndreas Gohr        echo '</li>';
212264f1744SAndreas Gohr
213264f1744SAndreas Gohr        echo '<li>';
2142507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$yday.'&amp;t='.$yday.'">';
215264f1744SAndreas Gohr        echo 'yesterday';
216264f1744SAndreas Gohr        echo '</a>';
217264f1744SAndreas Gohr        echo '</li>';
218264f1744SAndreas Gohr
219264f1744SAndreas Gohr        echo '<li>';
2202507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$week.'&amp;t='.$now.'">';
221264f1744SAndreas Gohr        echo 'last 7 days';
222264f1744SAndreas Gohr        echo '</a>';
223264f1744SAndreas Gohr        echo '</li>';
224264f1744SAndreas Gohr
225264f1744SAndreas Gohr        echo '<li>';
2262507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt='.$this->opt.'&amp;f='.$month.'&amp;t='.$now.'">';
227264f1744SAndreas Gohr        echo 'last 30 days';
228264f1744SAndreas Gohr        echo '</a>';
229264f1744SAndreas Gohr        echo '</li>';
230264f1744SAndreas Gohr
231264f1744SAndreas Gohr        echo '</ul>';
232264f1744SAndreas Gohr
233264f1744SAndreas Gohr
234264f1744SAndreas Gohr        echo '<form action="" method="get">';
235264f1744SAndreas Gohr        echo '<input type="hidden" name="do" value="admin" />';
236264f1744SAndreas Gohr        echo '<input type="hidden" name="page" value="statistics" />';
237264f1744SAndreas Gohr        echo '<input type="hidden" name="opt" value="'.$this->opt.'" />';
238264f1744SAndreas Gohr        echo '<input type="text" name="f" value="'.$this->from.'" class="edit" />';
239264f1744SAndreas Gohr        echo '<input type="text" name="t" value="'.$this->to.'" class="edit" />';
240264f1744SAndreas Gohr        echo '<input type="submit" value="go" class="button" />';
24114d99ec0SAndreas Gohr        echo '</form>';
242264f1744SAndreas Gohr
243264f1744SAndreas Gohr        echo '</div>';
24414d99ec0SAndreas Gohr    }
24514d99ec0SAndreas Gohr
24614d99ec0SAndreas Gohr
247f5f32cbfSAndreas Gohr    /**
248f5f32cbfSAndreas Gohr     * Print an introductionary screen
249f5f32cbfSAndreas Gohr     */
25014d99ec0SAndreas Gohr    function html_dashboard(){
2512812a751SAndreas Gohr        echo '<p>This page gives you a quick overview on what is happening in your Wiki. For detailed lists
2522812a751SAndreas Gohr              choose a topic from the list.</p>';
2532812a751SAndreas Gohr
2542812a751SAndreas Gohr
255264f1744SAndreas Gohr        echo '<div class="plg_stats_dashboard">';
256264f1744SAndreas Gohr
2572812a751SAndreas Gohr        // general info
2582812a751SAndreas Gohr        echo '<div class="plg_stats_top">';
2592812a751SAndreas Gohr        $result = $this->sql_aggregate($this->tlimit);
2602812a751SAndreas Gohr        echo '<ul>';
2612812a751SAndreas Gohr        echo '<li><span>'.$result['pageviews'].'</span> page views </li>';
2623c0acc14SAndreas Gohr        echo '<li><span>'.$result['sessions'].'</span> visits (sessions) </li>';
2633c0acc14SAndreas Gohr        echo '<li><span>'.$result['visitors'].'</span> unique visitors </li>';
2642812a751SAndreas Gohr        echo '<li><span>'.$result['users'].'</span> logged in users</li>';
2652812a751SAndreas Gohr
2662812a751SAndreas Gohr        echo '</ul>';
2672812a751SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=trend&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
2682812a751SAndreas Gohr        echo '</div>';
2692812a751SAndreas Gohr
27014d99ec0SAndreas Gohr
27187d5e44bSAndreas Gohr        // top pages today
272264f1744SAndreas Gohr        echo '<div>';
273264f1744SAndreas Gohr        echo '<h2>Most popular pages</h2>';
27495eb68e6SAndreas Gohr        $result = $this->sql_pages($this->tlimit,$this->start,15);
2752812a751SAndreas Gohr        $this->html_resulttable($result);
2762507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=page&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
277264f1744SAndreas Gohr        echo '</div>';
27887d5e44bSAndreas Gohr
27987d5e44bSAndreas Gohr        // top referer today
280264f1744SAndreas Gohr        echo '<div>';
281e7a2f1e0SAndreas Gohr        echo '<h2>Newest incoming links</h2>';
282e7a2f1e0SAndreas Gohr        $result = $this->sql_newreferer($this->tlimit,$this->start,15);
2832812a751SAndreas Gohr        $this->html_resulttable($result);
2842507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=newreferer&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
285264f1744SAndreas Gohr        echo '</div>';
28654f6c432SAndreas Gohr
28754f6c432SAndreas Gohr        // top countries today
288264f1744SAndreas Gohr        echo '<div>';
289264f1744SAndreas Gohr        echo '<h2>Visitor\'s top countries</h2>';
29095eb68e6SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
2912507f8e0SAndreas Gohr        echo '<a href="?do=admin&amp;page=statistics&amp;opt=country&amp;f='.$this->from.'&amp;t='.$this->to.'" class="more">more</a>';
292264f1744SAndreas Gohr        echo '</div>';
293264f1744SAndreas Gohr
294264f1744SAndreas Gohr        echo '</div>';
29514d99ec0SAndreas Gohr    }
29614d99ec0SAndreas Gohr
2979da6395dSAndreas Gohr    function html_country(){
2989da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
2999da6395dSAndreas Gohr        echo '<h2>Visitor\'s Countries</h2>';
300bd4217d3SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=country&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
3019da6395dSAndreas Gohr        $result = $this->sql_countries($this->tlimit,$this->start,150);
3022507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
3039da6395dSAndreas Gohr        echo '</div>';
3049da6395dSAndreas Gohr    }
3059da6395dSAndreas Gohr
3069da6395dSAndreas Gohr    function html_page(){
3079da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
3089da6395dSAndreas Gohr        echo '<h2>Popular Pages</h2>';
3099da6395dSAndreas Gohr        $result = $this->sql_pages($this->tlimit,$this->start,150);
3102507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
3119da6395dSAndreas Gohr        echo '</div>';
3129da6395dSAndreas Gohr    }
3139da6395dSAndreas Gohr
31475fa767dSAndreas Gohr    function html_browser(){
31575fa767dSAndreas Gohr        echo '<div class="plg_stats_full">';
31675fa767dSAndreas Gohr        echo '<h2>Browser Shootout</h2>';
31775fa767dSAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=browser&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
31875fa767dSAndreas Gohr        $result = $this->sql_browsers($this->tlimit,$this->start,150,true);
3192507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
32075fa767dSAndreas Gohr        echo '</div>';
32175fa767dSAndreas Gohr    }
32275fa767dSAndreas Gohr
323bd4217d3SAndreas Gohr    function html_os(){
324bd4217d3SAndreas Gohr        echo '<div class="plg_stats_full">';
325bd4217d3SAndreas Gohr        echo '<h2>Operating Systems</h2>';
326bd4217d3SAndreas Gohr        $result = $this->sql_os($this->tlimit,$this->start,150,true);
3272507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
328bd4217d3SAndreas Gohr        echo '</div>';
329bd4217d3SAndreas Gohr    }
330bd4217d3SAndreas Gohr
3319da6395dSAndreas Gohr    function html_referer(){
3329da6395dSAndreas Gohr        echo '<div class="plg_stats_full">';
3339da6395dSAndreas Gohr        echo '<h2>Incoming Links</h2>';
3342812a751SAndreas Gohr        $result = $this->sql_aggregate($this->tlimit);
3352812a751SAndreas Gohr
3362812a751SAndreas Gohr        $all    = $result['search']+$result['external']+$result['direct'];
3372812a751SAndreas Gohr
33894023548SAndreas Gohr        if($all){
3392812a751SAndreas Gohr            printf("<p>Of all %d external visits, %d (%.1f%%) were bookmarked (direct) accesses,
3402812a751SAndreas Gohr                    %d (%.1f%%) came from search engines and %d (%.1f%%) were referred through
3412812a751SAndreas Gohr                    links from other pages.</p>",$all,$result['direct'],(100*$result['direct']/$all),
3422812a751SAndreas Gohr                    $result['search'],(100*$result['search']/$all),$result['external'],
3432812a751SAndreas Gohr                    (100*$result['external']/$all));
34494023548SAndreas Gohr        }
3452812a751SAndreas Gohr
3469da6395dSAndreas Gohr        $result = $this->sql_referer($this->tlimit,$this->start,150);
3472507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
3489da6395dSAndreas Gohr        echo '</div>';
3499da6395dSAndreas Gohr    }
3509da6395dSAndreas Gohr
351e7a2f1e0SAndreas Gohr    function html_newreferer(){
352e7a2f1e0SAndreas Gohr        echo '<div class="plg_stats_full">';
353e7a2f1e0SAndreas Gohr        echo '<h2>New Incoming Links</h2>';
354e7a2f1e0SAndreas Gohr        echo '<p>The following incoming links where first logged in the selected time frame,
355e7a2f1e0SAndreas Gohr              and have never been seen before.</p>';
356e7a2f1e0SAndreas Gohr
357e7a2f1e0SAndreas Gohr        $result = $this->sql_newreferer($this->tlimit,$this->start,150);
3582507f8e0SAndreas Gohr        $this->html_resulttable($result,'',150);
359e7a2f1e0SAndreas Gohr        echo '</div>';
360e7a2f1e0SAndreas Gohr    }
361e7a2f1e0SAndreas Gohr
362e25286daSAndreas Gohr    function html_outlinks(){
363e25286daSAndreas Gohr        echo '<div class="plg_stats_full">';
364e25286daSAndreas Gohr        echo '<h2>Outgoing Links</h2>';
365e25286daSAndreas Gohr
366e25286daSAndreas Gohr        $result = $this->sql_outlinks($this->tlimit,$this->start,150);
367e25286daSAndreas Gohr        $this->html_resulttable($result,'',150);
368e25286daSAndreas Gohr        echo '</div>';
369e25286daSAndreas Gohr    }
370e25286daSAndreas Gohr
371*12dcdeccSAndreas Gohr    function html_searchphrases(){
372*12dcdeccSAndreas Gohr        echo '<div class="plg_stats_full">';
373*12dcdeccSAndreas Gohr        echo '<h2>Search Phrases</h2>';
374*12dcdeccSAndreas Gohr
375*12dcdeccSAndreas Gohr        $result = $this->sql_searchphrases($this->tlimit,$this->start,150);
376*12dcdeccSAndreas Gohr        $this->html_resulttable($result,'',150);
377*12dcdeccSAndreas Gohr        echo '</div>';
378*12dcdeccSAndreas Gohr    }
379*12dcdeccSAndreas Gohr
380*12dcdeccSAndreas Gohr    function html_searchwords(){
381*12dcdeccSAndreas Gohr        echo '<div class="plg_stats_full">';
382*12dcdeccSAndreas Gohr        echo '<h2>Search Words</h2>';
383*12dcdeccSAndreas Gohr
384*12dcdeccSAndreas Gohr        $result = $this->sql_searchwords($this->tlimit,$this->start,150);
385*12dcdeccSAndreas Gohr        $this->html_resulttable($result,'',150);
386*12dcdeccSAndreas Gohr        echo '</div>';
387*12dcdeccSAndreas Gohr    }
388*12dcdeccSAndreas Gohr
389*12dcdeccSAndreas Gohr    function html_searchengines(){
390*12dcdeccSAndreas Gohr        echo '<div class="plg_stats_full">';
391*12dcdeccSAndreas Gohr        echo '<h2>Search Engines</h2>';
392*12dcdeccSAndreas Gohr
393*12dcdeccSAndreas Gohr        $result = $this->sql_searchengines($this->tlimit,$this->start,150);
394*12dcdeccSAndreas Gohr        $this->html_resulttable($result,'',150);
395*12dcdeccSAndreas Gohr        echo '</div>';
396*12dcdeccSAndreas Gohr    }
397*12dcdeccSAndreas Gohr
398e25286daSAndreas Gohr
399c73e16f1SAndreas Gohr    function html_resolution(){
400c73e16f1SAndreas Gohr        echo '<div class="plg_stats_full">';
401c73e16f1SAndreas Gohr        echo '<h2>Resolution</h2>';
402c73e16f1SAndreas Gohr        $result = $this->sql_resolution($this->tlimit,$this->start,150);
403c73e16f1SAndreas Gohr        $this->html_resulttable($result,'',150);
404c73e16f1SAndreas Gohr
405c73e16f1SAndreas Gohr        echo '<p>While the data above gives you some info about the resolution your visitors use, it does not tell you
406c73e16f1SAndreas Gohr              much about about the real size of their browser windows. The graphic below shows the size distribution of
407c73e16f1SAndreas Gohr              the view port (document area) of your visitor\'s browsers. Please note that this data can not be logged
408c73e16f1SAndreas Gohr              in all browsers. Because users may resize their browser window while browsing your site the statistics may
409c73e16f1SAndreas Gohr              be flawed. Take it with a grain of salt.</p>';
410c73e16f1SAndreas Gohr
411c73e16f1SAndreas Gohr        echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/img.php?img=view&amp;f='.$this->from.'&amp;t='.$this->to.'" />';
412c73e16f1SAndreas Gohr        echo '</div>';
413c73e16f1SAndreas Gohr    }
4149da6395dSAndreas Gohr
4159da6395dSAndreas Gohr
41614d99ec0SAndreas Gohr    /**
41714d99ec0SAndreas Gohr     * Display a result in a HTML table
41814d99ec0SAndreas Gohr     */
4192507f8e0SAndreas Gohr    function html_resulttable($result,$header='',$pager=0){
42014d99ec0SAndreas Gohr        echo '<table>';
4212812a751SAndreas Gohr        if(is_array($header)){
42214d99ec0SAndreas Gohr            echo '<tr>';
42314d99ec0SAndreas Gohr            foreach($header as $h){
42414d99ec0SAndreas Gohr                echo '<th>'.hsc($h).'</th>';
42514d99ec0SAndreas Gohr            }
42614d99ec0SAndreas Gohr            echo '</tr>';
4272812a751SAndreas Gohr        }
42814d99ec0SAndreas Gohr
4292507f8e0SAndreas Gohr        $count = 0;
43014d99ec0SAndreas Gohr        foreach($result as $row){
43114d99ec0SAndreas Gohr            echo '<tr>';
43214d99ec0SAndreas Gohr            foreach($row as $k => $v){
4332812a751SAndreas Gohr                echo '<td class="plg_stats_X'.$k.'">';
43414d99ec0SAndreas Gohr                if($k == 'page'){
43514d99ec0SAndreas Gohr                    echo '<a href="'.wl($v).'" class="wikilink1">';
43614d99ec0SAndreas Gohr                    echo hsc($v);
43714d99ec0SAndreas Gohr                    echo '</a>';
43814d99ec0SAndreas Gohr                }elseif($k == 'url'){
43954f6c432SAndreas Gohr                    $url = hsc($v);
44083b63546SAndreas Gohr                    $url = preg_replace('/^https?:\/\/(www\.)?/','',$url);
4412812a751SAndreas Gohr                    if(strlen($url) > 45){
4422812a751SAndreas Gohr                        $url = substr($url,0,30).' &hellip; '.substr($url,-15);
44354f6c432SAndreas Gohr                    }
44414d99ec0SAndreas Gohr                    echo '<a href="'.$v.'" class="urlextern">';
44554f6c432SAndreas Gohr                    echo $url;
44614d99ec0SAndreas Gohr                    echo '</a>';
447*12dcdeccSAndreas Gohr                }elseif($k == 'engine'){
448*12dcdeccSAndreas Gohr                    include_once(dirname(__FILE__).'/inc/search_engines.php');
449*12dcdeccSAndreas Gohr                    echo $SearchEnginesHashLib[$v];
45075fa767dSAndreas Gohr                }elseif($k == 'browser'){
45175fa767dSAndreas Gohr                    include_once(dirname(__FILE__).'/inc/browsers.php');
45275fa767dSAndreas Gohr                    echo $BrowsersHashIDLib[$v];
45375fa767dSAndreas Gohr                }elseif($k == 'bflag'){
45475fa767dSAndreas Gohr                    include_once(dirname(__FILE__).'/inc/browsers.php');
45575fa767dSAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/browser/'.$BrowsersHashIcon[$v].'.png" alt="'.hsc($v).'" />';
456bd4217d3SAndreas Gohr                }elseif($k == 'os'){
457bd4217d3SAndreas Gohr                    if(empty($v)){
458bd4217d3SAndreas Gohr                        echo 'unknown';
459bd4217d3SAndreas Gohr                    }else{
460bd4217d3SAndreas Gohr                        include_once(dirname(__FILE__).'/inc/operating_systems.php');
461bd4217d3SAndreas Gohr                        echo $OSHashLib[$v];
462bd4217d3SAndreas Gohr                    }
463bd4217d3SAndreas Gohr                }elseif($k == 'osflag'){
464bd4217d3SAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/os/'.hsc($v).'.png" alt="'.hsc($v).'" />';
46575fa767dSAndreas Gohr                }elseif($k == 'cflag'){
46675fa767dSAndreas Gohr                    echo '<img src="'.DOKU_BASE.'lib/plugins/statistics/ico/flags/'.hsc($v).'.png" alt="'.hsc($v).'" width="18" height="12" />';
46714d99ec0SAndreas Gohr                }elseif($k == 'html'){
46814d99ec0SAndreas Gohr                    echo $v;
46914d99ec0SAndreas Gohr                }else{
47014d99ec0SAndreas Gohr                    echo hsc($v);
47114d99ec0SAndreas Gohr                }
47214d99ec0SAndreas Gohr                echo '</td>';
47314d99ec0SAndreas Gohr            }
47414d99ec0SAndreas Gohr            echo '</tr>';
4752507f8e0SAndreas Gohr
4762507f8e0SAndreas Gohr            if($pager && ($count == $pager)) break;
4772507f8e0SAndreas Gohr            $count++;
47814d99ec0SAndreas Gohr        }
47914d99ec0SAndreas Gohr        echo '</table>';
4802507f8e0SAndreas Gohr
4812507f8e0SAndreas Gohr        if($pager) $this->html_pager($pager,count($result) > $pager);
4821878f16fSAndreas Gohr    }
4831878f16fSAndreas Gohr
48495eb68e6SAndreas Gohr    /**
48595eb68e6SAndreas Gohr     * Create an image
48695eb68e6SAndreas Gohr     */
48795eb68e6SAndreas Gohr    function img_build($img){
48895eb68e6SAndreas Gohr        include(dirname(__FILE__).'/inc/AGC.class.php');
48995eb68e6SAndreas Gohr
49095eb68e6SAndreas Gohr        switch($img){
49195eb68e6SAndreas Gohr            case 'country':
49295eb68e6SAndreas Gohr                // build top countries + other
49395eb68e6SAndreas Gohr                $result = $this->sql_countries($this->tlimit,$this->start,0);
49495eb68e6SAndreas Gohr                $data = array();
49595eb68e6SAndreas Gohr                $top = 0;
49695eb68e6SAndreas Gohr                foreach($result as $row){
49795eb68e6SAndreas Gohr                    if($top < 7){
49895eb68e6SAndreas Gohr                        $data[$row['country']] = $row['cnt'];
49995eb68e6SAndreas Gohr                    }else{
50095eb68e6SAndreas Gohr                        $data['other'] += $row['cnt'];
50195eb68e6SAndreas Gohr                    }
50295eb68e6SAndreas Gohr                    $top++;
50395eb68e6SAndreas Gohr                }
50495eb68e6SAndreas Gohr                $pie = new AGC(300, 200);
50595eb68e6SAndreas Gohr                $pie->setProp("showkey",true);
50695eb68e6SAndreas Gohr                $pie->setProp("showval",false);
50795eb68e6SAndreas Gohr                $pie->setProp("showgrid",false);
50895eb68e6SAndreas Gohr                $pie->setProp("type","pie");
50995eb68e6SAndreas Gohr                $pie->setProp("keyinfo",1);
51095eb68e6SAndreas Gohr                $pie->setProp("keysize",8);
51195eb68e6SAndreas Gohr                $pie->setProp("keywidspc",-50);
51295eb68e6SAndreas Gohr                $pie->setProp("key",array_keys($data));
51395eb68e6SAndreas Gohr                $pie->addBulkPoints(array_values($data));
51495eb68e6SAndreas Gohr                @$pie->graph();
51595eb68e6SAndreas Gohr                $pie->showGraph();
51695eb68e6SAndreas Gohr                break;
51775fa767dSAndreas Gohr            case 'browser':
51875fa767dSAndreas Gohr                // build top browsers + other
51975fa767dSAndreas Gohr                include_once(dirname(__FILE__).'/inc/browsers.php');
52075fa767dSAndreas Gohr
52175fa767dSAndreas Gohr                $result = $this->sql_browsers($this->tlimit,$this->start,0,false);
52275fa767dSAndreas Gohr                $data = array();
52375fa767dSAndreas Gohr                $top = 0;
52475fa767dSAndreas Gohr                foreach($result as $row){
52575fa767dSAndreas Gohr                    if($top < 5){
52675fa767dSAndreas Gohr                        $data[strip_tags($BrowsersHashIDLib[$row['ua_info']])] = $row['cnt'];
52775fa767dSAndreas Gohr                    }else{
52875fa767dSAndreas Gohr                        $data['other'] += $row['cnt'];
52975fa767dSAndreas Gohr                    }
53075fa767dSAndreas Gohr                    $top++;
53175fa767dSAndreas Gohr                }
53275fa767dSAndreas Gohr                $pie = new AGC(300, 200);
53375fa767dSAndreas Gohr                $pie->setProp("showkey",true);
53475fa767dSAndreas Gohr                $pie->setProp("showval",false);
53575fa767dSAndreas Gohr                $pie->setProp("showgrid",false);
53675fa767dSAndreas Gohr                $pie->setProp("type","pie");
53775fa767dSAndreas Gohr                $pie->setProp("keyinfo",1);
53875fa767dSAndreas Gohr                $pie->setProp("keysize",8);
53975fa767dSAndreas Gohr                $pie->setProp("keywidspc",-50);
54075fa767dSAndreas Gohr                $pie->setProp("key",array_keys($data));
54175fa767dSAndreas Gohr                $pie->addBulkPoints(array_values($data));
54275fa767dSAndreas Gohr                @$pie->graph();
54375fa767dSAndreas Gohr                $pie->showGraph();
54475fa767dSAndreas Gohr                break;
545c73e16f1SAndreas Gohr            case 'view':
546c73e16f1SAndreas Gohr
547c73e16f1SAndreas Gohr                $graph = new AGC(400, 200);
548c73e16f1SAndreas Gohr                $graph->setColor('color',0,'blue');
549c73e16f1SAndreas Gohr                $graph->setColor('color',1,'red');
550c73e16f1SAndreas Gohr                $graph->setProp("showkey",true);
551c73e16f1SAndreas Gohr                $graph->setProp("key",'view port width',0);
552c73e16f1SAndreas Gohr                $graph->setProp("key",'view port height',1);
553c73e16f1SAndreas Gohr
554c73e16f1SAndreas Gohr                $result = $this->sql_viewport($this->tlimit,0,0,true);
555c73e16f1SAndreas Gohr                foreach($result as $row){
556c73e16f1SAndreas Gohr                    $graph->addPoint($row['cnt'],$row['res_x'],0);
557c73e16f1SAndreas Gohr                }
558c73e16f1SAndreas Gohr
559c73e16f1SAndreas Gohr                $result = $this->sql_viewport($this->tlimit,0,0,false);
560c73e16f1SAndreas Gohr                foreach($result as $row){
561c73e16f1SAndreas Gohr                    $graph->addPoint($row['cnt'],$row['res_y'],1);
562c73e16f1SAndreas Gohr                }
563c73e16f1SAndreas Gohr
564c73e16f1SAndreas Gohr                @$graph->graph();
565c73e16f1SAndreas Gohr                $graph->showGraph();
566c73e16f1SAndreas Gohr
567c73e16f1SAndreas Gohr                break;
5682812a751SAndreas Gohr            case 'trend':
5692812a751SAndreas Gohr                $hours  = ($this->from == $this->to);
5702812a751SAndreas Gohr                $result = $this->sql_trend($this->tlimit,$hours);
5712812a751SAndreas Gohr                $data1   = array();
5722812a751SAndreas Gohr                $data2   = array();
5732812a751SAndreas Gohr
5742812a751SAndreas Gohr                $graph = new AGC(400, 150);
5752812a751SAndreas Gohr                $graph->setProp("type","bar");
5762812a751SAndreas Gohr                $graph->setProp("showgrid",false);
5772812a751SAndreas Gohr                $graph->setProp("barwidth",.8);
57875fa767dSAndreas Gohr
5792812a751SAndreas Gohr                $graph->setColor('color',0,'blue');
5802812a751SAndreas Gohr                $graph->setColor('color',1,'red');
5813c0acc14SAndreas Gohr                $graph->setColor('color',2,'yellow');
5822812a751SAndreas Gohr
5832812a751SAndreas Gohr                if($hours){
5842812a751SAndreas Gohr                    //preset $hours
5852812a751SAndreas Gohr                    for($i=0;$i<24;$i++){
5862812a751SAndreas Gohr                        $data1[$i] = 0;
5872812a751SAndreas Gohr                        $data2[$i] = 0;
5883c0acc14SAndreas Gohr                        $data3[$i] = 0;
5892812a751SAndreas Gohr                        $graph->setProp("scale",array(' 0h','   4h','   8h','    12h','    16h','    20h','    24h'));
5902812a751SAndreas Gohr                    }
5912812a751SAndreas Gohr                }else{
5922812a751SAndreas Gohr                    $graph->setProp("scale",array(next(array_keys($data1)),$this->to));
5932812a751SAndreas Gohr                }
5942812a751SAndreas Gohr
5952812a751SAndreas Gohr                foreach($result as $row){
5962812a751SAndreas Gohr                    $data1[$row['time']] = $row['pageviews'];
5972812a751SAndreas Gohr                    $data2[$row['time']] = $row['sessions'];
5983c0acc14SAndreas Gohr                    $data3[$row['time']] = $row['visitors'];
5992812a751SAndreas Gohr                }
6002812a751SAndreas Gohr
6012812a751SAndreas Gohr                foreach($data1 as $key => $val){
6022812a751SAndreas Gohr                    $graph->addPoint($val,$key,0);
6032812a751SAndreas Gohr                }
6042812a751SAndreas Gohr                foreach($data2 as $key => $val){
6052812a751SAndreas Gohr                    $graph->addPoint($val,$key,1);
6062812a751SAndreas Gohr                }
6073c0acc14SAndreas Gohr                foreach($data3 as $key => $val){
6083c0acc14SAndreas Gohr                    $graph->addPoint($val,$key,2);
6093c0acc14SAndreas Gohr                }
6102812a751SAndreas Gohr
6112812a751SAndreas Gohr                @$graph->graph();
6122812a751SAndreas Gohr                $graph->showGraph();
6132812a751SAndreas Gohr
61495eb68e6SAndreas Gohr            default:
61595eb68e6SAndreas Gohr                $this->sendGIF();
61695eb68e6SAndreas Gohr        }
61795eb68e6SAndreas Gohr    }
61895eb68e6SAndreas Gohr
61995eb68e6SAndreas Gohr
6202812a751SAndreas Gohr    /**
6212812a751SAndreas Gohr     * Return some aggregated statistics
6222812a751SAndreas Gohr     */
6232812a751SAndreas Gohr    function sql_aggregate($tlimit){
6242812a751SAndreas Gohr        $data = array();
6252812a751SAndreas Gohr
6262812a751SAndreas Gohr        $sql = "SELECT ref_type, COUNT(*) as cnt
6272812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
6282812a751SAndreas Gohr                 WHERE $tlimit
6292812a751SAndreas Gohr                   AND ua_type = 'browser'
6302812a751SAndreas Gohr              GROUP BY ref_type";
6312812a751SAndreas Gohr        $result = $this->runSQL($sql);
6322812a751SAndreas Gohr
6332812a751SAndreas Gohr        foreach($result as $row){
6342812a751SAndreas Gohr            if($row['ref_type'] == 'search')   $data['search']   = $row['cnt'];
6352812a751SAndreas Gohr            if($row['ref_type'] == 'external') $data['external'] = $row['cnt'];
6362812a751SAndreas Gohr            if($row['ref_type'] == 'internal') $data['internal'] = $row['cnt'];
6372812a751SAndreas Gohr            if($row['ref_type'] == '')         $data['direct']   = $row['cnt'];
6382812a751SAndreas Gohr        }
6392812a751SAndreas Gohr
6402812a751SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as sessions,
6412812a751SAndreas Gohr                       COUNT(session) as views,
6423c0acc14SAndreas Gohr                       COUNT(DISTINCT user) as users,
6433c0acc14SAndreas Gohr                       COUNT(DISTINCT uid) as visitors
6442812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
6452812a751SAndreas Gohr                 WHERE $tlimit
6462812a751SAndreas Gohr                   AND ua_type = 'browser'";
6472812a751SAndreas Gohr        $result = $this->runSQL($sql);
6482812a751SAndreas Gohr
64975fa767dSAndreas Gohr        $data['users']     = max($result[0]['users'] - 1,0); // subtract empty user
6502812a751SAndreas Gohr        $data['sessions']  = $result[0]['sessions'];
6512812a751SAndreas Gohr        $data['pageviews'] = $result[0]['views'];
6523c0acc14SAndreas Gohr        $data['visitors']  = $result[0]['visitors'];
6532812a751SAndreas Gohr
6542812a751SAndreas Gohr        $sql = "SELECT COUNT(id) as robots
6552812a751SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
6562812a751SAndreas Gohr                 WHERE $tlimit
6572812a751SAndreas Gohr                   AND ua_type = 'robot'";
6582812a751SAndreas Gohr        $result = $this->runSQL($sql);
6592812a751SAndreas Gohr        $data['robots'] = $result[0]['robots'];
6602812a751SAndreas Gohr
6612812a751SAndreas Gohr        return $data;
6622812a751SAndreas Gohr    }
6632812a751SAndreas Gohr
664bd4217d3SAndreas Gohr    /**
665bd4217d3SAndreas Gohr     * standard statistics follow, only accesses made by browsers are counted
666bd4217d3SAndreas Gohr     * for general stats like browser or OS only visitors not pageviews are counted
667bd4217d3SAndreas Gohr     */
6682812a751SAndreas Gohr    function sql_trend($tlimit,$hours=false){
6692812a751SAndreas Gohr        if($hours){
6702812a751SAndreas Gohr            $sql = "SELECT HOUR(dt) as time,
6712812a751SAndreas Gohr                           COUNT(DISTINCT session) as sessions,
6723c0acc14SAndreas Gohr                           COUNT(session) as pageviews,
6733c0acc14SAndreas Gohr                           COUNT(DISTINCT uid) as visitors
6742812a751SAndreas Gohr                      FROM ".$this->getConf('db_prefix')."access as A
6752812a751SAndreas Gohr                     WHERE $tlimit
6762812a751SAndreas Gohr                       AND ua_type = 'browser'
6772812a751SAndreas Gohr                  GROUP BY HOUR(dt)
6782812a751SAndreas Gohr                  ORDER BY time";
6792812a751SAndreas Gohr        }else{
6802812a751SAndreas Gohr            $sql = "SELECT DATE(dt) as time,
6812812a751SAndreas Gohr                           COUNT(DISTINCT session) as sessions,
6823c0acc14SAndreas Gohr                           COUNT(session) as pageviews,
6833c0acc14SAndreas Gohr                            COUNT(DISTINCT uid) as visitors
6842812a751SAndreas Gohr                      FROM ".$this->getConf('db_prefix')."access as A
6852812a751SAndreas Gohr                     WHERE $tlimit
6862812a751SAndreas Gohr                       AND ua_type = 'browser'
6872812a751SAndreas Gohr                  GROUP BY DATE(dt)
6882812a751SAndreas Gohr                  ORDER BY time";
6892812a751SAndreas Gohr        }
6902812a751SAndreas Gohr        return $this->runSQL($sql);
6912812a751SAndreas Gohr    }
6922812a751SAndreas Gohr
693*12dcdeccSAndreas Gohr    function sql_searchengines($tlimit,$start=0,$limit=20){
694*12dcdeccSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, engine
695*12dcdeccSAndreas Gohr                  FROM ".$this->getConf('db_prefix')."search as A
696*12dcdeccSAndreas Gohr                 WHERE $tlimit
697*12dcdeccSAndreas Gohr              GROUP BY engine
698*12dcdeccSAndreas Gohr              ORDER BY cnt DESC, engine".
699*12dcdeccSAndreas Gohr              $this->sql_limit($start,$limit);
700*12dcdeccSAndreas Gohr        return $this->runSQL($sql);
701*12dcdeccSAndreas Gohr    }
702*12dcdeccSAndreas Gohr
703*12dcdeccSAndreas Gohr    function sql_searchphrases($tlimit,$start=0,$limit=20){
704*12dcdeccSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, query
705*12dcdeccSAndreas Gohr                  FROM ".$this->getConf('db_prefix')."search as A
706*12dcdeccSAndreas Gohr                 WHERE $tlimit
707*12dcdeccSAndreas Gohr              GROUP BY query
708*12dcdeccSAndreas Gohr              ORDER BY cnt DESC, query".
709*12dcdeccSAndreas Gohr              $this->sql_limit($start,$limit);
710*12dcdeccSAndreas Gohr        return $this->runSQL($sql);
711*12dcdeccSAndreas Gohr    }
712*12dcdeccSAndreas Gohr
713*12dcdeccSAndreas Gohr    function sql_searchwords($tlimit,$start=0,$limit=20){
714*12dcdeccSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, word
715*12dcdeccSAndreas Gohr                  FROM ".$this->getConf('db_prefix')."search as A,
716*12dcdeccSAndreas Gohr                       ".$this->getConf('db_prefix')."searchwords as B
717*12dcdeccSAndreas Gohr                 WHERE $tlimit
718*12dcdeccSAndreas Gohr                   AND A.id = B.sid
719*12dcdeccSAndreas Gohr              GROUP BY word
720*12dcdeccSAndreas Gohr              ORDER BY cnt DESC, word".
721*12dcdeccSAndreas Gohr              $this->sql_limit($start,$limit);
722*12dcdeccSAndreas Gohr        return $this->runSQL($sql);
723*12dcdeccSAndreas Gohr    }
724*12dcdeccSAndreas Gohr
725e25286daSAndreas Gohr    function sql_outlinks($tlimit,$start=0,$limit=20){
726e25286daSAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, link as url
727e25286daSAndreas Gohr                  FROM ".$this->getConf('db_prefix')."outlinks as A
728e25286daSAndreas Gohr                 WHERE $tlimit
729e25286daSAndreas Gohr              GROUP BY link
730e25286daSAndreas Gohr              ORDER BY cnt DESC, link".
731e25286daSAndreas Gohr              $this->sql_limit($start,$limit);
732e25286daSAndreas Gohr        return $this->runSQL($sql);
733e25286daSAndreas Gohr    }
734e25286daSAndreas Gohr
73595eb68e6SAndreas Gohr    function sql_pages($tlimit,$start=0,$limit=20){
7362812a751SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, page
73795eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
73895eb68e6SAndreas Gohr                 WHERE $tlimit
73995eb68e6SAndreas Gohr                   AND ua_type = 'browser'
74095eb68e6SAndreas Gohr              GROUP BY page
74195eb68e6SAndreas Gohr              ORDER BY cnt DESC, page".
74295eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
74395eb68e6SAndreas Gohr        return $this->runSQL($sql);
74495eb68e6SAndreas Gohr    }
74595eb68e6SAndreas Gohr
74695eb68e6SAndreas Gohr    function sql_referer($tlimit,$start=0,$limit=20){
7472812a751SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, ref as url
74895eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
74995eb68e6SAndreas Gohr                 WHERE $tlimit
75095eb68e6SAndreas Gohr                   AND ua_type = 'browser'
75195eb68e6SAndreas Gohr                   AND ref_type = 'external'
75295eb68e6SAndreas Gohr              GROUP BY ref_md5
75395eb68e6SAndreas Gohr              ORDER BY cnt DESC, url".
75495eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
75595eb68e6SAndreas Gohr        return $this->runSQL($sql);
75695eb68e6SAndreas Gohr    }
75795eb68e6SAndreas Gohr
758e7a2f1e0SAndreas Gohr    function sql_newreferer($tlimit,$start=0,$limit=20){
759e7a2f1e0SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt, ref as url
760e7a2f1e0SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
761e7a2f1e0SAndreas Gohr                 WHERE ua_type = 'browser'
762e7a2f1e0SAndreas Gohr                   AND ref_type = 'external'
763e7a2f1e0SAndreas Gohr              GROUP BY ref_md5
764e7a2f1e0SAndreas Gohr                HAVING DATE(MIN(dt)) >= DATE('".$this->from."')
765e7a2f1e0SAndreas Gohr                   AND DATE(MIN(dt)) <= DATE('".$this->to."')
766e7a2f1e0SAndreas Gohr              ORDER BY cnt DESC, url".
767e7a2f1e0SAndreas Gohr              $this->sql_limit($start,$limit);
768e7a2f1e0SAndreas Gohr        return $this->runSQL($sql);
769e7a2f1e0SAndreas Gohr    }
770e7a2f1e0SAndreas Gohr
77195eb68e6SAndreas Gohr    function sql_countries($tlimit,$start=0,$limit=20){
772bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, B.code AS cflag, B.country
77395eb68e6SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A,
77495eb68e6SAndreas Gohr                       ".$this->getConf('db_prefix')."iplocation as B
77595eb68e6SAndreas Gohr                 WHERE $tlimit
77695eb68e6SAndreas Gohr                   AND A.ip = B.ip
77795eb68e6SAndreas Gohr              GROUP BY B.country
77895eb68e6SAndreas Gohr              ORDER BY cnt DESC, B.country".
77995eb68e6SAndreas Gohr              $this->sql_limit($start,$limit);
78095eb68e6SAndreas Gohr        return $this->runSQL($sql);
78195eb68e6SAndreas Gohr    }
78295eb68e6SAndreas Gohr
78375fa767dSAndreas Gohr    function sql_browsers($tlimit,$start=0,$limit=20,$ext=true){
78475fa767dSAndreas Gohr        if($ext){
78575fa767dSAndreas Gohr            $sel = 'ua_info as bflag, ua_info as browser, ua_ver';
78675fa767dSAndreas Gohr            $grp = 'ua_info, ua_ver';
78775fa767dSAndreas Gohr        }else{
78875fa767dSAndreas Gohr            $grp = 'ua_info';
78975fa767dSAndreas Gohr            $sel = 'ua_info';
79075fa767dSAndreas Gohr        }
79175fa767dSAndreas Gohr
792bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, $sel
79375fa767dSAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
79475fa767dSAndreas Gohr                 WHERE $tlimit
79575fa767dSAndreas Gohr                   AND ua_type = 'browser'
79675fa767dSAndreas Gohr              GROUP BY $grp
79775fa767dSAndreas Gohr              ORDER BY cnt DESC, ua_info".
79875fa767dSAndreas Gohr              $this->sql_limit($start,$limit);
79975fa767dSAndreas Gohr        return $this->runSQL($sql);
80075fa767dSAndreas Gohr    }
80175fa767dSAndreas Gohr
802bd4217d3SAndreas Gohr    function sql_os($tlimit,$start=0,$limit=20){
803bd4217d3SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, os as osflag, os
804bd4217d3SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
805bd4217d3SAndreas Gohr                 WHERE $tlimit
806bd4217d3SAndreas Gohr                   AND ua_type = 'browser'
807bd4217d3SAndreas Gohr              GROUP BY os
808bd4217d3SAndreas Gohr              ORDER BY cnt DESC, os".
809bd4217d3SAndreas Gohr              $this->sql_limit($start,$limit);
810bd4217d3SAndreas Gohr        return $this->runSQL($sql);
811bd4217d3SAndreas Gohr    }
812bd4217d3SAndreas Gohr
813c73e16f1SAndreas Gohr    function sql_resolution($tlimit,$start=0,$limit=20){
814c73e16f1SAndreas Gohr        $sql = "SELECT COUNT(DISTINCT session) as cnt, CONCAT(screen_x,'x',screen_y) as res
815c73e16f1SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
816c73e16f1SAndreas Gohr                 WHERE $tlimit
817c73e16f1SAndreas Gohr                   AND ua_type  = 'browser'
818c73e16f1SAndreas Gohr                   AND screen_x != 0
819c73e16f1SAndreas Gohr              GROUP BY screen_x, screen_y
820c73e16f1SAndreas Gohr              ORDER BY cnt DESC, screen_x".
821c73e16f1SAndreas Gohr              $this->sql_limit($start,$limit);
822c73e16f1SAndreas Gohr        return $this->runSQL($sql);
823c73e16f1SAndreas Gohr    }
824c73e16f1SAndreas Gohr
825c73e16f1SAndreas Gohr    function sql_viewport($tlimit,$start=0,$limit=20,$x=true){
826c73e16f1SAndreas Gohr        if($x){
827c73e16f1SAndreas Gohr            $col = 'view_x';
828c73e16f1SAndreas Gohr            $res = 'res_x';
829c73e16f1SAndreas Gohr        }else{
830c73e16f1SAndreas Gohr            $col = 'view_y';
831c73e16f1SAndreas Gohr            $res = 'res_y';
832c73e16f1SAndreas Gohr        }
833c73e16f1SAndreas Gohr
834c73e16f1SAndreas Gohr        $sql = "SELECT COUNT(*) as cnt,
835c73e16f1SAndreas Gohr                       ROUND($col/10)*10 as $res
836c73e16f1SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."access as A
837c73e16f1SAndreas Gohr                 WHERE $tlimit
838c73e16f1SAndreas Gohr                   AND ua_type  = 'browser'
839c73e16f1SAndreas Gohr                   AND $col != 0
840c73e16f1SAndreas Gohr              GROUP BY $res
841c73e16f1SAndreas Gohr              ORDER BY cnt DESC, $res".
842c73e16f1SAndreas Gohr              $this->sql_limit($start,$limit);
843c73e16f1SAndreas Gohr        return $this->runSQL($sql);
844c73e16f1SAndreas Gohr    }
845c73e16f1SAndreas Gohr
84675fa767dSAndreas Gohr
84795eb68e6SAndreas Gohr    /**
84895eb68e6SAndreas Gohr     * Builds a limit clause
84995eb68e6SAndreas Gohr     */
85095eb68e6SAndreas Gohr    function sql_limit($start,$limit){
85195eb68e6SAndreas Gohr        $start = (int) $start;
85295eb68e6SAndreas Gohr        $limit = (int) $limit;
85395eb68e6SAndreas Gohr        if($limit){
8542507f8e0SAndreas Gohr            $limit += 1;
85595eb68e6SAndreas Gohr            return " LIMIT $start,$limit";
85695eb68e6SAndreas Gohr        }elseif($start){
85795eb68e6SAndreas Gohr            return " OFFSET $start";
85895eb68e6SAndreas Gohr        }
85995eb68e6SAndreas Gohr        return '';
86095eb68e6SAndreas Gohr    }
8611878f16fSAndreas Gohr
8621878f16fSAndreas Gohr    /**
86314d99ec0SAndreas Gohr     * Return a link to the DB, opening the connection if needed
8641878f16fSAndreas Gohr     */
86514d99ec0SAndreas Gohr    function dbLink(){
8661878f16fSAndreas Gohr        // connect to DB if needed
8671878f16fSAndreas Gohr        if(!$this->dblink){
8681878f16fSAndreas Gohr            $this->dblink = mysql_connect($this->getConf('db_server'),
8691878f16fSAndreas Gohr                                          $this->getConf('db_user'),
8701878f16fSAndreas Gohr                                          $this->getConf('db_password'));
8711878f16fSAndreas Gohr            if(!$this->dblink){
8721878f16fSAndreas Gohr                msg('DB Error: connection failed',-1);
8731878f16fSAndreas Gohr                return null;
8741878f16fSAndreas Gohr            }
8751878f16fSAndreas Gohr            // set utf-8
8761878f16fSAndreas Gohr            if(!mysql_db_query($this->getConf('db_database'),'set names utf8',$this->dblink)){
8771878f16fSAndreas Gohr                msg('DB Error: could not set UTF-8 ('.mysql_error($this->dblink).')',-1);
8781878f16fSAndreas Gohr                return null;
8791878f16fSAndreas Gohr            }
8801878f16fSAndreas Gohr        }
88114d99ec0SAndreas Gohr        return $this->dblink;
88214d99ec0SAndreas Gohr    }
8831878f16fSAndreas Gohr
88414d99ec0SAndreas Gohr    /**
88514d99ec0SAndreas Gohr     * Simple function to run a DB query
88614d99ec0SAndreas Gohr     */
88714d99ec0SAndreas Gohr    function runSQL($sql_string) {
88814d99ec0SAndreas Gohr        $link = $this->dbLink();
88914d99ec0SAndreas Gohr
89014d99ec0SAndreas Gohr        $result = mysql_db_query($this->conf['db_database'],$sql_string,$link);
89194171ff3SAndreas Gohr        if(!$result){
8922812a751SAndreas Gohr            msg('DB Error: '.mysql_error($link).' '.hsc($sql_string),-1);
8931878f16fSAndreas Gohr            return null;
8941878f16fSAndreas Gohr        }
8951878f16fSAndreas Gohr
8961878f16fSAndreas Gohr        $resultarray = array();
8971878f16fSAndreas Gohr
8981878f16fSAndreas Gohr        //mysql_db_query returns 1 on a insert statement -> no need to ask for results
8991878f16fSAndreas Gohr        if ($result != 1) {
9001878f16fSAndreas Gohr            for($i=0; $i< mysql_num_rows($result); $i++) {
9011878f16fSAndreas Gohr                $temparray = mysql_fetch_assoc($result);
9021878f16fSAndreas Gohr                $resultarray[]=$temparray;
9031878f16fSAndreas Gohr            }
9041878f16fSAndreas Gohr            mysql_free_result($result);
9051878f16fSAndreas Gohr        }
9061878f16fSAndreas Gohr
90714d99ec0SAndreas Gohr        if (mysql_insert_id($link)) {
90814d99ec0SAndreas Gohr            $resultarray = mysql_insert_id($link); //give back ID on insert
9091878f16fSAndreas Gohr        }
9101878f16fSAndreas Gohr
9111878f16fSAndreas Gohr        return $resultarray;
9121878f16fSAndreas Gohr    }
9131878f16fSAndreas Gohr
9141878f16fSAndreas Gohr    /**
91514d99ec0SAndreas Gohr     * Returns a short name for a User Agent and sets type, version and os info
9161878f16fSAndreas Gohr     */
91714d99ec0SAndreas Gohr    function ua_info($ua,&$type,&$ver,&$os){
91814d99ec0SAndreas Gohr        $ua = strtr($ua,' +','__');
91914d99ec0SAndreas Gohr        $ua = strtolower($ua);
92014d99ec0SAndreas Gohr
92114d99ec0SAndreas Gohr        // common browsers
92214d99ec0SAndreas Gohr        $regvermsie     = '/msie([+_ ]|)([\d\.]*)/i';
92314d99ec0SAndreas Gohr        $regvernetscape = '/netscape.?\/([\d\.]*)/i';
92414d99ec0SAndreas Gohr        $regverfirefox  = '/firefox\/([\d\.]*)/i';
92514d99ec0SAndreas Gohr        $regversvn      = '/svn\/([\d\.]*)/i';
92614d99ec0SAndreas Gohr        $regvermozilla  = '/mozilla(\/|)([\d\.]*)/i';
92714d99ec0SAndreas Gohr        $regnotie       = '/webtv|omniweb|opera/i';
92814d99ec0SAndreas Gohr        $regnotnetscape = '/gecko|compatible|opera|galeon|safari/i';
92914d99ec0SAndreas Gohr
93014d99ec0SAndreas Gohr        $name = '';
93114d99ec0SAndreas Gohr        # IE ?
93214d99ec0SAndreas Gohr        if(preg_match($regvermsie,$ua,$m) && !preg_match($regnotie,$ua)){
93314d99ec0SAndreas Gohr            $type = 'browser';
93414d99ec0SAndreas Gohr            $ver  = $m[2];
93514d99ec0SAndreas Gohr            $name = 'msie';
93614d99ec0SAndreas Gohr        }
93714d99ec0SAndreas Gohr        # Firefox ?
93814d99ec0SAndreas Gohr        elseif (preg_match($regverfirefox,$ua,$m)){
93914d99ec0SAndreas Gohr            $type = 'browser';
94014d99ec0SAndreas Gohr            $ver  = $m[1];
94114d99ec0SAndreas Gohr            $name = 'firefox';
94214d99ec0SAndreas Gohr        }
94314d99ec0SAndreas Gohr        # Subversion ?
94414d99ec0SAndreas Gohr        elseif (preg_match($regversvn,$ua,$m)){
94514d99ec0SAndreas Gohr            $type = 'rcs';
94614d99ec0SAndreas Gohr            $ver  = $m[1];
94714d99ec0SAndreas Gohr            $name = 'svn';
94814d99ec0SAndreas Gohr        }
94914d99ec0SAndreas Gohr        # Netscape 6.x, 7.x ... ?
95014d99ec0SAndreas Gohr        elseif (preg_match($regvernetscape,$ua,$m)){
95114d99ec0SAndreas Gohr            $type = 'browser';
95214d99ec0SAndreas Gohr            $ver  = $m[1];
95314d99ec0SAndreas Gohr            $name = 'netscape';
95414d99ec0SAndreas Gohr        }
95514d99ec0SAndreas Gohr        # Netscape 3.x, 4.x ... ?
95614d99ec0SAndreas Gohr        elseif(preg_match($regvermozilla,$ua,$m) && !preg_match($regnotnetscape,$ua)){
95714d99ec0SAndreas Gohr            $type = 'browser';
95814d99ec0SAndreas Gohr            $ver  = $m[2];
95914d99ec0SAndreas Gohr            $name = 'netscape';
96014d99ec0SAndreas Gohr        }else{
96114d99ec0SAndreas Gohr            include(dirname(__FILE__).'/inc/browsers.php');
96214d99ec0SAndreas Gohr            foreach($BrowsersSearchIDOrder as $regex){
96314d99ec0SAndreas Gohr                if(preg_match('/'.$regex.'/',$ua)){
96414d99ec0SAndreas Gohr                    // it's a browser!
96514d99ec0SAndreas Gohr                    $type = 'browser';
96614d99ec0SAndreas Gohr                    $name = strtolower($regex);
96714d99ec0SAndreas Gohr                    break;
96814d99ec0SAndreas Gohr                }
96914d99ec0SAndreas Gohr            }
97014d99ec0SAndreas Gohr        }
97114d99ec0SAndreas Gohr
97275fa767dSAndreas Gohr        // check versions for Safari and Opera
97375fa767dSAndreas Gohr        if($name == 'safari'){
97475fa767dSAndreas Gohr            if(preg_match('/safari\/([\d\.]*)/i',$ua,$match)){
97575fa767dSAndreas Gohr                $ver = $BrowsersSafariBuildToVersionHash[$match[1]];
97675fa767dSAndreas Gohr            }
97775fa767dSAndreas Gohr        }elseif($name == 'opera'){
97875fa767dSAndreas Gohr            if(preg_match('/opera[\/ ]([\d\.]*)/i',$ua,$match)){
97975fa767dSAndreas Gohr                $ver = $match[1];
98075fa767dSAndreas Gohr            }
98175fa767dSAndreas Gohr        }
98275fa767dSAndreas Gohr
98375fa767dSAndreas Gohr
98414d99ec0SAndreas Gohr        // check OS for browsers
98514d99ec0SAndreas Gohr        if($type == 'browser'){
98614d99ec0SAndreas Gohr            include(dirname(__FILE__).'/inc/operating_systems.php');
98714d99ec0SAndreas Gohr            foreach($OSSearchIDOrder as $regex){
98814d99ec0SAndreas Gohr                if(preg_match('/'.$regex.'/',$ua)){
98914d99ec0SAndreas Gohr                    $os = $OSHashID[$regex];
99014d99ec0SAndreas Gohr                    break;
99114d99ec0SAndreas Gohr                }
99214d99ec0SAndreas Gohr            }
99314d99ec0SAndreas Gohr
99414d99ec0SAndreas Gohr        }
99514d99ec0SAndreas Gohr
99614d99ec0SAndreas Gohr        // are we done now?
99714d99ec0SAndreas Gohr        if($name) return $name;
99814d99ec0SAndreas Gohr
99914d99ec0SAndreas Gohr        include(dirname(__FILE__).'/inc/robots.php');
100014d99ec0SAndreas Gohr        foreach($RobotsSearchIDOrder as $regex){
100114d99ec0SAndreas Gohr            if(preg_match('/'.$regex.'/',$ua)){
100214d99ec0SAndreas Gohr                    // it's a robot!
100314d99ec0SAndreas Gohr                    $type = 'robot';
100414d99ec0SAndreas Gohr                    return strtolower($regex);
100514d99ec0SAndreas Gohr            }
100614d99ec0SAndreas Gohr        }
100714d99ec0SAndreas Gohr
100814d99ec0SAndreas Gohr        // dunno
10091878f16fSAndreas Gohr        return '';
10101878f16fSAndreas Gohr    }
10111878f16fSAndreas Gohr
10121878f16fSAndreas Gohr    /**
1013322de360SAndreas Gohr     * Log search queries
101414d99ec0SAndreas Gohr     */
101514d99ec0SAndreas Gohr    function log_search($referer,&$type){
101614d99ec0SAndreas Gohr        $referer = strtolower($referer);
1017673875b1SAndreas Gohr        $ref     = strtr($referer,' +','__');
101814d99ec0SAndreas Gohr
101914d99ec0SAndreas Gohr        include(dirname(__FILE__).'/inc/search_engines.php');
102014d99ec0SAndreas Gohr
102114d99ec0SAndreas Gohr        foreach($SearchEnginesSearchIDOrder as $regex){
1022673875b1SAndreas Gohr            if(preg_match('/'.$regex.'/',$ref)){
102314d99ec0SAndreas Gohr                if(!$NotSearchEnginesKeys[$regex] ||
1024673875b1SAndreas Gohr                   !preg_match('/'.$NotSearchEnginesKeys[$regex].'/',$ref)){
102514d99ec0SAndreas Gohr                    // it's a search engine!
102614d99ec0SAndreas Gohr                    $type = 'search';
102714d99ec0SAndreas Gohr                    break;
102814d99ec0SAndreas Gohr                }
102914d99ec0SAndreas Gohr            }
103014d99ec0SAndreas Gohr        }
103114d99ec0SAndreas Gohr        if($type != 'search') return; // we're done here
103214d99ec0SAndreas Gohr
1033322de360SAndreas Gohr        // extract query
1034322de360SAndreas Gohr        $engine = $SearchEnginesHashID[$regex];
1035322de360SAndreas Gohr        $param = $SearchEnginesKnownUrl[$engine];
1036322de360SAndreas Gohr        if($param && preg_match('/'.$param.'(.*?)[&$]/',$referer,$match)){
1037322de360SAndreas Gohr            $query = array_pop($match);
1038322de360SAndreas Gohr        }elseif(preg_match('/'.$WordsToExtractSearchUrl.'(.*?)[&$]/',$referer,$match)){
1039322de360SAndreas Gohr            $query = array_pop($match);
1040322de360SAndreas Gohr        }
1041322de360SAndreas Gohr        if(!$query) return; // we failed
1042322de360SAndreas Gohr
1043322de360SAndreas Gohr        // clean the query
1044322de360SAndreas Gohr        $query = preg_replace('/^(cache|related):[^\+]+/','',$query);  // non-search queries
1045322de360SAndreas Gohr        $query = preg_replace('/%0[ad]/',' ',$query);                  // LF CR
1046322de360SAndreas Gohr        $query = preg_replace('/%2[02789abc]/',' ',$query);            // space " ' ( ) * + ,
1047322de360SAndreas Gohr        $query = preg_replace('/%3a/',' ',$query);                     // :
1048673875b1SAndreas Gohr        $query = strtr($query,'+\'()"*,:','        ');                 // badly encoded
1049322de360SAndreas Gohr        $query = preg_replace('/ +/',' ',$query);                      // ws compact
1050322de360SAndreas Gohr        $query = trim($query);
1051322de360SAndreas Gohr        $query = urldecode($query);
1052322de360SAndreas Gohr        if(!utf8_check($query)) $query = utf8_encode($query);          // assume latin1 if not utf8
1053322de360SAndreas Gohr        $query = utf8_strtolower($query);
1054322de360SAndreas Gohr
1055322de360SAndreas Gohr        // log it!
1056322de360SAndreas Gohr        $page  = addslashes($_REQUEST['p']);
1057322de360SAndreas Gohr        $query = addslashes($query);
1058673875b1SAndreas Gohr        $sql  = "INSERT INTO ".$this->getConf('db_prefix')."search
1059322de360SAndreas Gohr                    SET dt       = NOW(),
1060322de360SAndreas Gohr                        page     = '$page',
1061322de360SAndreas Gohr                        query    = '$query',
1062322de360SAndreas Gohr                        engine   = '$engine'";
1063322de360SAndreas Gohr        $id = $this->runSQL($sql);
1064322de360SAndreas Gohr        if(is_null($id)){
1065322de360SAndreas Gohr            global $MSG;
1066322de360SAndreas Gohr            print_r($MSG);
1067322de360SAndreas Gohr            return;
1068322de360SAndreas Gohr        }
1069322de360SAndreas Gohr
1070322de360SAndreas Gohr        // log single keywords
1071322de360SAndreas Gohr        $words = explode(' ',utf8_stripspecials($query,' ','\._\-:\*'));
1072322de360SAndreas Gohr        foreach($words as $word){
1073673875b1SAndreas Gohr            if(!$word) continue;
1074322de360SAndreas Gohr            $word = addslashes($word);
1075322de360SAndreas Gohr            $sql = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."searchwords
1076322de360SAndreas Gohr                       SET sid  = $id,
1077322de360SAndreas Gohr                           word = '$word'";
1078322de360SAndreas Gohr            $ok = $this->runSQL($sql);
1079322de360SAndreas Gohr            if(is_null($ok)){
1080322de360SAndreas Gohr                global $MSG;
1081322de360SAndreas Gohr                print_r($MSG);
1082322de360SAndreas Gohr            }
1083322de360SAndreas Gohr        }
108414d99ec0SAndreas Gohr    }
108514d99ec0SAndreas Gohr
108614d99ec0SAndreas Gohr    /**
108714d99ec0SAndreas Gohr     * Resolve IP to country/city
108814d99ec0SAndreas Gohr     */
108914d99ec0SAndreas Gohr    function log_ip($ip){
109014d99ec0SAndreas Gohr        // check if IP already known and up-to-date
109114d99ec0SAndreas Gohr        $sql = "SELECT ip
109214d99ec0SAndreas Gohr                  FROM ".$this->getConf('db_prefix')."iplocation
109314d99ec0SAndreas Gohr                 WHERE ip ='".addslashes($ip)."'
109414d99ec0SAndreas Gohr                   AND lastupd > DATE_SUB(CURDATE(),INTERVAL 30 DAY)";
109514d99ec0SAndreas Gohr        $result = $this->runSQL($sql);
109614d99ec0SAndreas Gohr        if($result[0]['ip']) return;
109714d99ec0SAndreas Gohr
109814d99ec0SAndreas Gohr        $http = new DokuHTTPClient();
109914d99ec0SAndreas Gohr        $http->timeout = 10;
110014d99ec0SAndreas Gohr        $data = $http->get('http://api.hostip.info/get_html.php?ip='.$ip);
110114d99ec0SAndreas Gohr
110214d99ec0SAndreas Gohr        if(preg_match('/^Country: (.*?) \((.*?)\)\nCity: (.*?)$/s',$data,$match)){
110314d99ec0SAndreas Gohr            $country = addslashes(trim($match[1]));
110414d99ec0SAndreas Gohr            $code    = addslashes(strtolower(trim($match[2])));
110514d99ec0SAndreas Gohr            $city    = addslashes(trim($match[3]));
110614d99ec0SAndreas Gohr            $host    = addslashes(gethostbyaddr($ip));
110714d99ec0SAndreas Gohr            $ip      = addslashes($ip);
110814d99ec0SAndreas Gohr
110914d99ec0SAndreas Gohr            $sql = "REPLACE INTO ".$this->getConf('db_prefix')."iplocation
111014d99ec0SAndreas Gohr                        SET ip = '$ip',
111114d99ec0SAndreas Gohr                            country = '$country',
111214d99ec0SAndreas Gohr                            code    = '$code',
111314d99ec0SAndreas Gohr                            city    = '$city',
111414d99ec0SAndreas Gohr                            host    = '$host'";
111514d99ec0SAndreas Gohr            $this->runSQL($sql);
111614d99ec0SAndreas Gohr        }
111714d99ec0SAndreas Gohr    }
111814d99ec0SAndreas Gohr
111914d99ec0SAndreas Gohr    /**
1120e25286daSAndreas Gohr     * log a click on an external link
1121e25286daSAndreas Gohr     *
1122e25286daSAndreas Gohr     * called from log.php
1123e25286daSAndreas Gohr     */
1124e25286daSAndreas Gohr    function log_outgoing(){
1125e25286daSAndreas Gohr        if(!$_REQUEST['ol']) return;
1126e25286daSAndreas Gohr
1127e25286daSAndreas Gohr        $link_md5 = md5($link);
1128e25286daSAndreas Gohr        $link     = addslashes($_REQUEST['ol']);
1129e25286daSAndreas Gohr        $session  = addslashes(session_id());
1130d8c4d85eSAndreas Gohr        $page     = addslashes($_REQUEST['p']);
1131e25286daSAndreas Gohr
1132e25286daSAndreas Gohr        $sql  = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."outlinks
1133e25286daSAndreas Gohr                    SET dt       = NOW(),
1134e25286daSAndreas Gohr                        session  = '$session',
1135d8c4d85eSAndreas Gohr                        page     = '$page',
1136e25286daSAndreas Gohr                        link_md5 = '$link_md5',
1137e25286daSAndreas Gohr                        link     = '$link'";
1138e25286daSAndreas Gohr        $ok = $this->runSQL($sql);
1139e25286daSAndreas Gohr        if(is_null($ok)){
1140e25286daSAndreas Gohr            global $MSG;
1141e25286daSAndreas Gohr            print_r($MSG);
1142e25286daSAndreas Gohr        }
1143e25286daSAndreas Gohr    }
1144e25286daSAndreas Gohr
1145e25286daSAndreas Gohr    /**
11461878f16fSAndreas Gohr     * log a page access
11471878f16fSAndreas Gohr     *
11481878f16fSAndreas Gohr     * called from log.php
11491878f16fSAndreas Gohr     */
11501878f16fSAndreas Gohr    function log_access(){
115194171ff3SAndreas Gohr        if(!$_REQUEST['p']) return;
115294171ff3SAndreas Gohr
115314d99ec0SAndreas Gohr        # FIXME check referer against blacklist and drop logging for bad boys
115414d99ec0SAndreas Gohr
115514d99ec0SAndreas Gohr        // handle referer
115614d99ec0SAndreas Gohr        $referer = trim($_REQUEST['r']);
115714d99ec0SAndreas Gohr        if($referer){
115814d99ec0SAndreas Gohr            $ref     = addslashes($referer);
115914d99ec0SAndreas Gohr            $ref_md5 = ($ref) ? md5($referer) : '';
116014d99ec0SAndreas Gohr            if(strpos($referer,DOKU_URL) === 0){
116114d99ec0SAndreas Gohr                $ref_type = 'internal';
116214d99ec0SAndreas Gohr            }else{
116314d99ec0SAndreas Gohr                $ref_type = 'external';
116414d99ec0SAndreas Gohr                $this->log_search($referer,$ref_type);
116514d99ec0SAndreas Gohr            }
116614d99ec0SAndreas Gohr        }else{
116714d99ec0SAndreas Gohr            $ref      = '';
116814d99ec0SAndreas Gohr            $ref_md5  = '';
116914d99ec0SAndreas Gohr            $ref_type = '';
117014d99ec0SAndreas Gohr        }
117114d99ec0SAndreas Gohr
117214d99ec0SAndreas Gohr        // handle user agent
117314d99ec0SAndreas Gohr        $agent   = trim($_SERVER['HTTP_USER_AGENT']);
117414d99ec0SAndreas Gohr
117514d99ec0SAndreas Gohr        $ua      = addslashes($agent);
117614d99ec0SAndreas Gohr        $ua_type = '';
117714d99ec0SAndreas Gohr        $ua_ver  = '';
117814d99ec0SAndreas Gohr        $os      = '';
117914d99ec0SAndreas Gohr        $ua_info = addslashes($this->ua_info($agent,$ua_type,$ua_ver,$os));
118014d99ec0SAndreas Gohr
11811878f16fSAndreas Gohr        $page    = addslashes($_REQUEST['p']);
11821878f16fSAndreas Gohr        $ip      = addslashes($_SERVER['REMOTE_ADDR']);
11831878f16fSAndreas Gohr        $sx      = (int) $_REQUEST['sx'];
11841878f16fSAndreas Gohr        $sy      = (int) $_REQUEST['sy'];
11851878f16fSAndreas Gohr        $vx      = (int) $_REQUEST['vx'];
11861878f16fSAndreas Gohr        $vy      = (int) $_REQUEST['vy'];
118775fa767dSAndreas Gohr        $js      = (int) $_REQUEST['js'];
11883c0acc14SAndreas Gohr        $uid     = addslashes($_REQUEST['uid']);
11891878f16fSAndreas Gohr        $user    = addslashes($_SERVER['REMOTE_USER']);
11901878f16fSAndreas Gohr        $session = addslashes(session_id());
11913c0acc14SAndreas Gohr        if(!$uid) $uid = $session;
11921878f16fSAndreas Gohr
119394171ff3SAndreas Gohr        $sql  = "INSERT DELAYED INTO ".$this->getConf('db_prefix')."access
119475fa767dSAndreas Gohr                    SET dt       = NOW(),
119575fa767dSAndreas Gohr                        page     = '$page',
11961878f16fSAndreas Gohr                        ip       = '$ip',
11971878f16fSAndreas Gohr                        ua       = '$ua',
11981878f16fSAndreas Gohr                        ua_info  = '$ua_info',
119914d99ec0SAndreas Gohr                        ua_type  = '$ua_type',
120014d99ec0SAndreas Gohr                        ua_ver   = '$ua_ver',
120114d99ec0SAndreas Gohr                        os       = '$os',
12021878f16fSAndreas Gohr                        ref      = '$ref',
120394171ff3SAndreas Gohr                        ref_md5  = '$ref_md5',
120414d99ec0SAndreas Gohr                        ref_type = '$ref_type',
12051878f16fSAndreas Gohr                        screen_x = '$sx',
12061878f16fSAndreas Gohr                        screen_y = '$sy',
12071878f16fSAndreas Gohr                        view_x   = '$vx',
12081878f16fSAndreas Gohr                        view_y   = '$vy',
120975fa767dSAndreas Gohr                        js       = '$js',
12101878f16fSAndreas Gohr                        user     = '$user',
12113c0acc14SAndreas Gohr                        session  = '$session',
12123c0acc14SAndreas Gohr                        uid      = '$uid'";
12131878f16fSAndreas Gohr        $ok = $this->runSQL($sql);
12141878f16fSAndreas Gohr        if(is_null($ok)){
12151878f16fSAndreas Gohr            global $MSG;
12161878f16fSAndreas Gohr            print_r($MSG);
12171878f16fSAndreas Gohr        }
121814d99ec0SAndreas Gohr
121914d99ec0SAndreas Gohr        // resolve the IP
122014d99ec0SAndreas Gohr        $this->log_ip($_SERVER['REMOTE_ADDR']);
12211878f16fSAndreas Gohr    }
12221878f16fSAndreas Gohr
12231878f16fSAndreas Gohr    /**
12241878f16fSAndreas Gohr     * Just send a 1x1 pixel blank gif to the browser
12251878f16fSAndreas Gohr     *
12261878f16fSAndreas Gohr     * @called from log.php
12271878f16fSAndreas Gohr     *
12281878f16fSAndreas Gohr     * @author Andreas Gohr <andi@splitbrain.org>
12291878f16fSAndreas Gohr     * @author Harry Fuecks <fuecks@gmail.com>
12301878f16fSAndreas Gohr     */
12311878f16fSAndreas Gohr    function sendGIF(){
12321878f16fSAndreas Gohr        $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7');
12331878f16fSAndreas Gohr        header('Content-Type: image/gif');
12341878f16fSAndreas Gohr        header('Content-Length: '.strlen($img));
12351878f16fSAndreas Gohr        header('Connection: Close');
12361878f16fSAndreas Gohr        print $img;
12371878f16fSAndreas Gohr        flush();
12381878f16fSAndreas Gohr        // Browser should drop connection after this
12391878f16fSAndreas Gohr        // Thinks it's got the whole image
12401878f16fSAndreas Gohr    }
12411878f16fSAndreas Gohr
12421878f16fSAndreas Gohr}
1243