Pipes and NodeSpy

This commit is contained in:
mysticbbs 2012-08-21 12:23:47 -04:00
parent 84e18433f9
commit 1a9939306f
18 changed files with 394 additions and 156 deletions

View File

@ -4689,4 +4689,9 @@
list display to not get redrawn after.
! Duplicate IP check in MIS was not working properly. It is now.
+ MIS telnet in Windows now has an option to hide node windows.
+ Added a new utility called NodeSpy. This utility will allow you to see
who is online from the command line. It will also allow you to snoop/spy
on a node, kick people from a node, and engage in chat with the user.

View File

@ -11,6 +11,7 @@ Uses
{$ENDIF}
m_FileIO,
m_Strings,
m_Pipe_Disk,
m_DateTime,
BBS_Common,
BBS_IO,
@ -26,13 +27,14 @@ Const
Type
TBBSCore = Class
{$IFNDEF UNIX}
Client : TIOBase;
Client : TIOBase;
{$ENDIF}
User : TBBSUser;
Msgs : TMsgBase;
FileBase : TFileBase;
Menu : TMenuEngine;
IO : TBBSIO;
Pipe : TPipeDisk;
EventFile : File of EventRec;
ThemeFile : File of RecTheme;
VoteFile : File of VoteRec;
@ -142,6 +144,7 @@ End;
Destructor TBBSCore.Destroy;
Begin
Pipe.Free;
Msgs.Free;
FileBase.Free;
Menu.Free;
@ -161,7 +164,7 @@ Procedure TBBSCore.UpdateHistory;
Var
History : RecHistory;
Begin
If User.ThisUser.Flags AND UserNoHistory = 0 Then Exit;
If User.ThisUser.Flags AND UserNoHistory <> 0 Then Exit;
Assign (HistoryFile, Config.DataPath + 'history.dat');
ioReset (HistoryFile, SizeOf(RecHistory), fmRWDN);

View File

@ -13,18 +13,9 @@ Uses
bbs_Common,
bbs_Core;
Procedure Print (S: String);
Begin
{$IFNDEF UNIX}
If Not Session.LocalMode Then Session.io.BufAddStr(S);
{$ENDIF}
Screen.WriteStr(S);
End;
Procedure PrintLn (S: String);
Begin
Print (S + #13#10);
Session.io.BufAddStr(S + #13#10);
End;
Function AnsiEditor (Var Lines: Integer; WrapPos: Byte; MaxLines: Integer; TEdit, Forced: Boolean; Var Subj: String) : Boolean;
@ -70,7 +61,7 @@ Begin
B := CurLine;
Repeat
If B <= TotalLine Then Print(Session.Msgs.MsgText[B]);
If B <= TotalLine Then Session.io.BufAddStr(Session.Msgs.MsgText[B]);
If B <= TotalLine + 1 Then Begin
Session.io.AnsiClrEOL;
PrintLn('');
@ -101,7 +92,7 @@ Begin
A := WinStart;
Repeat
If B <= TotalLine Then Print(Session.Msgs.MsgText[B]);
If B <= TotalLine Then Session.io.BufAddStr(Session.Msgs.MsgText[B]);
Session.io.AnsiClrEOL;
PrintLn('');
Inc (A);
@ -208,7 +199,7 @@ Begin
Repeat
If (CurY + (A - CurLine) <= WinEnd) and (A <= TotalLine) Then Begin
Print(Session.Msgs.MsgText[A]);
Session.io.BufAddStr(Session.Msgs.MsgText[A]);
Session.io.AnsiClrEOL;
PrintLn('');
End Else
@ -291,7 +282,7 @@ Begin
Delete (Session.Msgs.MsgText[CurLine], CurX, 1);
If CurX < Length(Session.Msgs.MsgText[CurLine]) + 1 Then Begin
Print (Copy(Session.Msgs.MsgText[CurLine], CurX, Length(Session.Msgs.MsgText[CurLine])) + ' ');
Session.io.BufAddStr (Copy(Session.Msgs.MsgText[CurLine], CurX, Length(Session.Msgs.MsgText[CurLine])) + ' ');
UpdatePosition;
End;
End Else
@ -391,13 +382,13 @@ Procedure AddChar (Ch: Char);
Begin
If InsertMode Then Begin
Insert (Ch, Session.Msgs.MsgText[Curline], CurX);
Print (Copy(Session.Msgs.MsgText[CurLine], CurX, Length(Session.Msgs.MsgText[CurLine])));
Session.io.BufAddStr (Copy(Session.Msgs.MsgText[CurLine], CurX, Length(Session.Msgs.MsgText[CurLine])));
End Else Begin
If CurX > Length(Session.Msgs.MsgText[CurLine]) Then
Inc(Session.Msgs.MsgText[CurLine][0]);
Session.Msgs.MsgText[CurLine][CurX] := Ch;
Print (Ch);
Session.io.BufAddStr (Ch);
End;
Inc (CurX);
@ -412,7 +403,7 @@ Begin
Session.io.AnsiColor (Session.io.ScreenInfo[3].A);
Session.io.AnsiGotoXY (Session.io.ScreenInfo[3].X, Session.io.ScreenInfo[3].Y);
If InsertMode Then Print('INS') else Print('OVR'); { ++lang }
If InsertMode Then Session.io.BufAddStr('INS') else Session.io.BufAddStr('OVR'); { ++lang }
Session.io.AnsiGotoXY (CurX, CurY);
Session.io.AnsiColor (WinText);
@ -520,7 +511,7 @@ Var
Else
Session.io.AnsiColor (Session.io.ScreenInfo[2].A);
Print (strPadR(QText[QuoteTopPage + QuoteCurLine], 79, ' '));
Session.io.BufAddStr (strPadR(QText[QuoteTopPage + QuoteCurLine], 79, ' '));
End;
Procedure UpdateWindow;
@ -531,7 +522,7 @@ Var
Session.io.AnsiColor (Session.io.ScreenInfo[2].A);
For Count := QuoteTopPage to QuoteTopPage + 5 Do Begin
If Count <= QuoteLines Then Print (QText[Count]);
If Count <= QuoteLines Then Session.io.BufAddStr (QText[Count]);
Session.io.AnsiClrEOL;
@ -805,7 +796,7 @@ Begin
#82 : ToggleInsert(True);
#83 : If CurX <= Length(Session.Msgs.MsgText[CurLine]) Then Begin
Delete (Session.Msgs.MsgText[CurLine], CurX, 1);
Print (Copy(Session.Msgs.MsgText[CurLine], CurX, Length(Session.Msgs.MsgText[CurLine])) + ' ');
Session.io.BufAddStr (Copy(Session.Msgs.MsgText[CurLine], CurX, Length(Session.Msgs.MsgText[CurLine])) + ' ');
UpdatePosition;
End Else
If CurLine < TotalLine Then

View File

@ -56,11 +56,11 @@ Type
InputPos : Byte;
GetKeyCallBack : TGetKeyCallBack;
LastSecond : LongInt;
OutBuffer : Array[0..TBBSIOBufferSize] of Char;
OutBufPos : SmallInt;
{$IFDEF WINDOWS}
OutBuffer : Array[0..TBBSIOBufferSize] of Char;
OutBufPos : SmallInt;
SocketEvent : THandle;
SocketEvent : THandle;
{$ENDIF}
Constructor Create (Var Owner: Pointer);
@ -143,11 +143,11 @@ Begin
LastMCIValue := '';
InputPos := 0;
FillChar(OutBuffer, SizeOf(OutBuffer), 0);
OutBufPos := 0;
{$IFDEF WINDOWS}
FillChar(OutBuffer, SizeOf(OutBuffer), 0);
OutBufPos := 0;
If Not TBBSCore(Core).LocalMode Then
SocketEvent := WSACreateEvent;
{$ENDIF}
@ -168,13 +168,11 @@ End;
Procedure TBBSIO.BufAddChar (Ch: Char);
Begin
{$IFDEF WINDOWS}
OutBuffer[OutBufPos] := Ch;
Inc (OutBufPos);
If OutBufPos = TBBSIOBufferSize Then BufFlush;
{$ENDIF}
Term.Process(Ch);
End;
@ -194,11 +192,19 @@ Begin
If Not TBBSCore(Core).LocalMode Then
TBBSCore(Core).Client.WriteBuf(OutBuffer, OutBufPos);
If Session.Pipe.Connected Then
Session.Pipe.SendToPipe(OutBuffer, OutBufPos);
OutBufPos := 0;
End;
{$ENDIF}
{$IFDEF UNIX}
If Session.Pipe.Connected Then
Session.Pipe.SendToPipe(OutBuffer, OutBufPos);
OutBufPos := 0;
Screen.BufFlush;
{$ENDIF}
End;

View File

@ -275,7 +275,7 @@ Begin
'C' : Node_Chat;
'P' : PageUserForChat;
'S' : Send_Node_Message (3, CmdData, 0);
'W' : Show_Whos_Online;
'W' : WhosOnline;
End;
'O' : Case Cmd[2] of
'S' : Session.Msgs.ToggleNewScan(True);

View File

@ -450,7 +450,7 @@ Begin
End Else
If Str2 = '/WHO' Then Begin
Session.io.AnsiClear;
Show_Whos_Online;
WhosOnline;
Chat_Template;
FullReDraw;
End Else

View File

@ -9,7 +9,7 @@ Uses
Function GetChatRecord (Node: Byte; Var Chat: ChatRec) : Boolean;
Function IsUserOnline (UserName: String) : Word;
Procedure Show_Whos_Online;
Procedure WhosOnline;
Procedure Send_Node_Message (MsgType: Byte; Data: String; Room: Byte);
Function CheckNodeMessages : Boolean;
Procedure Set_Node_Action (Action: String);
@ -87,7 +87,7 @@ Begin
{$ENDIF}
End;
Procedure Show_Whos_Online;
Procedure WhosOnline;
Var
TChat : ChatRec;
Count : Word;
@ -97,19 +97,12 @@ Begin
For Count := 1 to Config.INetTNNodes Do Begin
Session.io.PromptInfo[1] := strI2S(Count);
Assign (ChatFile, Config.DataPath + 'chat' + strI2S(Count) + '.dat');
{$I-} Reset(ChatFile); {$I+}
If IoResult <> 0 Then Begin
If Not GetChatRecord (Count, TChat) Then Begin
Session.io.OutFullLn (Session.GetPrompt(268));
Continue;
End;
Read (ChatFile, TChat);
Close (ChatFile);
If TChat.Active and ((Not TChat.Invisible) or (TChat.Invisible and Session.User.Access(Config.AcsSeeInvis))) Then Begin
Session.io.PromptInfo[2] := TChat.Name;
Session.io.PromptInfo[3] := TChat.Action;
@ -141,7 +134,7 @@ Begin
Repeat
Session.io.OutFull (Session.GetPrompt(146));
Str := Session.io.GetInput(3, 3, 12, '');
If Str = '?' Then Show_Whos_Online Else Break;
If Str = '?' Then WhosOnline Else Break;
Until False;
ToNode := strS2I(Str);
@ -230,8 +223,7 @@ Var
MsgFile : File of NodeMsgRec;
SplitChat : Boolean;
Begin
Result := False;
FileMode := 66;
Result := False;
Assign (MsgFile, Session.TempPath + 'chat.tmp');
@ -276,6 +268,12 @@ Begin
OpenUserChat(SplitChat, True, Msg.FromNode);
End;
10: OpenUserChat(SplitChat, False, Msg.FromNode);
11: Begin
Session.Pipe.CreatePipe;
Session.Pipe.WaitForPipe(300);
End;
12: If Session.Pipe.Connected Then Session.Pipe.Disconnect;
13: Halt(0);
End;
If Result And (Msg.MsgType = 3) Then

View File

@ -1081,7 +1081,7 @@ Begin
ThisUser.CallsToday := 0;
ThisUser.DLsToday := 0;
ThisUser.DLkToday := 0;
ThisUser.TimeLeft := Security.Time
ThisUser.TimeLeft := Security.Time;
End;
If Not Session.LocalMode And (ThisUser.Flags AND UserNoLastCall = 0) Then Begin
@ -1138,8 +1138,6 @@ Begin
If (Session.TimeOffset = 0) or (Session.TimeOffset > ThisUser.TimeLeft) Then
Session.SetTimeLeft (ThisUser.TimeLeft);
// check account expired -- DONE
// check password change -- DONE
// check auto-upgrades posts/calls/downloads/uploads/etc
If DateValid(Session.User.ThisUser.Expires) Then

View File

@ -29,7 +29,7 @@ Begin
Str := Session.io.GetInput(3, 3, 12, '');
If Str = '?' Then Show_Whos_Online Else
If Str = '?' Then WhosOnline Else
If Str = 'Q' Then Exit Else Break;
Until False;

View File

@ -373,7 +373,7 @@
; &1 = File base name
203 |CR |11|&1 will NOT be scanned in new file scan!|CR
; &1 = File base name
204 |CR| 11|&1 will be scanned in new file scan!|CR
204 |CR |11|&1 will be scanned in new file scan!|CR
; Displayed if file already exists when user trys to upload.
205 File already exists.
; Displayed before running uploads processor
@ -938,11 +938,11 @@
; User2User sending chat request &1=User &2=Node
482 |CR|15Sending chat request to |&1...|DE|DE|CR
; User2User chat mode starting
483 |CL|09|17 ° |15Chat mode engaged.|$X70 ESC/Quit |16|CR
483 |16|CL|09|17 ° |15Chat mode engaged.|$X70 ESC/Quit |16|CR
; User2User chat mode ended
484 |CL|09|17 ° |15Chat mode end.|$X79 |16|DE|DE
484 |16|CL|09|17 ° |15Chat mode end.|$X79 |16|DE|DE
; User2User accept chat page request? &1=user &2=Node
485 |CL|15|&1 is requesting private user chat. Accept? |11
485 |16|CL|15|&1 is requesting private user chat. Accept? |11
; MsgBase quickscan header prompt
486 |CR|12Starting Quick Scan|CR
; MsgBase quickscan Scanning prompt

View File

@ -419,6 +419,7 @@ Begin
End;
{$IFDEF UNIX}
(*
Procedure Snoop;
Begin
If FocusCurrent <> FocusTelnet Then Exit;
@ -453,7 +454,7 @@ Begin
SwitchFocus;
End;
End;
*)
Procedure DaemonEventSignal (Sig : LongInt); cdecl;
Begin
Case Sig of
@ -592,7 +593,7 @@ Begin
End;
End;
#09 : SwitchFocus;
#13 : {$IFDEF UNIX}Snoop{$ENDIF};
// #13 : {$IFDEF UNIX}Snoop{$ENDIF};
#27 : Break;
#32 : LocalLogin;
End;

View File

@ -31,7 +31,7 @@ Const
#1,'³',#25,'K','³', #8,'°',#24,'°', #1,'³',#25,'K','³', #8,'°',#24,
'°', #1,'À',#26,'K','Ä','Ù', #8,'°',#24,#26,'O','°',#24,#23,' ', #1,
'T','A','B','/','S','w','i','t','c','h',' ','W','i','n','d','o','w',
#25, #2,'E','N','T','E','R','/','S','n','o','o','p',#25, #2,'S','P',
#25, #2,' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',#25, #2,'S','P',
'A','C','E','/','L','o','c','a','l',#25, #2,'A','L','T','-','K','/',
'K','i','l','l',' ','U','s','e','r',#25, #2,'E','S','C','/','S','h',
'u','t','d','o','w','n',' ',#24);
@ -39,10 +39,6 @@ Begin
Console.LoadScreenImage(ImageData, ImageData_Length, ImageData_Width, 1, 1);
//Console.WriteXY (25, 1, 113, strPadC(mysVersionText, 30, ' '));
{$IFDEF UNIX}
Console.WriteXY (1, 25, 113, strPadC('ENTER/Snoop SPACE/Local TELNET TAB/Switch ESC/Shutdown', 79, ' '));
{$ELSE}
Console.WriteXY (1, 25, 113, strPadC('SPACE/Local TELNET TAB/Switch ESC/Shutdown', 79, ' '));
{$ENDIF}
Console.WriteXY (1, 25, 113, strPadC('SPACE/Local TELNET TAB/Switch ESC/Shutdown', 79, ' '));
End;

View File

@ -28,7 +28,7 @@ Function CreateTelnet (Owner: TServerManager; Config: RecConfig; ND: TNodeData;
Type
TTelnetServer = Class(TServerClient)
ND : TNodeData;
Snooping : Boolean;
// Snooping : Boolean;
Constructor Create (Owner: TServerManager; ND: TNodeData; CliSock: TIOSocket);
Procedure Execute; Override;
Destructor Destroy; Override;
@ -46,7 +46,7 @@ Begin
Inherited Create(Owner, CliSock);
Self.ND := ND;
Snooping := False;
// Snooping := False;
End;
{$IFDEF WINDOWS}
@ -84,8 +84,12 @@ Begin
FillChar(SI, SizeOf(SI), 0);
FillChar(PI, SizeOf(PI), 0);
SI.dwFlags := STARTF_USESHOWWINDOW;
SI.wShowWindow := SW_SHOWMINNOACTIVE;
SI.dwFlags := STARTF_USESHOWWINDOW;
If bbsConfig.inetTNHidden Then
SI.wShowWindow := SW_HIDE
Else
SI.wShowWindow := SW_SHOWMINNOACTIVE;
If CreateProcess(NIL, PChar(@Cmd[1]),
NIL, NIL, True, Create_New_Console + Normal_Priority_Class, NIL, NIL, SI, PI) Then
@ -140,8 +144,8 @@ Begin
bRead := Proc.Output.Read(Buffer, BufferSize);
Client.WriteBufEscaped (Buffer, bRead);
If Snooping Then
Term.ProcessBuf(Buffer[0], bRead);
// If Snooping Then
// Term.ProcessBuf(Buffer[0], bRead);
End;
End Else
If Client.DataWaiting Then Begin

View File

@ -40,7 +40,7 @@
Import_FIDONET.NA = false
Import_FILEBONE.NA = false
Import_FILES.BBS = false
Import_FILES.BBS = true
MassUpload = false
GenerateTopLists = false

View File

@ -40,6 +40,7 @@ Uses
m_DateTime,
m_Output,
m_Input,
m_Pipe_Disk,
bbs_Common,
bbs_Core,
bbs_NodeInfo,
@ -233,6 +234,8 @@ Begin
Session.TempPath := Config.SystemPath + 'temp' + strI2S(Session.NodeNum) + PathChar;
Session.Pipe := TPipeDisk.Create(Config.DataPath, False, Session.NodeNum);
{$I-}
MkDir (Config.SystemPath + 'temp' + strI2S(Session.NodeNum));
{$I+}

View File

@ -1,5 +1,12 @@
Program NodeSpy;
// page chat
// user editor
// split chat
// auto snoop
// local login
// terminal mode
{$I M_OPS.PAS}
Uses
@ -22,9 +29,21 @@ Uses
Const
HiddenNode = 255;
UpdateTimer = 500;
UpdateNode = 500;
UpdateStats = 6000 * 10;
AutoSnoop : Boolean = True;
Type
PNodeInfo = ^TNodeInfo;
TNodeInfo = Record
Node : Byte;
User : String[30];
Action : String[50];
End;
Var
NodeInfo : Array[1..255] of PNodeInfo;
ChatFile : File of ChatRec;
Chat : ChatRec;
ConfigFile : File of RecConfig;
@ -35,6 +54,75 @@ Var
Screen : TOutput;
Keyboard : TInput;
{$I NODESPY_ANSI.PAS}
Procedure ApplicationShutdown;
Var
Count : Byte;
Begin
For Count := Config.inetTNNodes DownTo 1 Do
If Assigned(NodeInfo[Count]) Then
Dispose(NodeInfo[Count]);
Keyboard.Free;
Screen.Free;
End;
Procedure ApplicationInit;
Var
{$IFDEF UNIX}
Info : Stat;
{$ENDIF}
Count : Byte;
Begin
{$IFDEF UNIX}
If fpStat('nodespy', Info) = 0 Then Begin
fpSetGID (Info.st_GID);
fpSetUID (Info.st_UID);
End;
{$ENDIF}
ExitProc := @ApplicationShutdown;
Screen := TOutput.Create(True);
Keyboard := TInput.Create;
Assign (ConfigFile, 'mystic.dat');
Reset (ConfigFile);
If IoResult <> 0 Then Begin
BasePath := GetENV('mysticbbs');
If BasePath <> '' Then BasePath := DirSlash(BasePath);
Assign (ConfigFile, BasePath + 'mystic.dat');
Reset (ConfigFile);
If IoResult <> 0 Then Begin
Screen.WriteLine ('ERROR: Unable to read MYSTIC.DAT' + #13#10);
Screen.WriteLine ('MYSTIC.DAT must exist in the same directory as NodeSpy, or in the');
Screen.WriteLine ('path defined by the MYSTICBBS environment variable.');
Halt (1);
End;
End;
Read (ConfigFile, Config);
Close (ConfigFile);
If Config.DataChanged <> mysDataChanged Then Begin
Screen.WriteLine ('ERROR: NodeSpy has detected a version mismatch' + #13#10);
Screen.WriteLine ('NodeSpy or another BBS utility is an older incompatible version. Make');
Screen.WriteLine ('sure you have upgraded properly!');
Halt (1);
End;
DirCreate(Config.SystemPath + 'temp' + strI2S(HiddenNode));
For Count := 1 to Config.inetTNNodes Do
New (NodeInfo[Count]);
End;
Function ShowMsgBox (BoxType: Byte; Str: String) : Boolean;
Var
Len : Byte;
@ -119,6 +207,7 @@ Begin
MsgBox.Free;
Screen.CursorXY (SavedX, SavedY);
Screen.TextAttr := SavedA;
End;
@ -277,8 +366,8 @@ Begin
Screen.TextAttr := 7;
Screen.ClearScreen;
Screen.WriteXY (1, 1, 31, strRep(' ', 79));
Screen.WriteXY (2, 1, 31, 'Chat mode engaged');
Screen.WriteXY ( 1, 1, 31, strRep(' ', 79));
Screen.WriteXY ( 2, 1, 31, 'Chat mode engaged');
Screen.WriteXY (71, 1, 31, 'ESC/Quit');
Screen.CursorXY (1, 3);
@ -355,6 +444,7 @@ Begin
Erase(fIn);
Screen.TextAttr := 7;
Screen.ClearScreen;
End;
@ -378,43 +468,42 @@ Var
Screen.WriteXY ( 1, 25, Config.StatusColor1, strRep(' ', 79));
Screen.WriteXY ( 2, 25, Config.StatusColor1, 'User');
Screen.WriteXY ( 7, 25, Config.StatusColor2, Chat.Name);
Screen.WriteXY (56, 25, Config.StatusColor3, 'ALT: C)hat K)ick e(X)it');
Screen.WriteXY (54, 25, Config.StatusColor3, 'ALT (C)hat (K)ick e(X)it');
Screen.SetWindow ( 1, 1, 80, 24, True);
Screen.CursorXY (SX, SY);
Screen.TextAttr := SA;
End;
End;
Begin
WriteLn;
WriteLn('Requesting snoop session for node ', Node, '...');
WriteLn;
GetChatRecord(Node, Chat);
If Not Chat.Active Then Begin
ShowMsgBox(0, 'Node ' + strI2S(Node) + ' is not in use');
Exit;
End;
ShowMsgBox (3, 'Requesting snoop session for node ' + strI2S(Node));
SendNodeMessage(Node, 11);
Pipe := TPipeDisk.Create(Config.DataPath, True, Node);
If Not Pipe.ConnectPipe(1500) Then Begin
WriteLn('NodeSpy was not able to establish a snoop session. Sessions');
WriteLn('cannot be created if a user is in a door or a file transfer.');
ShowMsgBox (0, 'Unable to establish a session. Try again');
Pipe.Free;
Exit;
End;
WriteLn('Connection established');
Term := TTermAnsi.Create(Screen);
Keyboard := TInput.Create;
Screen := TOutput.Create(True);
Term := TTermAnsi.Create(Screen);
Screen.SetWindowTitle('Snooping node ' + strI2S(Node));
Screen.SetWindowTitle('[NodeSpy] Snooping ' + strI2S(Node));
DrawStatus;
Update := TimerSet(UpdateTimer);
Update := TimerSet(UpdateNode);
While Pipe.Connected Do Begin
Pipe.ReadFromPipe(Buffer, SizeOf(Buffer), BufRead);
@ -443,7 +532,7 @@ Begin
DrawStatus;
Update := TimerSet(UpdateTimer);
Update := TimerSet(UpdateNode);
End;
End;
@ -457,88 +546,219 @@ Begin
Pipe.Disconnect;
Pipe.Free;
Term.Free;
Screen.Free;
WriteLn;
WriteLn;
WriteLn ('Session closed');
End;
Procedure ShowWhosOnline;
Procedure UpdateOnlineStatus;
Var
Count : Word;
Count : LongInt;
Begin
WriteLn;
WriteLn('### UserName Action');
WriteLn(strRep('=', 79));
For Count := 1 to Config.INetTNNodes Do Begin
If GetChatRecord(Count, Chat) Then Begin
WriteLn (strPadL(strI2S(Count), 3, '0') + ' ' +
strPadR(Chat.Name, 25, ' ') + ' ' +
strPadR(Chat.Action, 45, ' '));
End Else
WriteLn (strPadL(strI2S(Count), 3, '0') + ' ' +
strPadR('Waiting', 25, ' ') + ' ' +
strPadR('Waiting', 45, ' '));
End;
WriteLn (strRep('=', 79));
WriteLn ('Execute NodeSpy [node number] to spy on a node');
For Count := 1 to Config.inetTNNodes Do
If GetChatRecord(Count, Chat) and (Chat.Active) Then Begin
NodeInfo[Count]^.Node := Count;
NodeInfo[Count]^.User := Chat.Name;
NodeInfo[Count]^.Action := Chat.Action;
End Else Begin
NodeInfo[Count]^.Node := Count;
NodeInfo[Count]^.User := 'Waiting';
NodeInfo[Count]^.Action := 'Waiting';
End;
End;
Procedure MainMenu;
Var
NodeNum : Byte;
{$IFDEF UNIX}
Info : Stat;
{$ENDIF}
Begin
{$IFDEF UNIX}
If fpStat('nodespy', Info) = 0 Then Begin
fpSetGID (Info.st_GID);
fpSetUID (Info.st_UID);
StatTotalDays : LongInt = 0;
StatTodayCalls : LongInt = 0;
StatTotalCalls : LongInt = 0;
StatTodayNewUsers : LongInt = 0;
StatTotalNewUsers : LongInt = 0;
StatTodayPosts : LongInt = 0;
StatTotalPosts : LongInt = 0;
StatTodayEmail : LongInt = 0;
StatTotalEmail : LongInt = 0;
StatTodayDownloads : LongInt = 0;
StatTotalDownloads : LongInt = 0;
StatTodayUploads : LongInt = 0;
StatTotalUploads : LongInt = 0;
NodeTimer : LongInt;
TopPage : SmallInt = 1;
CurNode : SmallInt = 1;
Procedure DrawStats;
Begin
Screen.WriteXY (12, 18, 9, strPadL(strI2S(StatTodayCalls), 6, ' '));
Screen.WriteXY (12, 19, 9, strPadL(strI2S(StatTodayNewUsers), 6, ' '));
Screen.WriteXY (12, 20, 9, strPadL(strI2S(StatTodayPosts), 6, ' '));
Screen.WriteXY (12, 21, 9, strPadL(strI2S(StatTodayEmail), 6, ' '));
Screen.WriteXY (12, 22, 9, strPadL(strI2S(StatTodayDownloads), 6, ' '));
Screen.WriteXY (12, 23, 9, strPadL(strI2S(StatTodayUploads), 6, ' '));
Screen.WriteXY (19, 18, 9, strPadL(strComma(StatTotalCalls), 12, ' '));
Screen.WriteXY (19, 19, 9, strPadL(strComma(StatTotalNewUsers), 12, ' '));
Screen.WriteXY (19, 20, 9, strPadL(strComma(StatTotalPosts), 12, ' '));
Screen.WriteXY (19, 21, 9, strPadL(strComma(StatTotalEmail), 12, ' '));
Screen.WriteXY (19, 22, 9, strPadL(strComma(StatTotalDownloads), 12, ' '));
Screen.WriteXY (19, 23, 9, strPadL(strComma(StatTotalUploads), 12, ' '));
End;
{$ENDIF}
Assign (ConfigFile, 'mystic.dat');
Reset (ConfigFile);
Procedure UpdateStats;
Var
HistFile : File of RecHistory;
Hist : RecHistory;
Begin
FileMode := 66;
If IoResult <> 0 Then Begin
BasePath := GetENV('mysticbbs');
Assign (HistFile, Config.DataPath + 'history.dat');
Reset (HistFile);
If BasePath <> '' Then BasePath := DirSlash(BasePath);
If IoResult <> 0 Then Exit;
Assign (ConfigFile, BasePath + 'mystic.dat');
Reset (ConfigFile);
StatTotalDays := 0;
While Not Eof(HistFile) Do Begin
Read (HistFile, Hist);
Inc (StatTotalDays);
Inc (StatTotalCalls, Hist.Calls);
Inc (StatTotalNewUsers, Hist.NewUsers);
Inc (StatTotalDownloads, Hist.Downloads);
Inc (StatTotalPosts, Hist.Posts);
Inc (StatTotalEmail, Hist.Emails);
Inc (StatTotalUploads, Hist.Uploads);
If DateDos2Str(Hist.Date, 1) = DateDos2Str(CurDateDos, 1) Then Begin
Inc (StatTodayCalls, Hist.Calls);
Inc (StatTodayNewUsers, Hist.NewUsers);
Inc (StatTodayDownloads, Hist.Downloads);
Inc (StatTodayPosts, Hist.Posts);
Inc (StatTodayEmail, Hist.Emails);
Inc (StatTodayUploads, Hist.Uploads);
End;
End;
Close (HistFile);
DrawStats;
End;
Procedure DrawNodes;
Var
CN : Byte;
Count : Byte;
Attr : Byte;
Begin
For Count := 1 to 5 Do Begin
CN := Count + TopPage - 1;
If CN > Config.inetTNNodes Then Break;
If CurNode = CN Then Attr := 31 Else Attr := 7;
Screen.WriteXY (1, 10 + Count, Attr,
' ' +
strPadL(strI2S(NodeInfo[CN]^.Node), 3, ' ') + ' ' +
strPadR(NodeInfo[CN]^.User, 25, ' ') + ' ' +
strPadR(NodeInfo[CN]^.Action, 43, ' ') + ' '
);
If IoResult <> 0 Then Begin
WriteLn ('ERROR: Unable to read MYSTIC.DAT');
WriteLn;
WriteLn ('MYSTIC.DAT must exist in the same directory as NodeSpy, or in the');
WriteLn ('path defined by the MYSTICBBS environment variable.');
Halt (1);
End;
End;
Read (ConfigFile, Config);
Close (ConfigFile);
Var
Count : Byte;
Begin
DrawNodeSpyScreen;
UpdateStats;
UpdateOnlineStatus;
If Config.DataChanged <> mysDataChanged Then Begin
WriteLn ('ERROR: NodeSpy has detected a version mismatch');
WriteLn;
WriteLn ('NodeSpy or another BBS utility is an older incompatible version. Make');
WriteLn ('sure you have upgraded properly!');
Halt (1);
End;
DrawNodes;
DirCreate(Config.SystemPath + 'temp' + strI2S(HiddenNode));
NodeTimer := TimerSet(UpdateNode);
If ParamCount < 1 Then
ShowWhosOnline
Else Begin
NodeNum := strS2I(ParamStr(1));
Repeat
If Keyboard.KeyWait(1000) Then
Case Keyboard.ReadKey of
#00 : Case Keyboard.ReadKey of
#71 : Begin
TopPage := 1;
CurNode := 1;
If (NodeNum > 0) and (NodeNum <= Config.INetTNNodes) Then
SnoopNode(NodeNum);
End;
End.
DrawNodes;
End;
#72 : If CurNode > 1 Then Begin
Dec (CurNode);
If CurNode < TopPage Then Dec(TopPage);
DrawNodes;
End;
#73,
#75 : Begin
Dec (TopPage, 5);
Dec (CurNode, 5);
If TopPage < 1 Then TopPage := 1;
If CurNode < 1 Then CurNode := 1;
DrawNodes;
End;
#77,
#81 : Begin
Inc (TopPage, 5);
Inc (CurNode, 5);
If TopPage + 4 > Config.inetTNNodes Then TopPage := Config.inetTNNodes - 4;
If CurNode > Config.inetTNNodes Then CurNode := Config.inetTNNodes;
If TopPage < 1 Then TopPage := 1;
DrawNodes;
End;
#79 : Begin
TopPage := Config.inetTNNodes - 4;
CurNode := Config.inetTNNodes;
If Toppage < 1 Then TopPage := 1;
DrawNodes;
End;
#80 : If CurNode < Config.inetTNNodes Then Begin
Inc (CurNode);
If TopPage + 4 < CurNode Then Inc(TopPage);
DrawNodes;
End;
End;
#13 : Begin
SnoopNode(NodeInfo[CurNode]^.Node);
DrawNodeSpyScreen;
UpdateOnlineStatus;
DrawNodes;
DrawStats;
End;
#27 : Break;
End;
If TimerUp(NodeTimer) Then Begin
UpdateOnlineStatus;
DrawNodes;
NodeTimer := TimerSet(UpdateNode);
For Count := 1 to Config.inetTNNodes Do
If NodeInfo[Count]^.User <> 'Waiting' Then Begin
SnoopNode(NodeInfo[Count]^.Node);
DrawNodeSpyScreen;
UpdateOnlineStatus;
DrawNodes;
DrawStats;
End;
End;
Until False;
End;
Begin
ApplicationInit;
MainMenu;
End.

View File

@ -11,6 +11,13 @@
{$PACKRECORDS 1}
// Add minutes to history
// Change file listing size to Int64
// Extend msg and file base names to 70 chars?
// local qwk download/upload?
// rewrite event system...
// event types, exec commands, weekly/monthly option?
Const
mysSoftwareID = 'Mystic'; // no idea
mysCopyYear = '1997-2012'; // its been a long time!
@ -259,7 +266,8 @@ Type
inetNNTPDupes : Byte;
inetNNTPTimeOut : Word;
// UNSORTED
Reserved : Array[1..846] of Char;
inetTNHidden : Boolean;
Reserved : Array[1..845] of Char;
End;
Const
@ -769,5 +777,8 @@ Type
{ 8 = user 2 user page }
{ 9 = user 2 user forced }
{ 10 = chat accepted }
{ 11 = start pipe session }
{ 12 = end pipe session }
{ 13 = terminte node }
Room : Byte; { Chat room number. 0 = chat broadcast }
End;

View File

@ -19,6 +19,8 @@ BUGS AND POSSIBLE ISSUES
FPC BUG? DirAttr is suspect in MPL is it 1 byte or 4 in size?
! View archive not working if its external view? [Griffin]
! Test MIS blocking features or just rewrite MIS completely.
! Test midnight rollovers for time (flag for user to be immune to timecheck)
! Elasped time will need to be recalculated based on flag above ^^
FUTURE / IDEAS / WORK IN PROGRESS / NOTES
=========================================