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 ne comportant pas
d'adresse d'expéditeur, ou provenant d'expéditeurs refusés
La liste des adresses interdites est mémorisée dans un fichier
qui peut contenir :
- des adresses complètes
- des adresses de fournisseurs d'accès
- des adresses génériques contenant des parties variables
Un fichier de configuration est utilisé pour se connecter à la
boite aux lettres.
*/
#define appli // pour la déclaration de variables globales à l'application
/* prototypes */
void charge_adr (FILE *fconf);
void testadr (int numes);
int adr_generique (char *adresse);
int adr_interdite (char *adresse);
int adrgene_interdite (char *adresse);
int test_adrgene (char *adresse, char *adrgene);
/* variables globales au source
(pour éviter des tonnes de passages de paramètres) */
char **listadr; // mémorise les adresses interdites
char **listadrgene; // mémorise les adresses génériques interdites
int sz_listadr; // nombre d'adresses mémorisées dans listadr
int sz_listadrgene; // nombre d'adresses mémorisées dans listadrgene
FILE *ftrace; // fichier contenant les expéditeurs des mails refusés
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
// 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[])
{
FILE *fconf; // descripteur du fichier de configuration
int numes, nbmes; // muméro du mail courant et nombre de mails
// récupération du nom de l'exécutable
memcom (*varg);
// se positionner sur le premier argument de filtradr
nbarg --;
varg ++;
// si le programme a été lancé avec l'option -t
if (nbarg == 3 && strcmp (*varg, "-t") == 0)
{
// 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;
}
// sinon, pas d'utilisation d'un fichier trace
else
ftrace = NULL;
// 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))
{
// charger en mémoire les adresses interdites
charge_adr (fconf);
// 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"));
// récupération de la liste des mails
for (numes = 1; numes <= nbmes; numes++)
testadr (numes);
// 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 [-t fichier_trace] fich_configuration"
psyntaxe ("SYNT_FILTRADR");
return (0);
}
/* charge en mémoire le fichier des adresses interdites */
void charge_adr (FILE *fconf)
{
// fichier contenant les adresses refusées
char ficadr_refus [szchemin + 10];
char *car_ficadr_refus; // pointeur sur un caractère de ce fichier
char adresse [120]; // une adresse de ce fichier
char *nouvadr; // adresse retournée allouée dynamiquement
FILE *frefus; // descripteur du fichier des adresses
int szlistes; // taille des listes d'adresses allouées en mémoire
int i, j; // compteurs
// récupérer le nom du répertoire racine de la messagerie
fgets (ficadr_refus, szchemin, fconf);
// fabriquer le chemin d'accès au fichier contenant les adresses interdites
// <racine>/refus_adr
car_ficadr_refus = ficadr_refus + strlen (ficadr_refus);
*(car_ficadr_refus - 1) = '/';
strcpy (car_ficadr_refus, ficdir ("FIC_REFUS_ADR"));
// initialisation : pas encore d'adresse mémorisée
szlistes = 0;
sz_listadr = 0;
sz_listadrgene = 0;
// accès au fichier des adresses refusées
frefus = fopen (ficadr_refus, "r");
// si ce fichier existe
if (frefus)
{
// compter le nombre de lignes d'adresses qu'il contient
while (fgets (adresse, sizeof (adresse), frefus))
szlistes ++;
// allouer les zones mémoire pour mémoriser les listes d'adresses
// on préfère allouer systématiquement 2 fois trop d'espace mémoire
// (4 octets par ligne du fichier de perdus) plutot que de fixer la
// taille des 2 listes à la compilation ou d'analyser 2 fois le contenu
// du fichier pour distinguer le nombre d'adresses classiques et
// d'adresses génériques avant de relire le fichier pour les mémoriser
listadr = malloc (szlistes * sizeof (char *));
listadrgene = malloc (szlistes * sizeof (char *));
if (! listadrgene)
// "Manque de place mémoire, l'application ne peut fonctionner"
errfatale ("MANQUE_MEMOIRE", NULL);
// on revient au début du fichier
rewind (frefus);
// récupérer et mémoriser les différentes adresses du fichier
while (fgets (adresse, sizeof (adresse), frefus))
{
// allouer une variable pour mémoriser l'adresse lue
nouvadr = (char *) malloc (strlen (adresse));
if (! nouvadr)
// "Manque de place mémoire, l'application ne peut fonctionner"
errfatale ("MANQUE_MEMOIRE", NULL);
// recopier l'adresse en la retournant
// et en passant les caractères en minuscules
i = strlen (adresse) - 2;
j = 0;
while (i >= 0)
nouvadr [j++] = tolower (adresse [i--]);
// terminer la chaine
nouvadr [j] = 0;
// mémoriser l'adresse dans la bonne liste ou message d'erreur
switch (adr_generique (nouvadr))
{
// adresse classique
case 0 : listadr [sz_listadr ++] = nouvadr;
break;
// 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);
conserves ++;
return;
}
// lecture entête du message et mémorisation de l'adresse de l'expéditeur
do
{
// si on a trouvé le champ expéditeur
if (start ("From"))
{
// initialisations
i = 5;
j = 0;
// recherche du @ dans l'adresse
while (buf_lect [i] != '@' && buf_lect [i] != '\0')
i++;
// si l'adresse ne contient pas de @
if (buf_lect [i] != '@')
{
// on va tester la ligne suivante
lire_pop ();
// 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');
// si le mail contient une adresse d'expéditeur invalide ou interdite
if (bufadr [0] == 0 || adr_interdite (bufadr) || adrgene_interdite (bufadr))
{
// 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 l'adresse de l'expéditeur de ce mail
fprintf (ftrace, "%s%s\n", datecour, bufFrom);
}
else
conserves ++;
}
/* cherche si l'adresse passée en paramètre est une
adresse classique ou une adresse générique valide */
int adr_generique (char *adresse)
{
int retour = 0;
// on teste tous les caractères de l'adresse
// pour détecter les métas caractères des adresses génériques
while (*adresse)
{
// cas de 0, 1 ou plusieurs occurences d'un type de caractères
if (*adresse == '+' || *adresse == '*')
{
// tester le métacaractère suivant
adresse ++;
if (*adresse == 'a' || *adresse == '9' || *adresse == 'x')
retour = 1; // peut être une adresse générique valide
else
return (-1); // adresse générique invalide
}
// cas d'une suite de caractères variable de longueur fixe
else if (*adresse == ']')
{
retour = 1; // peut être une adresse générique valide
// analyse des méta caractères de l'intervalle
do
adresse++;
while (*adresse == 'a' || *adresse == '9' || *adresse == 'x');
// adresse générique invalide si caractère non autorisé
if (*adresse != '[')
return (-1);
}
// passage au caractère suivant
adresse ++;
}
// analyse de l'adresse terminée
return (retour);
}
/* recherche si l'adresse de l'expéditeur est une adresse interdite */
int adr_interdite (char *adresse)
{
int i, j;
// on compare l'adresse expéditeur avec toutes les adresses à refuser
for (i = 0; i < sz_listadr; i++)
{
j = 0;
// comparaison caractère par caractère
while (adresse [j] == listadr [i][j])
{
if (adresse [j])
j++; // passage au caractère suivant
else
return (1); // trouvé adresse refusée
}
if (listadr [i][j] == 0 && listadr [i][j-1] == '@')
return (1); // on refuse toutes les adresses de cet hébergeur
}
// l'adresse du mail ne fait pas partie des adresses interdites
return (0);
}
/* recherche si l'adresse de l'expéditeur correspond
à une adresses générique interdite */
int adrgene_interdite (char *adresse)
{
int i; // compteur
// on compare l'adresse expéditeur avec toutes les adresses à refuser
for (i = 0; i < sz_listadrgene; i++)
{
if (test_adrgene (adresse, listadrgene [i]))
return (1); // trouvé adresse refusée
}
// l'adresse du mail ne correspond pas à une adresse générique interdite
return (0);
}
/* comparaison entre l'adresse de l'expéditeur et une adresse
générique interdite (ou un morceau de ces 2 adresses) */
int test_adrgene (char *adresse, char *adrgene)
{
// tant que l'adresse générique n'a pas été analysée entièrement
while (*adrgene)
{
// traitement distinct en fonction du
// caractère courant de l'adresse générique
switch (*adrgene)
{
// traitement suite de caractères variables de longueur fixe
case ']' : adrgene++;
// cette suite est délimitée par des [ ]
while (*adrgene != '[')
{
// terminé si fin prématurée de l'adresse à comparer
if (! *adresse)
return 0;
switch (*adrgene)
{
// il faut trouver une lettre dans l'adresse
case 'a' : if (*adresse < 'a' || *adresse > 'z')
return 0;
break;
// il faut trouver un chiffer dans l'adresse
case '9' : if (*adresse < '0' || *adresse > '9')
return 0;
// caractère quelconque accepté dans l'adresse
default : break;
}
// continuer l'analyse avec les caractères suivants
adresse ++;
adrgene ++;
}
// sauter le '[' de l'adresse générique
adrgene ++;
break;
// traitement de 1 ou plusieurs caractères d'un type particulier
case '+' : if (! *adresse)
return 0; // terminé si adresse trop courte
else
{
// test du caractère courant de l'adresse à comparer
switch (adrgene [1])
{
// cas où il faut que ce soit une lettre
case 'a' : if (*adresse < 'a' || *adresse > 'z')
return 0;
break;
// cas où il faut que ce soit un chiffre
case '9' : if (*adresse < '0' || *adresse > '9')
return 0;
// cas général :n'importe quel caractère accepté
default : break;
}
// passer caractère suivant de l'adresse à comparer
adresse ++;
}
// traitement de 0, 1 ou plusieurs caractères d'un type particulier
case '*' : adrgene ++; // récupérer le type du caractère
// on va utiliser un appel récursif pour
// faire une analyse déterministe
switch (*adrgene)
{
// présence de 0, une ou plusieurs lettres avant
// la prochaine partie fixe de l'adresse
case 'a' : while ('a' <= *adresse && *adresse <= 'z')
{
if (test_adrgene (adresse, adrgene+1))
return (1);
adresse ++;
}
break;
// présence de 0, un ou plusieurs chiffres avant
// la prochaine partie fixe de l'adresse
case '9' : while ('0' <= *adresse && *adresse <= '9')
{
if (test_adrgene (adresse, adrgene+1))
return (1);
adresse ++;
}
break;
// caractères quelconques avant la
// prochaine partie fixe de l'adresse
default : while (*adresse)
{
if (test_adrgene (adresse, adrgene+1))
return (1);
adresse ++;
}
}
// dernier essai, celui qui a le
// plus de chances de réussir
return (test_adrgene (adresse, adrgene+1));
break;
// cas général, comparaison de 2 caractères classiques
default : if (*adresse == *adrgene) // si identiques
{
// continuer le test avec caractères suivants
adresse ++;
adrgene ++;
}
else
// sinon échec d'analyse
return (0);
}
}
// succès si l'analyse des 2 adresses se termine simultanément
return (*adresse == 0);
}