It is currently Sat May 25, 2013 4:15 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Simple Telnet Connection / Scripting
PostPosted: Tue Aug 19, 2008 8:47 pm 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 905
Location: Tacoma, WA
From my post here: http://www.purebasic.fr/english/viewtopic.php?t=31106

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 [b]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:
TelnetWaitUntilHas(connectionid, "27,91,80", "Main Menu", #True)


The code sends the F4 keystrokes as raw data and expects to be returned to the main menu. It will watch the text sent to the client until it gets those characters.

So, yeah. This all could be used as a basis for a much, much better library. Or, later (much later :cry: ), I could work something up as a small library.

Hope it helps!

Code:
;-
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
;-


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 20, 2008 10:44 am 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 2513
Location: Lyon - France
Thanks for sharing, but i have an error, line 222 : "Structure no found'.
Is it normal ?

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 20, 2008 11:11 am 
Offline
Addict
Addict
User avatar

Joined: Thu Jul 01, 2004 2:51 am
Posts: 905
Location: Tacoma, WA
Sorry, I left in some legacy code when I was trimming it down. Remove the...

Code:
Protected HoldFlash.FLASHWINFO


... line from TelnetConnect(). I was using it to flash the queue window in my main program when all scripts were finished.

However, in case you need it, the structure is...

Code:
Structure FLASHWINFO
   cbSize.l
   hwnd.l
   dwFlags.l
   uCount.l
   dwTimeout.l
EndStructure


Top
 Profile  
 
 Post subject:
PostPosted: Wed Sep 03, 2008 1:45 pm 
Offline
Addict
Addict
User avatar

Joined: Sun Nov 05, 2006 11:42 pm
Posts: 2513
Location: Lyon - France
Thanks, no error now 8)

_________________
ImageThe happiness is a road...
Not a destination


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye