{ JamDump                                }
{                                        }
{ Dumpt de header file van een JAM base  }


PROGRAM JamDump;

USES Ramon,Crt;

TYPE
	JAMBUFPTR		=	^JAMBUF;
	JAMBUF			=	array[0..$fffd] of char;
	FILENAMETYPE            =	string[200];
	ASCIIZ			=	array[1..255] of char;
	ARRAY4			=	array[1..4] of char;


TYPE
	JAMHDRINFO		=	RECORD
		Signature	:	ARRAY4;      {<J><A><M> followed by <NUL>}
		DateCreated	:	LONGINT;     {Creation date}
		ModCounter	:	LONGINT;     {Last processed counter}
		ActiveMsgs	:	LONGINT;     {Number of active (not deleted) messages}
		PasswordCRC	:	LONGINT;     {CRC-32 of password to access, or -1 if none}
		BaseMsgNum	:	LONGINT;     {Lowest message number in index file}
		Reserved	:	ARRAY[1..1000] of CHAR;
	END;{JAMHDRINFO}

TYPE     JAMHDR		= RECORD
		           Signature			:	ARRAY4;    {<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}

        JAMBINSUBFIELD	        = RECORD
		                   LoID	        :	WORD;      {Field ID, 0 - $ffff}
		                   HiID		:	WORD;      {Reserved for future use}
		                   DatLen	:	LONGINT;   {Length of buffer that follows}
                                  END;{JAMSUBFIELD}



VAR JamInput : FILE;
    JamText  : FILE;
    JHdr     : JAMHDRINFO;
    JMsg     : JAMHDR;
    JSub     : JAMBINSUBFIELD;
    Teken    : Char;
    Current  : Word;
    Teller   : Longint;
    BUffer   : String;
    Output   : Text;

BEGIN

 DirectVideo := False;
 Assign(Output,'');
 Rewrite(Output);

 Writeln('JAMDump v1.0');
 Writeln('(c) 1994 Martijn Dijksterhuis');
 Writeln;

 IF ParamCount = 0 THEN
  BEGIN
  Writeln(Output, 'Usage : JAMDUMP <basename>' );
  Exit;
  END;

 Assign( JamInput , ParamStr(1) + '.JHR' );
 {$I-} Reset(JamInput,1);{$I+}

 Assign( JamText , ParamStr(1) + '.JDT' );
 {$I-} Reset(JamText,1);{$I+}

 IF IoResult>1 THEN
  BEGIN
  Writeln(Output,'Error opening base file !');
  Exit;
  END;

 { Lees de header }
 {$I-} BlockRead( JamInput , JHDR , sizeof(JHDR)); {$I-}
 IF IoResult > 0 THEN
  BEGIN
  Writeln(Output,'Error Reading JAM base header !');
  Exit;
  END;

 { Schrijf de header op het scherm }
 Writeln(Output, 'Signature      : ' + JHDR.Signature[1] + JHDR.Signature[2] + JHDR.Signature[3] );
 Writeln(Output, 'Date Created   : ' + Long2HexString( JHDR.DateCreated ));
 Writeln(Output, 'Mod Counter    : ' + Longint2String( JHDR.ModCounter  ));
 Writeln(Output, 'Active messages: ' , JHDR.ActiveMsgs );
 Writeln(Output, 'Base msg number: ' + Longint2String( JHDR.BaseMsgNum ));
 Writeln(Output);

 Current := 1;
 WHILE (NOT Eof( JamInput )) DO
   WITH JMsg DO
     BEGIN

       Writeln( Output, 'Msg. ' , Current );
       Writeln( Output, RepChar( 79 , '-' ));
       Inc( Current );

       BlockRead( JamInput , Jmsg , sizeof( Jmsg ));

       Writeln(Output, 'Signature      : ' + Signature[1] + Signature[2] + Signature[3] );
       Writeln(Output, 'Revision       : ' + longint2string( Revision ));
       Writeln(Output, 'Reserved       : ' + longint2String( ReservedWord ));
       Writeln(Output, 'SubfieldLen    : ' + longint2String( SubfieldLen ));
       Writeln(Output, 'TimesRead      : ' + longint2String( TimesRead ));
       Writeln(Output, 'MsgId CRC      : ' + long2HexString( MsgIdCRC ));
       Writeln(Output, 'Reply CRC      : ' + long2HexString( ReplyCRC ));
       Writeln(Output, 'Reply To       : ' + longint2String( ReplyTo ));
       Writeln(Output, 'Reply 1St      : ' + longint2String( Reply1St ));
       Writeln(Output, 'Reply Next     : ' + longint2String( ReplyNext ));
       Writeln(Output, 'Date Written   : ' + long2HexString( DateWritten ));
       Writeln(Output, 'Date Received  : ' + long2HexString( DateReceived ));
       Writeln(Output, 'Date processed : ' + long2HexString( DateProcessed ));
       Writeln(Output, 'Msg number     : ' + longint2String( MsgNum ));
       Writeln(Output, 'Attribute      : ' + long2HexString( Attribute ));
       Writeln(Output, 'Attribute 2    : ' + longint2String( Attribute2 ));
       Writeln(Output, 'Text Offset    : ' + longint2String( TxtOffset ));
       Writeln(Output, 'Text length    : ' + longint2String( TxtLen ));
       Writeln(Output, 'Password CRC   : ' + long2HexString( PasswordCRC ));
       Writeln(Output, 'Cost           : ' + longint2String( Cost ));
       Writeln(Output);

       IF (Signature[1] <> 'J') OR (Signature[2] <> 'A') OR (Signature[3]<>'M') OR
          (Signature[4] <> #0) THEN
          BEGIN
           Writeln(Output,#7#7'Invalid JAM header !');
           Exit;
          END;

        WHILE SubFieldLen > 0 DO
        BEGIN

        { Lees het binaire header gedeelte , gevolgt door de buffer }
        {$I-} BlockRead( JamInput , JSub , sizeof( JAMBINSUBFIELD ));

        { Controlleer of SubfieldLen wel een geldige waarde heeft ! }
        { Als die echter troep bevat ging hij mooi door de buffer   }
        { heen, met als gevolg dat het programma vastliep !         }

        IF JSub.DatLen > 255 THEN
        BEGIN
         Writeln(Output, 'Damaged Subfield header found !');
         Exit;
        END;

        BlockRead( JamInput , Buffer[1] , JSub.datlen ); {$I+}
        Buffer[0] := char(JSub.DatLen);

        IF IoResult > 0 THEN
        BEGIN
        Writeln(Output, 'Damaged Subfield found !');
        Exit;
        END;

        Writeln(Output,'Type : ' + Word2String( JSub.LoId ) + ' ' + Buffer );
        SubFieldLen := SubFieldLen - JSub.DatLen - Sizeof( JSub );

        IF (SubFieldLen = 1) THEN
        BEGIN
             WriteLn ('SubFieldLen off by 1 error; correcting');
             Dec (SubFieldLen);
             blockRead (JamInput,Buffer,1);
        END;
      END;

       Seek( JamText  , TxtOffset );

       FOR Teller := 1 TO TxtLen DO
        BEGIN
        BlockRead( JamText , teken , 1 );
        IF Teken = #13 THEN Writeln(output)
         ELSE Write(Output, teken );
        END;

       Writeln(Output,'[EOT]');
       Writeln(Output);

   END;

END.
