FTP mailer

This commit is contained in:
mysticbbs 2013-09-22 01:32:42 -04:00
parent a31d6f36ff
commit 486c01f2f1
12 changed files with 340 additions and 88 deletions

View File

@ -1,22 +1,86 @@
========
ABOUT
========
This archive contains the source code for Mystic BBS software.
Mystic BBS is Copyright 1997-Current year by James Coyle.
Mystic BBS is currently compiled exclusively using Free Pascal
compiler (www.freepascal.org) the current release being 2.6.0.
Mystic BBS is released under GPL Version 3 licensing which is
included in the archive. An information header is prefixed on
each source file that compiles to an executable.
Current build options used with Free Pascal are as follows:
=========================
COMPILING MYSTIC BBS
=========================
fpc -CX -XX -Xs -O3 -B -OpPENTIUM3 -OoREGVAR -OoSTACKFRAME -OoPEEPHOLE -OoASMCSE -WN <source file>
Mystic BBS is currently compiled exclusively using Free Pascal
compiler (www.freepascal.org) the recommended release being 2.6.2.
(-WN is specific to Windows so it should be omitted on other platforms)
Current build options used with Free Pascal are below, contained in example
build.bat and build.sh (for Windows and Linux respectively). These use the
current recommend compiler options along with Free Pascal's Whole Program
Optimization. Each file is called as "build <executable>" so:
Mystic BBS is compiled to require a Pentium 3 or better processor (SSE instruction set) which
means that it should run on any computer built in the late 90s up to current day.
Windows: build mystic <- Compiles mystic.exe
Linux: sh build.sh mystic <- Compiles mystic binary
=========================
BUILD.BAT (WINDOWS)
=========================
@echo off
REM Purpose: Compile an EXE using whole program optimization
REM
REM To use this, change the \dev\mdl to point to the path where Mystic's MDL
REM source code is found. If you compile with ALL code in the same folder, then
REM change this to your folder where all source code is located. This build.bat
REM is intended to be ran from the same directory as Mystic's source code.
REM
SET MDLPATH=d:\dev\mdl
del *.wpo
fpc -Fi%MDLPATH% -Fu%MDLPATH% -CX -XX -Xs- -O3 -B -OpPENTIUM3 -OoREGVAR -OoSTACKFRAME -OoPEEPHOLE -OoASMCSE -WN -FW%1-1.wpo -OWall %1
fpc -Fi%MDLPATH% -Fu%MDLPATH% -CX -XX -Xs- -O3 -B -OpPENTIUM3 -OoREGVAR -OoSTACKFRAME -OoPEEPHOLE -OoASMCSE -WN -Fw%1-1.wpo -FW%1-2.wpo -OWall -Owall %1
fpc -Fi%MDLPATH% -Fu%MDLPATH% -CX -XX -Xs -O3 -B -OpPENTIUM3 -OoREGVAR -OoSTACKFRAME -OoPEEPHOLE -OoASMCSE -WN -Fw%1-2.wpo -Owall %1
=============================
BUILD.SH (LINUX 32-BIT)
=============================
# Purpose: Compile an executable using whole program optimization
#
# To use this, change the /mystic variable below to the path where Mystic's MDL
# soure code is found. If you compile with ALL code in the same folder, then
# change this to your folder where all the source code is located. This build
# script is intended to be ran from the same directory as Mystic's source code.
export MDLPATH=/mystic
rm *.wpo
fpc -Fi$MDLPATH -Fu$MDLPATH -CX -XX -Xs- -O3 -B -OpPENTIUM3 -OoREGVAR -OoSTACKFRAME -OoPEEPHOLE -OoASMCSE -FW$1-1.wpo -OWall $1
fpc -Fi$MDLPATH -Fu$MDLPATH -CX -XX -Xs- -O3 -B -OpPENTIUM3 -OoREGVAR -OoSTACKFRAME -OoPEEPHOLE -OoASMCSE -Fw$1-1.wpo -FW$1-2.wpo -OWall -Owall $1
fpc -Fi$MDLPATH -Fu$MDLPATH -CX -XX -Xs -O3 -B -OpPENTIUM3 -OoREGVAR -OoSTACKFRAME -OoPEEPHOLE -OoASMCSE -Fw$1-2.wpo -Owall $1
===========================
AUTOMATED COMPILATION
===========================
While a specific automated compilation script is not provided in this README, the
contents should provide enough to make this happen. The basic structure would be:
! CREATE A BACKUP OF YOUR CURRENT MYSTIC SYSTEM
1. Call GIT to synch against the latest repository for the latest source code
2. Call BUILD script for each of the Mystic executables
3. Copy newly compiled Mystic executables to appropriate location in Mystic folder
============================
ADDITIONAL INFORMATION
============================
Mystic BBS project can be found at mysticbbs.sourceforge.net
@ -27,10 +91,8 @@ encouraged that fixes and additions be coordinated with the current authors.
!!! WARNING!!!
The current code here reflects the latest 1.10 alphas and is not yet compatible with 1.09.
The current code here reflects the latest 1.10 alphas and is not compatible with 1.09.
With the 1.10 final/stable release we will be officially annoucing Mystic as a GPL program and
at that time we will branch off to a current stable and development code base as well as release
an upgrade package to get everyone on the same page with both binary and source distributions.
If you are not running at least 1.10 Alpha 15 than this code will not run for you.

View File

@ -159,8 +159,27 @@ Begin
Box.Close;
End;
1 : Begin
Box.Header := ' FTP ';
Box.Open (15, 7, 65, 16);
VerticalLine (32, 9, 14);
Form.AddStr ('H', ' Hostname' , 22, 9, 34, 9, 10, 30, 60, @Node.ftpOutHost, Topic);
Form.AddStr ('L', ' Login' , 25, 10, 34, 10, 7, 20, 20, @Node.ftpOutLogin, Topic);
Form.AddMask ('P', ' Password' , 22, 11, 34, 11, 10, 20, 20, @Node.ftpOutPass, Topic);
Form.AddBol ('A', ' Passive' , 23, 12, 34, 12, 9, 3, @Node.ftpPassive, Topic);
Form.AddStr ('O', ' Out Directory', 17, 13, 34, 13, 15, 30, 60, @Node.ftpOutDir, Topic);
Form.AddStr ('I', ' In Directory' , 18, 14, 34, 14, 14, 30, 60, @Node.ftpInDir, Topic);
Form.Execute;
Box.Close;
End;
2 : Begin
Box.Header := ' DIRECTORY ';
Box.Header := ' Directory ';
Box.Open (15, 8, 64, 13);

View File

@ -1,5 +1,26 @@
Program FidoPoll;
// ====================================================================
// Mystic BBS Software Copyright 1997-2013 By James Coyle
// ====================================================================
//
// This file is part of Mystic BBS.
//
// Mystic BBS is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Mystic BBS is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Mystic BBS. If not, see <http://www.gnu.org/licenses/>.
//
// ====================================================================
{$I M_OPS.PAS}
Uses
@ -10,6 +31,7 @@ Uses
m_Strings,
m_IO_Sockets,
m_Protocol_Queue,
m_tcp_Client_FTP,
BBS_Records,
BBS_DataBase,
MIS_Client_BINKP;
@ -42,26 +64,146 @@ Begin
End;
End;
Function PollNodeDirectory (OnlyNew: Boolean; Var Queue: TProtocolQueue; Var EchoNode: RecEchoMailNode) : Boolean;
Function FindBundleName (Str: String) : String;
Var
FN : String;
Ext : String;
Last : Byte;
Begin
Result := False;
FN := JustFileName(Str);
Ext := strLower(JustFileExt(Str));
Last := Byte(Ext[Length(Ext)]);
If Not (Last in [48..57, 97..122]) Then Last := 48;
Repeat
Result := FN + '.' + Ext;
Result[Length(Result)] := Char(Last);
If Not FileExist(Result) Then Break;
Inc (Last);
If Last = 58 Then Last := 97;
If Last = 123 Then Exit; // no 0-9,a-z could be generated
Until False;
End;
Function PollNodeFTP (OnlyNew: Boolean; Var Queue: TProtocolQueue; Var EchoNode: RecEchoMailNode) : Boolean;
Var
FTP : TFTPClient;
Count : LongInt;
Begin
Result := False;
Queue.Clear;
PrintStatus(NIL, 1, 'Scanning ' + Addr2Str(EchoNode.Address));
PrintStatus (NIL, 1, 'Scanning ' + Addr2Str(EchoNode.Address));
QueueByNode (Queue, True, EchoNode);
PrintStatus (NIL, 1, 'Queued ' + strI2S(Queue.QSize) + ' files (' + strI2S(Queue.QFSize) + ' bytes) to ' + Addr2Str(EchoNode.Address));
If OnlyNew and (Queue.QSize = 0) Then Exit;
PrintStatus (NIL, 1, 'Polling FTP node ' + Addr2Str(EchoNode.Address));
FTP := TFTPClient.Create(bbsCfg.iNetInterface);
If FTP.OpenConnection(EchoNode.ftpOutHost) Then Begin
PrintStatus (NIL, 1, 'Connected');
If FTP.Authenticate(EchoNode.ftpOutLogin, EchoNode.ftpOutPass) Then Begin
If FTP.GetDirectoryList(EchoNode.ftpPassive, True, EchoNode.ftpInDir) Then Begin
For Count := 1 to FTP.ResponseData.Count Do Begin
PrintStatus (NIL, 1, 'Receiving ' + FTP.ResponseData.Strings[Count - 1]);
If FTP.GetFile (EchoNode.ftpPassive, bbsCfg.InboundPath + FTP.ResponseData.Strings[Count - 1]) = ftpResOK Then Begin
If FTP.SendCommand('DELE ' + FTP.ResponseData.Strings[Count - 1]) <> 250 Then
FileErase(bbsCfg.InboundPath + FTP.ResponseData.Strings[Count - 1])
Else
PrintStatus (NIL, 1, 'Unable to delete from server ' + FTP.ResponseData.Strings[Count - 1]);
End Else
PrintStatus (NIL, 1, 'Failed');
End;
End Else
PrintStatus (NIL, 1, 'Unable to list ' + EchoNode.ftpInDir);
If Queue.QSize > 0 Then Begin
If FTP.ChangeDirectory(EchoNode.ftpOutDir) Then Begin
For Count := 1 to Queue.QSize Do Begin
PrintStatus (NIL, 1, 'Sending ' + Queue.QData[Count]^.FileNew);
If FTP.SendFile(EchoNode.ftpPassive, Queue.QData[Count]^.FilePath + Queue.QData[Count]^.FileName, Queue.QData[Count]^.FileNew) = ftpResOK Then Begin
FileErase (Queue.QData[Count]^.FilePath + Queue.QData[Count]^.FileName);
RemoveFilesFromFLO (GetFTNOutPath(EchoNode), TempPath, Queue.QData[Count]^.FilePath + Queue.QData[Count]^.FileName);
End Else
PrintStatus (NIL, 1, 'Failed');
End;
End Else
PrintStatus (NIL, 1, 'Unable to change to ' + echoNode.ftpOutDir);
End;
End Else
PrintStatus (NIL, 1, 'Unable to authenticate');
End Else
PrintStatus (NIL, 1, 'Unable to connect');
PrintStatus (NIL, 1, 'Session complete');
FTP.Free;
End;
Function PollNodeDirectory (OnlyNew: Boolean; Var Queue: TProtocolQueue; Var EchoNode: RecEchoMailNode) : Boolean;
Var
Count : LongInt;
DirInfo : SearchRec;
PKTName : String;
NewName : String;
OutPath : String;
Begin
Result := False;
Queue.Clear;
PrintStatus (NIL, 1, 'Scanning ' + Addr2Str(EchoNode.Address));
QueueByNode (Queue, False, EchoNode);
PrintStatus(NIL, 1, 'Queued ' + strI2S(Queue.QSize) + ' files (' + strI2S(Queue.QFSize) + ' bytes) to ' + Addr2Str(EchoNode.Address));
If OnlyNew and (Queue.QSize = 0) Then Exit;
PrintStatus(NIL, 1, 'Polling FTP node ' + Addr2Str(EchoNode.Address));
PrintStatus(NIL, 1, 'Polling DIRECTORY node ' + Addr2Str(EchoNode.Address));
OutPath := GetFTNOutPath(EchoNode);
For Count := 1 to Queue.QSize Do Begin
PKTName := Queue.QData[Count]^.FilePath + Queue.QData[Count]^.FileName;
NewName := FindBundleName(EchoNode.DirInDir + Queue.QData[Count]^.FileNew);
PrintStatus (NIL, 1, 'Move ' + PKTName + ' to ' + NewName);
If (Not FileExist(NewName)) And FileReName(PKTName, NewName) Then
RemoveFilesFromFLO (OutPath, TempPath, PKTName)
Else
PrintStatus (NIL, 1, 'Failed to move to ' + NewName);
End;
FindFirst (EchoNode.DirOutDir + '*', AnyFile, DirInfo);
While DosError = 0 Do Begin
If DirInfo.Attr And Directory = 0 Then Begin
PrintStatus (NIL, 1, 'Move ' + EchoNode.DirOutDir + DirInfo.Name + ' to ' + bbsCfg.InboundPath);
If (Not FileExist(bbsCfg.InboundPath + DirInfo.Name)) and (Not FileReName(EchoNode.DirOutDir + DirInfo.Name, bbsCfg.InboundPath + DirInfo.Name)) Then
PrintStatus (NIL, 1, 'Failed to move to ' + EchoNode.DirOutDir + DirInfo.Name);
End;
FindNext (DirInfo);
End;
FindClose (DirInfo);
End;
Function PollNodeBINKP (OnlyNew: Boolean; Var Queue: TProtocolQueue; Var EchoNode: RecEchoMailNode) : Boolean;
@ -220,9 +362,8 @@ Begin
End;
If ParamCount = 0 Then Begin
WriteLn ('This will likely be a temporary program which will be fused into');
WriteLn ('either MIS or MUTIL in the future (or both). Note only BINKP is');
WriteLn ('currently supported. FTN via FTP may be included in the future');
WriteLn ('This program will send and retreive echomail packets for configured');
WriteLn ('echomail nodes using any of BINKP, FTP, or Directory-based transmission');
WriteLn;
WriteLn ('FIDOPOLL SEND - Only send/poll if node has new outbound messages');
WriteLn ('FIDOPOLL FORCED - Poll/send to all configured/activenodes');

View File

@ -122,7 +122,6 @@ Type
Constructor Create (O: Pointer; Var C: TIOSocket; Var FL: TProtocolQueue; IsCli: Boolean; TOV: Word);
Destructor Destroy; Override;
Procedure RemoveFilesFromFLO (FN: String);
Function AuthenticateNode (AddrList: String) : Boolean;
Function EscapeFileName (Str: String) : String;
Function RestoreFileName (Str: String) : String;
@ -138,8 +137,10 @@ Function CreateBINKP (Owner: TServerManager; Config: RecConfig; ND: TNodeData; C
// these need to be moved to a generic area
Function GetFTNOutPath (EchoNode: RecEchoMailNode) : String;
Procedure QueueByNode (Var Queue: TProtocolQueue; SkipHold: Boolean; EchoNode: RecEchoMailNode);
Function GetFTNFlowName (Dest: RecEchoMailAddr) : String;
Function GetFTNOutPath (EchoNode: RecEchoMailNode) : String;
Procedure QueueByNode (Var Queue: TProtocolQueue; SkipHold: Boolean; EchoNode: RecEchoMailNode);
Procedure RemoveFilesFromFLO (OutPath, TP, FN: String);
Type
TBINKPServer = Class(TServerClient)
@ -273,66 +274,6 @@ Begin
Close (EchoFile);
End;
Procedure TBinkP.RemoveFilesFromFLO (FN: String);
Var
Str : String;
DirInfo : SearchRec;
OrigFile : Text;
NewFile : Text;
Matched : Boolean;
Begin
// Scan all FLO files in outbound directory, and PRUNE them all.
// possible issue if multiple BINKP connections are going. we need
// to revamp this to perform appropriate file locking and waiting.
// also should be moved to mis_common since FTN-FTP will also perform
// the same procedure.
// could also perform a critical section as a cheesy way to do this?
FindFirst (SetOutPath + '*.?lo', AnyFile, DirInfo);
While DosError = 0 Do Begin
FileRename (SetOutPath + DirInfo.Name, TempPath + DirInfo.Name);
Assign (NewFile, SetOutPath + DirInfo.Name);
ReWrite (NewFile);
Append (NewFile);
Assign (OrigFile, TempPath + DirInfo.Name);
Reset (OrigFile);
While Not Eof (OrigFile) Do Begin
ReadLn (OrigFile, Str);
If (Str = '') or (Str[1] = '!') Then
WriteLn (NewFile, Str)
Else Begin
Case Str[1] of
'~',
'#',
'^' : Matched := strUpper(FN) = strUpper(Copy(Str, 2, 255));
Else
Matched := (strUpper(FN) = strUpper(Str));
End;
If Not Matched Then
WriteLn (NewFile, Str);
End;
End;
Close (NewFile);
Close (OrigFile);
Erase (OrigFile);
If FileByteSize(SetOutPath + DirInfo.Name) = 0 Then
FileErase(SetOutPath + DirInfo.Name);
FindNext (DirInfo);
End;
FindClose (DirInfo);
End;
Function TBinkP.GetDataStr : String;
Var
SZ : Byte;
@ -725,7 +666,7 @@ Begin
FileList.QData[FileList.QPos]^.Status := QueueSuccess;
FileErase (FileList.QData[FileList.QPos]^.FilePath + FileList.QData[FileList.QPos]^.FileName);
RemoveFilesFromFLO (FileList.QData[FileList.QPos]^.FilePath + FileList.QData[FileList.QPos]^.FileName);
RemoveFilesFromFLO (SetOutPath, TempPath, FileList.QData[FileList.QPos]^.FilePath + FileList.QData[FileList.QPos]^.FileName);
HaveHeader := False;
NeedHeader := True;
@ -832,6 +773,65 @@ Begin;
Result := Result + strI2H((EchoNode.Address.Net SHL 16) OR EchoNode.Address.Node, 8) + '.pnt' + PathChar;
End;
Procedure RemoveFilesFromFLO (OutPath, TP, FN: String);
Var
Str : String;
DirInfo : SearchRec;
OrigFile : Text;
NewFile : Text;
Matched : Boolean;
Begin
// Scan all FLO files in outbound directory, and PRUNE them all.
// This should probably be changed to honor and create BSY files and
// instead of pruning ALL FLO files it should prune a single file.
// Need to review the code and figure out why I did it this way to
// begin with.
FindFirst (OutPath + '*.?lo', AnyFile, DirInfo);
While DosError = 0 Do Begin
FileRename (OutPath + DirInfo.Name, TP + DirInfo.Name);
Assign (NewFile, OutPath + DirInfo.Name);
ReWrite (NewFile);
Append (NewFile);
Assign (OrigFile, TP + DirInfo.Name);
Reset (OrigFile);
While Not Eof (OrigFile) Do Begin
ReadLn (OrigFile, Str);
If (Str = '') or (Str[1] = '!') Then
WriteLn (NewFile, Str)
Else Begin
Case Str[1] of
'~',
'#',
'^' : Matched := strUpper(FN) = strUpper(Copy(Str, 2, 255));
Else
Matched := (strUpper(FN) = strUpper(Str));
End;
If Not Matched Then
WriteLn (NewFile, Str);
End;
End;
Close (NewFile);
Close (OrigFile);
Erase (OrigFile);
If FileByteSize(OutPath + DirInfo.Name) = 0 Then
FileErase(OutPath + DirInfo.Name);
FindNext (DirInfo);
End;
FindClose (DirInfo);
End;
Procedure QueueByNode (Var Queue: TProtocolQueue; SkipHold: Boolean; EchoNode: RecEchoMailNode);
Var
DirInfo : SearchRec;
@ -855,7 +855,7 @@ Begin
Continue;
End;
If Not ((strUpper(JustFileName(DirInfo.Name)) = strUpper(GetFTNFlowName(EchoNode.Address))) and EchoNode.Active and (EchoNode.ProtType = 0)) Then Begin
If Not ((strUpper(JustFileName(DirInfo.Name)) = strUpper(GetFTNFlowName(EchoNode.Address))) and EchoNode.Active) Then Begin
FindNext (DirInfo);
Continue;
@ -895,7 +895,7 @@ Begin
Continue;
End;
If Not ((strUpper(JustFileName(DirInfo.Name)) = strUpper(GetFTNFlowName(EchoNode.Address))) and EchoNode.Active and (EchoNode.ProtType = 0)) Then Begin
If Not ((strUpper(JustFileName(DirInfo.Name)) = strUpper(GetFTNFlowName(EchoNode.Address))) and EchoNode.Active) Then Begin
FindNext (DirInfo);
Continue;

View File

@ -736,6 +736,9 @@ Begin
OpenDataSession;
// if qwlbyFTP.acs then
DataSocket.WriteLine(bbsCfg.QwkBBSID + '.qwk');
DirFile := TFileBuffer.Create(FileBufSize);
If DirFile.OpenStream (bbsCfg.DataPath + TempBase.FileName + '.dir', SizeOf(RecFileList), fmOpenCreate, fmRWDN) Then Begin

View File

@ -206,6 +206,9 @@ Var
MBase.DefQScan := INI.ReadInteger(Header_ECHOIMPORT, 'qwk_scan', 1);
MBase.NetAddr := 1;
MBase.FileName := strReplace(MBase.FileName, '/', '_');
MBase.FileName := strReplace(MBase.FileName, '\', '_');
For Count := 1 to 30 Do
If bbsCfg.NetAddress[Count].Zone = PKT.PKTHeader.DestZone Then Begin
MBase.NetAddr := Count;

View File

@ -70,6 +70,9 @@ Begin
MBase.DefQScan := INI.ReadInteger(Header_IMPORTMB, 'qwk_scan', 1);
MBase.NetAddr := 1;
MBase.FileName := strReplace(MBase.FileName, '/', '_');
MBase.FileName := strReplace(MBase.FileName, '\', '_');
For Count := 1 to 30 Do
If strAddr2Str(bbsCfg.NetAddress[Count]) = INI.ReadString(Header_IMPORTNA, 'netaddress', '') Then Begin
MBase.NetAddr := Count;

View File

@ -51,6 +51,12 @@ Begin
TagName := strStripLow(strWordGet(1, Str, ' '));
BaseName := strStripLow(strStripB(Copy(Str, Pos(' ', Str), 255), ' '));
// TagName := strReplace(TagName, '/', '_');
// TagName := strReplace(TagName, '\', '_');
// If Pos(TagName, '/') > 0 Then Continue;
// If Pos(TagName, '\') > 0 Then Continue;
ProcessStatus (BaseName, False);
If Not IsDupeMBase(TagName) Then Begin
@ -86,6 +92,9 @@ Begin
MBase.DefQScan := strS2I(INI.ReadString(Header_IMPORTNA, 'qwk_scan', '1'));
MBase.NetAddr := 1;
MBase.FileName := strReplace(MBase.FileName, '/', '_');
MBase.FileName := strReplace(MBase.FileName, '\', '_');
For Count := 1 to 30 Do
If strAddr2Str(bbsCfg.NetAddress[Count]) = INI.ReadString(Header_IMPORTNA, 'netaddress', '') Then Begin
MBase.NetAddr := Count;

View File

@ -282,7 +282,7 @@ Begin
Assign (Session.ThemeFile, bbsCfg.DataPath + 'theme.dat');
{$I-} Reset (Session.ThemeFile); {$I+}
If IoResult <> 0 Then Begin
Console.WriteLine ('ERROR: No theme configuration.');
Console.WriteLine ('ERROR: No theme configuration');
DisposeClasses;
Halt(1);
End;

View File

@ -61,7 +61,7 @@ Begin
If QWK.TotalMessages > 0 Then Begin
WriteLn (' - Sending reply packet');
Case FTP.SendFile(QwkNet.UsePassive, TempPath + QwkNet.PacketID + '.rep') of
Case FTP.SendFile(QwkNet.UsePassive, TempPath + QwkNet.PacketID + '.rep', QwkNet.PacketID) of
ftpResOK : SentFile := True;
ftpResBadData : WriteLn (' - Unable to open data connection');
Else

View File

@ -108,7 +108,7 @@ Type
ArcType : String[4];
MailType : Byte; // 0=BINKP,1=FTP,2=Dir
binkHost : String[60];
UNUSED1 : Byte;
ftpPassive : Boolean;
ProtType : Byte;
binkTimeout : Word;
binkBlock : Word;

View File

@ -3815,4 +3815,16 @@
! Netmail messages will no longer export from MUTIL if their destination
address is one of your configured AKA addresses.
+ Mystic echomail nodes can now be configured as a "Directory" session type,
which means that Mystic (FIDOPOLL) will send bundles to/from locally
configured inbound and outbound directories instead of using BINKP or FTP.
! Mystic's FTP server was not sending the QWK packet name in directory
listings when the NLST command was used (instead of LIST).
+ When importing a FIDONET.NA format file, or when creating message bases
during echomail import OR when using the ImportMsgBase function, MUTIL
will now change any filenames (calculated from ECHOTAG) to replace both
\ and / with a _ character.
<ALPHA 38 RELEASED>