Advertisement
Guest User

Pixmicat! mod_adminenhance special edition for 7th (Fix2)

a guest
Mar 4th, 2013
230
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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('管理工具增強組合包+自改 by dbfox');
  16.     }
  17.  
  18.     public function getModuleVersionInfo() {
  19.         return '7th.Release.SP(v130305) - 整合mod_siokara強制sage功能(100626)+擋字功能(120819)';
  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->getModulePageURL()).'", {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->getModulePageURL()."&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->getModulePageURL().'">封鎖黑名單管理</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.         $PIO = PMCLibrary::getPIOInstance();
  198.         $fh = new FlagHelper($status);
  199.  
  200.         if($isReply) {
  201.             $rpost = $PIO->fetchPosts($isReply); // 強制sage
  202.             $rfh = new FlagHelper($rpost[0]['status']);
  203.             if($rfh->value('asage')) $age = false;
  204.         }
  205.  
  206.     }
  207.  
  208.     public function ModulePage(){
  209.         if(isset($_GET['action'])) {
  210.             if($_GET['action'] == 'listwords') {
  211.                 $dat = '';
  212.                 $dat .= '字詞黑名單一覽<br /><hr />';
  213.                 $dat .= '<table border="0" width="100%"><tr><td>Word</td><td>Description</td></tr>';
  214.                
  215.                 foreach($this->_parseBlackListFile($this->wordfile) as $i => $l){
  216.                     $dat .= '<tr><td>'.htmlspecialchars($l[0]).'</td><td>'.(isset($l[1]) ? $l[1] : '').'</td></tr>'."\n";
  217.                 }
  218.                
  219.                 $dat .= '</table>';
  220.                 echo $dat;
  221.                 return;
  222.             }
  223.         }
  224.        
  225.         if(!adminAuthenticate('check'))
  226.                 die('[Error] Access Denied.');
  227.  
  228.         // 進行新增、刪除等動作
  229.         if (isset($_POST['operate'])) {
  230.             $op = $_POST['operate'];
  231.             // 新增資料
  232.            
  233.             // 資料內容
  234.             $ndata = isset($_POST['newdata']) ?
  235.             (get_magic_quotes_gpc() ? stripslashes($_POST['newdata']) :
  236.                     $_POST['newdata']) : '';
  237.             // 封鎖天數    
  238.             $nperiod = isset($_POST['newperiod']) ? intval($_POST['newperiod']) : 0;
  239.              // 註解
  240.             $ndesc = isset($_POST['newdesc']) ? CleanStr($_POST['newdesc']) : '';
  241.             // 刪除資料
  242.             $del = isset($_POST['del']) ? $_POST['del'] : null;
  243.             $newline = '';
  244.             // 是否需要修改檔案內容
  245.             $ismodified = ($ndata != '' || $del != null);
  246.             if ($ismodified) {
  247.                 switch ($op) {
  248.                     case 'ip':
  249.                         $file = $this->ipfile;
  250.                         if($ndata != '')
  251.                                $newline = $ndata."\t".$ndesc."\t".time()."\t".$nperiod."\n";
  252.                         break;
  253.                     case 'img':
  254.                         $file = $this->imgfile;
  255.                         if($ndata != '')
  256.                                $newline = $ndata."\t".$ndesc."\n";
  257.                         break;
  258.                     case 'word':
  259.                         $file = $this->wordfile;
  260.                         if($ndata != '')
  261.                                $newline = $ndata."\t".$ndesc."\n";
  262.                         break;
  263.                 }
  264.                  // 同步進行刪除及更新
  265.                 $this->_arrangeRecord($file, $del, $newline);
  266.             }
  267.             // AJAX 要求在此即停止,一般要求則繼續印出頁面
  268.             if (isset($_POST['ajax'])) {
  269.                 // IP黑名單資訊比圖檔多
  270.                 $extend = ($op=='ip') ?
  271.                         '<td>'.date('Y/m/d H:m:s', time())." ($nperiod)</td>" : '';
  272.                 echo '<tr><td>'.htmlspecialchars($ndata).'</td><td>'.$ndesc.
  273.                         '</td>'.$extend.'<td><input type="checkbox" name="del[]" value="#NO#" /></td></tr>';
  274.                 return;
  275.             }
  276.         }
  277.  
  278.         $dat = '';
  279.         $this->hookModuleMethod('Head', array(&$this, '_hookHeadCSS'));
  280.         head($dat);
  281.         $dat .= '<div class="bar_admin">封鎖黑名單管理</div>
  282. <div id="content">
  283. <form action="'.$this->getModulePageURL().'" method="post">
  284. <div id="ipconfig"><input type="hidden" name="operate" value="ip" />
  285. IP 黑名單<br />
  286. Pattern: <input type="text" name="newdata" size="30" />
  287. Period: <input type="text" name="newperiod" size="5" value="0" />Day(s)
  288. Desc: <input type="text" name="newdesc" size="30" />
  289. <input type="submit" value="新增" onclick="return add(this.form);" /><br />
  290. <div class="dos_list_short">
  291. <table border="0" width="100%">
  292. <tr><td>Pattern</td><td>Description</td><td>Add Date (Period)</td><td>Delete</td></tr>
  293. ';
  294.         foreach ($this->_parseBlackListFile($this->ipfile) as $i => $l) {
  295.             $dat .= '<tr><td>'.htmlspecialchars($l[0]).'</td><td>'.(isset($l[1]) ? $l[1] : '').'</td>'.
  296.             '<td>'.(isset($l[2]) ? date('Y/m/d H:m:s', $l[2]) : '-').(isset($l[3]) ? ' ('.$l[3].')' : ' (0)').'</td>'.
  297.             '<td><input type="checkbox" name="del[]" value="'.$i.'" /></td></tr>'."\n";
  298.         }
  299.         $dat .= '</table>
  300. </div>
  301. <input type="submit" value="刪除" />
  302. </div>
  303. </form>
  304.  
  305. <form action="'.$this->getModulePageURL().'" method="post">
  306. <div id="imgconfig"><input type="hidden" name="operate" value="img" />
  307. 圖檔 MD5 黑名單<br />
  308. MD5: <input type="text" name="newdata" size="30" />
  309. Desc: <input type="text" name="newdesc" size="30" />
  310. <input type="hidden" name="newperiod" value="0" />
  311. <input type="submit" value="新增" onclick="return add(this.form);" /><br />
  312. <div class="dos_list_short">
  313. <table border="0" width="100%">
  314. <tr><td>MD5</td><td>Description</td><td>Delete</td></tr>
  315. ';
  316.         foreach ($this->_parseBlackListFile($this->imgfile) as $i => $l) {
  317.                 $dat .= '<tr><td>'.htmlspecialchars($l[0]).'</td><td>'.
  318.                         (isset($l[1]) ? $l[1] : '').'</td><td><input type="checkbox" name="del[]" value="'.$i.'" /></td></tr>'."\n";
  319.         }
  320.         $dat .= '</table>
  321. </div>
  322. <input type="submit" value="刪除" />
  323. </div>
  324. </form>
  325.  
  326. <form action="'.$this->getModulePageURL().'" method="post">
  327. <div id="wordconfig"><input type="hidden" name="operate" value="word" />
  328. 字詞黑名單<br />
  329. Word: <input type="text" name="newdata" size="100" />
  330. Desc: <input type="text" name="newdesc" size="30" />
  331. <input type="submit" value="新增" onclick="return add(this.form);" /><br />
  332. <div class="dos_list_short">
  333. <table border="0" width="100%">
  334. <tr><td>Word</td><td>Description</td><td>Delete</td></tr>
  335. ';
  336.         foreach ($this->_parseBlackListFile($this->wordfile) as $i => $l){
  337.                 $dat .= '<tr><td>'.htmlspecialchars($l[0]).'</td><td>'.
  338.                         (isset($l[1]) ? $l[1] : '').'</td><td><input type="checkbox" name="del[]" value="'.$i.'" /></td></tr>'."\n";
  339.         }
  340.         $dat .= '</table>
  341. </div>
  342. <input type="submit" value="刪除" />
  343. </div>
  344. </form>
  345.  
  346. <hr />
  347. <div id="help"><pre>
  348. 說明
  349.  
  350. Pattern:
  351.  
  352. 可封鎖特定IP/Hostname發文。以使用者的IP位置或Host名稱進行判斷,所以兩種形式都可以使用。
  353. 例如 127.0.0.1 (IP) 和 localhost (Host) 代表的都是相同的電腦。
  354. 接受下列格式
  355.  
  356. - 完全相符
  357. 即是完全一模一樣的情況下才封鎖。
  358. 範例:
  359. 127.0.0.1 (127.0.0.1 O;127.0.0.2 X)
  360. localhost (localhost O;local X)
  361.  
  362. - 萬用字元
  363. 可接受 * , ? 來代替一段未知的字元 (如同大家熟知的使用方式),這樣一來可匹配的情況將增加。
  364. 範例:
  365. 192.168.0.* (192.168.0.3 O;192.168.1.3 X)
  366. local* (localhost O;remotehost X)
  367.  
  368. - 正規表達式
  369. 使用Regular Expression來進行匹配,可作出更多樣、更適合的條件。注意使用時需要使用 / 斜線將表達式括住。
  370. 範例:
  371. /127\.0\.0\.[0-9]{2}/ (127.0.0.28 O;127.0.0.1 X)
  372. /^.+\.proxy\.com$/ (gate1.proxy.com O;proxy2.com.tw X)
  373.  
  374. - CIDR Notation
  375. 使用 Classless Addressing 這種更有彈性的方式切割子網路,其表示法稱作 CIDR,以一段IP位置加上Mask來劃分子網路 (注意此表示法僅能使用 IP)。
  376. 範例:
  377. 192.168.0.1/20 (192.168.7.243 O;192.168.18.144 X)
  378.  
  379. Period:
  380.  
  381. 設定封鎖期限,在過期時可以自動刪除解鎖,以天為單位。如果想永久封鎖 (系統不自動回收,需手動解鎖) 則將此值設為 0 (0 表示無期限)。
  382.  
  383. Banword:
  384.  
  385. 可封鎖特定字詞發文,只支援以下一種格式:
  386.  
  387. - 完全相符
  388. 即是完全一模一樣的情況下才封鎖。
  389. 範例:
  390. 果然棒 (果然棒123 O;果然...棒 X)
  391. 活佛 (信活佛 O;活-佛 X)
  392. </pre>
  393. </div>
  394. </div>';
  395.         foot($dat);
  396.         echo $dat;
  397.     }
  398. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement