#include "signature.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
	Auteur: Benoit Papillault
	Creation: 08/01/1998

	Manipulation des fichiers de signatures. Il est a noter que
	les signatures incorrects devraient etre eliminer lors des
	operations de lecture/ecriture
*/

void signature_afficher(const struct signature *sign)
{
	int i;

	printf("Signature de '%s':\n",sign->name);
	printf("\tpt_entree=%d\n",sign->pt_entree);
	printf("\tsize=%d\n",sign->size);

	printf("\tcode/mask");
	for (i=0;i<sign->size;i++)
	{
		if ((i%16)==0)
			printf("\n");
		printf("%02x/%02x ",sign->code[i],sign->mask[i]);
	}
	printf("\n");
}

/* retourne 1 en cas de succes, 0 sinon */

int signature_lire(FILE *fp,struct signature *sign)
{
	char	namelen;
	byte	buffer[4];

	/* dans le fichier, on a:
	- 1 octet indiquant la longueur de la chaine
	- la chaine
	- 4 octets: le pt_entree avec poids forts d'abord
	- 4 octets: le champ size, idem
	- les octets corespondants a code
	- les octets corespondants a mask
	*/

	if (fread(&namelen,1,1,fp) != 1)
		return 0;

	sign->name = (char *)malloc(namelen+1);
	if (sign->name == NULL)
		return 0;

	sign->name[namelen] = 0;

	if (fread(sign->name,namelen,1,fp) != 1)
		return 0;

	if (fread(buffer,4,1,fp) != 1)
		return 0;

	sign->pt_entree = (buffer[0]<<24) | (buffer[1]<<16) | (buffer[2]<<8)
				| buffer[3];

	if (fread(buffer,4,1,fp) != 1)
		return 0;

	sign->size = (buffer[0]<<24) | (buffer[1]<<16) | (buffer[2]<<8)
				| buffer[3];

	sign->code = (byte *)malloc(sign->size);
	sign->mask = (byte *)malloc(sign->size);

	if (sign->code == NULL || sign->mask == NULL)
		return 0;

	if (fread(sign->code,sign->size,1,fp) != 1)
		return 0;

	if (fread(sign->mask,sign->size,1,fp) != 1)
		return 0;

	return 1;	/* Hourra !!! */
}

int signature_ecrire(FILE *fp,const struct signature *sign)
{
	char	namelen;
	byte	buffer[4];
	int	tmp;

	/* voir la fonction signature_lire() pour le codage */

	namelen = strlen(sign->name);

	if (fwrite(&namelen,1,1,fp) != 1)
		return 0;

	if (fwrite(sign->name,namelen,1,fp) != 1)
		return 0;

	tmp = sign->pt_entree;
	buffer[0] = (tmp>>24) & 0xff;
	buffer[1] = (tmp>>16) & 0xff;
	buffer[2] = (tmp>> 8) & 0xff;
	buffer[3] = (tmp    ) & 0xff;

	if (fwrite(buffer,4,1,fp) != 1)
		return 0;

	tmp = sign->size;
	buffer[0] = (tmp>>24) & 0xff;
	buffer[1] = (tmp>>16) & 0xff;
	buffer[2] = (tmp>> 8) & 0xff;
	buffer[3] = (tmp    ) & 0xff;

	if (fwrite(buffer,4,1,fp) != 1)
		return 0;

	if (fwrite(sign->code,tmp,1,fp) != 1)
		return 0;

	if (fwrite(sign->mask,tmp,1,fp) != 1)
		return 0;

	return 1;
}

void signature_init(struct signature *sign)
{
	sign->name = NULL;
	sign->code = NULL;
	sign->mask = NULL;
}

void signature_done(struct signature *sign)
{
	if (sign->name != NULL)
		free(sign->name);
	if (sign->code != NULL)
		free(sign->code);
	if (sign->mask != NULL)
		free(sign->mask);
}

/* retourne 1 si le debut du bloc corespond a la signature, 0 sinon */

int signature_comparer(const struct signature *sign,byte *bloc, int len)
{
	int i;

	if (len < sign->size)
		return 0;

	for (i=0;i<sign->size;i++)
	{
		if ((bloc[i]&sign->mask[i]) != (sign->code[i]&sign->mask[i]))
			return 0;
	}

	return 1;
}

/* retourne la position de la signature dans le bloc memoire de longueur
	len, ou -1 en cas d'echec. La position est relative au debut
	du bloc */

int signature_chercher(const struct signature *sign,byte *bloc,int len)
{
	int pos;

	for (pos=0;pos<=len-sign->size;pos++)
	{
		if (signature_comparer(sign,bloc+pos,len-pos))
			return pos;
	}

	return -1;
}
