Dotclear

source: plugins/antispam/filters/class.dc.filter.ip.php @ 780:a80ff8f1c92a

Revision 780:a80ff8f1c92a, 7.6 KB checked in by Dsls <dsls@…>, 14 years ago (diff)

Handled after-actions redirections, columns selection now works, author filter autocompletion ok.

Line 
1<?php
2# -- BEGIN LICENSE BLOCK ---------------------------------------
3#
4# This file is part of Antispam, a plugin for Dotclear 2.
5#
6# Copyright (c) 2003-2010 Olivier Meunier & Association Dotclear
7# Licensed under the GPL version 2.0 license.
8# See LICENSE file or
9# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
10#
11# -- END LICENSE BLOCK -----------------------------------------
12if (!defined('DC_RC_PATH')) { return; }
13
14class dcFilterIP extends dcSpamFilter
15{
16     public $name = 'IP Filter';
17     public $has_gui = true;
18
19     private $style_list = 'height: 200px; overflow: auto; margin-bottom: 1em; ';
20     private $style_p = 'margin: 1px 0 0 0; padding: 0.2em 0.5em; ';
21     private $style_global = 'background: #ccff99; ';
22
23     private $con;
24     private $table;
25
26     public function __construct($core)
27     {
28          parent::__construct($core);
29          $this->con =& $core->con;
30          $this->table = $core->prefix.'spamrule';
31     }
32
33     protected function setInfo()
34     {
35          $this->description = __('IP Blacklist / Whitelist Filter');
36     }
37
38     public function getStatusMessage($status,$comment_id)
39     {
40          return sprintf(__('Filtered by %1$s with rule %2$s.'),$this->guiLink(),$status);
41     }
42
43     public function isSpam($type,$author,$email,$site,$ip,$content,$post_id,&$status)
44     {
45          if (!$ip) {
46               return;
47          }
48
49          # White list check
50          if ($this->checkIP($ip,'white') !== false) {
51               return false;
52          }
53
54          # Black list check
55          if (($s = $this->checkIP($ip,'black')) !== false) {
56               $status = $s;
57               return true;
58          }
59     }
60
61     public function gui($url)
62     {
63          global $default_tab;
64          $core =& $this->core;
65
66          # Set current type and tab
67          $ip_type = 'black';
68          if (!empty($_REQUEST['ip_type']) && $_REQUEST['ip_type'] == 'white') {
69               $ip_type = 'white';
70          }
71          $default_tab = 'tab_'.$ip_type;
72
73          # Add IP to list
74          if (!empty($_POST['addip']))
75          {
76               try
77               {
78                    $global = !empty($_POST['globalip']) && $core->auth->isSuperAdmin();
79
80                    $this->addIP($ip_type,$_POST['addip'],$global);
81                    http::redirect($url.'&added=1&ip_type='.$ip_type);
82               }
83               catch (Exception $e)
84               {
85                    $core->error->add($e->getMessage());
86               }
87          }
88
89          # Remove IP from list
90          if (!empty($_POST['delip']) && is_array($_POST['delip']))
91          {
92               try {
93                    $this->removeRule($_POST['delip']);
94                    http::redirect($url.'&removed=1&ip_type='.$ip_type);
95               } catch (Exception $e) {
96                    $core->error->add($e->getMessage());
97               }
98          }
99
100          /* DISPLAY
101          ---------------------------------------------- */
102          $res = '';
103
104          if (!empty($_GET['added'])) {
105               $res .= '<p class="message">'.__('IP address has been successfully added.').'</p>';
106          }
107          if (!empty($_GET['removed'])) {
108               $res .= '<p class="message">'.__('IP addresses have been successfully removed.').'</p>';
109          }
110
111          $res .=
112          $this->displayForms($url,'black',__('Blacklist')).
113          $this->displayForms($url,'white',__('Whitelist'));
114
115          return $res;
116     }
117
118     private function displayForms($url,$type,$title)
119     {
120          $core =& $this->core;
121
122          $res =
123          '<div class="multi-part" id="tab_'.$type.'" title="'.$title.'">'.
124
125          '<form action="'.html::escapeURL($url).'" method="post">'.
126          '<fieldset><legend>'.__('Add an IP address').'</legend><p>'.
127          form::hidden(array('ip_type'),$type).
128          '<label class="classic" for="addip_'.$type.'">'.__('Add an IP address').' '.
129          form::field(array('addip', 'addip_'.$type),18,255).
130          '</label>';
131          if ($core->auth->isSuperAdmin()) {
132               $res .= '<label class="classic" for="globalip_'.$type.'">'.form::checkbox(array('globalip', 'globalip_'.$type),1).' '.
133               __('Global IP').'</label> ';
134          }
135
136          $res .=
137          $core->formNonce().
138          '<input type="submit" value="'.__('Add').'"/></p>'.
139          '</fieldset></form>';
140
141          $rs = $this->getRules($type);
142
143          if ($rs->isEmpty())
144          {
145               $res .= '<p><strong>'.__('No IP address in list.').'</strong></p>';
146          }
147          else
148          {
149               $res .=
150               '<form action="'.html::escapeURL($url).'" method="post">'.
151               '<fieldset><legend>' . __('IP list') . '</legend>'.
152               '<div style="'.$this->style_list.'">';
153
154               while ($rs->fetch())
155               {
156                    $bits = explode(':',$rs->rule_content);
157                    $pattern = $bits[0];
158                    $ip = $bits[1];
159                    $bitmask = $bits[2];
160
161                    $disabled_ip = false;
162                    $p_style = $this->style_p;
163                    if (!$rs->blog_id) {
164                         $disabled_ip = !$core->auth->isSuperAdmin();
165                         $p_style .= $this->style_global;
166                    }
167
168                    $res .=
169                    '<p style="'.$p_style.'"><label class="classic">'.
170                    form::checkbox(array('delip[]'),$rs->rule_id,false,'','',$disabled_ip, 'title="'.html::escapeHTML($pattern).'"').' '.
171                    html::escapeHTML($pattern).
172                    '</label></p>';
173               }
174               $res .=
175               '</div>'.
176               '<p><input class="submit delete" type="submit" value="'.__('Delete').'"/>'.
177               $core->formNonce().
178               form::hidden(array('ip_type'),$type).
179               '</p>'.
180               '</fieldset></form>';
181          }
182
183          $res .= '</div>';
184
185          return $res;
186     }
187
188     private function ipmask($pattern,&$ip,&$mask)
189     {
190          $bits = explode('/',$pattern);
191
192          # Set IP
193          $bits[0] .= str_repeat(".0", 3 - substr_count($bits[0], "."));
194          $ip = ip2long($bits[0]);
195
196          if (!$ip || $ip == -1) {
197               throw new Exception('Invalid IP address');
198          }
199
200          # Set mask
201          if (!isset($bits[1])) {
202               $mask = -1;
203          } elseif (strpos($bits[1],'.')) {
204               $mask = ip2long($bits[1]);
205               if (!$mask) {
206                    $mask = -1;
207               }
208          } else {
209               $mask = ~((1 << (32 - $bits[1])) - 1);
210          }
211     }
212
213     private function addIP($type,$pattern,$global)
214     {
215          $this->ipmask($pattern,$ip,$mask);
216          $pattern = long2ip($ip).($mask != -1 ? '/'.long2ip($mask) : '');
217          $content = $pattern.':'.$ip.':'.$mask;
218
219          $old = $this->getRuleCIDR($type,$global,$ip,$mask);
220          $cur = $this->con->openCursor($this->table);
221
222          if ($old->isEmpty())
223          {
224               $id = $this->con->select('SELECT MAX(rule_id) FROM '.$this->table)->f(0) + 1;
225
226               $cur->rule_id = $id;
227               $cur->rule_type = (string) $type;
228               $cur->rule_content = (string) $content;
229
230               if ($global && $this->core->auth->isSuperAdmin()) {
231                    $cur->blog_id = null;
232               } else {
233                    $cur->blog_id = $this->core->blog->id;
234               }
235
236               $cur->insert();
237          }
238          else
239          {
240               $cur->rule_type = (string) $type;
241               $cur->rule_content = (string) $content;
242               $cur->update('WHERE rule_id = '.(integer) $old->rule_id);
243          }
244     }
245
246     private function getRules($type='all')
247     {
248          $strReq =
249          'SELECT rule_id, rule_type, blog_id, rule_content '.
250          'FROM '.$this->table.' '.
251          "WHERE rule_type = '".$this->con->escape($type)."' ".
252          "AND (blog_id = '".$this->core->blog->id."' OR blog_id IS NULL) ".
253          'ORDER BY blog_id ASC, rule_content ASC ';
254
255          return $this->con->select($strReq);
256     }
257
258     private function getRuleCIDR($type,$global,$ip,$mask)
259     {
260          $strReq =
261          'SELECT * FROM '.$this->table.' '.
262          "WHERE rule_type = '".$this->con->escape($type)."' ".
263          "AND rule_content LIKE '%:".(integer) $ip.":".(integer) $mask."' ".
264          'AND blog_id '.($global ? 'IS NULL ' : "= '".$this->core->blog->id."' ");
265
266          return $this->con->select($strReq);
267     }
268
269     private function checkIP($cip,$type)
270     {
271          $core =& $this->core;
272
273          $strReq =
274          'SELECT DISTINCT(rule_content) '.
275          'FROM '.$this->table.' '.
276          "WHERE rule_type = '".$this->con->escape($type)."' ".
277          "AND (blog_id = '".$this->core->blog->id."' OR blog_id IS NULL) ".
278          'ORDER BY rule_content ASC ';
279
280          $rs = $this->con->select($strReq);
281          while ($rs->fetch())
282          {
283               list($pattern,$ip,$mask) = explode(':',$rs->rule_content);
284               if ((ip2long($cip) & (integer) $mask) == ((integer) $ip & (integer) $mask)) {
285                    return $pattern;
286               }
287          }
288          return false;
289     }
290
291     private function removeRule($ids)
292     {
293          $strReq = 'DELETE FROM '.$this->table.' ';
294
295          if (is_array($ids)) {
296               foreach ($ids as $i => $v) {
297                    $ids[$i] = (integer) $v;
298               }
299               $strReq .= 'WHERE rule_id IN ('.implode(',',$ids).') ';
300          } else {
301               $ids = (integer) $ids;
302               $strReq .= 'WHERE rule_id = '.$ids.' ';
303          }
304
305          if (!$this->core->auth->isSuperAdmin()) {
306               $strReq .= "AND blog_id = '".$this->core->blog->id."' ";
307          }
308
309          $this->con->execute($strReq);
310     }
311}
312?>
Note: See TracBrowser for help on using the repository browser.

Sites map