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 récupère les fichiers joints contenu dans
le fichier mail dont le nom est passé en paramètre.
Le chemin d'accès au fichier peut être absolu ou relatif
Les fichiers joints sont stockés :
1) si le répertoire racine du système de messagerie est connu
(commande recuppj lancée depui la suite vmail...)
- dans le répertoire précisé dans le fichier <racine>/dirpj
- à défaut dans le répertoire <racine>/pjointes
2) dans le cas contraire, dans un répertoire choisi par l'utilisateur
*/
#define appli // pour la déclaration de variables globales à l'application
/* variables globales au source
(pour éviter des tonnes de passages de paramètres) */
FILE *ficdest; // descripteur du fichier récupéré
char chemfich [120]; // chemin d'accès au fichier joint
/* programme principal */
int main (int nbarg, char *varg[])
{
// récupération du nom de l'exécutable
memcom (*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)
{
// extraire les pièces jointes
extraire ();
// et fermer le fichier mail
fclose (fmail);
}
else
// "Fichier %s non trouvé"
aff_err_arg ("FICH_ABSENT", varg [1]);
}
else
// "Syntaxe : %s nom_fichier_mail"
psyntaxe ("SYNT_GENE_FICMAIL");
// pour faire plaisir à gcc qui veut une fonction main de type int
return (0);
}
/* lit le message choisi et récupère les fichiers joints si
le mail est en mode multipart/mixed ou multipart/related */
void extraire ()
{
int dansmail; // pour s'arrêter de lire si fin de fichier mail
int posjoint; // position du nom du fichier joint
int posdebnom; // position du nom de fichier dans son chemin d'accès
int poschem; // position dans le chemin d'accès au fichier
int ctype; // pour mémoriser champ content-type du fichier
int derctype; // pour mémoriser champ content-type de la section
char reponse [10]; // réponse à une question
// lecture du fichier mail jusqu'au champ Content-Type
while (lire_fmail () && ! start ("Content-Type"))
;
// récupérer le type de base du fichier mail
ctype = recup_ctype ();
// si fichier en mode multipart/mixed ou multipart/related
if (ctype == MultipMixed || ctype == MultipRel)
{
// retour à la configuration standard du clavier si nécessaire
system ("stty icanon echo");
// récupérer ou choisir le répertoire de destination des pièces jointes
choixdirpj ();
//le compléter par un /
posdebnom = strlen (chemfich);
chemfich [posdebnom++] = '/';
chemfich [posdebnom] = '\0';
// mémoriser la bordure
while (*buf_lect && ! mem_boundary ())
dansmail = lire_fmail ();
// boucle de récupération de fichiers joints
while (dansmail && nbordures)
{
// initialisation
chemfich [posdebnom] = '\0';
// se positionner sur la prochaine section si on n'y est pas déjà
while (dansmail && ! surbordure ())
dansmail = lire_fmail ();
// initialisation du type de la section courante
derctype = 0;
// initialisation du mode d'encodage du fichier
encodage_texte = defaut;
// chercher et afficher le nom du fichier joint s'il y en a un
do
{
// lire une ligne et la convertir
dansmail = lire_fmail ();
// mémoriser le type de la section courante
if (start ("Content-Type"))
derctype = recup_ctype ();
// chercher la position du nom de fichier
posjoint = posnomfic ();
// si trouvé et pas une section text/html
if (posjoint && derctype != TextHtml)
{
// convertir les données encodées comme dans une entête
majlignentete ();
// récupérer son nom
poschem = posdebnom;
// sans les (horribles) blancs qu'il pourrait contenir !!!
while (buf_lect [posjoint] != '"' && buf_lect [posjoint])
{
// pas de blanc dans un nom de fichier !!!
if (buf_lect [posjoint] != ' ')
chemfich [poschem++] = buf_lect [posjoint];
posjoint++;
}
// terminer le nom de fichier
chemfich [poschem] = '\0';
}
// mémoriser aussi le mode d'encodage
else if (start ("Content-Transfer-Encoding"))
mem_encodage ();
}
while (dansmail && buf_lect [0] != '\0');
// si la section concerne un fichier joint
if (chemfich [posdebnom])
{
// demande de confirmation si le fichier existe déjà
if (access (chemfich, 0) == 0)
{
// "Fichier %s déjà existant.\n"
// "Voulez vous le remplacer ? "
printf (message ("FICH_EXISTANT"), chemfich);
affiche_msg_nocr ("MAJ_FICJOINT");
// lire et traiter la réponse
fgets (reponse, sizeof (reponse), stdin);
// indicateur pour test ultérieur
*reponse = 'o';
}
// si l'ouverture s'est bien passée
if (ficdest)
{
// récupérer le fichier en tenant compte du mode d'encodage
if (encodage_texte == Base64)
recup_b64 ();
else if (encodage_texte == QuotedPrint)
recup_quot ();
else
recup_brut ();
// récupération terminée
fclose (ficdest);
}
// sinon message d'erreur éventuel
else if (tolower (*reponse) != 'n')
// "Le fichier %s n'a pu être récupéré"
aff_err_arg ("ERR_RECUP_PJ", chemfich);
}
}
}
else
// "Ce fichier ne contient pas de pièces jointes"
affiche_err ("MAIL_SANS_PJ");
}
/* récupère un fichier joint encodé base64 */
void recup_b64 ()
{
int nbcar; // nombre de caractères après supprssion de l'encodage base64
int i; // compteur
// tant que ligne vide
while (*buf_lect == '\0')
// lire la ligne suivante
lire_fmail ();
// répéter
do
{
// convertion les données de la ligne
nbcar = decode64 (buf_lect);
// recopier les caractères correspondants dans le fichier
for (i = 0; i < nbcar; i++)
fputc (buf_lect [i], ficdest);
}
// passer à la ligne suivante jusqu'à ligne vide ou bordure
while (lire_fmail () && *buf_lect && !surbordure ());
}
/* récupère un fichier joint encodé quoted-printable
Remarque importante : on n'utilise pas majligne pour la conversion
en effet, majligne filtre les caractères de controle pour limiter
les problèmes d'affichage, ce qu'il faut éviter de faire pour
récupérer un fichier joint */
void recup_quot ()
{
char *carcourant; // caractères de buf_lect
// tant que non fin de section, lire une ligne
while (lire_fmail () && !surbordure ())
{
// positionnement en début de buffer
carcourant = buf_lect;
// tant que non fin de ligne
while (*carcourant)
{
// si caractère ordinaire
if (*carcourant != '=')
{
// on le recopie
fputc (*carcourant, ficdest);
// et on passe au suivant
carcourant ++;
}
// sinon
else
{
// avancer d'un caractère
carcourant ++;
// si on n'est pas en fin de ligne
if (*carcourant)
{
// convertir le code hexa et le recopier dans le fichier
fputc (hexa (carcourant), ficdest);
// se positionner après le code hexa
carcourant = carcourant + 2;
}
}
}
// rajout d'un éventuel CR LF
if (*(carcourant - 1) != '=')
{
fputc ('\r', ficdest);
fputc ('\n', ficdest);
}
// on traitera de la même manière les autres lignes
}
}
/* récupère un fichier joint non encodé */
void recup_brut ()
{
char *carcourant; // caractères de buf_lect
int sautligne = 0; // mémorise les sauts de ligne en attente
// tant que non fin de section, lire une ligne
while (lire_fmail () && !surbordure ())
{
// si ce n'est pas la première ligne
if (sautligne)
{
// terminer la ligne précédente par un caractère LF
fputc ('\n', ficdest);
// inutile de remettre sautligne à 0
}
// positionnement en début de buffer
carcourant = buf_lect;
// tant que non fin de ligne
while (*carcourant)
{
// on recopie le caractère lu
fputc (*carcourant, ficdest);
// et on passe au suivant
carcourant ++;
}
// un saut de ligne sera nécessaire si d'autres lignes suivent celles-ci
sautligne = 1;
// on traitera de la même manière les autres lignes
}
}
/* récupère le nom du répertoire de destination des pièces jointes */
void choixdirpj ()
{
FILE *fic_dirpj; // descripteur fichier contenant nom répertoire pièces
char reponse [10]; // réponse à une question
// si on connait le répertoire racine des mails
// (ce qui est le cas lorsque le sous répertoire d'envoi est connu)
if (getenv ("mailenv"))
{
// récupérer ce répertoire
strcpy (chemfich, getenv ("mailenv"));
// et accéder au fichier contenant le nom du répertoire pièces jointes
strcpy (chemfich + strlen (chemfich) - 6, ficdir ("FIC_DIRPJ"));
fic_dirpj = fopen (chemfich, "r");
// si ce fichier a pu être ouvert
if (fic_dirpj)
{
// récupérer le nom du répertoire destiné aux pièces jointes
fgets (chemfich, 120, fic_dirpj);
// suppression de l'éventuel \n en fin de ligne
if (chemfich [strlen (chemfich) - 1] == '\n')
chemfich [strlen (chemfich) - 1] = '\0';
// lecture du fichier terminée
fclose (fic_dirpj);
}
// sinon
else
// le répertoire destiné aux pièces jointes est défini par défaut
strcpy (chemfich + strlen (chemfich) - 5, ficdir ("DIR_PJOINTES"));
}
// sinon (répertoire racine de la messagerie inconnu)
else
{
// saisir au clavier le nom du répertoire des pièces jointes
// "Nom du répertoire de destination des pièces jointes ?"
affiche_msg ("REPERT_PJ");
fgets (chemfich, 120, stdin);
// suppression de l'éventuel \n en fin de ligne
if (chemfich [strlen (chemfich) - 1] == '\n')
chemfich [strlen (chemfich) - 1] = '\0';
// si ce répertoire n'existe pas
if (access (chemfich, 0) < 0)
{
// demande de confirmation
// "Répertoire inexistant, voulez vous le créer ? "
affiche_msg_nocr ("CREAT_REPERT");
fgets (reponse, 10, stdin);
// si réponse négative
if (tolower (*reponse) == 'n')
exit (-1); // on s'arrêtera sans récupérer les fichiers
}
}
// créer si nécessaire le répertoire des pièces jointes
mkdir (chemfich, 0755);
// erreur fatale si le répertoire n'existe pas encore
if (access (chemfich, 0) < 0)
// "Répertoire %s inexistant"
errfatale ("REPERT_INEXISTANT", chemfich);
}