diff -ruN /tmp/spamplemousse/inc/tb.php spamplemousse/inc/tb.php --- /tmp/spamplemousse/inc/tb.php 2005-12-27 22:01:30.000000000 +0100 +++ spamplemousse/inc/tb.php 2006-03-13 22:34:33.000000000 +0100 @@ -21,6 +21,9 @@ * ***** END LICENSE BLOCK ***** */ +define(SUSPICIOUS_SCORE, 0); +define(SPAM_SCORE, 8.0); + # on regarde si le plugin est activé $desc = implode('', file(dirname(__FILE__).'/../desc.xml')); if (strpos($desc, 'active="true"') || strpos($desc, 'active="1"')) { @@ -37,7 +40,19 @@ # on teste si le trackback est du spam, # si ce n'est pas le cas on rend la main au script initial $spam = spamfilter::is_spam($blog_name, '', $url, $ip, $comment); - if ($spam !== false) { + + $message=''; + if ($spam > SPAM_SCORE) { + $err = $blog->error(0); + $content = + '1'."\n". + 'Sorry no spam allowed. Listed in many RBLs our SURBLs ? Matching my adult/casino/pharmacy buzzwords ?'; + $con->close(); + echo $content."\n"; + echo ''; + exit; + } + elseif( (is_numeric($spam) && ($spam > SUSPICIOUS_SCORE) ) or (!is_numeric($spam) && ($spam !== false))) { $moderation = new moderation($blog); $id = $moderation->addComment($id, $blog_name, '', $url, $comment, true, dc_time_delta, dc_comments_pub, $spam, $ip); if ($id !== false) { diff -ruN /tmp/spamplemousse/l10n/fr/main.lang spamplemousse/l10n/fr/main.lang --- /tmp/spamplemousse/l10n/fr/main.lang 2005-12-27 21:08:33.000000000 +0100 +++ spamplemousse/l10n/fr/main.lang 2006-03-10 22:17:07.000000000 +0100 @@ -58,3 +58,5 @@ ;By Par +;Sorry, your messsage is a spam. I don't accept spam. Go away ! +Tu envoyes du spam ? Désolé, je n'accepte pas le spam. diff -ruN /tmp/spamplemousse/l10n/fr-utf8/main.lang spamplemousse/l10n/fr-utf8/main.lang --- /tmp/spamplemousse/l10n/fr-utf8/main.lang 2005-12-27 22:39:45.000000000 +0100 +++ spamplemousse/l10n/fr-utf8/main.lang 2006-03-10 22:17:38.000000000 +0100 @@ -58,3 +58,6 @@ ;By Par +;Sorry, your messsage is a spam. I don't accept spam. Go away ! +Tu envoyes du spam ? Désolé, je n'accepte pas le spam. + diff -ruN /tmp/spamplemousse/lib/class.spamfilter.php spamplemousse/lib/class.spamfilter.php --- /tmp/spamplemousse/lib/class.spamfilter.php 2005-12-26 17:31:54.000000000 +0100 +++ spamplemousse/lib/class.spamfilter.php 2006-03-13 23:17:25.000000000 +0100 @@ -22,6 +22,7 @@ */ require_once dirname(__FILE__).'/rbl.php'; +require_once dirname(__FILE__).'/surbl.php'; /** @class spamfilter @@ -92,18 +93,25 @@ function chk_spamwords($str) { global $con; + $words_score = 0; # récupération de la liste de mots spam + # TODO : donner un poids aux mots-spams (y compris négatif). $req = 'SELECT * FROM '.DB_PREFIX.'spamwords'; $res = $con->select($req); - # on compare les chaines en minuscules (strpos est sensible à la casse) + # on compare les chaines en minuscules (substr_count est sensible à la casse) + # TODO : recherche de mots-clefs spams via une regex ? $str = strtolower($str); while ($res->fetch()) { - if (strpos($str, $res->f('spamwords_word'), 0) !== false) - return true; + $occ = substr_count($str, $res->f('spamwords_word')); + if($occ) { + # TODO formule expérimentale + #echo $res->f('spamwords_word') . " $occ $words_score
"; + $words_score += min(pow(1.2, $occ), 3); + } } - return false; + return $words_score; } /** @@ -139,22 +147,35 @@ @param string authorURL url du site de l'auteur @param string authorIP ip de l'auteur @param string content contenu du commentaire - @return mixed id du filtre qui a répondu positivement, ou false si ce n'est pas du spam + return integer score du message (0 neutre ; > 0 douteux ; < 0 a priori clean) + + TODO : donner une réponse contenant les filtres qui nous ont heurtés ? + (simuler ancien fonctionnement) */ function is_spam($author, $authorMail, $authorURL, $authorIP, $content) { - -//* - # test de l'ip sur les rbl - if (rbl_lookup($authorIP) != '') - return 'RBL'; -//*/ + $score = 0; + + # Multiplie le nombre de RBL où la chose est listée par 3 + $score += rbl_lookup($authorIP) * 3; - # test de la présence de mots spam - if (spamfilter::chk_spamwords($author.' '.$authorMail.' '.$authorURL.' '.$content)) - return 'spamword'; + # score mots-clefs + $score += spamfilter::chk_spamwords($author.' '.$authorMail.' '.$authorURL.' '.$content) ; - return false; + # Formate si nécessaire l'URL de trackback/auteur + if(!preg_match("/^http:\/\//i", $authorURL)) + $authorURL = 'http://' . $authorURL; + + # score des SURBLS + $score += surbl_lookup($content, $ur_1) * 3; + $score += surbl_lookup($authorURL, $ur_2) * 5.01; + # (une RBL + URL de trackback en SURBL -> SPAM) + + # Pas d'URL ? Dans ce cas, difficile de faire un spam + if( ($ur_1 + $ur_2)==0) + $score -= 1000; + + return $score; } } diff -ruN /tmp/spamplemousse/lib/rbl.php spamplemousse/lib/rbl.php --- /tmp/spamplemousse/lib/rbl.php 2005-12-27 20:27:27.000000000 +0100 +++ spamplemousse/lib/rbl.php 2006-03-11 00:06:09.000000000 +0100 @@ -14,29 +14,46 @@ /* rbl list: an array of RBLs to look in + + TODO Spamplemousse : + 1. rendre cette liste configurable dans l'interface d'admin + 2. permettre de donner un poids aux RBL (celui-ci pouvant être, pourquoi pas, négatif) + + Une liste de RBLs se trouve par ici : http://www.moensted.dk/spam/ */ $rbls = array( 'bl.blbl.org', // blacklist de spam de commentaires 'bl.spamcop.net', // blacklist de spam de mails //'sbl.spamhaus.org', // blacklist de spam de mails (compris dans sbl-xbl.spamhaus.org) //'opm.blitzed.org', // blacklist d'open proxies (compris dans sbl-xbl.spamhaus.org) - 'sbl-xbl.spamhaus.org' // blacklist généraliste : spam, open proxies, exploits + 'sbl-xbl.spamhaus.org', // blacklist généraliste : spam, open proxies, exploits + + // Par pays (oui, c'est raciste & chauvin. De tte façon avec des commentaires + // en Français, vous vous attendiez à quoi ?) + 'cn.countries.nerd.dk', // Chine + 'brazil.blackholes.us', + 'argentina.blackholes.us', + 'korea.blackholes.us', + 'russia.blackholes.us', + + 'sagonet.blackholes.us' // ISP de merde qui m'a que trop cassé les c*uilles ); //this function does the actual lookup; it's here so it can be called externally function rbl_lookup($ip) { global $rbls; + $rbl_score=0; if (preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/', $ip, $matches)) { foreach ($rbls as $rbl) { $rblhost = $matches[4] . '.' . $matches[3] . '.' . $matches[2] . '.' . $matches[1] . '.' . $rbl.'.'; $resolved = gethostbyname($rblhost); if ($resolved != $rblhost) { - return $rbl; + $rbl_score++; } } } - return ''; + return $rbl_score; } diff -ruN /tmp/spamplemousse/lib/surbl.php spamplemousse/lib/surbl.php --- /tmp/spamplemousse/lib/surbl.php 1970-01-01 01:00:00.000000000 +0100 +++ spamplemousse/lib/surbl.php 2006-03-13 22:44:29.000000000 +0100 @@ -0,0 +1,77 @@ + http://pear.php.net/package/Net_DNSBL + */ + +$surbls = array('multi.surbl.org'); + +//this function does the actual lookup; it's here so it can be called externally +function surbl_lookup($text, &$tested) { + + global $surbls; + $surbl_score=0; + $tested = 0; + + $regex_url_1 = "/(?:ftp:\/\/|http:\/\/|https:\/\/)(?:www.)?([^'\/\"<\s]*)/im"; + preg_match_all($regex_url_1, $text, $regex_array_1); + + $regex_url_2 = "/(www.)([^'\/\"<\s]*)/im"; + preg_match_all($regex_url_2, $text, $regex_array_2); + + $uri_array = array_unique(array_merge($regex_array_1[1], $regex_array_2[2])); + + // Nous disposons maintenant de l'intégrale du texte donné en entrée, on va donc pouvoir lancer + // le check. + + foreach ($uri_array as $vhost ) { + $virtual_host = rtrim($vhost,"\\"); + + // Présence d'une IP numérique ? + if (preg_match('/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/', $virtual_host, $matches)) { + $domain_to_test = $matches[4] . '.' . $matches[3] . '.' . $matches[2] . '.' . $matches[1]; + } + else { + // Sinon, choper le vhost + $split_array = preg_split('/\./', $virtual_host); + $dot_array = array_reverse($split_array); + + // Pas de la regex de pédé... et pourtant ça reste approximatif + // on devrait checker par rapport à ça : http://spamcheck.freeapp.net/two-level-tlds + // mais bon + $double_TLD = "/([-_a-z0-9]+\.((ac|gov|org|co|com|edu|mil|biz|net)\.[a-z]{2,3}|web\.pk|(a|pp|m)\.se|(sc|go|ne)\.ug|(info|pro|name)\.tt|(ltd\.co|plc\.co|nic)\.im|[a-z]{2}\.us|(or|fi|ed|go|sa)\.cr|gouv\.fr|ath\.cx|fr\.st|[a-z]{2}\.ça|(gr|ne|or)\.jp))$/i"; + + if(preg_match($double_TLD, $virtual_host)) + $domain_to_test = $dot_array[2] .'.'. $dot_array[1] .'.'. $dot_array[0]; + else + $domain_to_test = $dot_array[1] .'.'. $dot_array[0]; + } + + // Le check propremeent dit. + if (strlen($domain_to_test) > 3) { + $tested++; + foreach ($surbls as $surbl) { + $dnsreq = $domain_to_test . '.' . $surbl; + $resolv = gethostbyname($dnsreq); + if( $resolv != $dnsreq ) { + $surbl_score++; + } + } + } + } + + // URL testés : $tested + return $surbl_score; +} + + +?> diff -ruN /tmp/spamplemousse/postcon.php spamplemousse/postcon.php --- /tmp/spamplemousse/postcon.php 2005-12-27 22:01:45.000000000 +0100 +++ spamplemousse/postcon.php 2006-03-11 02:23:13.000000000 +0100 @@ -23,6 +23,9 @@ # ce script gère le filtrage des commentaires +define(SUSPICIOUS_SCORE, 0); +define(SPAM_SCORE, 8.0); + # on regarde si le plugin est activé $desc = implode('', file(dirname(__FILE__).'/desc.xml')); if (strpos($desc, 'active="true"') || strpos($desc, 'active="1"')) { @@ -47,7 +50,10 @@ $ip = spamfilter::realip(@$_SERVER['REMOTE_ADDR'], @$_SERVER['HTTP_X_FORWARDED_FOR']); # On teste assez tot si c'est du spam, si ce n'en est pas on rend la main au fonctionnement normal $spam = spamfilter::is_spam($nom,$mail,$site, $ip, trim($_POST['c_content'])); - if ($spam !== false) { + if ($spam > SPAM_SCORE) { + $blog->setError(__("Sorry, your messsage is a spam. I don't accept spam. Go away !")); + } + elseif( (is_numeric($spam) && ($spam > SUSPICIOUS_SCORE) ) or (!is_numeric($spam) && ($spam !== false))) { # localisation $__lang = (!empty($lang)) ? $lang : dc_default_lang; if (dc_encoding == 'UTF-8') { @@ -153,8 +159,8 @@ } # avertissement de l'utilisateur, son message est dans la file de modération - if (!empty($_GET['mod'])) { - $form_msg = __('Your comment has been sent '. + if(!empty($_GET['mod'])) { + $form_msg = __('Your comment has been sent '. 'successfully. It will be online soon.'); } }