[AHK] launch putty session out of sftp-plugin connection

Discuss and announce Total Commander plugins, addons and other useful tools here, both their usage and their development.

Moderators: white, Hacker, petermad, Stefan2

Post Reply
TWatcher
Junior Member
Junior Member
Posts: 43
Joined: 2008-08-26, 18:46 UTC

[AHK] launch putty session out of sftp-plugin connection

Post by *TWatcher »

I open a new thread here to separate it from thread New SFTP plugin available now

I updated my AHK script which launches a putty session out of an active sftp-plugin connection.
It supports now detection of password stored in sftp plugin-session settings.

Please note: Storage of passwords is a security risk and is not recommended, however it is user's decision to use it or not and depending on the environment (e.g. separate network) it is reasonable to use it.

You can find the AHK script in the Wiki: AutoHotkey:_Launch_a_putty_session_out_of_an_active_sftp-plugin_connection_within_TC
Note: I am dealing with AHK for a short time only, may be the script is not perfect.

What does the AHK script do?
It starts (it tries to start) a new putty session out of an active TotalCommander sftp-plugin connection.
It uses parameter "server", "user" and "password" of the currently active sftp-plugin connection.

How to use :
preparation:
(1)
save the AHK script to a file, e.g. TcStrtPty.ahk
(2)
compile this AHK script to an exe, execute: "Ahk2Exe.exe /in TcStrtPty.ahk"; result should be: "TcStrtPty.exe"
(3)
Drag "TcStrtPty.exe" with the mouse to TC's Button bar.
usage:
(4)
within TC, within an active SFTP Session (!) just click on "TcStrtPty.exe-Button" in TC's Button bar.
A putty window should open asking for username (if not stored in plugin-session settings) and the password (if not stored in plugin-session settings).
If "user" and "password" are stored in plugin-session settings, then the scripts logs in automatically without any further user interaction and the script tries to send a "cd" command to change into directory which is the active directory in TotalCommander's sftp-plugin connection.
Note: To avoid undesired user input during login/changing directory the AHK script blocks user input (keyboard and mouse) for about 3 seconds.
The script works only if "putty.exe" is found in the PC's path.

For your convenience I uploaded a compiled version of the AHK script to rapidShare, you can download it form here (compiled version of the script TcStrtPty.exe) , (in this case just download the "TcStrtPty.exe" and follow steps 3 and 4 above)
If someone could give it a try please inform me about the results.

TWatcher
TWatcher
Junior Member
Junior Member
Posts: 43
Joined: 2008-08-26, 18:46 UTC

Post by *TWatcher »

Almost 2 weeks are gone, but no one seems to be willing to test the AHK script. It's a pity. :cry:
Nevertheless, for me it works fine. The script provides the functionality to open an extra Putty session window by one click, similar as WinSCP does.
So I do not need WinSCP any longer. :)
Thanks anyway - TWatcher
LarryD
New Member
New Member
Posts: 1
Joined: 2009-01-08, 12:24 UTC

Thanks!!!

Post by *LarryD »

Thanks for the script!!! Great Job!!!
:D :D :D
I had a single problem with it! In my sftpplug.ini file between the user and the password line there is an another line "scpfordata=1". I fixed this the quick (and dirty) way by skipping this line in the script.
TWatcher
Junior Member
Junior Member
Posts: 43
Joined: 2008-08-26, 18:46 UTC

Post by *TWatcher »

Hallo LarryD,
seems to be the case, that you are the first one reusing my script :D .
At the time I wrote the script, the order of parameters in sftpplug.ini file seemed to be fix with no gap (server, user, password), but this is obviously not (no longer) true.
I will update my script in the next days to take this behaviour in to account.
Regards TWatcher
TWatcher
Junior Member
Junior Member
Posts: 43
Joined: 2008-08-26, 18:46 UTC

Post by *TWatcher »

I updated my AHK script which launches a putty session out of an active sftp-plugin connection (it is now version: 18.01.2009).
It should be able now to detect the parameters in sftpplug.ini, even if the parameter are not in fix order.

You can find the updated AHK script in the Wiki: AutoHotkey:_Launch_a_putty_session_out_of_an_active_sftp-plugin_connection_within_TC

I hope it works as expected.
If someone would like to have a compiled version of the script (executable) then please contact me.
Regards TWatcher
konfekt
Junior Member
Junior Member
Posts: 12
Joined: 2021-11-16, 09:26 UTC

Re: [AHK] launch putty session out of sftp-plugin connection

Post by *konfekt »

Thank you for your useful script! It seems that the server address is in more recent versions of Total Commander, or probably more due to that of the SFTP plugin, no longer given by the control panel left of the command line; at least the script does no longer recognizes the server address when called in a tab of a folder of an SFTP server inside Total Commander.
Gernij
Junior Member
Junior Member
Posts: 7
Joined: 2013-01-26, 17:34 UTC

Re: [AHK] launch putty session out of sftp-plugin connection

Post by *Gernij »

Thanks for the scipt. I changed it a bit to work with TC v9.x and v10.x. I also changed the location of te log file and added a new parameter -puttyPath to specify the location of putty.

This is the new code (sorry can't find how to upload an attachment):

Code: Select all

; AHK script to launch a putty session out of active sftp-plugin connection within TC
;   using "server", "user" and "password" parameters (client certificate not supported here)
; author: TWatcher and Gernij
; history:
; version 24.07.2023
; changed: 24.07.2023:
;          - Added new parameter -puttyPath to specify the location of putty.
;          - Changed the location of the log file to the TEMP directory.
;          - Update for TotalCommander v10.x (changed panel name of panel left of the command line).
; changed: 18.01.2009: within sftpplug.ini the order of parameters for a stfp connection may be not in fix order,
;          other paramters may be between "server", "user" and "password".
;          Fixed, now the sript seraches for server, user and password in all lines (max. 15 lines) in the ini section
; version 29.09.2008
;         first published
;
; This works only with sftp-plugin provided by Mr. Ghisler.
; precondition: putty.exe has to be found within PC's path or to be specyfied with parameter -puttyPath
; parameter: "-logToFile" will generate some log statements in file TcStrtPty.log, located in the TEMP folder
;            "-showClearPw" will show the unencrypted password in the log file if it is specified in sftpplug.ini
;            "-puttyPath" to specify the complete path to putty to be used if putty is not within PC's path
;            "-h" if this is the first or only parameter is displays a short usage of the program
; preparation:
;  (1) save this AHK script to a file, e.g. "TcStrtPty.ahk"
;  (2) compile this AHK script to an exe, execute: "Ahk2Exe.exe /in TcStrtPty.ahk"
;      result should be "TcStrtPty.exe"
;  (3) Drag "TcStrtPty.exe" with the mouse to TC's Button bar.
; usage:
;  (4) within TC, within an active SFTP Session (!) just click on "TcStrtPty.exe-Button" in TC's Button bar.
;      A putty window should open asking for username (if not stored in plugin-session settings)
;      and the password (if not stored in plugin-session settings).
;      If "user" and "password" are stored in plugin-session settings, then the scripts logs in automatically
;      without any further user interaction and the script tries to send a "cd" command to change
;      into directory which is the active directory in TotalCommander's sftp-plugin connection.
; Note:
;   To avoid undesired user input during login/changing directory the AHK script blocks user input
;   (keyboard and mouse) for about 3 seconds.
; Note:
;   Storage of passwords is a security risk and is not recommended,
;   however it is user's decision to use it or not and depending on the environment
;   (e.g. separate network) it is reasonable to use it.

#IfWinExist, ahk_class TTOTAL_CMD

title = AHK script to lauch a putty session out of active sftp-plugin connection within TotalCommander

puttyErrMsg = The programm 'putty.exe' was not found or could not be launched`, please check your 'path' settings`!

version = 27.07.2023
startprg = putty.exe
SearchStrg = \\\Secure FTP\

if not WinActive( "ahk_class TTOTAL_CMD" )
{
   MsgBox,16,, TC is not active, doing nothing
   return
}

; Read current TC dir from the panel left of the command line
ControlGetText, TCPath, Window12
; if the above command doesn't work You can try the command below
;ControlGetText, TCPath, %SearchStrg%

DoLogToFile =
ShowClearPw =
AltPuttyPath =

if 0 > 0
{
  par = %1%
  if ( par = "-h" ) {
	msgstring := title . "`n`n"
	msgstring := msgstring . "Usage:`n"
	msgstring := msgstring . A_ScriptName . " [-h]`n"
	msgstring := msgstring . A_ScriptName . " [<parameter>]`n"
	msgstring := msgstring . "   '-h'   : this help text`n"
	msgstring := msgstring . "   '-logToFile'   : logs to log file`n"
	msgstring := msgstring . "   '-showClearPw'   : show unencrypted password in logfile`n"
	msgstring := msgstring . "   '-puttyPath <path to putty>' : putty command to be used`n"
    MsgBox, 64, ,%msgstring%
    exitapp
  }

  index := 1
  while index <= A_Args.length()
  {
    par := A_Args[index]
    if ( par = "-logToFile" ) {
      DoLogToFile = True
	}
    if ( par = "-showClearPw" ) {
      ShowClearPw = True
    }
	if ( par = "-puttyPath" ) {
	  if (index+1 <= A_Args.length()) {
	    AltPuttyPath = true
	    value := A_Args[index+1]
	    StringGetPos, pos, value, "-"
	    if (pos != 0) {
	  	  index++
		  startprg := A_Args[index]
	    }
	  }
	}
	index++
  }
}

iniPath = %COMMANDER_INI%
StringLen, pos_prev, iniPath
pos_prev += 1
StringGetPos, pos, iniPath, \, R1
pos += 1
StringLeft, iniPath, iniPath, pos


if DoLogToFile = True
{
  LogFile = %TEMP%\TcStrtPty.log
  FileDelete, %LogFile%
  Log(A_ScriptName . " : " . title)
  Log("version: " . version)
  Log("Param: '-logToFile' : Logging to file is active, LogFile: " . LogFile)
}

if showClearPw
{
  Log("Param: '-showClearPw' : Show clear password in log is active")
}

if AltPuttyPath
{
  Log("Param: '-puttyPath' : Use path to Putty: " . startprg)
}

FormatTime, TimeString
Log("Start " . TimeString)
Log("iniPath: " . iniPath )

Log("Found running TC")
Log("Active TCPath is: '" . TCPath )

; Check whether TCPath starts with SearchStrg
if ( InStr( TCPath, SearchStrg) > 0 )
{
  Log("Found SFTP within path")
  ; Replace SearchStrg
  StringReplace, TCPath, TCPath, %SearchStrg%,
  ; Replace the trailing > with a \
  StringReplace, TCPath, TCPath, >, \
  ; now replace any "\" by   "/"
  StringReplace, TCPath, TCPath, \ , / , all
  ; now find 1st "/"
  StringGetPos, pos, TCPath, /
  if pos >= 0
  {
    ; save startdir
    StringRight, startdir, TCPath, StrLen(TCPath) - pos
    ; and Remove rest
    StringLeft, Host, TCPath, pos
  }
}
Log("Host: '" . Host . "'")

iniFile = %iniPath%sftpplug.ini
;##############################
if Host
{
  Log("SFTP-Ini File is : " . iniFile )
  Gosub, SearchSection
}
else
{
  Log("Did not detect active 'Secure FTP' window in TC")
  MsgBox, 16,, Did not detect active 'Secure FTP' window in TC, can do nothing, aborting now...
}

Log("done...")

exitApp


;##############################

SearchSection:
ArrayCount = 0
SectionFound =
Loop, Read, %iniFile%
{
  ArrayCount += 1  ; Keep track of how many items are in the array.
  Array%ArrayCount% := A_LoopReadLine  ; Store this line in the next array element.
}

; Read from the array:
Loop %ArrayCount%
{
  If not SectionFound
  {
    element := Array%A_Index%
    if ( InStr( element, "[" ) = 1 )
    {
      Log("Found section: " . element)
    }
    IfInString, element, %Host%
      SectionFound := true
  }
  If SectionFound
  {
    Log("--> found Host in charge")
    Indextmp = %A_Index%

    MAXLOOP = 15 ; MAXLOOPs lines should be enough
    Loop , %MAXLOOP%
    {
      Indextmp += 1
      if Indextmp > %ArrayCount%
      {
        Log("serach for params: end of ini file reached: exiting loop")
        break
      }
      element2 := Array%Indextmp%
      Log("next line: "  . a_index . " : " . element2 )
      if ( InStr( element2, "[" ) = 1 )
      {
        Log("serach for params: next section found: exiting loop")
        break
      }

      if ( InStr( element2, "server=" ) = 1 )
      {
        ItemServer := Array%Indextmp%
      }
      if ( InStr( element2, "user=" ) = 1 )
      {
        ItemUser := Array%Indextmp%
      }
      if ( InStr( element2, "password=" ) = 1 )
      {
        ItemPassword := Array%Indextmp%
      }
      if ( ItemServer and ItemUser and ItemPassword )
        break
      if ( a_index = MAXLOOP )
      {
        Log("serach for params: searched " . MAXLOOP . " lines, it is enough, exiting loop")
        break
      }
    }

    Log(ItemServer . "   " . ItemUser . "   " . ItemPassword)

    StringReplace, ItemServer, ItemServer, server=,
    ; now replace any "\" by   "/"
    StringReplace, ItemServer, ItemServer, \ , / , all

    ; now find 1st "/"
    StringGetPos, pos, ItemServer, /
    if pos >= 0
    {
      ; Remove rest
      StringLeft, ItemServer, ItemServer, pos
    }

    StringReplace, ItemUser, ItemUser, user=,
    StringReplace, ItemPassword, ItemPassword, password=,

    Log("server='" . ItemServer . "'  user='" . ItemUser . "'  password='" . ItemPassword . "'")
    Log("startdir='" . startdir . "'")

    if not ItemServer
    {
      Log("Empty entry for server in section '" . element . "' can do nothing, aborting now..")
      MsgBox,16,, Empty entry for server in section '%element%' can do nothing, aborting now..
      break
    }

    passwordClear =
    if ItemPassword
    {
      passwordClear := DecryptPW(ItemPassword)
    }

    if ItemUser
    {
      Log("Now trying to start putty session to  " . ItemUser . "@" . ItemServer )
      if passwordClear
      {
        if ShowClearPw
        {
          Log("Run, " . startprg . " -ssh " . ItemServer . " -l " . ItemUser . " -pw " . passwordClear)
        }
        else
        {
          Log("Run, " . startprg . " -ssh " . ItemServer . " -l " . ItemUser . " -pw ******")
        }

        Run, %startprg% -ssh %ItemServer% -l %ItemUser% -pw %passwordClear%, , UseErrorLevel  ;
        if ErrorLevel = ERROR
        {
          MsgBox,16,, %puttyErrMsg%
          ;exit
        }
        else
        {
          if startdir
          {
            Log("ItemServer: '" . ItemServer . "'")

            SetTitleMatchMode, 2
            WinWait, %ItemServer%,, 10
            if not ErrorLevel
            {
              Log("found window: '" . ItemServer . "'")
              Log("switch BlockInput On ...")
              BlockInput On
              Log("going to sleep for 1000 ms ...")
              Sleep, 1000

              IfWinActive, PuTTY Security
              {
                Log("-found active window: PuTTY Security")
                Log("-switch BlockInput Off ...")
                BlockInput Off
                WinWaitNotActive, Security, , 55
                if ErrorLevel
                {
                  Log("-active window: PuTTY Security was not closed within 55 seconds, aborting now")
                  ExitApp ;
                }
                Log("-active window: PuTTY Security was closed")
                Log("going to sleep for 500 ms ...")
                Sleep, 500
              }

              Log("after (optional) handling of Security alert ...")

              IfWinExist, %ItemServer%
              {
                Log("+found existing window: '" . ItemServer . "'")
                IfWinNotActive, %ItemServer%
                {
                  Log("++window: '" . ItemServer . "' is not active, try to activate, wait 5 s")
                  WinWaitActive, %ItemServer%,, 5
                  if ErrorLevel
                  {
                    Log("ErrorLevel while wait for WinWaitActive for '" . ItemServer . "', ErrorLevel:'" . ErrorLevel . "'")
                  }
                }
                Log("+found active window: '" . ItemServer . "'")
                Log("+switch BlockInput On ...")
                BlockInput On
                Log("+going to sleep for 500 ms ...")
                Sleep, 500
                ; check again
                IfWinActive, %ItemServer%
                {
                  Log("++found again active window: '" . ItemServer . "'")
                  Log("++going to sleep for 1000 ms ...")
                  Sleep, 1000
                  Log("++Sending input string startdir '" . startdir . "' ...")
                  SendInput, cd %startdir%{Enter}
                }
                Log("+switch BlockInput Off ...")
                BlockInput Off

                Sleep, 2000
              }
              else
              {
                Log("+did not find window: '" . ItemServer . "', establishing of Putty session not successful, aborting now...")
                MsgBox Establishing of Putty session not successful, aborting now...
                Sleep, 2000
              }
            }
          }
        }
      }
      else
      {
        Log("Run, " . startprg . " -ssh " . ItemServer . " -l " . ItemUser )
        Run, %startprg% -ssh %ItemServer% -l %ItemUser%, , UseErrorLevel  ;
        if ErrorLevel = ERROR
        {
          MsgBox,16,, %puttyErrMsg%
        }
      }
    }
    else
    {
      Log("Now trying to start putty session to  " . ItemServer )
      Log("Run, " . startprg . " -ssh " . ItemServer )
      Run, %startprg% -ssh %ItemServer% , , UseErrorLevel  ;
      if ErrorLevel = ERROR
      {
        MsgBox,16,,  %puttyErrMsg%
      }
    }
    break
    return
  }
}
Log("After loop, now return")
return



;##############################
;functions:
;##############################
Log(LogString)
{
  global
  if DoLogToFile = True
  {
    if LogFile
      FormatTime, TimeString , , hh:mm:ss
      FileAppend, %TimeString% %LogString% `n,  %LogFile%
  }
}

DecryptPW(pwString)
{
  g_pszKey = unpzScGeCInX7XcRM2z+svTK+gegRLhz9KXVbYKJl5boSvVCcfym
  iKeyLength := StrLen(g_pszKey)
  Log("called DecryptPW with pwString: " . pwString)
  iEncryptedLength := StrLen(pwString)
  EnvDiv, iEncryptedLength, 3
  Log("iEncryptedLength: " . iEncryptedLength)
  iPos := mod(iEncryptedLength,iKeyLength)
  pwResult=
  Loop %iEncryptedLength%
  {
    SetFormat, integer, hex
    StringLeft, i3Digits, pwString, 3
    if i3Digits is not integer
    {
      Log("--: i3Digits: should have digits only!, aborted")
      return
    }
    StringRight, pwString, pwString, StrLen(pwString)-3
    encryptCharPos :=  Mod(A_Index + iPos,iKeyLength)
    encryptChar := SubStr(g_pszKey, encryptCharPos , 1)
    iEncryptChar := asc(encryptChar)
    Transform, result2, BitXOr, %iEncryptChar%, %i3Digits%
    pwResult:=pwResult . chr(result2)
    SetFormat, integer, d
  }
  global ShowClearPw
  if ShowClearPw
    Log("pwResult:: '" . pwResult . "'" )
  Log("DecryptPW done")
return pwResult
}
Greetings, Gerrit
Post Reply