home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / comm / term33so.lha / termIdentify.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  17KB  |  902 lines

  1. /*
  2. **    termIdentify.c
  3. **
  4. **    Heuristic file type identification routines (big words!).
  5. **
  6. **    Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* The file types we know. */
  13.  
  14. enum    {    TYPE_DIR,TYPE_FILE,
  15.         TYPE_ICON,
  16.         TYPE_TEXT,
  17.         TYPE_C,TYPE_H,
  18.         TYPE_ASM,TYPE_I,
  19.         TYPE_MOD,
  20.         TYPE_REXX,
  21.         TYPE_BASIC,
  22.         TYPE_AMIGAGUIDE,
  23.         TYPE_TEX,TYPE_METAFONT,TYPE_GF,TYPE_TEXFONT,TYPE_TEXDVI,TYPE_FLIB,
  24.         TYPE_OLDMANX,TYPE_NEWMANX,TYPE_OLDMANXLIB,TYPE_NEWMANXLIB,
  25.         TYPE_OBJECT,TYPE_LIB,
  26.         TYPE_EXECUTABLE,
  27.         TYPE_LIBRARY,TYPE_DEVICE,TYPE_FILESYS,TYPE_HANDLER,
  28.         TYPE_GIF,TYPE_DEGAS,TYPE_MACPAINT,TYPE_SUPERPAINT,TYPE_PICT,TYPE_SUNRASTER,TYPE_POSTSCRIPT,TYPE_PCX,TYPE_TIFF,TYPE_BMP,TYPE_JFIF,TYPE_ILBM,
  29.         TYPE_ANIM,TYPE_8SVX,TYPE_SMUS,TYPE_FTXT,TYPE_PREFS,TYPE_TERM,TYPE_AMIGAVISION,TYPE_IFF,
  30.         TYPE_IMPLODER,TYPE_POWERPACKER,TYPE_LHPAK,TYPE_LHASFX,
  31.         TYPE_ARC,TYPE_ARJ,TYPE_COMPRESSED,TYPE_CPIO,TYPE_UUENCODED,TYPE_FREEZE,TYPE_MACCOMPRESS,TYPE_COMPACT,TYPE_DIAMOND,TYPE_LHARC,TYPE_LHA,TYPE_ZOO,TYPE_ZIP,TYPE_STUFFIT,TYPE_PACKIT,TYPE_DMS,TYPE_WARP,TYPE_ZOOM,
  32.         TYPE_SPARCOBJECT,TYPE_SPARCEXECUTABLE,
  33.         TYPE_MSDOSEXECUTABLE,
  34.         TYPE_ATARIEXECUTABLE,
  35.         TYPE_MACEXECUTABLE,
  36.         TYPE_CDAF,TYPE_XPK,
  37.  
  38.         TYPE_COUNT
  39.     };
  40.  
  41.     /* File type/class mappings. */
  42.  
  43. STATIC WORD FileTypes[TYPE_COUNT] =
  44. {
  45.     FILETYPE_DIR,
  46.     FILETYPE_FILE,
  47.     FILETYPE_NONE,
  48.     FILETYPE_TEXT,
  49.     FILETYPE_TEXT,
  50.     FILETYPE_TEXT,
  51.     FILETYPE_TEXT,
  52.     FILETYPE_TEXT,
  53.     FILETYPE_TEXT,
  54.     FILETYPE_TEXT,
  55.     FILETYPE_TEXT,
  56.     FILETYPE_TEXT,
  57.     FILETYPE_TEXT,
  58.     FILETYPE_FILE,
  59.     FILETYPE_FILE,
  60.     FILETYPE_FILE,
  61.     FILETYPE_FILE,
  62.     FILETYPE_FILE,
  63.     FILETYPE_FILE,
  64.     FILETYPE_FILE,
  65.     FILETYPE_FILE,
  66.     FILETYPE_FILE,
  67.     FILETYPE_FILE,
  68.     FILETYPE_FILE,
  69.     FILETYPE_PROGRAM,
  70.     FILETYPE_FILE,
  71.     FILETYPE_FILE,
  72.     FILETYPE_FILE,
  73.     FILETYPE_FILE,
  74.     FILETYPE_PICTURE,
  75.     FILETYPE_PICTURE,
  76.     FILETYPE_PICTURE,
  77.     FILETYPE_PICTURE,
  78.     FILETYPE_PICTURE,
  79.     FILETYPE_PICTURE,
  80.     FILETYPE_PICTURE,
  81.     FILETYPE_PICTURE,
  82.     FILETYPE_PICTURE,
  83.     FILETYPE_PICTURE,
  84.     FILETYPE_PICTURE,
  85.     FILETYPE_PICTURE,
  86.     FILETYPE_PICTURE,
  87.     FILETYPE_SOUND,
  88.     FILETYPE_SOUND,
  89.     FILETYPE_TEXT,
  90.     FILETYPE_PREFS,
  91.     FILETYPE_PREFS,
  92.     FILETYPE_FILE,
  93.     FILETYPE_FILE,
  94.     FILETYPE_ARCHIVE,
  95.     FILETYPE_ARCHIVE,
  96.     FILETYPE_ARCHIVE,
  97.     FILETYPE_ARCHIVE,
  98.     FILETYPE_ARCHIVE,
  99.     FILETYPE_ARCHIVE,
  100.     FILETYPE_ARCHIVE,
  101.     FILETYPE_ARCHIVE,
  102.     FILETYPE_TEXT,
  103.     FILETYPE_ARCHIVE,
  104.     FILETYPE_ARCHIVE,
  105.     FILETYPE_ARCHIVE,
  106.     FILETYPE_ARCHIVE,
  107.     FILETYPE_ARCHIVE,
  108.     FILETYPE_ARCHIVE,
  109.     FILETYPE_ARCHIVE,
  110.     FILETYPE_ARCHIVE,
  111.     FILETYPE_ARCHIVE,
  112.     FILETYPE_ARCHIVE,
  113.     FILETYPE_ARCHIVE,
  114.     FILETYPE_ARCHIVE,
  115.     FILETYPE_ARCHIVE,
  116.     FILETYPE_PROGRAM,
  117.     FILETYPE_PROGRAM,
  118.     FILETYPE_PROGRAM,
  119.     FILETYPE_PROGRAM,
  120.     FILETYPE_PROGRAM,
  121.     FILETYPE_ARCHIVE,
  122.     FILETYPE_ARCHIVE
  123. };
  124.  
  125.     /* File class icon names. */
  126.  
  127. STATIC STRPTR ClassIconNames[FILETYPE_COUNT] =
  128. {
  129.     NULL,
  130.     "ENV:sys/def_drawer",
  131.     "ENV:sys/def_project",
  132.     "ENV:sys/def_text",
  133.     "ENV:sys/def_sound",
  134.     "ENV:sys/def_picture",
  135.     "ENV:sys/def_pref",
  136.     "ENV:sys/def_archive",
  137.     "ENV:sys/def_tool",
  138. };
  139.  
  140.     /* A structure containing both a file name suffix and the
  141.      * approriate file type.
  142.      */
  143.  
  144. struct Suffix
  145. {
  146.     UBYTE    *Name;
  147.     UBYTE     Type;
  148. };
  149.  
  150.     /* A table of valid ASCII characters (7 bits). */
  151.  
  152. STATIC BYTE ID_ValidTab[256] =
  153. {
  154.     0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,
  155.     0,1,0,1,0,0,0,0,0,0,0,1,0,0,0,0,
  156.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  157.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  158.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  159.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  160.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  161.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  162.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  163.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  164.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  165.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  166.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  167.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  168.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  169.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  170. };
  171.  
  172.     /* A table of clearly invalid ASCII characters (8 bits). */
  173.  
  174. STATIC BYTE ID_InvalidTab[256] =
  175. {
  176.     1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,
  177.     1,0,1,0,1,1,1,1,1,1,1,0,1,1,1,1,
  178.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  179.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  180.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  181.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  182.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  183.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  184.     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
  185.     1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,
  186.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  187.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  188.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  189.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  190.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  191.     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  192. };
  193.  
  194.     /* Some file name suffixes for text files and the approriate
  195.      * file types.
  196.      */
  197.  
  198. STATIC struct Suffix TextSuffix[] =
  199. {
  200.     ".C",        TYPE_C,
  201.     ".CPP",        TYPE_C,
  202.     ".CXX",        TYPE_C,
  203.     ".C++",        TYPE_C,
  204.     ".CC",        TYPE_C,
  205.     ".H",        TYPE_H,
  206.     ".ASM",        TYPE_ASM,
  207.     ".A",        TYPE_ASM,
  208.     ".S",        TYPE_ASM,
  209.     ".I",        TYPE_I,
  210.     ".BAS",        TYPE_BASIC,
  211.     ".GFA",        TYPE_BASIC,
  212.     ".REXX",    TYPE_REXX,
  213.     ".CED",        TYPE_REXX,
  214.     ".TTX",        TYPE_REXX,
  215.     ".VLT",        TYPE_REXX,
  216.     ".CPR",        TYPE_REXX,
  217.     ".TxEd",    TYPE_REXX,
  218.     ".ADPro",    TYPE_REXX,
  219.     ".TEX",        TYPE_TEX,
  220.     ".STY",        TYPE_TEX,
  221.     ".MF",        TYPE_METAFONT,
  222.     ".MOD",        TYPE_MOD,
  223.     ".DEF",        TYPE_MOD,
  224.     ".PS",        TYPE_POSTSCRIPT,
  225.     ".GUIDE",    TYPE_AMIGAGUIDE,
  226.     ".UUE",        TYPE_UUENCODED
  227. };
  228.  
  229.     /* Some more file name suffixes for executable files and the
  230.      * approriate file types.
  231.      */
  232.  
  233. STATIC struct Suffix ExecutableSuffix[] =
  234. {
  235.     ".device",    TYPE_DEVICE,
  236.     ".library",    TYPE_LIBRARY,
  237.     "FileSystem",    TYPE_FILESYS,
  238.     "Handler",    TYPE_HANDLER
  239. };
  240.  
  241.     /* Miscellaneous magic cookies. */
  242.  
  243. STATIC STRPTR MagicCookies[] =
  244. {
  245.     "P1",
  246.     "P2",
  247.     "P3",
  248.     "P4",
  249.     "P5",
  250.     "P6",
  251.     "begin",
  252.     "xbtoa"
  253. };
  254.  
  255.     /* LongCompare(UBYTE *Buffer,ULONG Value):
  256.      *
  257.      *    Compare space in memory with a longword value.
  258.      */
  259.  
  260. STATIC BYTE __regargs
  261. LongCompare(UBYTE *Buffer,ULONG Value)
  262. {
  263.     UBYTE *OtherBuffer = (UBYTE *)&Value,i;
  264.  
  265.     for(i = 0 ; i < 4 ; i++)
  266.     {
  267.         if(OtherBuffer[i] != Buffer[i])
  268.             return(FALSE);
  269.     }
  270.  
  271.     return(TRUE);
  272. }
  273.  
  274.     /* GetFileType(STRPTR Name,BYTE AttachComment):
  275.      *
  276.      *    Simple routine to identify a file type by looking at
  277.      *    its first 400 bytes. If successful a comment is
  278.      *    attached to the file describing the file type.
  279.      */
  280.  
  281. WORD __regargs
  282. GetFileType(STRPTR Name,BYTE AttachComment)
  283. {
  284.     ULONG    *Buffer;
  285.     UBYTE     Type        = TYPE_FILE,
  286.         *TypeName    = NULL;
  287.     WORD     i,
  288.          Len = strlen(Name);
  289.     UBYTE     IFFType[5];
  290.  
  291.         /* Allocate a buffer for the first 410 bytes of the
  292.          * file.
  293.          */
  294.  
  295.     if(Buffer = (ULONG *)AllocVec(410,MEMF_ANY | MEMF_CLEAR))
  296.     {
  297.         BPTR File,Size;
  298.  
  299.             /* Open the file. */
  300.  
  301.         if(File = Open(Name,MODE_OLDFILE))
  302.         {
  303.                 /* Read the first 410 bytes. */
  304.  
  305.             if((Size = Read(File,Buffer,410)) >= sizeof(ULONG))
  306.             {
  307.                 UBYTE    *CharBuffer = (UBYTE *)Buffer;
  308.                 WORD     Count = 0;
  309.  
  310.                     /* See if it's an ASCII file. */
  311.  
  312.                 for(i = 0 ; i < Size ; i++)
  313.                 {
  314.                     if(ID_ValidTab[CharBuffer[i]])
  315.                         Count++;
  316.                     else
  317.                     {
  318.                         if(ID_InvalidTab[CharBuffer[i]])
  319.                         {
  320.                             Count = 0;
  321.  
  322.                             break;
  323.                         }
  324.                     }
  325.                 }
  326.  
  327.                     /* If more than 75% of the
  328.                      * characters in the first
  329.                      * 400 bytes are legal
  330.                      * ASCII characters this
  331.                      * file is supposed to be
  332.                      * a text file.
  333.                      */
  334.  
  335.                 if(Count > 3 * (Size / 4))
  336.                     Type = TYPE_TEXT;
  337.  
  338.                     /* Examine the first longword. */
  339.  
  340.                 if(Type == TYPE_FILE)
  341.                 {
  342.                     switch(Buffer[0])
  343.                     {
  344.                         case 0x58504B46:
  345.  
  346.                             Type = TYPE_XPK;
  347.                             break;
  348.  
  349.                         case 0x000003E7:
  350.  
  351.                             Type = TYPE_OBJECT;
  352.                             break;
  353.  
  354.                         case 0x000003F3:
  355.  
  356.                             if(Buffer[10] == 'LSFX')
  357.                                 Type = TYPE_LHPAK;
  358.                             else
  359.                             {
  360.                                 if(Buffer[11] == 'SFX!')
  361.                                     Type = TYPE_LHASFX;
  362.                                 else
  363.                                     Type = TYPE_EXECUTABLE;
  364.                             }
  365.  
  366.                             break;
  367.  
  368.                         case 0x000003FA:
  369.  
  370.                             Type = TYPE_LIB;
  371.                             break;
  372.  
  373.                         case 0xF7593647:
  374.  
  375.                             Type = TYPE_TEXFONT;
  376.                             break;
  377.  
  378.                         case 0xF7020183:
  379.  
  380.                             Type = TYPE_TEXDVI;
  381.                             break;
  382.  
  383.                         case 0xF7832020:
  384.  
  385.                             Type = TYPE_GF;
  386.                             break;
  387.  
  388.                         case 0x504B0304:
  389.  
  390.                             Type = TYPE_ZIP;
  391.                             break;
  392.  
  393.                         case 0x01030107:
  394.  
  395.                             Type = TYPE_SPARCOBJECT;
  396.                             break;
  397.  
  398.                         case 0x8103010B:
  399.  
  400.                             Type = TYPE_SPARCEXECUTABLE;
  401.                             break;
  402.  
  403.                         case 0x59A66A95:
  404.  
  405.                             Type = TYPE_SUNRASTER;
  406.                             break;
  407.  
  408.                         case 0x1F9D902A:
  409.  
  410.                             Type = TYPE_COMPRESSED;
  411.                             break;
  412.  
  413.                         case 0x30373037:
  414.  
  415.                             Type = TYPE_CPIO;
  416.                             break;
  417.  
  418.                         case 'FLIB':
  419.  
  420.                             Type = TYPE_FLIB;
  421.                             break;
  422.  
  423.                         case 'FORM':
  424.  
  425.                             switch(Buffer[2])
  426.                             {
  427.                                 case 'ILBM':
  428.  
  429.                                     Type = TYPE_ILBM;
  430.                                     break;
  431.  
  432.                                 case 'ANIM':
  433.  
  434.                                     Type = TYPE_ANIM;
  435.                                     break;
  436.  
  437.                                 case '8SVX':
  438.  
  439.                                     Type = TYPE_8SVX;
  440.                                     break;
  441.  
  442.                                 case 'SMUS':
  443.  
  444.                                     Type = TYPE_SMUS;
  445.                                     break;
  446.  
  447.                                 case 'FTXT':
  448.  
  449.                                     Type = TYPE_FTXT;
  450.                                     break;
  451.  
  452.                                 case 'PREF':
  453.  
  454.                                     Type = TYPE_PREFS;
  455.                                     break;
  456.  
  457.                                 case 'TERM':
  458.  
  459.                                     Type = TYPE_TERM;
  460.                                     break;
  461.  
  462.                                 case 'AVCF':
  463.  
  464.                                     Type = TYPE_AMIGAVISION;
  465.                                     break;
  466.  
  467.                                 case 'CDAF':
  468.  
  469.                                     Type = TYPE_CDAF;
  470.                                     break;
  471.  
  472.                                 default:
  473.  
  474.                                     Type = TYPE_IFF;
  475.  
  476.                                     CopyMem(&Buffer[2],IFFType,4);
  477.  
  478.                                     IFFType[4] = 0;
  479.  
  480.                                     break;
  481.                             }
  482.  
  483.                             break;
  484.  
  485.                         case 'IMP!':
  486.  
  487.                             Type = TYPE_IMPLODER;
  488.                             break;
  489.  
  490.                         case 'PP20':
  491.  
  492.                             Type = TYPE_POWERPACKER;
  493.                             break;
  494.  
  495.                         case 'DMS!':
  496.  
  497.                             Type = TYPE_DMS;
  498.                             break;
  499.  
  500.                         case 'Warp':
  501.  
  502.                             Type = TYPE_WARP;
  503.                             break;
  504.  
  505.                         case 'ZOM5':
  506.                         case 'ZOOM':
  507.  
  508.                             Type = TYPE_ZOOM;
  509.                             break;
  510.  
  511.                         case 'ZOO ':
  512.  
  513.                             Type = TYPE_ZOO;
  514.                             break;
  515.  
  516.                         case 'GIF8':
  517.  
  518.                             Type = TYPE_GIF;
  519.                             break;
  520.                     }
  521.                 }
  522.  
  523.                     /* Now for oddly placed magic cookies... */
  524.  
  525.                 if(Type == TYPE_FILE)
  526.                 {
  527.                         /* Dumb check for PCX (awful header -- just
  528.                          * a single byte indicates that the file
  529.                          * is supposed to be a PCX file! Those
  530.                          * PC guys just don't have any
  531.                          * decent software culture!).
  532.                          */
  533.  
  534.                     if(CharBuffer[0] == 0x0A)
  535.                         Type = TYPE_PCX;
  536.  
  537.                         /* Yet another awful file format... */
  538.  
  539.                     if(CharBuffer[0] == 'B' && CharBuffer[1] == 'M')
  540.                         Type = TYPE_BMP;
  541.  
  542.                         /* Check for JFIF... */
  543.  
  544.                     if(LongCompare(&CharBuffer[6],'JFIF'))
  545.                         Type = TYPE_JFIF;
  546.  
  547.                         /* Check for `freeze' output file. */
  548.  
  549.                     if(CharBuffer[0] == (UBYTE)'\037' && CharBuffer[1] >= (UBYTE)'\236')
  550.                         Type = TYPE_FREEZE;
  551.                 }
  552.  
  553.                     /* Check for Macintosh data (note:
  554.                      * this code assumes that the Mac
  555.                      * binary header is still present,
  556.                      * so if you are dealing with stripped
  557.                      * binary files, don't expect the
  558.                      * following code to work!).
  559.                      */
  560.  
  561.                 if(Type == TYPE_FILE)
  562.                 {
  563.                     UBYTE *ByteBuffer = &((UBYTE *)Buffer)[65];
  564.  
  565.                         /* Check for MacPaint... */
  566.  
  567.                     if(LongCompare(ByteBuffer,'PNTG'))
  568.                         Type = TYPE_MACPAINT;
  569.  
  570.                         /* Check for SuperPaint... */
  571.  
  572.                     if(LongCompare(ByteBuffer,'SPTG'))
  573.                         Type = TYPE_SUPERPAINT;
  574.  
  575.                         /* Check for PICT... */
  576.  
  577.                     if(LongCompare(ByteBuffer,'PICT'))
  578.                         Type = TYPE_PICT;
  579.  
  580.                         /* Check for executable... */
  581.  
  582.                     if(LongCompare(ByteBuffer,'APPL') || LongCompare(ByteBuffer,'PRES') || LongCompare(ByteBuffer,'FDOC') || LongCompare(ByteBuffer,'cdev') || LongCompare(ByteBuffer,'INIT'))
  583.                         Type = TYPE_MACEXECUTABLE;
  584.  
  585.                         /* Check for StuffIt archive... */
  586.  
  587.                     if(LongCompare(ByteBuffer,'SIT!') || LongCompare(ByteBuffer,'SIT2'))
  588.                         Type = TYPE_STUFFIT;
  589.  
  590.                         /* Check for PackIt archive... */
  591.  
  592.                     if(LongCompare(ByteBuffer,'PIT '))
  593.                         Type = TYPE_PACKIT;
  594.  
  595.                         /* Check for self-extracting Compact archive. */
  596.  
  597.                     if(LongCompare(ByteBuffer,'APPL') && LongCompare(&ByteBuffer[4],'EXTR'))
  598.                         Type = TYPE_COMPACT;
  599.  
  600.                         /* Check for MacCompress archive. */
  601.  
  602.                     if(LongCompare(ByteBuffer,'ZIVM'))
  603.                         Type = TYPE_MACCOMPRESS;
  604.  
  605.                         /* Check for LhArc archive with MacBinary header. */
  606.  
  607.                     if(LongCompare(ByteBuffer,'LARC'))
  608.                         Type = TYPE_LHARC;
  609.  
  610.                         /* Check for Compact archive. */
  611.  
  612.                     if(LongCompare(ByteBuffer,'PACT'))
  613.                         Type = TYPE_COMPACT;
  614.  
  615.                         /* Check for Diamond archive. */
  616.  
  617.                     if(LongCompare(ByteBuffer,'Pack'))
  618.                         Type = TYPE_DIAMOND;
  619.                 }
  620.  
  621.                     /* Still no match? Have another try... */
  622.  
  623.                 if(Type == TYPE_FILE)
  624.                 {
  625.                     if((Buffer[0] & 0x0000FFFF) == 0x00002D6C && (Buffer[1] & 0xFF00FF00) == 0x68002D00)
  626.                     {
  627.                         if(CharBuffer[5] == '5')
  628.                             Type = TYPE_LHA;
  629.                         else
  630.                             Type = TYPE_LHARC;
  631.                     }
  632.                     else
  633.                     {
  634.                         switch(Buffer[0] & 0xFFFF0000)
  635.                         {
  636.                             case 0x4D4D0000:
  637.                             case 0x49490000:
  638.  
  639.                                 Type = TYPE_TIFF;
  640.                                 break;
  641.  
  642.                             case 0x1A080000:
  643.  
  644.                                 Type = TYPE_ARC;
  645.                                 break;
  646.  
  647.                             case 0x60EA0000:
  648.  
  649.                                 Type = TYPE_ARJ;
  650.                                 break;
  651.  
  652.                             case 0x434A0000:
  653.  
  654.                                 Type = TYPE_NEWMANX;
  655.                                 break;
  656.  
  657.                             case 0x414A0000:
  658.  
  659.                                 Type = TYPE_OLDMANX;
  660.                                 break;
  661.  
  662.                             case 0x636A0000:
  663.  
  664.                                 Type = TYPE_NEWMANXLIB;
  665.                                 break;
  666.  
  667.                             case 0x616A0000:
  668.  
  669.                                 Type = TYPE_OLDMANXLIB;
  670.                                 break;
  671.  
  672.                             case 0xF5000000:
  673.  
  674.                                 Type = TYPE_BASIC;
  675.                                 break;
  676.  
  677.                             case 0xE3100000:
  678.  
  679.                                 Type = TYPE_ICON;
  680.                                 break;
  681.  
  682.                             case 0x4D5A0000:
  683.  
  684.                                 Type = TYPE_MSDOSEXECUTABLE;
  685.                                 break;
  686.  
  687.                             case 0x601A0000:
  688.  
  689.                                 Type = TYPE_ATARIEXECUTABLE;
  690.                                 break;
  691.  
  692.                             case 0x80000000:
  693.  
  694.                                 Type = TYPE_DEGAS;
  695.                                 break;
  696.                         }
  697.                     }
  698.                 }
  699.  
  700.                     /* Take a look at the file name
  701.                      * suffixes.
  702.                      */
  703.  
  704.                 switch(Type)
  705.                 {
  706.                     case TYPE_TEXT:
  707.  
  708.                         for(i = 0 ; i < sizeof(TextSuffix) / sizeof(struct Suffix) ; i++)
  709.                         {
  710.                             Size = strlen(TextSuffix[i] . Name);
  711.  
  712.                             if(Len >= Size)
  713.                             {
  714.                                 if(!Stricmp(&Name[Len - Size],TextSuffix[i] . Name))
  715.                                 {
  716.                                     Type = TextSuffix[i] . Type;
  717.                                     break;
  718.                                 }
  719.                             }
  720.                         }
  721.  
  722.                             /* Is it still a text file? */
  723.  
  724.                         if(Type == TYPE_TEXT)
  725.                         {
  726.                                 /* Check for magic cookies. */
  727.  
  728.                             for(i = 0 ; i < sizeof(MagicCookies) / sizeof(STRPTR) ; i++)
  729.                             {
  730.                                 if(!memcmp(CharBuffer,MagicCookies[i],strlen(MagicCookies[i])))
  731.                                 {
  732.                                     TypeName = LocaleString(MSG_IDENTIFY_COOKIE_0 + i);
  733.  
  734.                                     break;
  735.                                 }
  736.                             }
  737.                         }
  738.  
  739.                         break;
  740.  
  741.                     case TYPE_EXECUTABLE:
  742.  
  743.                         for(i = 0 ; i < sizeof(ExecutableSuffix) / sizeof(struct Suffix) ; i++)
  744.                         {
  745.                             Size = strlen(ExecutableSuffix[i] . Name);
  746.  
  747.                             if(Len >= Size)
  748.                             {
  749.                                 if(!Stricmp(&Name[Len - Size],ExecutableSuffix[i] . Name))
  750.                                 {
  751.                                     Type = ExecutableSuffix[i] . Type;
  752.                                     break;
  753.                                 }
  754.                             }
  755.                         }
  756.  
  757.                         break;
  758.  
  759.                     case TYPE_OBJECT:
  760.  
  761.                         if(Len >= 4)
  762.                         {
  763.                             if(!Stricmp(&Name[Len - 4],".LIB"))
  764.                                 Type = TYPE_LIB;
  765.                         }
  766.  
  767.                         break;
  768.                 }
  769.             }
  770.  
  771.             Close(File);
  772.         }
  773.  
  774.         FreeVec(Buffer);
  775.     }
  776.  
  777.     if(AttachComment)
  778.     {
  779.         if(Type > TYPE_FILE || TypeName)
  780.         {
  781.             if(Type == TYPE_IFF)
  782.             {
  783.                 UBYTE NameBuffer[40];
  784.     
  785.                 SPrintf(NameBuffer,LocaleString(MSG_IDENTIFY_IFF_FILE),IFFType);
  786.     
  787.                 SetComment(Name,NameBuffer);
  788.             }
  789.             else
  790.             {
  791.                 if(TypeName)
  792.                     SetComment(Name,TypeName);
  793.                 else
  794.                     SetComment(Name,LocaleString(MSG_IDENTIFY_FILETYPE_0 + Type - TYPE_ICON));
  795.             }
  796.         }
  797.     
  798.             /* Is it an executable file? */
  799.     
  800.         if(Type != TYPE_EXECUTABLE && Type != TYPE_LHPAK && Type != TYPE_LHASFX)
  801.         {
  802.             BPTR FileLock;
  803.     
  804.                 /* Get a lock on it. */
  805.     
  806.             if(FileLock = Lock(Name,ACCESS_WRITE))
  807.             {
  808.                 struct FileInfoBlock *FileInfo;
  809.     
  810.                     /* Allocate fileinfo data. */
  811.     
  812.                 if(FileInfo = (struct FileInfoBlock *)AllocDosObjectTags(DOS_FIB,TAG_DONE))
  813.                 {
  814.                         /* Take a closer look at it... */
  815.     
  816.                     if(Examine(FileLock,FileInfo))
  817.                     {
  818.                             /* Release the lock. */
  819.     
  820.                         UnLock(FileLock);
  821.     
  822.                             /* Really drop it. */
  823.     
  824.                         FileLock = NULL;
  825.     
  826.                             /* Update protection bits. */
  827.     
  828.                         SetProtection(Name,FileInfo -> fib_Protection | FIBF_EXECUTE);
  829.                     }
  830.     
  831.                         /* Free fileinfo data. */
  832.     
  833.                     FreeDosObject(DOS_FIB,FileInfo);
  834.                 }
  835.             }
  836.     
  837.                 /* Release the lock if still allocated. */
  838.     
  839.             if(FileLock)
  840.                 UnLock(FileLock);
  841.         }
  842.     }
  843.  
  844.     return(Type);
  845. }
  846.  
  847.     /* Identify(STRPTR Name):
  848.      *
  849.      *    Try to identify the type of a file,
  850.      *    attach an icon if necessary.
  851.      */
  852.  
  853. VOID __regargs
  854. Identify(STRPTR Name)
  855. {
  856.     WORD Type = GetFileType(Name,TRUE);
  857.  
  858.     if(Config -> MiscConfig -> CreateIcons)
  859.         AddIcon(Name,FileTypes[Type],FALSE);
  860. }
  861.  
  862.     /* AddIcon(STRPTR Name,WORD Type,BYTE Override):
  863.      *
  864.      *    Add an icon to a file.
  865.      */
  866.  
  867. VOID __regargs
  868. AddIcon(STRPTR Name,WORD Index,BYTE Override)
  869. {
  870.     if(ClassIconNames[Index] && IconBase)
  871.     {
  872.         struct DiskObject *Icon;
  873.  
  874.         if(!Override)
  875.         {
  876.             if(Icon = GetDiskObject(Name))
  877.             {
  878.                 FreeDiskObject(Icon);
  879.  
  880.                 return;
  881.             }
  882.         }
  883.  
  884.         if(!(Icon = GetDiskObject(ClassIconNames[Index])))
  885.         {
  886.             if(Index == FILETYPE_PROGRAM)
  887.                 Icon = GetDefDiskObject(WBTOOL);
  888.             else
  889.                 Icon = GetDefDiskObject(WBPROJECT);
  890.         }
  891.  
  892.         if(Icon)
  893.         {
  894.             Icon -> do_CurrentX = Icon -> do_CurrentY = NO_ICON_POSITION;
  895.  
  896.             PutDiskObject(Name,Icon);
  897.  
  898.             FreeDiskObject(Icon);
  899.         }
  900.     }
  901. }
  902.