| [ Index ] |
|
Code source de b2evolution 2.1.0-beta |
1 <?php 2 /** 3 * This file implements Antispam handling functions. 4 * 5 * This file is part of the b2evolution/evocms project - {@link http://b2evolution.net/}. 6 * See also {@link http://sourceforge.net/projects/evocms/}. 7 * 8 * @copyright (c)2003-2007 by Francois PLANQUE - {@link http://fplanque.net/}. 9 * Parts of this file are copyright (c)2004-2005 by Daniel HAHLER - {@link http://thequod.de/contact}. 10 * Parts of this file are copyright (c)2004 by Vegar BERG GULDAL - {@link http://funky-m.com/}. 11 * Parts of this file are copyright (c)2005 by The University of North Carolina at Charlotte as 12 * contributed by Jason Edgecombe {@link http://tst.uncc.edu/}. 13 * 14 * @license http://b2evolution.net/about/license.html GNU General Public License (GPL) 15 * 16 * {@internal Open Source relicensing agreement: 17 * Daniel HAHLER grants Francois PLANQUE the right to license 18 * Daniel HAHLER's contributions to this file and the b2evolution project 19 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 20 * 21 * Vegar BERG GULDAL grants Francois PLANQUE the right to license 22 * Vegar BERG GULDAL's contributions to this file and the b2evolution project 23 * under any OSI approved OSS license (http://www.opensource.org/licenses/). 24 * 25 * The University of North Carolina at Charlotte grants Francois PLANQUE the right to license 26 * Jason EDGECOMBE's contributions to this file and the b2evolution project 27 * under the GNU General Public License (http://www.opensource.org/licenses/gpl-license.php) 28 * and the Mozilla Public License (http://www.opensource.org/licenses/mozilla1.1.php). 29 * }} 30 * 31 * @package evocore 32 * 33 * {@internal Below is a list of authors who have contributed to design/coding of this file: }} 34 * @author blueyed: Daniel HAHLER. 35 * @author fplanque: Francois PLANQUE. 36 * @author vegarg: Vegar BERG GULDAL. 37 * 38 * @version $Id: _antispam.funcs.php,v 1.2 2007/09/22 19:23:56 fplanque Exp $ 39 */ 40 if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' ); 41 42 43 /** 44 * antispam_create(-) 45 * 46 * Insert a new abuse string into DB 47 */ 48 function antispam_create( $abuse_string, $aspm_source = 'local' ) 49 { 50 global $DB; 51 52 // Cut the crap if the string is empty: 53 $abuse_string = trim( $abuse_string ); 54 if( empty( $abuse_string ) ) return false; 55 56 // Check if the string already is in the blacklist: 57 if( antispam_check($abuse_string) ) return false; 58 59 // Insert new string into DB: 60 $sql = "INSERT INTO T_antispam( aspm_string, aspm_source ) 61 VALUES( '".$DB->escape($abuse_string)."', '$aspm_source' )"; 62 $DB->query( $sql ); 63 64 return true; 65 } 66 67 68 /** 69 * antispam_update_source(-) 70 * 71 * Note: We search by string because we sometimes don't know the ID 72 * (e-g when download already in list/cache) 73 */ 74 function antispam_update_source( $aspm_string, $aspm_source ) 75 { 76 global $DB; 77 78 $sql = "UPDATE T_antispam 79 SET aspm_source = '$aspm_source' 80 WHERE aspm_string = '".$DB->escape($aspm_string)."'"; 81 $DB->query( $sql ); 82 } 83 84 /* 85 * antispam_delete(-) 86 * 87 * Remove an entry from the ban list 88 */ 89 function antispam_delete( $string_ID ) 90 { 91 global $DB; 92 93 $sql = "DELETE FROM T_antispam 94 WHERE aspm_ID = $string_ID"; 95 $DB->query( $sql ); 96 } 97 98 99 /** 100 * Check if a string contains abusive substrings 101 * 102 * Note: Letting the database do the LIKE %% match is a little faster than doing in it PHP, 103 * not to mention the incredibly long overhead of preloading the list into PHP 104 * 105 * @todo dh> IMHO this method is too generic used! It gets used for: 106 * - comment author name 107 * - comment/message author email 108 * - comment content 109 * - message (email) content 110 * - validate_url() 111 * ..and validates all this against the antispam blacklist! 112 * We should rather differentiate here more and make it pluggable! 113 * 114 * @return string blacklisted keyword found or false if no spam detected 115 */ 116 function antispam_check( $haystack ) 117 { 118 global $DB, $Debuglog, $Timer; 119 120 // TODO: 'SELECT COUNT(*) FROM T_antispam WHERE aspm_string LIKE "%'.$url.'%" ? 121 122 $Timer->resume( 'antispam_url' ); // resuming to get the total number.. 123 $block = $DB->get_var( 124 "SELECT aspm_string 125 FROM T_antispam 126 WHERE ".$DB->quote($haystack)." LIKE CONCAT('%',aspm_string,'%') 127 LIMIT 0, 1", 0, 0, 'Check URL against antispam blacklist' ); 128 if( $block ) 129 { 130 $Debuglog->add( 'Spam block: '.$block ); 131 return $block; // SPAM detected! 132 } 133 $Timer->pause( 'antispam_url' ); 134 135 return false; // no problem. 136 } 137 138 139 // -------------------- XML-RPC callers --------------------------- 140 141 /** 142 * Pings b2evolution.net to report abuse from a particular domain. 143 * 144 * @param string The keyword to report as abuse. 145 * @return boolean True on success, false on failure. 146 */ 147 function antispam_report_abuse( $abuse_string ) 148 { 149 global $debug, $antispamsrv_host, $antispamsrv_port, $antispamsrv_uri, $antispam_test_for_real; 150 global $baseurl, $Messages; 151 152 if( preg_match( '#^http://localhost[/:]#', $baseurl) && ( $antispamsrv_host != 'localhost' ) && empty( $antispam_test_for_real ) ) 153 { // Local install can only report to local test server 154 $Messages->add( T_('Reporting abuse to b2evolution aborted (Running on localhost).'), 'error' ); 155 return(false); 156 } 157 158 // Construct XML-RPC client: 159 load_funcs('_ext/xmlrpc/_xmlrpc.php' ); 160 $client = new xmlrpc_client( $antispamsrv_uri, $antispamsrv_host, $antispamsrv_port); 161 $client->debug = $debug; 162 163 // Construct XML-RPC message: 164 $message = new xmlrpcmsg( 165 'b2evo.reportabuse', // Function to be called 166 array( 167 new xmlrpcval(0,'int'), // Reserved 168 new xmlrpcval('annonymous','string'), // Reserved 169 new xmlrpcval('nopassrequired','string'), // Reserved 170 new xmlrpcval($abuse_string,'string'), // The abusive string to report 171 new xmlrpcval($baseurl,'string'), // The base URL of this b2evo 172 ) 173 ); 174 $result = $client->send($message); 175 if( $ret = xmlrpc_logresult( $result, $Messages ) ) 176 { // Remote operation successful: 177 antispam_update_source( $abuse_string, 'reported' ); 178 179 $Messages->add( sprintf( T_('Reported abuse to %s.'), $antispamsrv_host ), 'success' ); 180 } 181 else 182 { 183 $Messages->add( T_('Failed to report abuse to b2evolution.net.'), 'error' ); 184 } 185 186 return($ret); 187 } 188 189 190 /** 191 * Request abuse list from central blacklist. 192 * 193 * @param boolean Display while fetching it? 194 * @return boolean true = success, false = error 195 */ 196 function antispam_poll_abuse() 197 { 198 global $Messages, $Settings, $baseurl, $debug, $antispamsrv_host, $antispamsrv_port, $antispamsrv_uri; 199 200 // Construct XML-RPC client: 201 load_funcs('_ext/xmlrpc/_xmlrpc.php' ); 202 $client = new xmlrpc_client( $antispamsrv_uri, $antispamsrv_host, $antispamsrv_port); 203 $client->debug = $debug; 204 205 // Get datetime from last update, because we only want newer stuff... 206 $last_update = $Settings->get( 'antispam_last_update' ); 207 // Encode it in the XML-RPC format 208 $Messages->add( T_('Latest update timestamp').': '.$last_update, 'note' ); 209 $startat = mysql2date( 'Ymd\TH:i:s', $last_update ); 210 //$startat = iso8601_encode( mktime(substr($m,11,2),substr($m,14,2),substr($m,17,2),substr($m,5,2),substr($m,8,2),substr($m,0,4)) ); 211 212 // Construct XML-RPC message: 213 $message = new xmlrpcmsg( 214 'b2evo.pollabuse', // Function to be called 215 array( 216 new xmlrpcval(0,'int'), // Reserved 217 new xmlrpcval('annonymous','string'), // Reserved 218 new xmlrpcval('nopassrequired','string'), // Reserved 219 new xmlrpcval($startat,'dateTime.iso8601'), // Datetime to start at 220 new xmlrpcval(0,'int') // Reserved 221 ) 222 ); 223 224 $Messages->add( sprintf( T_('Requesting abuse list from %s...'), $antispamsrv_host ), 'note' ); 225 226 $result = $client->send($message); 227 228 if( $ret = xmlrpc_logresult( $result, $Messages ) ) 229 { // Response is not an error, let's process it: 230 $response = $result->value(); 231 if( $response->kindOf() == 'struct' ) 232 { // Decode struct: 233 $response = xmlrpc_decode_recurse($response); 234 if( !isset( $response['strings'] ) || !isset( $response['lasttimestamp'] ) ) 235 { 236 $Messages->add( T_('Incomplete reponse.'), 'error' ); 237 $ret = false; 238 } 239 else 240 { // Start registering strings: 241 $value = $response['strings']; 242 if( count($value) == 0 ) 243 { 244 $Messages->add( T_('No new blacklisted strings are available.'), 'note' ); 245 } 246 else 247 { // We got an array of strings: 248 $Messages->add( T_('Adding strings to local blacklist:'), 'note' ); 249 foreach($value as $banned_string) 250 { 251 if( antispam_create( $banned_string, 'central' ) ) 252 { // Creation successed 253 $Messages->add( T_('Adding:').' «'.$banned_string.'»: ' 254 .T_('OK.'), 'note' ); 255 } 256 else 257 { // Was already handled 258 $Messages->add( T_('Adding:').' «'.$banned_string.'»: ' 259 .T_('Not necessary! (Already handled)'), 'note' ); 260 antispam_update_source( $banned_string, 'central' ); 261 } 262 } 263 // Store latest timestamp: 264 $endedat = date('Y-m-d H:i:s', iso8601_decode($response['lasttimestamp']) ); 265 $Messages->add( T_('New latest update timestamp').': '.$endedat, 'note' ); 266 267 $Settings->set( 'antispam_last_update', $endedat ); 268 $Settings->dbupdate(); 269 } 270 $Messages->add( T_('Done.'), 'success' ); 271 } 272 } 273 else 274 { 275 $Messages->add( T_('Invalid reponse.'), 'error' ); 276 $ret = false; 277 } 278 } 279 280 return($ret); 281 } 282 283 284 /** 285 * Get the base domain that could be blacklisted from an URL. 286 * 287 * We want to concentrate on the main domain and we want to prefix it with either . or // in order not 288 * to blacklist too large. 289 * 290 * {@internal This function gets tested in _misc.funcs.simpletest.php}} 291 * 292 * @param string URL or domain 293 * @return string|false the pattern to match this domain in the blacklist; false if we could not extract the base domain 294 */ 295 function get_ban_domain( $url ) 296 { 297 // echo '<p>'.$url; 298 299 // Remove http:// part + everything after the last path element ( '/' alone is ignored on purpose ) 300 $domain = preg_replace( '~^ ([a-z]+://)? ([^/#]+) (/ ([^/]*/)+ )? .* ~xi', '\\2\\3', $url ); 301 302 // echo '<br>'.$domain; 303 304 if( preg_match( '~^[0-9.]+$~', $domain ) ) 305 { // All numeric = IP address, don't try to cut it any further 306 return '//'.$domain; 307 } 308 309 // Remove any www*. prefix: 310 $base_domain = preg_replace( '~^(www \w* \. )~xi', '', $domain ); 311 312 if( empty($base_domain) ) 313 { 314 return false; 315 } 316 317 if( strlen( $base_domain ) < strlen( $domain ) ) 318 { // The guy is spamming with subdomains (or www): 319 return '.'.$base_domain; 320 } 321 322 // The guy is spamming with the base domain: 323 return '//'.$base_domain; 324 } 325 326 327 /* 328 * $Log: _antispam.funcs.php,v $ 329 * Revision 1.2 2007/09/22 19:23:56 fplanque 330 * various fixes & enhancements 331 * 332 * Revision 1.1 2007/09/04 14:56:18 fplanque 333 * antispam cleanup 334 * 335 * Revision 1.1 2007/06/25 10:59:18 fplanque 336 * MODULES (refactored MVC) 337 * 338 * Revision 1.20 2007/04/26 00:11:03 fplanque 339 * (c) 2007 340 * 341 * Revision 1.19 2007/03/19 21:22:38 blueyed 342 * TODO antispam_check() 343 * 344 * Revision 1.18 2006/12/19 17:21:54 blueyed 345 * Fixed domain extraction if anchor (#) follows domain name directly. See http://forums.b2evolution.net/viewtopic.php?p=48672#48672 346 * 347 * Revision 1.17 2006/11/21 19:18:39 fplanque 348 * get_base_domain() / get_ban_domain() may need more unit tests, especially about what to do when invalid URLs are passed. 349 * 350 * Revision 1.16 2006/11/16 22:43:17 blueyed 351 * resume/pause antispam_url timer instead of start/stopping, because it may get called more than once 352 */ 353 ?>
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
| Généré le : Thu Nov 29 23:58:50 2007 | par Balluche grâce à PHPXref 0.7 |
|