/*
    Fichier deplpartiel.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éplace vers une autre boite aux lettres parmi
    les mail en attente sur le serveur de messagerie, ceux dont
    l'un des champs contient (ou ne contient pas) une chaine de
    caractères particulière.

    Une option permet de conserver les mails sélectionnés dans la
    boite aux lettres initiale. Dans ce cas, les mails sélectionnés
    sont seulement copiés.

    Un fichier de configuration est utilisé pour se connecter à
    la boite aux lettres, pour connaitre l'adresse d'expédition
    et pour sélectionner le serveur SMTP servant à la réexpédition
    des mails.
    Il s'agit d'une variante des fichiers de configuration utilisés
    par la plupart des autres outils de libremail.
*/


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

#include <stdio.h>
#include <string.h>
#include "messages.h"
#include "buflect.h"
#include "ficonf.h"
#include "pop.h"
#include "smtp.h"
#include "trtentete.h"
#include "copiedepl.h"


/* prototype */
int  testchamp (char *nomchamp, char *chainetest, int numes);


/* programme principal */

int main (int nbarg, char *varg[])
{
    char serv_smtp [120]; // nom du serveur smtp utilisé
    FILE *fconf;         // descripteur du fichier de configuration
    long nbmes;          // nombre de mails sur le serveur
    long numail;         // numéro du mail à déplacer ou copier
    long nbtraites;      // récapitulatif nombre de mails copiés ou déplacés
    int  optc;           // option : on conserve les mails déplacés
    int  optn;           // option : mail déplacé si valchamp n'est pas trouvé
                         //          dans le champ nomchamp ou si champ absent
    char *nomchamp;      // nom du champ sur lequel porte la sélection des mails
    char *valchamp;      // valeur de nomchamp pour que le mail soit sélectionné

    // message signalant la copie ou le déplacement d'un mail
    char mess_copdepl [50];


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

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

    // options de fonctionnement par défaut
    optc = 0;
    optn = 0;

    // récupération des options de fonctionnement éventuelles
    while (nbarg > 0 && **varg == '-')
    {
        switch (varg [0][1])
        {
            // option copie des mails plutôt que déplacement
            case 'c': optc = 1;
                      break;

            // option déplacement du mail si chaine non trouvée
            case 'n': optn = 1;
                      break;

                      // "Option %s incorrecte"
            default : aff_err_arg ("ERR_OPTION", *varg);
                      nbarg = 0;   // pour afficher la syntaxe de la commande
        }

        // décompter l'argument traité
        varg ++;
        nbarg --;
    }

    // récupération du nom de champ et de sa valeur
    if (nbarg >= 3)
    {
        // récupérer nomchamp et valchamp
        nomchamp = *varg;
        valchamp = varg [1];

        // décompter les arguments traités
        varg  = varg  + 2;
    }

    // la présence du nom de champ et de sa valeur était obligatoire
    nbarg = nbarg - 2;

    // on autorise la présence de l'option -c après -n nom_champ chaine_champ
    if (nbarg > 0 && strcmp (*varg, "-c") == 0)
    {
        // mémoriser l'option
        optc = 1;

        // décompter l'argument traité
        varg ++;
        nbarg --;
    }

    // controle du nombre d'arguments restant
    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 et mémoriser les adresses
                // Email d'expédition et de destination
                mem_adr (adr_exped, fconf);
                mem_adr (adr_dest, fconf);

                // récupération du nombre de mails
                nbmes = nbmails ();

                // si des mails peuvent être traités
                if (nbmes)
                {
                    // recupérer le nom du serveur smtp
                    fgets (serv_smtp, 120, fconf);
                    serv_smtp [strlen (serv_smtp) - 1] = '\0';

                    // connexion au serveur smtp pour l'envoi des mails
                    if (connect_smtp (serv_smtp))
                    {
                        // initialisation
                        nbtraites = 0;

                        // mémorisation message adapté au traitement des mails
                        if (optc)
                            strcpy (mess_copdepl, message ("COPIE_MAIL"));
                        else
                            strcpy (mess_copdepl, message ("DEPL_MAIL"));

                        // pour chaque mail du serveur
                        for (numail = 1; numail <= nbmes; numail++)
                        {
                            // si le champ à tester contient la chaine
                            // (ou ne la contient pas si option -n)
                            if (testchamp (nomchamp, valchamp, numail) != optn)
                            {
                                // message indiquant copie ou déplacement mail
                                printf (mess_copdepl, numail);
                                fflush (stdout);

                                // envoyer une copie du mail à l'autre adresse
                                copiemail (numail);

                                // si déplacement des mails
                                if (! optc)
                                    // supprimer le mail du premier serveur
                                    detruitmail (numail);

                                // on compte les mails copiés ou déplacés
                                nbtraites ++;
                            }
                        }

                        // édition d'un récapitulatif adapté
                        if (optc)
                            // "\n%d mails copiés sur %d\n"
                            printf (message ("TOTAL_COPIES"), nbtraites, nbmes);
                        else
                            // "\n%d mails déplacés sur %d\n"
                          printf (message ("TOTAL_DEPLACES"), nbtraites, nbmes);

                        // pour l'affichage
                        putchar ('\n');

                        // fermeture de la connexion smtp
                        deconnect_smtp ();
                    }
                }

                // se déconnecter proprement du serveur pop
                deconnect_pop ();
            }

            // on n'a plus besoin du fichier de configuration
            fclose (fconf);
        }
    }
    else
        // "Syntaxe : %s [-c] [-n] nom_champ chaine_champ fichier_configuration"
        psyntaxe ("SYNT_DEPLPARTIEL");

    // pour faire plaisir à gcc qui veut une fonction main de type int
    return (0);
}


/* vérifie si le champ nomchamp du mail de numéro numes
   contient la chaine passée en 2ème paramètre */


int testchamp (char *nomchamp, char *chainetest, int numes)
{
    char bufw [120];     // buffer d'envoi d'une requête
    char valchamp [120]; // contenu du champ à tester
    int  poschamp;       // positionnement dans valchamp
    int  i;              // positionnement dans chainetest


    // initialisation
    valchamp [0] = '\0';

    // message de suivi de déroulement
    // "\rAnalyse du mail n° %d       "
    printf (message ("ANALYSE_MAIL_BL"), numes);
    fflush (stdout);

    // 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 et mémorisation des caractéristiques du message
    do
    {
        // si elle contient le champ recherché
        if (start (nomchamp))
        {
            // convertir les caractères spéciaux
            majlignentete ();

            // et mémoriser ce champ
            membuf (valchamp);
        }

        // 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');

    // on se positionne au début du champ à tester
    poschamp = 0;

    // vérifier si la chaine chainetest se trouve dans valchamp
    do
    {
        i = 0;

        while (valchamp [poschamp+i] == chainetest [i])
        {
            // terminé si tous les caractères de chainetest trouvés
            if (chainetest [++i] == 0)
                return 1;
        }
    }
    // sinon recherche dans la suite de valchamp
    while (valchamp [poschamp++]);

    // aucune des chaines de la liste n'a été trouvée dans valchamp
    return (0);
}