/*
    Fichier deplpartaille.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 dépassant la
    taille limite ou n'atteignant pas la taille minimale passée en
    paramètre.

    Si la taille indiquée est positive, il s'agit de la taille
    maximale au delà de laquelle le mail est déplacé.
    Si la taille indiquée est négative, il s'agit de la taille
    minimale en deçà de laquelle le mail est déplacé.

    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 <ctype.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "messages.h"
#include "buflect.h"
#include "ficonf.h"
#include "pop.h"
#include "smtp.h"
#include "copiedepl.h"


/* constante */

// nombre de mails qu'on peut déplacer en une seule passe
#define szmaxliste    100


/* prototypes */
void selectmails (int numdepart);
void copieliste ();
void deplaceliste ();


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


long taillepivot;    // taille minimale ou maximale des mails déplacés
int  listemail [szmaxliste];  // numéro des gros mails à tester
int  szlistemail;    // nombre d'éléments dans listemail


/* 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 numail;          // numéro du mail à déplacer ou copier
    int  optc;            // option : on conserve les mails déplacés


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

    // nombre d'arguments passés en paramètre
    nbarg--;

    // si option -c (copie des mails plutôt que déplacement)
    if (nbarg > 1 && strcmp (varg [1], "-c") == 0)
    {
        // mémoriser cette option
        optc = 1;

        // sauter l'argument traité
        varg ++;
        nbarg --;
    }
    // sinon, les mails choisis seront déplacés
    else
        optc = 0;

    // controle du nombre d'arguments restants
    if (nbarg == 2)
    {
        // récupérer la taille pivot des mails
        // acceptés pour n'importe quel expéditeur
        taillepivot = atol (varg [1]);

        // erreur de syntaxe si la taille pivot est nulle
        if (! taillepivot)
        {
            // "Paramètre taille incorrect ou mal placé"
            affiche_err ("ERR_TAILLE");
            return (0);
        }

        // cette taille peut être exprimée en koctets
        if (tolower (varg [1][strlen (varg [1]) - 1]) == 'k')
            taillepivot *= 1024;

        // ouvrir le fichier de configuration
        fconf = ouvre_ficonf (varg [2]);

        // si on a pu y accéder
        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);

                // sélectionner les mails à déplacer en fonction de leur taille
                selectmails (0);

                // s'il y a des mails à déplacer
                if (szlistemail)
                {
                    // 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))
                    {
                        // déplacer ou copier les mails sélectionnés
                        if (optc)
                            copieliste ();
                        else
                            deplaceliste ();

                        // si la liste des mails sélectionnés avait atteint sa
                        // taille maximale, on relance une ou plusieurs étape(s)
                        // de filtrage
                        while (szlistemail == szmaxliste)
                        {
                            // sélectionner d'autres mails à déplacer
                            selectmails (listemail [szlistemail - 1]);

                            // s'il y en a
                            if (szlistemail)
                            {
                                // déplacer ou copier les mails sélectionnés
                                if (optc)
                                    copieliste ();
                                else
                                    deplaceliste ();
                            }
                        }

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

                        // fermeture de la connexion smtp
                        deconnect_smtp ();
                    }
                }
                // sinon, aucun mail à déplacer ou copier
                else
                {
                    // message adapté à l'opération demandée
                    if (taillepivot > 0)
                        // "Aucun mail ne dépasse la taille limite"
                        affiche_msg ("AUCUN_GROSMAIL");
                    else
                        // "Aucun mail n'est plus petit que la taille choisie"
                        affiche_msg ("AUCUN_PETITMAIL");
                }

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

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

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


/* mémorise les numéros des mails à déplacer en fonction
   de leur taille et dont le numéro est > numdepart */


void selectmails (int numdepart)
{
    long numail;     // numéro du mail dont on liste la taille
    long taillemail; // taille de ce mail


    // initialisation
    szlistemail = 0;

    // mémoriser les tailles des mails
    env_pop ("LIST");

    // sauter le message d'entête de la liste
    lire_pop ();

    // lire la taille d'un mail
    lire_pop ();

    // tantque des mails restent à analyser
    while (buf_lect [0] != '.')
    {
        // si ce mail n'a pas été encore examiné comme mail à déplacer
        // et que la liste des mails à déplacer n'est pas pleine
        if (numail > numdepart && szlistemail < szmaxliste)
        {
            // récupérer la taille du mail
            sscanf (buf_lect, "%ld%ld", &numail, &taillemail);

            // astuce pour simplifier le test qui suit
            if (taillepivot < 0)
                taillemail = - taillemail;

            // si ce mail dépasse la taille maximale (taillepivot > 0)
            // ou n'atteint pas la taille minimale (taillepivot < 0)
            if (taillemail > taillepivot)
            {
                // mémoriser le numéro de ce mail
                listemail  [szlistemail ++] = numail;
            }
        }

        // lire la taille du mail suivant
        lire_pop ();
    }
}


/* réexpédie les mails sélectionnés vers la nouvelle adresse
   email sans les supprimer sur le serveur courant */


void copieliste ()
{
    int numail;  // numéro de mail à copier
    int i;       // compteur


    // pour tous les mails sélectionnés
    for (i = 0; i < szlistemail; i++)
    {
        // récupérer le numéro du mail
        numail = listemail [i];

        // "Copie du mail n° %d"
        printf (message ("COPIE_MAIL"), numail);
        fflush (stdout);

        // envoyer une copie du mail à l'autre adresse
        copiemail (listemail [i]);
    }
}


/* réexpédie les mails sélectionnés vers la nouvelle adresse
   email et les supprime du serveur courant */


void deplaceliste ()
{
    char bufw [120]; // buffer d'envoi d'une requête de destruction
    int numail;      // numéro de mail à copier
    int i;           // compteur


    // pour tous les mails sélectionnés
    for (i = 0; i < szlistemail; i++)
    {
        // récupérer le numéro du mail
        numail = listemail [i];

        // "Déplacement du mail n° %d"
        printf (message ("DEPL_MAIL"), numail);
        fflush (stdout);

        // envoyer une copie du mail à l'autre adresse
        copiemail (listemail [i]);

        // demande de destruction du mail sur le serveur initial
        detruitmail (listemail [i]);
    }
}