mysticbbs/mystic/bbs_filebase.pas

4175 lines
112 KiB
ObjectPascal

// ====================================================================
// 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/>.
//
// ====================================================================
Unit bbs_FileBase;
{$I M_OPS.PAS}
Interface
{$DEFINE USEALTPROT}
Uses
m_io_Base,
{$IFDEF WINDOWS}
m_io_Sockets,
{$ENDIF}
{$IFDEF UNIX}
m_io_STDIO,
{$ENDIF}
DOS,
mkCrap,
m_Strings,
m_FileIO,
m_DateTime,
BBS_Records,
BBS_Common,
BBS_DataBase,
BBS_General,
BBS_NodeInfo,
BBS_Ansi_MenuBox,
AView,
{$IFDEF USEALTPROT}
m_Prot_Base,
// m_Prot_Xmodem,
// m_Prot_Ymodem,
m_Prot_Zmodem;
{$ELSE}
m_Protocol_Queue,
m_Protocol_Base,
m_Protocol_Zmodem;
{$ENDIF}
Type
BatchRec = Record
FileName : String[70];
Area : Integer;
Size : LongInt;
End;
TFileBase = Class
FBaseFile : File of RecFileBase;
FDirFile : File of RecFileList;
FScanFile : File of FScanRec;
ProtocolFile : File of RecProtocol;
FGroupFile : File of RecGroup;
ArcFile : File of RecArchive;
FBase : RecFileBase;
FGroup : RecGroup;
FScan : FScanRec;
FDir : RecFileList;
Arc : RecArchive;
Protocol : RecProtocol;
BatchNum : Byte;
Batch : Array[1..mysMaxBatchQueue] of BatchRec;
Constructor Create (Var Owner: Pointer);
Destructor Destroy; Override;
Procedure DszGetFile (Var LogFile: Text; Var FName: String; Var Res: Boolean);
Function DszSearch (FName: String) : Boolean;
Procedure GetTransferTime (Size: Longint; Var Mins : Integer; Var Secs: Byte);
Procedure ExecuteArchive (FName: String; Temp: String; Mask: String; Mode: Byte);
Procedure ExecuteProtocol (Mode: Byte; FName: String);
Function SelectArchive : Boolean;
Function ListFileAreas (Compress: Boolean) : Integer;
Procedure ChangeFileArea (Data: String);
Procedure DownloadFile;
Procedure BatchClear;
Procedure BatchAdd;
Procedure BatchList;
Procedure BatchDelete;
Procedure SetFileScan;
Procedure GetFileScan;
Function SelectProtocol (UseDefault, UseBatch: Boolean) : Char;
Procedure CheckFileNameLength (FPath : String; Var FName: String);
Procedure GetFileDescription (FN: String);
Function CheckFileLimits (DL: Byte; DLK: Integer) : Byte;
Function ArchiveList (FName: String) : Boolean; { was string }
Function ImportDIZ (FN: String) : Boolean;
Function IsDupeFile (FileName : String; Global : Boolean) : Boolean;
Function ListFiles (Mode : Byte; Data : String) : Byte;
Procedure SetFileScanDate;
Function CopiedToTemp (FName: String) : Boolean;
Function SendFile (Data: String) : Boolean;
Procedure DownloadFileList (Data: String);
Function ExportFileList (NewFiles: Boolean; Qwk: Boolean) : Boolean;
Function ArchiveView (FName : String) : Boolean;
Procedure FileGroupChange (Ops: String; FirstBase, Intro : Boolean);
Procedure XferDisconnect;
Procedure UploadFile;
Procedure DownloadBatch;
Procedure NewFileScan (Mode: Char);
Procedure ViewFile;
Procedure ToggleFileNewScan;
Procedure FileSearch;
Procedure DirectoryEditor (Edit: Boolean; Mask: String);
Procedure MassUpload;
End;
Implementation
Uses
bbs_Core,
MPL_Execute;
Constructor TFileBase.Create (Var Owner: Pointer);
Begin
Inherited Create;
FBase.Name := 'None';
FGroup.Name := 'None';
BatchNum := 0;
End;
Destructor TFileBase.Destroy;
Begin
Inherited Destroy;
End;
Procedure TFileBase.DszGetFile (Var LogFile: Text; Var FName: String; Var Res: Boolean);
Type
TLineBuf = Array[0..1024] of Char;
Var
LineBuf : TLineBuf;
WordPos : Integer;
Count : Integer;
Begin
FName := '';
Res := False;
WordPos := 1;
Count := 1;
If EOF(LogFile) Then Exit;
FillChar(LineBuf, SizeOf(LineBuf), #0);
ReadLn (LogFile, LineBuf);
If LineBuf[0] = #0 Then Exit;
Res := Pos(UpCase(LineBuf[0]), 'RSZ') > 0;
// Session.SystemLog('DEBUG: DSZ Status character: ' + LineBuf[0]);
While WordPos < 11 Do Begin
If LineBuf[Count] = #32 Then Begin
Inc (WordPos);
Repeat
Inc (Count);
Until LineBuf[Count] <> #32;
End Else
Inc (Count);
End;
Repeat
FName := FName + LineBuf[Count];
Inc (Count);
Until (LineBuf[Count] = #0) or (Count = 1024);
While FName[Length(FName)] <> #32 Do
Dec(FName[0]);
Dec(FName[0]);
FName := JustFile(FName);
End;
Function TFileBase.DszSearch (FName: String) : Boolean;
Var
LogFile : Text;
FileName : String;
Status : Boolean;
Begin
Result := False;
Assign (LogFile, Session.TempPath + 'xfer.log');
{$I-} Reset(LogFile); {$I+}
If IoResult <> 0 Then Begin
Session.SystemLog('ERROR: Can''t find xfer.log');
Exit;
End;
// Session.SystemLog('DEBUG: DSZ Searching for: ' + FName);
While Not Eof(LogFile) Do Begin
DszGetFile(LogFile, FileName, Status);
// Session.SystemLog('DEBUG: DSZ GetFile returned: ' + FileName + ' (success ' + strI2S(Ord(Status)) + ')');
If strUpper(FileName) = strUpper(FName) Then Begin
Result := Status;
Break;
End;
End;
Close (LogFile);
End;
{$IFNDEF USEALTPROT}
{$IFNDEF UNIX}
Procedure ProtocolStatus (Start, Finish: Boolean; Status: RecProtocolStatus);
Var
KBRate : LongInt;
Begin
Console.WriteXY (19, 10, 113, strPadR(Status.FileName, 56, ' '));
Console.WriteXY (19, 11, 113, strPadR(strComma(Status.FileSize), 15, ' '));
Console.WriteXY (19, 12, 113, strPadR(strComma(Status.Position), 15, ' '));
Console.WriteXY (64, 11, 113, strPadR(strI2S(Status.Errors), 3, ' '));
KBRate := 0;
If (TimerSeconds - Status.StartTime > 0) and (Status.Position > 0) Then
KBRate := Round((Status.Position / (TimerSeconds - Status.StartTime)) / 1024);
Console.WriteXY (64, 12, 113, strPadR(strI2S(KBRate) + ' k/sec', 12, ' '));
End;
{$ENDIF}
{$ENDIF}
{$IFDEF USEALTPROT}
{$IFNDEF UNIX}
Procedure XferStatus (P: AbstractProtocolPtr; First, Last: Boolean);
Var
KBRate : LongInt;
Begin
Console.WriteXY (19, 10, 113, strPadR(P^.PathName, 56, ' '));
Console.WriteXY (19, 11, 113, strPadR(strComma(P^.SrcFileLen), 15, ' '));
Console.WriteXY (19, 12, 113, strPadR(strComma(P^.BytesTransferred), 15, ' '));
Console.WriteXY (64, 11, 113, strPadR(strI2S(P^.TotalErrors), 3, ' '));
KBRate := 0;
If (TimerSeconds - P^.StartTimer > 0) and (P^.BytesTransferred > 0) Then
KBRate := Round((P^.SrcFileLen / (TimerSeconds - P^.StartTimer)) / 1024);
Console.WriteXY (64, 12, 113, strPadR(strI2S(KBRate) + ' k/sec', 12, ' '));
End;
{$ENDIF}
Procedure XferResult (P: AbstractProtocolPTR; Status: LogFileType);
Var
T : Text;
Res : Char;
Begin
Res := '!';
Case Status of
lfReceiveFail,
lfReceiveSkip,
lfTransmitSkip,
lfTransmitFail : Res := 'E';
lfReceiveOk,
lfTransmitOk : Res := 'Z';
End;
If Res <> '!' Then Begin
Assign (T, Session.TempPath + 'xfer.log');
{$I-} Append (T); {$I+}
If IoResult <> 0 Then ReWrite(T);
WriteLn (T, Res + ' 0 0 0 0 0 0 0 0 0 ' + P^.PathName + ' -1');
Close (T);
End;
End;
{$ENDIF}
Procedure TFileBase.ExecuteProtocol (Mode: Byte; FName: String);
// mode: 0=recv batch, 1=recv file, 2=send file, 3= send batch
Var
Command : String;
T : Text;
Res : String;
{$IFNDEF UNIX}
Box : TAnsiMenuBox;
SavedL : Boolean;
SavedA : Boolean;
{$ENDIF}
{$IFDEF USEALTPROT}
Procedure ExecInternal;
Var
Protocol : AbstractProtocolPTR;
Client : TIOBase;
FileList : FileListPTR;
Begin
{$IFDEF UNIX}
Client := TSTDIO.Create;
{$ELSE}
Client := Session.Client;
{$ENDIF}
Command := strStripB(strUpper(Command), ' ');
// If Command = '@XMODEM' Then
// Protocol := New(XmodemProtocolPTR, Init(Client, False, False, 0))
// Else
// If Command = '@YMODEM' Then
// Protocol := New(YmodemProtocolPTR, Init(Client, False, False, 0))
// Else
If Command = '@ZMODEM' Then
Protocol := New(ZmodemProtocolPTR, Init(Client, False))
Else
If Command = '@ZMODEM8' Then
Protocol := New(ZmodemProtocolPTR, Init(Client, True))
Else Begin
// Session.SystemLog('DEBUG: No internal protocol found');
{$IFDEF UNIX}
Client.Free;
{$ENDIF}
Exit;
End;
Protocol^.MakeFileList(FileList, 1024 * 8);
Case Mode of
0 : Protocol^.SetDestinationDirectory(JustPath(FName));
1 : Begin
Protocol^.SetDestinationDirectory(JustPath(FName));
Protocol^.AddFileToList(FileList, FName);
End;
2 : Protocol^.AddFileToList(FileList, FName);
3 : Begin
Assign (T, Session.TempPath + 'file.lst');
Reset (T);
While Not Eof(T) Do Begin
ReadLn (T, Res);
Protocol^.AddFileToList(FileList, Res);
End;
Close (T);
End;
End;
Session.io.BufFlush;
Protocol^.SetFileList(FileList);
Protocol^.SetLogFileProc(@XferResult);
{$IFNDEF UNIX}
Protocol^.SetShowStatusProc(@XferStatus);
SavedL := Session.LocalMode;
SavedA := Console.Active;
Session.LocalMode := True;
Session.io.LocalScreenEnable;
Box := TAnsiMenuBox.Create;
Case Mode of
0..1 : Box.Header := ' Zmodem Upload ';
2..3 : Box.Header := ' Zmodem Download ';
End;
Box.Open (6, 8, 76, 14);
Console.WriteXY ( 8, 10, 112, 'File Name:');
Console.WriteXY (13, 11, 112, 'Size:');
Console.WriteXY ( 9, 12, 112, 'Position:');
Console.WriteXY (56, 11, 112, 'Errors:');
Console.WriteXY (58, 12, 112, 'Rate:');
{$ENDIF}
Case Mode of
0..1 : Protocol^.ProtocolReceive;
2..3 : Protocol^.ProtocolTransmit;
End;
{$IFNDEF UNIX}
Box.Free;
Session.io.BufFlush;
If Not SavedA Then
Session.io.LocalScreenDisable;
Session.LocalMode := SavedL;
{$ENDIF}
Protocol^.DisposeFileList(FileList, 8 * 1024);
Dispose (Protocol, Done);
{$IFDEF UNIX}
Client.Free;
{$ENDIF}
End;
{$ELSE}
Procedure ExecInternal;
Var
Protocol : TProtocolBase;
Queue : TProtocolQueue;
Count : Word;
Client : TIOBase;
Begin
{$IFDEF UNIX}
Client := TSTDIO.Create;
{$ELSE}
Client := Session.Client;
{$ENDIF}
Command := strStripB(strUpper(Command), ' ');
Queue := TProtocolQueue.Create;
If Command = '@ZMODEM' Then
Protocol := TProtocolZmodem.Create(Client, Queue)
Else If Command = '@ZMODEM8' Then Begin
Protocol := TProtocolZmodem.Create(Client, Queue);
TProtocolZmodem(Protocol).CurBufSize := 8 * 1024;
End Else Begin
{$IFDEF UNIX}
Client.Free;
{$ENDIF}
Queue.Free;
Exit;
End;
Case Mode of
0,
1 : Protocol.ReceivePath := DirSlash(FName);
2 : Queue.Add(True, JustPath(FName), JustFile(FName));
3 : Begin
Assign (T, Session.TempPath + 'file.lst');
Reset (T);
While Not Eof(T) Do Begin
ReadLn (T, Res);
Queue.Add(True, JustPath(Res), JustFile(Res));
End;
Close (T);
End;
End;
Session.io.BufFlush;
{$IFNDEF UNIX}
SavedL := Session.LocalMode;
SavedA := Console.Active;
Session.LocalMode := True;
Protocol.StatusProc := ProtocolStatus;
Session.io.LocalScreenEnable;
Box := TAnsiMenuBox.Create;
Case Mode of
0..1 : Box.Header := ' ' + Protocol.Status.Protocol + ' Upload ';
2..3 : Box.Header := ' ' + Protocol.Status.Protocol + ' Download ';
End;
Box.Open (6, 8, 76, 14);
Console.WriteXY ( 8, 10, 112, 'File Name:');
Console.WriteXY (13, 11, 112, 'Size:');
Console.WriteXY ( 9, 12, 112, 'Position:');
Console.WriteXY (56, 11, 112, 'Errors:');
Console.WriteXY (58, 12, 112, 'Rate:');
{$ENDIF}
Case Mode of
0..1 : Protocol.QueueReceive;
2..3 : Protocol.QueueSend;
End;
{$IFNDEF UNIX}
Box.Free;
Session.io.BufFlush;
If Not SavedA Then
Session.io.LocalScreenDisable;
Session.LocalMode := SavedL;
{$ENDIF}
If Queue.QSize > 0 Then Begin
Assign (T, Session.TempPath + 'xfer.log');
ReWrite (T);
For Count := 1 to Queue.QSize Do Begin
Res[1] := 'E';
If Queue.QData[Count]^.Status = QueueSuccess Then Res[1] := 'Z';
WriteLn(T, Res[1] + ' 0 0 0 0 0 0 0 0 0 ' + Queue.QData[Count]^.FileName + ' -1');
End;
Close (T);
End;
Protocol.Free;
Queue.Free;
{$IFDEF UNIX}
Client.Free;
{$ENDIF}
End;
{$ENDIF}
Procedure ExecExternal;
Var
Path : String;
Count : Byte;
Begin
Res := '';
Path := '';
Count := 1;
While Count <= Length(Command) Do Begin
If Command[Count] = '%' Then Begin
Inc(Count);
{$IFNDEF UNIX}
If Command[Count] = '0' Then Res := Res + strI2S(TIOSocket(Session.Client).FSocketHandle) Else
{$ENDIF}
If Command[Count] = '1' Then Res := Res + '1' Else
If Command[Count] = '2' Then Res := Res + strI2S(Session.Baud) Else
If Command[Count] = '3' Then Res := Res + FName Else
If Command[Count] = '4' Then Res := Res + Session.UserIPInfo Else
If Command[Count] = '5' Then Res := Res + Session.UserHostInfo Else
If Command[Count] = '6' Then Res := Res + strReplace(Session.User.ThisUser.Handle, ' ', '_') Else
If Command[Count] = '7' Then Res := Res + strI2S(Session.NodeNum);
End Else
Res := Res + Command[Count];
Inc (Count);
End;
{$IFDEF UNIX}
Assign (T, Session.TempPath + 'xfer.sh');
ReWrite (T);
WriteLn (T, 'export DSZLOG=' + Session.TempPath + 'xfer.log');
WriteLn (T, Res);
Close (T);
{$ELSE}
Assign (T, Session.TempPath + 'xfer.bat');
ReWrite (T);
WriteLn (T, 'SET DSZLOG=' + Session.TempPath + 'xfer.log');
WriteLn (T, Res);
Close (T);
{$ENDIF}
// If uploading and batch, switch to upload directory via shelldos
If (Mode < 2) And Protocol.Batch Then Path := FName;
If Res[1] = '!' Then Begin
Delete (Res, 1, 1);
ExecuteMPL (NIL, Res);
End Else
{$IFDEF UNIX}
ShellDOS (Path, 'sh ' + Session.TempPath + 'xfer.sh');
{$ELSE}
ShellDOS (Path, Session.TempPath + 'xfer.bat');
{$ENDIF}
DirChange (bbsCfg.SystemPath);
End;
Begin
If Session.LocalMode Then Begin
Session.io.OutFullLn(Session.GetPrompt(63));
Exit;
End;
Set_Node_Action(Session.GetPrompt(351));
If Mode > 1 Then
Command := Protocol.SendCmd
Else
Command := Protocol.RecvCmd;
// Session.SystemLog('DEBUG: Exec Protocol: ' + Command);
If Command[1] = '@' Then
ExecInternal
Else
ExecExternal;
End;
Procedure TFileBase.GetTransferTime (Size: Longint; Var Mins : Integer; Var Secs: Byte);
Var
B : LongInt;
Begin
B := 0;
If Not Session.LocalMode Then B := Size DIV (Session.Baud DIV 10);
Mins := B DIV 60;
Secs := B MOD 60;
End;
Function TFileBase.ImportDIZ (FN: String) : Boolean;
Procedure RemoveLine (Num: Byte);
Var
Count : Byte;
Begin
For Count := Num To FDir.DescLines - 1 Do
Session.Msgs.Msgtext[Count] := Session.Msgs.MsgText[Count + 1];
Session.Msgs.MsgText[FDir.DescLines] := '';
Dec (FDir.DescLines);
End;
Var
DizFile : Text;
DizName : String;
{$IFDEF FS_SENSITIVE}
Arc : PArchive;
SR : ArcSearchRec;
{$ENDIF}
Begin
Result := False;
DizName := 'file_id.diz';
{$IFDEF FS_SENSITIVE}
Arc := New(PArchive, Init);
If Arc^.Name(FN) Then Begin
Arc^.FindFirst(SR);
While SR.Name <> '' Do Begin
If Pos('FILE_ID.DIZ', strUpper(SR.Name)) > 0 Then Begin
DizName := strStripLow(SR.Name);
Break;
End;
Arc^.FindNext(SR);
End;
Dispose (Arc, Done);
End;
{$ENDIF}
ExecuteArchive (FBase.Path + FN, '', DizName, 2);
DizName := FileFind(Session.TempPath + 'file_id.diz');
Assign (DizFile, DizName);
{$I-} Reset (DizFile); {$I+}
If IoResult = 0 Then Begin
Result := True;
FDir.DescLines := 0;
While Not Eof(DizFile) Do Begin
Inc (FDir.DescLines);
ReadLn (DizFile, Session.Msgs.MsgText[FDir.DescLines]);
Session.Msgs.MsgText[FDir.DescLines] := strStripLOW(Session.Msgs.MsgText[FDir.DescLines]);
If Length(Session.Msgs.MsgText[FDir.DescLines]) > mysMaxFileDescLen Then Session.Msgs.MsgText[FDir.DescLines][0] := Chr(mysMaxFileDescLen);
If FDir.DescLines = bbsCfg.MaxFileDesc Then Break;
End;
Close (DizFile);
FileErase(DizName);
While (Session.Msgs.MsgText[1] = '') and (FDir.DescLines > 0) Do
RemoveLine(1);
While (Session.Msgs.MsgText[FDir.DescLines] = '') And (FDir.DescLines > 0) Do
Dec (FDir.DescLines);
End;
End;
Procedure TFileBase.SetFileScan;
Var
A : Integer;
Temp : FScanRec;
Begin
Temp.NewScan := FBase.DefScan;
Temp.LastNew := CurDateDos;
If Temp.NewScan = 2 Then Dec (Temp.NewScan);
Assign (FScanFile, bbsCfg.DataPath + FBase.FileName + '.scn');
{$I-} Reset (FScanFile); {$I+}
If IoResult <> 0 Then ReWrite (FScanFile);
If FileSize(FScanFile) < Session.User.UserNum - 1 Then Begin
Seek (FScanFile, FileSize(FScanFile));
For A := FileSize(FScanFile) to Session.User.UserNum - 1 Do
Write (FScanFile, Temp);
End;
Seek (FScanFile, Session.User.UserNum - 1);
Write (FScanFile, FScan);
Close (FScanFile);
End;
Procedure TFileBase.GetFileScan;
Begin
FScan.NewScan := FBase.DefScan;
FScan.LastNew := CurDateDos;
If FScan.NewScan = 2 Then Dec(FScan.NewScan);
Assign (FScanFile, bbsCfg.DataPath + FBase.FileName + '.scn');
{$I-} Reset (FScanFile); {$I+}
If IoResult <> 0 Then Exit;
If FileSize(FScanFile) >= Session.User.UserNum Then Begin
Seek (FScanFile, Session.User.UserNum - 1);
Read (FScanFile, FScan);
End;
Close (FScanFile);
End;
Procedure TFileBase.SetFileScanDate;
Var
L : LongInt;
Old : RecFileBase;
Str : String;
Begin
Session.io.OutFull (Session.GetPrompt(255));
If FBase.FileName <> '' Then Begin
GetFileScan;
L := FScan.LastNew;
End Else
L := CurDateDos;
Str := Session.io.GetInput(8, 8, 15, DateDos2Str(L, Session.User.ThisUser.DateType));
If Not DateValid(Str) Then Exit;
L := DateStr2Dos(Str);
If Session.io.GetYN (Session.GetPrompt(256), False) Then Begin
Reset (FBaseFile);
Old := FBase;
While Not Eof(FBaseFile) Do Begin
Read (FBaseFile, FBase);
GetFileScan;
FScan.LastNew := L;
SetFileScan;
End;
Close (FBaseFile);
FBase := Old;
End Else Begin
If FBase.FileName = '' Then Begin
Session.io.OutFullLn (Session.GetPrompt(38));
Exit;
End;
GetFileScan;
FScan.LastNew := L;
SetFileScan;
End;
Session.io.PromptInfo[1] := DateDos2Str(L, Session.User.ThisUser.DateType);
Session.io.OutFull (Session.GetPrompt(257));
End;
Function TFileBase.SendFile (Data: String) : Boolean;
Begin
Result := False;
// Session.SystemLog('DEBUG: In SendFile checking if exists: ' + Data);
If Not FileExist(Data) Then Exit;
// Session.SystemLog('DEBUG: Calling SelectProtocol w/ use default');
If SelectProtocol(True, False) = 'Q' Then Exit;
// Session.SystemLog('DEBUG: Calling ExecuteProtocol');
ExecuteProtocol(2, Data);
Session.io.OutRawLn ('');
Session.io.PromptInfo[1] := JustFile(Data);
If DszSearch(JustFile(Data)) Then Begin
Result := True;
Session.io.OutFullLn (Session.GetPrompt(385));
End Else
Session.io.OutFullLn (Session.GetPrompt(386));
FileErase (Session.TempPath + 'xfer.log');
End;
Procedure TFileBase.DownloadFileList (Data: String);
Var
A : Byte;
NewFiles : Boolean;
FileName : String[12];
Begin
NewFiles := False;
FileName := 'allfiles.';
For A := 1 to strWordCount(Data, ' ') Do
If Pos('/NEW', strWordGet(A, Data, ' ')) > 0 Then Begin
NewFiles := True;
FileName := 'newfiles.';
End Else
If Pos('/ALLGROUP', strWordGet(A, Data, ' ')) > 0 Then
Session.User.IgnoreGroup := True;
If ExportFileList(NewFiles, False) Then Begin
If Session.io.GetYN (Session.GetPrompt(227), True) Then Begin
FileName := FileName + Session.User.ThisUser.Archive;
ExecuteArchive (Session.TempPath + FileName, Session.User.ThisUser.Archive, Session.TempPath + '*', 1);
End Else
FileName := FileName + 'txt';
SendFile (Session.TempPath + FileName);
End;
DirClean(Session.TempPath, '');
Session.User.IgnoreGroup := False;
End;
Function TFileBase.ExportFileList (NewFiles : Boolean; Qwk: Boolean) : Boolean;
Var
TF : Text;
DF : File;
Count : Byte;
Temp : String[mysMaxFileDescLen];
Str : String;
AreaFiles : LongInt;
AreaSize : Cardinal;
TotalFiles : LongInt;
Begin
If NewFiles Then Begin
If Qwk Then Temp := 'newfiles.dat' Else Temp := 'newfiles.txt';
Session.io.OutFullLn (Session.GetPrompt(219));
End Else Begin
Temp := 'allfiles.txt';
Session.io.OutFullLn (Session.GetPrompt(220));
End;
Session.io.OutFullLn (Session.GetPrompt(221));
Assign (TF, Session.TempPath + Temp);
ReWrite (TF);
TotalFiles := 0;
Reset (FBaseFile);
While Not Eof(FBaseFile) Do Begin
Read (FBaseFile, FBase);
If Not Session.User.Access(FBase.ListACS) Then Continue;
Session.io.OutFull (Session.GetPrompt(222));
GetFileScan;
AreaFiles := 0;
AreaSize := 0;
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (FDirFile); {$I+}
If IoResult = 0 Then Begin
Assign (DF, bbsCfg.DataPath + FBase.FileName + '.des');
{$I-} Reset (DF, 1); {$I+}
If IoResult <> 0 Then ReWrite (DF, 1);
While Not Eof(FDirFile) Do Begin
Read (FDirFile, FDir);
If (NewFiles and (FDir.DateTime > FScan.LastNew)) or Not NewFiles Then
If FDir.Flags And FDirDeleted = 0 Then Begin
Inc (TotalFiles);
Inc (AreaFiles);
Inc (AreaSize, (FDir.Size DIV 1024) DIV 1024);
If AreaFiles = 1 Then Begin
WriteLn (TF, '');
WriteLn (TF, '.-' + strRep('-', Length(strStripPipe(FBase.Name))) + '-.');
WriteLn (TF, '| ' + strStripPipe(FBase.Name) + ' |');
WriteLn (TF, '`-' + strRep('-', Length(strStripPipe(FBase.Name))) + '-''');
WriteLn (TF, '.' + strRep('-', 77) + '.');
WriteLn (TF, '| File Size Date Description |');
WriteLn (TF, '`' + strRep('-', 77) + '''');
End;
WriteLn (TF, FDir.FileName);
Write (TF, ' `- ' + strPadL(strComma(FDir.Size), 11, ' ') + ' ' + DateDos2Str(FDir.DateTime, Session.User.ThisUser.DateType) + ' ');
Seek (DF, FDir.DescPtr);
For Count := 1 to FDir.DescLines Do Begin
BlockRead (DF, Temp[0], 1);
BlockRead (DF, Temp[1], Ord(Temp[0]));
If Count = 1 Then WriteLn (TF, Temp) Else WriteLn (TF, strRep(' ', 27) + Temp);
End;
End;
End;
Session.io.PromptInfo[2] := strI2S(FileSize(FDirFile));
Close (FDirFile);
Close (DF);
SetFileScan;
If AreaFiles > 0 Then Begin
Str := 'Total files: ' + strI2S(AreaFiles) + ' (' + strI2S(AreaSize) + 'mb)';
WriteLn (TF, '.' + strRep('-', 77) + '.');
WriteLn (TF, '| ' + strPadR(Str, 76, ' ') + '|');
WriteLn (TF, '`' + strRep('-', 77) + '''');
End;
End Else
Session.io.PromptInfo[2] := '0';
Session.io.PromptInfo[1] := FBase.Name;
Session.io.PromptInfo[3] := strI2S(AreaFiles);
Session.io.OutBS (Console.CursorX, False);
Session.io.OutFullLn (Session.GetPrompt(223));
End;
Close (FBaseFile);
Close (TF);
Session.io.OutFullLn (Session.GetPrompt(225));
Result := (TotalFiles > 0);
If Not Result Then Session.io.OutFullLn(Session.GetPrompt(425));
End;
Function TFileBase.ArchiveList (FName : String) : Boolean;
Var
ArcView : PArchive;
SR : ArcSearchRec;
Begin
Result := False;
If Not FileExist(FName) Then Exit;
ArcView := New(PArchive, Init);
If Not ArcView^.Name(FName) Then Begin
Dispose (ArcView, Done);
If FileExist(FName) Then Begin
ExecuteArchive (FName, '', '_view_.tmp', 3);
Result := Session.io.OutFile (Session.TempPath + '_view_.tmp', True, 0);
FileErase (Session.TempPath + '_view_.tmp');
End;
Exit;
End;
Session.io.AllowPause := True;
Session.io.PausePtr := 1;
Session.io.PromptInfo[1] := JustFile(FName);
Session.io.OutFullLn (Session.GetPrompt(192));
ArcView^.FindFirst(SR);
While SR.Name <> '' Do Begin
Session.io.PromptInfo[1] := SR.Name;
If SR.Attr = $10 Then
Session.io.PromptInfo[2] := '<DIRECTORY>' {++lang}
Else
Session.io.PromptInfo[2] := strComma(SR.Size);
Session.io.PromptInfo[3] := DateDos2Str(SR.Time, Session.User.ThisUser.DateType);
Session.io.PromptInfo[4] := TimeDos2Str(SR.Time, 1);
Session.io.OutFullLn (Session.GetPrompt(193));
If (Session.io.PausePtr >= Session.User.ThisUser.ScreenSize) and (Session.io.AllowPause) Then
Case Session.io.MorePrompt of
'N' : Break;
'C' : Session.io.AllowPause := False;
End;
ArcView^.FindNext(SR);
End;
Dispose (ArcView, Done);
Result := True;
Session.io.OutFull (Session.GetPrompt(194));
End;
Function TFileBase.CheckFileLimits (DL: Byte; DLK: Integer) : Byte;
{ 0 = OK to download }
{ 1 = Offline or Invalid or Failed : NO ACCESS (prompt 224)}
{ 2 = DL per day limit exceeded (prompt 58) }
{ 3 = UL/DL file ratio bad (prompt 211) }
Var
A : Byte;
Begin
Result := 1;
If FDir.Flags And FDirOffline <> 0 Then Exit;
If (FDir.Flags And FDirInvalid <> 0) And Not Session.User.Access(bbsCfg.AcsDLUnvalid) Then Exit;
If (FDir.Flags And FDirFailed <> 0) And Not Session.User.Access(bbsCfg.AcsDLFailed) Then Exit;
If (FDir.Flags And FDirFree <> 0) or (Session.User.ThisUser.Flags and UserNoRatio <> 0) or (FBase.Flags and FBFreeFiles <> 0) Then Begin
Result := 0;
Exit;
End;
If (Session.User.ThisUser.DLsToday + BatchNum + DL > Session.User.Security.MaxDLs) and (Session.User.Security.MaxDLs > 0) Then Begin
Result := 2;
Exit;
End;
If (Session.User.Security.DLRatio > 0) and ((Session.User.ThisUser.DLs <> 0) or (Session.User.ThisUser.ULs <> 0)) Then
If (Session.User.ThisUser.ULs * Session.User.Security.DLRatio) <= (Session.User.ThisUser.DLs + BatchNum + DL) Then Begin
Result := 3;
Exit;
End;
If BatchNum > 0 Then
For A := 1 to BatchNum Do
Inc (DLK, Batch[A].Size DIV 1024);
If (Session.User.Security.DLKRatio > 0) and ((Session.User.ThisUser.DLs <> 0) or (Session.User.ThisUser.ULs <> 0)) Then
If (Session.User.ThisUser.ULk * Session.User.Security.DLkRatio) <= (Session.User.ThisUser.DLk + DLk) Then Begin
Result := 3;
Exit;
End;
If (Session.User.ThisUser.DLkToday + DLk > Session.User.Security.MaxDLk) and (Session.User.Security.MaxDLk > 0) Then Begin
Result := 2;
Exit;
End;
Result := 0;
End;
Function TFileBase.ArchiveView (FName: String) : Boolean;
Var
Mask : String[70];
Begin
Result := ArchiveList(FName);
If Not Result Then Exit;
Repeat
Session.io.OutFull (Session.GetPrompt(304));
Case Session.io.OneKey('DQRV', True) of
'D' : Begin
Session.io.OutFull (Session.GetPrompt(384));
Mask := Session.io.GetInput (70, 70, 11, '');
If Mask <> '' Then Begin
ExecuteArchive (FName, '', Mask, 2);
If FileExist(Session.TempPath + Mask) Then Begin
Case CheckFileLimits (1, FileByteSize(Session.TempPath + Mask) DIV 1024) of
0 : If SendFile (Session.TempPath + Mask) Then Begin;
Session.SystemLog ('Download from ' + FName + ': ' + Mask);
Inc (Session.User.ThisUser.DLs);
Inc (Session.User.ThisUser.DLsToday);
Inc (Session.User.ThisUser.DLk, FDir.Size DIV 1024);
Inc (Session.User.ThisUser.DLkToday, FDir.Size DIV 1024);
Inc (Session.HistoryDLs);
Inc (Session.HistoryDLKB, FDir.Size DIV 1024);
End;
1 : Session.io.OutFullLn (Session.GetPrompt(224));
2 : Session.io.OutFullLn (Session.GetPrompt(58));
3 : Session.io.OutFullLn (Session.GetPrompt(211));
End;
FileErase(Session.TempPath + Mask);
End;
End;
End;
'Q' : Exit;
'R' : ArchiveList(FName);
'V' : Begin
Session.io.OutFull (Session.GetPrompt(384));
Mask := Session.io.GetInput (70, 70, 11, '');
If Mask <> '' Then Begin
ExecuteArchive (FName, '', Mask, 2);
If Not ArchiveList(Session.TempPath + Mask) Then Begin
Session.io.PromptInfo[1] := Mask;
Session.io.OutFullLn(Session.GetPrompt(306));
Session.io.AllowMCI := False;
Session.io.OutFile (Session.TempPath + Mask, True, 0);
Session.io.AllowMCI := True;
If Session.io.NoFile Then
Session.io.OutFullLn (Session.GetPrompt(305));
End;
FileErase(Session.TempPath + Mask);
End;
End;
End;
Until False;
End;
Procedure TFileBase.ToggleFileNewScan;
Var
Total : Word;
Procedure List_Bases;
Begin
Session.io.PausePtr := 1;
Session.io.AllowPause := True;
Session.io.OutFullLn (Session.GetPrompt(200));
Total := 0;
FileMode := 66;
Reset (FBaseFile);
While Not Eof(FBaseFile) Do Begin
Read (FBaseFile, FBase);
If Session.User.Access(FBase.ListACS) Then Begin
Inc (Total);
Session.io.PromptInfo[1] := strI2S(Total);
Session.io.PromptInfo[2] := FBase.Name;
GetFileScan;
Session.io.PromptInfo[3] := Session.io.OutYN(FScan.NewScan > 0);
Session.io.OutFull (Session.GetPrompt(201));
If (Total MOD bbsCfg.FColumns = 0) And (Total > 0) Then Session.io.OutRawLn('');
End;
If EOF(FBaseFile) and (Total MOD bbsCfg.FColumns <> 0) Then Session.io.OutRawLn('');
If (Session.io.PausePtr = Session.User.ThisUser.ScreenSize) and (Session.io.AllowPause) Then
Case Session.io.MorePrompt of
'N' : Break;
'C' : Session.io.AllowPause := False;
End;
End;
Session.io.OutFull (Session.GetPrompt(449));
End;
Procedure ToggleBase (A : Word);
Var
B : Word;
Begin
If A = 0 Then Exit;
B := 0;
FileMode := 66;
Reset (FBaseFile);
Repeat
{$I-} Read (FBaseFile, FBase); {$I+}
If IoResult <> 0 Then Exit;
If Session.User.Access(FBase.ListACS) Then Inc(B);
If A = B Then Break;
Until False;
GetFileScan;
Session.io.PromptInfo[1] := FBase.Name;
If FBase.DefScan = 2 Then Begin
FScan.NewScan := 1;
Session.io.OutFullLn (Session.GetPrompt(289));
End Else
If FScan.NewScan = 0 Then Begin
FScan.NewScan := 1;
Session.io.OutFullLn (Session.GetPrompt(204));
End Else Begin
FScan.NewScan := 0;
Session.io.OutFullLn (Session.GetPrompt(203));
End;
SetFileScan;
End;
Var
Old : RecFileBase;
Temp : String[40];
Count1 : LongInt;
Count2 : LongInt;
Num1 : String[40];
Num2 : String[40];
Begin
Old := FBase;
List_Bases;
If Total = 0 Then Begin
Session.io.OutFullLn (Session.GetPrompt(37));
FBase := Old;
Exit;
End;
Repeat
Session.io.OutFull (Session.GetPrompt(202));
Temp := Session.io.GetInput(10, 40, 12, '');
If (Temp = '') or (Temp = 'Q') Then Break;
If Temp = '?' Then
List_Bases
Else Begin
Num1 := '';
Num2 := '';
For Count1 := 1 to Length(Temp) Do Begin
If Temp[Count1] = ' ' Then Continue;
If Temp[Count1] = ',' Then Begin
If Num2 <> '' Then Begin
For Count2 := strS2I(Num2) to strS2I(Num1) Do
ToggleBase(Count2);
End Else
ToggleBase(strS2I(Num1));
Num1 := '';
Num2 := '';
End Else
If Temp[Count1] = '-' Then Begin
Num2 := Num1;
Num1 := '';
End Else
Num1 := Num1 + Temp[Count1];
End;
If Num2 <> '' Then Begin
For Count1 := strS2I(Num2) to strS2I(Num1) Do
ToggleBase(Count1);
End Else
ToggleBase(strS2I(Num1));
List_Bases;
End;
Until False;
Close (FBaseFile);
FBase := Old;
End;
Function TFileBase.SelectArchive : Boolean;
Var
NewArc : SmallInt;
Count : SmallInt;
Begin
Result := False;
Count := 0;
Reset (ArcFile);
While Not Eof(ArcFile) Do Begin
Read (ArcFile, Arc);
If Arc.Active and ((Arc.OSType = OSType) or (Arc.OSType = 3)) Then Begin
Inc (Count);
If Count = 1 Then
Session.io.OutFullLn (Session.GetPrompt(73));
Session.io.PromptInfo[1] := strI2S(Count);
Session.io.PromptInfo[2] := Arc.Desc;
Session.io.PromptInfo[3] := Arc.Ext;
Session.io.OutFullLn (Session.GetPrompt(170));
End;
End;
If Count = 0 Then Begin
Session.io.OutFullLn (Session.GetPrompt(169));
Close (ArcFile);
Exit;
End;
Session.io.OutFull (Session.GetPrompt(171));
NewArc := strS2I(Session.io.GetInput(2, 2, 12, ''));
If (NewArc > 0) and (NewArc <= Count) Then Begin
Reset (ArcFile);
Count := 0;
While Not Eof(ArcFile) And (Count <> NewArc) Do Begin
Read (ArcFile, Arc);
If (Arc.Active) and ((Arc.OSType = OSType) or (Arc.OSType = 3)) Then
Inc (Count);
End;
End Else Begin
Close (ArcFile);
Exit;
End;
Close (ArcFile);
Session.io.PromptInfo[1] := Arc.Ext;
Session.io.OutFullLn (Session.GetPrompt(74));
Session.User.ThisUser.Archive := Arc.Ext;
Result := True;
End;
Function TFileBase.SelectProtocol (UseDefault, UseBatch: Boolean) : Char;
Function LoadByKey (Key: Char) : Boolean;
Begin
Result := False;
// Session.SystemLog('DEBUG: In LoadByByDefault.');
If Key = 'Q' Then Exit;
FileMode := 66;
Reset (ProtocolFile);
While Not Eof(ProtocolFile) Do Begin
Read (ProtocolFile, Protocol);
If ((Protocol.Active) And (Key = Protocol.Key) And (Protocol.Batch = UseBatch) And ((Protocol.OSType = OSType) or (Protocol.OSType = 3))) Then Begin
Result := True;
Break;
End;
End;
Close(ProtocolFile);
// Session.SystemLog('DEBUG: LoadKeyByDefault result=' + Session.io.OutYN(Result));
End;
Var
SavedP1 : String;
SavedP2 : String;
Keys : String;
Begin
SavedP1 := Session.io.PromptInfo[1];
SavedP2 := Session.io.PromptInfo[2];
Result := Session.User.ThisUser.Protocol;
If Result = 'Q' Then Result := #0;
//Session.SystemLog('DEBUG: In SelectProtocol');
If Not LoadByKey(Result) Or Not UseDefault Then Begin
Keys := 'Q';
Session.io.OutFullLn(Session.GetPrompt(359));
Reset (ProtocolFile);
While Not Eof(ProtocolFile) Do Begin
Read (ProtocolFile, Protocol);
If Protocol.Active And (Protocol.Batch = UseBatch) And ((Protocol.OSType = OSTYpe) or (Protocol.OSType = 3)) Then Begin
Keys := Keys + Protocol.Key;
Session.io.PromptInfo[1] := Protocol.Key;
Session.io.PromptInfo[2] := Protocol.Desc;
Session.io.OutFullLn (Session.GetPrompt(61));
End;
End;
Close (ProtocolFile);
Session.io.OutFull (Session.GetPrompt(62));
Result := Session.io.OneKey(Keys, True);
If Result = 'Q' Then Begin
Session.io.PromptInfo[1] := SavedP1;
Session.io.PromptInfo[2] := SavedP2;
Exit;
End;
End;
LoadByKey(Result);
Session.io.PromptInfo[1] := Protocol.Desc;
Session.io.OutFullLn (Session.GetPrompt(65));
Session.io.PromptInfo[1] := SavedP1;
End;
Procedure TFileBase.ExecuteArchive (FName: String; Temp: String; Mask: String; Mode: Byte);
{mode: 1 = pack, 2 = unpack, 3 = view}
Var
A : Byte;
Temp2 : String[60];
Begin
// Session.SystemLog('DEBUG: In ExecuteArchive');
If Temp = '' Then
Case GetArchiveType(FName) of
'A' : Temp := 'ARJ';
'L' : Begin
Temp := 'LZH';
If strUpper(JustFileExt(FName)) = 'LHA' Then Temp := 'LHA';
End;
'R' : Temp := 'RAR';
'Z' : Temp := 'ZIP';
'?' : Temp := strUpper(JustFileExt(FName));
End;
// Session.SystemLog('DEBUG: ExecArc found type ' + Temp);
FileMode := 66;
Reset (ArcFile);
Repeat
If Eof(ArcFile) Then Begin
Close (ArcFile);
Exit;
End;
Read (ArcFile, Arc);
// Session.SystemLog('DEBUG: ExecArc read one');
If (Not Arc.Active) or ((Arc.OSType <> OSType) and (Arc.OSType <> 3)) Then
Continue;
If strUpper(Arc.Ext) = Temp Then Break;
Until False;
Close (ArcFile);
// Session.SystemLog('DEBUG: ExecArc found config for ' + Arc.Ext);
Case Mode of
1 : Temp2 := Arc.Pack;
2 : Temp2 := Arc.Unpack;
3 : Temp2 := Arc.View;
End;
If Temp2 = '' Then Exit;
Temp := '';
A := 1;
While A <= Length(Temp2) Do Begin
If Temp2[A] = '%' Then Begin
Inc(A);
If Temp2[A] = '1' Then Temp := Temp + FName Else
If Temp2[A] = '2' Then Temp := Temp + Mask Else
If Temp2[A] = '3' Then Temp := Temp + Session.TempPath;
End Else
Temp := Temp + Temp2[A];
Inc(A);
End;
//Session.SystemLog('DEBUG: ExecArc build exec for: ' + Temp);
ShellDOS ('', Temp);
End;
(*************************************************************************)
Procedure TFileBase.ViewFile;
Var
FName : String[70];
Old : RecFileBase;
Begin
Session.io.OutFull (Session.GetPrompt(353));
FName := Session.io.GetInput(70, 70, 11, '');
If FName = '' Then Exit;
Old := FBase;
Reset (FBaseFile);
While Not Eof(FBaseFile) Do Begin
Read (FBaseFile, FBase);
If Session.User.Access(FBase.ListACS) Then Begin
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (FDirFile); {$I+}
If IoResult <> 0 Then ReWrite (FDirFile);
While Not Eof(FDirFile) Do Begin
Read (FDirFile, FDir);
If FDir.FileName = FName Then Begin
If Not ArchiveView (FBase.Path + FName) Then Session.io.OutFullLn(Session.GetPrompt(191));
Close (FDirFile);
Close (FBaseFile);
FBase := Old;
Exit;
End;
End;
Close (FDirFile);
End;
End;
Close (FBaseFile);
FBase := Old;
Session.io.OutFullLn (Session.GetPrompt(51));
End;
Procedure TFileBase.BatchList;
Var
A : Byte;
M : Integer;
S : Byte;
Begin
If BatchNum = 0 Then Begin
Session.io.OutFullLn (Session.GetPrompt(52));
Exit;
End;
Session.io.OutFullLn (Session.GetPrompt(56));
For A := 1 to BatchNum Do Begin
GetTransferTime (Batch[A].Size, M, S);
Session.io.PromptInfo[1] := strI2S(A);
Session.io.PromptInfo[2] := Batch[A].FileName;
Session.io.PromptInfo[3] := strComma(Batch[A].Size);
Session.io.PromptInfo[4] := strI2S(M);
Session.io.PromptInfo[5] := strI2S(S);
Session.io.OutFullLn (Session.GetPrompt(57));
End;
Session.io.OutFullLn (Session.GetPrompt(428));
End;
Procedure TFileBase.BatchClear;
Begin
BatchNum := 0;
Session.io.OutFullLn (Session.GetPrompt(59));
End;
Procedure TFileBase.BatchAdd;
Var
FName : String[70];
A : Byte;
Old : RecFileBase;
OkSave : Boolean;
Begin
If BatchNum = mysMaxBatchQueue Then Begin
Session.io.OutFullLn (Session.GetPrompt(46));
Exit;
End;
Session.io.OutFull (Session.GetPrompt(47));
FName := Session.io.GetInput(70, 70, 11, '');
If FName = '' Then Exit;
Old := FBase;
Reset (FBaseFile);
While Not Eof(FBaseFile) Do Begin
Read (FBaseFile, FBase);
If Session.User.Access(FBase.ListACS) and Session.User.Access(FBase.DLACS) Then Begin
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (FDirFile); {$I+}
If IoResult <> 0 Then ReWrite (FDirFile);
While Not Eof(FDirFile) Do Begin
Read (FDirFile, FDir);
{$IFDEF FS_SENSITIVE}
If (FDir.FileName = FName) And (FDir.Flags And FDirDeleted = 0) Then Begin
{$ELSE}
If (strUpper(FDir.FileName) = strUpper(FName)) And (FDir.Flags And FDirDeleted = 0) Then Begin
{$ENDIF}
okSave := False;
Case CheckFileLimits(1, FDir.Size DIV 1024) of
0 : okSave := True;
1 : Session.io.OutFullLn (Session.GetPrompt(224));
2 : Session.io.OutFullLn (Session.GetPrompt(58));
3 : Session.io.OutFullLn (Session.GetPrompt(211));
End;
For A := 1 to BatchNum Do
If FName = Batch[A].FileName Then Begin
Session.io.OutFullLn (Session.GetPrompt(49));
OkSave := False;
End;
If OkSave Then Begin
Session.io.PromptInfo[1] := FName;
Session.io.PromptInfo[2] := strComma(FDir.Size);
Session.io.OutFullLn (Session.GetPrompt(50));
Inc (BatchNum);
Batch[BatchNum].FileName := FName;
Batch[BatchNum].Area := FilePos(FBaseFile);
Batch[BatchNum].Size := FDir.Size;
End;
Close (FDirFile);
Close (FBaseFile);
FBase := Old;
Exit;
End;
End;
Close (FDirFile);
End;
End;
Close (FBaseFile);
FBase := Old;
Session.io.OutFullLn (Session.GetPrompt(51));
End;
Procedure TFileBase.BatchDelete;
Var
A : Byte;
B : Byte;
Begin
If BatchNum = 0 Then Begin
Session.io.OutFullLn (Session.GetPrompt(52));
Exit;
End;
Session.io.PromptInfo[1] := strI2S(BatchNum);
Session.io.OutFull (Session.GetPrompt(53));
A := strS2I(Session.io.GetInput(2, 2, 12, ''));
If (A > 0) and (A <= BatchNum) Then Begin
Session.io.PromptInfo[1] := FDir.FileName;
Session.io.PromptInfo[2] := strComma(Batch[A].Size);
Session.io.OutFullLn (Session.GetPrompt(54));
For B := A to BatchNum do
Batch[B] := Batch[B+1];
Dec (BatchNum);
End;
End;
Procedure TFileBase.FileGroupChange (Ops: String; FirstBase, Intro: Boolean);
Var
Count : Word;
Total : Word;
tGroup : recGroup;
tFBase : RecFileBase;
tLast : Word;
Areas : Word;
Data : Word;
Begin
tGroup := FGroup;
If (Ops = '+') or (Ops = '-') Then Begin
Reset (FGroupFile);
Count := Session.User.ThisUser.LastFGroup - 1;
Repeat
Case Ops[1] of
'+' : Inc(Count);
'-' : Dec(Count);
End;
{$I-}
Seek (FGroupFile, Count);
Read (FGroupFile, FGroup);
{$I+}
If IoResult <> 0 Then Break;
If Session.User.Access(FGroup.ACS) Then Begin
Session.User.ThisUser.LastFGroup := FilePos(FGroupFile);
Close (FGroupFile);
If Intro Then Session.io.OutFile ('fgroup' + strI2S(Session.User.ThisUser.LastFGroup), True, 0);
If FirstBase Then Begin
Session.User.ThisUser.LastFBase := 0;
ChangeFileArea ('+');
End;
Exit;
End;
Until False;
Close (FGroupFile);
FGroup := tGroup;
Exit;
End;
Data := strS2I(Ops);
Reset (FGroupFile);
If Data > 0 Then Begin
If Data > FileSize(FGroupFile) Then Begin
Close (FGroupFile);
Exit;
End;
Seek (FGroupFile, Data-1);
Read (FGroupFile, FGroup);
If Session.User.Access(FGroup.ACS) Then Begin
Session.User.ThisUser.LastFGroup := FilePos(FGroupFile);
If Intro Then Session.io.OutFile ('fgroup' + strI2S(Data), True, 0);
End Else
FGroup := tGroup;
Close (FGroupFile);
If FirstBase Then Begin
Session.User.ThisUser.LastFBase := 0;
ChangeFileArea ('+');
End;
Exit;
End;
Session.io.PausePtr := 1;
Session.io.AllowPause := True;
Session.io.OutFullLn (Session.GetPrompt(214));
tLast := Session.User.ThisUser.LastFGroup;
Total := 0;
While Not Eof(FGroupFile) Do Begin
Read (FGroupFile, FGroup);
If Not FGroup.Hidden And Session.User.Access(FGroup.ACS) Then Begin
Areas := 0;
Session.User.ThisUser.LastFGroup := FilePos(FGroupFile);
Reset (FBaseFile);
While Not Eof(FBaseFile) Do Begin
Read (FBaseFile, tFBase);
If Session.User.Access(tFBase.ListACS) Then Inc(Areas);
End;
Close (FBaseFile);
Inc (Total);
Session.io.PromptInfo[1] := strI2S(Total);
Session.io.PromptInfo[2] := FGroup.Name;
Session.io.PromptInfo[3] := strI2S(Areas);
Session.io.OutFullLn (Session.GetPrompt(215));
If (Session.io.PausePtr = Session.User.ThisUser.ScreenSize) and (Session.io.AllowPause) Then
Case Session.io.MorePrompt of
'N' : Break;
'C' : Session.io.AllowPause := False;
End;
End;
End;
Session.User.ThisUser.LastFGroup := tLast;
If Total = 0 Then
Session.io.OutFullLn (Session.GetPrompt(216))
Else Begin
Session.io.OutFull (Session.GetPrompt(217));
Session.io.OneKeyRange(#13 + 'Q', 1, Total);
Count := Session.io.RangeValue;
If (Count > 0) and (Count <= Total) Then Begin
Total := 0;
Reset (FGroupFile);
Repeat
Read (FGroupFile, FGroup);
If Not FGroup.Hidden And Session.User.Access(FGroup.ACS) Then Inc(Total);
If Count = Total Then Break;
Until False;
Session.User.ThisUser.LastFGroup := FilePos(FGroupFile);
If Intro Then Session.io.OutFile ('fgroup' + strI2S(Session.User.ThisUser.LastFGroup), True, 0);
Session.User.ThisUser.LastFBase := 0;
ChangeFileArea ('+');
End Else
FGroup := tGroup;
End;
Close (FGroupFile);
End;
Function TFileBase.ListFileAreas (Compress: Boolean) : Integer;
Var
Total : Word = 0;
Listed : Word = 0;
tDirFile : File of RecFileList;
Begin
Reset (FBaseFile);
Session.io.PausePtr := 1;
Session.io.AllowPause := True;
While Not Eof(FBaseFile) Do Begin
Read (FBaseFile, FBase);
If Session.User.Access(FBase.ListACS) Then Begin
Inc (Listed);
If Listed = 1 Then Session.io.OutFullLn (Session.GetPrompt(33));
If Compress Then
Inc (Total)
Else
Total := FilePos(FBaseFile);
Session.io.PromptInfo[1] := strI2S(Total);
Session.io.PromptInfo[2] := FBase.Name;
Session.io.PromptInfo[3] := '0';
Assign (TDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (TDirFile); {$I+}
If IoResult = 0 Then Begin
Session.io.PromptInfo[3] := strI2S(FileSize(TDirFile));
Close (TDirFile);
End;
Session.io.OutFull (Session.GetPrompt(34));
If (Listed MOD bbsCfg.FColumns = 0) and (Listed > 0) Then Session.io.OutRawLn('');
End;
If EOF(FBaseFile) and (Listed MOD bbsCfg.FColumns <> 0) Then Session.io.OutRawLn('');
If (Session.io.PausePtr = Session.User.ThisUser.ScreenSize) and (Session.io.AllowPause) Then
Case Session.io.MorePrompt of
'N' : Begin
Total := FileSize(FBaseFile);
Break;
End;
'C' : Session.io.AllowPause := False;
End;
End;
Close (FBaseFile);
Result := Total;
End;
Procedure TFileBase.ChangeFileArea (Data: String);
Var
A : Word;
Total : Word;
Old : RecFileBase;
Compress : Boolean;
Begin
Old := FBase;
Compress := bbsCfg.FCompress;
If (Data = '+') or (Data = '-') Then Begin
Reset (FBaseFile);
A := Session.User.ThisUser.LastFBase - 1;
Repeat
Case Data[1] of
'+' : Inc(A);
'-' : Dec(A);
End;
{$I-}
Seek (FBaseFile, A);
Read (FBaseFile, FBase);
{$I+}
If IoResult <> 0 Then Break;
If Session.User.Access(FBase.ListACS) Then Begin
Session.User.ThisUser.LastFBase := FilePos(FBaseFile);
Close (FBaseFile);
Exit;
End;
Until False;
Close (FBaseFile);
FBase := Old;
Exit;
End;
A := strS2I(Data);
If A > 0 Then Begin
Reset (FBaseFile);
If A <= FileSize(FBaseFile) Then Begin
Seek (FBaseFile, A-1);
Read (FBaseFile, FBase);
If Session.User.Access(FBase.ListACS) Then Begin
Session.User.ThisUser.LastFBase := FilePos(FBaseFile)
End Else
FBase := Old;
End;
Close (FBaseFile);
Exit;
End;
If Pos('NOLIST', strUpper(Data)) > 0 Then Begin
Reset (FBaseFile);
Total := FileSize(FBaseFile);
Close (FBaseFile);
End Else
Total := ListFileAreas(Compress);
If Total = 0 Then Begin
Session.io.OutFullLn (Session.GetPrompt(37));
FBase := Old;
End Else Begin
Repeat
Session.io.OutFull (Session.GetPrompt(36));
Case Session.io.OneKeyRange(#13 + '?Q', 1, Total) of
'?': Begin
Compress := bbsCfg.FCompress;
Total := ListFileAreas(Compress);
End;
Else
Break;
End;
Until False;
A := Session.io.RangeValue;
If (A > 0) and (A <= Total) Then Begin
Reset (FBaseFile);
If Not Compress Then Begin
Seek (FBaseFile, A - 1);
Read (FBaseFile, FBase);
If Not Session.User.Access(FBase.ListACS) Then Begin
FBase := Old;
Close (FBaseFile);
Exit;
End;
End Else Begin
Total := 0;
While Not Eof(FBaseFile) And (A <> Total) Do Begin
Read (FBaseFile, FBase);
If Session.User.Access(FBase.ListACS) Then Inc(Total);
End;
If A <> Total Then Begin
Close (FBaseFile);
FBase := OLD;
Exit;
End;
End;
Session.User.ThisUser.LastFBase := FilePos(FBaseFile);
Close (FBaseFile);
End Else
FBase := Old;
End;
End;
Function TFileBase.ListFiles (Mode: Byte; Data : String) : Byte;
Var
ListType : Byte; { 0 = ascii, 1 = ansi }
DataFile : File;
Lines : Byte; { lines already displayed }
CurPos : Byte; { current cursor position }
ListSize : Byte; { number of files in this page listing }
CurPage : Word; { current page number }
TopPage : Word; { top of page file position }
TopDesc : Byte; { top of page description offset }
BotPage : Word; { bot of page file position }
BotDesc : Byte; { bot of page description offset }
PageSize : Byte; { total lines in window/page }
LastPage : Boolean; { is the last page displayed? }
Found : Boolean; { were any files found? }
First : Boolean; { first file on page? }
IsNotLast : Boolean;
List : Array[1..13] of Record
FileName : String[70];
RecPos : Word;
yPos : Byte;
Batch : Boolean;
End;
strListFormat,
strDesc,
strExtDesc,
strUploader,
strBarON,
strBarOFF : String;
Function OkFile : Boolean;
Var
T2 : Boolean;
A : Byte;
Temp : String[mysMaxFileDescLen];
Begin
OkFile := False;
If (FDir.Flags And FDirDeleted <> 0) Then Exit;
If (FDir.Flags AND FDirOffline <> 0) And (Not Session.User.Access(bbsCfg.AcsSeeOffline)) Then Exit;
If (FDir.Flags And FDirInvalid <> 0) And (Not Session.User.Access(bbsCfg.AcsSeeUnvalid)) Then Exit;
If (FDir.Flags And FDirFailed <> 0) And (Not Session.User.Access(bbsCfg.AcsSeeFailed)) Then Exit;
Case Mode of
1 : If Data <> '' Then
If Not WildMatch (Data, FDir.FileName, False) Then Exit;
2 : If FDir.DateTime < FScan.LastNew Then Exit;
3 : Begin
T2 := Bool_Search(Data, FDir.FileName);
If Not T2 Then Begin
Seek (DataFile, FDir.DescPtr);
For A := 1 to FDir.DescLines Do Begin
BlockRead (DataFile, Temp[0], 1);
BlockRead (DataFile, Temp[1], Length(Temp));
If Bool_Search(Data, Temp) Then Begin
T2 := True;
Break;
End;
End;
End;
If Not T2 Then Exit;
End;
End;
OkFile := True;
End;
Procedure ClearWindow;
Var
A : Byte;
Begin
Session.io.AnsiGotoXY (1, Session.io.ScreenInfo[1].Y);
Session.io.OutFull('|16');
For A := Session.io.ScreenInfo[1].Y to Session.io.ScreenInfo[2].Y Do Begin
Session.io.AnsiClrEOL;
Session.io.OutRawLn('');
End;
Session.io.AnsiGotoXY (1, Session.io.ScreenInfo[1].Y);
End;
Procedure SearchHighlight (Var Temp: String);
Var
Attr : Byte;
Begin
If Bool_Search(Data, Temp) Then Begin
Attr := Console.TextAttr;
Console.TextAttr := 255;
Insert (
Session.io.Attr2Ansi(Session.Theme.FileDescLo),
Temp,
Pos(Data, strUpper(Temp)) + Length(Data)
);
Console.TextAttr := 255;
Insert (
Session.io.Attr2Ansi(Session.Theme.FileDescHi),
Temp,
Pos(Data, strUpper(Temp)));
Console.TextAttr := Attr;
End;
End;
Procedure NextPage;
Begin
Inc (CurPage);
TopDesc := BotDesc;
TopPage := BotPage;
CurPos := 1;
End;
Function ShowText (Str : String) : Boolean;
Begin
If Lines = PageSize Then Begin
ShowText := False;
Exit;
End;
Inc (BotDesc);
Inc (Lines);
Session.io.OutFullLn (Str);
Found := True;
ShowText := True;
End;
Procedure PrevPage;
Var
NewPos : LongInt;
Count : Word;
Begin
If CurPage = 1 Then Exit;
Dec (CurPage);
NewPos := TopPage;
Count := 0;
If TopDesc = 0 Then Dec(NewPos);
While (NewPos >= 0) and (Count < PageSize) Do Begin
Seek (FDirFile, NewPos);
Read (FDirFile, FDir);
Dec (NewPos);
If Not OkFile Then Continue;
If TopDesc > 0 Then Begin
Inc (Count, FDir.DescLines - (FDir.DescLines - TopDesc + 1) + 1);
If TopDesc = FDir.DescLines + 2 Then Dec(Count);
TopDesc := 0;
End Else Begin
Inc (Count, FDir.DescLines + 1);
If FBase.Flags And FBShowUpload <> 0 Then Inc(Count);
End;
End;
If NewPos < -1 Then Begin
CurPage := 1;
TopPage := 0;
TopDesc := 0;
End Else Begin
TopPage := NewPos + 1;
TopDesc := Count - PageSize;
End;
End;
Procedure PrintMessage (N : Integer);
Begin
Session.io.AnsiGotoXY (1, Session.io.ScreenInfo[3].Y);
Session.io.AnsiClrEOL;
Session.io.OutFull (Session.GetPrompt(N));
Session.io.AnsiGotoXY (1, Session.io.ScreenInfo[3].Y);
Session.io.AnsiClrEOL;
If Session.User.Access(FBase.SysopACS) Then
Session.io.OutFull (Session.GetPrompt(339))
Else
Session.io.OutFull (Session.GetPrompt(323));
End;
Procedure UpdateBatch;
Begin
If Session.io.ScreenInfo[4].X = 0 Then Exit;
Session.io.AnsiGotoXY (Session.io.ScreenInfo[4].X, Session.io.ScreenInfo[4].Y);
Session.io.AnsiColor (Session.io.ScreenInfo[4].A);
Session.io.OutRaw (strZero(BatchNum));
End;
Procedure FullReDraw;
Begin
Session.io.ScreenInfo[5].Y := 0;
Session.io.ScreenInfo[6].Y := 0;
Session.io.OutFile (FBase.Template, True, 0);
PageSize := Session.io.ScreenInfo[2].Y - Session.io.ScreenInfo[1].Y + 1;
BotDesc := TopDesc;
BotPage := TopPage;
If Session.User.Access(FBase.SysopACS) Then
PrintMessage (339)
Else
PrintMessage (323);
UpdateBatch;
End;
Function GetFileListSize (SizeInfo: String) : String;
Var
A : Cardinal;
Begin
If FDir.Flags And FDirOffline <> 0 Then
GetFileListSize := strWordGet(1, SizeInfo, ' ')
Else
If FDir.Flags And FDirFailed <> 0 Then
GetFileListSize := strWordGet(2, SizeInfo, ' ')
Else
If FDir.Flags And FDirInvalid <> 0 Then
GetFileListSize := strWordGet(3, SizeInfo, ' ')
Else
If FDir.Size >= 1024000000 Then Begin
A := (FDir.Size DIV 1024) DIV 1024;
GetFileListSize := strI2S(A DIV 1000) + '.' + Copy(strI2S(A MOD 1000), 1, 2) + strWordGet(4, SizeInfo, ' ')
End Else
If FDir.Size >= 1024000 Then Begin
A := FDir.Size DIV 1024;
GetFileListSize := strI2S(A DIV 1000) + '.' + Copy(strI2S(A MOD 1000), 1, 2) + strWordGet(5, SizeInfo, ' ')
End Else
If FDir.Size >= 1024 Then
GetFileListSize := strI2S(FDir.Size DIV 1024) + strWordGet(6, SizeInfo, ' ')
Else
GetFileListSize := strI2S(FDir.Size) + strWordGet(7, SizeInfo, ' ');
End;
Procedure HeaderCheck;
Begin
Case ListType of
0 : If First Then Begin
First := False;
If bbsCfg.FShowHeader or (CurPage = 1) Then Begin
Session.io.PausePtr := 1;
Session.io.OutFullLn(Session.GetPrompt(41))
End Else Begin
Session.io.OutRawLn('');
Session.io.PausePtr := 1;
End;
PageSize := Session.User.ThisUser.ScreenSize - Session.io.PausePtr - 1;
End;
1 : If Not Found Then Begin
FullReDraw;
ClearWindow;
First := False;
End Else
If First Then Begin
ClearWindow;
First := False;
End;
End;
End;
Procedure DoEditor;
Var
SavedPos : LongInt;
Begin
{$I-} SavedPos := FilePos(FBaseFile); {$I+}
If IoResult = 0 Then
Close (FBaseFile)
Else
SavedPos := -1;
Close (FDirFile);
Close (DataFile);
DirectoryEditor(True, List[CurPos].FileName);
If SavedPos <> -1 Then Begin
Reset (FBaseFile);
Seek (FBaseFile, SavedPos);
End;
Reset (FDirFile);
Reset (DataFile, 1);
End;
Procedure DrawPage;
Var
OK : Boolean;
Str : String;
A : SmallInt;
SizeStr : String;
Begin
ListSize := 0;
Lines := 0;
SizeStr := Session.GetPrompt(491);
Seek (FDirFile, TopPage);
If TopDesc <> 0 Then Read (FDirFile, FDir);
BotDesc := TopDesc;
OK := True;
First := True;
IsNotLast := False;
Repeat
If BotDesc = 0 Then Begin
Read (FDirFile, FDir);
If Not OkFile Then Continue;
HeaderCheck;
Session.io.PromptInfo[1] := strZero(ListSize + 1);
Session.io.PromptInfo[2] := FDir.FileName;
Session.io.PromptInfo[3] := ' ';
Session.io.PromptInfo[4] := GetFileListSize(SizeStr);
Session.io.PromptInfo[5] := DateDos2Str(FDir.DateTime, Session.User.ThisUser.DateType);
Session.io.PromptInfo[6] := strI2S(FDir.Downloads);
List[ListSize + 1].Batch := False;
For A := 1 to BatchNum Do
If Batch[A].FileName = FDir.FileName Then Begin
List[ListSize + 1].Batch := True;
Session.io.PromptInfo[3] := Session.Theme.TagChar;
Break;
End;
OK := ShowText(strListFormat);
If Not OK Then Begin
IsNotLast := True;
Break;
End;
Inc (ListSize);
List[ListSize].FileName := FDir.FileName;
List[ListSize].YPos := Console.CursorY - 1;
List[ListSize].RecPos := FilePos(FDirFile) - 1;
End Else
HeaderCheck;
If BotDesc <= FDir.DescLines + 2 Then Begin { skip if 1st line is uler }
Seek (DataFile, FDir.DescPtr);
For A := 1 to FDir.DescLines Do Begin
BlockRead (DataFile, Str[0], 1);
BlockRead (DataFile, Str[1], Ord(Str[0]));
If A < BotDesc Then Continue;
If Mode = 3 Then SearchHighlight(Str);
If A = 1 Then Begin
Session.io.PromptInfo[1] := GetFileListSize(SizeStr);
Session.io.PromptInfo[2] := DateDos2Str(FDir.DateTime, Session.User.ThisUser.DateType);
Session.io.PromptInfo[3] := strI2S(FDir.Downloads);
Session.io.PromptInfo[4] := Str;
Session.io.PromptInfo[5] := FDir.Uploader;
Session.io.PromptInfo[6] := strI2S(FDir.Downloads);
OK := ShowText(strDesc);
End Else Begin
Session.io.PromptInfo[4] := Str;
OK := ShowText(strExtDesc);
End;
If Not OK Then Break;
End;
End;
If BotDesc > FDir.DescLines Then Begin
If FBase.Flags and FBShowUpload <> 0 Then Begin
OK := ShowText(strUploader);
If OK Then
BotDesc := 0
Else
Inc (BotDesc);
End Else
BotDesc := 0;
End;
Until EOF(FDirFile) Or Not OK;
BotPage := FilePos(FDirFile) - 1;
LastPage := Eof(FDirFile) And (BotDesc = 0) And Not IsNotLast;
IsNotLast := False;
Str := Session.io.DrawPercent(Session.Theme.FileBar, BotPage, FileSize(FDirFile), A);
If Found Then Begin
If (ListType = 1) and (Session.io.ScreenInfo[5].Y <> 0) Then Begin
Session.io.AnsiGotoXY (Session.io.ScreenInfo[5].X, Session.io.ScreenInfo[5].Y);
Session.io.AnsiColor (Session.io.ScreenInfo[5].A);
Session.io.OutRaw (strPadL(strI2S(A), 3, ' '));
End;
If (ListType = 1) and (Session.io.ScreenInfo[6].Y <> 0) Then Begin
Session.io.AnsiGotoXY (Session.io.ScreenInfo[6].X, Session.io.ScreenInfo[6].Y);
Session.io.OutFull (Str);
End;
End;
End;
Procedure BarOFF;
Begin
Session.io.AnsiGotoXY (1, List[CurPos].YPos);
Session.io.PromptInfo[1] := strZero(CurPos);
Session.io.PromptInfo[2] := List[CurPos].FileName;
If List[CurPos].Batch Then
Session.io.PromptInfo[3] := Session.Theme.TagChar
Else
Session.io.PromptInfo[3] := ' ';
Session.io.OutFull(strBarOFF);
End;
Procedure Ansi_List;
Var
Ch : Char;
A : Byte;
B : Integer;
Begin
Session.io.AllowArrow := True;
ListType := 1;
strListFormat := Session.GetPrompt(431);
strBarON := Session.GetPrompt(432);
strBarOFF := Session.GetPrompt(433);
strDesc := Session.GetPrompt(434);
strExtDesc := Session.GetPrompt(435);
strUploader := Session.GetPrompt(436);
NextPage;
DrawPage;
If Found Then Begin
Repeat
If ListSize > 0 Then Begin
Session.io.AnsiGotoXY (1, List[CurPos].yPos);
Session.io.PromptInfo[1] := strZero(CurPos);
Session.io.PromptInfo[2] := List[CurPos].FileName;
If List[CurPos].Batch Then
Session.io.PromptInfo[3] := Session.Theme.TagChar
Else
Session.io.PromptInfo[3] := ' ';
Session.io.OutFull (strBarON);
End;
Session.io.PurgeInputBuffer;
Ch := UpCase(Session.io.GetKey);
If Session.io.IsArrow Then Begin
Case Ch of
#71 : If CurPage > 1 Then Begin
While CurPage > 1 Do PrevPage;
CurPos := 1;
DrawPage;
End Else If CurPos > 1 Then Begin
BarOFF;
CurPos := 1;
End;
#72 : If (CurPos > 1) and (ListSize > 0) Then Begin
BarOFF;
Dec (CurPos);
End Else If CurPage > 1 Then Begin
PrevPage;
DrawPage;
CurPos := ListSize;
End;
#73,
#75 : If CurPage > 1 Then Begin
PrevPage;
DrawPage;
CurPos := ListSize;
End Else
If ListSize > 0 Then Begin
BarOFF;
CurPos := 1;
End;
#79 : If LastPage Then Begin
BarOFF;
CurPos := ListSize;
End Else Begin
While Not LastPage Do Begin
NextPage;
DrawPage;
End;
CurPos := ListSize;
End;
#80 : If CurPos < ListSize Then Begin
BarOFF;
Inc (CurPos);
End Else If Not LastPage Then Begin
NextPage;
DrawPage;
End;
#77,
#81 : If Not LastPage Then Begin
NextPage;
DrawPage;
End Else If ListSize > 0 Then Begin
BarOFF;
CurPos := ListSize;
End;
End;
End Else Begin
Case Ch of
#13 : If LastPage Then Begin
Result := 2;
Break;
End Else Begin
NextPage;
DrawPage;
End;
#27 : Begin
Result := 1;
Break;
End;
#32 : If Not Session.User.Access(FBase.DLACS) Then
PrintMessage(212)
Else
If ListSize > 0 Then Begin
If List[CurPos].Batch Then Begin
For A := 1 to BatchNum Do
If Batch[A].FileName = List[CurPos].FileName Then Begin
For B := A to BatchNum Do Batch[B] := Batch[B+1];
Dec (BatchNum);
List[CurPos].Batch := False;
BarOFF;
UpdateBatch;
Break;
End;
End Else
If BatchNum < mysMaxBatchQueue Then Begin
Seek (FDirFile, List[CurPos].RecPos);
Read (FDirFile, FDir);
Case CheckFileLimits(1, FDir.Size DIV 1024) of
0 : Begin
Inc (BatchNum);
Batch[BatchNum].FileName := FDir.FileName;
If Mode = 1 Then
Batch[BatchNum].Area := Session.User.ThisUser.LastFBase
Else
Batch[BatchNum].Area := FilePos(FBaseFile);
Batch[BatchNum].Size := FDir.Size;
List[CurPos].Batch := True;
BarOFF;
updateBatch;
End;
1 : PrintMessage (212);
2 : PrintMessage (312);
3 : PrintMessage (313);
End;
End Else
PrintMessage (314);
If CurPos < ListSize Then Begin
BarOFF;
Inc (CurPos);
End Else If Not LastPage Then Begin
NextPage;
DrawPage;
End;
End;
'?' : Begin
Session.io.OutFile ('flisthlp', True, 0);
If Not Session.io.NoFile Then Begin
FullReDraw;
DrawPage;
End;
End;
'E' : If Session.User.Access(FBase.SysopACS) Then Begin
DoEditor;
FullReDraw;
DrawPage;
If CurPos > ListSize Then CurPos := ListSize;
Session.io.AllowArrow := True;
End;
'N' : If Mode > 1 Then Begin
Result := 2;
Break;
End;
'V' : Begin
Session.io.AnsiGotoXY (1, 23);
If ArchiveView(FBase.Path + List[CurPos].FileName) Then Begin
FullRedraw;
DrawPage;
End Else
PrintMessage (324);
Session.io.AllowArrow := True;
End;
End;
End;
Until False;
Session.io.AnsiGotoXY (1, Session.User.ThisUser.ScreenSize);
End;
Session.io.AllowArrow := False;
End;
Procedure Ascii_List;
Var
A : LongInt;
okSave : Byte;
Keys : String[20];
Files : Cardinal;
Procedure FlagFile (Number: Integer);
Var
Count1 : Integer;
Count2 : Integer;
Begin
If Not Session.User.Access(FBase.DLACS) Then
Session.io.OutFullLn (Session.GetPrompt(224))
Else Begin
If BatchNum = mysMaxBatchQueue Then Begin
Session.io.OutFullLn (Session.GetPrompt(46));
Exit;
End;
If (Number < 1) or (Number > ListSize) Then Exit;
okSave := 0;
Seek (FDirFile, List[Number].RecPos);
Read (FDirFile, FDir);
For Count1 := 1 to BatchNum Do
If FDir.FileName = Batch[Count1].FileName Then Begin
Session.io.PromptInfo[1] := FDir.FileName;
Session.io.PromptInfo[2] := strComma(Batch[Count1].Size);
Session.io.OutFullLn (Session.GetPrompt(54));
For Count2 := Count1 to BatchNum Do
Batch[Count2] := Batch[Count2 + 1];
Dec (BatchNum);
okSave := 2;
End;
If okSave = 0 Then
Case CheckFileLimits(1, FDir.Size DIV 1024) of
0 : okSave := 1;
1 : Session.io.OutFullLn (Session.GetPrompt(224));
2 : Session.io.OutFullLn (Session.GetPrompt(58));
3 : Session.io.OutFullLn (Session.GetPrompt(211));
End;
If okSave = 1 Then Begin
Session.io.PromptInfo[1] := FDir.FileName;
Session.io.PromptInfo[2] := strComma(FDir.Size);
Session.io.OutFullLn (Session.GetPrompt(50));
Inc (BatchNum);
Batch[BatchNum].FileName := FDir.FileName;
Batch[BatchNum].Size := FDir.Size;
If Mode = 1 Then
Batch[BatchNum].Area := Session.User.ThisUser.LastFBase
Else
Batch[BatchNum].Area := FilePos(FBaseFile);
End;
End;
End;
Begin
ListType := 0;
Files := FileSize(FDirFile);
strListFormat := Session.GetPrompt(42);
strDesc := Session.GetPrompt(43);
strExtDesc := Session.GetPrompt(45);
strUploader := Session.GetPrompt(437);
NextPage;
DrawPage;
If Not Found Then Exit;
Result := 2;
Keys := #13 + 'FNPQV';
If Session.User.Access(FBase.SysopACS) Then Keys := Keys + 'E';
Repeat
Session.io.PromptInfo[1] := strI2S(Files);
Session.io.PromptInfo[2] := strI2S(BotPage);
Session.io.OutFull (Session.GetPrompt(44));
Case Session.io.OneKeyRange(Keys, 1, ListSize) of
#00 : Begin
FlagFile(Session.io.RangeValue);
DrawPage;
Continue;
End;
'E' : Begin
DoEditor;
DrawPage;
End;
#13,
'N' : If LastPage Then
Break
Else Begin
NextPage;
DrawPage;
End;
'P' : Begin
PrevPage;
If CurPage = 1 Then
TopDesc := 0;
DrawPage;
End;
'Q' : Begin
Result := 1;
Break;
End;
'V' : Begin
Session.io.OutFull (Session.GetPrompt(358));
Session.io.OneKeyRange('Q' + #13, 1, ListSize);
A := Session.io.RangeValue;
If (A > 0) and (A <= ListSize) Then
If Not ArchiveView (FBase.Path + List[A].FileName) Then
Session.io.OutFullLn(Session.GetPrompt(191));
DrawPage;
End;
'F' : Begin
Repeat
Session.io.OutFull (Session.GetPrompt(357));
Case Session.io.OneKeyRange('Q' + #13, 1, ListSize) of
#00 : FlagFile(Session.io.RangeValue);
'Q',
#13 : Break;
End;
Until False;
DrawPage;
End;
End;
Until False;
Session.io.OutRawLn('');
End;
Begin
If FBase.FileName = '' Then Begin
Session.io.OutFullLn(Session.GetPrompt(38));
Exit;
End;
If Not Session.User.Access(FBase.ListACS) Then Begin
Session.io.OutFullLn (Session.GetPrompt(39));
Exit;
End;
If (Mode = 1) and (Data = 'SEARCH') Then Begin
Session.io.OutFull (Session.GetPrompt(195));
Data := Session.io.GetInput(70, 70, 11, '*.*');
If Data = '' Then Exit;
End;
Set_Node_Action (Session.GetPrompt(350));
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (FDirFile); {$I+}
If IoResult <> 0 Then Begin
If Mode = 1 Then Session.io.OutFullLn (Session.GetPrompt(40));
Exit;
End;
If Eof(FDirFile) Then Begin
If Mode = 1 Then Session.io.OutFullLn (Session.GetPrompt(40));
Close (FDirFile);
Exit;
End;
Assign (DataFile, bbsCfg.DataPath + FBase.FileName + '.des');
{$I-} Reset (DataFile, 1); {$I+}
If IoResult <> 0 Then ReWrite (DataFile, 1);
If Mode = 1 Then
Session.io.OutFile(FBase.DispFile, True, 0);
Result := 0;
CurPage := 0;
TopPage := 0;
TopDesc := 0;
BotPage := 0;
BotDesc := 0;
Found := False;
If (Session.User.ThisUser.FileList = 1) and (Session.io.Graphics > 0) Then
Ansi_List
Else
Ascii_List;
Close (FDirFile);
Close (DataFile);
End;
Procedure TFileBase.CheckFileNameLength (FPath : String; Var FName : String);
Var
D : DirStr;
N : NameStr;
E : ExtStr;
F : File;
S : String;
Begin
If Length(FName) > 70 Then Begin
FSplit(FName, D, N, E);
S := Copy(N, 1, 70 - Length(E)) + E;
Repeat
Assign (F, FPath + FName);
{$I-} ReName(F, FPath + S); {$I+}
If IoResult = 0 Then Begin
FName := S;
Break;
End Else Begin
Session.io.OutFull (Session.GetPrompt(461));
S := strStripB(Session.io.GetInput(70, 70, 11, S), ' ');
End;
Until False;
End;
End;
Function TFileBase.IsDupeFile (FileName : String; Global : Boolean) : Boolean;
Var
Res : Boolean;
OLD : RecFileBase;
Procedure Check_Area;
Var
TempFile : File of RecFileList;
Temp : RecFileList;
Begin
Assign (TempFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (TempFile); {$I+}
If IoResult <> 0 Then ReWrite (TempFile);
While Not Eof(TempFile) Do Begin
Read (TempFile, Temp);
{$IFDEF FS_SENSITIVE}
If (Temp.FileName = FileName) And (Temp.Flags And FDirDeleted = 0) Then Begin
{$ELSE}
If (strUpper(Temp.FileName) = strUpper(FileName)) And (Temp.Flags And FDirDeleted = 0) Then Begin
{$ENDIF}
Res := True;
Break;
End;
End;
Close (TempFile);
End;
Begin
Res := False;
OLD := FBase;
If Global Then Begin
Reset (FBaseFile);
While Not Eof(FBaseFile) And Not Res Do Begin
Read (FBaseFile, FBase);
Check_Area;
End;
Close (FBaseFile);
End Else
Check_Area;
FBase := OLD;
Result := Res;
End;
Procedure TFileBase.GetFileDescription (FN : String);
Var
A : Byte;
Begin
Session.io.PromptInfo[1] := strI2S(bbsCfg.MaxFileDesc);
Session.io.PromptInfo[2] := FN;
Session.io.OutFullLn (Session.GetPrompt(72));
FDir.DescLines := bbsCfg.MaxFileDesc;
For A := 1 to bbsCfg.MaxFileDesc Do Begin
Session.io.PromptInfo[1] := strZero(A);
Session.io.OutFull (Session.GetPrompt(207));
Session.Msgs.MsgText[A] := Session.io.GetInput(mysMaxFileDescLen, mysMaxFileDescLen, 11, '');
If Session.Msgs.MsgText[A] = '' Then Begin
FDir.DescLines := Pred(A);
Break;
End;
End;
If FDir.DescLines = 0 Then Begin
Session.Msgs.MsgText[1] := Session.GetPrompt(208);
FDir.DescLines := 1;
End;
End;
Procedure TFileBase.UploadFile;
// ignore group with configured upload base is an issue...
// how do we fix this up?
Var
FileName : String;
A : LongInt;
OLD : RecFileBase;
Blind : Boolean;
Temp : String;
FullName : String;
DataFile : File;
Found : Boolean;
LogFile : Text;
FileStatus : Boolean;
SavedIgnore : Boolean;
{$IFNDEF UNIX}
D : DirStr;
N : NameStr;
E : ExtStr;
{$ENDIF}
Begin
OLD := FBase;
Found := False;
SavedIgnore := Session.User.IgnoreGroup;
If bbsCfg.UploadBase > 0 Then Begin
Session.User.IgnoreGroup := True; { just in case ul area is in another group }
Reset (FBaseFile);
{$I-} Seek (FBaseFile, bbsCfg.UploadBase - 1); {$I+}
If IoResult = 0 Then Read (FBaseFile, FBase);
Close (FBaseFile);
Session.User.IgnoreGroup := SavedIgnore;
End;
If Not Session.User.Access(FBase.ULacs) Then Begin
Session.io.OutFullLn (Session.GetPrompt(68));
FBase := OLD;
Exit;
End;
Session.User.IgnoreGroup := False;
If FBase.FileName = '' Then Begin
Session.io.OutFullLn(Session.GetPrompt(38));
FBase := OLD;
Exit;
End;
If FBase.Flags And FBSlowMedia <> 0 Then Begin
Session.io.OutFullLn (Session.GetPrompt(80));
FBase := OLD;
Exit;
End;
If bbsCfg.FreeUL > 0 Then Begin
{$IFDEF UNIX}
If DiskFree(0) DIV 1024 < bbsCfg.FreeUL Then Begin
Session.io.OutFullLn (Session.GetPrompt(81));
FBase := OLD;
Exit;
End;
{$ELSE}
FSplit (FBase.Path, D, N, E);
If DiskFree(Ord(UpCase(D[1])) - 64) DIV 1024 < bbsCfg.FreeUL Then Begin
Session.io.OutFullLn (Session.GetPrompt(81));
FBase := OLD;
Exit;
End;
{$ENDIF}
End;
Blind := Session.io.GetYN(Session.GetPrompt(375), False);
FileName := '';
If Blind Then
Session.io.OutFile ('blindul', True, 0)
Else Begin
Session.io.OutFile ('upload', True, 0);
Session.io.OutFull (Session.GetPrompt(343));
FileName := strStripB(Session.io.GetInput(70, 70, 11, ''), ' ');
If (FileName = '') or (Pos('*', FileName) > 0) or (Pos('?', FileName) > 0) Then Begin
Session.io.OutFullLn (Session.GetPrompt(69));
FBase := OLD;
Exit;
End;
If bbsCfg.FDupeScan > 0 Then Begin
Session.io.OutFull (Session.GetPrompt(70));
If IsDupeFile(FileName, bbsCfg.FDupeScan = 2) Then Begin
Session.io.OutFullLn (Session.GetPrompt(205));
FBase := OLD;
Exit;
End;
Session.io.OutFullLn (Session.GetPrompt(71));
End;
FileName := FBase.Path + FileName;
End;
If SelectProtocol(True, Blind) = 'Q' Then Begin
FBase := OLD;
Exit;
End;
If Blind Then
ExecuteProtocol(0, FBase.Path)
Else
ExecuteProtocol(0, FileName);
Session.io.OutFull (Session.GetPrompt(376));
Assign (DataFile, bbsCfg.DataPath + FBase.FileName + '.des');
{$I-} Reset (DataFile, 1); {$I+}
If IoResult <> 0 Then ReWrite(DataFile, 1);
Seek (DataFile, FileSize(DataFile));
Assign (LogFile, Session.TempPath + 'xfer.log');
{$I-} Reset(LogFile); {$I+}
If IoResult = 0 Then Begin
While Not Eof(LogFile) Do Begin
DszGetFile (LogFile, FileName, FileStatus);
If FileName = '' Then Continue;
CheckFileNameLength(FBase.Path, FileName);
FullName := FBase.Path + FileName;
Session.io.PromptInfo[1] := FileName;
If Not FileStatus Then Begin
Session.SystemLog ('Failed Upload: ' + FileName + ' to ' + strStripMCI(FBase.Name));
Session.io.OutFull (Session.GetPrompt(84));
FileErase(FullName);
End Else Begin
Found := True;
Session.SystemLog ('Uploaded: ' + FileName + ' to ' + strStripMCI(FBase.Name));
Session.io.OutFull (Session.GetPrompt(83));
FDir.FileName := FileName;
FDir.DateTime := CurDateDos;
FDir.Uploader := Session.User.ThisUser.Handle;
FDir.Flags := 0;
FDir.Downloads := 0;
FDir.Rating := 0;
If bbsCfg.FDupeScan > 0 Then Begin
Session.io.OutFull (Session.GetPrompt(377));
If IsDupeFile(FileName, bbsCfg.FDupeScan = 2) Then Begin
Session.io.OutFullLn (Session.GetPrompt(378));
Continue;
End Else
Session.io.OutFullLn (Session.GetPrompt(379));
End;
If bbsCfg.TestUploads and (bbsCfg.TestCmdLine <> '') Then Begin
Session.io.OutFull (Session.GetPrompt(206));
Temp := '';
A := 1;
While A <= Length(bbsCfg.TestCmdLine) Do Begin
If bbsCfg.TestCmdLine[A] = '%' Then Begin
Inc(A);
{$IFDEF UNIX}
If bbsCfg.TestCmdLine[A] = '0' Then Temp := Temp + '1' Else
{$ELSE}
If bbsCfg.TestCmdLine[A] = '0' Then Temp := Temp + strI2S(TIOSocket(Session.Client).FSocketHandle) Else
{$ENDIF}
If bbsCfg.TestCmdLine[A] = '1' Then Temp := Temp + '1' Else
If bbsCfg.TestCmdLine[A] = '2' Then Temp := Temp + '38400' Else
If bbsCfg.TestCmdLine[A] = '3' Then Temp := Temp + FullName {FBase.Path + FileName};
End Else
Temp := Temp + bbsCfg.TestCmdLine[A];
Inc(A);
End;
If ShellDOS('', Temp) <> bbsCfg.TestPassLevel Then Begin
Session.io.OutFullLn (Session.GetPrompt(35));
Session.SystemLog (FileName + ' has failed upload test');
FDir.Flags := FDir.Flags or FDirFailed;
End Else
Session.io.OutFullLn (Session.GetPrompt(55));
End;
If bbsCfg.ImportDIZ Then Begin
Session.io.OutFull (Session.GetPrompt(380));
If ImportDIZ(FileName) Then
Session.io.OutFullLn (Session.GetPrompt(381))
Else Begin
Session.io.OutFullLn (Session.GetPrompt(382));
GetFileDescription(FileName);
End;
End Else
GetFileDescription(FileName);
FDir.DescPtr := FileSize(DataFile);
For A := 1 to FDir.DescLines Do
BlockWrite (DataFile, Session.Msgs.MsgText[A][0], Length(Session.Msgs.MsgText[A]) + 1);
FDir.Size := FileByteSize(FBase.Path + FileName);
If FDir.Size = -1 Then Begin
FDir.Flags := FDir.Flags Or FDirOffline;
FDir.Size := 0;
End;
If Not Session.User.Access(bbsCfg.AcsValidate) Then FDir.Flags := FDir.Flags Or FDirInvalid;
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (FDirFile); {$I+}
If IoResult <> 0 Then ReWrite (FDirFile);
Seek (FDirFile, FileSize(FDirFile));
Write (FDirFile, FDir);
Close (FDirFile);
Inc (Session.User.ThisUser.ULs);
Inc (Session.User.ThisUser.ULk, FDir.Size DIV 1024);
Inc (Session.HistoryULs);
Inc (Session.HistoryULKB, FDir.Size DIV 1024);
End;
End;
Close (LogFile);
End;
Close (DataFile);
FBase := OLD;
DirClean(Session.TempPath, '');
If Found Then
Session.io.OutFullLn (Session.GetPrompt(75))
Else
Session.io.OutFullLn (Session.GetPrompt(424));
End;
Function TFileBase.CopiedToTemp (FName: String) : Boolean;
Var
Copied : Boolean;
Begin
Copied := False;
If FBase.Flags And FBSlowMedia <> 0 Then Begin
Copied := True;
If bbsCfg.FreeCDROM > 0 Then
Copied := DiskFree(0) DIV 1024 >= bbsCfg.FreeCDROM;
If Copied Then Copied := DiskFree(0) >= FDir.Size;
If Copied Then Begin
Session.io.PromptInfo[1] := FName;
Session.io.OutFullLn (Session.GetPrompt(82));
Copied := FileCopy(FBase.Path + FName, Session.TempPath + FName)
End;
End;
Result := Copied;
End;
Procedure TFileBase.DownloadFile;
Var
FName : String[70];
Dir : String[40];
Min : Integer;
Sec : Byte;
HangUp : Boolean;
Begin
If FBase.FileName = '' Then Begin
Session.io.OutFullLn(Session.GetPrompt(38));
Exit;
End;
If Not Session.User.Access(FBase.DLAcs) Then Begin
Session.io.OutFullLn (Session.GetPrompt(76));
Exit;
End;
Session.io.OutFull (Session.GetPrompt(344));
FName := Session.io.GetInput(70, 70, 11, '');
If FName = '' Then Exit;
Session.io.OutFullLn (Session.GetPrompt(77));
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (FDirFile); {$I+}
If IoResult <> 0 Then ReWrite (FDirFile);
While Not Eof(FDirFile) Do Begin
Read (FDirFile, FDir);
{$IFDEF FS_SENSITIVE}
If (FDir.FileName = FName) And (FDir.Flags And FDirDeleted = 0) Then Begin
{$ELSE}
If (strUpper(FDir.FileName) = strUpper(FName)) And (FDir.Flags And FDirDeleted = 0) Then Begin
{$ENDIF}
Case CheckFileLimits (1, FDir.Size DIV 1024) of
0 : Begin
Session.io.PromptInfo[1] := FDir.FileName;
Session.io.PromptInfo[2] := strComma(FDir.Size);
Session.io.PromptInfo[3] := FDir.Uploader;
Session.io.PromptInfo[4] := DateDos2Str(FDir.DateTime, Session.User.ThisUser.DateType);
Session.io.PromptInfo[5] := strI2S(FDir.Downloads);
GetTransferTime (FDir.Size, Min, Sec);
Session.io.PromptInfo[6] := strI2S(Min);
Session.io.PromptInfo[7] := strI2S(Sec);
Session.io.OutFull (Session.GetPrompt(78));
If CopiedToTemp(FName) Then
Dir := Session.TempPath
Else
Dir := FBase.Path;
HangUp := Session.io.GetYN(Session.GetPrompt(66), False);
If SendFile(Dir + FName) Then Begin
Session.SystemLog ('Downloaded: ' + FDir.FileName);
Inc (Session.User.ThisUser.DLs);
Inc (Session.User.ThisUser.DLsToday);
Inc (Session.User.ThisUser.DLk, FDir.Size DIV 1024);
Inc (Session.User.ThisUser.DLkToday, FDir.Size DIV 1024);
Inc (FDir.Downloads);
Inc (Session.HistoryDLs);
Inc (Session.HistoryDLKB, FDir.Size DIV 1024);
Seek (FDirFile, FilePos(FDirFile) - 1);
Write (FDirFile, FDir);
End Else
Session.SystemLog ('Download of ' + FDir.FileName + ' FAILED');
FileErase(Session.TempPath + FName);
If HangUp Then XferDisconnect;
End;
1 : Session.io.OutFullLn (Session.GetPrompt(224));
2 : Session.io.OutFullLn (Session.GetPrompt(58));
3 : Session.io.OutFullLn (Session.GetPrompt(211));
End;
Close (FDirFile);
Exit;
End;
End;
Close (FDirFile);
Session.io.OutFullLn (Session.GetPrompt(51));
End;
Procedure TFileBase.XferDisconnect;
Var
Timer : LongInt;
Begin
Timer := TimerSet(1000);
Session.io.OutFull(Session.GetPrompt(67));
Session.io.BufFlush;
While Not TimerUp(Timer) Do
If Session.io.InKey(1000) <> #255 Then Begin
Session.io.OutRawLn('');
Exit;
End;
Halt(0);
End;
Procedure TFileBase.DownloadBatch;
Var
A : Byte;
K : LongInt;
M : Integer;
Dir : String[40];
Old : RecFileBase;
FL : Text;
Hangup : Boolean;
Begin
K := 0;
For A := 1 to BatchNum Do Inc (K, Batch[A].Size);
GetTransferTime (K, M, A);
Session.io.PromptInfo[1] := strI2S(BatchNum);
Session.io.PromptInfo[2] := strComma(K);
Session.io.PromptInfo[3] := strI2S(M);
Session.io.PromptInfo[4] := strI2S(A);
Session.io.OutFullLn (Session.GetPrompt(79));
If SelectProtocol(True, True) = 'Q' Then Exit;
HangUp := Session.io.GetYN(Session.GetPrompt(66), False);
Assign (FL, Session.TempPath + 'file.lst');
ReWrite (FL);
Reset (FBaseFile);
For A := 1 to BatchNum Do Begin
Seek (FBaseFile, Batch[A].Area - 1);
Read (FBaseFile, Old);
FDir.Size := Batch[A].Size;
If CopiedToTemp(Batch[A].FileName) Then
Dir := Session.TempPath
Else
Dir := Old.Path;
WriteLn (FL, Dir + Batch[A].FileName);
End;
Close (FBaseFile);
Close (FL);
ExecuteProtocol(3, Session.TempPath + 'file.lst');
Reset (FBaseFile);
Session.io.OutRawLn ('');
For A := 1 to BatchNum Do Begin
Session.io.PromptInfo[1] := JustFile(Batch[A].FileName);
If DszSearch (Batch[A].FileName) Then Begin
Session.SystemLog ('Download: ' + Batch[A].FileName);
Session.io.OutFullLn (Session.GetPrompt(385));
Inc (Session.User.ThisUser.DLs);
Inc (Session.User.ThisUser.DLsToday);
Inc (Session.User.ThisUser.DLk, Batch[A].Size DIV 1024);
Inc (Session.User.ThisUser.DLkToday, Batch[A].Size DIV 1024);
Inc (Session.HistoryDLs);
Inc (Session.HistoryDLKB, Batch[A].Size DIV 1024);
Seek (FBaseFile, Batch[A].Area - 1);
Read (FBaseFile, Old);
Assign (FDirFile, bbsCfg.DataPath + Old.FileName + '.dir');
Reset (FDirFile);
While Not Eof(FDirFile) Do Begin
Read (FDirFile, FDir);
If (FDir.FileName = Batch[A].FileName) And (FDir.Flags And FDirDeleted = 0) Then Begin
Inc (FDir.Downloads);
Seek (FDirFile, FilePos(FDirFile) - 1);
Write (FDirFile, FDir);
Break;
End;
End;
Close (FDirFile);
End Else Begin
Session.SystemLog ('Download: ' + Batch[A].FileName + ' FAILED');
Session.io.OutFullLn (Session.GetPrompt(386));
End;
End;
Close (FBaseFile);
BatchNum := 0;
DirClean (Session.TempPath, '');
If HangUp Then XferDisconnect;
End;
Procedure TFileBase.FileSearch;
Var
Str : String[40];
Done : Boolean;
Found : Boolean;
All : Boolean;
Procedure Scan_Base;
Begin
Session.io.PromptInfo[1] := FBase.Name;
Session.io.OutBS (Console.CursorX, True);
Session.io.OutFull (Session.GetPrompt(87));
Session.io.BufFlush;
Case ListFiles (3, Str) of
0 : Found := False;
1 : Begin
Done := True;
Found := True;
End;
2 : Found := True;
End;
End;
Var
Old : RecFileBase;
Begin
Old := FBase;
Found := False;
Done := False;
All := False;
Session.io.OutFile ('fsearch', True, 0);
Session.io.OutFull (Session.GetPrompt(196));
Str := Session.io.GetInput(40, 40, 12, '');
If Str = '' Then Exit;
Session.SystemLog ('File search: "' + Str + '"');
All := Session.io.GetYN(Session.GetPrompt(197), True);
If All Then Session.User.IgnoreGroup := Session.io.GetYN(Session.GetPrompt(64), True);
If All Then Begin
Session.io.OutRawLn ('');
Reset (FBaseFile);
While (Not Eof(FBaseFile)) and (Not Done) Do Begin
Found := False;
Read (FBaseFile, FBase);
If Session.User.Access(FBase.ListACS) Then
Scan_Base;
End;
Close (FBaseFile);
End Else Begin
Session.io.OutRawLn ('');
Reset (FBaseFile);
Seek (FBaseFile, Session.User.ThisUser.LastFBase - 1);
Read (FBaseFile, FBase);
Scan_Base;
Close (FBaseFile);
End;
If Not Found Then Session.io.OutFullLn('|CR');
Session.io.OutFullLn (Session.GetPrompt(198));
FBase := Old;
Session.User.IgnoreGroup := False;
End;
Procedure TFileBase.NewFileScan (Mode: Char);
Var
TempFBase : RecFileBase;
Found : Boolean;
Done : Boolean;
NewFiles : Boolean;
Procedure Scan_Current_Base;
Begin
Session.io.PromptInfo[1] := FBase.Name;
Session.io.OutBS (Console.CursorX, True);
Session.io.OutFull (Session.GetPrompt(87));
Session.io.BufFlush;
Case ListFiles (2, '') of
0 : Found := False;
1 : Begin
Done := True;
Found := True;
NewFiles := True;
End;
2 : Begin
Found := True;
NewFiles := True;
End;
End;
FScan.LastNew := CurDateDos;
SetFileScan;
End;
Var
Global : Boolean;
Begin
TempFBase := FBase;
Done := False;
Found := False;
NewFiles := False;
Session.SystemLog ('Scan for new files');
Case Mode of
'G' : Global := True;
'C' : Global := False;
'A' : Begin
Global := True;
Session.User.IgnoreGroup := True;
End;
Else
Global := Session.io.GetYN(Session.GetPrompt(86), True);
End;
Session.io.OutRawLn ('');
If Global Then Begin
Reset (FBaseFile);
While (Not Eof(FBaseFile)) And (Not Done) Do Begin;
Read (FBaseFile, FBase);
GetFileScan;
If (FScan.NewScan > 0) and Session.User.Access(FBase.ListACS) Then Scan_Current_Base;
End;
Close (FBaseFile);
End Else Begin
If FBase.FileName = '' Then
Session.io.OutFullLn(Session.GetPrompt(038))
Else Begin
GetFileScan;
Reset (FBaseFile);
Seek (FBaseFile, Session.User.ThisUser.LastFBase - 1);
Read (FBaseFile, FBase);
Scan_Current_Base;
Close (FBaseFile);
End;
End;
If Not Found Then Session.io.OutFullLn('|CR');
If NewFiles Then
Session.io.OutFullLn (Session.GetPrompt(89))
Else
Session.io.OutFullLn (Session.GetPrompt(88));
Session.User.IgnoreGroup := False;
FBase := TempFBase;
End;
(**************************************************************************)
(* FILE SECTION - SYSOP FUNCTIONS *)
(**************************************************************************)
Procedure TFileBase.DirectoryEditor (Edit : Boolean; Mask: String);
Function Get_Next_File (Back: Boolean): Boolean;
Var
Old : RecFileList;
Pos : LongInt;
Begin
Old := FDir;
Pos := FilePos(FDirFile);
Result := True;
Repeat
If (Eof(FDirFile) And Not Back) or ((FilePos(FDirFile) = 1) and Back) Then Begin
FDir := Old;
Seek (FDirFile, Pos);
Result := False;
Exit;
End;
If Back Then Seek (FDirFile, FilePos(FDirFile) - 2);
Read (FDirFile, FDir);
If (FDir.Flags And FDirDeleted = 0) and WildMatch(Mask, FDir.FileName, False) Then
Break;
Until False;
End;
Var
DataFile : File;
DataFile2 : File;
A : Integer;
B : Integer;
Temp : String;
Old : RecFileBase;
TF : Text;
Begin
If FBase.FileName = '' Then Begin
Session.io.OutFullLn(Session.GetPrompt(38));
Exit;
End;
If Not Session.User.Access(FBase.SysopACS) Then Begin
Session.io.OutFullLn (Session.GetPrompt(39));
Exit;
End;
If Mask = '' Then Begin
Session.io.OutFull (Session.GetPrompt(195));
Mask := Session.io.GetInput(70, 70, 11, '*.*');
End;
Session.SystemLog ('File DIR editor');
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (FDirFile); {$I+}
If IoResult <> 0 Then Begin
Session.io.OutFullLn (Session.GetPrompt(40));
Exit;
End;
If Eof(FDirFile) Then Begin
Session.io.OutFullLn (Session.GetPrompt(40));
Close (FDirFile);
Exit;
End;
Assign (DataFile, bbsCfg.DataPath + FBase.FileName + '.des');
{$I-} Reset (DataFile, 1); {$I+}
If IoResult <> 0 Then ReWrite (DataFile, 1);
If Get_Next_File(False) Then Begin
If Edit Then Mask := '*.*';
Repeat
Session.io.OutFullLn ('|07|CLFile DIR Editor : ' + strI2S(FilePos(FDirFile)) + ' of ' + strI2S(FileSize(FDirFile)));
Session.io.OutFullLn ('|08|$D79Ä');
Session.io.OutFullLn ('|031) |14' + FDir.FileName);
Session.io.OutFullLn ('|08|$D79Ä');
Session.io.OutFullLn ('|032) File Size : |11' + strPadR(strComma(FDir.Size) + ' bytes', 19, ' ') +
'|033) Uploader : |11' + FDir.Uploader);
Session.io.OutFullLn ('|034) File Date : |11' + strPadR(DateDos2Str(FDir.DateTime, Session.User.ThisUser.DateType), 19, ' ') +
'|035) Downloads : |11' + strI2S(FDir.Downloads));
Session.io.OutFull ('|036) Status : |11');
Temp := '';
If FDir.Flags And FDirDeleted <> 0 Then
Temp := '|12DELETED'
Else Begin
If FDir.Flags And FDirInvalid <> 0 Then Temp := 'Invalid ';
If FDir.Flags And FDirOffline <> 0 Then Temp := Temp + 'Offline ';
If FDir.Flags And FDirFailed <> 0 Then Temp := Temp + 'Failed ';
If FDir.Flags And FDirFree <> 0 Then Temp := Temp + 'Free';
If Temp = '' Then Temp := 'Normal';
End;
Session.io.OutFullLn (Temp);
Session.io.OutFullLn ('|08|$D79Ä');
Seek (DataFile, FDir.DescPtr);
For A := 1 to 11 Do Begin
Temp := '';
If A <= FDir.DescLines Then Begin
BlockRead (DataFile, Temp[0], 1);
BlockRead (DataFile, Temp[1], Ord(Temp[0]));
End;
If A = 1 Then
Session.io.OutFullLn ('|03!) Description : |07' + Temp)
Else
Session.io.OutFullLn (strRep(' ', 17) + Temp);
End;
Session.io.OutFullLn ('|08|$D79Ä');
Session.io.OutFull ('|09([) Previous (]) Next (D) Delete (I) Import DIZ (U) Update DIZ' +
'|CR(M) Move (V) View Archive (E) Email ULer (Q) Quit: ');
Case Session.io.OneKey('123456[]DEIMQUV!', True) of
'1' : Begin
Temp := Session.io.InXY (4, 3, 70, 70, 11, FDir.FileName);
If FBase.Flags And FBSlowMedia = 0 Then
If (Temp <> FDir.FileName) and (Temp <> '') Then Begin
If Not FileExist(FBase.Path + Temp) or (strUpper(Temp) = strUpper(FDir.FileName)) Then Begin
Assign(TF, FBase.Path + FDir.FileName);
{$I-} ReName(TF, FBase.Path + Temp); {$I+}
If IoResult = 0 Then FDir.FileName := Temp;
End;
End;
End;
'D' : Begin
If Session.io.GetYN('|CR|12Delete this entry? |11', False) Then Begin
FDir.Flags := FDir.Flags Or FDirDeleted;
If FileExist(FBase.Path + FDir.FileName) Then
If Session.io.GetYN ('|12Delete ' + FBase.Path + FDir.FileName + '? |11', False) Then
FileErase(FBase.Path + FDir.FileName);
End Else
FDir.Flags := FDir.Flags And (Not FDirDeleted);
Seek (FDirFile, FilePos(FDirFile) - 1);
Write (FDirFile, FDir);
End;
'E' : Session.Menu.ExecuteCommand ('MW', '/TO:' + strReplace(FDir.Uploader, ' ', '_'));
'I' : Begin
Session.io.OutFullLn ('|CR|14Importing file_id.diz...');
If ImportDIZ(FDir.FileName) Then Begin
FDir.DescPtr := FileSize(DataFile);
Seek (DataFile, FDir.DescPtr);
For A := 1 to FDir.DescLines Do
BlockWrite (DataFile, Session.Msgs.MsgText[A][0], Length(Session.Msgs.MsgText[A]) + 1);
End;
End;
'M' : Begin
Session.User.IgnoreGroup := True;
Repeat
Session.io.OutFull ('|CR|09Move to which base (?/List): ');
Temp := Session.io.GetInput(4, 4, 12, '');
If Temp = '?' Then Begin
Old := FBase;
ListFileAreas(False);
FBase := Old;
End Else Begin
Reset (FBaseFile);
B := strS2I(Temp);
If (B > 0) and (B <= FileSize(FBaseFile)) Then Begin
Session.io.OutFull ('|CR|14Moving |15' + FDir.FileName + '|14: ');
Old := FBase;
Seek (FBaseFile, B - 1);
Read (FBaseFile, FBase);
If FileExist(FBase.Path + FDir.FileName) or (Not FileCopy(Old.Path + FDir.FileName, FBase.Path + FDir.FileName)) Then Begin
Session.io.OutFull ('ERROR|CR|CR|PA');
FBase := Old;
Break;
End;
FileErase(Old.Path + FDir.FileName);
A := FilePos(FDirFile);
Close (FDirFile);
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
{$I-} Reset (FDirFile); {$I+}
If IoResult <> 0 Then ReWrite(FDirFile);
Assign (DataFile2, bbsCfg.DataPath + FBase.FileName + '.des');
{$I-} Reset (DataFile2, 1); {$I+}
If IoResult <> 0 Then ReWrite (DataFile2, 1);
Seek (DataFile, FDir.DescPtr);
FDir.DescPtr := FileSize(DataFile2);
Seek (DataFile2, FDir.DescPtr);
For B := 1 to FDir.DescLines Do Begin
BlockRead (DataFile, Temp[0], 1);
BlockRead (DataFile, Temp[1], Ord(Temp[0]));
BlockWrite (DataFile2, Temp[0], Length(Temp) + 1);
End;
Close (DataFile2);
Seek (FDirFile, FileSize(FDirFile));
Write (FDirFile, FDir);
Close (FDirFile);
FBase := Old;
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
Reset (FDirFile);
Seek (FDirFile, A - 1);
Read (FDirFile, FDir);
FDir.Flags := FDir.Flags Or FDirDeleted;
End;
Close (FBaseFile);
Break;
End;
Until False;
Session.User.IgnoreGroup := False;
End;
'Q' : Begin
Seek (FDirFile, FilePos(FDirFile) - 1);
Write (FDirFile, FDir);
Break;
End;
'U' : Begin
Session.io.OutFullLn ('|CR|14Updating FILE_ID.DIZ...');
Assign (TF, Session.TempPath + 'file_id.diz');
ReWrite (TF);
Seek (DataFile, FDir.DescPtr);
For B := 1 to FDir.DescLines Do Begin
BlockRead (DataFile, Temp[0], 1);
BlockRead (DataFile, Temp[1], Ord(Temp[0]));
WriteLn (TF, Temp);
End;
Close (TF);
ExecuteArchive (FBase.Path + FDir.FileName, '', Session.TempPath + 'file_id.diz', 1);
FileErase(Session.TempPath + 'file_id.diz');
End;
'V' : If Not ArchiveView (FBase.Path + FDir.FileName) Then Session.io.OutFullLn(Session.GetPrompt(191));
'[' : Begin
Seek (FDirFile, FilePos(FDirFile) - 1);
Write (FDirFile, FDir);
Get_Next_File(True);
End;
']' : Begin
Seek (FDirFile, FilePos(FDirFile) - 1);
Write (FDirFile, FDir);
Get_Next_File(False);
End;
'!' : Begin
Seek (DataFile, FDir.DescPtr);
If FDir.DescLines > bbsCfg.MaxFileDesc Then FDir.DescLines := bbsCfg.MaxFileDesc;
For A := 1 to FDir.DescLines Do Begin
BlockRead (DataFile, Session.Msgs.MsgText[A][0], 1);
BlockRead (DataFile, Session.Msgs.MsgText[A][1], Ord(Session.Msgs.MsgText[A][0]));
End;
Temp := 'Description Editor';
B := FDir.DescLines;
If Editor(B, mysMaxFileDescLen, bbsCfg.MaxFileDesc, False, fn_tplTextEdit, Temp) Then Begin
FDir.DescLines := B;
FDir.DescPtr := FileSize(DataFile);
Seek (DataFile, FDir.DescPtr);
For A := 1 to FDir.DescLines Do
BlockWrite (DataFile, Session.Msgs.MsgText[A][0], Length(Session.Msgs.MsgText[A]) + 1);
End;
End;
'2' : Begin
Session.io.OutFull ('Size: ');
FDir.Size := strS2I(Session.io.GetInput(8, 8, 12, strI2S(FDir.Size)));
End;
'4' : FDir.DateTime := DateStr2Dos(Session.io.InXY(16, 6, 8, 8, 15, DateDos2Str(FDir.DateTime, Session.User.ThisUser.DateType)));
'3' : FDir.Uploader := Session.io.InXY(50, 5, 30, 30, 18, FDir.Uploader);
'5' : FDir.Downloads := strS2I(Session.io.InXY(50, 6, 4, 4, 12, strI2S(FDir.Downloads)));
'6' : Begin
Session.io.OutFull('|CRFlags: F(a)iled, (F)ree, (O)ffline, (U)nvalidated, (Q)uit: ');
Case Session.io.OneKey('AFOUQ', True) of
'A' : FDir.Flags := FDir.Flags XOR FDirFailed;
'F' : FDir.Flags := FDir.Flags XOR FDirFree;
'O' : FDir.Flags := FDir.Flags XOR FDirOffline;
'U' : FDir.Flags := FDir.Flags XOR FDirInvalid;
End;
End;
End;
Until False;
End;
Close (FDirFile);
Close (DataFile);
End;
Procedure TFileBase.MassUpload;
Var
Done : Boolean;
AutoAll : Boolean;
Procedure Do_Area;
Var
A : Byte;
OldPos : Word;
Skip : Boolean;
DataFile : File;
DirInfo : SearchRec;
AutoArea : Boolean;
Temp : String;
Begin
If FBase.FileName = '' Then Exit;
AutoArea := AutoAll;
Session.io.OutFullLn ('|CR|03Processing |14|FB|03...');
Assign (DataFile, bbsCfg.DataPath + FBase.FileName + '.des');
{$I-} Reset (DataFile, 1); {$I+}
If IoResult = 0 Then
Seek (DataFile, FileSize(DataFile))
Else
ReWrite (DataFile, 1);
Assign (FDirFile, bbsCfg.DataPath + FBase.FileName + '.dir');
FindFirst(FBase.Path + '*', Archive, DirInfo);
While DosError = 0 Do Begin
OldPos := FilePos(FBaseFile);
Close (FBaseFile);
CheckFileNameLength(FBase.Path, DirInfo.Name);
Skip := IsDupeFile(DirInfo.Name, False);
Reset (FBaseFile);
Seek (FBaseFile, OldPos);
If Not Skip Then
Session.io.OutFullLn ('|CR|03File : |14' + DirInfo.Name);
If Not AutoArea And Not Skip Then Begin
Session.io.OutFull ('|03Cmd : |09(Y)es, (N)o, (A)uto, (G)lobal, (S)kip, (Q)uit: ');
Case Session.io.OneKey('AGNQSY', True) of
'A' : AutoArea := True;
'G' : Begin
AutoArea := True;
AutoAll := True;
End;
'N' : Skip := True;
'Q' : Begin
Done := True;
Break;
End;
'S' : Break;
End;
End;
If Not Skip Then Begin
FDir.FileName := DirInfo.Name;
FDir.Size := DirInfo.Size;
FDir.DateTime := CurDateDos;
FDir.Uploader := Session.User.ThisUser.Handle;
FDir.Downloads := 0;
FDir.Flags := 0;
FDir.DescLines := 0;
FDir.Rating := 0;
If bbsCfg.ImportDIZ Then
If Not ImportDIZ(DirInfo.Name) Then
If Not AutoArea Then
GetFileDescription(DirInfo.Name);
If FDir.DescLines = 0 Then Begin
Session.Msgs.MsgText[1] := Session.GetPrompt(208);
FDir.DescLines := 1;
End;
FDir.DescPtr := FileSize(DataFile);
For A := 1 to FDir.DescLines Do
BlockWrite (DataFile, Session.Msgs.MsgText[A][0], Length(Session.Msgs.MsgText[A]) + 1);
If bbsCfg.TestUploads and (bbsCfg.TestCmdLine <> '') Then Begin
Temp := '';
A := 1;
While A <= Length(bbsCfg.TestCmdLine) Do Begin
If bbsCfg.TestCmdLine[A] = '%' Then Begin
Inc(A);
If bbsCfg.TestCmdLine[A] = '1' Then Temp := Temp + '1' Else
If bbsCfg.TestCmdLine[A] = '2' Then Temp := Temp + '38400' Else
If bbsCfg.TestCmdLine[A] = '3' Then Temp := Temp + FBase.Path + FDir.FileName;
End Else
Temp := Temp + bbsCfg.TestCmdLine[A];
Inc (A);
End;
If ShellDOS('', Temp) <> bbsCfg.TestPassLevel Then
FDir.Flags := FDir.Flags OR FDirFailed;
End;
{$I-} Reset (FDirFile); {$I+}
If IoResult <> 0 Then ReWrite(FDirFile);
Seek (FDirFile, FileSize(FDirFile));
Write (FDirFile, FDir);
Close (FDirFile);
End;
FindNext(DirInfo);
End;
FindClose(DirInfo);
Close (DataFile);
End;
Var
Old : RecFileBase;
Pos : LongInt;
Begin
Session.SystemLog ('Mass upload');
Old := FBase;
Done := False;
AutoAll := False;
Reset (FBaseFile);
If Session.io.GetYN('|CR|12Upload files in all directories? |11', True) Then Begin {++lang}
While Not Done and Not Eof(FBaseFile) Do Begin
Read (FBaseFile, FBase);
Pos := FilePos(FBaseFile);
Do_Area;
Seek (FBaseFile, Pos);
End;
End Else
Do_Area;
Close (FBaseFile);
FBase := Old;
End;
End.