Advertisement
dbfoxtw

pixmicat mod_adminenhance special edition by dbfox

Feb 18th, 2013
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 13.18 KB | None | 0 0
  1. <?php
  2. class mod_adminenhance{
  3.     var $mypage;
  4.     var $ipfile, $imgfile;
  5.  
  6.     function mod_adminenhance(){
  7.         global $PMS;
  8.         $PMS->hookModuleMethod('ModulePage', __CLASS__);
  9.         $this->mypage = $PMS->getModulePageURL(__CLASS__);
  10.         $this->ipfile = '.ht_blacklist'; $this->imgfile = '.ht_md5list';
  11.         $this->wordfile = '.ht_wordlist';
  12.     }
  13.  
  14.     function getModuleName(){
  15.         return 'mod_adminenhance : 管理工具增強組合包+自改';
  16.     }
  17.  
  18.     function getModuleVersionInfo(){
  19.         return '4th.Release.4-dev (b090131) - (100626)整合siokara強制sage功能 - (120819)整合擋字功能';
  20.     }
  21.  
  22.     /* 從資料檔抓出資料 */
  23.     function _parseBlackListFile($fname, $only1st=false){
  24.         if(!is_file($fname)) return array();
  25.         $l = file($fname);
  26.         $r = array(); $autodelno = array();
  27.         $tmp = '';
  28.         $now = time();
  29.         for($i = 0, $len = count($l); $i < $len; $i++){
  30.             $tmp = explode("\t", rtrim($l[$i]));
  31.             if(isset($tmp[3]) && $tmp[3] != '0'){ // 封鎖時段已過
  32.                 if($tmp[2] + intval($tmp[3]) * 86400 < $now){
  33.                     $autodelno[] = $i;
  34.                     continue;
  35.                 }
  36.             }
  37.             $r[] = $only1st ? $tmp[0] : $tmp;
  38.         }
  39.         if(count($autodelno)) $this->_arrangeRecord($this->ipfile, $autodelno, ''); // 進行清除動作
  40.         return $r;
  41.     }
  42.  
  43.     /* 重新整理記錄檔內容 (同步進行刪除及新增動作) */
  44.     function _arrangeRecord($fname, $arrDel, $newline){
  45.         $line = is_file($fname) ? file($fname) : array();
  46.         if(is_array($arrDel)) foreach($arrDel as $delid) unset($line[$delid]); // 刪除
  47.         $line = implode('', $line).$newline;
  48.         $fp = fopen($fname, 'w');
  49.         fwrite($fp, $line);
  50.         fclose($fp);
  51.     }
  52.  
  53.     /* 在前端管理顯示 Hostname */
  54.     function _showHostString(&$arrLabels, $post, $isReply){
  55.         $arrLabels['{$NOW}'] .= " <u>{$post['host']}</u>";
  56.     }
  57.  
  58.     /* 封鎖黑名單管理頁面插入CSS & JS */
  59.     function _hookHeadCSS(&$style, $isReply){
  60.         $style .= '<style type="text/css">
  61. .dos_list_short {
  62.     height: 150px;
  63.     width: 800px;
  64.     overflow: auto;
  65.     background: #e9f5ff;
  66.     border: 1px solid #666;
  67. }
  68. </style>
  69. <script type="text/javascript">
  70. // <![CDATA[
  71. function add(form){
  72.     var op = form.operate.value, ndata = form.newdata.value, nperiod = form.newperiod.value, ndesc = form.newdesc.value;
  73.     $.post("'.str_replace('&amp;', '&', $this->mypage).'", {operate: op, newdata: ndata, newperiod: nperiod, newdesc: ndesc, ajax: true}, function(d){
  74.         var l, lastno = (l = $("input:checkbox:last", form).get(0)) ? parseInt(l.value) + 1 : 0;
  75.         $("table", form).append(d.replace("#NO#", lastno));
  76.         form.newdata.value = form.newdesc.value = "";
  77.     });
  78.     return false;
  79. }
  80. // ]]>
  81. </script>
  82. ';
  83.     }
  84.  
  85.     function autoHookRegistBegin(){
  86.         global $BANPATTERN, $BAD_FILEMD5, $BAD_STRING;
  87.         // 載入封鎖黑名單定義檔
  88.         if(is_file($this->ipfile)) $BANPATTERN = array_merge($BANPATTERN, array_map('rtrim', $this->_parseBlackListFile($this->ipfile, true)));
  89.         if(is_file($this->imgfile)) $BAD_FILEMD5 = array_merge($BAD_FILEMD5, array_map('rtrim', $this->_parseBlackListFile($this->imgfile, true)));
  90.         if(is_file($this->wordfile)) $BAD_STRING = array_merge($BAD_STRING, array_map('rtrim', $this->_parseBlackListFile($this->wordfile, true)));
  91.     }
  92.  
  93.     function autoHookAdminFunction($action, &$param, $funcLabel, &$message){
  94.         global $PIO, $PMS;
  95.         if($action=='add'){
  96.             // Manual hook: showing hostname of users
  97.             $PMS->hookModuleMethod('ThreadPost', array(&$this, '_showHostString'));
  98.             $PMS->hookModuleMethod('ThreadReply', array(&$this, '_showHostString'));
  99.  
  100.             $param[] = array('mod_adminenhance_thstop', 'AE: 停止/恢復討論串');
  101.             $param[] = array('mod_adminenhance_thsage', 'AE: 強制SAGE/恢復討論串');
  102.             $param[] = array('mod_adminenhance_banip', 'AE: IP 加到黑名單 (鎖 Class C)');
  103.             $param[] = array('mod_adminenhance_banimg', 'AE: 圖檔 MD5 加到黑名單');
  104.             return;
  105.         }
  106.  
  107.         switch($funcLabel){
  108.             case 'mod_adminenhance_thstop':
  109.                 $infectThreads = array();
  110.                 foreach($PIO->fetchPosts($param) as $th){
  111.                     if($th['resto']) continue; // 是回應
  112.                     $infectThreads[] = $th['no'];
  113.                     $flgh = $PIO->getPostStatus($th['status']);
  114.                     $flgh->toggle('TS');
  115.                     $PIO->setPostStatus($th['no'], $flgh->toString());
  116.                 }
  117.                 $PIO->dbCommit();
  118.                 $message .= '停止/恢復討論串 (No.'.implode(', ', $infectThreads).') 完成<br />';
  119.                 break;
  120.             case 'mod_adminenhance_thsage':
  121.                 $infectThreads = array();
  122.                 foreach($PIO->fetchPosts($param) as $th){
  123.                     if($th['resto']) continue; // 是回應
  124.                     $infectThreads[] = $th['no'];
  125.                     $flgh = $PIO->getPostStatus($th['status']);
  126.                     $flgh->toggle('asage');
  127.                     $PIO->setPostStatus($th['no'], $flgh->toString());
  128.                 }
  129.                 $PIO->dbCommit();
  130.                 $message .= '強制SAGE/恢復討論串 (No.'.implode(', ', $infectThreads).') 完成<br />';
  131.                 break;
  132.             case 'mod_adminenhance_banip':
  133.                 $fp = fopen($this->ipfile, 'a');
  134.                 foreach($PIO->fetchPosts($param) as $th){
  135.                     if(($IPaddr = gethostbyname($th['host'])) != $th['host']) $IPaddr .= '/24';
  136.                     fwrite($fp, $IPaddr."\t\t".time()."\t0\n");
  137.                 }
  138.                 fclose($fp);
  139.                 $message .= 'IP 黑名單更新完成<br />';
  140.                 break;
  141.             case 'mod_adminenhance_banimg':
  142.                 $fp = fopen($this->imgfile, 'a');
  143.                 foreach($PIO->fetchPosts($param) as $th){
  144.                     if($th['md5chksum']) fwrite($fp, $th['md5chksum']."\n");
  145.                 }
  146.                 fclose($fp);
  147.                 $message .= '圖檔黑名單更新完成<br />';
  148.                 break;
  149.             default:
  150.         }
  151.     }
  152.    
  153.     function autoHookPostInfo(&$postinfo){
  154.         $postinfo .= "<li>本版因各種原因有鎖關鍵字,請至<a href='".$this->mypage."&amp;action=listwords' rel='_blank'>字詞黑名單一覽</a>查詢。</li>\n";
  155.     }
  156.  
  157.     function autoHookLinksAboveBar(&$link, $pageId, $addinfo=false){
  158.         if($pageId == 'admin' && $addinfo == true)
  159.             $link .= '[<a href="'.$this->mypage.'">封鎖黑名單管理</a>]';
  160.     }
  161.    
  162.         function autoHookThreadPost(&$arrLabels, $post, $isReply){
  163.         global $PIO;
  164.         $fh = new FlagHelper($post['status']);
  165.         if($fh->value('asage')) { // 強制sage
  166.             if($arrLabels['{$COM}']) $arrLabels['{$WARN_ENDREPLY}'].='<span class="warn_txt">此討論串已被強制sage,可繼續留言但不會浮上去。<br/></span>';
  167.             else $arrLabels['{$WARN_ENDREPLY}'] = '<span class="warn_txt">此討論串已被強制sage,可繼續留言但不會浮上去。<br/></span>';
  168.         }
  169.     }
  170.    
  171.     function autoHookThreadReply(&$arrLabels, $post, $isReply){
  172.         $this->autoHookThreadPost($arrLabels, $post, $isReply);
  173.     }
  174.    
  175.     function autoHookRegistBeforeCommit(&$name, &$email, &$sub, &$com, &$category, &$age, $dest, $isReply, $imgWH, &$status){
  176.         global $PIO;
  177.         $fh = new FlagHelper($status);
  178.  
  179.         if($isReply) {
  180.             $rpost = $PIO->fetchPosts($isReply); // 強制sage
  181.             $rfh = new FlagHelper($rpost[0]['status']);
  182.             if($rfh->value('asage')) $age = false;
  183.         }
  184.  
  185.     }
  186.  
  187.     function ModulePage(){
  188.         global $PMS;
  189.        
  190.         if(isset($_GET['action'])) {
  191.             if($_GET['action'] == 'listwords') {
  192.                 $dat = '';
  193.                 $dat .= '字詞黑名單一覽<br /><hr />';
  194.                 $dat .= '<table border="0" width="100%"><tr><td>Word</td><td>Description</td></tr>';
  195.                
  196.                 foreach($this->_parseBlackListFile($this->wordfile) as $i => $l){
  197.                     $dat .= '<tr><td>'.htmlspecialchars($l[0]).'</td><td>'.(isset($l[1]) ? $l[1] : '').'</td></tr>'."\n";
  198.                 }
  199.                
  200.                 $dat .= '</table>';
  201.                 echo $dat;
  202.                 return;
  203.             }
  204.         }
  205.        
  206.         if(!adminAuthenticate('check')) die('[Error] Access Denied.');
  207.  
  208.         // 進行新增、刪除等動作
  209.         if(isset($_POST['operate'])){
  210.             $op = $_POST['operate'];
  211.             // 新增資料
  212.             $ndata = isset($_POST['newdata']) ? (get_magic_quotes_gpc() ? stripslashes($_POST['newdata']) : $_POST['newdata']) : ''; // 資料內容
  213.             $nperiod = isset($_POST['newperiod']) ? intval($_POST['newperiod']) : 0; // 封鎖天數
  214.             $ndesc = isset($_POST['newdesc']) ? CleanStr($_POST['newdesc']) : ''; // 註解
  215.             // 刪除資料
  216.             $del = isset($_POST['del']) ? $_POST['del'] : null;
  217.             $newline = '';
  218.             $ismodified = ($ndata != '' || $del != null); // 是否需要修改檔案內容
  219.             if($ismodified){
  220.                 switch($op){
  221.                     case 'ip':
  222.                         $file = $this->ipfile;
  223.                         if($ndata != '') $newline = $ndata."\t".$ndesc."\t".time()."\t".$nperiod."\n";
  224.                         break;
  225.                     case 'img':
  226.                         $file = $this->imgfile;
  227.                         if($ndata != '') $newline = $ndata."\t".$ndesc."\n";
  228.                         break;
  229.                     case 'word':
  230.                         $file = $this->wordfile;
  231.                         if($ndata != '') $newline = $ndata."\t".$ndesc."\n";
  232.                         break;
  233.                 }
  234.                 $this->_arrangeRecord($file, $del, $newline); // 同步進行刪除及更新
  235.             }
  236.             if(isset($_POST['ajax'])){ // AJAX 要求在此即停止,一般要求則繼續印出頁面
  237.                 $extend = ($op=='ip') ? '<td>'.date('Y/m/d H:m:s', time())." ($nperiod)</td>" : ''; // IP黑名單資訊比圖檔多
  238.                 echo '<tr><td>'.htmlspecialchars($ndata).'</td><td>'.$ndesc.'</td>'.$extend.'<td><input type="checkbox" name="del[]" value="#NO#" /></td></tr>';
  239.                 return;
  240.             }
  241.         }
  242.  
  243.         $dat = '';
  244.         $PMS->hookModuleMethod('Head', array(&$this, '_hookHeadCSS'));
  245.         head($dat);
  246.         $dat .= '<div class="bar_admin">封鎖黑名單管理</div>
  247. <div id="content">
  248. <form action="'.$this->mypage.'" method="post">
  249. <div id="ipconfig"><input type="hidden" name="operate" value="ip" />
  250. IP 黑名單<br />
  251. Pattern: <input type="text" name="newdata" size="30" />
  252. Period: <input type="text" name="newperiod" size="5" value="0" />Day(s)
  253. Desc: <input type="text" name="newdesc" size="30" />
  254. <input type="submit" value="新增" onclick="return add(this.form);" /><br />
  255. <div class="dos_list_short">
  256. <table border="0" width="100%">
  257. <tr><td>Pattern</td><td>Description</td><td>Add Date (Period)</td><td>Delete</td></tr>
  258. ';
  259.         foreach($this->_parseBlackListFile($this->ipfile) as $i => $l){
  260.             $dat .= '<tr><td>'.htmlspecialchars($l[0]).'</td><td>'.(isset($l[1]) ? $l[1] : '').'</td>'.
  261.             '<td>'.(isset($l[2]) ? date('Y/m/d H:m:s', $l[2]) : '-').(isset($l[3]) ? ' ('.$l[3].')' : ' (0)').'</td>'.
  262.             '<td><input type="checkbox" name="del[]" value="'.$i.'" /></td></tr>'."\n";
  263.         }
  264.         $dat .= '</table>
  265. </div>
  266. <input type="submit" value="刪除" />
  267. </div>
  268. </form>
  269.  
  270. <form action="'.$this->mypage.'" method="post">
  271. <div id="imgconfig"><input type="hidden" name="operate" value="img" />
  272. 圖檔 MD5 黑名單<br />
  273. MD5: <input type="text" name="newdata" size="30" />
  274. Desc: <input type="text" name="newdesc" size="30" />
  275. <input type="submit" value="新增" onclick="return add(this.form);" /><br />
  276. <div class="dos_list_short">
  277. <table border="0" width="100%">
  278. <tr><td>MD5</td><td>Description</td><td>Delete</td></tr>
  279. ';
  280.         foreach($this->_parseBlackListFile($this->imgfile) as $i => $l){
  281.             $dat .= '<tr><td>'.htmlspecialchars($l[0]).'</td><td>'.(isset($l[1]) ? $l[1] : '').'</td><td><input type="checkbox" name="del[]" value="'.$i.'" /></td></tr>'."\n";
  282.         }
  283.         $dat .= '</table>
  284. </div>
  285. <input type="submit" value="刪除" />
  286. </div>
  287. </form>
  288.  
  289. <form action="'.$this->mypage.'" method="post">
  290. <div id="wordconfig"><input type="hidden" name="operate" value="word" />
  291. 字詞黑名單<br />
  292. Word: <input type="text" name="newdata" size="100" />
  293. Desc: <input type="text" name="newdesc" size="30" />
  294. <input type="submit" value="新增" onclick="return add(this.form);" /><br />
  295. <div class="dos_list_short">
  296. <table border="0" width="100%">
  297. <tr><td>Word</td><td>Description</td><td>Delete</td></tr>
  298. ';
  299.         foreach($this->_parseBlackListFile($this->wordfile) as $i => $l){
  300.             $dat .= '<tr><td>'.htmlspecialchars($l[0]).'</td><td>'.(isset($l[1]) ? $l[1] : '').'</td><td><input type="checkbox" name="del[]" value="'.$i.'" /></td></tr>'."\n";
  301.         }
  302.         $dat .= '</table>
  303. </div>
  304. <input type="submit" value="刪除" />
  305. </div>
  306. </form>
  307.  
  308. <hr />
  309. <div id="help"><pre>
  310. 說明
  311.  
  312. Pattern:
  313.  
  314. 可封鎖特定IP/Hostname發文。以使用者的IP位置或Host名稱進行判斷,所以兩種形式都可以使用。
  315. 例如 127.0.0.1 (IP) 和 localhost (Host) 代表的都是相同的電腦。
  316. 接受下列格式
  317.  
  318. - 完全相符
  319. 即是完全一模一樣的情況下才封鎖。
  320. 範例:
  321. 127.0.0.1 (127.0.0.1 O;127.0.0.2 X)
  322. localhost (localhost O;local X)
  323.  
  324. - 萬用字元
  325. 可接受 * , ? 來代替一段未知的字元 (如同大家熟知的使用方式),這樣一來可匹配的情況將增加。
  326. 範例:
  327. 192.168.0.* (192.168.0.3 O;192.168.1.3 X)
  328. local* (localhost O;remotehost X)
  329.  
  330. - 正規表達式
  331. 使用Regular Expression來進行匹配,可作出更多樣、更適合的條件。注意使用時需要使用 / 斜線將表達式括住。
  332. 範例:
  333. /127\.0\.0\.[0-9]{2}/ (127.0.0.28 O;127.0.0.1 X)
  334. /^.+\.proxy\.com$/ (gate1.proxy.com O;proxy2.com.tw X)
  335.  
  336. - CIDR Notation
  337. 使用 Classless Addressing 這種更有彈性的方式切割子網路,其表示法稱作 CIDR,以一段IP位置加上Mask來劃分子網路 (注意此表示法僅能使用 IP)。
  338. 範例:
  339. 192.168.0.1/20 (192.168.7.243 O;192.168.18.144 X)
  340.  
  341. Period:
  342.  
  343. 設定封鎖期限,在過期時可以自動刪除解鎖,以天為單位。如果想永久封鎖 (系統不自動回收,需手動解鎖) 則將此值設為 0 (0 表示無期限)。
  344.  
  345. Banword:
  346.  
  347. 可封鎖特定字詞發文,只支援以下一種格式:
  348.  
  349. - 完全相符
  350. 即是完全一模一樣的情況下才封鎖。
  351. 範例:
  352. 果然棒 (果然棒123 O;果然...棒 X)
  353. 活佛 (信活佛 O;活-佛 X)
  354. </pre>
  355. </div>
  356. </div>';
  357.         foot($dat);
  358.         echo $dat;
  359.     }
  360. }
  361.  
  362.  
  363.  
  364. ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement