1<?php
2// must be run within Dokuwiki
3if(!defined('DOKU_INC')) die();
4define('BB2_CWD', dirname(__FILE__));
5
6if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
7require_once(DOKU_PLUGIN.'admin.php');
8
9require_once(BB2_CWD.'/bad-behavior/responses.inc.php');
10
11/**
12 * All DokuWiki plugins to extend the admin function
13 * need to inherit from this class
14 */
15class admin_plugin_badbehaviour extends DokuWiki_Admin_Plugin {
16
17    /**
18     * return some info
19     */
20    function getInfo(){
21        return confToHash(dirname(__FILE__).'/plugin.info.txt');
22    }
23
24    /**
25     * Access for managers allowed
26     */
27    function forAdminOnly(){
28        return false;
29    }
30
31    /**
32     * return sort order for position in admin menu
33     */
34    function getMenuSort() {
35        return 140;
36    }
37
38    /**
39     * handle user request
40     */
41    function handle() {
42    }
43
44    /**
45     * output appropriate html
46     */
47    function html() {
48        if($_REQUEST['lookup']){
49            $this->_lookup($_REQUEST['lookup']);
50        }else{
51            $this->_stats();
52        }
53
54        echo $this->_lookupform();
55    }
56
57    function _stats(){
58        print $this->locale_xhtml('stats');
59
60        $days = 7;
61        $list = $this->_readlines($days);
62
63        $all = 0;
64        $stats = array();
65        foreach($list as $line){
66            if(!$line) continue;
67            $data = explode("\t",$line);
68            $stats[$data[6]] = (int) $stats[$data[6]] + 1;
69            $all++;
70        }
71        arsort($stats);
72
73        printf('<p><b>'.$this->getLang('blocked').'</b></p>',$all,$days);
74
75        echo '<table class="inline">';
76        echo '<tr>';
77        echo '<th>'.$this->getLang('percent').'</th>';
78        echo '<th>'.$this->getLang('count').'</th>';
79        echo '<th>'.$this->getLang('reason').'</th>';
80        echo '</tr>';
81        foreach($stats as $code => $count){
82            $resp = bb2_get_response($code);
83            echo '<tr>';
84            echo '<td>';
85            printf("%.2f%%",100*$count/$all);
86            echo '</td>';
87            echo '<td>';
88            echo $count;
89            echo '</td>';
90            echo '<td>';
91            echo $resp['log'];
92            echo '</td>';
93            echo '</tr>';
94        }
95        echo '</table>';
96    }
97
98    function _lookup($key){
99        global $ID;
100        global $conf;
101        global $lang;
102
103        print $this->locale_xhtml('lookup');
104
105        $code = str_replace('-','',$key);
106        $ip   = hexdec(substr($code,0,2)).'.'.
107                hexdec(substr($code,2,2)).'.'.
108                hexdec(substr($code,4,2)).'.'.
109                hexdec(substr($code,6,2));
110        $code = substr($code,8);
111
112        $resp = bb2_get_response($code);
113        printf('<p>'.$this->getLang('lkpresult').'</p>',
114               $ip,$resp['log'],$resp['explanation'],hsc($key));
115
116        printf('<p>'.$this->getLang('lkplist').'</p>',7);
117
118        $lines = preg_grep('/'.preg_quote($ip).'/',$this->_readlines());
119        if(count($lines)){
120            echo '<table class="inline">';
121            foreach($lines as $line){
122                $fields = explode("\t",$line);
123                $resp = bb2_get_response($fields[6]);
124                echo '<tr>';
125                echo '<td>'.strftime($conf['dformat'],$fields[0]).'</td>';
126                echo '<td>'.hsc($fields[1]).'</td>';
127                echo '<td>'.hsc($fields[2]).'</td>';
128                echo '<td>'.hsc($fields[3]).'</td>';
129                echo '<td>'.hsc($fields[4]).'</td>';
130                echo '<td>'.hsc($fields[5]).'</td>';
131                echo '<td>'.$resp['log'].'</td>';
132                echo '</tr>';
133            }
134            echo '</table>';
135        }else{
136            echo '<p><i>'.$lang['nothingfound'].'</i></p>';
137        }
138    }
139
140    function _lookupform(){
141        global $lang;
142        echo '<div>';
143        echo '<form action="" method="get">';
144        echo '<input type="hidden" name="do" value="admin" />';
145        echo '<input type="hidden" name="page" value="badbehaviour" />';
146        echo '<label for="key__lookup">'.$this->getLang('lookup').':</label> ';
147        echo '<input type="text" id="key__lookup" name="lookup" value="'.hsc($_REQUEST['lookup']).'" />';
148        echo '<input type="submit" value="'.$lang['btn_search'].'" class="button" />';
149        echo '</form>';
150        echo '</div>';
151    }
152
153    /**
154     * Read loglines backward
155     */
156    function _readlines($days=7){
157        global $conf;
158        $file = $conf['cachedir'].'/badbehaviour.log';
159
160        $date  = time() - ($days*24*60*60);
161
162        $data  = array();
163        $lines = array();
164        $chunk_size = 8192;
165
166        if (!@file_exists($file)) return $data;
167        $fp = fopen($file, 'rb');
168        if ($fp===false) return $data;
169
170        //seek to end
171        fseek($fp, 0, SEEK_END);
172        $pos = ftell($fp);
173        $chunk = '';
174
175        while($pos){
176
177            // how much to read? Set pointer
178            if($pos > $chunk_size){
179                $pos -= $chunk_size;
180                $read = $chunk_size;
181            }else{
182                $read = $pos;
183                $pos  = 0;
184            }
185            fseek($fp,$pos);
186
187            $tmp = fread($fp,$read);
188            if($tmp === false) break;
189            $chunk = $tmp.$chunk;
190
191            // now split the chunk
192            $cparts = explode("\n",$chunk);
193
194            // keep the first part in chunk (may be incomplete)
195            if($pos) $chunk = array_shift($cparts);
196
197            // no more parts available, read on
198            if(!count($cparts)) continue;
199
200            // put the new lines on the stack
201            $lines = array_merge($cparts,$lines);
202
203            // check date of first line:
204            list($cdate) = explode("\t",$cparts[0]);
205            if($cdate < $date) break; // we have enough
206        }
207        fclose($fp);
208
209        return $lines;
210    }
211}
212//Setup VIM: ex: et ts=4 :
213