Advertisement
Guest User

pixmicat mod_adminenhance special edition 7th

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