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