Dotclear

source: plugins/antispam/filters/class.dc.filter.ip.php @ 2322:a75984c93a86

Revision 2322:a75984c93a86, 7.7 KB checked in by franck <carnet.franck.paul@…>, 12 years ago (diff)

Second step of contextual helps, closes #1760, now the help has to be completed.

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

Sites map