/*
    Fichier testchamp.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 de récupérer dans un fichier
    la liste des valeurs interdites dans un champ d'un mail puis de
    vérifier si un champ de mail contient l'une de ces valeurs.
*/


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "buflect.h"
#include "messages.h"
#include "testchamp.h"



/* charge en mémoire le fichier contenant une liste de chaines de caractères */

char ** charge_valchamp (char *nomfic, int *sz_liste)
{
    char valchaine [120]; // une chaine de ce fichier
    char *nouvchaine;     // chaine retournée allouée dynamiquement
    FILE *fliste;         // descripteur du fichier des chaines à mémoriser
    char **liste;         // liste des chaines de caractères issues du fichier
    int  pos_liste;       // position dans la liste de chaines mémorisées


    // initialisation : pas encore de chaine mémorisée
    *sz_liste = 0;

    // accès au fichier contenant les chaines à mémoriser
    fliste = fopen (nomfic, "r");

    // si ce fichier existe
    if (fliste)
    {
        // compter le nombre de chaines de caractères qu'il contient
        while (fgets (valchaine, sizeof (valchaine), fliste))
            *sz_liste = *sz_liste + 1;

        // allouer la zone mémoire pour mémoriser la liste des chaines
        // la taille de la liste allouée est optimale et non limitée
        // à la compilation
        liste = malloc (*sz_liste * sizeof (char *));

        if (! liste)
            // "Manque de place mémoire, l'application ne peut fonctionner"
            errfatale ("MANQUE_MEMOIRE", NULL);

        // on revient au début du fichier
        rewind (fliste);

        // initialisation
        pos_liste = 0;

        // récupérer et mémoriser les différentes chaines de caractères
        while (fgets (valchaine, sizeof (valchaine), fliste))
        {
            // supprimer le \n en fin de ligne
            valchaine [strlen (valchaine) - 1] = '\0';

            // allouer une variable pour mémoriser la chaine lue
            nouvchaine = (char *) malloc (strlen (valchaine) + 1);

            if (! nouvchaine)
                // "Problème d'allocation mémoire"
                errfatale ("MANQUE_MEMOIRE", NULL);

            // recopier la chaine
            strcpy (nouvchaine, valchaine);

            // mémoriser la chaine dans la liste (on copie l'adresse)
            liste [pos_liste ++] = nouvchaine;
        }

        // terminé avec ce fichier
        fclose (fliste);
    }
    else
    {
        // message d'erreur si fichier des chaines à mémoriser manquant
        // "Pas de fichier %s aucun filtrage possible"
        aff_err_arg ("FIC_FILTR_ABSENT", nomfic);
    }

    // retourner le nombre d'éléments de la liste récupérés
    return (liste);
}



/* recherche si le champ du mail passée en paramètre
   contient l'une des chaines de la liste */


int trouve_valchamp (char *valchamp, char **liste, int sz_liste)
{
    char *chainetest;  // chaine de la liste à tester
    int  i, j, k;      // compteurs

    // on compare la chaine valchamp avec toutes les chaines de la liste
    for (i = 0; i < sz_liste; i++)
    {
        // permettra d'éviter des calculs de déplacements dans tableau
        chainetest = liste [i];

        // initialisation
        k = 0;

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

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

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