{$IFDEF WtrGate}{$IFDEF UseOvr}{$O+,F+}{$ENDIF}{$ENDIF}

{$i platform.inc}

{ (Inbound) Soup packet handling }
UNIT Soup;

INTERFACE

PROCEDURE SoupToss;

IMPLEMENTATION

USES Ramon,
     Logs,
     Cfg,
     Address,
     AreaBase,
     FBuffer,
     Globals,
     Msgs,
     Start,
     Database,
     Userbase,
     Usenet,
     NewStats,
     HdrSrch;

VAR
     IsReplacementAreasFileOpen:BOOLEAN;
     ReplacementAreasFile     : TEXT;

{--------------------------------------------------------------------------}
{ SoupProcessNewsFileBn                                                    }
{                                                                          }
{ Processes a file containing newsgroup messages in the Bn format.  After  }
{ delivering the messages, it returns TRUE if all went well, or FALSE if   }
{ an error occured.                                                        }
{                                                                          }
{ Bn format: <msg len>        Longint (in big-endian order)                }
{            Message text     <msg len> bytes of text                      }
{                                                                          }
FUNCTION SoupProcessNewsFileBn (Filename: STRING) : BOOLEAN;
VAR
     Fp : FBufferType;

     Done: BOOLEAN;
     MsgLen: LONGINT;
     MsgOfs: LONGINT;
     Line: STRING;
     MsgStart: LONGINT;
     PrevHad13: BOOLEAN;
     IORes: INTEGER;

     TempFp: FILE;

     Ch: Byte;
     TempBytes : array [1..4] of byte;

     OldNews: LONGINT;

BEGIN
     OldNews := RetrieveInfoNr (INFO_SoupIn_News);

     SoupProcessNewsFileBn := False;

     LogMessage (liGeneral, 'Processing SOUP job "'+Filename+'.MSG'+'"');
     IF (NOT FBufferOpen (Fp, Filename+'.MSG', 10000, 0)) THEN
     BEGIN
          FBufferClose (Fp);
          LogMessage (liFatal, '[SoupProcessNewsFileBn] Cannot open file '+Filename+'.MSG');
          Exit;
     END;

     UpdateInfoNr (INFO_SoupIn_Jobs, 1);
     
     Done := False;
     
     WHILE (NOT Done) DO
     BEGIN
          MsgsEmptyKeepDeliveringUser;
          
          RFC_AddWhereTo := Header_U;             { ## check }
          PrevHad13 := False;

          IF (NOT FBBlockRead (Fp, MsgLen, 4)) THEN
               Break;

          { Swap the bytes }
          Move (MsgLen, TempBytes, 4);
          Ch := TempBytes [1];
          TempBytes [1] := TempBytes [4];
          TempBytes [4] := Ch;

          Ch := TempBytes [2];
          TempBytes [2] := TempBytes [3];
          TempBytes [3] := Ch;

          Move (TempBytes, MsgLen, 4);

          IF (MsgLen = 0) THEN
               Break;

          MsgOfs := 0;

          Msg.Ready_U := News;

          WHILE (MsgOfs < MsgLen) DO
          BEGIN
               IF (NOT FBReadLnLF (Fp, Line)) THEN
                    Break;

               Inc (MsgOfs, Length (Line));

               RFC_AddTossedRegel (Line, PrevHad13);
          END;


          Msg.Ready_U := News;

          RFC_GoProcess;
     
          MsgsEmptyKeepDeliveringUser;
     
          UpdateInfoNr (INFO_SoupIn_Bytes, MsgLen);
     END;

     { Update statistics }
     StatEntry_SOUPJob (stdInbound, PacketUserData.UUCPName, 'LOCAL',
                              FileSize (Fp.Bestand),
                              RetrieveInfoNr (INFO_SoupIn_News) - OldNews,
                              0 {Num mail});

     FBufferClose (Fp);

     { Erase the .MSG file }
     Assign (TempFP, Filename+'.MSG');
     {$I-} Erase (TempFP); IORes := IOResult; {$I+}
     IF (IORes <> 0) THEN
     BEGIN
          LogDiskIOError (IORes, 'SOUP: Unable to delete job '+Filename+'.MSG');
          Exit;
     END;

     SoupProcessNewsFileBn := True;
END;

{--------------------------------------------------------------------------}
{ SoupProcessMailFileBn                                                    }
{                                                                          }
{ Processes a file containing e-mail messages in the Bn format.  After     }
{ delivering the messages, it returns TRUE if all went well, or FALSE if   }
{ an error occured.                                                        }
{                                                                          }
{ Bn format: <msg len>        Longint (in big-endian order)                }
{            Message text     <msg len> bytes of text                      }
{                                                                          }
FUNCTION SoupProcessMailFileBn (Filename: STRING) : BOOLEAN;
VAR
     Fp : FBufferType;

     Done: BOOLEAN;
     MsgLen: LONGINT;
     MsgOfs: LONGINT;
     Line: STRING;
     PrevHad13: BOOLEAN;
     IORes: INTEGER;
     IsHeader: BOOLEAN;

     TempFp: FILE;

     Ch: Byte;
     TempBytes : array [1..4] of byte;

     OldMail: LONGINT;

     {-------------------------------------------------------------------}
     { Soup_Pop3Process                                                  }
     {                                                                   }
     { Called instead of RFC_GoProcess to process an e-mail message      }
     { downloaded from a POP3 mailbox.  (When the new fields are in,     }
     { This will fill in the Recipient if none were found in the actual  }
     { message.                                                          }
     PROCEDURE Soup_Pop3Process;
     BEGIN
          (* -- HDRSRCH.PAS
          IF (Msg.FirstDest = NIL) THEN
          BEGIN
               IF (PacketUserData.SoupEnvelopeHdr <> '') THEN
                    LogMessage (liGeneral, '[Soup] POP3 envelope header not found!');

               LogMessage (liGeneral, '[Soup] Sending POP message to '+PacketUserData.SoupRecipient);
               Address_AddRFCRaw (PacketUserData.SoupRecipient, destTo, False, False);
          END;
          *)

          HeaderSearch_CheckNoRecipients (PacketUserData.SoupRecipient);

          Msg.Ready_U := Mail;

          RFC_GoProcess;
     END;

     (* --- HDRSRCH.PAS
     PROCEDURE CheckEnvelopeHdr (Regel : STRING);
     BEGIN
          IF (Regel[Length (Regel)] = #13) THEN
               Delete (Regel,Length (Regel),1);

          IF Config.LogDebug THEN
               LogMessage (liTrivial,'[Soup] Found POP3 envelope header: '+Regel);

          Delete (Regel,1,Length (PacketUserData.SoupEnvelopeHdr));
          Regel:=DeleteFrontAndBackSpaces (Regel);

          Regel:=UseGetAddress (Regel);

          Address_AddRFCRaw (Regel,destTo,FALSE,FALSE);
     END;

     PROCEDURE SearchHeaderLine (Regel : STRING);

     VAR Lp      : BYTE;
         UpRegel : STRING;
         P,P2    : BYTE;

     BEGIN
          P:=Pos (#13,Regel);
          IF (P > 0) THEN
               Regel:=Copy (Regel,1,P-1);

          UpRegel:=UpCaseString (Regel);

          FOR Lp:=1 TO MaxSystemDomains DO
               IF (Config.Domains[Lp] <> '') THEN
               BEGIN
                    P:=Pos (UpCaseString (Config.Domains[Lp]),UpRegel);

                    IF (P > 0) THEN
                    BEGIN
                         { found a header that might match }
                         LogMessage (liDebug,'[Soup] Pop3Header: "'+Regel+'"');

                         IF NOT (Regel[1] IN [' ',#9]) THEN
                         BEGIN
                              Regel:=Regel+' ';
                              Delete (Regel,1,Pos (' ',Regel));
                         END;

                         Regel:=UseGetAddress (Regel);

                         { avoid finding otherdomain.com if we are domain.com }
                         UpRegel:=UpCaseString (Regel);
                         P:=Pos (UpCaseString (Config.Domains[Lp]),UpRegel);

                         { can be domain.com!user }
                         IF (P > 0) AND (Regel[P-1] IN ['.','@']) THEN
                         BEGIN
                              IF Config.LogDebug THEN
                                   LogMessage (liTrivial,'[Soup] Found in header: '+Regel);

                              Address_AddRFCRaw (Regel,destTo,{Note:}FALSE,{ByFilter:}FALSE);
                         END;
                    END;
               END; { if, for }
     END;
     *)

BEGIN
     OldMail := RetrieveInfoNr (INFO_SoupIn_Mail);

     SoupProcessMailFileBn := False;

     LogMessage (liGeneral, 'Processing SOUP job "'+Filename+'.MSG'+'"');
     IF (NOT FBufferOpen (Fp, Filename+'.MSG', 10000, 0)) THEN
     BEGIN
          FBufferClose (Fp);
          LogMessage (liFatal, '[SoupProcessMailFileBn] Cannot open file '+Filename+'.MSG');
          Exit;
     END;

     UpdateInfoNr (INFO_SoupIn_Jobs, 1);
     
     Done := False;

     { If the user didn't set a Recipient, set one ourself }

     IF PacketUserData.SoupRecipient = '' THEN
          PacketUserData.SoupRecipient := 'postmaster@'+Config.Domains[1];

     HeaderSearch_SetEnvelope (PacketUserData.SoupEnvelopeHdr);

     WHILE (NOT Done) DO
     BEGIN
          IF (NOT FBBlockRead (Fp, MsgLen, 4)) THEN
               Break;

          { Swap the bytes }
          Move (MsgLen, TempBytes, 4);
          Ch := TempBytes [1];
          TempBytes [1] := TempBytes [4];
          TempBytes [4] := Ch;

          Ch := TempBytes [2];
          TempBytes [2] := TempBytes [3];
          TempBytes [3] := Ch;

          Move (TempBytes, MsgLen, 4);
          IF (MsgLen = 0) THEN
               Break;

          MsgOfs := 0;

          MsgsEmptyKeepDeliveringUser;
          Msg.Ready_U := Mail;
          
          IsHeader := True;
          RFC_AddWhereTo := Header_U;             { ## check }
          PrevHad13 := False;

          {LogMessage (liGeneral, 'Soup len='+Longint2String (MsgLen));}

         { Received: by dijkline.wlink.nl (0.01 beta/WaterGate) }
         {           via SOUP; Sat, 10 Jul 93 00:06:50 +0100    }

         Line:='Received: by '+UseGetSystemFromName+' ('+ProgramShortName+' '+MainRevisionNr+')'+#13;
         RFC_AddTossedRegel (Line,PrevHad13);

         Line:='          via SOUP; '+UsenetArpaNetDate+#13;
         RFC_AddTossedRegel (Line,PrevHad13);


          WHILE (MsgOfs < MsgLen) DO
          BEGIN
               IF (NOT FBReadLnLF (Fp, Line)) THEN
                    Break;

               {LogMessage (liGeneral, 'AT OFS='+Longint2String (MsgOfs)+'; '+Line);}
               Inc (MsgOfs, Length (Line));

               IF IsHeader THEN
               BEGIN
                    IF (PrevHad13) AND (Line = #13) THEN
                    BEGIN
                         { Transition from header to body }
                         IsHeader := FALSE;

                         { Check the header for MIME and Content-Type so }
                         { we can act on boundary headers while reading  }
                         { the message.                                  }
                         RFC_CompleteAdmin;
                    END ELSE
                    BEGIN
                         HeaderSearch_ScanLine (Line);
                         MsgsAddLineToNoEOL (Header_U, Line);
                         PrevHad13 := Line [Length (Line)] = #13;
                    END;
               END ELSE            { Isn't the header (NOT IsHeader) }
               BEGIN
                    { body }
                    RFC_PreCheckBodyLine (Line);
                    MsgsAddLineToNoEOL (Body, Line);
               END;
          END;

          {LogMessage (liGeneral, 'Final OFS='+Longint2String (MsgOfs));}

          IF (MsgOfs > MsgLen) THEN
          BEGIN
               LogMessage (liDebug, '<SOUP> MsgOfs > MsgLen ['+
                    longint2string (msgOfs)+'/'+longint2string(msglen));
          END;

          Msg.Ready_U := Mail;
          Soup_Pop3Process;
     
          MsgsEmptyKeepDeliveringUser;
     
          UpdateInfoNr (INFO_SoupIn_Bytes, MsgLen);
     END;

     { Update statistics }
     StatEntry_SOUPJob (stdInbound, PacketUserData.UUCPName, 'LOCAL',
                              FileSize (Fp.Bestand),
                              0 {NUm news},
                              RetrieveInfoNr (INFO_SoupIn_Mail) - OldMail);

     FBufferClose (Fp);

     { Erase the .MSG file }
     Assign (TempFP, Filename+'.MSG');
     {$I-} Erase (TempFP); IORes := IOResult; {$I+}
     IF (IORes <> 0) THEN
     BEGIN
          LogDiskIOError (IORes, 'SOUP: Unable to delete job '+Filename+'.MSG');
          Exit;
     END;

     SoupProcessMailFileBn := True; 
END;

{--------------------------------------------------------------------------}
{ SoupProcessMailFilemn                                                    }
{                                                                          }
{ Processes a file containing e-mail messages in the mn format.  After     }
{ delivering the messages, it returns TRUE if all went well, or FALSE if   }
{ an error occured.                                                        }
{                                                                          }
{ mn format is same as POP3, except seperator is always From               }
{                                                                          }
FUNCTION SoupProcessMailFilemn (Filename: STRING): BOOLEAN;
VAR
     Fp : FBufferType;

     Done: BOOLEAN;
     Line: STRING;
     PrevHad13: BOOLEAN;
     IORes: INTEGER;
     IsHeader: BOOLEAN;
     IsFirstMsg: BOOLEAN;

     TempFp: FILE;

     MsgLen: LONGINT;
     OldMail: LONGINT;

     {-------------------------------------------------------------------}
     { Soup_Pop3Process                                                  }
     {                                                                   }
     { Called instead of RFC_GoProcess to process an e-mail message      }
     { downloaded from a POP3 mailbox.  (When the new fields are in,     }
     { This will fill in the Recipient if none were found in the actual  }
     { message.                                                          }
     PROCEDURE Soup_Pop3Process;
     BEGIN
          (* --- HDRSRCH.PAS
          IF (Msg.FirstDest = NIL) THEN
          BEGIN
               IF (PacketUserData.SoupEnvelopeHdr <> '') THEN
                    LogMessage (liGeneral, '[Soup] POP3 envelope header not found!');

               LogMessage (liGeneral, '[Soup] Sending POP message to '+PacketUserData.SoupRecipient);
               Address_AddRFCRaw (PacketUserData.SoupRecipient, destTo, False, False);
          END;
          *)

          HeaderSearch_CheckNoRecipients (PacketUserData.SoupRecipient);
          Msg.Ready_U := Mail;

          RFC_GoProcess;
          MsgsEmptyKeepDeliveringUser;
     END;

     (* --- HDRSRCH.PAS
     PROCEDURE CheckEnvelopeHdr (Regel : STRING);
     BEGIN
          IF (Regel[Length (Regel)] = #13) THEN
               Delete (Regel,Length (Regel),1);

          IF Config.LogDebug THEN
               LogMessage (liTrivial,'[Soup] Found POP3 envelope header: '+Regel);

          Delete (Regel,1,Length (PacketUserData.SoupEnvelopeHdr));
          Regel:=DeleteFrontAndBackSpaces (Regel);

          Regel:=UseGetAddress (Regel);

          Address_AddRFCRaw (Regel,destTo,FALSE,FALSE);
     END;

     PROCEDURE SearchHeaderLine (Regel : STRING);

     VAR Lp      : BYTE;
         UpRegel : STRING;
         P,P2    : BYTE;

     BEGIN
          P:=Pos (#13,Regel);
          IF (P > 0) THEN
               Regel:=Copy (Regel,1,P-1);

          UpRegel:=UpCaseString (Regel);

          FOR Lp:=1 TO MaxSystemDomains DO
               IF (Config.Domains[Lp] <> '') THEN
               BEGIN
                    P:=Pos (UpCaseString (Config.Domains[Lp]),UpRegel);

                    IF (P > 0) THEN
                    BEGIN
                         { found a header that might match }
                         LogMessage (liDebug,'[Soup] Pop3Header: "'+Regel+'"');

                         IF NOT (Regel[1] IN [' ',#9]) THEN
                         BEGIN
                              Regel:=Regel+' ';
                              Delete (Regel,1,Pos (' ',Regel));
                         END;

                         Regel:=UseGetAddress (Regel);

                         { avoid finding otherdomain.com if we are domain.com }
                         UpRegel:=UpCaseString (Regel);
                         P:=Pos (UpCaseString (Config.Domains[Lp]),UpRegel);

                         { can be domain.com!user }
                         IF (P > 0) AND (Regel[P-1] IN ['.','@']) THEN
                         BEGIN
                              IF Config.LogDebug THEN
                                   LogMessage (liTrivial,'[Soup] Found in header: '+Regel);

                              Address_AddRFCRaw (Regel,destTo,{Note:}FALSE,{ByFilter:}FALSE);
                         END;
                    END;
               END; { if, for }
     END;
     *)

BEGIN
     OldMail := RetrieveInfoNr (INFO_SoupIn_Mail);

     SoupProcessMailFileMn := False;

     LogMessage (liGeneral, 'Processing SOUP job "'+Filename+'.MSG'+'"');
     IF (NOT FBufferOpen (Fp, Filename+'.MSG', 10000, 0)) THEN
     BEGIN
          FBufferClose (Fp);
          LogMessage (liFatal, '[SoupProcessMailFilemn] Cannot open file '+Filename+'.MSG');
          Exit;
     END;

     UpdateInfoNr (INFO_SoupIn_Jobs, 1);
     
     Done := False;

     { If the user didn't set a Recipient, set one ourself }

     IF PacketUserData.SoupRecipient = '' THEN
          PacketUserData.SoupRecipient := 'postmaster@'+Config.Domains[1];

     HeaderSearch_SetEnvelope (PacketUserData.SoupEnvelopeHdr);

     IsFirstMsg := TRUE;
     
     MsgLen := 0;

     { Received: by dijkline.wlink.nl (0.01 beta/WaterGate) }
     {           via SOUP; Sat, 10 Jul 93 00:06:50 +0100    }

     Line:='Received: by '+UseGetSystemFromName+' ('+ProgramShortName+' '+MainRevisionNr+')'+#13;
     RFC_AddTossedRegel (Line,PrevHad13);

     Line:='          via SOUP; '+UsenetArpaNetDate+#13;
     RFC_AddTossedRegel (Line,PrevHad13);


     WHILE FBReadLnLF (Fp, Line) DO
     BEGIN
          IF (NOT IsHeader) THEN
          BEGIN
               IF (Copy (Line, 1, 5) = 'From ') THEN
               BEGIN
                    IF (NOT IsFirstMsg) THEN
                    BEGIN
                         Msg.Ready_U := Mail;
                         SOUP_Pop3Process;
                    END
                    ELSE
                         IsFirstMsg := FALSE;

                    IsHeader := TRUE;
               END ELSE
               BEGIN
                    RFC_PreCheckBodyLine (Line);
                    MsgsAddLineToNoEOL (Body, Line);
               END;
          END;

          IF IsHeader THEN
          BEGIN
               IF (PrevHad13) AND (Line = #13) THEN
               BEGIN
                    { Transition from header to body }
                    IsHeader := FALSE;

                    { Check the header for MIME and Content-Type so }
                    { we can act on boundary headers while reading  }
                    { the message.                                  }
                    RFC_CompleteAdmin;
               END ELSE
               BEGIN
                    (*
                    IF (PacketUserData.SoupEnvelopeHdr <> '') THEN
                    BEGIN
                         IF CaselessStartMatch (Line, PacketUserData.SoupEnvelopeHdr) THEN
                              CheckEnvelopeHdr (Line);
                    END ELSE
                         SearchHeaderLine (Line);
                    *)

                    HeaderSearch_ScanLine (Line);
                    MsgsAddLineToNoEOL (Header_U, Line);
                    PrevHad13 := Line [Length (Line)] = #13;
               END;
          END;
          UpdateInfoNr (INFO_SoupIn_Bytes, Length (Line));
          MsgLen := 0;
     END;

     Msg.Ready_U := Mail;
     Soup_Pop3Process;

     MsgsEmptyKeepDeliveringUser;

     { Update statistics }
     StatEntry_SOUPJob (stdInbound, PacketUserData.UUCPName, 'LOCAL',
                              FileSize (Fp.Bestand),
                              0 {NUm news},
                              RetrieveInfoNr (INFO_SoupIn_Mail) - OldMail);

     FBufferClose (Fp);

     { Erase the .MSG file }
     Assign (TempFP, Filename+'.MSG');
     {$I-} Erase (TempFP); IORes := IOResult; {$I+}
     IF (IORes <> 0) THEN
     BEGIN
          LogDiskIOError (IORes, 'SOUP: Unable to delete job '+Filename+'.MSG');
          Exit;
     END;

     SoupProcessMailFilemn := True; 
END;

{--------------------------------------------------------------------------}
{ SoupProcessNewsFileun                                                    }
{                                                                          }
{ Processes a file containing newsgroup messages in the un format.  After  }
{ delivering the messages, it returns TRUE if all went well, or FALSE if   }
{ an error occured.                                                        }
{                                                                          }
{ The un format is basically identical to a UUCP job, except that the      }
{ rnews/rmail header doesn't have leading 0s.  :-)  Cut&pasted from UUCP   }
{ module.                                                                  }
{                                                                          }
FUNCTION SoupProcessNewsFileun (Filename: STRING) : BOOLEAN;
VAR
     Fp : FBufferType;

     Line: STRING;
     PrevHad13: BOOLEAN;
     IORes: INTEGER;

     TempFp: FILE;

     Ch: Byte;
     TempBytes : array [1..4] of byte;

     OldNews: LONGINT;

BEGIN
     OldNews := RetrieveInfoNr (INFO_SoupIn_News);

     SoupProcessNewsFileun := False;

     LogMessage (liGeneral, 'Processing SOUP job "'+Filename+'.MSG'+'"');
     IF (NOT FBufferOpen (Fp, Filename+'.MSG', 10000, 0)) THEN
     BEGIN
          FBufferClose (Fp);
          LogMessage (liFatal, '[SoupProcessNewsFileun] Cannot open file '+Filename+'.MSG');
          Exit;
     END;

     UpdateInfoNr (INFO_SoupIn_Jobs, 1);
     
     MsgsEmptyKeepDeliveringUser;
          
     RFC_AddWhereTo := Header_U;            
     RFC_TossWhat := twNews;

     PrevHad13 := False;

     { We have to read each message seperately? }

     WHILE FBReadLnLF (Fp, Line) DO
          RFC_AddTossedRegel (Line, PrevHad13);
          
     Msg.Ready_U := News;
     RFC_GoProcess;
     
     MsgsEmptyKeepDeliveringUser;
     
     UpdateInfoNr (INFO_SoupIn_Bytes, FileSize (Fp.Bestand));

     { Update statistics }
     StatEntry_SOUPJob (stdInbound, PacketUserData.UUCPName, 'LOCAL',
                              FileSize (Fp.Bestand),
                              RetrieveInfoNr (INFO_SoupIn_News) - OldNews,
                              0 {Num mail});

     FBufferClose (Fp);

     { Erase the .MSG file }
     Assign (TempFP, Filename+'.MSG');
     {$I-} Erase (TempFP); IORes := IOResult; {$I+}
     IF (IORes <> 0) THEN
     BEGIN
          LogDiskIOError (IORes, 'SOUP: Unable to delete job '+Filename+'.MSG');
          Exit;
     END;

     SoupProcessNewsFileun := True;   {## change to true}
END;

{--------------------------------------------------------------------------}
{ AddLineToAreasFile                                                       }
{                                                                          }
{ Used by soup toss.  If a toss fails for some reason, the job can be      }
{ queued for processing in the next run.  (For example, unsupported format }
{ errors.)  This also allows the operator to review the problem, and not   }
{ completely lose a message.                                               }
{                                                                          }
{ This procedure adds the specified line back into a temporary AREAS file. }
{ At the end of the SOUP processing, this AREAS file can be renamed to the }
{ 'real' one.                                                              }
{                                                                          }
PROCEDURE AddLineToAreasFile (Line: STRING);
VAR
     IORes: INTEGER;

BEGIN
     LogMessage (liGeneral, 'Re-queuing unprocessed SOUP job: '+Line);
     IF (NOT IsReplacementAreasFileOpen) THEN
     BEGIN
          Assign (ReplacementAreasFile, CorrectPath (PacketUserData.SoupInPath)+'AREAS.$$$');
          {$I-} Rewrite (ReplacementAreasFile);  IORes := IOResult; {$I+}
          IF (IORes <> 0) THEN
          BEGIN
               LogDiskIOError (IORes, 'SOUP: Unable to open temporary areas file AREAS.$$$');
               LogMessage (liFatal, '*.MSG file remains, but will not be processed');
               Exit;
          END;

          IsReplacementAreasFileOpen := True;
     END;

     IF (Line [Length (Line)] = #13) THEN
          Delete (Line, Length (Line), 1);

     Write (ReplacementAreasFile, Line+#10);
END;

{--------------------------------------------------------------------------}
{ ScanSoupIn                                                               }
{                                                                          }
{ This routine scans the SOUP-In path for the current user, and processes  }
{ any messages found in the 'AREAS' file there.  If a job cannot be        }
{ procesed for some reason, it is left int he AREAS file for the next      }
{ run.                                                                     }
{                                                                          }
PROCEDURE ScanSoupIn;
VAR
     Path      : STRING;
     AreasFile : FBufferType;
     OriginalLine,
     Line      : STRING;
     JobFile   : STRING [8];
     AreaName  : STRING [60];                     { Should be lots }
     Format    : STRING [3];
     I         : INTEGER;
     TempFP    : FILE;

BEGIN
     Line := 'Checking SOUP-In for '+PacketUserData.UUCPName;
     IF (PacketUserData.UsingWGSOUP) THEN
          Line := Line + ' (WGSOUP)';

     LogMessage (liGeneral, Line);

     Path := CorrectPath (PacketUserData.SoupInPath);

     IF (NOT FBufferOpen (AreasFile, Path+'AREAS', 5000, 5000)) THEN
     BEGIN
          { File not existing isn't an error! }
          IF (LastFBufferError <> 2) THEN
               LogMessage (liFatal, '   Failed to open '+Path+'AREAS');

          FBufferClose (AreasFile);
          Exit;
     END;

     WHILE (FBReadLnLF (AreasFile, Line)) DO
     BEGIN
          OriginalLine := Line;
          Line := DeleteFrontAndBackSpaces (Line);

          { Format is:
            JOBFILE<tab>AREANAME<tab>FORMAT<tab> OR <cr/lf> }

          { - FILE -------------- }
          I := Pos (#9, Line);
          IF (I = 0) THEN
          BEGIN
               LogMessage (liDebug, 'SOUP: Skipping (no tab 1)');
               Continue;
          END;
          JobFile := Copy (Line, 1, I-1);
          Delete (Line, 1, I);

          { - AREA -------------- }
          I := Pos (#9, Line);
          IF (I = 0) THEN
          BEGIN
               LogMessage (liDebug, 'SOUP: Skipping (no tab 2)');
               Continue;
          END;
          AreaName := Copy (Line, 1, I-1);
          Delete (Line, 1, I);

          { - AREA -------------- }
          { Stop on a tab, a CR, or an LF }
          I := Pos (#9#10#13, Line);
          IF (I = 0) THEN
          BEGIN
               { Try to get the rest of the line.. }
               { Chew off the trailing CR }
               IF (Line [Length (Line)] = #13) THEN
                    Delete (Line, Length (Line), 1);

               Line := DeleteFrontAndBackSpaces (Line);
               IF (Line = '') THEN
               BEGIN
                    LogMessage (liDebug, 'SOUP: Skipping (no delim 3)');
                    Continue;
               END;
               I := Length (Line) + 1;
          END;
          Format := Copy (Line, 1, I-1);

          { ========================================================= }
          {## FOR EMAIL,we have to support the mn format as well}

          IF (Format <> 'Bn') AND (Format <> 'bn') AND (Format <> 'un') AND (Format <> 'mn') THEN
          BEGIN
               LogMessage (liReport, 'SOUP: Unsupported format "'+Format+'"');
               AddLineToAreasFile (OriginalLine);
               Continue;
          END;

          { -------- NEWS (Bn, un) ----------------------------------- }
          IF (AreaName <> 'Email') THEN
          BEGIN
               IF (Format = 'Bn') THEN
               BEGIN
                    IF (NOT SoupProcessNewsFileBn (Path+JobFile)) THEN
                         AddLineToAreasFile (OriginalLine);
               END ELSE IF (Format = 'un') THEN
               BEGIN
                    IF (NOT SoupProcessNewsFileUn (Path+JobFile)) THEN
                         AddLineToAreasFile (OriginalLine);
               END;

               Continue;
          END ELSE BEGIN           { AreaName = 'Email' }
               IF (Format = 'Bn') OR (Format = 'bn') THEN
                    SoupProcessMailFileBn (Path+JobFile)
               ELSE IF (Format = 'mn') THEN
                    SoupProcessMailFilemn (Path+JobFile)
               ELSE BEGIN
                    LogMessage (liReport, '[SOUP] Unsupported e-mail format "'+Format+'"');
                    AddLineToAreasFile (OriginalLine);
               END;

               Continue;
          END;
          
          LogMessage (liReport, 'SOUP: Function not implemented');
          AddLineToAreasFile (OriginalLine);
     END;

     FBufferClose (AreasFile);

     { Erase the AREAS file }
     Assign (TempFP, Path+'AREAS');
     {$I-} Erase (TempFP); I := IOResult; {$I+}
     IF (I <> 0) THEN
     BEGIN
          LogDiskIOError (I, 'SOUP: Error deleting '+Path+'AREAS');
          LogMessage (liFatal, 'Errors may result next run due to missing *.MSG files');
          Exit;
     END;
     
     IF (IsReplacementAreasFileOpen) THEN
     BEGIN
          Close (ReplacementAreasFile);
          IsReplacementAreasFileOpen := False;

          Assign (TempFP, Path+'AREAS.$$$');
          {$I-} Rename (TempFP, Path+'AREAS'); I := IOResult; {$I+}
          IF (I <> 0) THEN
          BEGIN
               LogDiskIOError (I, 'SOUP: Error renaming '+Path+'AREAS.$$$ to AREAS');
               LogMessage (liFatal, '*.MSG file(s) remain, but will not be processed');
               Exit;
          END;
     END;
END;


{--------------------------------------------------------------------------}
{ SoupToss                                                                 }
{                                                                          }
{ This routine scans for inbound SOUP packets, and processes them.         }
{                                                                          }
PROCEDURE SoupToss;
VAR
     i : UserBaseRecordNrType;

BEGIN
     LogMessage (liTrivial, 'SOUP toss started on '+DateStamp);

     FOR I := 1 TO UserBaseRecCount DO
     BEGIN
          IF (NOT GlobalAbort) THEN
          BEGIN
               Msg.DeliveringUserRecNr := I;
               ReadUserBaseRecord (I, PacketUserData);

               IF (NOT PacketUserData.Deleted) AND (PacketUserData.System = _SOUP) THEN
               BEGIN
                    UserDataRecNr := I;                               { for MsgsExport }
                    AreaCreatorUserBaseRecNr := I;
                    PacketUserData.UUCPName := UpCaseString (PacketUserData.UUCPName);

                    UpdateAction ('Checking SOUP-In for "'+PacketUserData.UUCPName+'"');

                    ScanSoupIn;
               END;
          END; { IF NOT global abort }
     END; { for }

     LogMessage (liTrivial, 'SOUP toss finished');
END;

BEGIN
     IsReplacementAreasFileOpen := False;
END.

