Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- unit cMRCClient;
- {$mode ObjFPC}{$H+}
- interface
- uses
- Classes, SysUtils, cTelnetServer, IDContext, IdTCPClient, IDTCPConnection, IDThreadSafe, strutils, programinfo, baseunix, ansi, cyberio, userhandler, dateutils;
- type
- TStringDynArray = array of string;
- {
- type
- ClientLoadThread = class(TThread)
- class var
- // Client : IdTCPClient.TIdTCPClient;
- protected
- class procedure Execute;
- public
- // Constructor Create(CreateSuspended : boolean);
- end;
- }
- type TReadingThread = class(TThread)
- protected
- FConn: TIdTCPConnection;
- FQueue: TIdThreadSafeStringList;
- procedure Execute; override;
- public
- constructor Create(AConn: TIdTCPConnection; AQueue: TIdThreadSafeStringList);
- end;
- {
- ...
- Msgs := TIdThreadSafeStringList.Create;
- Client.Connect;
- Thread := TReadingThread.Create(Client, Msgs);
- }
- //Forward Declared
- procedure DrawScreen();
- function MRCPrompt(): string;
- procedure SendMsg(sMsg: string);
- procedure PrintHelp();
- procedure PrintContent;
- procedure ShiftArray;
- procedure AddContent(sInput: string);
- procedure ClearAll;
- procedure ClearLine(iLine: integer);
- procedure CheckMsgs();
- //Client Functions
- procedure SENDALIVE();
- procedure BroadCastMsg(sMsg: string);
- procedure Quit();
- function LoadMsgs(sMsg: string): integer;
- function ParseMessage(sMessage: string): TStringDynArray;
- procedure SendIAMHERE();
- procedure SetPrompt;
- function Sanitize(sStringGiven: string): string;
- //System Commands
- procedure JoinMRC();
- procedure cmd_SHOWMRCDIR();
- //Commands
- procedure cmd_BBSES();
- procedure cmd_ROOM();
- procedure cmd_USERS();
- procedure cmd_ROOMLIST();
- procedure StartMRC();
- implementation
- uses
- MainMenu;
- threadvar
- cMultiPlexerClient: IdTCPClient.TIdTCPClient;
- //LoadThread: ClientLoadThread;
- ContentArray: array [0..20] of string;
- sReturnString: string;
- sRoom: string;
- boolNewMessages: boolean;
- IAMHERECnt: integer;
- Msgs : TIdThreadSafeStringList;
- Thread : TReadingThread;
- {
- class procedure ClientLoadThread.Execute;
- begin
- CheckMsgs(self.Client);
- end;
- }
- constructor TReadingThread.Create(AConn: TIdTCPConnection; AQueue: TIdThreadSafeStringList);
- begin
- inherited Create(False);
- FConn := AConn;
- FQueue := AQueue;
- end;
- procedure TReadingThread.Execute;
- begin
- while not Terminated do
- begin
- FQueue.Add(FConn.IOHandler.ReadLn);
- end;
- end;
- //Start MRC
- procedure StartMRC;
- begin
- Msgs := TIdThreadSafeStringList.Create;
- Thread := TReadingThread.Create(cMultiPlexerClient, Msgs);
- //Start Client
- cMultiPlexerClient := IdTCPClient.TIdTCPClient.Create;
- cMultiPlexerClient.Host := programinfo.cbbsServicesIni.Mrc_Server_Hostname;
- cMultiPlexerClient.Port := programinfo.cbbsServicesIni.Mrc_Port.ToInteger;
- cMultiPlexerClient.Connect();
- // cMultiPlexerClient.IOHandler.RecvBufferSize := 1; //Set Recv Buffer To 1 (Turn off buffering of input of client)
- cMultiPlexerClient.IOHandler.ReadTimeout:=0;
- sleep(250);
- //Start Thread With Client
- Thread := TReadingThread.Create(cMultiPlexerClient, Msgs);
- //Set Variables
- ansi.PipeClrScr;
- JoinMRC();
- SendAlive();
- DrawScreen();
- MRCPrompt();
- end;
- //Draw Blank Screen
- procedure DrawScreen();
- begin
- gotoxy(1, 1);
- ansi.DrawDoubleLine(BrightCyan, 80);
- gotoxy(1, 7);
- cyberio.PipeWriteString('|14[ |15CyberBBS V.' + programinfo.sProgVersion + ' MRC Client |14]');
- gotoxy(23, 1);
- ansi.DrawDoubleLine(BrightCyan, 80);
- gotoxy(23, 65);
- cyberio.PipeWriteString('|14[ |15[/?] Help |14]');
- end;
- //Input MRC Prompt
- function MRCPrompt(): string;
- var
- ByteInput: byte;
- chInput: char;
- sSendMsg: string;
- boolReturn: boolean;
- sRecvData: string;
- begin
- boolReturn := False;
- gotoxy(24, 1);
- cyberio.PipeWriteString('|14[-> |15');
- gotoxy(24, 5);
- cyberio.SetPromptTimeout(0);
- repeat
- ByteInput := 0;
- chInput := ' ';
- cyberio.PipeWriteString('|15'); //Set Gray Color
- //Code To Get String (Char by Char - Byte);
- // if (cContext.Connection.IOHandler.CheckForDataOnSource(1)) then
- //PrintContent;
- //SetPrompt;
- chInput := cContext.Connection.IOHandler.ReadChar();
- // PrintContent();
- while (cContext.Connection.IOHandler.CheckForDataOnSource(10)) do
- begin
- chInput := cContext.Connection.IOHandler.ReadChar();
- end;
- if (chInput <> chr(0)) then
- begin
- case (chInput) of
- chr(byte(255)):
- begin
- write('255 sent');
- if (cyberio.PipeReadByte() = 241) then
- begin
- chInput := chr(0);
- cyberio.PipeReadByte();
- cyberio.PipeReadByte();
- cyberio.PipeReadByte();
- cyberio.PipeReadByte();
- cyberio.PipeReadByte();
- cyberio.PipeReadByte();
- cyberio.PipeReadByte();
- cyberio.PipeReadByte();
- cyberio.PipeReadByte();
- end;
- end;
- //cyberio.PipeReadByte(); // Read and flush IAC + After Bytes //IAC
- //chr(241): begin chInput :=chr(0); cyberio.PipeReadByte(); cyberio.PipeReadByte(); chInput := chr(0); end;//NOP (NetRuner 19+ Beta Polls these
- #32.. #125:
- begin
- if (length(sReturnString) < 76) then
- begin
- //Add To String
- // sReturnString := sReturnString + chr(Ord(ByteInput));
- sReturnString := sReturnString + chInput;
- //Print Character
- // cyberio.PipeWriteChar(chr(Ord(ByteInput)));
- cyberio.PipeWriteChar(chInput);
- //Set Byte To Nothing
- // ByteInput := 0;
- chInput := chr(0);
- end;
- end;
- #8, #127:
- begin
- if (length(sReturnString) > 0) then
- begin
- //Delete One Char From String
- Delete(sReturnString, length(sReturnString), 1);
- cyberio.AnsiMoveLeft1;
- cyberio.PipeWriteString(' ');
- cyberio.AnsiMoveLeft1;
- byteinput := 0;
- chInput := chr(0);
- end;
- end;
- //handle ESC
- #27:
- begin
- cyberio.PipeFlushBuffer4B;
- sleep(250);
- cyberio.PipeFlushBuffer4B;
- sleep(250);
- cyberio.PipeFlushBuffer4B;
- sleep(250);
- cyberio.PipeFlushBuffer4B;
- ByteInput := 0;
- chInput := chr(0);
- end;
- //Handle Other
- #1.. #7, #9, #11, #12, #14.. #26, #28.. #31:
- begin
- cyberio.PipeFlushBuffer4B;
- sleep(250);
- cyberio.PipeFlushBuffer4B;
- sleep(250);
- cyberio.PipeFlushBuffer4B;
- sleep(250);
- cyberio.PipeFlushBuffer4B;
- ByteInput := 0;
- chInput := chr(0);
- end;
- #0:
- begin
- chInput := ' ';
- end;
- #10, #13:
- begin
- case (sReturnString) of
- //System Commands
- '/?', '/help': PrintHelp();
- '/quit', '/q': Quit();
- '/cls', '/clear', '/c': ClearAll();
- '/showmrcdir': cmd_SHOWMRCDIR();
- //Custom Commands
- '/bbses', '/connected': cmd_BBSES();
- '/room': cmd_ROOM();
- '/users', '/u': cmd_USERS();
- '/rooms', '/r/': cmd_ROOMLIST();
- //Fun Commands
- else
- begin
- if (length(sReturnString) > 0) then
- begin
- //Setup Message
- BroadCastMsg(sReturnString);
- end;
- sReturnString := '';
- // cContext.Connection.IOHandler.WriteBufferClear;
- DrawScreen;
- SetPrompt();
- chInput := chr(0);
- end;
- end;
- //Clear Return String
- sReturnString := '';
- end
- //Else On Input Loop
- else
- begin
- end;
- end;
- end;
- ansi.CursorSavePos;
- CheckMsgs();
- ansi.CursorLastPos;
- //sRecvData := '';
- {
- if (cMultiPlexerClient.IOHandler.CheckForDataOnSource(15)) then
- begin
- sRecvData := cMultiPlexerClient.IOHandler.ReadLn();
- self.LoadMsgs(sRecvData);
- self.PrintContent;
- end;
- }
- until (boolReturn = True);
- end;
- //Send Message Routine
- //This routine will take the text and write it to a file, to be sent by the multiplexer
- procedure SendMsg(sMsg: string);
- begin
- cMultiPlexerClient.IOHandler.WriteLn(sMsg);
- end;
- {
- class procedure MRCClient.SendMsg(sMsg: string);
- var
- sOutPath: string;
- sFormattedMsg: string;
- F: textfile;
- sFilename: string;
- begin
- //Set Out Path To Write File
- sOutPath := programinfo.cbbsMRC.sMRCOutboundDir;
- if (DirectoryExists(sOutPath)) then
- begin
- //Set FileName:
- sFilename := 'outmess-' + random(9999999).ToString + '.mrc';
- AssignFile(F, sOutPath + sFilename);
- //Open For Writing
- rewrite(F);
- //Write To File
- writeln(F, sMsg);
- //Close File
- CloseFile(F);
- end;
- end;
- }
- //Print Help
- procedure PrintHelp();
- begin
- AddContent('|11======= |15CyberBBS MRC Client Help |11=======');
- AddContent('');
- AddContent('|11[|14/?|11]|15...... Help With Functions');
- AddContent('|11[|14/cls|11]|15.... Clear Screen');
- AddContent('|11[|14/showmrcdir|11]|15.. Show MRC In Dir');
- AddContent('|11[|14/bbses|11]|15.. List Connected BBS Systems');
- AddContent('|11[|14/users|11]|15.. List Connected Users');
- AddContent('|11[|14/rooms|11]|15.. List Current Rooms On Server');
- AddContent('|11[|14/room|11]|15... List Current Room (Locally)');
- AddContent('|11[|14/quit|11]|15... Quit MRC Chat');
- AddContent('');
- PrintContent;
- //Return Prompt
- SetPrompt;
- end;
- //Print Content
- procedure PrintContent;
- var
- iLineCnt: integer;
- iAryCnt: integer;
- iWhereX: integer;
- iWhereY: integer;
- begin
- //Save Current Location
- //iWhereX := cyberio.GetX;
- //iWhereY := cyberio.GetY;
- ansi.CursorSavePos;
- //Go To First Line To Print (Line 22)
- gotoxy(22, 1);
- iLineCnt := 22;
- iAryCnt := 20;
- //Run Loop To Print All Lines
- repeat
- ClearLine(iLineCnt);
- cyberio.PipeWriteString('|07' + ContentArray[iAryCnt]);
- iLineCnt := iLineCnt - 1;
- iAryCnt := iAryCnt - 1;
- gotoxy(iLineCnt, 1);
- until (iLineCnt = 1);
- //Return To Start Position
- // gotoxy(iWhereY, iWhereX);
- ansi.CursorLastPos;
- end;
- //Shift Array Up And Add One Line To Last Area
- procedure ShiftArray;
- var
- iCnt: integer;
- begin
- iCnt := 0;
- repeat
- ContentArray[iCnt] := ContentArray[iCnt + 1];
- iCnt := iCnt + 1;
- until (iCnt = 20);
- ContentArray[20] := ' ';
- end;
- //Add Content To Array
- procedure AddContent(sInput: string);
- begin
- //Adjust Array
- ShiftArray;
- ContentArray[20] := sInput;
- end;
- //Clear Line
- procedure ClearLine(iLine: integer);
- var
- iCnt: integer;
- begin
- iCnt := 1;
- gotoxy(iLine, 1);
- repeat
- cyberio.PipeWriteString(' ');
- Inc(iCnt);
- until (iCnt = 80);
- gotoxy(iLine, 1);
- end;
- //Clear Screen & Array
- procedure ClearAll;
- var
- iCnt: integer;
- begin
- iCnt := 0;
- repeat
- ContentArray[iCnt] := ' ';
- Inc(iCnt);
- until (iCnt = 20);
- ansi.PipeClrScr;
- DrawScreen;
- // SetPrompt;
- end;
- //Return, Clear Line, and Set Prompt
- procedure SetPrompt;
- begin
- ClearLine(24);
- gotoxy(24, 1);
- cyberio.PipeWriteString('|14[-> |15');
- gotoxy(24, 5);
- end;
- //Send Message on MRC Chat (Direct - no file);
- procedure BroadCastMsg(sMsg: string);
- var
- sFormattedMsg: string;
- begin
- //Add handle to msg
- sMsg := '|11<|14' + Sanitize(recCurrentUser.Handle) + '|11> |10' + sMsg;
- //Format Msg
- sFormattedMsg := Sanitize(recCurrentUser.Handle) + '~' + Sanitize(programinfo.cbbsMRC.sBBSName) + '~' + Sanitize(sRoom) + '~~~~' + sMsg + '~';
- if (sFormattedMsg <> '') then
- begin
- SendMsg(sFormattedMsg); //Send Message Through Routine
- //cMRCMultiplexer.mrcMultiPlexer.SendMsg(sFormattedMsg); //Send Message with CRLF
- end;
- end;
- procedure JoinMRC();
- var
- sFormattedMsg: string;
- sReturnMSg: string;
- sHandShake: string;
- begin
- //Setup MSg
- sFormattedMsg := sanitize(userhandler.recCurrentUser.Handle) + '~' + sanitize(programinfo.cbbsMRC.sBBSName) + '~' + 'lobby' + '~NOTME~~~~';
- //Send LogOff MSg
- //cMRCMultiplexer.mrcMultiPlexer.SendMsg(sFormattedMsg); //Send Message with CRLF
- sHandShake := Sanitize(programinfo.cbbsMRC.sBBSName) + '~' + 'CyberBBS/Linux64/1.2.9';
- SendMsg(sHandShake);
- sleep(100);
- SendMsg(sFormattedMsg);
- sReturnMSg := cMultiPlexerClient.IOHandler.ReadLn();
- sleep(500);
- sRoom := 'lobby';
- AddContent('|10-Welcome to MRC Chat on CyberBBS!-');
- AddContent('Server Sent: ' + sReturnMSg);
- PrintContent;
- end;
- //Quit
- procedure Quit();
- var
- sFormattedMsg: string;
- begin
- //Setup MSg
- sFormattedMsg := userhandler.recCurrentUser.Handle + '~~~SERVER~~~LOGOFF~';
- //Send LogOff MSg
- //cMRCMultiplexer.mrcMultiPlexer.SendMsg(sFormattedMsg); //Send Message with CRLF
- SendMsg(sFormattedMsg);
- sleep(250);
- cMultiPlexerClient.Disconnect;
- sleep(250);
- MainMenu.MainMenu();
- exit;
- end;
- //Load Messages
- function LoadMsgs(sMsg: string): integer;
- var
- sFileDir: string;
- iCnt: integer;
- MsgList: TStringList;
- iMsgCnt: integer;
- F: TextFile;
- sData: string;
- MsgArray: TStringDynArray;
- begin
- iCnt := 0;
- {
- sFileDir := csessions.cbbsSession.sMRC_In;
- MsgList := TStringList.Create();
- MsgList := fileutil.FindAllFiles(sFileDir, '*.mrc', False);
- iMsgCnt := MsgList.Count;
- if (MsgList.Count > 0) then
- begin
- repeat
- AssignFile(F, MsgList[iCnt]);
- reset(F);
- readln(F, sData);
- CloseFile(F);
- }
- MsgArray := ParseMessage(sMsg);
- //Check Msg For Auto-Response Messages
- if (MsgArray[6] = 'ping') then
- begin
- SendAlive(); //Send I Am Alive Message
- MsgArray[6] := '';
- end;
- //Add Info If MsgArray Not Empty
- if (MsgArray[6] <> '') then
- begin
- Write('6: ' + MsgArray[6]);
- //Add Info From Array
- AddContent(MsgArray[6]);
- end;
- //Send IAMHERE
- if (IAMHERECnt = 50) then
- begin
- SendIAMHERE();
- IAMHERECnt := 0;
- end
- else
- begin
- Inc(IAMHERECnt);
- end;
- end;
- //Parse Message Received
- function ParseMessage(sMessage: string): TStringDynArray;
- var
- ReturnString: TStringDynArray;
- begin
- ReturnString := strutils.SplitString(sMessage, '~');
- exit(ReturnString);
- end;
- //Send IAMHere
- procedure SendIAMHERE();
- var
- sStringSend: string;
- begin
- sStringSend := userhandler.recCurrentUser.Handle + '~~~SERVER~~~IAMHERE~';
- // cMRCMultiplexer.mrcMultiPlexer.SendMsg(sStringSend); //Send Message with CRLF
- SendMsg(sStringSend);
- end;
- //Send I AM Alive Response (Respond To Ping)
- procedure SENDALIVE();
- var
- sStringSend: string;
- begin
- sStringSend := 'CLIENT~' + sanitize(programinfo.cbbsMRC.sBBSName) + '~~SERVER~ALL~~IMALIVE:' + sanitize(programinfo.cbbsMRC.sBBSName) + '~';
- SendMsg(sStringSend);
- end;
- //Replace Spaces with _
- function Sanitize(sStringGiven: string): string;
- var
- sReturnStringSani: string;
- begin
- sReturnStringSani := strutils.StringReplace(sStringGiven, ' ', '_', [rfReplaceAll, rfIgnoreCase]);
- exit(sReturnStringSani);
- end;
- //Get List Of Connected BBS Systems
- procedure cmd_BBSES();
- var
- sString: string;
- begin
- sString := '~~~SERVER~~~CONNECTED~';
- // cMRCMultiplexer.mrcMultiPlexer.SendMsg(sString); //Send Message with CRLF
- SendMsg(sString);
- //Print
- PrintContent();
- //Return Prompt
- SetPrompt;
- end;
- //Show Room (Local)
- procedure cmd_ROOM();
- begin
- AddContent('|15Current Room: |11' + sRoom);
- PrintContent;
- //Return Prompt
- SetPrompt;
- end;
- //Request Users List & Print
- procedure cmd_USERS();
- var
- sString: string;
- begin
- sString := '~~~SERVER~~~WHOON~';
- // cMRCMultiplexer.mrcMultiPlexer.SendMsg(sString); //Send Message with CRLF
- SendMsg(sString);
- //Return Prompt
- SetPrompt;
- end;
- //Get A List of Rooms
- procedure cmd_ROOMLIST();
- var
- sString: string;
- begin
- sString := '~~~SERVER~~~LIST~';
- //cMRCMultiplexer.mrcMultiPlexer.SendMsg(sString); //Send Message with CRLF
- SendMsg(sString);
- //Return Prompt
- SetPrompt;
- end;
- //Show Current MRC Directory Being Used
- procedure cmd_SHOWMRCDIR();
- var
- sMRCDir: string;
- begin
- //sMRCDir := csessions.cbbsSession.sMRC_In;
- // self.AddContent('|15Current MRC Dir: |11' + sMRCDir);
- // self.AddContent('');
- // self.PrintContent;
- // self.SetPrompt;
- end;
- function CheckDataFromClient(sMsgGiven: string): string;
- begin
- case sMsgGiven[1] of
- #32.. #126:
- begin
- exit(sMsgGiven);
- end;
- else
- exit(chr(0));
- end;
- end;
- {
- procedure CheckMsgs();
- var
- sMsg: string;
- sMsgChecked: string;
- boolRun: boolean;
- begin
- boolRun := True;
- sMsg := chr(0);
- Write('Start MSG');
- repeat
- sMsg := chr(0);
- if (cMultiPlexerClient.IOHandler.CheckForDataOnSource(10)) then
- begin
- sMsg := cMultiPlexerClient.IOHandler.ReadLn();
- sMsgChecked := CheckDataFromClient(sMsg);
- if (sMsgChecked <> chr(0)) then
- begin
- SendIAMHERE();
- LoadMsgs(sMsg);
- PrintContent;
- end;
- end
- else
- sMsg := chr(0);
- Write('MSg: ' + sMsg);
- until (sMsg = chr(0));
- end;
- }
- procedure CheckMsgs();
- var
- sMsg: string;
- List : TStringList;
- iCnt : integer;
- begin
- {
- sMsg := '';
- Write('Start MSG');
- repeat
- if cMultiPlexerClient.IOHandler.InputBufferIsEmpty then
- begin
- cMultiPlexerClient.IOHandler.CheckForDataOnSource(250);
- cMultiPlexerClient.IOHandler.CheckForDisconnect;
- if cMultiPlexerClient.IOHandler.InputBufferIsEmpty then Break;
- end;
- // sMsg := cMultiPlexerClient.IOHandler.ReadLn();
- Write('MSg: ' + sMsg);
- LoadMsgs(sMsg);
- PrintContent();
- sMsg := '';
- until False;
- }
- iCnt := 0;
- //list := TStringList.Create;
- list := Msgs.lock;
- try
- repeat
- write(list.Strings[iCnt]);
- LoadMsgs(list.Strings[iCnt]);
- PrintContent;
- iCnt := iCnt + 1;
- until (iCnt = List.Count);
- list.clear;
- finally
- Msgs.unlock;
- end;
- end;
- end.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement