Dotclear

source: plugins/antispam/filters/class.dc.filter.ip.php @ 1179:a43a29427ef3

Revision 1179:a43a29427ef3, 8.0 KB checked in by franck <carnet.franck.paul@…>, 11 years ago (diff)

Update copyright notice

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-2013 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 .= dcPage::message(__('IP address has been successfully added.'),true,false,false);
106          }
107          if (!empty($_GET['removed'])) {
108               $res .= dcPage::message(__('IP addresses have been successfully removed.'),true,false,false);
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" class="fieldset">'.
126          form::hidden(array('ip_type'),$type).
127          '<label class="classic" for="addip_'.$type.'">'.__('Add an IP address: ').' '.
128          form::field(array('addip', 'addip_'.$type),18,255).
129          '</label>';
130          if ($core->auth->isSuperAdmin()) {
131               $res .= '<label class="classic" for="globalip_'.$type.'">'.form::checkbox(array('globalip', 'globalip_'.$type),1).' '.
132               __('Global IP (used for all blogs)').'</label> ';
133          }
134
135          $res .=
136          $core->formNonce().
137          '</p>'.
138          '<p><input type="submit" value="'.__('Add').'"/></p>'.
139          '</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               '<h3>' . __('IP list') . '</h3>'.
152               '<div style="'.$this->style_list.'">';
153
154               $res_global = '';
155               $res_local = '';
156               while ($rs->fetch())
157               {
158                    $bits = explode(':',$rs->rule_content);
159                    $pattern = $bits[0];
160                    $ip = $bits[1];
161                    $bitmask = $bits[2];
162
163                    $disabled_ip = false;
164                    $p_style = $this->style_p;
165                    if (!$rs->blog_id) {
166                         $disabled_ip = !$core->auth->isSuperAdmin();
167                         $p_style .= $this->style_global;
168                    }
169
170                    $item =
171                    '<p style="'.$p_style.'"><label class="classic" for="'.$type.'-ip-'.$rs->rule_id.'">'.
172                    form::checkbox(array('delip[]',$type.'-ip-'.$rs->rule_id),$rs->rule_id,false,'','',$disabled_ip).' '.
173                    html::escapeHTML($pattern).
174                    '</label></p>';
175
176                    if ($rs->blog_id) {
177                         // local list
178                         if ($res_local == '') {
179                              $res_local = '<h4>'.__('Local IPs (used only for this blog)').'</h4>';
180                         }
181                         $res_local .= $item;
182                    } else {
183                         // global list
184                         if ($res_global == '') {
185                              $res_global = '<h4>'.__('Global IPs (used for all blogs)').'</h4>';
186                         }
187                         $res_global .= $item;
188                    }
189               }
190               $res .= $res_local.$res_global;
191
192               $res .=
193               '</div>'.
194               '<p><input class="submit delete" type="submit" value="'.__('Delete').'"/>'.
195               $core->formNonce().
196               form::hidden(array('ip_type'),$type).
197               '</p>'.
198               '</form>';
199          }
200
201          $res .= '</div>';
202
203          return $res;
204     }
205
206     private function ipmask($pattern,&$ip,&$mask)
207     {
208          $bits = explode('/',$pattern);
209
210          # Set IP
211          $bits[0] .= str_repeat(".0", 3 - substr_count($bits[0], "."));
212          $ip = ip2long($bits[0]);
213
214          if (!$ip || $ip == -1) {
215               throw new Exception('Invalid IP address');
216          }
217
218          # Set mask
219          if (!isset($bits[1])) {
220               $mask = -1;
221          } elseif (strpos($bits[1],'.')) {
222               $mask = ip2long($bits[1]);
223               if (!$mask) {
224                    $mask = -1;
225               }
226          } else {
227               $mask = ~((1 << (32 - $bits[1])) - 1);
228          }
229     }
230
231     private function addIP($type,$pattern,$global)
232     {
233          $this->ipmask($pattern,$ip,$mask);
234          $pattern = long2ip($ip).($mask != -1 ? '/'.long2ip($mask) : '');
235          $content = $pattern.':'.$ip.':'.$mask;
236
237          $old = $this->getRuleCIDR($type,$global,$ip,$mask);
238          $cur = $this->con->openCursor($this->table);
239
240          if ($old->isEmpty())
241          {
242               $id = $this->con->select('SELECT MAX(rule_id) FROM '.$this->table)->f(0) + 1;
243
244               $cur->rule_id = $id;
245               $cur->rule_type = (string) $type;
246               $cur->rule_content = (string) $content;
247
248               if ($global && $this->core->auth->isSuperAdmin()) {
249                    $cur->blog_id = null;
250               } else {
251                    $cur->blog_id = $this->core->blog->id;
252               }
253
254               $cur->insert();
255          }
256          else
257          {
258               $cur->rule_type = (string) $type;
259               $cur->rule_content = (string) $content;
260               $cur->update('WHERE rule_id = '.(integer) $old->rule_id);
261          }
262     }
263
264     private function getRules($type='all')
265     {
266          $strReq =
267          'SELECT rule_id, rule_type, blog_id, rule_content '.
268          'FROM '.$this->table.' '.
269          "WHERE rule_type = '".$this->con->escape($type)."' ".
270          "AND (blog_id = '".$this->core->blog->id."' OR blog_id IS NULL) ".
271          'ORDER BY blog_id ASC, rule_content ASC ';
272
273          return $this->con->select($strReq);
274     }
275
276     private function getRuleCIDR($type,$global,$ip,$mask)
277     {
278          $strReq =
279          'SELECT * FROM '.$this->table.' '.
280          "WHERE rule_type = '".$this->con->escape($type)."' ".
281          "AND rule_content LIKE '%:".(integer) $ip.":".(integer) $mask."' ".
282          'AND blog_id '.($global ? 'IS NULL ' : "= '".$this->core->blog->id."' ");
283
284          return $this->con->select($strReq);
285     }
286
287     private function checkIP($cip,$type)
288     {
289          $core =& $this->core;
290
291          $strReq =
292          'SELECT DISTINCT(rule_content) '.
293          'FROM '.$this->table.' '.
294          "WHERE rule_type = '".$this->con->escape($type)."' ".
295          "AND (blog_id = '".$this->core->blog->id."' OR blog_id IS NULL) ".
296          'ORDER BY rule_content ASC ';
297
298          $rs = $this->con->select($strReq);
299          while ($rs->fetch())
300          {
301               list($pattern,$ip,$mask) = explode(':',$rs->rule_content);
302               if ((ip2long($cip) & (integer) $mask) == ((integer) $ip & (integer) $mask)) {
303                    return $pattern;
304               }
305          }
306          return false;
307     }
308
309     private function removeRule($ids)
310     {
311          $strReq = 'DELETE FROM '.$this->table.' ';
312
313          if (is_array($ids)) {
314               foreach ($ids as $i => $v) {
315                    $ids[$i] = (integer) $v;
316               }
317               $strReq .= 'WHERE rule_id IN ('.implode(',',$ids).') ';
318          } else {
319               $ids = (integer) $ids;
320               $strReq .= 'WHERE rule_id = '.$ids.' ';
321          }
322
323          if (!$this->core->auth->isSuperAdmin()) {
324               $strReq .= "AND blog_id = '".$this->core->blog->id."' ";
325          }
326
327          $this->con->execute($strReq);
328     }
329}
330?>
Note: See TracBrowser for help on using the repository browser.

Sites map