{$IFDEF WtrGate}{$IFDEF UseOvr}{$O+,F+}{$ENDIF}{$ENDIF}
UNIT FidoPkt;

{$i platform.inc}

{ FidoPkt                                                                   }
{                                                                           }
{ Deze unit bevat de routines om Fido *.PKT bestanden te kunnen verwerken.  }
{ Oorspronkelijk waren deze routines verdeeld over <FIDO> en <MSGS>         }
{                                                                           }
{ MD 10-09-93 Hierheen verplaatst                                           }
{    23-09-93 Onbekende areas worden nu niet meer automatisch aangemaakt    }
{             maar in de bad mail gegooid.                                  }
{    18-11-93 FSC-0048 support toegevoegt, we creeren nog steeds gewone     }
{             stone age pakketen. (doet gecho ook, en is compatible met     }
{             alles.)                                                       }
{    19-01-94 FidoExportMsg geeft nu ook TRUE terug als een gebied          }
{             gemodereerd wordt door een Usenet Moderator                   }

INTERFACE

USES Cfg,
     Dos,
     DataBase;

TYPE FidoPktHdr = RECORD                               { close to stoneage }
       {00}             orig_node : WORD;               { originating node }
       {02}             dest_node : WORD;               { destination node }

       {04}             year   : WORD;                      { 1989 - nnnnn }
       {06}             month  : WORD;
       {08}             day    : WORD;
       {0a}             hour   : WORD;
       {0c}             minute : WORD;
       {0e}             second : WORD;

       {10}             baud : WORD;                              { unused }
       {12}             ver  : WORD;                                   { 2 }

       {14}             orig_net : INTEGER;              { originating net }
       {16}             dest_net : INTEGER;              { destination net }

       {18}             product : BYTE;                { FTSC produkt code }
       {19}             rev_lev : BYTE;                    { versie nummer }

       {1a}             password : ARRAY[1..8] OF BYTE;    { Node password }

       {22}             qm_orig_zone : WORD;               { qm = Qmail ?? }
       {24}             qm_dest_zone : WORD;                 { (verouderd) }

       {26}             F48_AuxNet         : WORD;
       {28}             F48_ValidationCopy : WORD;
       {2a}             F48_ProduktCode    : BYTE;
       {2b}             F48_Revision       : BYTE;
       {2c}             F48_Capability     : WORD;

       {2e}             orig_zone  : WORD;              { originating zone }
       {30}             dest_zone  : WORD;              { destination zone }
       {32}             orig_point : WORD;             { originating point }
       {34}             dest_point : WORD;             { destination point }
       {36}             pr_data    : LONGINT;          { product dependent }
                  END;

     FidoPktMsgHdrAdres = RECORD
       {00}                     TypeIdent,               { Moet 0002 zijn }
       {02}                     OrigNode,
       {04}                     DestNode,
       {06}                     OrigNet,
       {08}                     DestNet,
       {0a}                     AttrFlag,
       {0c}                     Cost      : WORD;
                                { DateTime verhuisd naar FidoPktMsgHdr }
                         END;

     FidoPktMsgHdr = RECORD
                           Adres        : FidoPktMsgHdrAdres;
                           DateTime     : STRING[20];
                           ToUserName   : STRING[36]; {array[1..36] of char }
                           FromUserName : STRING[36]; {array[1..36] of char }
                           Subject      : STRING[72]; {array[1..72] of char }
                     END;

PROCEDURE ProcessInboundPkts (Path : FilePathStr; Ext : ExtStr; Security : SecurityType; BBSRecNr : UserBaseRecordNrType);
PROCEDURE FidoPktProcess (PktPath : FilePathStr; Security : SecurityType; BBSRecNr : UserBaseRecordNrType);

IMPLEMENTATION

USES Ramon,
     {Stats,}
     NewStats,
     Fido,
     DupeChk,
     FBuffer,
     Logs,
     AreaBase,
     UserBase,
     Msgs,
     Strings,
     Binkley,
     Globals,
     SwapMem,
     Routing,
     Start,
     SeenBy,
     {Translat,}
     Address,
     Deliver;

{--------------------------------------------------------------------------}
{ FidoReadPktMsgHdr                                                        }
{                                                                          }
{ Deze routine leest uit de .PKT file een message header. Terug gegeven    }
{ wordt:                                                                   }
{  0 = Succes                                                              }
{  1 = Einde .PKT                                                          }
{ -1 = Error                                                               }
{                                                                          }
FUNCTION FidoReadPktMsgHdr (VAR PktFile : FBufferType;
                            VAR Header  : FidoPktMsgHdr) : INTEGER;
BEGIN
     IF (NOT FBBlockRead (PktFile,Header,SizeOf (FidoPktMsgHdrAdres))) THEN
     BEGIN
          IF (FBByteRead (PktFile) = 0) THEN FidoReadPktMsgHdr:=1   { eof }
                                        ELSE FidoReadPktMsgHdr:=-1; { err }
          Exit;
     END;

     { deze strings zijn op disk null terminated }
     Header.DateTime:=FBReadNull (PktFile);
     Header.ToUserName:=FBReadNull (PktFile);
     Header.FromUserName:=FBReadNull (PktFile);
     Header.Subject:=FBReadNull (PktFile);

     FidoReadPktMsgHdr:=0; { succes }
END;



{--------------------------------------------------------------------------}
{ ScanPktFileForEchomail                                                   }
{                                                                          }
{ This routine scans an opened PKT file for echomail messages. It returns  }
{ with FALSE as soon as it finds an echomail and otherwise returns TRUE    }
{ indicating that the PKT file only contains netmail messages.             }
{ The FBuffer is left in undefined state on return.                        }
{ On calling this function, FBuffer must point past the binary PKT file    }
{ header.                                                                  }
{                                                                          }
{ Echomail is detected by checking for the AREA: kludge right after the    }
{ binary message header. If it is not there, the NUL character is searched }
{ for, indicating the end of a message, and the procedure is repeated from }
{ that point on.                                                           }
{                                                                          }
FUNCTION ScanPktFileForEchomail (PktFile : FBufferType) : BOOLEAN;

VAR Done       : BOOLEAN;
    MsgHeader  : FidoPktMsgHdr;
    AreaKludge : STRING[5];

BEGIN
     ScanPktFileForEchomail:=FALSE; { assume we will find echomail }

     Done:=FALSE;
     REPEAT
           { read the binary message header }
           CASE FidoReadPktMsgHdr (PktFile,MsgHeader) OF
                0 : {normal};

                1 : Done:=TRUE; { end of PKT file }

                ELSE BEGIN
                     LogMessage (liFatal,'[EchoCheck] Read error');
                     Exit; { ## EXIT ## }
                END;
           END; { case }

           IF (NOT Done) THEN
           BEGIN
                { check if an AREA: kludge follows the header }
                IF (NOT FBBlockRead (PktFile,AreaKludge[1],5)) THEN
                BEGIN
                     LogMessage (liFatal,'[EchoCheck] Peek error');
                     Exit; { ## EXIT ## }
                END;

                { if we detected the AREA: kludge, then this PKT file }
                { contains echomail.                                  }
                AreaKludge[0]:=#5;
                IF CaselessMatch (AreaKludge,'AREA:') THEN
                   Exit; { ## EXIT ## }

                { AREA: kludge not found; scan for #0 }
                IF (Pos (#0,AreaKludge) > 0) THEN
                BEGIN
                     LogMessage (liReport,'[EchoCheck] Exception! ** SEND EXAMPLE **');
                     LogExtraMessage ('File: '+FBGetFilename (PktFile));
                     Exit; { ## EXIT ## }
                END;

                IF (NOT FBSkipReadNul (PktFile)) THEN
                BEGIN
                     { reached end of file instead of #0 !! }
                     LogMessage (liReport,'[EchoCheck] Unexpected EOF ** SEND EXAMPLE **');
                     LogExtraMessage ('File: '+FBGetFilename (PktFile));
                     Exit; { ## EXIT ## }
                END;
           END;

     UNTIL Done;

     ScanPktFileForEchomail:=TRUE; { no echomail found }
END;


{--------------------------------------------------------------------------}
{ FidoOpenPktFile                                                          }
{                                                                          }
{ Deze routine opent een Fido Pkt file. En voert controles op de invoer    }
{ file uit, en leest de header. Het volledige pad naar de .PKT moet worden }
{ opgegeven. Als het packet met succes geopend is en de header goed inge-  }
{ lezen is, dan wordt TRUE terug gegeven, anders FALSE. De handl moet ook  }
{ worden opgegeven.                                                        }
{                                                                          }
FUNCTION FidoOpenPktFile (VAR PktPath : STRING;
                          VAR PktFile: FBufferType;
                          VAR Header : FidoPktHdr;
                          VAR NetmailOnly : BOOLEAN) : BOOLEAN;

VAR IORes : BYTE;
    RFile : FILE;

BEGIN
     { rename the .PKT before tossing }
     Assign (RFile,PktPath);

     PktPath[Length (PktPath)]:='P';
     PktPath[Length (PktPath)-1]:='P';

     {$I-} Rename (RFile,PktPath); {$I+} IORes:=IOResult;
     IF (IORes <> 0) THEN
     BEGIN
          LogDiskIOError (IORes,'Failed to rename .PKT to '+PktPath);
          LogMessage (liGeneral,'Processing anyway; crash might cause re-toss!');
     END;

     IF (NOT FBufferOpen (PktFile,PktPath,15000,0)) THEN
     BEGIN
          FBufferClose (PktFile);
          FidoOpenPktFile:=FALSE;
          Exit;
     END;

     IF (NOT FBBlockRead (PktFile,Header,SizeOf (FidoPktHdr))) THEN
     BEGIN
          FBufferClose (PktFile);
          FidoOpenPktFile:=FALSE;
          Exit;
     END;

{ MD:   ---- Routine om programma dat pakket creerde te herkennen ----- }
{ RvdW: bull shit... waarom zou je? }
{ MD:   Staat stoer in de logs      }

     { check the contents of the PKT file to work out whether it  }
     { contains Netmail only. To save time we stop when we find   }
     { the first echomail message and do not work out whether the }
     { PKT file is netmail only, echomail only or a mixture.      }

     {## this *should* be done when we have found out that we do not }
     {## know the sender, so we don't do this for each and every     }
     {## PKT file.                                                   }
     NetmailOnly:=ScanPktFileForEchomail (PktFile);

     { go back to start }
     FBSeek (PktFile,0);

     IF (NOT FBBlockRead (PktFile,Header,SizeOf (FidoPktHdr))) THEN
     BEGIN
          FBufferClose (PktFile);
          FidoOpenPktFile:=FALSE;
          Exit;
     END;

     FidoOpenPktFile:=TRUE;
END;


{--------------------------------------------------------------------------}
{ FidoClosePktFile                                                         }
{                                                                          }
{ Routine om Pkt met stijl af te sluiten (ahum)... De file wordt via de    }
{ FBuffer routines gesloten.                                               }
{ Deze routine wordt alleen aangeroepen in geval van problemen met de .PKT }
{ file. We renamen em hier terug naar .PKT zodat andere tossers em kunnen  }
{ verwerken.                                                               }
{                                                                          }
PROCEDURE FidoClosePktFile (VAR PktFile : FBufferType; VAR PktPath : STRING);

VAR IORes : BYTE;

BEGIN
     FBufferClose (PktFile);

     PktPath[Length (PktPath)]:='T';
     PktPath[Length (PktPath)-1]:='K';

     {$I-} Rename (PktFile.Bestand,PktPath); {$I+} IORes:=IOResult;
     IF (IORes <> 0) THEN
        LogDiskIOError (IORes,'Failed to rename .PPP file back to '+PktPath);
END;


{--------------------------------------------------------------------------}
{ StripSeenByAndPathLines                                                  }
{                                                                          }
{ Deze routine voegt alle regels toe aan de Footer_F, behalve SEEN-BY en   }
{ PATH lines. Dit wordt gebruikt voor inbound echomail van een BBS user.   }
{                                                                          }
FUNCTION StripSeenByAndPathLines (VAR Regel : STRING) : BOOLEAN; FAR;
BEGIN
     StripSeenByAndPathLines:=FALSE; { continue always }

     IF (Copy (Regel,1,8) = 'SEEN-BY:') OR (Copy (Regel,1,6) = #1'PATH:') THEN
        Exit;

     MsgsAddLineToNoEOL (Footer_F,Regel);
END;


{--------------------------------------------------------------------------}
{ FidoPktProcess                                                           }
{                                                                          }
{ Met deze routine wordt een gevonden .PKT bestand verwerkt. Het volledige }
{ pad moet meegegeven worden.                                              }
{                                                                          }
PROCEDURE FidoPktProcess (PktPath : FilePathStr; Security : SecurityType; BBSRecNr : UserBaseRecordNrType);

VAR
{ pkt variabelen }
    PktFile       : FBufferType;
    PktHeader     : FidoPktHdr;
    NetmailOnly   : BOOLEAN;

{ msg variabelen }
    MsgHeader     : FidoPktMsgHdr;

{ regel variabelen }
    Regel,
    LastRegel     : STRING;
    WhereTo       : WhereToType;

{ security }
    Temp,
    Sender,
    SentTo        : FidoAddrType;
    AreaRecNr     : AreaBaseRecordNrType;
    Result,
    IORes         : BYTE;

    Password      : STRING[9];
    Destination   : STRING;
    SenderIsKnownToUs : BOOLEAN;

    FromUserData  : UserBaseRecord;  { RWI 950621: lokaal gemaakt }
    FromUserRecNr : UserBaseRecordNrType;

    LineBuffer    : TopRegelRecordPtr;

    SecureText    : STRING[40];

    DupeValue     : LONGINT;

    Lp            : 1..MAX_AREA_CROSS_POSTS;

    NumEcho,
    NumNet        : LONGINT;
BEGIN
     IF (NOT CheckMinDiskFree) THEN
        Exit;

     IF (NOT FidoOpenPktFile (PktPath,PktFile,PktHeader,NetmailOnly)) THEN
     BEGIN
          LogMessage (liFatal,'Failed to open '+PktPath);
          Exit;
     END;

     UpdateInfoNr (INFO_PktIn_Jobs,1);

     { Lees adres informatie uit de FidoPkt header }
     { "ondersteuning van TYPE 2+"                 }

     NumNet := 0;
     NumEcho := 0;

     WITH Sender,PktHeader DO
     BEGIN
          Zone:=Orig_Zone;
          Net:=Orig_Net;
          Node:=Orig_Node;
          Point:=Orig_Point;
          Domain:=''; { niet uit de header halen? Is dat receiver domain? }

          { RWI 950317: als de zone nul is, dan pakken we de qm_orig_zone }
          IF (Zone = 0) THEN
             Zone:=qm_orig_zone;

          IF (Orig_Net = -1) AND (F48_ValidationCopy = F48_Capability) THEN
             Net:=F48_AuxNet;
     END; { with }

     WITH SentTo,PktHeader DO
     BEGIN
          Zone:=Dest_Zone;
          Net:=Dest_Net;
          Point:=Dest_Point;
          Node:=Dest_Node;
          Domain:=''; { niet uit de header halen? }

          IF (Zone = 0) THEN
             Zone:=qm_dest_zone;
     END; { with }

     IF (BBSRecNr = NILRecordNr) THEN
     BEGIN
          { Aangezien 280/802 nu door ons niet herkent zou worden,.. }
          { fixup het binnenkomende adres                            }

          FidoMatch (Sender,Temp);
          FidoMergeAdres (Temp,Sender);

          {WriteXY (33,6,AddUpWithSpaces (23,Fido2Str (Sender)));}
          SenderIsKnownToUs:=FindUserBaseRecordByFidoAddress (Sender,FromUserRecNr);

          IF (NOT NetmailOnly) AND (Security = Secure) AND (NOT SenderIsKnownToUs) THEN
          BEGIN
               LogExtraMessage ('System '+Fido2Str (Sender)+' is not defined in the user base!');

               FBufferClose (PktFile);

               Destination:=Copy (PktPath,1,Length (PktPath)-4)+'.UNK';

               IF RenameSerial (PktPath,Destination) THEN
                  LogExtraMessage ('Renamed PKT to '+Destination)
               ELSE
                   LogExtraMessage ('Serial rename failed, leaving as '+PktPath);

               Exit; { ## EXIT ## }
          END;

          IF SenderIsKnownToUs THEN
          BEGIN
               { voor conversie etc. is het FROM user UserBase record nodig }
               Msg.DeliveringUserRecNr:=FromUserRecNr;
               ReadUserBaseRecord (FromUserRecNr,FromUserData);
               PacketUserData:=FromUserData; { RWI 950102 ivm routines achter MsgsExport }
               AreaCreatorUserBaseRecNr:=FromUserRecNr; { voor aanmaken nieuwe areas }
          END ELSE
          BEGIN
               Msg.DeliveringUserRecNr:=NILRecordNr;
               AreaCreatorUserBaseRecNr:=NILRecordNr;
          END;

          { Controle op passwords bij het importeren }

          IF SenderIsKnownToUs AND (Security = Secure) THEN
          BEGIN
               { Converteer het password naar een pascal string }
               Move (PktHeader.password,Password[1],8);
               Password[0]:=#0;
               WHILE (Byte (Password[Byte (PassWord[0])+1]) <> 0) AND (Byte (Password[0]) < 8) DO
                     Inc (Byte (Password[0]));

               { controleer adres + password creerder van het pakket met berichten }
               IF (FromUserData.PacketPwd <> '') AND
                  (UpCaseString (FromUserData.PacketPwd) <> UpCaseString (DeleteBackspaces (Password))) THEN
               BEGIN
                    { Pasword failure ! }
                    LogExtraMessage ('Password failure for '+PktPath+' from '+Fido2Str (Sender));
                    LogExtraMessage ('Got "'+Password+'" but expected "'+FromUserData.PacketPwd+'"');

                    Destination:=Copy (PktPath,1,Length (PktPath)-4)+'.PWD';

                    FBufferClose (PktFile);

                    IF RenameSerial (PktPath,Destination) THEN
                       LogExtraMessage ('Renaming to '+Destination)
                    ELSE
                        LogExtraMessage ('Rename of bad packet failed!');

                    Exit;
               END;

               SecureText:='secure';
          END ELSE
          BEGIN
               SecureText:='normal';

               IF (NOT SenderIsKnownToUs) AND NetmailOnly THEN
                  SecureText:='insecure, netmail only';
          END;

          IF Config.LogFidoTossed THEN
          BEGIN
               LogMessage (liTrivial,'Processing ('+SecureText+') '+PktPath+
                           ' ('+Longint2String (FileSize (PktFile.Bestand))+' bytes)');

               LogExtraMessage ('Sender '+Fido2Str (Sender)+
                                ' for '+Fido2Str (SentTo));
          END;
     END ELSE
     BEGIN
          { BBS Interface }
          FromUserRecNr:=BBSRecNr;
          SenderIsKnownToUs:=TRUE;
          Msg.DeliveringUserRecNr:=FromUserRecNr;
          ReadUserBaseRecord (FromUserRecNr,FromUserData);
          PacketUserData:=FromUserData; { RWI 950102 ivm routines achter MsgsExport }
          AreaCreatorUserBaseRecNr:=NILRecordNr; { mag niet voorkomen }

          IF Config.LogFidoTossed THEN
             LogMessage (liTrivial,'Processing (bbs) '+PktPath+' ('+Longint2String (FileSize (PktFile.Bestand))+' bytes)');
     END;

     AreaRecNr:=NILRecordNr;    { not loaded yet }
     AreaData.AreaName_F:=#255; { RAWI 980302: avoid match }

     {---------------------------------------------------------------}
     { controleren of het pakket wel aan ons gericht is met hdr info }
     { lees de berichten uit de .pkt                                 }
     WHILE (FidoReadPktMsgHdr (PktFile,MsgHeader) = 0) DO
     BEGIN
          {FidoProcessStatusShow;}

          { maak het universele MsgBuffer leeg }
          MsgsEmptyKeepDeliveringUser;

          { UserDataRecNr werd onderweg ergens onderuit gehaald en bij }
          { het verwerken van het tweede bericht gaat het dan mis.     }
          { Helaas werd deze niet altijd onderuit gehaald...           }
          UserDataRecNr:=FromUserRecNr;

          { copieer gegevens uit de PktMsgHdr naar het universele buffer }
          WITH Msg DO
          BEGIN
               {Ready_F:=Netmail; wordt nu achteraf bepaald! }
               FromUser_F:=MsgHeader.FromUserName;
               Stored_ToUser:=MsgHeader.ToUserName;
               Subj_F:=MsgHeader.Subject;
               Date_F:=FidoCorrectDate (MsgHeader.DateTime);
               Attr_F:=MsgHeader.Adres.AttrFlag;   {## strip some? -> seen export "AND filter" }
               Cost_F:=MsgHeader.Adres.Cost;
          END; { with }

          WITH Msg.Stored_ToAddr DO
          BEGIN
               Net:=MsgHeader.Adres.DestNet;
               Node:=MsgHeader.Adres.DestNode;
          END; { with }

          WITH Msg.FromAddr_F DO
          BEGIN
               Net:=MsgHeader.Adres.OrigNet;
               Node:=MsgHeader.Adres.OrigNode; { 31-03-93, was DestNode }
               { Origin will override this }
          END; { with }

          WhereTo:=Header_F;
          PrevKludgeID:=klNone;

          {--------------------------------------------------------------}
          { nu de hele body van het bericht inlezen en opslaan.          }
          WHILE FBReadLnCR (PktFile,Regel) AND (Regel <> #0) DO
          BEGIN
               FidoAddLineToMessage (Regel,LastRegel);

               { RWI 960223: changed "<> Echomail" into "= NotReady" om te }
               {             voorkomen dat een AREA: in het midden van een }
               {             netmail het bericht omzet in een echomail     }

               {IF (PrevKludgeID = klArea) AND (Msg.Ready_F = NotReady) THEN}

               { RAWI 970528: werkt natuurlijk niet, want Msg.Ready_F wordt }
               {              pas op Netmail gezet als het geen echomail    }
               {              was. Nieuwe check: er mag geen body zijn.     }

               IF (PrevKludgeID = klArea) AND
                  ((Msg.BodyParts[1] = NIL) OR (Msg.BodyParts[1]^.TotalRegelLength = 0)) THEN
               BEGIN
                    { echomail bericht }
                    Msg.Ready_F:=Echomail;
                    UpdateInfoNr (INFO_PktIn_Echo,1);

                    { RWI 950215: UpCaseString toegevoegd... }
                    { RWI 960223: DeleteFrontSpaces toegevoegd... }
                    Msg.Area_F:=DeleteFrontSpaces (UpCaseString (Copy (Regel,Pos (':',Regel)+1,255)));

                    IF (Msg.Area_F <> '') AND (Msg.Area_F[Length (Msg.Area_F)] = #13) THEN
                       Delete (Msg.Area_F,Length (Msg.Area_F),1);

                    { Controleer of node toegang heeft tot de area dit    }
                    { is verplaatst naar vOOr MsgExport omdat er nog meer }
                    { informatie over de node nodig is, die nog uit rest  }
                    { van de kludges (Pntl etc.) moet worden gehaald.     }

                    { AreaData is hierheen verhuist, omdat deze informatie  }
                    { keihard nodig is voor SeenBy + Path lines             }
                    { Ook wordt een area nu al aangemaakt als die nog niet  }
                    { bestond, dit is ook nodig voor de bovenstaande regels }

                    {## AreaRecNr is NILRecordNr when the following }
                    {## combination comes by:                    }
                    {## KNOWN_AREA_1                             }
                    {## Unknown area                             }
                    {## KNOWN_AREA_1                             }
                    {## It works fine when another area comes by after }
                    {## the unknown one                                }
                    IF (AreaData.AreaName_F <> Msg.Area_F) THEN
                    BEGIN
                         AreaRecNr:=GetAreaBaseRecordNrByAreaName_F (Msg.Area_F);

                         IF (AreaRecNr = NILRecordNr) THEN
                         BEGIN
                              AreaData.AreaName_F:='***'; { avoid re-use }

                              { Controleer of een user wel een area mag creeren }
                              { identisch: NOT (SenderIsKnownToUs AND AllowCreated) }
                              IF (NOT SenderIsKnownToUs) OR
                                 (SenderIsKnownToUs AND (NOT FromUserData.AllowCreate)) THEN
                              BEGIN
                                   LogMessage (liGeneral,'Echomail sent by '+Fido2Str (Sender)+' in unknown area '+Msg.Area_F);
                                   Msg.Ready_F:=Bad;
                                   Msg.BadReason:='Sender '+Fido2Str (Sender)+
                                                  ' is not allowed to create new area "'+Msg.Area_F+'"';
                                   {##notify sending system's sysop?}
                              END ELSE
                              BEGIN
                                   LogMessage (liGeneral,'Auto creating area '+Msg.Area_F+' sent by '+Fido2Str (Sender));
                                   AreaRecNr:=AutoCreateArea (Msg.Area_F,'');
                                   ReadAreaBaseRecord (AreaRecNr,AreaData);
                              END;
                         END ELSE
                             ReadAreaBaseRecord (AreaRecNr,AreaData);
                    END;
               END; { klArea }

          END; { while not entire message read in }

          FidoAddLastLine (LastRegel);

          { SEEN-BY en PATH lines verwijderen voor een BBS user }
          IF (BBSRecNr <> NILRecordNr) THEN
          BEGIN
               LineBuffer:=Msg.FooterTop_F;
               Msg.FooterTop_F:=NIL;
               MsgsForEachKill (LineBuffer,StripSeenByAndPathLines);
          END;

          { als het geen echomail was (of bad of dupes nu), dan moet }
          { het wel netmail zijn.                                    }
          IF (Msg.Ready_F = NotReady) THEN
             Msg.Ready_F:=Netmail;

          UpdateInfoNr (INFO_PktIn_Msgs,1);

          { controleer of de node wel in deze area mag schrijven }
          { en of de area wel bestaat.                           }
          IF SenderIsKnownToUs AND (FromUserData.System <> _BBS) THEN
          BEGIN
               IF (Msg.Ready_F = Echomail) THEN
               BEGIN
                    IF (NOT TestIfUserIsInAreaRec_UserList (AreaData.UserList,FromUserRecNr)) THEN
                    BEGIN
                         LogMessage (liGeneral,'Delivering user '+Fido2Str (Sender)+
                                               ' is not subscribed to area '+AreaData.AreaName_F);
                         Msg.Ready_F:=Bad;
                         Msg.BadReason:='User '+Fido2Str (Sender)+' is not subscribed to area '+AreaData.AreaName_F;
                    END;
               END;

               IF (Msg.Ready_F = Echomail) THEN
               BEGIN
                    { kijk of de area in een read/write group zit, anders }
                    { mag de user er niet in schrijven. RWI 941126        }
                    { RWI 950621: Ipv FromUserData of PacketUserData werd UserData gebruikt... }
                    { RWI 950722: Er stond nog steeds UserData ipv FromUserData! }
                    { RWI 950802: Newly created areas area only in group Z!   }
                    {             Fixed by setting the Z flag for these users }

                    { the below statement doesn't allow users to write in    }
                    { read-only areas, but does allow posts in newly created }
                    { areas. Notice that it is not possible to block writes  }
                    { to these newly created areas.                          }

                    { RWI 960224: User now has write access when not in any }
                    {             of the groups the area is in.             }

                    IF TestIfGroupCommon (FromUserData.Groups,AreaData.IsInGroups) THEN { new }
                       IF (NOT TestIfGroupCommon3 (FromUserData.Groups,AreaData.IsInGroups,ReadWriteGroupsFilter)) AND
                          NOT ((FromUserData.AllowCreate AND TestIfInGroup (AreaData.IsInGroups,Group_NewAreas))) THEN
                      {IF ((FromUserData.Groups AND AreaData.IsInGroups AND ReadWriteGroupsFilter) = 0) AND
                          NOT ((FromUserData.AllowCreate AND (AreaData.IsInGroups = GROUP_Z))) THEN}
                       BEGIN
                            { nee, user mag niet in een group waarin de area zit }
                            { en waarin geschreven mag worden. BAD met die hap.  }
                            LogMessage (liGeneral,'User '+Fido2Str (Sender)+
                                                  ' attemted to post to read-only area '+AreaData.AreaName_F);
                            Msg.Ready_F:=Bad;
                            Msg.BadReason:='User "'+Fido2Str (Sender)+'" attempted to post to read-only area "'+
                                           AreaData.AreaName_F+'"';
                       END;
               END;
          END;

          IF (Msg.Ready_F = Echomail) THEN
          BEGIN
               IF Config.LogPktEachEcho THEN
                  LogExtraMessage ('  '+AddUpWithPreSpaces (6,Longint2String (Msg.MsgSize))+' '+AreaData.AreaName_F);

               { check of het een Dupe is }
               IF Config.DoDupeChk AND (AreaData.DupeAge <> 0) THEN
               BEGIN
                    DupeValue:=DupeCheck_CalcDupeValue_Echomail;
                    DupeCheck_SetAreaRef (AreaRecNr,AreaData);

                    IF DupeCheck_Exists (DupeValue) THEN
                    BEGIN
                         LogMessage (liGeneral,'Echomail message is a duplicate');
                         Msg.Ready_F:=Dupe;
                    END;
               END;
          END;

          IF (Msg.Ready_F = Echomail) THEN
          BEGIN
               { werk de informatie van deze user bij }
               { de user is altijd bekend, want we staan geen echo }
               { van onbekende systemen toe.                       }
               {### stats}
               {
               UpdateUserStats (Msg.DeliveringUserRecNr,EchoFrom,Msg.MsgSize);
               }

               Inc (NumEcho);

               { RWI 960219: BAD echomail is no longer counted in the area stats }
               {
               IF (Msg.Ready_F = Echomail) THEN
                  UpdateAreaStats (AreaRecNr,Msg.MsgSize);
               }

               Address_AddAreaToAreaRecNrsList (AreaRecNr);
          END; { echomail }

          { RAWI982123 Netmails without INTL line kept from zone }
          { equal to 0. The To-zone is then fixed, but the from  }
          { zone is never filled in. This is done here.          }
          IF (Msg.FromAddr_F.Zone = 0) THEN
             Msg.FromAddr_F.Zone:=Sender.Zone;

          { Als de TO zone nog steeds nul is, probeer hem dan aan te }
          { vullen met de SENDER zone.                               }
          IF (Msg.Stored_ToAddr.Zone = 0) THEN
             Msg.Stored_ToAddr.Zone:=Sender.Zone;

          { Als de TO zone nog steeds nul is, probeer hem dan aan te }
          { vullen met de FROM zone.                                 }
          IF (Msg.Stored_ToAddr.Zone = 0) THEN
             Msg.Stored_ToAddr.Zone:=Msg.FromAddr_F.Zone;

          { replace the to-aka if it matches the fake aka for a bbs interface }
          IF (FromUserData.System = _BBS) THEN
             WITH FromUserData,Msg.Stored_ToAddr DO
                  IF (FakeZone = Zone) AND (FakeNet = Net) AND
                     (FakeNode = Node) AND (Point = 0) THEN
                  BEGIN
                       { take the system node number selected in the bbs record }
                       Msg.Stored_ToAddr:=Config.NodeNrs[FromUserData.SystemAka];
                  END;

          IF (Msg.Ready_F = Netmail) THEN
          BEGIN
               IF Config.LogPktEachEcho THEN
               BEGIN
                    LogExtraMessage ('  '+AddUpWithPreSpaces (6,Longint2String (Msg.MsgSize))+' Netmail');
                    LogExtraMessage ('         From "'+Msg.FromUser_F+'" '+Fido2Str (Msg.FromAddr_F));
                    LogExtraMessage ('         To "'+Msg.Stored_ToUser+'" '+Fido2Str (Msg.Stored_ToAddr));
               END;

               UpdateInfoNr (INFO_PktIn_Net,1);
               
               { werk de informatie van deze user bij }
               {### stats}
               {
               IF SenderIsKnownToUs THEN
                  UpdateUserStats (Msg.DeliveringUserRecNr,NetFrom,Msg.MsgSize);
               }
               Inc (NumNet);

          END;

          { Stript de CRASH flag om te voorkomen dat wij voor de rekening }
          { opdraaien.                                                    }
          Msg.Attr_F:=Msg.Attr_F AND ($FFFF-MSGCRASH);

          IF (Msg.Ready_F = Netmail) THEN
             Address_AddFTN (Msg.Stored_ToUser,Msg.Stored_ToAddr,FALSE,FALSE);

          IF (Msg.Ready_F = Echomail) THEN
          BEGIN
               IF SBP_StoreSeenbysAndPath (Sender.Zone) THEN
               BEGIN
                    { circular path detected! }
                    LogMessage (liGeneral,'Echomail message is a duplicate (circular PATH)');
                    Msg.Ready_F:=Dupe;
               END ELSE
                   Address_AddEcho;
          END;

          { fill in the informational fields }
          Msg.ToUser_F:=Msg.Stored_ToUser;

          DeliverNow;
     END; { while niet einde .PKT }

     { uit de while verhuisd, stond vlak voor de END en er staat er ook }
     { eentje bovenin... RWI 941126.                                    }

     MsgsEmptyKeepDeliveringUser; { geef het geheugen weer vrij }

     { Update statistics }
     IF (FidoOurAdres (SentTo)) THEN
          StatEntry_FidoPkt (stdInbound, Fido2Str(Sender), 'LOCAL', FileSize (PktFile.Bestand)-58, NumEcho, NumNet)
     ELSE
          StatEntry_FidoPkt (stdInbound, Fido2Str(Sender), Fido2Str (SentTo), FileSize (PktFile.Bestand)-58, NumEcho, NumNet);

     UpdateInfoNr (INFO_PktIn_Bytes,FileSize (PktFile.Bestand));

     FBufferClose (PktFile);

     { PKT file wissen }

     {$I-} Erase (PktFile.Bestand); {$I+} IORes:=IOResult;
     IF (IORes <> 0) THEN
        LogDiskIOError (IORes,'Unable to delete '+PktPath);
END;


{--------------------------------------------------------------------------}
{ ProcessInboundPkts                                                       }
{                                                                          }
{ Deze routine loopt alle inbound directories af en leest daaruit alle     }
{ .PKT files in om te verwerken.                                           }
{                                                                          }
PROCEDURE ProcessInboundPkts (Path : FilePathStr; Ext : ExtStr; Security : SecurityType; BBSRecNr : UserBaseRecordNrType);

VAR Search : SearchRec;

BEGIN
     Path:=CorrectPath (Path);

     FindFirst (Path+'*.'+Ext,saJustFiles,Search);
     WHILE (DosError = 0) DO
     BEGIN
          IF KeyPressed AND (Ramon.ReadKey = kEsc) THEN
          BEGIN
               GlobalAbort:=TRUE;
               Break; { uit de while }
          END;

          UpdateReadFile (Path+Search.Name,Search.Size);

          { verwerk het pakket }
          FidoPktProcess (Path+Search.Name,Security,BBSRecNr);

          FindNext (Search);
     END; { while }

     FindClose (Search);
END;


END.


