Please don't laugh too much at this because I never worked with the network library before and certainly not with telnet in it's raw form. Take this is an example for building your own library. I didn't take the time to clean this up since it works fine for me in my application (of which it is a pretty small but important part). I use it for scripting entry of information into our old CRM system. I've tested it with two different types of "scripts" and it works fine.
The code here is stripped down but hopefully gives some idea of how to do it.
TelnetConnect() is the main procedure that connects to a server and handles initial negotiation. You can make your own mini "scripts" in a similar way to the Telnet_DoSomething(). In my program I have a queue system that will handle different types of scripts in a thread without bothering the user. It outputs what it's doing to a separate window that the user can minimize while working on other parts of the program.
TelnetWaitUntilHas() is the procedure that actually does most of the work. It's ugly, big and can certainly be better but I don't have the time to fix it up at the moment. The Send parameter contains the keys or text you want to send. The Contains parameter is what you're expecting AFTER[\b] Send is sent to the server. AsRaw tells the procedure you're sending raw character codes. For example, to send F4 to the server I connect to, I need to send "chr(27)+[P" which are the characters "27, 91 and 80" so I would do...
Code: Select all
TelnetWaitUntilHas(connectionid, "27,91,80", "Main Menu", #True)
So, yeah. This all could be used as a basis for a much, much better library. Or, later (much later ), I could work something up as a small library.
Hope it helps!
Code: Select all
;-
EnableExplicit
;-
InitNetwork()
;-
Structure s_Telnet_Result
;
Text.s
;
EndStructure
;-
Procedure.s TelnetCleanText(Value.s)
;
Protected CaughtEscape.l
;
Protected *HoldChar.Character
;
Protected HoldString.s = Space(Len(Value))
;
Protected *HoldOut.Character = @HoldString
;
Protected IndexBegin.l, IndexEnd.l
;
*HoldChar = @Value
;
While *HoldChar\c
;
If *HoldChar\c = 27
;
CaughtEscape = #True
;
ElseIf CaughtEscape And (*HoldChar\c = 'm' Or *HoldChar\c = 'H')
;
CaughtEscape = #False
;
Else
;
If CaughtEscape = #False
;
*HoldOut\c = *HoldChar\c
;
*HoldOut + SizeOf(Character)
;
EndIf
;
EndIf
;
*HoldChar + SizeOf(Character)
;
Wend
;
ProcedureReturn Left(HoldString, *HoldOut - @HoldString)
;
EndProcedure
Procedure TelnetSendRaw(iConnection.l, Codes.s)
;
Protected iMax.l
Protected iLoop.l
;
Protected *Memory.l
Protected *Position.Byte
;
iMax = CountString(Codes, ",") + 1
*Memory = AllocateMemory(iMax)
*Position = *Memory
For iLoop = 1 To iMax
*Position\b = Val(StringField(Codes, iLoop, ","))
*Position + 1
Next iLoop
SendNetworkData(iConnection, *Memory, iMax)
FreeMemory(*Memory)
;
EndProcedure
Procedure.l TelnetWaitUntilHas(iConnection.l, Send.s, Contains.s, AsRaw.l = #False, Wait.l = 10000, *Result.s_Telnet_Result = #Null)
;
Protected iMax.l
Protected iLoop.l
;
Protected HoldTime.q
Protected HoldString.s
Protected CaughtMatch.l
Protected *HoldChar.Character
;
Protected Result.l
;
Protected *Memory.l
Protected *Position.Byte
;
Protected q.l, r.l
;
Protected HoldStart.l
;
Protected IsError.l
;
Protected HoldLength.l
;
If AsRaw
;
iMax = CountString(Send, ",") + 1
*Memory = AllocateMemory(iMax)
*Position = *Memory
For iLoop = 1 To iMax
*Position\b = Val(StringField(Send, iLoop, ","))
*Position + 1
Next iLoop
Debug "Sending: "+Send
SendNetworkData(iConnection, *Memory, iMax)
Debug "Done Sending..."
FreeMemory(*Memory) : *Memory = 0
;
If Contains = "" : CaughtMatch = #True : EndIf
;
Else
;
For iLoop = 1 To 255
Send = ReplaceString(Send, "chr("+Str(iLoop)+")", Chr(iLoop))
Next iLoop
;
Debug "Sending: "+Send
If Send <> "" : SendNetworkString(iConnection, Send) : EndIf
Debug "Done Sending..."
;
EndIf
;
HoldTime = ElapsedMilliseconds()
;
Repeat
;
If NetworkClientEvent(iConnection) = #PB_NetworkEvent_Data
;
If *Memory : FreeMemory(*Memory) : *Memory = 0 : EndIf
*Memory = AllocateMemory(1000)
HoldLength = ReceiveNetworkData(iConnection, *Memory, 1000)
;
Debug TelnetCleanText(PeekS(*Memory, HoldLength))
;
If HoldLength
;
*HoldChar = *Memory
While *HoldChar - *Memory < HoldLength
If *HoldChar\c = 0 : *HoldChar\c = 1 : EndIf
*HoldChar + SizeOf(Character)
Wend
;
HoldString = HoldString + TelnetCleanText(ReplaceString(PeekS(*Memory, HoldLength), Chr(1), ""))
;
If Contains <> ""
;
iMax = CountString(Contains, Chr(29)) + 1
For iLoop = 1 To iMax
If FindString(HoldString, StringField(Contains, iLoop, Chr(29)), 1)
CaughtMatch = #True
If iLoop > 1 : IsError = #True : EndIf
EndIf
Next iLoop
;
Else
;CaughtMatch = #True
EndIf
;
EndIf
;
If *Memory : FreeMemory(*Memory) : *Memory = 0 : EndIf
;
EndIf
;
Until CaughtMatch Or ElapsedMilliseconds() - HoldTime > Wait
;
Debug " Took: "+Str(ElapsedMilliseconds() - HoldTime)
;
If *Result : *Result\Text = HoldString : EndIf
;
If Contains = "" : CaughtMatch = #True : EndIf
;
If IsError : CaughtMatch = #False : EndIf
;
ProcedureReturn CaughtMatch
;
EndProcedure
Procedure Telnet_DoSomething(iConnection.l)
;
If TelnetWaitUntilHas(iConnection, "D", "A. Inventory Information")
;
;
EndIf
;
EndProcedure
Procedure TelnetConnect()
;
Protected *HoldOut.l
Protected *Out.Byte
;
Protected *HoldMemory.l
;
Protected iLoop.l
;
Protected CaughtMatch.l
;
Protected GotPrompt.l, GotPassword.l
;
Protected HasDBChoiceMenu.l, HasMainMenu.l
;
Protected *HoldChar.Character
;
Protected StartTime.q
;
Protected HoldString.s
;
Protected HoldValue.l
;
Protected HoldThread
;
Protected Result.l
;
Protected IsCheckingTerminalType.l
;
Protected iConnection.l
;
Protected *Memory.l
Protected HoldLength.l
;
Protected HoldFlash.FLASHWINFO
;
Protected HoldResult.s_Telnet_Result
;
Protected lResult.l
;
iConnection = OpenNetworkConnection("server_name", 23)
;
If iConnection
;
;{ Negotiate
Repeat
;
Result = 0
;
If *Memory : FreeMemory(*Memory) : *Memory = 0 : EndIf
;
*Memory = AllocateMemory(1000)
;
HoldLength = ReceiveNetworkData(iConnection, *Memory, 1000)
;
If HoldLength = 0 : Break : EndIf
;
*HoldMemory = *Memory
;
; Debug Str(gLength)+" characters."
; For iLoop = 0 To gLength - 1
; Debug Str(PeekB(*HoldMemory + iLoop) & $FF)
; Next iLoop
;
While *HoldMemory - *Memory < HoldLength
;
If PeekB(*HoldMemory) & $FF = 255
; IAC code.
HoldValue = PeekB(*HoldMemory + 1) & $FF
;
If HoldValue = 250
;{ SB
If PeekB(*HoldMemory + 2) & $FF = 24 And PeekB(*HoldMemory + 3) & $FF = 1 And PeekB(*HoldMemory + 4) & $FF = 255 And PeekB(*HoldMemory + 5) & $FF = 240
; IAC SB TERMINAL-TYPE SEND IAC SE
; TelnetSendRawData("255,250,24,0,65,78,83,73,255,240")
TelnetSendRaw(iConnection, "255,250,24,0,86,84,49,48,48,255,240")
; Send ANSI terminal type.
*HoldMemory + 6
;
EndIf
;}
ElseIf HoldValue = 251
;{ Will
If PeekB(*HoldMemory + 2) & $FF = 1
; Echo
TelnetSendRaw(iConnection, "255,254,1")
; Send DONT echo.
*HoldMemory + 3
;
ElseIf PeekB(*HoldMemory + 2) & $FF = 3
; Echo
TelnetSendRaw(iConnection, "255,253,3")
; Send DON suppress go ahead.
*HoldMemory + 3
;
Else
;
TelnetSendRaw(iConnection, "255,254,"+Str(PeekB(*HoldMemory+2) & $FF))
; Send DONT to the message.
*HoldMemory + 3
;
EndIf
;}
ElseIf HoldValue = 252
;{ Won't
If PeekB(*HoldMemory + 2) & $FF = 37
; Athenticate
TelnetSendRaw(iConnection, "255,254,37")
; Send DONT authenticate.
*HoldMemory + 3
;
Else
;
TelnetSendRaw(iConnection, "255,254,"+Str(PeekB(*HoldMemory+2) & $FF))
; Send DONT to the message.
*HoldMemory + 3
;
EndIf
;}
ElseIf HoldValue = 253
;{ Do
If PeekB(*HoldMemory + 2) & $FF = 24
; Terminal Type
If IsCheckingTerminalType = #False : TelnetSendRaw(iConnection, "255,251,24") : EndIf
; If IsCheckingTerminalType = #False : TelnetSendRaw(iconnection, "255,252,24") : EndIf
; Agree to send terminal type. Don't send this out again if already sent.
*HoldMemory + 3
;
IsCheckingTerminalType = #True
;
ElseIf PeekB(*HoldMemory + 2) & $FF = 1
; Allow echo
TelnetSendRaw(iConnection, "255,252,1")
; Tell the server we WONT echo.
*HoldMemory + 3
;
ElseIf PeekB(*HoldMemory + 2) & $FF = 3
; SUPPRESS-GO-AHEAD, Suppress Go Ahead.
TelnetSendRaw(iConnection, "255,251,3")
; Tell the server we WILL suppress go-ahead messages
*HoldMemory + 3
;
ElseIf PeekB(*HoldMemory + 2) & $FF = 31
; Negotiate about window size
TelnetSendRaw(iConnection, "255,252,31")
; Tell the server we WONT negotiate about window size.
*HoldMemory + 3
;
Else
;
TelnetSendRaw(iConnection, "255,252,"+Str(PeekB(*HoldMemory+2) & $FF))
; Send WONT to the message.
*HoldMemory + 3
;
EndIf
;}
ElseIf HoldValue = 254
;{ Don't
If PeekB(*HoldMemory + 2) & $FF = 37
; Athenticate
TelnetSendRaw(iConnection, "255,252,37")
; Send WONT authenticate.
*HoldMemory + 3
;
Else
;
TelnetSendRaw(iConnection, "255,252,"+Str(PeekB(*HoldMemory+2) & $FF))
; Send WONT to the message.
*HoldMemory + 3
EndIf
;}
EndIf
;
Else
;
If PeekB(*HoldMemory) & $FF <= 0 : Break 2 : EndIf
;
*HoldMemory + 1
;
EndIf
;
Wend
;
ForEver
;
If *HoldOut : FreeMemory(*HoldOut) : *HoldOut = 0 : EndIf
;
If *Memory : FreeMemory(*Memory) : *Memory = 0 : EndIf
;}
;
If TelnetWaitUntilHas(iConnection, "", "login:")
;
If TelnetWaitUntilHas(iConnection, "username_here" + Chr(13) + Chr(10), "Password:")
;
lResult = TelnetWaitUntilHas(iConnection, "password_here" + Chr(13) + Chr(10), "Secur Menu"+Chr(29)+"You entered an invalid login name Or Password.", #False, 10000, @HoldResult)
;
If lResult = 0
; Bad username or password.
Debug "Bad username or password."
;
Else
; Password is valid.
If TelnetWaitUntilHas(iConnection, Chr(13)+Chr(10), "A. Overview")
;
Telnet_DoSomething(iConnection)
;- Do work here. The user is at the main menu.
;
If TelnetWaitUntilHas(iConnection, "27,91,80", "Do you want to Exit?", #True)
;
Debug "Gracefully exited."
;
EndIf
;
EndIf
;
EndIf
;
EndIf
; Session.Send chr(27) + "~[P"
; and then "Y" + enter
; and then Session.Send chr(27) + "~[P"
EndIf
;
CloseNetworkConnection(iConnection) : iConnection = 0
;
EndIf
;
EndProcedure
;-
TelnetConnect()
;-
End
;-