/*
    Fichier simulsmtp.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


    Bibliothèque de fonctions permettant
    la simulation d'envoi de mails au serveur smtp
    Fonctionne même sans connexion au réseau
*/


#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "buflect.h"
#include "smtp.h"
#include "base64.h"


#define defaut_port_smtp  25  // port utilisé par défaut par les serveurs smtp

#define octet      unsigned char


/* Connexion au serveur smtp (même fonction qu'en mode normal) */

int connect_smtp (char *infoserveur)
{
    octet *carinfo;        // caractère de infoserveur
    char  serv_smtp [120]; // nom du serveur smtp utilisé
    int   port;            // numéro du port smtp utilisé
    FILE  *fich_auth;      // descripteur du fichier d'authentification smtp
    char  bufin [120];     // buffer pour lire le fichier d'authentification
    char  bufw [120];      // buffer d'envoi d'une ligne ou requête smtp
    int   caract;          // caractère du fichier d'authentification smtp
    int   retour;          // code de retour de la fonction


    // initialisation du numéro de port par défaut
    port = defaut_port_smtp;

    // si la ligne smtp de fichier de configuration fait
    // référence à un fichier d'authentification smtp
    if (*infoserveur == '>')
    {
        // se positionner sur le nom de ce fichier
        carinfo = infoserveur + 1;

        while (*carinfo == ' ' || *carinfo == '\t')
            carinfo ++;

        fich_auth = fopen (carinfo, "r");

        if (fich_auth)
        {
            // recupérer le nom du serveur smtp
            fgets (serv_smtp, 120, fich_auth);
            serv_smtp [strlen (serv_smtp) - 1] = '\0';

            // mémoriser les autres lignes particulières du fichier
            // d'authentification smtp (on s'arrête sur une ligne vide)
            while (fgets (bufin, 120, fich_auth) && *bufin != '\n')
            {
                bufin [strlen (bufin) - 1] = '\0';

                // numéro de port spécifié ?
                if (startligne (bufin, "port"))
                {
                    // récupérer le numéro du port
                    carinfo = bufin + 4;

                    while (*carinfo == ' ' || *carinfo == '\t')
                        carinfo++;

                    port = atoi (carinfo);

                    // le vérifier sommairement
                    if (!port)
                    {
                        // "Numéro de port smtp invalide"
                        affiche_err ("PORT_SMTP_INVALIDE");
                        retour = 0;
                    }
                }
            }

            // tentative de connexion au serveur smtp
            if (port)
                retour = connect_serv_smtp (serv_smtp, port);

            // si la connexion s'est bien déroulée
            if (retour)
            {
                // se positionner sur la première ligne
                // du dialogue d'authentification
                while (fgets (bufin, 120, fich_auth) && *bufin == '\n')
                    ;

                // dialogue d'authentification
                do
                {
                    // mise en forme de la ligne lue
                    bufin [strlen (bufin) - 1] = '\0';

                    // si ligne à encoder base 64
                    if (startligne (bufin, "b64"))
                    {
                        // l'encoder avant de l'envoyer
                        encode64 (bufin + 4, bufw, strlen (bufin + 4));
                        puts (bufin);
                        envoie_smtp (bufw);
                    }
                    // sinon, envoyer directement la ligne
                    else
                        envoie_smtp (bufin);

                    // et lire la réponse du serveur
                    lire_smtp ();
                }
                // passage à la ligne suivante
                while (fgets (bufin, 120, fich_auth));
            }

            // libérer le fichier d'authentification smtp
            fclose (fich_auth);
        }
        else
        {
            // message d'erreur
            // "Fichier %s non trouvé"
            aff_err_arg ("FICH_ABSENT", carinfo);
            retour = 0;
        }
    }
    // sinon simple connexion à un serveur smtp sans authentification
    else
    {
        // parcourir le nom du serveur smtp
        carinfo = infoserveur;

        while (*carinfo > ' ')
            carinfo ++;

        // si le nom du serveur smtp est suivi d'autres informations
        if (*carinfo)
        {
            // terminer le nom du serveur smtp
            *carinfo = '\0';

            // se positionner sur le numéro de port éventuel
            do
                carinfo++;
            while (*carinfo == ' ' || *carinfo == '\t');
        }

        // si un numéro de port semble présent
        if (*carinfo)
            // le récupérer
            port = atoi (carinfo);

        // si numéro de port trouvé ou si on a conservé le port par défaut
        if (port)
            // établir la connexion smtp avec le port choisi
            retour = connect_serv_smtp (infoserveur, port);

        // sinon message d'erreur
        else
        {
            // "Numéro de port smtp invalide"
            affiche_err ("PORT_SMTP_INVALIDE");
            retour = 0;
        }

        // si la connexion smtp s'est bien déroulée
        if (retour)
        {
            // générer le message  helo nom_de_calculateur
            strcpy (bufw, "HELO ");
            gethostname (bufw + 5, sizeof (bufw) - 5);

            // identification de l'ordinateur connecté
            envoie_smtp (bufw);
            lire_smtp ();
        }
    }

    // renvoyer le code de retour de la fonction
    return (retour);
}



/* Simulation de connexion réussie au serveur smtp sans authentification */

int connect_serv_smtp (char *serveur, int port_smtp)
{
    char bufw [120];  // buffer d'envoi d'une ligne ou requête smtp


    printf ("Connexion au serveur %s sur le port %d\n", serveur, port_smtp);

    // simulation de la réponse du serveur smtp
    lire_smtp ();
    return (1);
}



/* teste si la ligne passée en paramètre commence par un mot clé particulier */

int startligne (char *ligne, char *motcle)
{
    int i;

    i = 0;

    // on teste caractère par caractère en ignorant la casse
    while (motcle [i] && tolower (ligne [i]) == tolower (motcle [i]))
        i++;

    // le mot clé doit être suivi d'un blanc dans la ligne lue
    return (ligne [i] == ' ');
}



/* Simulation écriture de données */

void envoie_smtp (char *buffer)
{
    puts (buffer);
}



/* Simulation lecture d'une ligne de données */

void lire_smtp ()
{
    strcpy (buf_lect, "250 OK");
}



/* Simulation déconnexion propre du serveur smtp */

void deconnect_smtp ()
{
    // envoi du message de deconnexion
    envoie_smtp ("QUIT");

    // lecture de l'acquittement
    lire_smtp ();
}