pixmicat - Blame information for rev 875

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