/*
Fichier trtsection.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
Bibliothèque de fonctions permettant de parcourir les différentes
sections d'un mail en mode multipart, pour accéder à la zone texte
et récupérer la liste des fichiers joints.
*/
// si un champ Content-Type figure dans l'entête du mail
if (pos_ctype >= 0)
{
// se positionner sur ce champ
fseek (fmail, pos_ctype, SEEK_SET);
lire_fmail ();
// récupérer la valeur du champ
ctypeorig = recup_ctype ();
// si mode multipart
if (ctypeorig & Multipart)
{
// mémoriser la bordure
while (*buf_lect && ! mem_boundary ())
lire_fmail ();
}
// sinon
else
// récupérer le jeu de caractères utilisé
while (*buf_lect && ! lire_charset ())
lire_fmail ();
}
else
// si pas de champ Content-Type, on affichera quand même le mail
ctypeorig = TextPlain;
// pour l'instant, le type principal du mail est le type courant
ctype = ctypeorig;
}
/* avancer jusqu'à la section suivante si
on n'est pas sur un marqueur de section */
void prochaine_section ()
{
// tant que bordure non trouvée et non fin de mail
// remarque : il est important de tester la bordure
// avant de passer à la ligne
while (! surbordure () && lire_fmail ())
; // chercher la bordure sur la ligne suivante
// si bordure trouvée, lire la ligne suivante
if (buf_lect [0] == '-')
lire_fmail ();
}
/* mémorise le type, le jeu de caractères et le mode d'encodage de la section */
void recup_infos_section ()
{
// initialisation : type de section non trouvé
ctype = 0;
// tant qu'on est dans l'entête de la section, on va chercher
// des informations dans toutes les lignes sachant qu'elles
// peuvent apparaitre dans un ordre quelconque
while (buf_lect [0])
{
// type de la section
if (start ("Content-Type"))
ctype = recup_ctype ();
// mode d'encodage des caractères
else if (start ("Content-Transfer-Encoding"))
mem_encodage ();
// si section multipart
if (ctype & Multipart)
// mémoriser la bordure quand on la trouve
mem_boundary ();
// sinon
else
// récupérer le jeu de caractères utilisé quand on le trouve
lire_charset ();
// passer à la ligne suivante
lire_fmail ();
}
}
/* se positionner sur la section texte du mail (si l'on n'y est pas) */
/* se positionner (si l'on n'y est pas) sur la section text/plain
ou text/html du mail, en fonction du paramètre typetexte */
void posit_section (int typetexte)
{
// tant qu'on n'a pas trouvé la section contenant
// le texte du mail et non fin de mail
while (ctype != typetexte && lire_fmail ())
{
// si une bordure a été mémorisée
if (nbordures)
// se positionner sur la section suivante
prochaine_section ();
// récupérer les informations sur la section
recup_infos_section ();
}
// message d'erreur si on est arrivé en fin de mail
if (! buf_lect [0])
{
// Problème de structure d'un mail multi section : fin de mail atteinte
sprintf (buf_lect, " %s\n", message ("PB_STRUCT_MAIL"));
}
}
/* lister les pièces jointes */
void liste_pj ()
{
int posjoint; // position du nom du fichier joint
char nomjoint [120]; // nom du fichier joint
int nbext; // nombre d'extentions du fichier
int derctype; // pour mémoriser champ content-type de la section
int i; // compteur
// on ne conserve que la bordure de premier niveau
// (permet de sauter le texte HTML en mode multipart/alternative)
nbordures = 1;
// répéter
do
{
// se positionner sur la prochaine section si on n'y est pas déjà
prochaine_section ();
// réinitialisation type de section
derctype = 0;
// chercher et mémoriser le nom du fichier joint s'il y en a un
do
{
// mémoriser les sections message/rfc822 et text/html
if (start ("Content-Type"))
derctype = recup_ctype ();
// chercher si la ligne contient un nom de fichier joint
posjoint = posnomfic ();
// si trouvé hors d'une section text/html
if (posjoint && derctype != TextHtml)
{
// récupérer son nom
// "-> Fichier joint : "
strcpy (nomjoint, message ("FICJOINT"));
i = strlen (nomjoint);
nbext = 0;
// convertir les données encodées comme dans une entête
majlignentete ();
// recopie du nom de fichier sans déborder du tableau
while (buf_lect [posjoint] != '"' && buf_lect [posjoint])
{
// sans les (horribles) blancs qu'il pourrait contenir !!!
// et sans déborder du tableau
if (buf_lect [posjoint] != ' ' && i < sizeof (nomjoint))
nomjoint [i++] = buf_lect [posjoint];
// passer au caractère suivant
posjoint++;
// on compte les . (nombre d'extentions) du fichier
// à partir du 2ème caractère du nom
if (buf_lect [posjoint] == '.')
nbext ++;
}
// terminer la chaine générée
if (i + 1 >= sizeof (nomjoint))
i = sizeof(nomjoint) - 2;
// si fichier joint trouvé hors d'une section text/html
if (posjoint && derctype != TextHtml)
{
// actuellement tous les fichiers joints avec extention peuvent
// contenir des virus, on accepte quand même les .exe
if (nbext > 1 || (nbext == 1 && strcmp (nomjoint + i - 4, ".exe\n")
!= 0 && strcmp (nomjoint + i - 4, ".EXE\n") != 0))
{
// se positionner sur la première ligne du contenu du fichier
while (buf_lect [0] != '\0')
lire_fmail ();
lire_fmail ();
// si le fichier commence par les caractères MZ
// (on teste l'encodage base64 correspondant)
if (buf_lect [0] == 'T' && buf_lect [1] == 'V'
&& buf_lect [2] >= 'o' && buf_lect [2] <= 'r')
// il peut s'agir d'un virus MS-DOS / Windows
// " *** VIRUS ? ***\n"
strcpy (nomjoint + i, message ("VIRUS_POSSIBLE"));
}
// mémoriser le fichier joint trouvé
genligne (nomjoint);
}
// sinon, si section message/rfc822 trouvée
else if (derctype == Mesrfc822)
// la récupérer et la traiter
recup_rfc822 ();
}
// jusqu'en fin de mail ou sortie de la section de premier niveau
while (nbordures && lire_fmail ());
}
/* récupère et traite le contenu d'une section rfc822 */
void recup_rfc822 ()
{
char fichtmp [20]; // fichier pour mémoriser le contenu de la section
char commande [54]; // commande à exécuter pour afficher cette section
char fichier2 [20]; // fichier généré par cette commande
FILE *ftmp; // descripteur associé à un fichier
// fabriquer un nom de fichier de travail
sprintf (fichtmp, "/tmp/mail-1-%d", getpid ());
// l'ouvrir en écriture
ftmp = fopen (fichtmp, "w");
// terminé si problème d'accès au fichier
if (! ftmp)
{
// "Impossible de récupérer un mail en pièce jointe"
genligne (message ("PB_RECUP_MAILJOINT"));
return;
}
// afficher une ligne de séparation
genligne ("\n");
// lecture de la première ligne non vide de la section
lire_fmail ();
// tant que non fin de section
while (! surbordure ())
{
// mémoriser la ligne
fputs (buf_lect, ftmp);
fputc ('\n', ftmp);
// et lire la suivante
lire_fmail ();
}
// la section a été entièrement récupérée
fclose (ftmp);
// fabriquer un nom de fichier de travail pour le mail après traitement
sprintf (fichier2, "/tmp/mail-2-%d", getpid ());
// générer et lancer la commande de récupération du contenu de la section
sprintf (commande, "voirfmail %s > %s", fichtmp, fichier2);
system (commande);
// on peut détruire le premier fichier de travail
unlink (fichtmp);
// ouvrir le fichier obtenu en lecture
ftmp = fopen (fichier2, "r");
// terminé si problème d'accès au fichier
if (! ftmp)
{
// "Problème de droits d'accès, mail joint irrécupérable\n"
genligne (message ("ACCES_MAILJOINT"));
return;
}
// afficher les lignes précédentes du mail
fflush (stdout);
// lire et traiter le fichier obtenu ligne par ligne
while (fgets (buf_lect, sz_buflect, ftmp))
genligne (buf_lect);
// la section a été entièrement traitée
fclose (ftmp);
// on peut détruire le 2ème fichier de travail
unlink (fichier2);
}