Table des matières

Création de filtres antispam

Généralités

La création de filtres supplémentaires pour le plugin antispam n'est pas compliquée, elle consiste à faire un plugin tout simple contenant une classe de filtrage. Cette classe va prendre en charge la reconnaissance du message comme un spam, l'entraînement éventuel du filtre, l'affichage d'une possible interface de configuration et l'affichage de messages d'information concernant le spam.

Nous allons ici voir comment réaliser un filtre tout simple.

Définition du plugin

Comme d'habitude, tout commence par un répertoire dans vos plugins, contenant un fichier _define.php :

<?php
if (!defined('DC_RC_PATH')) { return; }
 
$this->registerModule(
	/* Name */			"FooFilter",
	/* Description*/		"Foo Spam Filter",
	/* Author */			"Peter McAlloway",
	/* Version */			'1.0',
	/* Permissions */		'usage,contentadmin',
	/* Priority */			200
);
?>

Note :

Spécifiez toujours une priorité supérieure à 10 sinon votre filtre ne va pas fonctionner.

Maintenant, nous devons déclarer notre nouveau filtre à $core. Nous allons faire ceci dans un fichier _prepend.php :

<?php
if (!defined('DC_RC_PATH')) { return; }
 
global $__autoload, $core;
$__autoload['dcFilterFoo'] = dirname(__FILE__).'/class.dc.filter.foo.php';
$core->spamfilters[] = 'dcFilterFoo';
?>

Ce fichier indique au système de chargement automatique de classes où trouver la classe de filtrage puis ajoute le filtre (le nom de la classe) aux autres filtres dans $core→spamfilters.

Création du filtre

Nous avons déclaré une classe de filtrage mais celle-ci n'existe pas, c'est un peu dommage. Nous allons donc de ce pas créer un fichier class.dc.filter.foo.php dans notre plugin :

La classe de filtrage

<?php
class dcFilterFoo extends dcSpamFilter
{
	public $name = 'Foo Filter';
	public $has_gui = false;
	public $active = false;
 
	protected function setInfo()
	{
		$this->description = __('My new foo spam filter');
	}
}
?>

Important :

Votre classe de filtre doit impérativement être enfant de dcSpamFilter sinon elle ne sera même pas chargée.

Nous venons de réaliser un filtre dont le nom est "Foo Filter", avec une description qui sera affichée dans la liste des filtres. Le paramètre $has_gui = false indique que notre filtre n'a pas d'écran de configuration. Le paramètre $active = false indique que le filtre est inactif par defaut.

Astuce :

La classe ainsi créée dispose d'une propriété $this→core permettant d'accéder à tous les objets utiles de Dotclear (base de données, blog en cours, permissions…).

La méthode isSpam

Notre filtre est pour le moment parfaitement inutile puisqu'il ne contient pas de méthode pour reconnaître un spam. Cette méthode s'appelle isSpam, nous allons l'ajouter (dans le corps de la classe donc) :

<?php
...
public function isSpam($type,$author,$email,$site,$ip,
$content,$post_id,&$status)
{
	$status = 'Filtered';
	return true;
}
...

Ici, notre méthode va déclarer que tous les commentaires sont du spam et assigner le status "Filtered" à celui-ci.

Cette méthode prend les paramètres suivants :

La dernière variable $status doit bien être déclarée en référence (&$status) puisqu'elle permet de transmettre le statut du commentaire si celui-ci est marqué comme spam.

Cette méthode doit renvoyer true si le message est un spam et null si on ne sait pas.

Attention :

Si la méthode renvoie false le message sera immédiatement reconnu comme non spam quel que soit les résultats des autres filtres. Ça peut-être utile dans certains cas mais faites attention à ne pas vous tromper.

La méthode getStatusMessage

Cette méthode doit renvoyer une chaîne contenant une information sur le pourquoi du filtrage. Elle sera affichée après chaque commentaire dans les listes ou dans la page d'édition de ceux-ci.

Pour notre filtre, voici ce que nous pouvons indiquer (toujours en ajoutant cette méthode dans le corps de la classe) :

<?php
...
public function getStatusMessage($status,$comment_id)
{
	return sprintf(__('Filtered by %s.'),$this->guiLink());
}
...
?>

Chaque commentaire filtré par votre plugin indiquera "Filtré par Foo Filter". Vous n'êtes pas obligé de créer cette méthode. Dans ce cas, vous aurez une indication par défaut : "Filtré par Foo Filter (raison)".

La méthode trainFilter

Si votre filtre nécessite qu'on lui apprenne à reconnaître un spam ou un non-spam, cette méthode peut être nécessaire. Elle sera appelée dans les cas suivants :

Dans ces deux cas, les méthodes trainFilter de chaque filtre seront appelées.

La méthode prend les paramètres suivants :

Votre méthode se déclare donc comme ceci :

<?php
...
public function trainFilter($status,$filter,$type,$author,
$email,$site,$ip,$content,$rs)
{
	// Choses à faire pour entraîner le filtre
}
...
?>

La méthode gui

La methode gui($url) permet de créer l'interface de configuration de votre filtre. Pour que celle-ci soit active, vous devez spécifier public $has_gui = true; au début de votre classe.

Cette méthode prend un seul paramètre : l'URL de configuration du filtre.

Par exemple, une interface toute simple de votre filtre :

<?php
...
public function gui($url)
{
	return '<p>My filter GUI</p>';
}
...
?>

Note :

Le paramètre $url contient des caractères spéciaux, pensez à l'afficher dans la page avec html::escapeHTML($url). Vous n'avez par contre pas besoin de faire ça, si vous faites une redirection vers $url.

Conclusion

Vous avez pu voir que faire un filtre antispam n'est pas bien compliqué. Afin d'approfondir ce court tutoriel, vous êtes encouragés à lire le code des filtres intégrés dans le plugin antispam (dans le répertoire "filters" de celui-ci).

Modèle de code pour une classe de filtrage

Voici un modèle de classe pour réaliser un filtre. Pensez à changer le nom de la classe.

<?php
class dcFilterFirst extends dcSpamFilter
{
	public $name = 'Filter Name'; // The name of your filter
	public $has_gui = true;       // Has your filter a GUI?
 
	// Set here the localized description of your filter
	protected function setInfo()
	{
		$this->description = __('My first spam filter');
	}
 
	/*
	You may need this method or let parent method do its job.
	public function getStatusMessage($status,$comment_id)
	{
		return sprintf(__('Filtered by %s.'),$this->guiLink());
	}
	*/
 
	public function isSpam($type,$author,$email,
		$site,$ip,$content,$post_id,&$status)
	{
		/*
		return true and set $status if message is a spam
		return null if you don't know (not false)
		*/
	}
 
	/*
	Only if you need to train your filter
	public function trainFilter($status,$filter,$type,
		$author,$email,$site,$ip,$content,$rs)
	{
	}
	*/
 
	// A totaly useless GUI
	public function gui($url)
	{
		return '<p>'.__('My filter GUI').'</p>';
	}
}
?>