/**
 * 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;
}