#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//==============================================================
int GetLocalFileHeaderName(FILE* P_FHandle,char **L_ppcFileName)
{
	char L_pucBuffer[26];
	char * L_pucFileName;
	unsigned int l_uiTmp;
	unsigned long L_dwCompressedSize,L_wFileNameLength,L_wExtraFieldLength;
	try
	{
		fread(L_pucBuffer, 1, 26, P_FHandle);
		L_dwCompressedSize=((unsigned long *)(L_pucBuffer+14))[0];
		L_wFileNameLength=((unsigned short *)(L_pucBuffer+22))[0];
		L_wExtraFieldLength=((unsigned short *)(L_pucBuffer+24))[0];
		L_pucFileName=(char*)malloc(L_wFileNameLength+1);
		l_uiTmp=fread(L_pucFileName, 1, L_wFileNameLength, P_FHandle);
		L_pucFileName[l_uiTmp]=0;
		fseek(P_FHandle,L_dwCompressedSize+L_wExtraFieldLength,SEEK_CUR);
		L_ppcFileName[0]=L_pucFileName;
		return(0);
	}
	catch(...)
	{
		printf("ERREUR dans la fonction 'GetLocalFileHeaderName'.\n");
		return(-1);
	}
}

//==============================================================
int GetCentralDirectoryStructureName(FILE* P_FHandle,char **L_ppcFileName)
{
	char L_pucBuffer[42];
	char * L_pucFileName;
	unsigned int l_uiTmp;
	unsigned short L_wFileCommentLength,L_wFileNameLength,L_wExtraFieldLength;
	try
	{
		fread(L_pucBuffer, 1, 42, P_FHandle);
		L_wFileNameLength=((unsigned short *)(L_pucBuffer+24))[0];
		L_wExtraFieldLength=((unsigned short *)(L_pucBuffer+26))[0];
		L_wFileCommentLength=((unsigned short *)(L_pucBuffer+28))[0];
		L_pucFileName=(char*)malloc(L_wFileNameLength+1);
		l_uiTmp=fread(L_pucFileName, 1, L_wFileNameLength, P_FHandle);
		L_pucFileName[l_uiTmp]=0;
		fseek(P_FHandle,L_wFileCommentLength+L_wExtraFieldLength,SEEK_CUR);
		L_ppcFileName[0]=L_pucFileName;
		return(0);
	}
	catch(...)
	{
		printf("ERREUR dans la fonction 'GetCentralDirectoryStructureName'.\n");
		return(-1);
	}
}
//==============================================================
int TestZipFile(char* P_sFileName)
{
	char L_pucBuffer[16];
	char *L_psFileName[256];
	char *L_psFileNameTemp;
	unsigned int	L_uiFileCounter1=0,L_uiFileCounter2=0,L_uiSuspicions=0,L_uiReturnValue=0;
	FILE *L_FHandle=fopen(P_sFileName,"rb");
	try
	{
		if(L_FHandle==NULL)
		{
			printf("ERREUR : Fichier non trouvé !\n");
			return(-1);
		}
		while((L_uiReturnValue==0)&&(fread(L_pucBuffer, 1, 4, L_FHandle)!=0))
		{
			switch(((unsigned int *)L_pucBuffer)[0])
			{
				case 0x04034b50 : // Local File Header - On récupère les noms de fichiers
					L_uiReturnValue=GetLocalFileHeaderName(L_FHandle,&L_psFileName[L_uiFileCounter1++]);
					break;
				case 0x02014b50 : // Central directory structure - On vérifie que le nom trouvé figure dans la liste
					L_uiReturnValue=GetCentralDirectoryStructureName(L_FHandle,&L_psFileNameTemp);
					if(strcmp(L_psFileNameTemp,L_psFileName[L_uiFileCounter2]))
					{
						printf("ALERTE : Le fichier '%s' est caché sous le nom '%s' !\n",L_psFileName[L_uiFileCounter2],L_psFileNameTemp);
						L_uiSuspicions+=1;
					}
					L_uiFileCounter2+=1;
					free(L_psFileNameTemp);
					break;
				case 0x06054b50 : // End of central dir record : Pas utile pour nous. On le passe.
					fseek(L_FHandle,16,SEEK_CUR);
					fread(L_pucBuffer, 1, 2, L_FHandle);
					fseek(L_FHandle,((unsigned short *)(L_pucBuffer))[0],SEEK_CUR);
					break;
				default:
					printf("ERREUR : Tag non reconnu, position : %08X\n",ftell(L_FHandle));
					return(1);
			}
		}
		for(L_uiFileCounter2=0;L_uiFileCounter2<L_uiFileCounter1;L_uiFileCounter2++)
			free(L_psFileName[L_uiFileCounter2]);
		fclose(L_FHandle);
		if(L_uiReturnValue==0) // Si on n'a pas rencontré d'erreur
			if(L_uiSuspicions==0)
				printf("Ce fichier ZIP semble correct.\n");
			else
				printf("Ce fichier ZIP a été hacké, %d nom(s) de fichier(s) ont été manipulés.\n\n",L_uiSuspicions);
		return(L_uiReturnValue);
	}
	catch(...)
	{
		printf("ERREUR dans la fonction 'TestZipFile'.\n");
		L_uiReturnValue=1;
	}

}
//==============================================================
int main(int argc, char* argv[])
{
	printf("SCANZIP - Scanne un fichier ZIP et indique s'il a été hacké ou non.\n");
	printf("(c) Janvier 2004, le Virus Informatique et Saint-Emilion\n\n");
	if((argc!=2))
	{
		printf("Usage : SCANZIP [Nom de fichier]\n");
		return 0;
	}
	return TestZipFile(argv[1]);
}
