QWK and REP by FTP complete

This commit is contained in:
mysticbbs 2013-09-01 06:33:30 -04:00
parent 641bac34ef
commit 9ee5efdf96
4 changed files with 466 additions and 51 deletions

View File

@ -25,13 +25,16 @@ Const
Function GetBaseConfiguration (UseEnv: Boolean; Var TempCfg: RecConfig) : Byte; Function GetBaseConfiguration (UseEnv: Boolean; Var TempCfg: RecConfig) : Byte;
Function PutBaseConfiguration (Var TempCfg: RecConfig) : Boolean; Function PutBaseConfiguration (Var TempCfg: RecConfig) : Boolean;
Function ShellDOS (ExecPath: String; Command: String) : LongInt; Function ShellDOS (ExecPath: String; Command: String) : LongInt;
Function Addr2Str (Addr : RecEchoMailAddr) : String;
// MESSAGE BASE // MESSAGE BASE
Function MBaseOpenCreate (Var Msg: PMsgBaseABS; Var Area: RecMessageBase; TP: String) : Boolean; Function MBaseOpenCreate (Var Msg: PMsgBaseABS; Var Area: RecMessageBase; TP: String) : Boolean;
Function GetOriginLine (Var mArea: RecMessageBase) : String;
Function GetMBaseByIndex (Num: LongInt; Var TempBase: RecMessageBase) : Boolean; Function GetMBaseByIndex (Num: LongInt; Var TempBase: RecMessageBase) : Boolean;
Procedure GetMessageScan (UN: Cardinal; TempBase: RecMessageBase; Var TempScan: MScanRec); Procedure GetMessageScan (UN: Cardinal; TempBase: RecMessageBase; Var TempScan: MScanRec);
Procedure PutMessageScan (UN: Cardinal; TempBase: RecMessageBase; TempScan: MScanRec); Procedure PutMessageScan (UN: Cardinal; TempBase: RecMessageBase; TempScan: MScanRec);
Procedure MBaseAssignData (Var User: RecUser; Var Msg: PMsgBaseABS; Var TempBase: RecMessageBase);
// FILE BASE // FILE BASE
@ -47,8 +50,87 @@ Implementation
Uses Uses
DOS, DOS,
m_FileIO, m_FileIO,
m_DateTime,
m_Strings; m_Strings;
Function Addr2Str (Addr : RecEchoMailAddr) : String;
Var
Temp : String[20];
Begin
Temp := strI2S(Addr.Zone) + ':' + strI2S(Addr.Net) + '/' +
strI2S(Addr.Node);
If Addr.Point <> 0 Then Temp := Temp + '.' + strI2S(Addr.Point);
Result := Temp;
End;
Function GetOriginLine (Var mArea: RecMessageBase) : String;
Var
Loc : Byte;
FN : String;
TF : Text;
Buf : Array[1..2048] of Char;
Str : String;
Count : LongInt;
Pick : LongInt;
Begin
Result := '';
Loc := Pos('@RANDOM=', strUpper(mArea.Origin));
If Loc > 0 Then Begin
FN := strStripB(Copy(mArea.Origin, Loc + 8, 255), ' ');
If Pos(PathChar, FN) = 0 Then FN := bbsCfg.DataPath + FN;
FileMode := 66;
Assign (TF, FN);
SetTextBuf (TF, Buf, SizeOf(Buf));
{$I-} Reset (TF); {$I+}
If IoResult <> 0 Then Exit;
Count := 0;
While Not Eof(TF) Do Begin
ReadLn (TF, Str);
If strStripB(Str, ' ') = '' Then Continue;
Inc (Count);
End;
If Count = 0 Then Begin
Close (TF);
Exit;
End;
Pick := Random(Count) + 1;
Reset (TF);
Count := 0;
While Not Eof(TF) Do Begin
ReadLn (TF, Str);
If strStripB(Str, ' ') = '' Then Continue;
Inc (Count);
If Count = Pick Then Begin
Result := Str;
Break;
End;
End;
Close (TF);
End Else
Result := mArea.Origin;
End;
Function GetBaseConfiguration (UseEnv: Boolean; Var TempCfg: RecConfig) : Byte; Function GetBaseConfiguration (UseEnv: Boolean; Var TempCfg: RecConfig) : Byte;
Var Var
TempFile : File; TempFile : File;
@ -220,6 +302,43 @@ Begin
Result := True; Result := True;
End; End;
Procedure MBaseAssignData (Var User: RecUser; Var Msg: PMsgBaseABS; Var TempBase: RecMessageBase);
Var
SemFile : Text;
Begin
Msg^.StartNewMsg;
If TempBase.Flags And MBRealNames <> 0 Then
Msg^.SetFrom(User.RealName)
Else
Msg^.SetFrom(User.Handle);
Msg^.SetLocal (True);
If TempBase.NetType > 0 Then Begin
If TempBase.NetType = 3 Then
Msg^.SetMailType(mmtNetMail)
Else
Msg^.SetMailType(mmtEchoMail);
Msg^.SetOrig(bbsCfg.NetAddress[TempBase.NetAddr]);
Case TempBase.NetType of
1 : Assign (SemFile, bbsCfg.SemaPath + fn_SemFileEcho);
2 : Assign (SemFile, bbsCfg.SemaPath + fn_SemFileNews);
3 : Assign (SemFile, bbsCfg.SemaPath + fn_SemFileNet);
End;
ReWrite (SemFile);
Close (SemFile);
End Else
Msg^.SetMailType(mmtNormal);
Msg^.SetPriv (TempBase.Flags and MBPrivate <> 0);
Msg^.SetDate (DateDos2Str(CurDateDos, 1));
Msg^.SetTime (TimeDos2Str(CurDateDos, 0));
End;
Function GetTotalFiles (Var TempBase: RecFileBase) : LongInt; Function GetTotalFiles (Var TempBase: RecFileBase) : LongInt;
Begin Begin
Result := 0; Result := 0;

View File

@ -13,7 +13,8 @@ Uses
BBS_MsgBase_Squish; BBS_MsgBase_Squish;
Const Const
QWK_EOL = #13#10; QWK_EOL = #13#10;
QWK_CONTROL = 'MYSTICQWK';
Type Type
BSingle = Array [0..3] of Byte; BSingle = Array [0..3] of Byte;
@ -140,7 +141,7 @@ Begin
Write (TempFile, 'DOOR = ' + mysSoftwareID + QWK_EOL); Write (TempFile, 'DOOR = ' + mysSoftwareID + QWK_EOL);
Write (TempFile, 'VERSION = ' + mysVersion + QWK_EOL); Write (TempFile, 'VERSION = ' + mysVersion + QWK_EOL);
Write (TempFile, 'SYSTEM = ' + mysSoftwareID + ' ' + mysVersion + QWK_EOL); Write (TempFile, 'SYSTEM = ' + mysSoftwareID + ' ' + mysVersion + QWK_EOL);
Write (TempFile, 'CONTROLNAME = MYSTICQWK' + QWK_EOL); Write (TempFile, 'CONTROLNAME = ' + QWK_CONTROL + QWK_EOL);
Write (TempFile, 'CONTROLTYPE = ADD' + QWK_EOL); Write (TempFile, 'CONTROLTYPE = ADD' + QWK_EOL);
Write (TempFile, 'CONTROLTYPE = DROP' + QWK_EOL); Write (TempFile, 'CONTROLTYPE = DROP' + QWK_EOL);
Close (TempFile); Close (TempFile);
@ -286,7 +287,7 @@ Begin
While MsgBase^.SeekFound Do Begin While MsgBase^.SeekFound Do Begin
If Not IsNetworked Then If Not IsNetworked Then
If ((bbsCfg.QwkMaxBase > 0) and (MsgAdded = bbsCfg.QwkMaxBase)) or If ((bbsCfg.QwkMaxBase > 0) and (MsgAdded = bbsCfg.QwkMaxBase)) or
((bbsCfg.QwkMaxPacket > 0) and (TotalMessages = bbsCfg.QwkMaxPacket)) Then Break; ((bbsCfg.QwkMaxPacket > 0) and (TotalMessages = bbsCfg.QwkMaxPacket)) Then Break;
MsgBase^.MsgStartUp; MsgBase^.MsgStartUp;
@ -453,13 +454,13 @@ Begin
If HasAccess(Self, MBase.ReadACS) Then Begin If HasAccess(Self, MBase.ReadACS) Then Begin
GetMessageScan (UserNumber, MBase, MScan); GetMessageScan (UserNumber, MBase, MScan);
If MScan.QwkScan > 0 Then Begin If MScan.QwkScan > 0 Then Begin
Inc (TotalBases); Inc (TotalBases);
QwkLR.Base := FilePos(MBaseFile); QwkLR.Base := FilePos(MBaseFile);
QwkLR.Pos := WriteMSGDAT; QwkLR.Pos := WriteMSGDAT;
Write (QwkLRFile, QwkLR); Write (QwkLRFile, QwkLR);
End; End;
@ -481,8 +482,190 @@ Begin
End; End;
Function TQWKEngine.ProcessReply : Boolean; Function TQWKEngine.ProcessReply : Boolean;
Procedure QwkControl (Idx: LongInt; Mode: Byte);
Var
TempBase : RecMessageBase;
TempScan : MScanRec;
Begin
If GetMBaseByIndex(Idx, TempBase) Then Begin
GetMessageScan (UserNumber, TempBase, TempScan);
TempScan.QwkScan := Mode;
If Mode = 0 Then Inc (RepBaseDel);
If Mode = 1 Then Inc (RepBaseAdd);
PutMessageScan (UserNumber, TempBase, TempScan);
End;
End;
Var
QwkBlock : String[128];
QwkHeader : QwkDATHdr;
Chunks : SmallInt;
Line : String;
LineCount : SmallInt;
IsControl : Boolean;
GotControl : Boolean;
ExtFile : Text;
Count1 : SmallInt;
Count2 : SmallInt;
Begin Begin
Result := False; Result := False;
DataFile := TFileBuffer.Create(4 * 1024);
If Not DataFile.OpenStream (FileFind(WorkPath + PacketID + '.msg'), 1, fmOpen, fmRWDN) Then Begin
DataFile.Free;
DirClean (WorkPath, '');
Exit;
End;
DataFile.ReadBlock(QwkBlock[1], 128);
QwkBlock[0] := #128;
If Pos(strUpper(PacketID), strUpper(QwkBlock)) = 0 Then Begin
DataFile.Free;
DirClean(WorkPath, '');
Exit;
End;
While Not DataFile.EOF Do Begin
DataFile.ReadBlock(QwkHeader, SizeOf(QwkHeader));
Move (QwkHeader.MsgNum, QwkBlock[1], 7);
QwkBlock[0] := #7;
If GetMBaseByIndex(strS2I(QwkBlock), MBase) Then Begin
If MBaseOpenCreate(MsgBase, MBase, WorkPath) Then Begin
MBaseAssignData(UserRecord, MsgBase, MBase);
QwkBlock[0] := #25;
Move (QwkHeader.UpTo, QwkBlock[1], 25);
MsgBase^.SetTo(strStripR(QwkBlock, ' '));
Move (QwkHeader.Subject, QwkBlock[1], 25);
MsgBase^.SetSubj(strStripR(QwkBlock, ' '));
Move (QwkHeader.ReferNum, QwkBlock[1], 6);
QwkBlock[0] := #6;
MsgBase^.SetRefer(strS2I(strStripR(QwkBlock, ' ')));
Move (QwkHeader.NumChunk, QwkBlock[1], 6);
Chunks := strS2I(QwkBlock) - 1;
Line := '';
LineCount := 0;
IsControl := MsgBase^.GetTo = QWK_CONTROL;
GotControl := False;
// disable control in network packets (for now?)
If IsNetworked Then
IsControl := False;
If IsControl And ((MsgBase^.GetSubj = 'ADD') or (MsgBase^.GetSubj = 'DROP')) Then
QwkControl (MBase.Index, Ord(MsgBase^.GetSubj = 'ADD'));
For Count1 := 1 to Chunks Do Begin
DataFile.ReadBlock (QwkBlock[1], 128);
QwkBlock[0] := #128;
QwkBlock := strStripR(QwkBlock, ' ');
For Count2 := 1 to Length(QwkBlock) Do Begin
If QwkBlock[Count2] = #227 Then Begin
Inc (LineCount);
If (LineCount < 4) and (Copy(Line, 1, 5) = 'From:') Then Begin
GotControl := True;
// ignore from name unless its networked
If IsNetworked Then
MsgBase^.SetTo(strStripB(Copy(Line, 6, Length(Line)), ' '));
End Else
If (LineCount < 4) and (Copy(Line, 1, 3) = 'To:') Then Begin
MsgBase^.SetTo(strStripB(Copy(Line, 4, Length(Line)), ' '));
GotControl := True;
End Else
If (LineCount < 4) and (Copy(Line, 1, 8) = 'Subject:') Then Begin
MsgBase^.SetSubj(strStripB(Copy(Line, 9, Length(Line)), ' '));
GotControl := True;
End Else
If GotControl And (Line = '') Then
GotControl := False
Else
MsgBase^.DoStringLn(Line);
Line := '';
End Else
Line := Line + QwkBlock[Count2];
End;
End;
If Line <> '' Then
MsgBase^.DoStringLn(Line);
If MBase.NetType > 0 Then Begin
If IsNetworked Then Begin
MsgBase^.DoStringLn (#13 + '--- ' + mysSoftwareID + '/QWK v' + mysVersion + ' (' + OSID + ')');
MsgBase^.DoStringLn (' * Origin: ' + GetOriginLine(MBase));
End Else Begin
MsgBase^.DoStringLn (#13 + '--- ' + mysSoftwareID + '/QWK v' + mysVersion + ' (' + OSID + ')');
MsgBase^.DoStringLn (' * Origin: ' + GetOriginLine(MBase) + ' (' + Addr2Str(MsgBase^.GetOrigAddr) + ')');
End;
End;
If Not IsControl Then Begin
If HasAccess(Self, MBase.PostACS) Then Begin
MsgBase^.WriteMsg;
Inc (RepOK); // must increase user and history posts by repOK
End Else
Inc (RepFailed);
End;
MsgBase^.CloseMsgBase;
Dispose (MsgBase, Done);
End Else
Inc (RepFailed);
End Else
Inc (RepFailed);
End;
DataFile.Free;
Assign (ExtFile, FileFind(WorkPath + 'todoor.ext'));
{$I-} Reset (ExtFile); {$I+}
If IoResult = 0 Then Begin
While Not Eof(ExtFile) Do Begin
ReadLn (ExtFile, Line);
If strWordGet(1, Line, ' ') = 'AREA' Then Begin
QwkBlock := strWordGet(3, Line, ' ');
If Pos('a', QwkBlock) > 0 Then QwkControl(strS2I(strWordGet(2, Line, ' ')), 1);
If Pos('D', QwkBlock) > 0 Then QwkControl(strS2I(strWordGet(2, Line, ' ')), 0);
End;
End;
Close (ExtFile);
End;
DirClean (WorkPath, '');
Result := True;
End; End;
End. End.

View File

@ -4,10 +4,6 @@ Unit MIS_Client_FTP;
{.$DEFINE FTPDEBUG} {.$DEFINE FTPDEBUG}
// does not send file/directory datestamps
// does not support uploading (need to make bbs functions generic for this
// and for mbbsutil -fupload command)
Interface Interface
Uses Uses
@ -54,15 +50,17 @@ Type
Function OpenDataSession : Boolean; Function OpenDataSession : Boolean;
Procedure CloseDataSession; Procedure CloseDataSession;
Procedure ResetSession; Procedure ResetSession;
Procedure UpdateUserStats (TFBase: RecFileBase; FDir: RecFileList; DirPos: LongInt); Procedure UpdateUserStats (TFBase: RecFileBase; FDir: RecFileList; DirPos: LongInt; IsUpload: Boolean);
Function CheckFileLimits (TempFBase: RecFileBase; FDir: RecFileList) : Byte; Function CheckFileLimits (TempFBase: RecFileBase; FDir: RecFileList) : Byte;
Function ValidDirectory (TempBase: RecFileBase) : Boolean; Function ValidDirectory (TempBase: RecFileBase) : Boolean;
Function FindDirectory (Var TempBase: RecFileBase) : LongInt; Function FindDirectory (Var TempBase: RecFileBase) : LongInt;
Function GetQWKName : String; Function GetQWKName : String;
Function GetFTPDate (DD: LongInt) : String; Function GetFTPDate (DD: LongInt) : String;
Procedure SendFile (Str: String); Procedure SendFile (Str: String);
Function RecvFile (Str: String; IsAppend: Boolean) : Boolean;
Function QWKCreatePacket : Boolean; Function QWKCreatePacket : Boolean;
Procedure QWKProcessREP;
Procedure cmdUSER; Procedure cmdUSER;
Procedure cmdPASS; Procedure cmdPASS;
@ -75,7 +73,7 @@ Type
Procedure cmdLIST; Procedure cmdLIST;
Procedure cmdPWD; Procedure cmdPWD;
Procedure cmdRETR; Procedure cmdRETR;
Procedure cmdSTOR; Procedure cmdSTOR (IsAppend: Boolean);
Procedure cmdSTRU; Procedure cmdSTRU;
Procedure cmdMODE; Procedure cmdMODE;
Procedure cmdSYST; Procedure cmdSYST;
@ -161,17 +159,16 @@ Begin
InTransfer := False; InTransfer := False;
End; End;
Procedure TFTPServer.UpdateUserStats (TFBase: RecFileBase; FDir: RecFileList; DirPos: LongInt); Procedure TFTPServer.UpdateUserStats (TFBase: RecFileBase; FDir: RecFileList; DirPos: LongInt; IsUpload: Boolean);
Var Var
HistFile: File of RecHistory; HistFile : File of RecHistory;
History : RecHistory; History : RecHistory;
FDirFile: File of RecFileList; FDirFile : File of RecFileList;
UserFile: File of RecUser; UserFile : File of RecUser;
Begin Begin
Inc (FDir.Downloads); // change to getuserbypos
Assign (UserFile, bbsConfig.DataPath + 'users.dat'); Assign (UserFile, bbsConfig.DataPath + 'users.dat');
ioReset (UserFile, SizeOf(RecUser), fmReadWrite + fmDenyWrite); ioReset (UserFile, SizeOf(RecUser), fmRWDW);
ioSeek (UserFile, UserPos - 1); ioSeek (UserFile, UserPos - 1);
ioRead (UserFile, User); ioRead (UserFile, User);
@ -179,28 +176,33 @@ Begin
User.CallsToday := 0; User.CallsToday := 0;
User.DLsToday := 0; User.DLsToday := 0;
User.DLkToday := 0; User.DLkToday := 0;
User.TimeLeft := SecLevel.Time User.TimeLeft := SecLevel.Time;
User.LastOn := CurDateDos;
End; End;
// need to check if it were an upload and do things accordingly If IsUpload Then Begin
Inc (User.ULs);
Inc (User.ULk, FDir.Size DIV 1024);
End Else Begin
Inc (FDir.Downloads);
Inc (User.DLs);
Inc (User.DLsToday);
Inc (User.DLk, FDir.Size DIV 1024);
Inc (User.DLkToday, FDir.Size DIV 1024);
Inc (User.DLs); Assign (FDirFile, bbsConfig.DataPath + TFBase.FileName + '.dir');
Inc (User.DLsToday); ioReset (FDirFile, SizeOf(RecFileList), fmRWDW);
Inc (User.DLk, FDir.Size DIV 1024); ioSeek (FDirFile, DirPos - 1);
Inc (User.DLkToday, FDir.Size DIV 1024); ioWrite (FDirFile, FDir);
Close (FDirFile);
End;
ioSeek (UserFile, UserPos - 1); ioSeek (UserFile, UserPos - 1);
ioWrite (UserFile, User); ioWrite (UserFile, User);
Close (UserFile); Close (UserFile);
Assign (FDirFile, bbsConfig.DataPath + TFBase.FileName + '.dir');
ioReset (FDirFile, SizeOf(RecFileList), fmReadWrite + fmDenyWrite);
ioSeek (FDirFile, DirPos - 1);
ioWrite (FDirFile, FDir);
Close (FDirFile);
Assign (HistFile, bbsConfig.DataPath + 'history.dat'); Assign (HistFile, bbsConfig.DataPath + 'history.dat');
ioReset (HistFile, SizeOf(RecHistory), fmReadWrite + fmDenyWrite); ioReset (HistFile, SizeOf(RecHistory), fmRWDW);
If IoResult <> 0 Then ReWrite(HistFile); If IoResult <> 0 Then ReWrite(HistFile);
@ -217,11 +219,17 @@ Begin
If Eof(HistFile) Then Begin If Eof(HistFile) Then Begin
FillChar(History, SizeOf(History), 0); FillChar(History, SizeOf(History), 0);
History.Date := CurDateDos; History.Date := CurDateDos;
End; End;
Inc (History.Downloads, 1); If IsUpload Then Begin
Inc (History.DownloadKB, FDir.Size DIV 1024); Inc (History.Uploads);
Inc (History.UploadKB, FDir.Size DIV 1024);
End Else Begin
Inc (History.Downloads);
Inc (History.DownloadKB, FDir.Size DIV 1024);
End;
ioWrite (HistFile, History); ioWrite (HistFile, History);
Close (HistFile); Close (HistFile);
@ -282,6 +290,7 @@ Begin
If DataSocket <> NIL Then Begin If DataSocket <> NIL Then Begin
Client.WriteLine(re_DataOpen); Client.WriteLine(re_DataOpen);
Result := True; Result := True;
Exit; Exit;
End; End;
@ -301,6 +310,7 @@ Begin
If Not Assigned(DataSocket) Then Begin If Not Assigned(DataSocket) Then Begin
WaitSock.Free; WaitSock.Free;
Client.WriteLine(re_NoData); Client.WriteLine(re_NoData);
Exit; Exit;
End; End;
@ -312,6 +322,7 @@ Begin
Client.WriteLine(re_NoData); Client.WriteLine(re_NoData);
DataSocket.Free; DataSocket.Free;
DataSocket := NIL; DataSocket := NIL;
Exit; Exit;
End; End;
End; End;
@ -420,6 +431,57 @@ Begin
End; End;
End; End;
Function TFTPServer.RecvFile (Str: String; IsAppend: Boolean) : Boolean;
Var
F : File;
Buf : Array[1..FileXferSize] of Byte;
Res : LongInt;
Begin
Result := False;
If FileExist(Str) And Not IsAppend Then Begin
Client.WriteLine(re_BadFile);
Exit;
End;
If Not OpenDataSession Then Exit;
Server.Status ('Receiving: ' + Str);
InTransfer := True;
Result := True;
Assign (F, Str);
If FileExist(Str) And IsAppend Then Begin
Reset (F, 1);
Seek (F, FileSize(F));
End Else Begin
ReWrite (F, 1);
IsAppend := False;
End;
Repeat
Res := DataSocket.ReadBuf(Buf[1], SizeOf(Buf));
If Res > 0 Then
BlockWrite (F, Buf[1], Res)
Else
Break;
Until False;
Close (F);
If Result Then
Client.WriteLine (re_XferOK);
CloseDataSession;
InTransfer := False;
End;
Procedure TFTPServer.SendFile (Str: String); Procedure TFTPServer.SendFile (Str: String);
Var Var
F : File; F : File;
@ -434,11 +496,14 @@ Begin
OpenDataSession; OpenDataSession;
Server.Status('Sending: ' + Str);
While Not Eof(F) Do Begin While Not Eof(F) Do Begin
BlockRead (F, Buf, SizeOf(Buf), Res); BlockRead (F, Buf, SizeOf(Buf), Res);
Repeat Repeat
Tmp := DataSocket.WriteBuf(Buf, Res); Tmp := DataSocket.WriteBuf(Buf, Res);
Dec (Res, Tmp); Dec (Res, Tmp);
Until Res <= 0; Until Res <= 0;
End; End;
@ -475,10 +540,33 @@ Begin
QWK.UpdateLastReadPointers; QWK.UpdateLastReadPointers;
QWK.Free; QWK.Free;
Server.Status ('Created packet in ' + TempPath);
ExecuteArchive (TempPath, TempPath + GetQWKName + '.qwk', User.Archive, TempPath + '*', 1); ExecuteArchive (TempPath, TempPath + GetQWKName + '.qwk', User.Archive, TempPath + '*', 1);
SendFile (TempPath + GetQWKName + '.qwk'); SendFile (TempPath + GetQWKName + '.qwk');
DirClean (TempPath, '');
End;
Procedure TFTPServer.QWKProcessREP;
Var
QWK : TQwkEngine;
Begin
// need to change temppath to a unique directory created for this
// ftp instance. before that we need to push a unique ID to this
// session.
RecvFile (TempPath + GetQWKName + '.rep', False);
ExecuteArchive (TempPath, TempPath + GetQWKName + '.rep', User.Archive, '*', 2);
QWK := TQwkEngine.Create(TempPath, GetQWKName, UserPos, User);
QWK.HasAccess := @QWKHasAccess;
QWK.IsNetworked := User.Flags AND UserQWKNetwork <> 0;
QWK.IsExtended := User.QwkExtended;
QWK.ProcessReply;
QWK.Free;
// update user stats posts and bbs history if not networked
End; End;
Procedure TFTPServer.cmdUSER; Procedure TFTPServer.cmdUSER;
@ -737,7 +825,7 @@ Begin
If (Dir.Flags And FDirDeleted <> 0) Then Continue; If (Dir.Flags And FDirDeleted <> 0) Then Continue;
If (Dir.Flags and FDirOffline <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeOffline)) Then Continue; If (Dir.Flags and FDirOffline <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeOffline)) Then Continue;
If (Dir.Flags And FDirInvalid <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeUnvalid)) Then Continue; If (Dir.Flags And FDirInvalid <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeUnvalid)) Then Continue;
If (Dir.Flags And FDirFailed <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeFailed)) Then Continue; If (Dir.Flags And FDirFailed <> 0) And (Not CheckAccess(User, True, bbsConfig.AcsSeeFailed)) Then Continue;
If WildMatch(FileMask, Dir.FileName, False) Then If WildMatch(FileMask, Dir.FileName, False) Then
DataSocket.WriteLine('-rw-r--r-- 1 ftp ftp ' + strPadL(strI2S(Dir.Size), 13, ' ') + ' ' + GetFTPDate(Dir.DateTime) + ' ' + Dir.FileName) DataSocket.WriteLine('-rw-r--r-- 1 ftp ftp ' + strPadL(strI2S(Dir.Size), 13, ' ') + ' ' + GetFTPDate(Dir.DateTime) + ' ' + Dir.FileName)
@ -753,7 +841,7 @@ Begin
Client.WriteLine(re_BadCommand); Client.WriteLine(re_BadCommand);
End; End;
Procedure TFTPServer.cmdSTOR; Procedure TFTPServer.cmdSTOR (IsAppend: Boolean);
Var Var
TempPos : LongInt; TempPos : LongInt;
TempBase : RecFileBase; TempBase : RecFileBase;
@ -764,6 +852,12 @@ Begin
Exit; Exit;
End; End;
If strUpper(Data) = strUpper(GetQWKName + '.rep') Then Begin
QWKProcessREP;
Exit;
End;
TempPos := FindDirectory(TempBase); TempPos := FindDirectory(TempBase);
If (TempPos = -1) Or Not ValidDirectory(TempBase) Then Begin If (TempPos = -1) Or Not ValidDirectory(TempBase) Then Begin
@ -772,17 +866,27 @@ Begin
Exit; Exit;
End; End;
Client.WriteLine(re_BadFile); server.status('calling recvfile');
//reasons why i haven't finished this (todo): RecvFile ('d:\code\mystic1\temp0\infile.tmp', IsAppend);
// ratios // Client.WriteLine(re_BadFile);
// diskspace
// dreadful things required to do for upload process:
// find upload base
// check diskspace
// check slowmedia
// check access
// check filename length
// duplicate file checking
// get file
// update user statistics
// update history statistics
// archive testing // archive testing
// file_id.diz importing // file_id.diz importing
// forcing uploads to upload base (if non-zero)
// duplicate file checking // other things: add no desc and ftp test batch to configuration?
// upload statistic tracking
End; End;
Procedure TFTPServer.cmdRETR; Procedure TFTPServer.cmdRETR;
@ -818,6 +922,7 @@ Begin
If WildMatch(FileMask, Dir.FileName, False) Then Begin If WildMatch(FileMask, Dir.FileName, False) Then Begin
Found := DirFile.FilePosRecord; Found := DirFile.FilePosRecord;
Break; Break;
End; End;
End; End;
@ -833,7 +938,7 @@ Begin
Case CheckFileLimits(TempBase, Dir) of Case CheckFileLimits(TempBase, Dir) of
0 : Begin 0 : Begin
SendFile (TempBase.Path + Dir.FileName); SendFile (TempBase.Path + Dir.FileName);
UpdateUserStats (TempBase, Dir, Found); UpdateUserStats (TempBase, Dir, Found, False);
End; End;
1 : Client.WriteLine(re_NoAccess); 1 : Client.WriteLine(re_NoAccess);
2 : Client.WriteLine(re_DLLimit); 2 : Client.WriteLine(re_DLLimit);
@ -956,6 +1061,7 @@ Begin
Server.Status ('Cmd: ' + Cmd + ' Data: ' + Data); Server.Status ('Cmd: ' + Cmd + ' Data: ' + Data);
{$ENDIF} {$ENDIF}
//If Cmd = 'APPE' Then cmdSTOR(True) Else
If Cmd = 'CDUP' Then cmdCDUP Else If Cmd = 'CDUP' Then cmdCDUP Else
If Cmd = 'CWD' Then cmdCWD Else If Cmd = 'CWD' Then cmdCWD Else
If Cmd = 'DELE' Then Client.WriteLine(re_NoAccess) Else If Cmd = 'DELE' Then Client.WriteLine(re_NoAccess) Else
@ -974,7 +1080,8 @@ Begin
If Cmd = 'RETR' Then cmdRETR Else If Cmd = 'RETR' Then cmdRETR Else
If Cmd = 'RMD' Then Client.WriteLine(re_NoAccess) Else If Cmd = 'RMD' Then Client.WriteLine(re_NoAccess) Else
If Cmd = 'SIZE' Then cmdSIZE Else If Cmd = 'SIZE' Then cmdSIZE Else
If Cmd = 'STOR' Then cmdSTOR Else If Cmd = 'STOR' Then cmdSTOR(False) Else
// implement STOU which in turn calls cmdSTOR after getting filename
If Cmd = 'STRU' Then cmdSTRU Else If Cmd = 'STRU' Then cmdSTRU Else
If Cmd = 'SYST' Then cmdSYST Else If Cmd = 'SYST' Then cmdSYST Else
If Cmd = 'TYPE' Then cmdTYPE Else If Cmd = 'TYPE' Then cmdTYPE Else

View File

@ -3605,6 +3605,12 @@
the file base editor for their names to be automatically changed. the file base editor for their names to be automatically changed.
+ Users can now download QWK packets using the FTP server. A QWK packet + Users can now download QWK packets using the FTP server. A QWK packet
filename will be shown in all FTP listings. filename will be shown in all FTP listings. If the user is flagged as a
FTP network account, their handle will be used as the BBSID for the QWK
packet (handle.qwk).
+ Users can now upload QWK reply packets using the FTP server. If the user
is flagged as a FTP network account, their reply packet will need to be
"handle.rep".
<ALPHA 37 RELEASED> <ALPHA 37 RELEASED>