/*
    Fichier filtresujet.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 détruit les mails du serveur comportant une chaine de
    caractères particulière dans le sujet.

    La liste des chaines de caractères interdites est mémorisée dans
    un fichier

    Un fichier de configuration est utilisé pour se connecter à la
    boite aux lettres.
*/


#define appli   // pour la déclaration de variables globales à l'application

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "messages.h"
#include "buflect.h"
#include "ficonf.h"
#include "pop.h"
#include "testchamp.h"
#include "trtentete.h"
#include "datecour.h"
#include "szchemin.h"


/* prototypes */
int testsujet (int numes);


/* variables globales au source
   (pour éviter des tonnes de passages de paramètres) */


char **listesujet;      // mémorise les sujets interdits
int  sz_listesujet;     // nombre de sujets mémorisés dans listesujet
char bufSubject [120];  // buffer contenant le sujet du mail
int  opto, optO;        // options de traitement

// 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[])
{
    // fichier contenant la liste des chaines à tester
    char fichliste [szchemin + 12];
    char *car_fichliste; // pointeur sur un caractère de ce fichier
    FILE *fconf;         // descripteur du fichier de configuration
    FILE *ftrace;        // fichier contenant les sujets des mail refusés
    int  numes, nbmes;   // muméro du mail courant et nombre de mails
    char bufw [120];     // buffer d'envoi d'une requête de destruction de mail
    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


    // récupération du nom de l'exécutable
    memcom (*varg);

    // se positionner sur le premier argument de filtresujet
    nbarg --;
    varg ++;

    // initialisations valeur des options
    ftrace = NULL;
    opto = 0;
    optO = 0;

    // si le programme a été lancé avec des options
    while (nbarg >= 2 && **varg == '-')
    {
        // traitement des options
        switch (varg [0][1])
        {
            // option trace des mails supprimés
            case 't' : // 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;
                       break;

            // option test de la ligne d'entête d'origine (avant conversion)
            case 'o' : if (! optO)
                           opto = 1;
                       else
                           // "L'option -O est prioritaire sur l'option -o"
                           affiche_err ("PRIO_OPT_O");

                       // sauter l'argument traité
                       nbarg --;
                       varg  ++;
                       break;

            // option test de la ligne d'entête d'origine (avant conversion)
            case 'O' : optO = 1;

                       if (opto)
                           // "L'option -O est prioritaire sur l'option -o"
                           affiche_err ("PRIO_OPT_O");

                       // sauter l'argument traité
                       nbarg --;
                       varg  ++;
                       break;

            // aucune autre option n'est reconnue
                       // "Option %s incorrecte"
            default  : aff_err_arg ("ERR_OPTION", *varg);
                       nbarg = 0;  // pour rappeller la syntaxe
        }
    }

    // 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))
            {
                // récupérer le nom du répertoire racine de la messagerie
                fgets (fichliste, szchemin, fconf);

                // fabriquer le chemin d'accès au fichier contenant les
                // sujets interdits : <racine>/refus_sujet
                car_fichliste = fichliste + strlen (fichliste);
                *(car_fichliste - 1) = '/';
                strcpy (car_fichliste, ficdir ("FIC_REFUS_SUJET"));

                // charger en mémoire les sujets interdits
                listesujet = charge_valchamp (fichliste, &sz_listesujet);

                // si la liste n'est pas vide
                if (sz_listesujet)
                {
                    // 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"));

                    // vérification des différents mails
                    for (numes = 1; numes <= nbmes; numes++)
                    {
                        // si le sujet du mail contient une chaine interdite
                        if (testsujet (numes))
                        {
                            // 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 le sujet de ce mail
                               fprintf (ftrace, "%s%s\n", datecour, bufSubject);
                        }
                        else
                            conserves ++;
                    }

                    // édition d'un récapitulatif
                    // "\n%d messages conservés, %d supprimés\n"
                    printf (message ("BILAN_FILTRAGE"), conserves, supprimes);
                }

                // 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 [-(o|O)] [-t fichier_trace] fich_configuration"
        psyntaxe ("SYNT_FILT-DEST/SUJ");

    return (0);
}



/* lit l'entête d'un mail et vérifie si son sujet est autorisé */

int testsujet (int numes)
{
    char bufw [120];      // buffer d'envoi d'une requête
    char sujetbrut [120]; // buffer contenant le sujet du mail avant décodage
    int  debsujet;        // position du premier caractère significatif du sujet


    // "\rAnalyse du mail n° %d"
    printf (mess_analys, numes);
    fflush (stdout);

    // initialisations
    bufSubject [0] = '\0';
    sujetbrut  [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 sujet du mail
    do
    {
        // si on a trouvé le champ sujet
        if (start ("Subject"))
        {
            // recherche du premier caractère significatif du sujet
            debsujet = 8;

            while (buf_lect [debsujet] == ' ')
                debsujet++;

            // si option -o ou -O
            if (opto || optO)
            {
                // mémoriser le sujet du mail avant conversion en le tronquant
                // si nécessaire pour éviter un débordement de tableau
                if (strlen (buf_lect + debsujet) >= sizeof (sujetbrut))
                {
                    memcpy (sujetbrut, buf_lect + debsujet, sizeof (sujetbrut));
                    sujetbrut [sizeof (sujetbrut) - 1] = '\0';
                }
                else
                    strcpy (sujetbrut, buf_lect + debsujet);
            }

            // si on n'utilise pas l'option -O
            if (! optO)
            {
                // convertir les caractères spéciaux de la ligne
                majlignentete ();

                // tronquer si nécessaire le sujet
                if (strlen (buf_lect + debsujet) >= sizeof (bufSubject))
                     buf_lect [debsujet + sizeof (bufSubject) - 1] = '\0';

                // mémorisation du sujet converti
                strcpy (bufSubject, buf_lect + debsujet);
            }
        }

        // 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 sujets de la liste interdite
    if (optO)
        // option -O : test sur le sujet brut seulement
        return trouve_valchamp (sujetbrut, listesujet, sz_listesujet);
    else if (opto)
    {
        // option -o (seule) : test sur le sujet brut et le sujet converti
        return (trouve_valchamp (sujetbrut,  listesujet, sz_listesujet)
            ||  trouve_valchamp (bufSubject, listesujet, sz_listesujet));
    }
    else
        // aucune option : test sur le sujet converti seulement
        return trouve_valchamp (bufSubject, listesujet, sz_listesujet);
}