/* constantes pour indiquer si l'on efface le(s) mail(s) téléchargé(s) */
#define OPTDEFAUT 0
#define EFFACE 1
#define CONSERVE 2
/* prototypes */
int testchamp (int numes, char *nomchamp);
void chargemail (int numes, long numail, int effacement);
/* variable globale au source
(pour éviter des tonnes de passages de paramètres) */
char **listechamp; // mémorise les champs interdits
int sz_listechamp; // nombre de champs mémorisés dans listechamp
char bufChamp [120]; // buffer contenant le champ du mail à tester
char dirmails [szchemin]; // répertoire de destination des messages
// chaines de caractères mémorisées pour éviter appels répétitifs à message ()
char mess_analys [50]; // message signalant l'analyse d'un mail
char mess_telech [50]; // message signalant le téléchargement d'un mail
/* programme principal */
int main (int nbarg, char *varg[])
{
FILE *fconf; // descripteur du fichier de configuration
char fichliste [szchemin]; // fichier contenant liste des chaines à tester
char *nomchamp; // nom du champ à tester
char *nomfliste; // nom du fichier contenant les chaines à tester
int numes, nbmes; // numéro du mail courant et nombre de mails
int nbrecup = 0; // nombre de mails téléchargés
long numail; // numéro du mail dans le fichier téléchargé
int option; // détermine si on conserve sur le serveur les mails récupérés
int i, j; // compteurs
// récupération du nom de l'exécutable
memcom (*varg);
// se positionner sur le premier argument de chargechampoc
nbarg --;
varg ++;
// récupération du nom du champ à tester
if (nbarg > 1)
{
nomchamp = varg [0];
nbarg --;
varg ++;
}
// si le programme a été lancé avec des options
while (nbarg >= 2 && **varg == '-')
{
switch (varg [0][1])
{
// option effacement du serveur des mails récupérés
case 'd': if (option == CONSERVE)
{
// "Options -d et -k incompatibles"
affiche_err ("COMPAT_OPT_DK");
return (-1);
}
else
option = EFFACE;
break;
// option conservation sur le serveur des mails récupérés
case 'k': if (option == EFFACE)
{
// "Options -d et -k incompatibles"
affiche_err ("COMPAT_OPT_DK");
return (-1);
}
else
option = CONSERVE;
break;
// option nom du fichier contenant la liste des chaines autorisées
case 'f' : nomfliste = varg [1];
// controle du nombre d'arguments
if (nbarg == 1)
{
// ouvrir le fichier de configuration
fconf = ouvre_ficonf (varg [0]);
if (fconf)
{
// connexion sur le compte mail du serveur pop
if (connect_pop (fconf))
{
// récupérer le répertoire racine de la messagerie
fgets (dirmails, sizeof (dirmails) - 7, fconf);
dirmails [strlen (dirmails) - 1] = '\0';
// si ce répertoire existe
if (access (dirmails, 0) == 0)
{
// détermination du nom du fichier
// contenant les chaines interdites
// cas particulier : chemin d'accès absolu à ce fichier
if (nomfliste && *nomfliste == '/')
strcpy (fichliste, nomfliste);
else
{
// cas général : pas de chemin d'accès absolu au fichier
// on complète ce nom d'un /
strcpy (fichliste, dirmails);
strcat (fichliste, "/");
// si le nom de ce fichier a été passé en paramètre
if (nomfliste)
// le rajouter au nom du répertoire
strcat (fichliste, nomfliste);
else
{
// sinon, on va générer un nom à
// partir du nom du champ
strcat (fichliste, ficdir ("FIC_ACCEPT_"));
i = strlen (fichliste);
j = 0;
do
// le nom du champ est recopié en minuscules
fichliste [i++] = tolower (nomchamp [j]);
while (nomchamp [j++]);
}
}
// charger en mémoire les champs interdits
listechamp = charge_valchamp (fichliste, &sz_listechamp);
// si la liste n'est pas vide
if (sz_listechamp)
{
// créer si nécessaire le sous repertoire d'entrée
strcat (dirmails, "/");
strcat (dirmails, ficdir ("DIR_ENTREE"));
mkdir (dirmails, 0755);
// récupération du nombre de mails
nbmes = nbmails ();
// si des mails peuvent être récupérés
if (nbmes)
{
// récupération du numéro du dernier fichier mail
numail = num_dermail (dirmails);
// Initialisation des messages à afficher à chaque
// analyse ou téléchargement de mail
// "\rAnalyse du mail n° %d "
strcpy (mess_analys, message ("ANALYSE_MAIL_BL"));
// "\rTéléchargement du mail n° %d"
strcpy (mess_telech, message ("TELECH_MAIL"));
// pour chaque fichier mail du serveur
for (numes = 1; numes <= nbmes; numes++)
{
// si l'expéditeur du mail est autorisé
if (testchamp (numes, nomchamp))
{
// télécharger le mail correspondant
chargemail (numes, ++numail, option);
// on compte les mails téléchargés
nbrecup ++;
}
}
// édition d'un récapitulatif
// "\n%d mails téléchargés sur %d\n"
printf (message ("TOTAL_TELECH"), nbrecup, nbmes);
// sauvegarde du numéro du dernier fichier mail
sauv_num_dermail (dirmails, numail);
}
}
}
else
// "répertoire de messagerie %s inexistant"
aff_err_arg ("REP_RACINE_ABSENT", dirmails);
// se déconnecter proprement du serveur pop
deconnect_pop ();
}
// on n'a plus besoin du fichier de configuration
fclose (fconf);
}
}
else
// "Syntaxe : %s nom_champ [-f fich_liste] [-(k|d)] fich_configuration"
psyntaxe ("SYNT_CHARGECHAMPOK");
// pour faire plaisir à gcc qui veut une fonction main de type int
return (0);
}
/* lit l'entête d'un mail et vérifie si son champ est autorisé */
int testchamp (int numes, char *nomchamp)
{
char bufw [120]; // buffer d'envoi d'une requête
int i; // simple compteur
// "\rAnalyse du mail n° %d "
printf (mess_analys, numes);
fflush (stdout);
// initialisation
bufChamp [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 champ du mail
do
{
if (start (nomchamp))
{
// convertir les caractères spéciaux de la ligne
majlignentete ();
// initialisation
i = strlen (nomchamp) + 1;
// recherche du début du champ
while (buf_lect [i] == ' ')
i++;
// tronquer si nécessaire le champ (pour éviter un plantage)
if (strlen (buf_lect + i) > sizeof (bufChamp))
buf_lect [i + sizeof (bufChamp) - 1] = '\0';
// mémorisation du champ
strcpy (bufChamp, buf_lect + i);
}
// 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 champ de la liste interdite
return trouve_valchamp (bufChamp, listechamp, sz_listechamp);
}
/* télécharge le mail choisi et l'enlève du serveur si c'est demandé */
void chargemail (int numes, long numail, int effacement)
{
char bufw [120]; // buffer d'envoi d'une requête
char ficmail [sizeof (dirmails) + 9];
FILE *fmail;
// création du fichier mail
sprintf (ficmail, "%s/r%07ld.n", dirmails, numail);
fmail = fopen (ficmail, "w");
if (fmail)
{
// message de suivi du déroulement
// "\rTéléchargement du mail n° %d"
printf (mess_telech, numes);
fflush (stdout);
// demande de lecture du message et réception de l'acquittement
sprintf (bufw, "RETR %d", numes);
env_pop (bufw);
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);
fclose (fmail);
unlink (ficmail);
return;
}
// lire la première ligne de l'entête du mail
lire_pop ();
// lecture et copie du message jusqu'à une ligne limitée a un .
while (buf_lect [0] != '.' || buf_lect [1] != '\0')
{
// copie de la ligne lue dans le fichier mail
fputs (buf_lect, fmail);
fputc ('\n', fmail); // nécessaire car supprimé de buf_lect
// et lecture de la suivante
lire_pop ();
}
// fermer le fichier contenant le mail
fclose (fmail);
// et supprimer si nécessaire le mail du serveur
if (effacement != CONSERVE)
{
sprintf (bufw, "DELE %d", numes);
env_pop (bufw);
lire_pop ();
}
}
else
// "Impossible d'écrire dans le fichier %s"
aff_err_arg ("IMPOS_ECR_FICH", ficmail);
}