/*
Fichier filtresujet.c
Auteur Bernard Chardonneau
Logiciel libre, droits d'utilisation précisés en français
dans le fichier : licence-fr.txt
Traductions des droits d'utilisation dans les fichiers :
licence-de.txt , licence-en.txt , licence-es.txt ,
licence-it.txt , licence-nl.txt , licence-pt.txt ,
licence-eo.txt , licence-eo-utf.txt
Droits d'utilisation également sur la page web :
http://libremail.tuxfamily.org/voir.php?page=droits
Ce programme détruit les mails du serveur comportant une chaine de
caractères particulière dans le sujet.
La liste des chaines de caractères interdites est mémorisée dans
un fichier
Un fichier de configuration est utilisé pour se connecter à la
boite aux lettres.
*/
#define appli // pour la déclaration de variables globales à l'application
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "messages.h"
#include "buflect.h"
#include "ficonf.h"
#include "pop.h"
#include "testchamp.h"
#include "trtentete.h"
#include "datecour.h"
#include "szchemin.h"
/* prototypes */
int testsujet (int numes);
/* variables globales au source
(pour éviter des tonnes de passages de paramètres) */
char **listesujet; // mémorise les sujets interdits
int sz_listesujet; // nombre de sujets mémorisés dans listesujet
char bufSubject [120]; // buffer contenant le sujet du mail
int opto, optO; // options de traitement
// chaine de caractère mémorisée pour éviter appels répétitifs à message ()
char mess_analys [50]; // message signalant l'analyse d'un mail
/* programme principal */
int main (int nbarg, char *varg[])
{
// fichier contenant la liste des chaines à tester
char fichliste [szchemin + 12];
char *car_fichliste; // pointeur sur un caractère de ce fichier
FILE *fconf; // descripteur du fichier de configuration
FILE *ftrace; // fichier contenant les sujets des mail refusés
int numes, nbmes; // muméro du mail courant et nombre de mails
char bufw [120]; // buffer d'envoi d'une requête de destruction de mail
char datecour [10]; // date courante (pour le fichier des mails refusés)
int conserves = 0; // nombre de mails conservés
int supprimes = 0; // nombre de mails supprimés
// récupération du nom de l'exécutable
memcom (*varg);
// se positionner sur le premier argument de filtresujet
nbarg --;
varg ++;
// initialisations valeur des options
ftrace = NULL;
opto = 0;
optO = 0;
// si le programme a été lancé avec des options
while (nbarg >= 2 && **varg == '-')
{
// traitement des options
switch (varg [0][1])
{
// option trace des mails supprimés
case 't' : // ouvrir le fichier trace en écriture fin de fichier
ftrace = fopen (varg [1], "a");
// si nom de fichier correct
if (ftrace)
// initialiser la date courante
initdatecour (datecour);
else
// sinon, avertir l'utilisateur
// "Impossible d'écrire dans le fichier %s"
aff_err_arg ("IMPOS_ECR_FICH", varg [1]);
// sauter les arguments traités
nbarg -= 2;
varg += 2;
break;
// option test de la ligne d'entête d'origine (avant conversion)
case 'o' : if (! optO)
opto = 1;
else
// "L'option -O est prioritaire sur l'option -o"
affiche_err ("PRIO_OPT_O");
// sauter l'argument traité
nbarg --;
varg ++;
break;
// option test de la ligne d'entête d'origine (avant conversion)
case 'O' : optO = 1;
if (opto)
// "L'option -O est prioritaire sur l'option -o"
affiche_err ("PRIO_OPT_O");
// sauter l'argument traité
nbarg --;
varg ++;
break;
// aucune autre option n'est reconnue
// "Option %s incorrecte"
default : aff_err_arg ("ERR_OPTION", *varg);
nbarg = 0; // pour rappeller la syntaxe
}
}
// controle du nombre d'arguments restants
if (nbarg == 1)
{
// ouvrir le fichier de configuration
fconf = ouvre_ficonf (*varg);
if (fconf)
{
// connexion sur le compte mail du serveur pop
if (connect_pop (fconf))
{
// récupérer le nom du répertoire racine de la messagerie
fgets (fichliste, szchemin, fconf);
// fabriquer le chemin d'accès au fichier contenant les
// sujets interdits : <racine>/refus_sujet
car_fichliste = fichliste + strlen (fichliste);
*(car_fichliste - 1) = '/';
strcpy (car_fichliste, ficdir ("FIC_REFUS_SUJET"));
// charger en mémoire les sujets interdits
listesujet = charge_valchamp (fichliste, &sz_listesujet);
// si la liste n'est pas vide
if (sz_listesujet)
{
// récupération du nombre de mails
nbmes = nbmails ();
// Initialisation du message à afficher
// à chaque analyse de mail
// "\rAnalyse du mail n° %d"
strcpy (mess_analys, message ("ANALYSE_MAIL"));
// vérification des différents mails
for (numes = 1; numes <= nbmes; numes++)
{
// si le sujet du mail contient une chaine interdite
if (testsujet (numes))
{
// demande de destruction du mail
sprintf (bufw, "DELE %d", numes);
env_pop (bufw);
lire_pop ();
supprimes ++;
// si utilisation d'un fichier trace
if (ftrace)
// mémoriser le sujet de ce mail
fprintf (ftrace, "%s%s\n", datecour, bufSubject);
}
else
conserves ++;
}
// édition d'un récapitulatif
// "\n%d messages conservés, %d supprimés\n"
printf (message ("BILAN_FILTRAGE"), conserves, supprimes);
}
// se déconnecter proprement du serveur pop
deconnect_pop ();
// si des mails ont été supprimés
if (supprimes)
// attendre pour enregistrement correct des suppressions
// (évite problème si autre filtre appelé juste après)
sleep (2);
}
// on n'a plus besoin du fichier de configuration
fclose (fconf);
}
}
else
// "Syntaxe : %s [-(o|O)] [-t fichier_trace] fich_configuration"
psyntaxe ("SYNT_FILT-DEST/SUJ");
return (0);
}
/* lit l'entête d'un mail et vérifie si son sujet est autorisé */
int testsujet (int numes)
{
char bufw [120]; // buffer d'envoi d'une requête
char sujetbrut [120]; // buffer contenant le sujet du mail avant décodage
int debsujet; // position du premier caractère significatif du sujet
// "\rAnalyse du mail n° %d"
printf (mess_analys, numes);
fflush (stdout);
// initialisations
bufSubject [0] = '\0';
sujetbrut [0] = '\0';
// demande de lecture de l'entête du message
sprintf (bufw, "TOP %d 1", numes);
env_pop (bufw);
// lire la première ligne de l'entête du message
lire_pop ();
// terminé pour ce mail si erreur d'envoi coté serveur
if (memcmp (buf_lect, "-ERR ", 5) == 0)
{
// Erreur serveur pour l'accès au mail
aff_err_argnum ("ERREUR_SERVEUR", numes);
return 0;
}
// lecture entête du message et mémorisation de le sujet du mail
do
{
// si on a trouvé le champ sujet
if (start ("Subject"))
{
// recherche du premier caractère significatif du sujet
debsujet = 8;
while (buf_lect [debsujet] == ' ')
debsujet++;
// si option -o ou -O
if (opto || optO)
{
// mémoriser le sujet du mail avant conversion en le tronquant
// si nécessaire pour éviter un débordement de tableau
if (strlen (buf_lect + debsujet) >= sizeof (sujetbrut))
{
memcpy (sujetbrut, buf_lect + debsujet, sizeof (sujetbrut));
sujetbrut [sizeof (sujetbrut) - 1] = '\0';
}
else
strcpy (sujetbrut, buf_lect + debsujet);
}
// si on n'utilise pas l'option -O
if (! optO)
{
// convertir les caractères spéciaux de la ligne
majlignentete ();
// tronquer si nécessaire le sujet
if (strlen (buf_lect + debsujet) >= sizeof (bufSubject))
buf_lect [debsujet + sizeof (bufSubject) - 1] = '\0';
// mémorisation du sujet converti
strcpy (bufSubject, buf_lect + debsujet);
}
}
// lire la ligne suivante de l'entête du message
lire_pop ();
}
// lecture terminée si ligne limitée à un .
while (buf_lect [0] != '.' || buf_lect [1] != '\0');
// vérifier si le mail contient un des sujets de la liste interdite
if (optO)
// option -O : test sur le sujet brut seulement
return trouve_valchamp (sujetbrut, listesujet, sz_listesujet);
else if (opto)
{
// option -o (seule) : test sur le sujet brut et le sujet converti
return (trouve_valchamp (sujetbrut, listesujet, sz_listesujet)
|| trouve_valchamp (bufSubject, listesujet, sz_listesujet));
}
else
// aucune option : test sur le sujet converti seulement
return trouve_valchamp (bufSubject, listesujet, sz_listesujet);
}