/** * Verification supplementaire antispam sur le formulaire_ecrire_auteur * * @param array $flux * @return array */ function nospam_verifier_formulaire_ecrire_auteur_dist($flux) { $form = $flux['args']['form']; if (!isset($flux['data']['texte_message_auteur'])) { include_spip("inc/nospam"); include_spip("inc/texte"); // regarder si il y a du contenu en dehors des liens ! $texte_message_auteur = _request('texte_message_auteur'); $caracteres = compter_caracteres_utiles($texte_message_auteur); if ($caracteres < 10) { $flux['data']['texte_message_auteur'] = _T('forum_attention_dix_caracteres'); unset($flux['data']['previsu']); } // on analyse le sujet $infos_sujet = analyser_spams(_request('sujet_message_auteur')); // si un lien dans le sujet = spam ! if ($infos_sujet['nombre_liens'] > 0) { $flux['data']['sujet_message_auteur'] = _T('nospam:erreur_spam'); unset($flux['data']['previsu']); } // on analyse le texte $infos_texte = analyser_spams($texte_message_auteur); if ($infos_texte['nombre_liens'] > 0) { // si un lien a un titre de moins de 3 caracteres = spam ! if ($infos_texte['caracteres_texte_lien_min'] < 3) { $flux['data']['texte_message_auteur'] = _T('nospam:erreur_spam'); } // si le texte contient plus de trois liens = spam ! if ($infos_texte['nombre_liens'] >= 3) { $flux['data']['texte_message_auteur'] = _T('nospam:erreur_spam'); } } } return $flux; }
/** * Verification supplementaire antispam sur le formulaire_signature * * @param array $flux * @return array */ function nospam_verifier_formulaire_signature_dist($flux) { $form = $flux['args']['form']; $id_article = $flux['args']['args'][0]; $row = sql_fetsel('*', 'spip_petitions', "id_article=" . intval($id_article)); if (!isset($flux['data']['message']) && $row['message'] == "oui") { include_spip("inc/nospam"); include_spip("inc/texte"); // regarder si il y a du contenu en dehors des liens ! $message = _request('message'); // on analyse le texte $infos_texte = analyser_spams($message); if ($infos_texte['nombre_liens'] > 0) { // si un lien a un titre de moins de 3 caracteres = spam ! if ($infos_texte['caracteres_texte_lien_min'] < 3) { $flux['data']['message_erreur'] = _T('nospam:erreur_spam'); } // si le texte contient plus de trois liens = spam ! if ($infos_texte['nombre_liens'] >= 2) { $flux['data']['message_erreur'] = _T('nospam:erreur_spam'); } } } // S'il y a un lien dans le champ session_nom => spam if (!isset($flux['data']['session_nom'])) { include_spip("inc/nospam"); $infos_texte = analyser_spams(_request('session_nom')); if ($infos_texte['nombre_liens'] > 0) { $flux['data']['message_erreur'] = _T('nospam:erreur_spam'); spip_log("Lien dans le champ session_nom " . $flux['data']['message_erreur'], 'nospam'); } } return $flux; }
/** * Au moment de decider du statut d'un forum, * quelques verifications et une moderation si necessaire ! * * @param array $flux * @return array */ function nospam_pre_edition($flux) { if ($flux['args']['table'] == 'spip_forum' and $flux['args']['action'] == 'instituer') { // ne pas publier automatiquement certains messages suspects ... // sauf si le posteur a de toute facon le pouvoir de moderer et de se publier include_spip('inc/autoriser'); if (in_array($flux['data']['statut'], array('prop', 'publie')) and (!isset($GLOBALS['visiteur_session']['statut']) or !autoriser('modererforum'))) { // verifier le status de cette IP nospam_check_ip_status($GLOBALS['ip']); $email = strlen($flux['data']['email_auteur']) ? " OR email_auteur=" . sql_quote($flux['data']['email_auteur']) : ""; $spammeur_connu = (!isset($GLOBALS['visiteur_session']['statut']) and (isset($GLOBALS['ip_greylist'][$GLOBALS['ip']]) or isset($GLOBALS['ip_blacklist'][$GLOBALS['ip']]) or sql_countsel('spip_forum', '(ip=' . sql_quote($GLOBALS['ip']) . "{$email}) AND statut='spam'") > 0)); // activer aussi le flag spammeur connu en cas de flood, meme si aucune detection spam jusqu'ici // on sera plus severe sur les liens dans ce cas // cas du spammeur qui envoie que des messages a 3 liens a haute frequence (passe a travers tous les filtres) // au bout du 5e message en <10min ou 10e en <30min on va moderer tout message avec un lien if (!$spammeur_connu) { if (($nb = sql_countsel('spip_forum', '(ip=' . sql_quote($GLOBALS['ip']) . $email . ') AND ' . nospam_sql_date_proche('date_heure', '-30', 'minute'))) >= 7) { spip_log("[Flood] {$nb} message pour (ip=" . $GLOBALS['ip'] . "{$email}) dans les 30 dernieres minutes", 'nospam'); $spammeur_connu = true; } } if (!$spammeur_connu) { if (($nb = sql_countsel('spip_forum', '(ip=' . sql_quote($GLOBALS['ip']) . $email . ') AND ' . nospam_sql_date_proche('date_heure', '-10', 'minute'))) >= 3) { spip_log("[Flood] {$nb} message pour (ip=" . $GLOBALS['ip'] . "{$email}) dans les 10 dernieres minutes", 'nospam'); $spammeur_connu = true; } } $lang_suspecte = false; // si c'est un spammeur connu, // verifier que cette ip n'en est pas a son N-ieme spam en peu de temps // a partir d'un moment on refuse carrement le spam massif, le posteur devra attendre pour reposter if ($spammeur_connu) { // plus de 30 spams dans les dernieres 2h, faut se calmer ... // ou plus de 10 spams dans la dernieres 1h, faut se calmer ... // ou IP blacklistee et plus de 5 messages prop/spam dans les dernieres 48h, faut se calmer ... if (isset($GLOBALS['ip_blacklist'][$GLOBALS['ip']]) and ($nb = sql_countsel('spip_forum', sql_in('statut', array('spam')) . ' AND (ip=' . sql_quote($GLOBALS['ip']) . ') AND ' . nospam_sql_date_proche('date_heure', '-48', 'hour'))) >= 5 and $h = 48 or ($nb = sql_countsel('spip_forum', 'statut=\'spam\' AND (ip=' . sql_quote($GLOBALS['ip']) . $email . ') AND ' . nospam_sql_date_proche('date_heure', '-120', 'minute'))) >= 30 and $h = 2 or ($nb = sql_countsel('spip_forum', 'statut=\'spam\' AND (ip=' . sql_quote($GLOBALS['ip']) . $email . ') AND ' . nospam_sql_date_proche('date_heure', '-60', 'minute'))) >= 10 and $h = 1) { $flux['data']['statut'] = ''; // on n'en veut pas ! spip_log("[Refuse] {$nb} spam pour (ip=" . $GLOBALS['ip'] . "{$email}) dans les {$h} dernieres heures", 'nospam'); return $flux; } spip_log("POST *suspect* spammeur_connu", "nospam"); } else { $lang_objet = $GLOBALS['spip_lang'] ? $GLOBALS['spip_lang'] : $GLOBALS['meta']['langue_site']; if ($flux['data']['objet']) { $table = table_objet_sql($flux['data']['objet']); $trouver_table = charger_fonction("trouver_table", "base"); if ($desc = $trouver_table($table) and isset($desc['field']['lang'])) { $primary = id_table_objet($flux['data']['objet']); $lang_objet = sql_getfetsel("lang", $table, "{$primary}=" . intval($flux['data']['id_objet'])); } } include_spip("inc/detecter_langue"); $lang_post = _detecter_langue($flux['data']['texte']); if ($lang_post !== $lang_objet) { $lang_suspecte = true; } spip_log("POST " . ($lang_suspecte ? "*suspect* " : "") . "en langue [{$lang_post}] sur {$primary}=" . $flux['data']['id_objet'] . " en langue [{$lang_objet}]", "nospam"); } // si c'est un message bourre de liens, on le modere // le seuil varie selon le champ et le fait que le spammeur est deja connu ou non $seuils = array(0 => array(0 => array(1 => 'prop', 3 => 'spam'), 'url_site' => array(2 => 'spam'), 'texte' => array(4 => 'prop', 20 => 'spam')), 'suspect' => array(0 => array(1 => 'spam'), 'url_site' => array(2 => 'spam'), 'texte' => array(1 => 'prop', 5 => 'spam')), 'blacklist' => array(0 => array(1 => 'spam'), 'url_site' => array(2 => 'spam'), 'texte' => array(0 => 'prop', 1 => 'spam'))); $seuils = isset($GLOBALS['ip_blacklist'][$GLOBALS['ip']]) ? $seuils['blacklist'] : (($spammeur_connu or $lang_suspecte) ? $seuils['suspect'] : $seuils[0]); include_spip("inc/nospam"); // pour analyser_spams() foreach ($flux['data'] as $champ => $valeur) { $infos = analyser_spams($valeur); if ($infos['contenu_cache']) { // s'il y a du contenu caché avec des styles => spam direct $flux['data']['statut'] = 'spam'; spip_log("\t" . $flux['data']['auteur'] . "\t" . $GLOBALS['ip'] . "\t" . "requalifié en spam car contenu cache", 'nospam'); } elseif ($infos['nombre_liens'] > 0) { // si un lien a un titre de moins de 3 caracteres, c'est louche... if ($infos['caracteres_texte_lien_min'] < 3) { $flux['data']['statut'] = 'prop'; // en dur en attendant une idee plus generique spip_log("\t" . $flux['data']['auteur'] . "\t" . $GLOBALS['ip'] . "\t" . "requalifié en prop car moins de 3car hors liens", 'nospam'); } if (isset($seuils[$champ])) { $seuil = $seuils[$champ]; } else { $seuil = $seuils[0]; } foreach ($seuil as $s => $stat) { if ($infos['nombre_liens'] >= $s) { $flux['data']['statut'] = $stat; spip_log("\t" . $flux['data']['auteur'] . "\t" . $GLOBALS['ip'] . "\t" . "requalifié en " . $stat . " car nombre_liens >= " . $s, 'nospam'); } } if ($flux['data']['statut'] != 'spam') { $champs = array_unique(array('texte', $champ)); if ($h = rechercher_presence_liens_spammes($infos['liens'], _SPAM_URL_MAX_OCCURENCES, 'spip_forum', $champs)) { $flux['data']['statut'] = 'spam'; spip_log("\t" . $flux['data']['auteur'] . "\t" . $GLOBALS['ip'] . "\t" . "requalifié en spam car lien {$h} deja dans un spam", 'nospam'); } } } } // verifier qu'un message identique n'a pas ete publie il y a peu if ($flux['data']['statut'] != 'spam') { if (sql_countsel('spip_forum', 'texte=' . sql_quote($flux['data']['texte']) . " AND statut IN ('publie','off','spam')") > 0) { $flux['data']['statut'] = 'spam'; spip_log("\t" . $flux['data']['auteur'] . "\t" . $GLOBALS['ip'] . "\t" . "requalifié en spam car message identique deja existant", 'nospam'); } } // verifier que cette ip n'en est pas a son N-ieme post en peu de temps // plus de 5 messages en 5 minutes c'est suspect ... if ($flux['data']['statut'] != 'spam') { if (($nb = sql_countsel('spip_forum', 'ip=' . sql_quote($GLOBALS['ip']) . ' AND ' . nospam_sql_date_proche('date_heure', '-5', 'minute'))) >= 5) { $flux['data']['statut'] = 'spam'; spip_log("[Flood2] {$nb} message pour (ip=" . $GLOBALS['ip'] . "{$email}) dans les 5 dernieres minutes : requalif en spam", 'nospam'); } } } } return $flux; }
/** * Verification supplementaire antispam sur le formulaire_forum * * @param array $flux * @return array */ function nospam_verifier_formulaire_forum_dist($flux) { $form = $flux['args']['form']; if (!isset($flux['data']['texte']) and $GLOBALS['meta']['forums_texte'] == 'oui') { $texte = _request('texte'); include_spip("inc/nospam"); // regarder si il y a du contenu en dehors des liens ! $caracteres = compter_caracteres_utiles($texte); $min_length = defined('_FORUM_LONGUEUR_MINI') ? _FORUM_LONGUEUR_MINI : 10; if ($caracteres < $min_length) { $flux['data']['texte'] = _T('forum_attention_dix_caracteres'); } // regarder si il y a du contenu cache if (!isset($flux['data']['texte'])) { $infos = analyser_spams($texte); if (isset($infos['contenu_cache']) and $infos['contenu_cache']) { $flux['data']['texte'] = _T('nospam:erreur_attributs_html_interdits'); } } // regarder si il y a des liens deja references par des spammeurs if (!isset($flux['data']['texte']) and isset($infos['liens']) and count($infos['liens'])) { if ($h = rechercher_presence_liens_spammes($infos['liens'], _SPAM_URL_MAX_OCCURENCES, 'spip_forum', array('texte'))) { spip_log("Refus message de forum qui contient un lien vers {$h}", "nospam"); $flux['data']['texte'] = _T('nospam:erreur_url_deja_spammee'); } } // on prend en compte la checkbox de confirmation // si le flag en session est bien leve if (_request('notabuse')) { session_start(); if ($_SESSION['notabuse_check']) { unset($_SESSION['notabuse_check']); $_SESSION['notabuse_checked'] = true; // on leve une globale pour la fin de ce hit, a toute fin utile (puisque plus rien en $_SESSION) $GLOBALS['notabuse_checked'] = true; } } if (!count($flux['data'])) { if (nospam_check_ip_status($GLOBALS['ip']) !== 'ok') { session_start(); if ($_SESSION['notabuse_checked']) { // ok on retire de la session le check qui ne sert qu'une fois unset($_SESSION['notabuse_checked']); // et on laisse passer } else { $flux['data']['texte'] = _T('nospam:info_ip_suspecte') . "<br />\n\t\t\t\t\t<span class='choix'>\n\t\t\t\t\t<input type='checkbox' name='notabuse' value='1' id='notabuse'/> <label for='notabuse'>" . _T('nospam:label_message_licite') . "</label>\n\t\t\t\t\t</span>"; $_SESSION['notabuse_check'] = true; spip_log("notabuse_check sur IP " . $GLOBALS['ip'], "nospam"); } } } // si il y a une erreur, pas de previsu, on reste bloque a la premiere etape if (isset($flux['data']['texte'])) { unset($flux['data']['previsu']); } elseif (!count($flux['data'])) { $now = $_SERVER['REQUEST_TIME']; // calculer la "popularite" des POST forums et forums avec liens if (!isset($GLOBALS['meta']['nospam_pop_forum_post'])) { $GLOBALS['meta']['nospam_pop_forum_post'] = 0; } if (!isset($GLOBALS['meta']['nospam_pop_forum_postwlink'])) { $GLOBALS['meta']['nospam_pop_forum_postwlink'] = 0; } if (!isset($GLOBALS['meta']['nospam_pop_date'])) { $GLOBALS['meta']['nospam_pop_date'] = date('Y-m-d H:i:s', $now); } $duree = max($now - strtotime($GLOBALS['meta']['nospam_pop_date']), 1); list($a, $b) = nospam_popularite_constantes($duree); spip_log("Pop forum : {$duree}, {$a}, {$b}", "nospam"); // decrementer if ($duree > 1800) { $GLOBALS['meta']['nospam_pop_date'] = date('Y-m-d H:i:s', $now); $GLOBALS['meta']['nospam_pop_forum_post'] = round(floatval($GLOBALS['meta']['nospam_pop_forum_post']) * $a, 2); $GLOBALS['meta']['nospam_pop_forum_postwlink'] = round(floatval($GLOBALS['meta']['nospam_pop_forum_postwlink']) * $a, 2); spip_log("Pop Decremente : " . $GLOBALS['meta']['nospam_pop_forum_post'] . ", " . $GLOBALS['meta']['nospam_pop_forum_postwlink'], "nospam"); } // incrementer $GLOBALS['meta']['nospam_pop_forum_post'] = round(floatval($GLOBALS['meta']['nospam_pop_forum_post']) + $b, 2); if (isset($infos['liens']) and count($infos['liens'])) { $GLOBALS['meta']['nospam_pop_forum_postwlink'] = round(floatval($GLOBALS['meta']['nospam_pop_forum_postwlink']) + $b, 2); } ecrire_meta("nospam_pop_forum_post", $GLOBALS['meta']['nospam_pop_forum_post']); ecrire_meta("nospam_pop_forum_postwlink", $GLOBALS['meta']['nospam_pop_forum_postwlink']); ecrire_meta("nospam_pop_date", $GLOBALS['meta']['nospam_pop_date']); spip_log("Pop Incremente : " . $GLOBALS['meta']['nospam_pop_forum_post'] . ", " . $GLOBALS['meta']['nospam_pop_forum_postwlink'], "nospam"); } } return $flux; }