OSDN Git Service

v1.0.2
[nucleus-jp/nucleus-plugins.git] / trunk / NP_Blacklist / NP_Blacklist.php
1 <?php
2
3 /**
4   * NP_Blacklist(JP) ($Revision: 1.8 $)
5   * by hsur ( http://blog.cles.jp/np_cles )
6   * $Id: NP_Blacklist.php,v 1.8 2007-02-11 08:57:12 hsur Exp $
7   *
8   * Based on NP_Blacklist 0.98
9   * by xiffy
10   * http://forum.nucleuscms.org/viewtopic.php?t=5300
11 */
12
13 /*
14   * Copyright (C) 2005-2007 cles All rights reserved.
15   *
16   * This program is free software; you can redistribute it and/or
17   * modify it under the terms of the GNU General Public License
18   * as published by the Free Software Foundation; either version 2
19   * of the License, or (at your option) any later version.
20   * 
21   * This program is distributed in the hope that it will be useful,
22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24   * GNU General Public License for more details.
25   * 
26   * You should have received a copy of the GNU General Public License
27   * along with this program; if not, write to the Free Software
28   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
29 */
30
31 include_once(dirname(__FILE__)."/blacklist/blacklist_lib.php");
32
33 class NP_Blacklist extends NucleusPlugin {
34         function getName() {
35                 return 'Blacklist(JP)';
36         }
37         function getAuthor() {
38                 return 'xiffy + hsur';
39         }
40         function getURL() {
41                 return 'http://blog.cles.jp/np_cles/category/31/subcatid/11';
42         }
43         function getVersion() {
44                 return '1.0.2';
45         }
46         function getDescription() {
47                 return '[$Revision: 1.8 $]<br />'.NP_BLACKLIST_description;
48         }
49         function supportsFeature($what) {
50                 switch ($what) {
51                         case 'SqlTablePrefix' :
52                                 return 1;
53                         default :
54                                 return 0;
55                 }
56         }
57
58         function install() {
59                 // create some options
60                 $this->createOption('enabled', NP_BLACKLIST_enabled, 'yesno', 'yes');
61                 $this->createOption('redirect', NP_BLACKLIST_redirect, 'text', '');
62                 $this->createOption('ipblock', NP_BLACKLIST_ipblock, 'yesno', 'yes');
63                 $this->createOption('ipthreshold', NP_BLACKLIST_ipthreshold, 'text', '10');
64                 $this->createOption('BulkfeedsKey', NP_BLACKLIST_BulkfeedsKey, 'text', '');
65                 $this->createOption('SkipNameResolve', NP_BLACKLIST_SkipNameResolve, 'yesno', 'yes');
66
67                 $this->_initSettings();
68         }
69
70         function unInstall() {
71         }
72
73         function getPluginOption($name) {
74                 return $this->getOption($name);
75         }
76
77         function getEventList() {
78                 $this->_initSettings();
79                 return array ('QuickMenu', 'SpamCheck');
80         }
81
82         function hasAdminArea() {
83                 return 1;
84         }
85
86         function init() {
87                 // include language file for this plugin 
88                 $language = ereg_replace('[\\|/]', '', getLanguageName());
89                 if (file_exists($this->getDirectory().'language/'.$language.'.php'))
90                         @ include_once ($this->getDirectory().'language/'.$language.'.php');
91                 else
92                         @ include_once ($this->getDirectory().'language/english.php');
93                 $this->resultCache = false;
94         }
95
96         function event_QuickMenu(& $data) {
97                 global $member, $nucleus, $blogid;
98                 // only show to admins
99                 if (preg_match("/MD$/", $nucleus['version'])) {
100                         $isblogadmin = $member->isBlogAdmin(-1);
101                 } else {
102                         $isblogadmin = $member->isBlogAdmin($blogid);
103                 }
104                 if (!($member->isLoggedIn() && ($member->isAdmin() | $isblogadmin)))
105                         return;
106                 array_push($data['options'], array ('title' => NP_BLACKLIST_name, 'url' => $this->getAdminURL(), 'tooltip' => NP_BLACKLIST_nameTips,));
107         }
108
109         // handle SpamCheck event
110         function event_SpamCheck(& $data) {
111                 global $DIR_PLUGINS;
112                 if (isset ($data['spamcheck']['result']) && $data['spamcheck']['result'] == true) {
113                         // Already checked... and is spam
114                         return;
115                 }
116
117                 if (!isset ($data['spamcheck']['return'])) {
118                         $data['spamcheck']['return'] = true;
119                 }
120
121                 // for SpamCheck API 2.0 compatibility
122                 if (!$data['spamcheck']['data']) {
123                         switch (strtolower($data['spamcheck']['type'])) {
124                                 case 'comment' :
125                                         $data['spamcheck']['data'] = $data['spamcheck']['body']."\n";
126                                         $data['spamcheck']['data'] .= $data['spamcheck']['author']."\n";
127                                         $data['spamcheck']['data'] .= $data['spamcheck']['url']."\n";
128                                         break;
129                                 case 'trackback' :
130                                         $data['spamcheck']['data'] = $data['spamcheck']['title']."\n";
131                                         $data['spamcheck']['data'] .= $data['spamcheck']['excerpt']."\n";
132                                         $data['spamcheck']['data'] .= $data['spamcheck']['blogname']."\n";
133                                         $data['spamcheck']['data'] .= $data['spamcheck']['url'];
134                                         break;
135                                 case 'referer' :
136                                         $data['spamcheck']['data'] = $data['spamcheck']['url'];
137                                         break;
138                         }
139                 }
140                 $ipblock = ($data['spamcheck']['ipblock']) || ($data['spamcheck']['live']);
141
142                 // Check for spam
143                 $result = $this->blacklist($data['spamcheck']['type'], $data['spamcheck']['data'], $ipblock);
144
145                 if ($result) {
146                         // Spam found
147                         // logging !
148                         pbl_logspammer($data['spamcheck']['type'].': '.$result);
149                         if (isset ($data['spamcheck']['return']) && $data['spamcheck']['return'] == true) {
150                                 // Return to caller
151                                 $data['spamcheck']['result'] = true;
152                                 $data['spamcheck']['plugin'] = $this->getName();
153                                 $data['spamcheck']['message'] = 'Marked as spam by NP_Blacklist';
154                                 return;
155                         } else {
156                                 $this->_redirect($this->getOption('redirect'));
157                         }
158                 }
159         }
160
161         // Obsolete
162         function event_PreAddComment(& $data) {
163                 $comment = $data['comment'];
164                 $result = $this->blacklist('comment', postVar('body')."\n".$comment['host']."\n".$comment['user']."\n".$comment['userid']);
165                 if ($result) {
166                         pbl_logspammer('comment: '.$result);
167                         $this->_redirect($this->getOption('redirect'));
168                 }
169         }
170
171         // Obsolete
172         function event_ValidateForm(& $data) {
173                 if ($data['type'] == 'comment') {
174                         $comment = $data['comment'];
175                         $result = $this->blacklist('comment', postVar('body')."\n".$comment['host']."\n".$comment['user']."\n".$comment['userid']);
176                         if ($result) {
177                                 pbl_logspammer('comment: '.$result);
178                                 $this->_redirect($this->getOption('redirect'));
179                         }
180                 } else {
181                         if ($data['type'] == 'membermail') {
182                                 $result = $this->blacklist('membermail', postVar('frommail')."\n".postVar('message'));
183                                 if ($result) {
184                                         pbl_logspammer('membermail: '.$result);
185                                         $this->_redirect($this->getOption('redirect'));
186                                 }
187                         }
188                 }
189         }
190
191         // Obsolete
192         function event_PreSkinParse(& $data) {
193                 $result = $this->blacklist('PreSkinParse', '');
194                 if ($result) {
195                         pbl_logspammer('PreSkinParse: '.$result);
196                         $this->_redirect($this->getOption('redirect'));
197                 }
198         }
199
200         function blacklist($type, $testString, $ipblock = true) {
201                 global $DIR_PLUGINS, $member;
202                 if ($this->resultCache)
203                         return $this->resultCache.'[Cached]';
204
205                 if ($member->isLoggedIn()) {
206                         return '';
207                 }
208
209                 if ($this->getOption('enabled') == 'yes') {
210                         // update the blacklist first file
211                         //pbl_updateblacklist($this->getOption('update'),false);
212                         if ($ipblock) {
213                                 $ipblock = ($this->getOption('ipblock') == 'yes') ? true : false;
214                         }
215
216                         $result = '';
217                         if ($ipblock || $testString != '') {
218                                 $result = pbl_checkforspam($testString, $ipblock, $this->getOption('ipthreshold'), true);
219                         }
220
221                         if ($result) {
222                                 $this->resultCache = $result;
223                         }
224
225                         return $result;
226                 }
227         }
228
229         function submitSpamToBulkfeeds($url) {
230                 if (is_array($url))
231                         $url = implode("\n", $url);
232
233                 $postData['apikey'] = $this->getOption('BulkfeedsKey');
234                 if (!$postData['apikey'])
235                         return "BulkfeedsKey not found. see http://bulkfeeds.net/app/register_api.html";
236                 $postData['url'] = $url;
237
238                 $data = $this->_http('http://bulkfeeds.net:80/app/submit_spam.xml', 'POST', '', $postData);
239                 return $data;
240         }
241
242         function _http($url, $method = "GET", $headers = "", $post = array ("")) {
243                 $URL = parse_url($url);
244
245                 if (isset ($URL['query'])) {
246                         $URL['query'] = "?".$URL['query'];
247                 } else {
248                         $URL['query'] = "";
249                 }
250
251                 if (!isset ($URL['port']))
252                         $URL['port'] = 80;
253
254                 $request = $method." ".$URL['path'].$URL['query']." HTTP/1.0\r\n";
255
256                 $request .= "Host: ".$URL['host']."\r\n";
257                 $request .= "User-Agent: NP_Blacklist/".phpversion()."\r\n";
258
259                 if (isset ($URL['user']) && isset ($URL['pass'])) {
260                         $request .= "Authorization: Basic ".base64_encode($URL['user'].":".$URL['pass'])."\r\n";
261                 }
262
263                 $request .= $headers;
264
265                 if (strtoupper($method) == "POST") {
266                         while (list ($name, $value) = each($post)) {
267                                 $POST[] = $name."=".urlencode($value);
268                         }
269                         $postdata = implode("&", $POST);
270                         $request .= "Content-Type: application/x-www-form-urlencoded\r\n";
271                         $request .= "Content-Length: ".strlen($postdata)."\r\n";
272                         $request .= "\r\n";
273                         $request .= $postdata;
274                 } else {
275                         $request .= "\r\n";
276                 }
277
278                 $fp = fsockopen($URL['host'], $URL['port'], $errno, $errstr, 20);
279
280                 if ($fp) {
281                         socket_set_timeout($fp, 20);
282                         fputs($fp, $request);
283                         $response = "";
284                         while (!feof($fp)) {
285                                 $response .= fgets($fp, 4096);
286                         }
287                         fclose($fp);
288                         $DATA = split("\r\n\r\n", $response, 2);
289                         return $DATA[1];
290                 } else {
291                         $host = $URL['host'];
292                         $port = $URL['port'];
293                         ACTIONLOG :: add(WARNING, $this->getName().':'."[$errno]($host:$port) $errstr");
294                         return "";
295                 }
296         }
297
298         function _redirect($url) {
299                 if (!$url) {
300                         header("HTTP/1.0 403 Forbidden");
301                         header("Status: 403 Forbidden");
302
303                         include (dirname(__FILE__).'/blacklist/blocked.txt');
304                 } else {
305                         $url = preg_replace('|[^a-z0-9-~+_.?#=&;,/:@%]|i', '', $url);
306                         header('Location: '.$url);
307                 }
308                 exit;
309         }
310
311         function _initSettings() {
312                 $settingsDir = dirname(__FILE__).'/blacklist/settings/';
313                 $settings = array ('blacklist.log', 'blockip.pbl', 'matched.pbl', 'blacklist.pbl', 'blacklist.txt', 'suspects.pbl',);
314                 $personalBlacklist = $settingsDir.'personal_blacklist.pbl';
315                 $personalBlacklistDist = $settingsDir.'personal_blacklist.pbl.dist';
316
317                 // setup settings
318                 if ($this->_is_writable($settingsDir)) {
319                         foreach ($settings as $setting) {
320                                 touch($settingsDir.$setting);
321                         }
322                         // setup personal blacklist
323                         if (!file_exists($personalBlacklist)) {
324                                 if (copy($personalBlacklistDist, $personalBlacklist)) {
325                                         $this->_warn("'$personalBlacklist' ".NP_BLACKLIST_isCreated);
326                                 } else {
327                                         $this->_warn("'$personalBlacklist' ".NP_BLACKLIST_canNotCreate);
328                                 }
329                         }
330                 }
331
332                 // check settings       
333                 foreach ($settings as $setting) {
334                         $this->_is_writable($settingsDir.$setting);
335                 }
336                 $this->_is_writable($personalBlacklist);
337
338                 // setup and check cache dir
339                 $cacheDir = NP_BLACKLIST_CACHE_DIR;
340                 $this->_is_writable($cacheDir);
341         }
342
343         function _is_writable($file) {
344                 $ret = is_writable($file);
345                 if (!$ret) {
346                         $this->_warn("'$file' ".NP_BLACKLIST_isNotWritable);
347                 }
348                 return $ret;
349         }
350
351         function _warn($msg) {
352                 ACTIONLOG :: add(WARNING, 'Blacklist: '.$msg);
353         }
354
355 }