PROGRAM JamDump3;

{ this program dumps the JAM message base .JDX file, so I can check it }
{ for possible errors. You can type anything on the commmandline, like }
{ * or *.JHR or TITLE14 or something like that.                        }

USES Dos,
     Ramon,
     Crt;

{
 structure of the .JDX file:

 Records met daarin:

      UserCRC   : LONGINT;
      HdrOffset : LONGINT;

 Waarbij de offset in de index file het bericht nummer is, of zoiets.
}

TYPE IndexRecord = RECORD
                         UserCRC   : LONGINT;
                         HdrOffset : LONGINT;
                   END;

     JAMHDR = RECORD
                    Signature     : ARRAY[1..4] OF CHAR;    {<J><A><M> followed by <NUL>}
                    Revision      : WORD;      {CurrentRevLev}
                    ReservedWord  : WORD;      {Reserved for future use}
                    SubfieldLen   : LONGINT;   {Length of subfields}
                    TimesRead     : LONGINT;   {Number of times message read}
                    MsgIdCRC      : LONGINT;   {CRC-32 of MSGID line}
                    ReplyCRC      : LONGINT;   {CRC-32 of REPLY line}
                    ReplyTo       : LONGINT;   {This msg is a reply to..}
                    Reply1st      : LONGINT;   {First reply to this msg}
                    ReplyNext     : LONGINT;   {Next msg in reply chain}
                    DateWritten   : LONGINT;   {When msg was written}
                    DateReceived  : LONGINT;   {When msg was received/read}
                    DateProcessed : LONGINT;   {When msg was processed by packer}
                    MsgNum        : LONGINT;   {Message number (1-based)}
                    Attribute     : LONGINT;   {Msg attribute, see "Status bits"}
                    Attribute2    : LONGINT;   {Reserved for future use}
                    TxtOffset     : LONGINT;   {Offset of text in text file}
                    TxtLen        : LONGINT;   {Length of message text}
                    PasswordCRC   : LONGINT;   {CRC-32 of password to access msg}
                    Cost          : LONGINT;   {Cost of message}
              END; {JAMHDR}

{---------------------------------------------------------------------------}
{ Process                                                                   }
{                                                                           }
PROCEDURE Process (Filename : STRING);

VAR IdxFile   : FILE;
    JhrFile   : FILE;
    IORes     : BYTE;
    BytesRead : WORD;
    FP        : LONGINT;                { filepos }
    IdxRec    : IndexRecord;
    MsgNr     : WORD;

LABEL Einde;

BEGIN
     WriteLn (Output,'Processing ',Filename);

     Assign (IdxFile,Filename);
     {$I-} Reset (IdxFile,1); {$I+} IORes:=IOResult;
     IF (IORes <> 0) THEN
     BEGIN
          WriteLn (' ! Cannot open file (error ',IORes,')');
          Exit;
     END;

     MsgNr:=0;

     Seek (IdxFile,0);
     WHILE (FilePos (IdxFile) < FileSize (IdxFile)) DO
     BEGIN
          FP:=FilePos (IdxFile);

          {$I-} BlockRead (IdxFile,IdxRec,SizeOf (IndexRecord),BytesRead); {$I+} IORes:=IOResult;
          IF (IORes <> 0) THEN
          BEGIN
               WriteLn (' ! Error reading index record (error ',IORes,')');
               GOTO Einde;
          END;

          Inc (MsgNr);
          WriteLn (Output,'MsgNr ',MsgNr:5,
                          '  | FilePos ',FP:9,'  | UserCRC ',IdxRec.UserCRC:9,'  | HdrOffset ',IdxRec.HdrOffset);
     END; { while }

     (*
     IF (BytesRead <> 1024) THEN
     BEGIN
          WRiteLn (' ! Not enough data for the info header');
          GOTO Einde;
     END;

     { check the signature }
     IF (HdrInfo.Signature[1] <> 'J') OR
        (HdrInfo.Signature[2] <> 'A') OR
        (HdrInfo.Signature[3] <> 'M') OR
        (HdrInfo.Signature[4] <> #0) THEN
     BEGIN
          WriteLn (' ! Info record does not have a valid JAM signature');
          GOTO Einde;
     END;

     MsgNr:=0;
     WHILE (FilePos (InFile) < FileSize (InFile)) DO
     BEGIN
          MsgNr:=MsgNr+1;

          {$I-} BlockRead (InFile,Hdr,SizeOf (JAMHDR),BytesRead); {$I+} IORes:=IOResult;
          IF (IORes <> 0) THEN
          BEGIN
               WriteLn (' ! Error reading message header for message ',MsgNr,' (error ',IORes,')');
               GOTO Einde;
          END;

          IF (BytesRead <> SizeOf (JAMHDR)) THEN
          BEGIN
               WriteLn (' ! Not enough data for a complete message header for message ',MsgNr);
               GOTO Einde;
          END;

          { check the signature }
          IF (Hdr.Signature[1] <> 'J') OR
             (Hdr.Signature[2] <> 'A') OR
             (Hdr.Signature[3] <> 'M') OR
             (Hdr.Signature[4] <> #0) THEN
          BEGIN
               WriteLn (' ! Header for message ',MsgNr,' does not have a valid JAM signature');
               GOTO Einde;
          END;

          { check out the subfields }
          SubLeft:=Hdr.SubFieldLen;
          IF (SubLeft = 0) THEN
             Continue; { no subfields for this message }

          {WriteLn ('SubLength = ',SubLeft);}

          SubNr:=0;
          WHILE (SubLeft > SizeOf (JAMBINSUBFIELD)) DO
          BEGIN
               SubNr:=SubNr+1;

               {$I-} BlockRead (InFile,SubField,SizeOf (JAMBINSUBFIELD),BytesRead); {$I+} IORes:=IOResult;
               IF (IORes <> 0) THEN
               BEGIN
                    WriteLn (' ! Error reading subfield ',SubNr,' for message ',MsgNr,' (error ',IORes,')');
                    GOTO Einde;
               END;

               IF (BytesRead <> SizeOf (JAMBINSUBFIELD)) THEN
               BEGIN
                    WriteLn (' ! Not enough data for subfield ',SubNr,' header of message ',MsgNr);
                    GOTO Einde;
               END;

               {WriteLn ('   SubFieldNr: ',SubNr,'  SubFieldType:',SubField.LoID,'  SubLeft: ',SubLeft);}

               IF NOT (((SubField.LoID >= 0) AND (SubField.LoID <= 9)) OR
                       ((SubField.LoID >= 2000) AND (SubField.LoID <= 2003)))THEN
               BEGIN
                    WriteLn (' ! Unknown subfield LoID: ',SubField.LoID);
                    WriteLn ('   - HiID = ',SubField.HiID);
                    WriteLn ('   - DatLen = ',SubField.DatLen);
               END;

               IF (SubField.DatLen > 255) THEN
               BEGIN
                    WriteLn (' ! SubField ',SubNr,' of message ',MsgNr,' contains too much data for WaterGate');
                    WriteLn ('   - LoID = ',SubField.LoID,' (should be 0000-0009,2000-2003)');
                    WriteLn ('   - HiID = ',SubField.HiID,' (should be 0)');
                    WriteLn ('   - DatLen = ',SubField.DatLen,' (should be 255 max.)');

                    {$I-} BlockRead (InFile,Buffer,50,BytesRead); {$I+} IORes:=IOResult;
                    IF (IORes <> 0) THEN
                    BEGIN
                         WriteLn ('   - Error reading data (error ',IORes,')');
                         GOTO Einde;
                    END;

                    IF (BytesRead <> 50) THEN
                    BEGIN
                         WriteLn ('   - Can''t read first 50 bytes! (',BytesRead,' only)');
                         GOTO Einde;
                    END;

                    Buffer[0]:=Char (50);
                    WriteLn ('   - Data: "',Buffer,'"...');

                    GOTO Einde;
               END;

               { read the subfield data }
               BlockRead (InFile,Buffer[0],SubField.DatLen);

               SubLeft:=SubLeft-SizeOf (JAMBINSUBFIELD)-SubField.DatLen;
          END; { while }

          IF (SubLeft > 0) THEN
          BEGIN
               WriteLn ('   SubFields length miscount in message ',MsgNr,': ',SubLeft,' byte(s) left!');
               Seek (InFile,FilePos (InFile)+SubLeft); { compensate }
          END;
     END;
     *)

     WriteLn (' û ',MsgNr,' messages checked');

Einde:
     Close (IdxFile);
END;


{---------------------------------------------------------------------------}
{ main                                                                      }
{                                                                           }

VAR Arg    : STRING;
    Search : SearchRec;
    Dir    : DirStr;
    Name   : NameStr;
    Ext    : ExtStr;

BEGIN
     DirectVideo:=FALSE;
     Assign (Output,'');
     ReWrite (Output);

     WriteLn ('JamDump3 - Quick and dirty JAM .JDX file dumper - version 1.00');
     WriteLn ('(c) Copyright 1996 Waterline Software Development V.O.F.');
     WriteLn ('Written by Ramon van der Winkel');
     WriteLn;

     IF (ParamCount = 0) THEN
        Arg:='*.JDX'
     ELSE
         Arg:=ParamStr (1);

     IF (Pos ('.',Arg) = 0) THEN
        Arg:=Arg+'.JDX';

     Arg:=UpCaseString (Arg);

     WriteLn ('Searching '+Arg);
     WriteLn;

     FSplit (FExpand (Arg),Dir,Name,Ext);

     FindFirst (Arg,$3F,Search);
     WHILE (DosError = 0) DO
     BEGIN
          Process (Dir+Search.Name);

          WriteLn ('-- escape or other key for next file --');
          IF (Ramon.ReadKey = kEsc) THEN
             Break;

          FindNext (Search);
     END; { while }

     WriteLn ('<no more files>');
END.

