UNIT Pkt2000;

{$i platform.inc}

{ this unit contains a lot of the code related to the PKT2000 format }

{ supported versions:                        }
{                                            }
{ PKT2000.005 - 9806?? - no longer supported }
{ PKT2000.100 - 980809                       }


INTERFACE

USES Outbound,
     Database;

TYPE Pkt2000Address = RECORD
                            Zone,
                            Net,
                            Node,
                            Point : WORD;
                      END;

     Pkt2000Header = RECORD
                           Id              : ARRAY[1..3] OF CHAR;
                           MainHeaderLen   : WORD;
                           SubHeaderLen    : WORD;
                           OrigAddr        : Pkt2000Address;
                           OrigDomain      : STRING[30];
                           DestAddr        : Pkt2000Address;
                           DestDomain      : STRING[30];
                           Password        : STRING[8];
                           ProductName     : STRING[30];
                           PktVersionMajor : WORD;
                           PktVersionMinor : WORD;
                     END;

     Pkt2000MsgHeader = RECORD
                              Id          : ARRAY[1..3] OF CHAR;
                              OrigAddr,
                              DestAddr,
                              WrittenAddr : Pkt2000Address;
                              Year        : WORD;
                              Month,
                              Day,
                              Hour,
                              Min,
                              Sec,
                              Sec100      : BYTE;
                              Attribute   : BYTE; {Bits: 1 - IsFileAttached }
                                                  {      2 - IsFileRequest  }
                                                  {      3 - IsPrivate      }
                                                  {      4 - IsCrash        }
                        END;

     Pkt2000MsgHeader2 = RECORD
                               SeenBys     : WORD;
                               Paths       : WORD;
                               TextBytes   : LONGINT;
                               CharSet     : STRING[25];
                               TimeZone    : STRING[5];
                         END;

                        { followed by strings; used part stored only
                        ReplyTo,
                        MsgId,
                        MsgFrom,
                        MsgTo,
                        MsgSubj,
                        EchoArea,
                        Organization

                        ExtraFields: WORD
                        <0..n>ExtraFields: string, used part only
                        }

                        { followed by seenbys
                          followed by paths
                          followed by body text
                        }

PROCEDURE Pkt2000_WriteHeader (OutPtr : OutboundRecordPtr; VAR UserRec : UserBaseRecord; PktSenderAddress : FidoAddrType);
PROCEDURE FidoAttr2Pkt2000 (Attr_F : WORD; ExtAttr_F : LONGINT; VAR P2kMsgHeader : Pkt2000MsgHeader);
PROCEDURE FidoDate2Pkt2000 (Date_F : STRING; VAR P2kMsgHeader : Pkt2000MsgHeader);


IMPLEMENTATION

USES Ramon,
     Dos,
     Logs,
     Globals,
     Start,
     Fido;

{--------------------------------------------------------------------------}
{ Pkt2000_WriteHeader                                                      }
{                                                                          }
{ This routine creates a type PKT2000 file header and writes it to the     }
{ newly created .P2K file pointed to by OutPtr. The first must be oped.    }
{ The Address field in UserRec is used for the destination address and     }
{ the PktSenderAdres is used as the source address and must be one of our  }
{ AKAs, possibly modified into a point address.                            }
{                                                                          }
PROCEDURE Pkt2000_WriteHeader (OutPtr : OutboundRecordPtr;
                               VAR UserRec : UserBaseRecord;
                               PktSenderAddress : FidoAddrType);

VAR cYear,cMonth,cDay,
    cHour,cMin,cSec,
    Nop              : WordLong;
    Len,Lp           : BYTE;
    Header           : Pkt2000Header;
    IORes            : BYTE;

BEGIN
     GetDate (cYear,cMonth,cDay,Nop);
     GetTime (cHour,cMin,cSec,Nop);

     FillChar (Header,SizeOf (Pkt2000Header),0);

     WITH Header DO
     BEGIN
          Id[1]:='P';
          Id[2]:='2';
          Id[3]:='K';

          MainHeaderLen:=SizeOf (Pkt2000Header);
          SubHeaderLen:=SizeOf (Pkt2000MsgHeader)+SizeOf (Pkt2000MsgHeader2);

          OrigAddr.Zone:=PktSenderAddress.Zone;
          OrigAddr.Net:=PktSenderAddress.Net;
          OrigAddr.Node:=PktSenderAddress.Node;
          OrigAddr.Point:=PktSenderAddress.Point;
          OrigDomain:=PktSenderAddress.Domain;

          DestAddr.Zone:=UserRec.Address.Zone;
          DestAddr.Net:=UserRec.Address.Net;
          DestAddr.Node:=UserRec.Address.Node;
          DestAddr.Point:=UserRec.Address.Point;
          DestDomain:=UserRec.Address.Domain;

          Password:=UserRec.PacketPwd;

          ProductName:=DesktopProgramName+' '+FullProgramVersion;

          PktVersionMajor:=2000;       { PKT2000 format }
          PktVersionMinor:=100;        { sub-version 100 }
     END; { with }

     {$I-} BlockWrite (OutPtr^.OutFile,Header,SizeOf (Pkt2000Header)); {$I-} IORes:=IOResult;
     IF (IORes <> 0) THEN
        LogDiskIOError (IORes,'Error writing P2K header');

     UpdateInfoNr (INFO_PktOut_Bytes,SizeOf (Pkt2000Header));
END;


{--------------------------------------------------------------------------}
{ FidoAttr2Pkt2000                                                         }
{                                                                          }
{ This routine converts the attribute bits into the three fields for a     }
{ Pkt2000 attributes.                                                      }
{                                                                          }
PROCEDURE FidoAttr2Pkt2000 (Attr_F : WORD;
                            ExtAttr_F : LONGINT;
                            VAR P2kMsgHeader : Pkt2000MsgHeader);
BEGIN
     WITH P2kMsgHeader DO
     BEGIN
          { From the PKT2000 specification; 1 = LSBit

          Bits: 1 - IsFileAttached ($01)
                2 - IsFileRequest  ($02)
                3 - IsPrivate      ($04)
                4 - IsCrash        ($08)
          }

          Attribute:=0;

          IF ((Attr_F AND MSGFILE) <> 0) THEN
             Attribute:=Attribute OR $01;

          IF ((Attr_F AND MSGFRQ) <> 0) THEN
             Attribute:=Attribute OR $02;

          IF ((ExtAttr_F AND EXTMSGFRQ) <> 0) THEN
             Attribute:=Attribute OR $02;

          IF ((Attr_F AND MSGPRIVATE) <> 0) THEN
             Attribute:=Attribute OR $04;

          IF ((Attr_F AND MSGCRASH) <> 0) THEN
             Attribute:=Attribute OR $08;

          IF ((ExtAttr_F AND EXTMSGCRA) <> 0) THEN
             Attribute:=Attribute OR $08;
     END; { with }
END;


{--------------------------------------------------------------------------}
{ FidoDate2Pkt2000                                                         }
{                                                                          }
{ This routine splits an FTN date into the fields of a Pkt2000 message     }
{ header.                                                                  }
{                                                                          }
PROCEDURE FidoDate2Pkt2000 (Date_F : STRING; VAR P2kMsgHeader : Pkt2000MsgHeader);

VAR Nop : ValNop;
    Lp  : BYTE;

BEGIN
     Val (Copy (Date_F,8,2),P2kMsgHeader.Year,Nop);
     Val (Copy (Date_F,1,2),P2kMsgHeader.Day,Nop);
     Val (Copy (Date_F,12,2),P2kMsgHeader.Hour,Nop);
     Val (Copy (Date_F,15,2),P2kMsgHeader.Min,Nop);
     Val (Copy (Date_F,18,2),P2kMsgHeader.Sec,Nop);
     P2kMsgHeader.Sec100:=0;

     P2kMsgHeader.Month:=1;

     FOR Lp:=1 TO 12 DO
         IF (Month[Lp] = Copy (Date_F,4,3)) THEN
         BEGIN
              P2kMsgHeader.Month:=Lp;
              Break;
         END;

     IF (P2kMsgHeader.Year > 79) THEN
        Inc (P2kMsgHeader.Year,1900)
     ELSE
         Inc (P2kMsgHeader.Year,2000);
END;


END.
