From 44908433fb4bd38693fc59227bacebfe4a3ed343 Mon Sep 17 00:00:00 2001 From: mysticbbs Date: Thu, 29 Aug 2013 04:21:11 -0400 Subject: [PATCH] Initial import --- mystic/bbs_msgbase_qwk.pas | 979 +++++++++++++++++++++++++++++++++++++ 1 file changed, 979 insertions(+) create mode 100644 mystic/bbs_msgbase_qwk.pas diff --git a/mystic/bbs_msgbase_qwk.pas b/mystic/bbs_msgbase_qwk.pas new file mode 100644 index 0000000..01fa978 --- /dev/null +++ b/mystic/bbs_msgbase_qwk.pas @@ -0,0 +1,979 @@ +Unit bbs_MsgBase_QWK; + +// networking notes: +// no control files +// no file list +// no index files +// extended = selectable by user's setting +// archive = selectable by user's setting + +{$I M_OPS.PAS} + +Interface + +Uses + m_FileIO, + bbs_DataBase; + +Const + QWK_EOL = #13#10; + +Type + BSingle = Array [0..3] of Byte; + + QwkNdxHdr = Record + MsgPos : BSingle; + Junk : Byte; + End; + + QwkDATHdr = Record {128 bytes} + Status : Char; + MSGNum : Array [1..7] of Char; + Date : Array [1..8] of Char; + Time : Array [1..5] of Char; + UpTO : Array [1..25] of Char; + UpFROM : Array [1..25] of Char; + Subject : Array [1..25] of Char; + PassWord : Array [1..12] of Char; + ReferNum : Array [1..8] of Char; + NumChunk : Array [1..6] of Char; + Active : Char; {225 active, 226 killed} + ConfNum : Word; + Junk : Word; + NetTag : Char; + End; + + QwkLRRec = Record + Base : Word; + Pos : LongInt; + End; + + TQWKEngine_HasAccess = Function (AcsStr: String) : Boolean; + + TQWKEngine = Class + IsExtended : Boolean; + IsNetworked : Boolean; + WorkPath : String; + PacketID : String; + UserRecord : RecUser; + UserNumber : Cardinal; + HasAccess : TQWKEngine_HasAccess; + TotalMessages : Cardinal; + TotalBases : Cardinal; + RepOK : LongInt; + RepFailed : LongInt; + RepBaseAdd : LongInt; + RepBaseDel : LongInt; + DataFile : TFileBuffer; + + Constructor Create (QwkPath, QwkID: String; UN: Cardinal; UR: RecUser); + Procedure LONG2MSB (Index : LongInt; Var MS : BSingle); + Procedure WriteDOORID; + Procedure WriteTOREADEREXT; + Procedure WriteCONTROLDAT; + Function WriteMSGDAT : LongInt; + Procedure CreatePacket; + Function ProcessReply : Boolean; + End; + +Implementation + +Uses + m_Strings, + m_DateTime; + +Constructor TQWKEngine.Create (QwkPath, QwkID: String; UN: Cardinal; UR: RecUser); +Begin + Inherited Create; + + WorkPath := QwkPath; + PacketID := QwkID; + UserNumber := UN; + UserRecord := UR; + IsExtended := False; + IsNetworked := False; + TotalMessages := 0; + TotalBases := 0; + RepOK := 0; + RepFailed := 0; + RepBaseAdd := 0; + RepBaseDel := 0; +End; + +Procedure TQWKEngine.LONG2MSB (Index : LongInt; Var MS : BSingle); +Var + Exp : Byte; +Begin + If Index <> 0 Then Begin + Exp := 0; + + While Index And $800000 = 0 Do Begin + Inc (Exp); + Index := Index SHL 1 + End; + + Index := Index And $7FFFFF; + End Else + Exp := 152; + + MS[0] := Index AND $FF; + MS[1] := (Index SHR 8) AND $FF; + MS[2] := (Index SHR 16) AND $FF; + MS[3] := 152 - Exp; +End; + +Procedure TQWKEngine.WriteDOORID; +Var + TempFile : Text; +Begin + If IsNetworked Then Exit; + + Assign (TempFile, WorkPath + 'door.id'); + ReWrite (TempFile); + Write (TempFile, 'DOOR = ' + mysSoftwareID + QWK_EOL); + Write (TempFile, 'VERSION = ' + mysVersion + QWK_EOL); + Write (TempFile, 'SYSTEM = ' + mysSoftwareID + ' ' + mysVersion + QWK_EOL); + Write (TempFile, 'CONTROLNAME = MYSTICQWK' + QWK_EOL); + Write (TempFile, 'CONTROLTYPE = ADD' + QWK_EOL); + Write (TempFile, 'CONTROLTYPE = DROP' + QWK_EOL); + Close (TempFile); +End; + +Procedure TQWKEngine.WriteTOREADEREXT; +Var + TempFile : Text; + BaseFile : File; + Flags : String; + Base : RecMessageBase; +Begin + If IsNetworked Or (Not IsExtended) Then Exit; + + Assign (TempFile, WorkPath + 'toreader.ext'); + ReWrite (TempFile); + Write (TempFile, 'ALIAS ' + UserRecord.Handle + QWK_EOL); + + Assign (BaseFile, bbsCfg.DataPath + 'mbases.dat'); + + If ioReset (BaseFile, SizeOf(RecMessageBase), fmRWDN) Then Begin + + While Not Eof(BaseFile) Do Begin + ioRead (BaseFile, Base); + + If HasAccess(Base.ReadACS) Then Begin + Flags := ' '; + + If Base.Flags AND MBPrivate = 0 Then + Flags := Flags + 'aO' + Else + Flags := Flags + 'pP'; + + If Base.Flags AND MBRealNames = 0 Then + Flags := Flags + 'H'; + + If Not HasAccess(Base.PostACS) Then + Flags := Flags + 'BRZ'; + + Case Base.NetType of + 0 : Flags := Flags + 'L'; + 1 : Flags := Flags + 'E'; + 2 : Flags := Flags + 'U'; + 3 : Flags := Flags + 'N'; + End; + + If Base.DefQScan = 2 Then + Flags := Flags + 'F'; + + Write (TempFile, 'AREA ' + strI2S(Base.Index) + Flags, QWK_EOL); + End; + End; + + Close (BaseFile); + End; + + Close (TempFile); +End; + +Procedure TQWKEngine.WriteCONTROLDAT; +Var + TempFile : Text; + BaseFile : File; + Base : RecMessageBase; +Begin + If IsNetworked Then Exit; + + Assign (TempFile, WorkPath + 'control.dat'); + ReWrite (TempFile); + + Write (TempFile, bbsCfg.BBSName + QWK_EOL); + Write (TempFile, QWK_EOL); + Write (TempFile, QWK_EOL); + Write (TempFile, bbsCfg.SysopName + QWK_EOL); + Write (TempFile, '0,' + bbsCfg.qwkBBSID + QWK_EOL); + Write (TempFile, DateDos2Str(CurDateDos, 1), ',', TimeDos2Str(CurDateDos, 0) + QWK_EOL); + Write (TempFile, strUpper(UserRecord.Handle) + QWK_EOL); + Write (TempFile, QWK_EOL); + Write (TempFile, '0' + QWK_EOL); + Write (TempFile, TotalMessages, QWK_EOL); + Write (TempFile, TotalBases - 1, QWK_EOL); + + Assign (BaseFile, bbsCfg.DataPath + 'mbases.dat'); + + If ioReset (BaseFile, SizeOf(RecMessageBase), fmRWDN) Then Begin + + While Not Eof(BaseFile) Do Begin + ioRead (BaseFile, Base); + + If HasAccess(Base.ReadACS) Then Begin + Write (TempFile, Base.Index, QWK_EOL); + + If IsExtended Then + Write (TempFile, strStripMCI(Base.Name) + QWK_EOL) + Else + Write (TempFile, Base.QwkName + QWK_EOL); + End; + End; + + Close (BaseFile); + End; + + Write (TempFile, JustFile(bbsCfg.qwkWelcome) + QWK_EOL); + Write (TempFile, JustFile(bbsCfg.qwkNews) + QWK_EOL); + Write (TempFile, JustFile(bbsCfg.qwkGoodbye) + QWK_EOL); + + Close (TempFile); +End; + +Function TQWKEngine.WriteMSGDAT : LongInt; +Var + NdxFile : File of QwkNdxHdr; + NdxHdr : QwkNdxHdr; + Header : String[128]; + BufStr : String[128]; + Chunks : Word; + MsgAdded : LongInt; + LastRead : LongInt; + QwkIndex : LongInt; + TooBig : Boolean; + + Procedure DoString (Str: String); + Var + Count : SmallInt; + Begin + For Count := 1 to Length(Str) Do Begin + BufStr := BufStr + Str[Count]; + + If BufStr[0] = #128 Then Begin + DataFile.WriteBlock (BufStr[1], 128); + + BufStr := ''; + End; + End; + End; + +Var + TempStr : String; +Begin + MsgAdded := 0; + + If Not OpenCreateBase(MsgBase, MBase) Then Exit; + + LastRead := MsgBase^.GetLastRead(UserNumber) + 1; + + MsgBase^.SeekFirst (LastRead); + + While MsgBase^.SeekFound Do Begin + + If Not IsNetworked Then + If ((bbsCfg.QwkMaxBase > 0) and (MsgAdded = bbsCfg.QwkMaxBase)) or + ((bbsCfg.QwkMaxPacket > 0) and (TotalMsgs = bbsCfg.QwkMaxPacket)) Then Break; + + MsgBase^.MsgStartUp; + + If MsgBase^.IsPriv And Not Session.User.IsThisUser(MsgBase^.GetTo) Then Begin + MsgBase^.SeekNext; + + Continue; + End; + + Inc (MsgAdded); + Inc (TotalMsgs); + + LastRead := MsgBase^.GetMsgNum; + Chunks := 0; + BufStr := ''; + TooBig := False; + QwkIndex := FileSize(DataFile) DIV 128 + 1; + + MsgBase^.MsgTxtStartUp; + + While Not MsgBase^.EOM Do Begin + TempStr := MsgBase^.GetString(79); + + If TempStr[1] = #1 Then Continue; + + Inc (Chunks, Length(TempStr)); + End; + + If Chunks MOD 128 = 0 Then + Chunks := Chunks DIV 128 + 1 + Else + Chunks := Chunks DIV 128 + 2; + + Header := + ' ' + + strPadR(strI2S(MsgBase^.GetMsgNum), 7, ' ') + + MsgBase^.GetDate + + MsgBase^.GetTime + + strPadR(strUpper(MsgBase^.GetTo), 25, ' ') + + strPadR(strUpper(MsgBase^.GetFrom), 25, ' ') + + strPadR(strUpper(MsgBase^.GetSubj), 25, ' ') + + strPadR('', 12, ' ') + + strPadR(strI2S(MsgBase^.GetRefer), 8, ' ') + + strPadR(strI2S(Chunks), 6, ' ') + + #255 + + ' ' + + ' ' + + ' '; + + If MsgAdded = 1 Then Begin + Assign (NdxFile, WorkPath + strPadL(strI2S(MBase.Index), 3, '0') + '.ndx'); + ReWrite (NdxFile); + End; + + LONG2MSB (QwkIndex, NdxHdr.MsgPos); + Write (NdxFile, NdxHdr); + + DataFile.WriteBlock (Header[1], 128); + + If IsExtended Then Begin + If Length(MsgBase^.GetFrom) > 25 Then Begin + DoString('From: ' + MsgBase^.GetFrom + #227); + + TooBig := True; + End; + + If Length(MsgBase^.GetTo) > 25 Then Begin + DoString('To: ' + MsgBase^.GetTo + #227); + + TooBig := True; + End; + + If Length(MsgBase^.GetSubj) > 25 Then Begin + DoString('Subject: ' + MsgBase^.GetSubj + #227); + + TooBig := True; + End; + + If TooBig Then DoString(#227); + End; + + MsgBase^.MsgTxtStartUp; + + While Not MsgBase^.EOM Do Begin + TempStr := MsgBase^.GetString(79) + #227; + + If TempStr[1] = #1 Then Continue; + + DoString (TempStr); + End; + + If BufStr <> '' Then Begin + BufStr := strPadR (BufStr, 128, ' '); + + DataFile.WriteBlock (BufStr[1], 128); + End; + + MsgBase^.SeekNext; + End; + + If MsgAdded > 0 Then Close (NdxFile); + + MsgBase^.CloseMsgBase; + Dispose (MsgBase, Done); + + Result := LastRead; +End; + +Procedure TQWKEngine.CreatePacket; +Var + Temp : String; + QwkLR : QwkLRRec; + QwkLRFile : File of QwkLRRec; + MBaseFile : File; + MBase : RecMessageBase; + MScan : MScanRec; +Begin + DataFile := TFileBuffer.Create(4 * 1024); + + DataFile.OpenStream (WorkPath + 'messages.dat', 1, fmCreate, fmRWDN); + + Temp := strPadR('Produced By ' + mysSoftwareID + ' v' + mysVersion + '. ' + mysCopyNotice, 128, ' '); + + DataFile.WriteBlock (Temp[1], 128); + + Assign (QwkLRFile, WorkPath + 'qlr.dat'); + ReWrite (QwkLRFile); + + Assign (MBaseFile, bbsCfg.DataPath + 'mbases.dat'); + + If ioReset (MBaseFile, SizeOf(RecMessageBase), fmRWDN) Then Begin + + If IsNetworked Then + ioRead (MBaseFile, MBase); + + While Not Eof(MBaseFile) Do Begin + ioRead (MBaseFile, MBase); + + If IsNetworked And (MBase.Flags AND MBAllowQWKNet = 0) Then + Continue; + + If HasAccess(MBase.ReadACS) Then Begin + + GetMessageScan (UserNumber, MBase, MScan); + + If MScan.QwkScan > 0 Then Begin + QwkLR.Base := FilePos(MBaseFile); + QwkLR.Pos := WriteMSGDAT; + + Write (QwkLRFile, QwkLR); + End; + End; + End; + + Close (MBaseFile); + End; + + Close (QwkLRFile); + + DataFile.Free; + + If Not IsNetworked Then Begin + WriteControlDAT; + WriteDOORID; + WriteTOREADEREXT; + End; +End; + +Function TQWKEngine.ProcessReply : Boolean; +Begin + Result := False; +End; + +End. + + + + + + + +Function TMsgBase.WriteMSGDAT (Extended: Boolean) : LongInt; +Var + DataFile : File; + NdxFile : File of QwkNdxHdr; + NdxHdr : QwkNdxHdr; + Header : String[128]; + Chunks : Word; + BufStr : String[128]; + MsgAdded : Integer; + LastRead : LongInt; + QwkIndex : LongInt; + TooBig : Boolean; + + Procedure DoString (Str: String); + Var + Count : SmallInt; + Begin + For Count := 1 to Length(Str) Do Begin + BufStr := BufStr + Str[Count]; + + If BufStr[0] = #128 Then Begin + BlockWrite (DataFile, BufStr[1], 128); + + BufStr := ''; + End; + End; + End; + +Var + TempStr : String; +Begin + MsgAdded := 0; + + If Not OpenCreateBase(MsgBase, MBase) Then Exit; + + Session.io.OutFull (Session.GetPrompt(231)); + + Assign (DataFile, Session.TempPath + 'messages.dat'); + Reset (DataFile, 1); + Seek (DataFile, FileSize(DataFile)); + + LastRead := MsgBase^.GetLastRead(Session.User.UserNum) + 1; + + MsgBase^.SeekFirst (LastRead); + + While MsgBase^.SeekFound Do Begin + If ((bbsCfg.QwkMaxBase > 0) and (MsgAdded = bbsCfg.QwkMaxBase)) or + ((bbsCfg.QwkMaxPacket > 0) and (TotalMsgs = bbsCfg.QwkMaxPacket)) Then Break; + + MsgBase^.MsgStartUp; + + If MsgBase^.IsPriv And Not Session.User.IsThisUser(MsgBase^.GetTo) Then Begin + MsgBase^.SeekNext; + + Continue; + End; + + Inc (MsgAdded); + Inc (TotalMsgs); + + LastRead := MsgBase^.GetMsgNum; + Chunks := 0; + BufStr := ''; + TooBig := False; + QwkIndex := FileSize(DataFile) DIV 128 + 1; + + MsgBase^.MsgTxtStartUp; + + While Not MsgBase^.EOM Do Begin + TempStr := MsgBase^.GetString(79); + + If TempStr[1] = #1 Then Continue; + + Inc (Chunks, Length(TempStr)); + End; + + If Chunks MOD 128 = 0 Then + Chunks := Chunks DIV 128 + 1 + Else + Chunks := Chunks DIV 128 + 2; + + Header := + ' ' + + strPadR(strI2S(MsgBase^.GetMsgNum), 7, ' ') + + MsgBase^.GetDate + + MsgBase^.GetTime + + strPadR(strUpper(MsgBase^.GetTo), 25, ' ') + + strPadR(strUpper(MsgBase^.GetFrom), 25, ' ') + + strPadR(strUpper(MsgBase^.GetSubj), 25, ' ') + + strPadR('', 12, ' ') + + strPadR(strI2S(MsgBase^.GetRefer), 8, ' ') + + strPadR(strI2S(Chunks), 6, ' ') + + #255 + + ' ' + + ' ' + + ' '; + + If MsgAdded = 1 Then Begin + Assign (NdxFile, Session.TempPath + strPadL(strI2S(MBase.Index), 3, '0') + '.ndx'); + ReWrite (NdxFile); + End; + + LONG2MSB (QwkIndex, NdxHdr.MsgPos); + Write (NdxFile, NdxHdr); + BlockWrite (DataFile, Header[1], 128); + + If Extended Then Begin + If Length(MsgBase^.GetFrom) > 25 Then Begin + DoString('From: ' + MsgBase^.GetFrom + #227); + + TooBig := True; + End; + + If Length(MsgBase^.GetTo) > 25 Then Begin + DoString('To: ' + MsgBase^.GetTo + #227); + + TooBig := True; + End; + + If Length(MsgBase^.GetSubj) > 25 Then Begin + DoString('Subject: ' + MsgBase^.GetSubj + #227); + + TooBig := True; + End; + + If TooBig Then DoString(#227); + End; + + MsgBase^.MsgTxtStartUp; + + While Not MsgBase^.EOM Do Begin + TempStr := MsgBase^.GetString(79) + #227; + + If TempStr[1] = #1 Then Continue; + + DoString (TempStr); + End; + + If BufStr <> '' Then Begin + BufStr := strPadR (BufStr, 128, ' '); + + BlockWrite (DataFile, BufStr[1], 128); + End; + + MsgBase^.SeekNext; + End; + + Close (DataFile); + + If MsgAdded > 0 Then Close (NdxFile); + + Session.io.PromptInfo[1] := strI2S(MBase.Index); + Session.io.PromptInfo[2] := MBase.Name; + Session.io.PromptInfo[3] := MBase.QwkName; + Session.io.PromptInfo[4] := strI2S(MsgBase^.NumberOfMsgs); + Session.io.PromptInfo[5] := strI2S(MsgAdded); + + MsgBase^.CloseMsgBase; + Dispose (MsgBase, Done); + + Session.io.OutBS (Screen.CursorX, True); + Session.io.OutFullLn (Session.GetPrompt(232)); + + Result := LastRead; +End; + +Procedure TMsgBase.DownloadQWK (Extended: Boolean; Data: String); +Type + QwkLRRec = Record + Base : Word; + Pos : LongInt; + End; +Var + Old : RecMessageBase; + DataFile : File; + Temp : String; + QwkLR : QwkLRRec; + QwkLRFile : File of QwkLRRec; +Begin + If Session.User.ThisUser.QwkFiles Then + Session.FileBase.ExportFileList(True, True); + + FileMode := 66; + Old := MBase; + Temp := strPadR('Produced By ' + mysSoftwareID + ' v' + mysVersion + '. ' + CopyID, 128, ' '); + + Assign (DataFile, Session.TempPath + 'messages.dat'); + ReWrite (DataFile, 1); + BlockWrite (DataFile, Temp[1], 128); + Close (DataFile); + + Assign (QwkLRFile, Session.TempPath + 'qlr.dat'); + ReWrite (QwkLRFile); + Reset (MBaseFile); + + Session.io.OutFullLn (Session.GetPrompt(230)); + + TotalMsgs := 0; + TotalConf := 0; + + Session.User.IgnoreGroup := Pos('/ALLGROUP', strUpper(Data)) > 0; + + While Not Eof(MBaseFile) Do Begin + Read (MBaseFile, MBase); + + If Session.User.Access(MBase.ReadACS) Then Begin + Inc (TotalConf); + + GetMessageScan; + + If MScan.QwkScan > 0 Then Begin + QwkLR.Base := FilePos(MBaseFile); + QwkLR.Pos := WriteMsgDAT(Extended); + + Write (QwkLRFile, QwkLR); + End; + End; + End; + + Close (QwkLRFile); + + WriteControlDAT (Extended); + WriteDOORID (Extended); + + If Extended Then WriteTOREADEREXT; + + If TotalMsgs > 0 Then Begin + Session.io.PromptInfo[1] := strI2S(TotalMsgs); + Session.io.PromptInfo[2] := strI2S(TotalConf); + + Session.io.OutFullLn (Session.GetPrompt(233)); + + Temp := bbsCfg.qwkBBSID + '.qwk'; + + Session.io.OutFullLn (Session.GetPrompt(234)); + + Session.io.PromptInfo[1] := Temp; + + If FileExist(bbsCfg.QwkWelcome) Then FileCopy(bbsCfg.qwkWelcome, Session.TempPath + JustFile(bbsCfg.qwkWelcome)); + If FileExist(bbsCfg.QwkNews) Then FileCopy(bbsCfg.qwkNews, Session.TempPath + JustFile(bbsCfg.qwkNews)); + If FileExist(bbsCfg.QwkGoodbye) Then FileCopy(bbsCfg.qwkGoodbye, Session.TempPath + JustFile(bbsCfg.qwkGoodbye)); + +// Session.SystemLog('DEBUG: Archiving QWK packet'); + + If Session.LocalMode Then Begin + FileErase (bbsCfg.QWKPath + Temp); + + Session.FileBase.ExecuteArchive (bbsCfg.QWKPath + Temp, Session.User.ThisUser.Archive, Session.TempPath + '*', 1); + + Session.io.OutFullLn (Session.GetPrompt(235)); + End Else Begin + Session.FileBase.ExecuteArchive (Session.TempPath + Temp, Session.User.ThisUser.Archive, Session.TempPath + '*', 1); + Session.FileBase.SendFile (Session.TempPath + Temp); + End; + + If Session.io.GetYN (Session.GetPrompt(236), True) Then Begin + Reset (MBaseFile); + Reset (QwkLRFile); + + While Not Eof(QwkLRFile) Do Begin + Read (QwkLRFile, QwkLR); + Seek (MBaseFile, QwkLR.Base - 1); + Read (MBaseFile, MBase); + + Case MBase.BaseType of + 0 : MsgBase := New(PMsgBaseJAM, Init); + 1 : MsgBase := New(PMsgBaseSquish, Init); + End; + + MsgBase^.SetMsgPath (MBase.Path + MBase.FileName); + + If MsgBase^.OpenMsgBase Then Begin + MsgBase^.SetLastRead (Session.User.UserNum, QwkLR.Pos); + MsgBase^.CloseMsgBase; + End; + + Dispose(MsgBase, Done); + End; + Close (QwkLRFile); + End; + End Else + Session.io.OutFullLn (Session.GetPrompt(228)); + + Session.User.IgnoreGroup := False; + + Close (MBaseFile); + + MBase := Old; + + DirClean (Session.TempPath, ''); +End; + +Procedure TMsgBase.UploadREP; +Var + DataFile : File; + TempBase : RecMessageBase; + OldBase : RecMessageBase; + QwkHeader : QwkDATHdr; + QwkBlock : String[128]; + Line : String; + A : SmallInt; + B : SmallInt; + Chunks : SmallInt; + LineCount : SmallInt; + IsControl : Boolean; + GotControl : Boolean; + ExtFile : Text; + StatOK : LongInt = 0; + StatFailed : LongInt = 0; + StatBaseAdd : LongInt = 0; + StatBaseDel : LongInt = 0; + + Procedure QwkControl (Idx: LongInt; Mode: Byte); + Begin + OldBase := MBase; + + If GetBaseByIndex(Idx, MBase) Then Begin + GetMessageScan; + + MScan.QwkScan := Mode; + + If Mode = 0 Then Inc (StatBaseDel); + If Mode = 1 Then Inc (StatBaseAdd); + + SetMessageScan; + End; + + MBase := OldBase; + End; + +Begin + If Session.LocalMode Then + Session.FileBase.ExecuteArchive (bbsCfg.QWKPath + bbsCfg.qwkBBSID + '.rep', Session.User.ThisUser.Archive, '*', 2) + Else Begin + If Session.FileBase.SelectProtocol(True, False) = 'Q' Then Exit; + + Session.FileBase.ExecuteProtocol(1, Session.TempPath + bbsCfg.qwkBBSID + '.rep'); + + If Not Session.FileBase.DszSearch(bbsCfg.qwkBBSID + '.rep') Then Begin + Session.io.PromptInfo[1] := bbsCfg.qwkBBSID + '.rep'; + + Session.io.OutFullLn (Session.GetPrompt(84)); + + Exit; + End; + + Session.FileBase.ExecuteArchive (Session.TempPath + bbsCfg.qwkBBSID + '.rep', Session.User.ThisUser.Archive, '*', 2) + End; + + Assign (DataFile, FileFind(Session.TempPath + bbsCfg.qwkBBSID + '.msg')); + + If Not ioReset(DataFile, 1, fmRWDN) Then Begin + Session.io.OutFull (Session.GetPrompt(238)); + DirClean (Session.TempPath, ''); + Exit; + End; + + BlockRead (DataFile, QwkBlock[1], 128); + QwkBlock[0] := #128; + + If Pos(strUpper(bbsCfg.qwkBBSID), strUpper(QwkBlock)) = 0 Then Begin + Session.io.OutFullLn (Session.GetPrompt(239)); + Close (DataFile); + DirClean(Session.TempPath, ''); + Exit; + End; + + Session.io.OutFull (Session.GetPrompt(240)); + + While Not Eof(DataFile) Do Begin + BlockRead (DataFile, QwkHeader, SizeOf(QwkHeader)); + Move (QwkHeader.MsgNum, QwkBlock[1], 7); + + QwkBlock[0] := #7; + + If GetBaseByIndex(strS2I(QwkBlock), TempBase) Then Begin + + If OpenCreateBase(MsgBase, TempBase) Then Begin + + AssignMessageData(MsgBase, TempBase); + + 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 = qwkControlName; + GotControl := False; + + If IsControl And ((MsgBase^.GetSubj = 'ADD') or (MsgBase^.GetSubj = 'DROP')) Then + QwkControl (TempBase.Index, Ord(MsgBase^.GetSubj = 'ADD')); + + For A := 1 to Chunks Do Begin + BlockRead (DataFile, QwkBlock[1], 128); + + QwkBlock[0] := #128; + QwkBlock := strStripR(QwkBlock, ' '); + + For B := 1 to Length(QwkBlock) Do Begin + If QwkBlock[B] = #227 Then Begin + Inc (LineCount); + + If (LineCount < 4) and (Copy(Line, 1, 5) = 'From:') Then + GotControl := True + // Mystic uses the username of the person who uploaded the + // reply package, based on the alias/realname setting of the + // base itself. This prevents people from spoofing "From" + // fields. + // If QWK networking will need to allow this of course + 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[B]; + End; + End; + + If Line <> '' Then MsgBase^.DoStringLn(Line); + + If TempBase.NetType > 0 Then Begin + MsgBase^.DoStringLn (#13 + '--- ' + mysSoftwareID + '/QWK v' + mysVersion + ' (' + OSID + ')'); + MsgBase^.DoStringLn (' * Origin: ' + ResolveOrigin(TempBase) + ' (' + strAddr2Str(MsgBase^.GetOrigAddr) + ')'); + End; + + If Not IsControl Then Begin + MsgBase^.WriteMsg; + + Inc (StatOK); + Inc (Session.User.ThisUser.Posts); + Inc (Session.HistoryPosts); + End; + + MsgBase^.CloseMsgBase; + + Dispose (MsgBase, Done); + End Else + Inc (StatFailed); + End Else + Inc (StatFailed); + End; + + Close (DataFile); + + Assign (ExtFile, FileFind(Session.TempPath + '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 (Session.TempPath, ''); + + Session.io.PromptInfo[1] := strI2S(StatOK); + Session.io.PromptInfo[2] := strI2S(StatFailed); + Session.io.PromptInfo[3] := strI2S(StatBaseAdd); + Session.io.PromptInfo[4] := strI2S(StatBaseDel); + + Session.io.OutFullLn(Session.GetPrompt(503)); +End; + +End. + +// need one of these for the file list compiler now too which MAYBE can be +// used in MUTIL also. lets template and build that out first.. then... +// create and upload QWK/REP packets without relying on BBS specific stuff + +Type + TMsgBaseQWK = Class + User : RecUser; + Extended : Boolean; + + Constructor Create (UD: RecUser; Ext: Boolean); + Function CreatePacket : Boolean; + Function ProcessReply (bbsid, temppath, usernum, var user, forcefrom ): Boolean; + Destructor Destroy; Override; + End;