Wikini

DiscussionsActionDAdministrationEraseSpam

PagePrincipale :: DerniersChangements :: DerniersCommentaires :: ParametresUtilisateur :: Vous êtes ec2-34-230-66-177.compute-1.amazonaws.com
(Bon, on est pas encore tout à fait d'accord sur les droits d'accès aux actions... alors comme LordFarquaad est parti une semaine en vacance et que les autres ne se manifestent pas beaucoup, je vais débuter cette action permettant de supprimer simplement le SPAM. -- CharlesNepote)

Le process


[à suivre]


Solution 1

...
(2005-01-21 : BasHaq)
On pourrait pour la premiere partie faire ActionUserChanges? et ActionUserPages? à l'image de ActionMyChanges et ActionMyPages
"{{userchanges/IP=XXX}}" donnerait la liste des pages modifiés par l'IP XXX
"{{userchanges}}" prendrais pas défaut l'IP actuelle de l'utilisateur (qu'il soit identifié ou non).

Solution 2

Une seule action se décomposant en trois écrans qui parlent d'eux-mêmes.

Premier formulaire
Sélection des pages

Nom de l'utilisateur :

ou

Toutes les modifications depuis



Second formulaire :

Nettoyage des pages vandalisées depuis 1 heure(s)

TestAbcd1 (2005-02-20 22:57:46) (historique) [Suppr.!] Restaurer depuis la version du 2005-02-20 22:57:42 par PC0846
TestAbcd2 (2005-02-20 22:57:29) (historique) [Suppr.!]
TestA (2005-02-20 22:57:01) (historique) [Suppr.!] Restaurer depuis la version du 2005-02-20 22:30:00 par PC0846
Restaurer depuis la version du 2005-02-20 22:26:46 par PC0846
Restaurer depuis la version du 2005-02-20 22:26:00 par PC0846
Restaurer depuis la version du 2005-02-20 22:24:51 par PC0846
Restaurer depuis la version du 2005-02-20 22:11:05 par PC0846
Restaurer depuis la version du 2005-02-20 22:09:17 par PC0846
Restaurer depuis la version du 2005-02-20 22:08:20 par PC0846
Restaurer depuis la version du 2005-02-16 00:45:45 par PC0846

Commentaire :



Ecran de confirmation :

Résultats :

Retour au formulaire de départ >>

Consultation du journal des nettoyages >>



Les nettoyages opérés sont logués automatiquement sur une autre page, à la fin de l'action :
La page de log est déterminée de la façon suivante :
Le log se présente sous la forme suivante :

C'est encore un peu léger mais ça tourne. Le code ci-dessous est fonctionnel, mais encore en beta :
<?php


// Charles Népote 2005
// License GPL.
// Version 0.6.1 du 08/02/2005 à 22:10.

// TODO
// -- cas où un spammeur édite 98 fois une page (solution : par date)
// -- cas où le spammeur change d'IP à chaque passage (solution : par date)
// -- case pour sélectionner tout
// -- attention au cas où la version mais aussi la page est effacée
//   (cf. handler deletepage) (et les commentaires ?)


// Vérification de sécurité
if (!defined('WIKINI_VERSION'))
{
    die (
'acc&egrave;s direct interdit');
}


echo    
"\n<!-- == Action erasespam v 0.6 ============================= -->\n";
// La norme HTML interdit la basile style ailleurs que dans <head></head>
// on l'utilise ici à titre de débogage et pendant la construction de l'action
echo    "<style type=\"text/css\">",
    
"p { margin: 0; }",
    
".action_erasespam { background-color: yellow; }",
    
"</style>\n";


// Contrôle d'accès à cette action
/*
if (!$this->GetUser() == "CharlesNepote")
{
    echo    "<p class =\"action_erasespam\">",
        "Vous n'êtes pas autorisé à utiliser cette action.</p>";
    return;
}
/* */



// -- (1) Formulaire d'accueil de l'action -------------------------------
//
// Le formulaire est affiché si aucun spammer n'a encore été précisé ou
// si le champ a été laissé vide et validé
if(empty($_POST['spammer']))
{
    echo    
"<div class=\"action_erasespam\">\n",
        
"<form method=\"post\" action=\""$this->Href() . "\" name=\"selection\">\n",
        
"<fieldset>\n",
        
"<legend>S&eacute;lection des pages</legend>\n";
    
// Si le formulaire a été validé avec le champ vide, on alerte l'utilisateur
    
if(isset($_POST['spammer']))
        echo    
"<p><em>Attention&nbsp;: ",
            
"veuillez préciser un nom d'utilisateur</em></p>\n";
    echo    
"<p>\n",
        
"Nom de l'utilisateur : <input name=\"spammer\" /> ",
        
"<button value=\"Valider\">Valider</button>\n",
        
"</p>\n";
    echo    
"</fieldset>\n",
        
"</form>\n",
        
"</div>\n";
}


// -- (2) Page de résultats et form. de sélection des pages à effacer ----
//
else if(!isset($_POST['erase']))
{
    
// Sélection de toutes les pages de cet utilisateur
    // TODO : ne sélectionner que les pages des n derniers jours
    // TODO : contrôler préalablement le contenu de $_POST['spammer']
    
$requete =
        
"select *
        from "
.$this->config["table_prefix"]."pages
        where user = '" 
$_POST['spammer'] . "' and latest = 'Y'
        order by `time` desc"
;
    
$pagesFromSpammer $this->LoadAll($requete);
    
    
// Affichage des pages pour validation
    
echo    "<div class=\"action_erasespam\">\n";
    echo    
"<p>Nettoyage des pages vandalisées par " $_POST['spammer'] . "</p>\n";
    echo    
"<form method=\"post\" action=\""$this->Href() . "\">\n";
    foreach (
$pagesFromSpammer as $i => $page)
    {
        echo    
"<p><input name=\"" $page["tag"] . "\" type=\"checkbox\" />",
            
"("$page["time"], ") ",
            
"(",$this->ComposeLinkToPage($page["tag"], "revisions""historique"0),") ",
            
$this->ComposeLinkToPage($page["tag"], """"0),
            
" . . . . ",$this->Format($page["user"]),"</p>\n" ;
    }
    echo    
"<p>Commentaire&nbsp;: <input name=\"comment\" style=\"width: 80%;\" /></p>\n";
    echo    
"<p>\n",
        
"<input type=\"hidden\" name=\"wiki\" value=\"" $this->GetPageTag() . "\" />\n",
        
"<input type=\"hidden\" name=\"spammer\" value=\"" $_POST['spammer'] . "\" />\n",
        
"<input type=\"hidden\" name=\"erase\" value=\"yes\" />\n",
        
"<button value=\"Valider\">Effacer les versions sélectionnées</button>\n",
        
"</p>\n";
    echo    
"</form>\n";
    echo    
"</div>\n";
}


// -- (3) Effacement des pages et page de résultats ----------------------
//
else
{
    
$deletedPages "";
    
    
// Sélection de toutes les pages de cet utilisateur
    
$requete1 =
        
"select *
        from "
.$this->config["table_prefix"]."pages
        where user = '" 
$_POST['spammer'] . "' and latest = 'Y'";
    
$pagesFromSpammer $this->LoadAll($requete1);
    
    
// Pour chaque page sélectionnée
    
foreach ($pagesFromSpammer as $i => $page)
    {
        
// Si la case d'une page a été cochée comme SPAM
        
if (isset($_POST[$page["tag"]]))
        {
            
$requeteVersionBefore =
                
"select * " .
                
"from " $this->config["table_prefix"] . "pages " .
                
"where tag = '" $page["tag"] . "' " .
                
"and time < '" $page["time"] . "' " .
                
"order by `time` desc limit 1";
            
$versionBefore $this->LoadSingle($requeteVersionBefore);
            
// Pour l'instant l'effacement ne peut avoir lieu que s'il
            // existe une version antérieure à la page
            // Ce qui fait qu'une page créée par un spammeur ne sera pas
            // effacée... Il faudrait attendre le nouveau système de
            // purge permettant de toujours conserver une page au delà
            // du délai de purge
            
if (!empty($versionBefore))
            {
                
// Efface
                
$requeteDelete =
                    
"delete from " $this->config["table_prefix"] . "pages " .
                    
"where id = '" $page["id"] . "' " .
                    
"and tag = '" $page["tag"] . "' " .
                    
"limit 1";
                
$this->Query($requeteDelete);
                
//echo "$$$$$$$$$$$$$$";
                
$deletedPages .= $page["tag"] . " ";

                
// Fait de la version précédente la version active
                // if($page['latest'] == 'Y' && !empty($versionBefore))
                
$makeLatest =
                    
"update " $this->config["table_prefix"] . "pages " .
                    
"set latest = 'Y' ".
                    
"where id = '" $versionBefore["id"] . "' " .
                    
"and tag = '" $page["tag"] . "' " .
                    
"limit 1";
                
$this->Query($makeLatest);
            }
        }
    }

    
// Affichage de la page des résultats ; par exemple :
    // Pages effacées : BacASable WikiNi
    
echo    "<div class=\"action_erasespam\">\n";
    echo    
$deletedPages ?
        
"Pages effacées&nbsp;: " $this->Format($deletedPages) . "\n" :
        
"Aucune page effacée\n";
    echo    
"</div>\n\n";
    
    
// S'il y a eu des pages nettoyées,
    // on enregistre dans une page choisie qui a fait quoi
    
if ($deletedPages)
    {
        
// Détermine quelle est la page de log :
        // -- passée en paramètre (que se passe-t'il si elle n'existe pas ?)
        // -- ou la page en cours par défaut
        
$test $this->GetParameter("logpage");
        
$reportingPage $test $test $this->GetPageTag();

        
// Ajout de la ligne de log
        // TODO : remplacer par une méthode AppendContent ?
        /* $requeteBody =
            "select body " .
            "from " . $this->config["table_prefix"] . "pages " .
            "where tag = '" . $reportingPage . "' " .
            "and latest = 'Y' " .
            "limit 1";
        $result = $this->LoadSingle($requeteBody); */
        
$result $this->LoadPage($reportingPage);
        
$body $result['body'];
        
// Ajout de qui à fait quoi au corps de la page
        
$body .= "\n("date("Y-m-d H:i:s") . ") Pages nettoyées par " .
            
$this->GetUserName() .
            
" [" $_POST['comment'] . "]&nbsp;: " $deletedPages "\n";

        
// Sauvegarde de la page
        //   Note : la page est sauvegardée même si l'utilisateur n'a pas accès
        //   à cette page
        
$this->SavePage($reportingPage$body);
        
// now we render it internally so we can write the updated link table.
        
$this->ClearLinkTable();
        
$this->StartLinkTracking();
        
$this->Format($body);
        if(
$user $this->GetUser())
        {
            
$this->TrackLinkTo($user['name']);
        }
        if(
$owner $this->GetPageOwner())
        {
            
$this->TrackLinkTo($owner);
        }
        
$this->StopLinkTracking();
        
$this->WriteLinkTable();
        
$this->ClearLinkTable();
    }
}
?>

Ce code, fonctionnel, pourrait être installé sur wikini.net en codant en dur les droits d'accès à quelques habitués. On pourrait ainsi tester cette action de vivo et observer son efficacité ou ses problèmes sur les quelques spam qui affectent réguilèrement le site. Qu'en pensez-vous ?
-- CharlesNepote
Comme tu me l'as demandé, je fais mon petit commentaire sur ton code ;-) (dans l'ordre de celui-ci)
-- LordFarquaad


En fait il faut peut-être distinguer plusieurs types techniques de spam et donc plusieurs types de corrections : -- CharlesNepote




En fait, ce qui permettrait de résoudre ces trois cas, c'est :
Est-ce clair ?
-- CharlesNepote
D'ailleurs au fait, s'il y a une version antérieure, que fait le choix "supprimer" ? Il supprime complètement la page ? Car sinon il faut bien restaurer une version tout de même :-S A mon sens il faudrait un "supprimer définitivement" (s'il n'y a pas de version antérieure... ou même ultérieure !) et un "supprimer et restaurer la version <selection de la version>" (sil y en a une). NB.: il faudra tout de même vérifier que la version à supprimer est bien la dernière [c'est forcément que les "latest = 'y'" qui sont listées -- CharlesNepote] ! -- LordFarquaad

Nouvelle version 0.7.2 qui à l'air fonctionnelle (à contrôler bien proprement sur une base de test)
<?php


// Charles Népote 2005
// Didier Loiseau 2005
// License GPL.
// Version 0.7.2 du 20/02/2005 à 21:32.

// TODO
// -- case pour sélectionner tout
// -- attention au cas où la version mais aussi la page est effacée
//   (cf. handler deletepage) (et les commentaires ?)
// -- les opérations sur la page contenant cette action + logpage devraient
//    être impossibles ?
// -- ne rien loguer si rien n'a été effacé
// -- idéalement la dernière page affiche les résultats mais ne renettoie
//    pas les pages si elle est rechargée
// -- test pour savoir si quelque chose a bien été effacé


/*$essai = $this->GetLinkTable();
echo "<pre>";
print_r($essai);
echo "</pre>\n";*/

// Vérification de sécurité
if (!defined('WIKINI_VERSION'))
{
    die (
'acc&egrave;s direct interdit');
}


echo    
"\n<!-- == Action erasespam v 0.7.2 ============================= -->\n";
// La norme HTML interdit la balise style ailleurs que dans <head></head>
// on l'utilise ici à titre de débogage et pendant la construction de l'action
echo    "<style type=\"text/css\">",
    
"p { margin: 0; }",
    
".action_erasespam { background-color: yellow; }",
    
".action_erasespam td { text-align: right; vertical-align: top; }",
    
"</style>\n";


// Contrôle d'accès à cette action
/*
if (!$this->GetUser() == "CharlesNepote")
{
    echo    "<p class =\"action_erasespam\">",
        "Vous n'êtes pas autorisé à utiliser cette action.</p>";
    return;
}
/* */



// -- (1) Formulaire d'accueil de l'action -------------------------------
//
// Le formulaire est affiché si aucun spammer n'a encore été précisé ou
// si le champ a été laissé vide et validé
if(empty($_POST['spammer']) && empty($_POST['from']) && !isset($_POST['clean']))
{
    echo    
"<div class=\"action_erasespam\">\n",
        
"<form method=\"post\" action=\""$this->Href() . "\" name=\"selection\">\n",
        
"<fieldset>\n",
        
"<legend>S&eacute;lection des pages</legend>\n";
    
// Si le formulaire a été validé avec le champ vide, on alerte l'utilisateur
    
if(isset($_POST['spammer']))
        echo    
"<p><em>Attention&nbsp;: ",
            
"veuillez préciser un nom d'utilisateur</em></p>\n";
    echo    
"<p>\n",
        
"Nom de l'utilisateur : <input name=\"spammer\" /> ",
        
"<button name=\"1\" value=\"Valider\">Valider</button>\n",
        
"</p>\n";
    echo    
"<p>\n",
        
"ou\n",
        
"</p>\n";
    echo    
"<p>\n",
        
"Toutes les modifications depuis ",
        
"<select name=\"from\">\n",
        
"<option selected=\"selected\" value=\"1\">depuis 1 heure</option>\n",
        
"<option value=\"3\">depuis 3 heures</option>\n",
        
"<option value=\"6\">depuis 6 heures</option>\n",
        
"<option value=\"12\">depuis 12 heures</option>\n",
        
"<option value=\"24\">depuis 24 heures</option>\n",
        
"<option value=\"48\">depuis 48 heures</option>\n",
        
"<option value=\"168\">depuis 1 semaine</option>\n",
        
"<option value=\"336\">depuis 2 semaines</option>\n",
        
"<option value=\"744\">depuis 1 mois</option>\n",
        
"</select>\n",
        
"<button name=\"2\" value=\"Valider\">Valider</button>\n",
        
"</p>\n";
    echo    
"</fieldset>\n",
        
"</form>\n",
        
"</div>\n\n";
}


// -- (2) Page de résultats et form. de sélection des pages à effacer ----
//
else if(!isset($_POST['clean']))
{
    
// Sélection de toutes les pages de cet utilisateur
    // TODO : ne sélectionner que les pages des n derniers jours
    // TODO : contrôler préalablement le contenu de $_POST['spammer']
    
if(isset($_POST['spammer']) && isset($_POST['1']))
    {
        
$requete =
            
"select *
            from "
.$this->config["table_prefix"]."pages
            where
            user = '" 
$_POST['spammer'] . "'
            and latest = 'Y'
            order by `time` desc"
;
        
$title =
            
"<p>Nettoyage des pages vandalisées par " .
            
$_POST['spammer'] . "</p>\n";
    }
    
    if(isset(
$_POST['from']) && isset($_POST['2']))
    {
        
$requete =
            
"select *
            from "
.$this->config["table_prefix"]."pages
            where
            time > date_sub(now(), interval " 
$_POST['from'] . " hour)
            and latest = 'Y'
            order by `time` desc"
;
        
$title =
            
"<p>Nettoyage des pages vandalisées depuis " .
            
$_POST['from'] . " heure(s)</p>\n";
    }

    
//echo $requete;
    
$pagesFromSpammer $this->LoadAll($requete);
    
    
// Affichage des pages pour validation
    
echo    "<div class=\"action_erasespam\">\n";
    echo    
$title;
    echo    
"<form method=\"post\" action=\""$this->Href() . "\">\n";
    echo    
"<table>\n";
    foreach (
$pagesFromSpammer as $i => $page)
    {
        
/*echo    "<p><input name=\"" . $page["tag"] . "\" type=\"checkbox\" />",
            "(", $page["time"], ") ",
            "(",$this->ComposeLinkToPage($page["tag"], "revisions", "historique", 0),") ",
            $this->ComposeLinkToPage($page["tag"], "", "", 0),
            " . . . . ",$this->Format($page["user"]),"</p>\n" ;*/
        
$revisions $this->LoadRevisions($page["tag"]);
        echo    
"<tr>\n",
            
"<td>",
            
$this->ComposeLinkToPage($page["tag"], """"0), " ",
            
"("$page["time"], ") ",
            
"(",$this->ComposeLinkToPage($page["tag"], "revisions""historique"0),") ",
            
"</td>\n";
        echo    
"<td>",
            
"<input name=\"suppr[]\" value=\"" $page["tag"] . "\" type=\"checkbox\" /> [Suppr.!]",
            
"</td>\n";
        echo    
"<td>\n";
        foreach (
$revisions as $revision)
        {
            
// Si c'est la dernière version on saute cette itération
            // ce n'est pas elle qu'on va vouloir restaurer...
            
if(!isset($revision1))
            {
                
$revision1 "";
                continue;
            }
            echo    
"<input name=\"rev[]\" value=\"" $revision["id"] . "\" type=\"checkbox\" /> ";
            echo    
"Restaurer depuis la version du ",
                
"<a href=\"".$this->href("show")."&amp;time=".urlencode($revision["time"])."\">".$revision["time"]."</a>",
                
" par "$this->Format($revision['user']), " ",
                
"<br />\n";
        }
        unset(
$revision1);
        echo    
//" . . . . ",$this->Format($page["user"]),"</p>\n",
            
"</td>\n",
            
"</tr>\n",
            
"";
    }
    echo    
"</table>\n";
    echo    
"<p>Commentaire&nbsp;: <input name=\"comment\" style=\"width: 80%;\" /></p>\n";
    echo    
"<p>\n",
        
"<input type=\"hidden\" name=\"spammer\" value=\"" $_POST['spammer'] . "\" />\n",
        
"<input type=\"hidden\" name=\"clean\" value=\"yes\" />\n",
        
"<button value=\"Valider\">Nettoyer >></button>\n",
        
"</p>\n";
    echo    
"</form>\n";
    echo    
"</div>\n\n";
}


// -- (3) Nettoyage des pages et affichage de la page de résultats -------
//
else if(isset($_POST['clean']))
{
    
//echo "<script type=\"text/javascript\">alert('test');</script>";
    
$deletedPages "";
    
$restoredPages "";
    
$logPage $this->GetParameter("logpage");


    
// -- 3.1 Effacement ---
    // On efface chaque élément du tableau suppr[]
    // Pour chaque page sélectionnée
    
if (!empty($_POST['suppr']))
    {
        foreach (
$_POST['suppr'] as $page)
        {
            
// Effacement de la page en utilisant la méthode adéquate
            // (si DeleteOrphanedPage ne convient pas, soit on créé
            // une autre, soit on la modifie
            
$this->DeleteOrphanedPage($page);
            
$deletedPages .= $page ", ";
        }
        
$deletedPages trim($deletedPages", ");
    }


    
// -- 3.2 Restauration des pages sélectionnées ---
    
if (!empty($_POST['rev']))
    {
        
//print_r($_POST["rev"]);
        
foreach ($_POST["rev"] as $rev_id)
        {
            echo 
$rev_id."<br>";
            
// Sélectionne la révision
            
$revision $this->LoadPageById($rev_id);
    
            
// Fait de la dernière version de cette révision
            // une version archivée
            
$requeteUpdate =
                
"update " $this->config["table_prefix"] . "pages " .
                
"set latest = 'N' ".
                
"where latest = 'Y' " .
                
"and tag = '" $revision["tag"] . "' " .
                
"limit 1";
            
$this->Query($requeteUpdate);
            
$restoredPages .= $revision["tag"] . ", ";
    
            
// Fait de la version sélectionnée la nouvelle version active
            
$this->SavePage($revision["tag"], $revision['body']);
            
// */
        
}
        
$restoredPages trim($restoredPages", ");
    }


    
// -- 3.3 Affichage de la page des résultats ---
    //        par exemple :
    //        Pages effacées : BacASable WikiNi
    
echo    "<div class=\"action_erasespam\">\n";
    echo    
"<p><em>Résultats&nbsp;:</em></p>\n";
    echo    
"<ul>\n";
    echo    !empty(
$deletedPages) ?
        
"<li>Pages définitivement effacées&nbsp;: " .
        
$this->Format($deletedPages) . ".</li>\n" :
        
"<li>Aucune page effacée.</li>\n";
    echo    !empty(
$restoredPages) ?
        
"<li>Pages restaurées&nbsp;: " .
        
$this->Format($restoredPages) . ".</li>\n" :
        
"<li>Aucune page restaurée.</li>\n";
    echo    
"</ul>\n";
    echo    
"<p><a href=\""$this->Href(), "\">Retour au formulaire de départ >></p>\n";
    echo    
"<p><a href=\"" .
        (!empty(
$logPage) ?
        
$this->Href(''$logPage) :
        
$this->Href()) . "\">Consultation du journal des nettoyages >></p>\n";
    echo    
"</div>\n\n";


    
// -- 3.4 Écriture du journal des actions ---
    //        S'il y a eu des pages nettoyées,
    //        on enregistre dans une page choisie qui a fait quoi
    
if ($deletedPages||$restoredPages)
    {
        
// -- Détermine quelle est la page de log :
        //    -- passée en paramètre (que se passe-t'il si elle n'existe pas ?)
        //    -- ou la page en cours par défaut
        
$reportingPage $logPage $logPage $this->GetPageTag();

        
// -- Ajout de la ligne de log
        // TODO : remplacer par une méthode AppendContent ?
        
$result $this->LoadPage($reportingPage);
        
$body $result['body'];
        
// Ajout de qui à fait quoi au corps de la page
        
$deletedPages $deletedPages $deletedPages." (effacée(s))" "";
        
$restoredPages $restoredPages $restoredPages." (restaurée(s))" "";
        if (
$deletedPages&&$restoredPages$liaison " et ";
        else 
$liaison "";
        
$body .= "\n("date("Y-m-d H:i:s") . ") Pages nettoyées par " .
            
$this->GetUserName() .
            
" [" $_POST['comment'] . "]&nbsp;: " $deletedPages .
            
$liaison $restoredPages"\n";

        
// -- Sauvegarde de la page
        //    Note : la page est sauvegardée même si l'utilisateur n'a pas accès
        //    à cette page
        
$this->SavePage($reportingPage$body);
        
// now we render it internally so we can write the updated link table.
        /*$this->ClearLinkTable();
        $this->StartLinkTracking();
        $this->Format($body);
        if($user = $this->GetUser())
        {
            $this->TrackLinkTo($user['name']);
        }
        if($owner = $this->GetPageOwner())
        {
            $this->TrackLinkTo($owner);
        }
        $this->StopLinkTracking();
        $this->WriteLinkTable();
        $this->ClearLinkTable();*/
    
}
    
}
?>



Ailleurs :



Bonjour,
je suis de passage ici (je cherche quel sera le wiki que j'utiliserai si j'en utilise un :) ) et je lis toutes ces discussions à propos du spam. Il me semble capital pour un wiki de se protéger au mieux de ce fléau et je me demande s'il ne serait pas plus pertinent de prendre le problème dans l'autre sens : surveiller la probabilité qu'une édition soit du spam et activer le cas échéant certaines actions pour faciliter le traitement postérieur.
(faire un code de suppression automatique, ça va pas être facile, et le temps de le faire, les spammeurs auront trouvé l'astuce pour pourrir le travail... ; il faudrait essayer de ne pas courir après eux :)
Par exemple, je vois déjà plusieurs éléments de réflexion :
le spammeur professionnel utilise un robot, c'est sa faille ; ce n'est pas lui qui agit, et son robot travaille en masse : donc surveiller si plusieurs pages sont modifiées par la même ip dans un temps très limité ;
piéger le spam en utilisant des vieux trucs : page cachée : s'il y a édition alors il y a problème sur toutes les pages éditées par cette ip ;
le spammeur va poster des adresses : surveiller les éditions comportant + d'un certain nombre d'adresses (densité dans l'édition, pas dans la page entière) ;
filtre bayesien (il y a des codes sur le net, pour le spam par courriel c'est vraiment très efficace) ;

L'idée est que le programme n'enregistre pas les infos màj bêtement mais qu'il les évalue. La question préjudicielle : est-ce une édition a priori acceptable ? Si c'est ok, comme normal ; si ça coince, on passe à l'édition a posteriori. On peut aussi penser à tester l'auteur, pour savoir s'il s'agit d'un humain ; marquer immédiatement la page comme douteuse (indice de qualité) pour la faire valider rapidement. Dans certains cas (qui n'a pas déjà vu une page totalement remplie de liens pouris?), ne pas éditer la page (on peut la conserver pour modération avec appel à un utilisateur inscrit/admin/vérificateur, personne de confiance).
Bien sûr, un des principes du wiki (édition immédiate pour tout le monde) en prend un petit coup, mais le spam - qui a déjà bien flingué le courrier par pop - est susceptible de flinguer les wikis.
Bref, l'idée c'est d'intervenir le maximum AVANT pour ne pas être énormément emmerdé après à perdre du temps à faire un code à faible valeur ajoutée. Principe sentinelle, cerbère, chien de garde, aprioriste.
Sinon, très sympa votre boulot !
gb.
Il n'y a pas de commentaire sur cette page. [Afficher commentaires/formulaire]