[plug] Slippery, secure file transfers

Bernd Felsche bernie at innovative.iinet.net.au
Fri Feb 10 08:27:47 WST 2006


Russell Steicke <r.steicke at bom.gov.au> writes:
>On Wed, Feb 08, 2006 at 08:48:49PM +0800, Bernd Felsche wrote:
>> Russell Steicke <r.steicke at bom.gov.au> writes:

>> >If you want to drive sftp, perhaps expect would be a better tool
>> >than python and libraries.  I've used it to drive telnet mostly,
>> >but it's pretty darned good at it.

>> Check python-expect.

>Ah, I didn't know about that.  Thanks.

Here's a short "demo" of sftp being driven by Python and the
"pexpect" package. The following has been adapted from the ftp
example that comes with pexpect.

	http://pexpect.sourceforge.net/

Note that most urlparse packages still have a bug in not recognizing
sftp as a protocol.

--------------------------------------------------------------------------------
#!/usr/local/bin/python
"""Testing sftp connection for (initially) bits
This connects to the sftp site; uploads the nominated file to the 
nominated destination.

sftp [-p password] source destination_url

destination_url must be sftp://[user@]server.name/...

Specifying the password on the command line is NOT recommended for
security reasons.

Copyright (C) 2006 Bernd Felsche, Innovative Reckoning, Western Australia

History:
  2006-02-09 BHF Initial
"""
import pexpect
import os,sys
import getopt, getpass
import urllib2, urllib

### NB patched urlparse to recognize 'sftp'
import urlparse

# constants
COMMAND_PROMPT = 'sftp> '

def exit_with_usage():
  print globals()['__doc__']
  os._exit(1)

def main():
  global COMMAND_PROMPT

  # process command line args
  try:
    optlist, args = getopt.getopt(sys.argv[1:], 'h?p:', ['help','h','?'])
  except Exception, e:
    print str(e)
    exit_with_usage()

  options = dict(optlist)
  if len(args) != 2:
    exit_with_usage()

  if [elem for elem in options if elem in ['-h','--h','-?','--?','--help']]:
    print "Help:"
    exit_with_usage()

  password = ''
  if '-p' in options:
    password = options['-p']

  datafile = sys.argv[1]
  sendto   = sys.argv[2]

  proto,host,path,parm,qry,frag = urlparse.urlparse(sendto)

  # proto is sftp --- or else... !

  # connect and login
  child = pexpect.spawn('sftp %s' % host)
  i = child.expect([pexpect.TIMEOUT, COMMAND_PROMPT, '(?i)assword'])
  if i == 0: # Timeout
    print 'ERROR! could not login to %s with SFTP' % host
    os._exit(1)
  if i == 2: # Password prompt
    if password == '':
      password = getpass.getpass('Password: ')
    child.sendline(password)
    i = child.expect([pexpect.TIMEOUT, COMMAND_PROMPT, '(?i)assword'])
    if i in [ 0, 2 ]: # Timeout or bad password
      print 'ERROR! could not login to %s with SFTP' % host
      os._exit(1)

  # go to the nominated directory
  finalname = os.path.basename(datafile)
  child.sendline('cd %s' % path[1:])
  i = child.expect([pexpect.TIMEOUT, COMMAND_PROMPT, '3..:', '(?i)directory'])
  if i == 0: # Timeout
    print 'ERROR! Timeout change to directory %s.' % path[1:]
    print child.before, child.after
    print str(child)
    os._exit(1)
  if i in [ 2, 3 ]: #  Can't chdir if path is filename.. try again
    finalname = os.path.basename(path)
    parent = os.path.dirname(path)
    child.sendline('')
    child.expect(COMMAND_PROMPT)
    child.sendline('cd %s' % parent[1:])
    i = child.expect([pexpect.TIMEOUT, COMMAND_PROMPT, '3..:', '(?i)directory'])
    if i in [ 0, 2, 3 ]: # Timeout or other error
      print 'ERROR! Could not change to directory %s.' % parent[1:]
      print child.before, child.after
      print str(child)
      os._exit(1)
  
  child.sendline('put %s %s' % (datafile, finalname))
  i = child.expect([pexpect.TIMEOUT, COMMAND_PROMPT, '(?i)directory'])
  if i in [ 0, 2 ]: # Timeout or other error
    print 'ERROR! could upload to %s. Here\'s the gripe:' % finalname
    print child.before, child.after
    print str(child)
    os._exit(1)
 
  if child.isalive():
      child.sendline('bye') # Try to ask ftp child to exit.
      child.close()

if __name__ == "__main__":
    try:
        main()
    except Exception, e:
        print str(e)
        os._exit(1)

--------------------------------------------------------------------------------
-- 
/"\ Bernd Felsche - Innovative Reckoning, Perth, Western Australia
\ /  ASCII ribbon campaign | "Laws do not persuade just because
 X   against HTML mail     |  they threaten."
/ \  and postings          | Lucius Annaeus Seneca, c. 4BC - 65AD.




More information about the plug mailing list