- Timestamp:
- 02/17/18 18:03:29 (8 years ago)
- Branch:
- default
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
plugins/antispam/filters/class.dc.filter.ip.php
r3047 r3707 10 10 # 11 11 # -- END LICENSE BLOCK ----------------------------------------- 12 if (!defined('DC_RC_PATH')) { return;}12 if (!defined('DC_RC_PATH')) {return;} 13 13 14 14 class dcFilterIP extends dcSpamFilter 15 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 public 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 } 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 try 73 { 74 $global = !empty($_POST['globalip']) && $core->auth->isSuperAdmin(); 75 76 $this->addIP($ip_type, $_POST['addip'], $global); 77 dcPage::addSuccessNotice(__('IP address has been successfully added.')); 78 http::redirect($url . '&ip_type=' . $ip_type); 79 } catch (Exception $e) { 80 $core->error->add($e->getMessage()); 81 } 82 } 83 84 # Remove IP from list 85 if (!empty($_POST['delip']) && is_array($_POST['delip'])) { 86 try { 87 $this->removeRule($_POST['delip']); 88 dcPage::addSuccessNotice(__('IP addresses have been successfully removed.')); 89 http::redirect($url . '&ip_type=' . $ip_type); 90 } catch (Exception $e) { 91 $core->error->add($e->getMessage()); 92 } 93 } 94 95 /* DISPLAY 96 ---------------------------------------------- */ 97 $res = dcPage::notices(); 98 99 $res .= 100 $this->displayForms($url, 'black', __('Blacklist')) . 101 $this->displayForms($url, 'white', __('Whitelist')); 102 103 return $res; 104 } 105 106 private function displayForms($url, $type, $title) 107 { 108 $core = &$this->core; 109 110 $res = 111 '<div class="multi-part" id="tab_' . $type . '" title="' . $title . '">' . 112 113 '<form action="' . html::escapeURL($url) . '" method="post" class="fieldset">' . 114 115 '<p>' . 116 form::hidden(array('ip_type'), $type) . 117 '<label class="classic" for="addip_' . $type . '">' . __('Add an IP address: ') . '</label> ' . 118 form::field(array('addip', 'addip_' . $type), 18, 255); 119 if ($core->auth->isSuperAdmin()) { 120 $res .= '<label class="classic" for="globalip_' . $type . '">' . form::checkbox(array('globalip', 'globalip_' . $type), 1) . ' ' . 121 __('Global IP (used for all blogs)') . '</label> '; 122 } 123 124 $res .= 125 $core->formNonce() . 126 '</p>' . 127 '<p><input type="submit" value="' . __('Add') . '"/></p>' . 128 '</form>'; 129 130 $rs = $this->getRules($type); 131 132 if ($rs->isEmpty()) { 133 $res .= '<p><strong>' . __('No IP address in list.') . '</strong></p>'; 134 } else { 135 $res .= 136 '<form action="' . html::escapeURL($url) . '" method="post">' . 137 '<h3>' . __('IP list') . '</h3>' . 138 '<div class="antispam">'; 139 140 $res_global = ''; 141 $res_local = ''; 142 while ($rs->fetch()) { 143 $bits = explode(':', $rs->rule_content); 144 $pattern = $bits[0]; 145 $ip = $bits[1]; 146 $bitmask = $bits[2]; 147 148 $disabled_ip = false; 149 $p_style = ''; 150 if (!$rs->blog_id) { 151 $disabled_ip = !$core->auth->isSuperAdmin(); 152 $p_style .= ' global'; 153 } 154 155 $item = 156 '<p class="' . $p_style . '"><label class="classic" for="' . $type . '-ip-' . $rs->rule_id . '">' . 157 form::checkbox(array('delip[]', $type . '-ip-' . $rs->rule_id), $rs->rule_id, 158 array( 159 'disabled' => $disabled_ip 160 ) 161 ) . ' ' . 162 html::escapeHTML($pattern) . 163 '</label></p>'; 164 165 if ($rs->blog_id) { 166 // local list 167 if ($res_local == '') { 168 $res_local = '<h4>' . __('Local IPs (used only for this blog)') . '</h4>'; 169 } 170 $res_local .= $item; 171 } else { 172 // global list 173 if ($res_global == '') { 174 $res_global = '<h4>' . __('Global IPs (used for all blogs)') . '</h4>'; 175 } 176 $res_global .= $item; 177 } 178 } 179 $res .= $res_local . $res_global; 180 181 $res .= 182 '</div>' . 183 '<p><input class="submit delete" type="submit" value="' . __('Delete') . '"/>' . 184 $core->formNonce() . 185 form::hidden(array('ip_type'), $type) . 186 '</p>' . 187 '</form>'; 188 } 189 190 $res .= '</div>'; 191 192 return $res; 193 } 194 195 private function ipmask($pattern, &$ip, &$mask) 196 { 197 $bits = explode('/', $pattern); 198 199 # Set IP 200 $bits[0] .= str_repeat(".0", 3 - substr_count($bits[0], ".")); 201 $ip = ip2long($bits[0]); 202 203 if (!$ip || $ip == -1) { 204 throw new Exception('Invalid IP address'); 205 } 206 207 # Set mask 208 if (!isset($bits[1])) { 209 $mask = -1; 210 } elseif (strpos($bits[1], '.')) { 211 $mask = ip2long($bits[1]); 212 if (!$mask) { 213 $mask = -1; 214 } 215 } else { 216 $mask = ~((1 << (32 - $bits[1])) - 1); 217 } 218 } 219 220 public function addIP($type, $pattern, $global) 221 { 222 $this->ipmask($pattern, $ip, $mask); 223 $pattern = long2ip($ip) . ($mask != -1 ? '/' . long2ip($mask) : ''); 224 $content = $pattern . ':' . $ip . ':' . $mask; 225 226 $old = $this->getRuleCIDR($type, $global, $ip, $mask); 227 $cur = $this->con->openCursor($this->table); 228 229 if ($old->isEmpty()) { 230 $id = $this->con->select('SELECT MAX(rule_id) FROM ' . $this->table)->f(0) + 1; 231 232 $cur->rule_id = $id; 233 $cur->rule_type = (string) $type; 234 $cur->rule_content = (string) $content; 235 236 if ($global && $this->core->auth->isSuperAdmin()) { 237 $cur->blog_id = null; 238 } else { 239 $cur->blog_id = $this->core->blog->id; 240 } 241 242 $cur->insert(); 243 } else { 244 $cur->rule_type = (string) $type; 245 $cur->rule_content = (string) $content; 246 $cur->update('WHERE rule_id = ' . (integer) $old->rule_id); 247 } 248 } 249 250 private function getRules($type = 'all') 251 { 252 $strReq = 253 'SELECT rule_id, rule_type, blog_id, rule_content ' . 254 'FROM ' . $this->table . ' ' . 255 "WHERE rule_type = '" . $this->con->escape($type) . "' " . 256 "AND (blog_id = '" . $this->core->blog->id . "' OR blog_id IS NULL) " . 257 'ORDER BY blog_id ASC, rule_content ASC '; 258 259 return $this->con->select($strReq); 260 } 261 262 private function getRuleCIDR($type, $global, $ip, $mask) 263 { 264 $strReq = 265 'SELECT * FROM ' . $this->table . ' ' . 266 "WHERE rule_type = '" . $this->con->escape($type) . "' " . 267 "AND rule_content LIKE '%:" . (integer) $ip . ":" . (integer) $mask . "' " . 268 'AND blog_id ' . ($global ? 'IS NULL ' : "= '" . $this->core->blog->id . "' "); 269 270 return $this->con->select($strReq); 271 } 272 273 private function checkIP($cip, $type) 274 { 275 $core = &$this->core; 276 277 $strReq = 278 'SELECT DISTINCT(rule_content) ' . 279 'FROM ' . $this->table . ' ' . 280 "WHERE rule_type = '" . $this->con->escape($type) . "' " . 281 "AND (blog_id = '" . $this->core->blog->id . "' OR blog_id IS NULL) " . 282 'ORDER BY rule_content ASC '; 283 284 $rs = $this->con->select($strReq); 285 while ($rs->fetch()) { 286 list($pattern, $ip, $mask) = explode(':', $rs->rule_content); 287 if ((ip2long($cip) & (integer) $mask) == ((integer) $ip & (integer) $mask)) { 288 return $pattern; 289 } 290 } 291 return false; 292 } 293 294 private function removeRule($ids) 295 { 296 $strReq = 'DELETE FROM ' . $this->table . ' '; 297 298 if (is_array($ids)) { 299 foreach ($ids as $i => $v) { 300 $ids[$i] = (integer) $v; 301 } 302 $strReq .= 'WHERE rule_id IN (' . implode(',', $ids) . ') '; 303 } else { 304 $ids = (integer) $ids; 305 $strReq .= 'WHERE rule_id = ' . $ids . ' '; 306 } 307 308 if (!$this->core->auth->isSuperAdmin()) { 309 $strReq .= "AND blog_id = '" . $this->core->blog->id . "' "; 310 } 311 312 $this->con->execute($strReq); 313 } 322 314 }
Note: See TracChangeset
for help on using the changeset viewer.