/*
Fichier voirfmail.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 affiche le contenu d'un fichier mail passé en paramètre
Le chemin d'accès au fichier peut être absolu ou relatif
*/
#define appli // pour la déclaration de variables globales à l'application
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "messages.h"
#include "buflect.h"
#include "fmail.h"
#include "encodage.h"
#include "trtentete.h"
#include "trtligne.h"
#include "trtbordure.h"
#include "trtsection.h"
/* prototypes */
void aff_entete ();
void affchamp (long pos_deblig, int conversion);
void aff_corpsmail ();
void aff_mail ();
void aff_texte ();
void genligne (char *chaine);
/* variable globale au source
(pour éviter des tonnes de passages de paramètres) */
// options d'affichage
int opthb; // de la section text/html au lieu de text/plain
int optT; // affichage partiel de l'entête pour les traductions
int lig_nonvide; // présence de caractères significatifs dans la ligne
/* programme principal */
int main (int nbarg, char *varg[])
{
// récupération du nom de l'exécutable
memcom (*varg);
// pas encore d'option mémorisée
opthb = 0;
optT = 0;
// traitement des options éventuelles de la commande
while (--nbarg > 1 && varg [1][0] == '-')
{
// si option -h ou -H
if ((varg [1][1] | 0x20) == 'h')
{
// mémoriser cette option
if (varg [1][1] == 'h')
opthb = opthb | 1;
else
opthb = opthb | 3;
}
// sinon si option -b ou -B
else if ((varg [1][1] | 0x20) == 'b')
{
// mémoriser cette option qui inclue -h ou -H
if (varg [1][1] == 'b')
opthb = opthb | 5;
else
opthb = 7;
}
// sinon, prendre en compte l'option -T
else if (varg [1][1] == 'T')
optT = 1;
// sinon, option incorrecte
else
// "Syntaxe : %s [-(h|H|b|B)] [-T] nom_fichier_mail"
psyntaxe ("SYNT_VOIRFMAIL");
// un argument traité
varg ++;
}
// controle du nombre d'arguments
if (nbarg == 1)
{
// ouvrir le fichier mail
fmail = fopen (varg [1], "r");
// si le fichier a pu être ouvert
if (fmail)
{
// afficher l'entête du mail
aff_entete ();
// afficher son contenu
aff_corpsmail ();
// et fermer le fichier mail
fclose (fmail);
}
else
// "Fichier %s non trouvé"
aff_err_arg ("FICH_ABSENT", varg [1]);
}
else
// "Syntaxe : %s [-(h|H)] [-T] nom_fichier_mail"
psyntaxe ("SYNT_VOIRFMAIL");
// pour faire plaisir à gcc qui veut une fonction main de type int
return (0);
}
/* lit l'entête du message choisi et l'affiche */
void aff_entete ()
{
long pos_deblig; // position dans le fichier en début de ligne
// position dans le fichier mail des principaux champs de l'entête
long posDate, posFrom, posXorig, posTo, posCc, posReply, posSubject,
posContent;
char *varenv_xorig; // variable d'environnement libremail_xorig
char xorig; // information utile de libremail_xorig
// initialisation
posDate = -1;
posFrom = -1;
posXorig = -1;
posTo = -1;
posCc = -1;
posReply = -1;
posSubject = -1;
posContent = -1;
// récupérer la partie significative de la variable libremail_xorig
varenv_xorig = getenv ("libremail_xorig");
if (varenv_xorig)
xorig = tolower (*varenv_xorig);
else
xorig = '\0';
// lecture de l'entête et mémorisation de la position des champs importants
do
{
// récupérer la position en début de ligne
pos_deblig = ftell (fmail);
// lire une ligne de l'entête du message
lire_fmail ();
// repérage des champs importants et mémorisation de leur position
// Le premier champ est un peu pour le fun
if ((start ("X-Mailer") || start ("User-Agent")) && ! optT)
puts (buf_lect); // le mailer est affiché directement
else if (start ("Date"))
posDate = pos_deblig;
else if (start ("From"))
posFrom = pos_deblig;
else if (start ("X-Original-From") && xorig != 'n')
posXorig = pos_deblig;
else if (start ("To"))
posTo = pos_deblig;
else if (start ("Cc"))
posCc = pos_deblig;
else if (start ("Reply-To"))
posReply = pos_deblig;
else if (start ("Subject"))
posSubject = pos_deblig;
else if (start ("Content-Type"))
posContent = pos_deblig;
else if (start ("Content-Transfer-Encoding"))
mem_encodage ();
}
while (buf_lect [0] != '\0'); // lecture entête terminée si ligne vide
// si mode de fonctionnement standard
if (! optT)
{
// affichage ordonné des champs principaux de l'entête
if (posDate >= 0)
affchamp (posDate, 0);
if (posFrom >= 0 && (posXorig < 0 || xorig == '2'))
affchamp (posFrom, 1);
if (posXorig >= 0)
affchamp (posXorig, 1);
if (posTo >= 0)
affchamp (posTo, 1);
if (posCc >= 0)
affchamp (posCc, 1);
if (posReply >= 0)
affchamp (posReply, 1);
if (posSubject >= 0)
affchamp (posSubject, 1);
}
// sinon affichage réduit au sujet sans le nom de ce champ
else if (posSubject >= 0)
affchamp (posSubject + 8, 1);
// revenir au début du corps du message
fseek (fmail, pos_deblig, SEEK_SET);
// récupérer le type principal du message et ses caractéristiques
recup_typeorig (posContent);
}
/* affiche un champ de l'entête d'une ou plusieurs lignes
repéré à partir de sa position dans le fichier mail */
void affchamp (long pos_deblig, int conversion)
{
// se positionner sur la ligne contenant le champ
fseek (fmail, pos_deblig, SEEK_SET);
// lire cette ligne
lire_fmail ();
// répéter
do
{
// interpréter si nécessaire les caractères spéciaux
if (conversion)
majlignentete ();
// et afficher la ligne
printf ("%s", buf_lect);
// en tenant compte d'un éventuel \n dans le buffer
if (buf_lect [strlen (buf_lect) - 1] != '\n')
putchar ('\n');
// lire la ligne suivante
lire_fmail ();
}
// jusqu'à ce qu'on ait traité tout le champ
while (*buf_lect == ' ' || *buf_lect == '\t');
}
/* lit le corps du message choisi et l'affiche */
void aff_corpsmail ()
{
// sauter la ligne blanche entre l'entête et le corps du mail
lire_fmail ();
// affichage du contenu du mail
if (ctypeorig & Multipart)
// il faudra analyser les sections
aff_mail ();
else
// un affichage simple suffit
aff_texte ();
}
/* suppression des balises html et affichage du reste */
void filtre_balhtm ()
{
// supprimer les balises html
sup_balhtm ();
// réduit à un les blancs multiples et les supprime en fin de ligne
sup_multiblancs ();
// et convertir les caractère sous la forme &...;
conv_carhtm ();
// si la dernière ligne lue n'est pas vide
if (*buf_lect && *buf_lect != '\n')
{
// l'afficher
printf ("%s", buf_lect);
// et mémoriser le fait qu'elle n'est pas vide
lig_nonvide = 1;
}
// sinon si la précédente n'était pas vide ou pas d'option -H
else if (lig_nonvide)
{
// l'afficher
putchar ('\n');
// et mémoriser le fait qu'elle est vide
lig_nonvide = 0;
}
}
/* affichage du contenu d'un mail en mode multipart */
void aff_mail ()
{
// mémorisation des modes multipart trouvés
int multipmixed = 0, multipalter = 0, multiprel = 0, multiprep = 0;
// mémoriser tous les modes multipart imbriqués
do
{
switch (ctype)
{
case MultipMixed : multipmixed = 1;
break;
case MultipAlter : multipalter = 1;
break;
case MultipRep : multiprep = 1;
break;
case MultipRel : multiprel = 1;
}
// passer à la section suivante
prochaine_section ();
// récupérer ses caractéristiques
recup_infos_section ();
}
while ((ctype & Multipart) && lire_fmail ());
// indiquer si le mail peut contenir des pièces jointes
if (multipmixed)
// "Pièce(s) jointes(s) probable(s)"
affiche_msg ("PJ_PROBABLE");
// si une section multipart/alternative a été trouvée, se positionner
// (si l'on n'y est pas) sur la section text/plain ou text/html du mail
if (multipalter)
{
if (opthb)
posit_texthtm ();
else
posit_texte ();
}
// générer une ligne de séparation avec l'entête
putchar ('\n');
// si structure du mail non conforme, message d'erreur
if (! lire_fmail ())
{
if (opthb)
// "Pas de zone texte html dans ce mail !!!"
affiche_msg ("MANQUE_ZONE_HTML");
else
// "Pas de zone texte dans ce mail !!!"
affiche_msg ("MANQUE_ZONE_TEXTE");
}
// si on doit supprimer la partie html avant <body
if (opthb & 4)
// le mémoriser
avantbody = 1;
// lecture et affichage du corps du message
do
{
// mise en forme de la dernière ligne lue
majligne ();
// si on est dans l'entête html qu'on doit supprimer
if (avantbody)
// le faire
supavantbody ();
// si option de suppression des balises html
if (opthb & 2)
// les supprimer
filtre_balhtm ();
// sinon afficher simplement la ligne
else
printf ("%s", buf_lect);
// et lecture de la suivante
if (! lire_fmail ())
return; // on sort en fin de fichier
// si mode multipart/report, on saute les entêtes de section
if (multiprep && nbordures && surbordure ())
{
// aller à la prochaine ligne vide
while (lire_fmail () && *buf_lect)
;
}
}
// on s'arrête en fin de fichier, ou sur la prochaine bordure
while (nbordures == 0 || ! surbordure ());
// si mode multipart mixed on va lister les pièces jointes
if (ctypeorig == MultipMixed)
liste_pj ();
}
/* lecture et affichage d'un mail de type text/plain */
void aff_texte ()
{
// si le mail est au format text/plain
if (ctypeorig == TextPlain)
// on ne traitera pas les balises html
opthb = 0;
// si texte encodé base 64
if (encodage_texte == Base64)
// générer une ligne de séparation avec l'entête
putchar ('\n');
// si on doit supprimer la partie html avant <body
if (opthb & 4)
// le mémoriser
avantbody = 1;
// répéter
do
{
// mise en forme de la dernière ligne lue
majligne ();
// si on est dans l'entête html qu'on doit supprimer
if (avantbody)
// le faire
supavantbody ();
// si option de suppression des balises html
if (opthb & 2)
// les supprimer
filtre_balhtm ();
// sinon afficher simplement la ligne
else
printf ("%s", buf_lect);
// et lecture de la suivante
}
// on s'arrête en fin de fichier
while (lire_fmail ());
}
/* pour compatibilité avec la bibliothèque trtsection */
void genligne (char *chaine)
{
printf ("%s", chaine);
}