/*
 * Analyse.c :
 * -----------
 * Auteur        : Xavier Mertens
 * Version   $VER: 2.55
 * Création      : 09 Feb 1992 - 13:33
 * Modification  : 02 Feb 1993 - 11:40
 * Langage       : SAS/C v6.00
 * Compatibilité : 2.x - 3.0
 * Description   : Identification du type d'un fichier d'après la lecture
 *                 de quelques octets dans celui-çi.
 * Syntaxe       : Analyse <fichier> [?] [LIST]
 * Compilation   : Voir le fichier SCOPTIONS
 *
 * Fich. reconnus: - PowerPacker 2.x
 *                 - PowerPacker 2.x protégé par mot de passe
 *                 - PowerPacker 1.x
 *                 - Source AmigaBASIC      
 *                 - Source SBPro 3.01
 *                 - Formulaire SBPro 3.01
 *                 - Base de données SBPro 3.01
 *                 - Feuille de calcul Maxiplan
 *                 - Icône
 *                 - Image IFF
 *                 - Son IFF
 *                 - Document Excellence!
 *                 - Fichier objet
 *                 - Document PageStream
 *                 - Fichier Resource 4.0
 *                 - Fichier PowerWindows 2.5b
 *                 - Document VizaWrite
 *                 - Projet IntroCAD
 *                 - Projet CanDo
 *                 - Exécutable
 *                 - Fonte
 *                 - Document PageSetter
 *                 - Une archive Arc
 *                 - Rapport SBPro 3.01
 *                 - Archive LHArc
 *                 - Archive Zoo 2.00
 *                 - Base de données DBase III +  
 *                 - Musique SoundFX 1.3
 *                 - Musique SMUS
 *                 - Sampling
 *                 - Image RAW
 *                 - Document WordPerfect 5.1
 *                 - Arbre des répertoire (.info)
 *                 - Script SKsh 1.7 (preparsed)
 *                 - Préférences 2.x - 3.0
 *                 - Une animation Real3D 1.3
 *                 - Une animation Sculpt Animate 4D Jr
 *                 - Un fichier Header du Lattice 5.0 compacté
 *                 - Une source GFABasic v3.03
 *                 - Un projet XCAD Professionnal
 *                 - Un document Kindwords
 *                 - Une animation FantaVision
 *                 - Une animation au format ANIM
 *                 - Un fichier de configuration CygnusEd profesionnal 
 *                 - Préférences 1.x
 *                 - Un fichier ASCII
 *                 - Une source C
 *                 - Un répertoire
 *                 - Une image au format GIF
 *                 - Un document PDraw 1.0
 *                 - Un exécutable compacté avec TurboImploder 4.0
 *                 - Une archive LhA
 *                 - Un requester DirectoryOpus 3.52
 *                 - Un fichier GadToolsBox
 *                 - Une source AMOS
 */

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <libraries/dosextens.h>
#include <workbench/startup.h>
#include <workbench/workbench.h>
#include <string.h>

#include <stdio.h>
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/dos_protos.h>
#include <clib/icon_protos.h>
#include <clib/wb_protos.h>

#include "Analyse.h"  /* Définitions externes */

#define PRINT(x)    Write(Output(),x,strlen(x))
#define OS_VERSION  37L
#define WARN        5
#define LOWPRI      -5
#define MAXLEN      80
#define VERSION     "2.55"
#define DATE        "02 Février 1993"
#define MAXB        8
#define WARNING     5 
#define TYPE        (FIBlock->fib_DirEntryType)
#define SIZE        (FIBlock->fib_Size)

int CXBRK(void) { return(0); }
int chkabort(void) { return(0); }

static char *VERSIONS = " $VER:2.55(02.02.93)";

struct IntuitionBase  *IntuitionBase = NULL;
struct WorkbenchBase  *WorkbenchBase = NULL;

extern struct ExecBase *SysBase;
struct MsgPort       *msgport;
struct AppIcon       *appicon;
struct FileHandle    *FHandle;
struct FileInfoBlock fib;
struct FileLock      *Verrou;

/* Prototypes des fonctions */
VOID CloseAll(int returncode);
BOOL Analyse(char *FileName);
BOOL ReadBytesInFile(char *nom,struct FileHandle *fichier,int octet,int saut);
int CheckASCII(char *name);
int CheckDir(char *name);

UBYTE Tampon[80],
      Tampon2[80];
int i,j;
char *Buffer;
BOOL WBench=FALSE;

/*
---------------------------------------------------------------------------
---------------------------------- MAIN -----------------------------------
---------------------------------------------------------------------------
*/

__stdargs __main(char *argv){

  struct AppMessage   *appmsg;
  struct WBArg        *argptr;
  struct Task         *MyTask;
  ULONG IconID = 1,
        UserData = 0;
  UBYTE Argument[MAXLEN],
        Argument2[MAXLEN];

  MyTask=SysBase->ThisTask; 
  SetTaskPri(MyTask,LOWPRI);

  if((((struct Process *)SysBase->ThisTask)->pr_CLI)){
    i=0;
    do{
      i++;
    }while(argv[i]&&(argv[i]!=' '));
    for(++i,j=0;argv[i];i++,j++)
      Argument[j]=argv[i];
    Argument[--j]='\0';
    if((!strcmp(Argument,"?")) || (strlen(Argument) == 0)){
      sprintf(Tampon,"\n\033[32mAnalyse version %s © Xavier Mertens - %s.\033[31m\n\n",VERSION,DATE);
      PRINT(Tampon);
      PRINT("Usage : Analyse <fichier> [LIST] [?] \n\n");
      sprintf(Tampon,"(%d types de fichier reconnus!)\n\n",MAX);
      PRINT(Tampon);
      CloseAll(WARN);
    }
    if(!strcmp(strupr(Argument),"LIST")){
      sprintf(Tampon,"Analyse \033[32mv%s\033[31m (%s) reconnait les fichiers suivants:\n",VERSION,DATE);
      PRINT(Tampon);
      for(i=0;i<MAX;i++){
        sprintf(Tampon," - %s\n",infos[i]);
        PRINT(Tampon);
      }
      CloseAll(NULL);                 
    }
    strcpy(Tampon2,Argument);
    Analyse(Argument);
    CloseAll(NULL);
  }

  WBench = TRUE;

  if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",OS_VERSION)) ||
     !(WorkbenchBase = (struct WorkbenchBase *)OpenLibrary("workbench.library",OS_VERSION)) ||
     !(msgport = CreateMsgPort()) ||
     !(appicon = AddAppIcon(IconID,UserData,NULL,msgport,NULL,&AnalyseAppIcon,NULL)))
    CloseAll(WARN);

/* Boucle principale */

  FOREVER{
    Wait(1<<msgport->mp_SigBit);
    while(appmsg = (struct AppMessage *)GetMsg(msgport)){
      if(appmsg->am_NumArgs == 0){
        ReplyMsg((struct Message *)appmsg);
        if(EasyRequest(NULL,&RequeteFin,NULL,"Analyse v2.55 © Xavier Mertens\n       (02 Février 93)\n55 types de fichiers reconnus!"))
          CloseAll(NULL);
      }
      else{
        argptr = appmsg->am_ArgList;
        for(i=0;i<appmsg->am_NumArgs;i++){
          NameFromLock(argptr->wa_Lock,Argument,MAXLEN);
          if(Argument[strlen(Argument)-1] == ':')
            sprintf(Argument2,"%s%s",Argument,argptr->wa_Name);
          else
            sprintf(Argument2,"%s/%s",Argument,argptr->wa_Name);
          strcpy(Tampon2,argptr->wa_Name);
          Analyse(Argument2);
          argptr++;
        }
        ReplyMsg((struct Message *)appmsg);
      }
    }
  }
}

BOOL Analyse(char *FileName){
  switch(CheckDir(FileName)){
    case 0:
      sprintf(Tampon,"%s est un répertoire",Tampon2);
      if(WBench)
        EasyRequest(NULL,&Requete,NULL,Tampon);
      else{
        PRINT(Tampon);
        PRINT("\n");
      }
      return(TRUE);
    case 2:
    case 3:
      strcpy(Tampon,"Une erreur s'est produite!");
      if(WBench)
        EasyRequest(NULL,&Requete,NULL,Tampon);
      else{
        PRINT(Tampon);
        PRINT("\n");
      }
      return(FALSE);
  }
  switch(CheckASCII(FileName)){
    case 0:
      sprintf(Tampon,"%s est un fichier ASCII",Tampon2);
      if(WBench)
        EasyRequest(NULL,&Requete,NULL,Tampon);
      else{
        PRINT(Tampon);
        PRINT("\n");
      }
      return(TRUE);
    case 1:
      sprintf(Tampon,"%s est une source C",Tampon2);
      if(WBench)
        EasyRequest(NULL,&Requete,NULL,Tampon);
      else{
        PRINT(Tampon);
        PRINT("\n");
      }
      return(TRUE);
    case 2:
    case 3:
      strcpy(Tampon,"Une erreur s'est produite!");
      if(WBench)
        EasyRequest(NULL,&Requete,NULL,Tampon);
      else{
        PRINT(Tampon);
        PRINT("\n");
      }
      return(FALSE);
  }
  if(!(FHandle=(struct FileHandle *)Open(FileName,MODE_OLDFILE)))
    return(FALSE);
  for(i=0;i<MAX;i++){
    if(ReadBytesInFile(fib.fib_FileName,FHandle,i,jump[i])){
      sprintf(Tampon,"%s est %s",Tampon2,infos[i]);
      if(WBench)
        EasyRequest(NULL,&Requete,NULL,Tampon);
      else{
        PRINT(Tampon);
        PRINT("\n");
      }
      Close((BPTR)FHandle);
      return(TRUE);
    }
  }
  sprintf(Tampon,"%s est d'origine inconnue!",Tampon2);
  if(WBench)
    EasyRequest(NULL,&Requete,NULL,Tampon);
  else{
    PRINT(Tampon);
    PRINT("\n");
  }
  Close((BPTR)FHandle);
  return(TRUE);
}

BOOL ReadBytesInFile(char *nom,struct FileHandle *fichier,int octet,int saut){
  if(!(Buffer=(char *)AllocMem(sizeof(strlen(chaine[octet])),MEMF_CLEAR|MEMF_FAST)))
    return(FALSE);
  Seek((BPTR)fichier,saut,OFFSET_BEGINNING);
  Read((BPTR)FHandle,Buffer,strlen(chaine[octet]));
  if((!(strcmp(Buffer,chaine[octet]))) || ((char *)Buffer[0]==chaine[octet])){
    FreeMem(Buffer,sizeof(strlen(chaine[octet])));
    return(TRUE);
  }
  else{
    FreeMem(Buffer,sizeof(strlen(chaine[octet])));
    Seek((BPTR)FHandle,0,OFFSET_BEGINNING);
    return(FALSE);
  }
}

/* 
  Code :
    0 : c'est un répertoire
    1 : ce n'est pas un répertoire
    2 : erreur de lecture
    3 : out of memory
*/

int CheckDir(char *name){
  struct FileLock      *lock;
  struct FileInfoBlock *FIBlock;

  if(lock=(struct FileLock *)Lock(name,ACCESS_READ)){
    if(FIBlock=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR|MEMF_FAST)){
      if(!(Examine((BPTR)lock,FIBlock))){
        UnLock((BPTR)lock);
        return(2);
      }
    }
    else{
      UnLock((BPTR)lock);
      return(3);
    }
    UnLock((BPTR)lock);
  }
  else
    return(2);
  if(TYPE>0){
    FreeMem(FIBlock,sizeof(struct FileInfoBlock));
    return(0);
  }
  FreeMem(FIBlock,sizeof(struct FileInfoBlock));
  return(1);
}

/*
  Code :
    0 : fichier ascii
    1 : source c
    2 : erreur de lecture
    3 : out of memory
    4 : ni l'un ni l'autre
*/

int CheckASCII(char *name){
  struct FileLock      *lock;
  struct FileInfoBlock *FIBlock;
  struct FileHandle    *FH;
  register int i,
               compteur;
  if(lock=(struct FileLock *)Lock(name,ACCESS_READ)){
    if(FIBlock=(struct FileInfoBlock *)AllocMem(sizeof(struct FileInfoBlock),MEMF_CLEAR|MEMF_FAST)){
      if(!(Examine((BPTR)lock,FIBlock))){
        UnLock((BPTR)lock);
        return(2);
      }
    }
    else{
      UnLock((BPTR)lock);
      return(3);
    }
    UnLock((BPTR)lock);
  }
  else
    return(2);
  if(!(Buffer=(char *)AllocMem(SIZE,MEMF_CLEAR|MEMF_FAST)))
    return(3);
  else 
    if(!(FH=(struct FileHandle *)Open(name,MODE_OLDFILE))){
      FreeMem(Buffer,SIZE);
      return(2);
    }
  else
    if(Read((BPTR)FH,Buffer,SIZE)!=SIZE){
      FreeMem(Buffer,SIZE);
      Close((BPTR)FH);
      return(2);
    }
    else
      Close((BPTR)FH);
  i=0;
  do{
    if((Buffer[i]=='\014')||
       (Buffer[i]=='\015')||
       (Buffer[i]=='\012')||
       ((Buffer[i]>=32)&&(Buffer[i]<=126)))
      compteur++;
      i++;
  }while(i<SIZE);

  if(((float)compteur/(float)SIZE)>=.9){ /* Ok,c'est bien un fichier ascii */
    i=0;compteur=0;
    do{
      if((Buffer[i]=='\043')|| /* # */
         (Buffer[i]=='\057')|| /* / */
         (Buffer[i]=='\052')|| /* * */
         (Buffer[i]=='\133')|| /* [ */
         (Buffer[i]=='\135')|| /* ] */
         (Buffer[i]=='\073')|| /* ; */
         (Buffer[i]=='\173')|| /* { */
         (Buffer[i]=='\175')|| /* } */
         (Buffer[i]=='\134')) /* \ */
        compteur++;
        i++;
    }while(i<SIZE);
    if(((float)compteur/(float)SIZE)>=.05){	/* C'est une source en c */
      FreeMem(Buffer,SIZE);
      FreeMem(FIBlock,sizeof(struct FileInfoBlock));
      return(1);
    }
    FreeMem(Buffer,SIZE);
    FreeMem(FIBlock,sizeof(struct FileInfoBlock));
    return(0);
  }
  FreeMem(Buffer,SIZE);
  FreeMem(FIBlock,sizeof(struct FileInfoBlock));
  return(4);
}

VOID CloseAll(int returncode){
  if(appicon)	RemoveAppIcon(appicon);
  if(msgport)	DeleteMsgPort(msgport);
  if(WorkbenchBase)	CloseLibrary((struct Library *)WorkbenchBase);
  if(IntuitionBase)	CloseLibrary((struct Library *)IntuitionBase);
  __exit(returncode);
}

/* Eof */
