📄 idtelnet.pas
字号:
{ $HDR$}
{**********************************************************************}
{ Unit archived using Team Coherence }
{ Team Coherence is Copyright 2002 by Quality Software Components }
{ }
{ For further information / comments, visit our WEB site at }
{ http://www.TeamCoherence.com }
{**********************************************************************}
{}
{ $Log: 11781: IdTelnet.pas
{
{ Rev 1.14 10/07/2004 10:00:28 ANeillans
{ Fixed compile bug
}
{
{ Rev 1.13 7/8/04 4:12:06 PM RLebeau
{ Updated calls to Write() to use the IOHandler
}
{
{ Rev 1.12 7/4/04 1:38:36 PM RLebeau
{ Updated Negotiate() to trigger the OnDataAvailable event only when data is
{ actually available.
}
{
{ Rev 1.11 5/16/04 3:14:06 PM RLebeau
{ Added destructor to terminate the reading thread
}
{
{ Rev 1.10 3/29/04 11:47:00 AM RLebeau
{ Updated to support new ThreadedEvent property
}
{
{ Rev 1.9 2004.03.06 1:31:56 PM czhower
{ To match Disconnect changes to core.
}
{
{ Rev 1.8 2004.02.03 5:44:32 PM czhower
{ Name changes
}
{
{ Rev 1.7 1/21/2004 4:20:48 PM JPMugaas
{ InitComponent
}
{
{ Rev 1.6 2003.11.29 10:20:16 AM czhower
{ Updated for core change to InputBuffer.
}
{
{ Rev 1.5 3/6/2003 5:08:50 PM SGrobety
{ Updated the read buffer methodes to fit the new core (InputBuffer ->
{ InputBufferAsString + call to CheckForDataOnSource)
}
{
{ Rev 1.4 2/24/2003 10:32:46 PM JPMugaas
}
{
{ Rev 1.3 12/8/2002 07:26:10 PM JPMugaas
{ Added published host and port properties.
}
{
{ Rev 1.2 12/7/2002 06:43:30 PM JPMugaas
{ These should now compile except for Socks server. IPVersion has to be a
{ property someplace for that.
}
{
{ Rev 1.1 12/6/2002 05:30:40 PM JPMugaas
{ Now decend from TIdTCPClientCustom instead of TIdTCPClient.
}
{
{ Rev 1.0 11/13/2002 08:02:50 AM JPMugaas
}
unit IdTelnet;
// CHANGES
//
// 26-05-2000 SG: Converted to Indy, no other change
// 13-JAN-2000 MTL: Moved to new Palette Scheme (Winshoes Servers)
//
///////////////////////////////////////////////////////////////////////////////
// Author: Mark Holmes
// ..
// This is the telnet client component. I'm still testing {Do not Localize}
// There is no real terminal emulation other than dumb terminal
//
////////////////////////////////////////////////////////////////////////////////
{
******************************************************************************
Date Author Change.
--------------------------------------------------------------------------------
05-Mar-2000 Mark Added constants for telnet implememtation.
07-Mar-2000 Mark Added a bunch of stuff... it's very much a work in progress
03-01-2002 Andrew P.Rybin Renamings and standardization
}
interface
uses
Classes,
IdAssignedNumbers,
IdGlobal,
IdException,
IdStack,
IdTCPClient, IdThread,
SysUtils;
const
{ These are the telnet command constansts from RFC 854 }
TNC_EOR = #239; // End of Record RFC 885
TNC_SE = #240; // End of subnegotiation parameters.
TNC_NOP = #241; // No operation.
TNC_DATA_MARK = #242; // The data stream portion of a Synch.
// This should always be accompanied
// by a TCP Urgent notification.
TNC_BREAK = #243; // NVT character BRK.
TNC_IP = #244; // The function IP.
TNC_AO = #245; // The function ABORT OUTPUT.
TNC_AYT = #246; // The function ARE YOU THERE.
TNC_EC = #247; // The function ERASE CHARACTER.
TNC_EL = #248; // The function ERASE LINE.
TNC_GA = #249; // The GO AHEAD signal.
TNC_SB = #250; // Indicates that what follows is
// subnegotiation of the indicated
// option.
TNC_WILL = #251; // Indicates the desire to begin
// performing, or confirmation that
// you are now performing, the
// indicated option.
TNC_WONT = #252; // Indicates the refusal to perform,
// or continue performing, the
// indicated option.
TNC_DO = #253; // Indicates the request that the
// other party perform, or
// confirmation that you are expecting
// the other party to perform, the
// indicated option.
TNC_DONT = #254; // Indicates the demand that the
// other party stop performing,
// or confirmation that you are no
// longer expecting the other party
// to perform, the indicated option.
TNC_IAC = #255; // Data Byte 255.
{ Telnet options from RFC 1010 }
TNO_BINARY = #0; // Binary Transmission
TNO_ECHO = #1; // Echo
TNO_RECONNECT = #2; // Reconnection
TNO_SGA = #3; // Suppress Go Ahead
TNO_AMSN = #4; // Approx Message Size Negotiation
TNO_STATUS = #5; // Status
TNO_TIMING_MARK = #6; // Timing Mark
TNO_RCTE = #7; // Remote Controlled Trans and Echo -BELL
TNO_OLW = #8; // Output Line Width
TNO_OPS = #9; // Output Page Size
TNO_OCRD = #10; // Output Carriage-Return Disposition
TNO_OHTS = #11; // Output Horizontal Tab Stops
TNO_OHTD = #12; // Output Horizontal Tab Disposition
TNO_OFD = #13; // Output Formfeed Disposition
TNO_OVT = #14; // Output Vertical Tabstops
TNO_OVTD = #15; // Output Vertical Tab Disposition
TNO_OLD = #16; // Output Linefeed Disposition
TNO_EA = #17; // Extended ASCII
TNO_LOGOUT = #18; // Logout
TNO_BYTE_MACRO = #19; // Byte Macro
TNO_DET = #20; // Data Entry Terminal
TNO_SUPDUP = #21; // SUPDUP
TNO_SUPDUP_OUTPUT = #22; // SUPDUP Output
TNO_SL = #23; // Send Location
TNO_TERMTYPE = #24; // Terminal Type
TNO_EOR = #25; // End of Record
TNO_TACACS_ID = #26; // TACACS User Identification
TNO_OM = #27; // Output Marking
TNO_TLN = #28; // Terminal Location Number
TNO_3270REGIME = #29; // 3270 regime
TNO_X3PAD = #30; // X.3 PAD
TNO_NAWS = #31; // Window size
TNO_TERM_SPEED = #32; // Terminal speed
TNO_RFLOW = #33; // Remote flow control
TNO_LINEMODE = #34; // Linemode option
TNO_XDISPLOC = #35; // X Display Location
TNO_AUTH = #37; // Authenticate
TNO_ENCRYPT = #38; // Encryption option
TNO_EOL = #255; // Extended-Options-List [84,JBP]
// Sub options
TNOS_TERM_IS = #0;
TNOS_TERMTYPE_SEND = #1; // Sub option
TNOS_REPLY = #2;
TNOS_NAME = #3;
type
TIdTelnet = class;
{Various states for telnet }
TIdTelnetState =(tnsDATA, tnsIAC, tnsIAC_SB, tnsIAC_WILL, tnsIAC_DO, tnsIAC_WONT,
tnsIAC_DONT, tnsIAC_SBIAC, tnsIAC_SBDATA, tnsSBDATA_IAC);
{Commands to telnet client from server}
TIdTelnetCommand = (tncNoLocalEcho, tncLocalEcho, tncEcho);
TIdTelnetDataAvailEvent = procedure (Sender: TIdTelnet; const Buffer: String) of object;
TIdTelnetCommandEvent = procedure(Sender: TIdTelnet; Status: TIdTelnetCommand) of object;
{This object is for the thread that listens for the telnet server responses
to key input and initial protocol negotiations }
TIdTelnetReadThread = class(TIdThread)
protected
FClient: TIdTelnet;
//
procedure Run; override;
procedure HandleIncomingData;
public
constructor Create(AClient: TIdTelnet); reintroduce;
property Client: TIdTelnet read FClient;
End; //TIdTelnetReadThread
TIdTelnet = class(TIdTCPClientCustom)
protected
fState: TIdTelnetState;
fReply: Char;
fSentDoDont: String;
fSentWillWont: String;
fReceivedDoDont: String;
fReceivedWillWont: String;
fTerminal : String;
fThreadedEvent: Boolean;
FOnDataAvailable: TIdTelnetDataAvailEvent;
fIamTelnet: Boolean;
FOnDisconnect: TNotifyEvent;
FOnConnect: TNotifyEvent;
FOnTelnetCommand: TIdTelnetCommandEvent;
FTelnetThread: TIdTelnetReadThread;
//
procedure DoOnDataAvailable(const Buf: String);
// what is our current state ?
property State : TIdTelnetState read fState write fState;
// what we send to the telnet server in response to protocol negotiations
property Reply : Char read fReply write fReply;
// did we send a DO DONT command?
property SentDoDont : String read fSentDoDont write fSentDoDont;
// did we send a WILL WONT command?
property SentWillWont: String read fSentWillWont write fSentWillWont;
// did we receive a DO DONT request from the server?
property ReceivedDoDont: String read fReceivedDoDont write fReceivedDoDont;
// did we receive a WILL WONT answer from the server?
property ReceivedWillWont: String read fReceivedWillWont write fReceivedWillWont;
// Are we connected to a telnet server or some other server?
property IamTelnet: Boolean read fIamTelnet write fIamTelnet;
// Protocol negotiation begins here
procedure Negotiate(const Buf: String);
// Handle the termtype request
procedure Handle_SB(CurrentSb: Byte; sbData: String; sbCount: Integer);
// Send the protocol resp to the server based on what's in Reply {Do not Localize}
procedure SendNegotiationResp(var Resp: String);
// Update the telnet status
procedure DoTelnetCommand(Status: TIdTelnetCommand);
procedure InitComponent; override;
public
//
destructor Destroy; override;
procedure Connect; override;
procedure Disconnect(AImmediate: Boolean); override;
procedure SendCh(Ch: Char);
property TelnetThread: TIdTelnetReadThread read FTelnetThread;
published
property Host;
property Port default IdPORT_TELNET;
property OnTelnetCommand: TIdTelnetCommandEvent read FOnTelnetCommand write FOnTelnetCommand;
property OnDataAvailable: TIdTelnetDataAvailEvent read FOnDataAvailable write FOnDataAvailable;
property Terminal: string read fTerminal write fTerminal;
property ThreadedEvent: Boolean read fThreadedEvent write fThreadedEvent default False;
property OnConnect: TNotifyEvent read FOnConnect write FOnConnect;
property OnDisconnect: TNotifyEvent read FOnDisconnect write FOnDisconnect;
end;
EIdTelnetError = class(EIdException);
EIdTelnetClientConnectError = class(EIdTelnetError);
EIdTelnetServerOnDataAvailableIsNil = class(EIdTelnetError);
implementation
uses
IdResourceStringsProtocols;
constructor TIdTelnetReadThread.Create(AClient: TIdTelnet);
begin
inherited Create(False);
FClient := AClient;
FreeOnTerminate:= FALSE; //other way TRUE
end;
procedure TIdTelnetReadThread.Run;
begin
// if we have data run it through the negotiation routine. If we aren't
// connected to a telnet server then the data just passes through the
// negotiate routine unchanged.
// RLebeau 3/29/04 - made Negotiate() get called by Synchronize() to
// ensure that the OnTelnetCommand event handler is synchronized when
// ThreadedEvent is false
FClient.IOHandler.CheckForDataOnSource;
if FClient.ThreadedEvent then begin
HandleIncomingData;
end else begin
Synchronize(HandleIncomingData);
end;
FClient.IOHandler.CheckForDisconnect;
end;
procedure TIdTelnetReadThread.HandleIncomingData;
begin
FClient.Negotiate(FClient.IOHandler.InputBufferAsString);
end;
{ TIdTelnet }
procedure TIdTelnet.SendCh(Ch : Char);
begin
// this code is necessary to allow the client to receive data properly
// from a non-telnet server
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -