sftp.py :  » Network » FtpCube » ftpcube-0.5.1 » libftpcube » transports » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Network » FtpCube 
FtpCube » ftpcube 0.5.1 » libftpcube » transports » sftp.py
"""
FtpCube
Copyright (C) Michael Gilfix

This file is part of FtpCube.

You should have received a file COPYING containing license terms
along with this program; if not, write to Michael Gilfix
(mgilfix@eecs.tufts.edu) for a copy.

This version of FtpCube is open source; you can redistribute it and/or
modify it under the terms listed in the file COPYING.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
"""

import libftpcube.dispatcher
import libftpcube.protocol
from libftpcube.logger import Logger
import libftpcube.messages
import libftpcube.utils

import paramiko
import wx

import errno
import exceptions
import os
import socket
import sys
import threading
import time


class SFtpException(libftpcube.protocol.ProtocolException):
    """Base exception for SFTP communications."""

    def __init__(self, args=None):
        libftpcube.protocol.ProtocolException.__init__(self, args)

class SFTPDispatcher(libftpcube.dispatcher.Dispatcher):
    """SFTP command dispatcher.

    This class extends the base dispatcher to allow for dispatching of SFTP
    command objects. Unless otherwise noted, the extension methods should be
    executed within the dispatcher thread. The SFTP dispatcher provides the
    low level handling of SSH communications to the SFTP server. The extension
    methods allow commands to wait on the dispatcher for received messages
    from the import SFTP session. It is recommended that command objects have
    access to the dispatcher in order to send/receive data while executing
    from within the dispatcher thread. This allows the command classes to
    make use of the dipatcher capabilities without worrying about thread safety
    issues.
    """

    def __init__(self, **kwargs):
        """Creates an SFTP dispatcher instance.

        This initializes the private variables for use within the dispatcher
        command execution thread. These variables are either set once during
        initialization or serve as variables for the thread stack. Although
        command objects may have reference to the dispatcher object, instance
        variables should never be accessed directly -only through accessor
        functions.

        This method defines the following keywords:
            'host'      : The host to connect to - default is localhost.
            'port'      : The SSH port to connect to - default is 22.
            'host_keys' : The path to the SSH host keys file - default
                          searches in well known places.
        """
        libftpcube.dispatcher.Dispatcher.__init__(self, **kwargs)

        self.sock = None
        self.transport = None
        self.sftp_client = None

        try:
            self.host = kwargs['host']
        except KeyError:
            self.host = 'localhost'
        try:
            self.port = kwargs['port']
        except KeyError:
            self.port = 22
        try:
            self.host_key_path = kwargs['host_keys']
        except KeyError:
            self.host_key_path = self.getDefaultHostKeyPath()

        self.host_keys = self.initializeHostKeys()

    def getDefaultHostKeyPath(self):
        """Returns the full default path to the host key file."""
        path = None
        if sys.platform == 'win32':
            path = os.path.join('.ssh', 'known_hosts')
            path = os.path.join(os.environ['USERPROFILE'], path)
        elif sys.platform == 'posix':
            path = os.sep.join([ '~', '.ssh', 'known_hosts' ])
            path = os.path.expanduser(path)
        else:
            path = './known_hosts'
        return path

    def getHostKeyPath(self):
        """Returns the host key path."""
        return self.host_key_path

    def initializeHostKeys(self):
        """Initializes the host keys file using the supplied host key path and returns a
        host key object.

        This checks to see if the host keys file exists. Otherwise, it creates the containing
        directory so the host key file can be saved in the future."""
        host_keys = None
        host_key_path = self.getHostKeyPath()
        if not os.path.exists(host_key_path) or not os.path.isfile(host_key_path):
            base_dir = os.path.dirname(host_key_path)
            if not os.path.exists(base_dir):
                try:
                    os.makedirs(base_dir)
                except OSError, strerror:
                    raise SFtpException, sterror
            elif not os.path.isdir(base_dir):
                raise SFtpException, \
                    _("Path must be directory to create host keys file: %(path)s") \
                    %{ 'path' : base_dir }
            host_keys = paramiko.HostKeys()
        else:
            try:
                host_keys = paramiko.HostKeys(host_key_path)
            except Exception, strerror:
                raise SFtpException, _("Error initializing host key file: %(f)s") \
                    %{ 'f' : strerror }
        return host_keys

    def connect(self):
        """Opens a socket connection to the SSH server.

        This method only establishes the connection and starts the SFTP client negotation.
        This does not authenticate the user, which must be performed in a separate step.
        This method should be executed either as initialization or within the thread
        context of the dispatcher. Otherwise, this method should not be considered thread
        safe. If an error occurs establishing a connection, then this method will raise
        an SFtpException.

        The establishment of the connect is performed asynchronously. This allows for
        destruction of the dispatcher object (i.e., tearing down the connection) while
        a connection is being established."""
        proto = socket.getprotobyname('tcp')
        try:
            self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, proto)
        except socket.error, strerror:
            self.closeSocket()
            raise SFtpException(_("Error opening SFTP socket: %(err)s") %{ 'err' : strerror })

        self.log(Logger.LOCAL, _("Connecting to %(h)s on port %(p)d.")
            %{ 'h' : self.host, 'p' : self.port })

        self.sock.setblocking(0)
        try:
            err = self.sock.connect_ex((self.host, self.port))
        except socket.error, strerror:
            self.closeSocket()
            raise SFtpException(_("Error connecting to host %(h)s: %(err)s")
                %{ 'h' : self.host, 'err' : strerror })

        self.log(Logger.LOCAL, _("Connected to %(h)s.") %{ 'h' : self.host })

        while (err == errno.EINPROGRESS or err == errno.EWOULDBLOCK) and not self.die.isSet():
            time.sleep(0.25)
            err = self.sock.getsockopt(socket.SOL_SOCKET, socket.SO_ERROR)

        if err != 0 or self.die.isSet():
            self.closeSocket()
            raise SFtpException(_("Error connecting to host %(h)s: %(err)s")
                %{ 'h' : self.host, 'err' : os.strerror(err) })

        self.log(Logger.LOCAL, _("Opening SSH transport and negotiating keys."))
        self.sock.setblocking(1)

        try:
            self.transport = paramiko.Transport(self.sock)
            self.transport.start_client()
            key = self.transport.get_remote_server_key()
        except Exception, strerror:
            self.closeTransport()
            raise SFtpException(_("Error opening SSH transport: %(err)s")
                %{ 'err' : strerror })

        ret = None
        if not self.host_keys.has_key(self.host) or \
           not self.host_keys[self.host].has_key(key.get_name()):
            ret = libftpcube.messages.displayMessageDialog(libftpcube.utils.getMainWindow(),
                 _("Ftpcube - SFTP Unknown Host Key"),
                 _("WARNING: Unknown host key for %(host)s. Proceed?")
                 %{ 'host' : self.host }, style=wx.YES_NO)
        elif self.host_keys[self.host][key.get_name()] != key:
            ret = libftpcube.messages.displayMessageDialog(libftpcube.utils.getMainWindow(),
                 _("Ftpcube - SFTP Host Key Changed"),
                 _("WARNING: Host key has changed for %(host)s. Proceed?")
                 %{ 'host' : self.host }, style=wx.YES_NO)

        # Process the outcome of the popup if one was made
        if ret == wx.ID_NO:
            self.closeTransport()
            raise SFtpException(_("Error opening SSH transport: Host key rejected."))
        elif ret == wx.ID_YES:
            self.host_keys.add(self.host, key.get_name(), key)
            try:
                self.host_keys.save(self.getHostKeyPath())
            except IOError, strerror:
                self.closeTransport()
                raise SFtpException(_("Error writing host key file: %(err)s")
                    %{ 'err' : strerror })

        self.log(Logger.REMOTE, _("SSH channel successfully negotiated."))

    def getHost(self):
        """Returns the host that this SFTP session is connected to."""
        return self.host

    def getPort(self):
        """Returns the port that this SFTP session is connected to."""
        return self.port

    def getTransport(self):
        """Returns the underlying SSH transport for the SFTP session."""
        return self.transport

    def getSFTPClient(self):
        """Returns the SFTP client object."""
        return self.sftp_client

    def closeTransport(self):
        """Closes the SSH transport connection."""
        if self.transport is not None:
            self.transport.close()
            self.transport = None
        self.closeSocket()

    def closeSocket(self):
        """Closes the socket connection."""
        if self.sock is not None:
            self.sock.close()
            self.sock = None

    def openSFTPSession(self):
        """Opens an SFTP session.

        This method should be called once authentication has finished. It gets the current
        wording directory and sets up the SFTP client so paramiko keeps track of relative
        directories."""
        self.log(Logger.LOCAL, _("Opening SFTP session."))
        try:
            self.sftp_client = paramiko.SFTPClient.from_transport(self.transport)
            self.log(Logger.LOCAL, _("Getting remote directory."))
            real_cwd = self.sftp_client.normalize('.')
            self.log(Logger.REMOTE, _("Remote directory: %(dir)s") %{ 'dir' : real_cwd })
            self.sftp_client.chdir(real_cwd)
        except Exception, strerror:
            raise SFtpException(_("Error creating SFTP client session: %(err)s")
                %{ 'err' : strerror })
        self.log(Logger.LOCAL, _("SFTP session opened."))

    def run(self):
        """Overrides the dispatcher execute method to clean up the SFTP session after the
        thread has terminated."""
        try:
            libftpcube.dispatcher.Dispatcher.run(self)
        finally:
            try:
                self.quit()
            except Exception, strerror:
                pass

    def quit(self):
        """Quits the current session."""
        if self.sftp_client is not None:
            self.sftp_client.close()
        self.closeTransport()

class SFTPAbstractCommand(libftpcube.dispatcher.DispatcherCommand):
    """Abstract base class for all SFTP commands."""
    
    REMOTE_SEP = '/'

class SFTPConnect(SFTPAbstractCommand):
    """SFTP connection command.

    This command opens up the SSH connection to the remote server. After execution of this
    command, crypto keys will have been negotiated, but the user will remain unauthenticated.
    The connection can be aborted by destroying the dispatcher instance while this
    connection is outstanding."""

    def execute(self, dispatcher):
        dispatcher.connect()

class SFTPLogin(SFTPAbstractCommand):
    """SFTP Login command.

    Completes the authentication of the user over the SSH connection. This then finalizes
    the SFTP client session. If an error occurs during log-in, then an SFtpException will
    be raised."""

    def __init__(self, user, pw):
        SFTPAbstractCommand.__init__(self)
        self.user = user
        self.pw = pw

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("Logging in: USER %(user)s, PASS %(pass)s")
            %{ 'user' : self.user, 'pass' : '*' * len(self.pw) })
        transport = dispatcher.getTransport()
        try:
            transport.auth_password(self.user, self.pw)
            if not transport.is_authenticated():
                raise _("Invalid username and password")
            dispatcher.log(Logger.REMOTE, _("Login successful."))
            dispatcher.openSFTPSession()
        except Exception, strerror:
            raise SFtpException(_("Error logging in to SSH connection: %(err)s")
                 %{ 'err' : strerror })

class SFTPNOOP(SFTPAbstractCommand):
    """SFTP NOOP command.

    This sends some ignored junk data that can be used to keep alive the connection."""

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("NOOP"))
        transport = dispatcher.getTransport()
        if transport is None:
            return
        transport.send_ignore()
        dispatcher.log(Logger.REMOTE, _("NOOP OK"))

class SFTPCwd(SFTPAbstractCommand):
    """SFTP change working directory command."""

    def __init__(self, dir):
        SFTPAbstractCommand.__init__(self)
        self.dir = dir

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("Changing reference directory: %(dir)s")
            %{ 'dir' : self.dir })
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None or self.dir == '.':
            return
        sftp_client.chdir(self.dir)

class SFTPPwd(SFTPAbstractCommand):
    """SFTP get working directory command."""

    def __init__(self, status=None):
        SFTPAbstractCommand.__init__(self)
        self.status = status

    def execute(self, dispatcher):
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return
        cwd = sftp_client.getcwd()
        dispatcher.log(Logger.LOCAL, _("Getting current reference directory: %(dir)s")
            %{ 'dir' : cwd })
        if self.status:
            self.status.setOptionalData(cwd)
            self.status.finished()

class SFTPDelete(SFTPAbstractCommand):
    """SFTP delete comand."""

    def __init__(self, file):
        SFTPAbstractCommand.__init__(self)
        self.file = file

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("Deleting file: %(file)s") %{ 'file' : self.file })
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return
        sftp_client.remove(self.file)
        dispatcher.log(Logger.REMOTE, _("File successfuly removed."))

class SFTPRename(SFTPAbstractCommand):
    """SFTP rename command."""

    def __init__(self, old_name, new_name):
        SFTPAbstractCommand.__init__(self)
        self.old_name = old_name
        self.new_name = new_name

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("Renaming file: %(old)s to %(new)s")
            %{ 'old' : self.old_name, 'new' : self.new_name })
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return
        sftp_client.rename(self.old_name, self.new_name)
        dispatcher.log(Logger.REMOVE, _("File successfully renamed."))

class SFTPMkdir(SFTPAbstractCommand):
    """SFTP make directory command."""

    def __init__(self, dir, status=None):
        SFTPAbstractCommand.__init__(self)
        self.dir = dir
        self.status = status

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("Creating new directory: %(dir)s")
            %{ 'dir' : self.dir })
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return
        sftp_client.mkdir(self.dir)
        if self.status:
            path = self.REMOTE_SEP.join([ sftp_client.getcwd(), self.dir ])
            self.status.setOptionalData(path)
            self.status.finished()
        dispatcher.log(Logger.REMOTE, _("Directory successfully created."))

class SFTPRmdir(SFTPAbstractCommand):
    """SFTP remove directory command."""

    def __init__(self, dir):
        SFTPAbstractCommand.__init__(self)
        self.dir = dir

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("Removing directory: %(dir)s") %{ 'dir' : self.dir })
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return
        sftp_client.rmdir(self.dir)
        dispatcher.log(Logger.REMOTE, _("Directory successfully removed."))

class SFTPChmod(SFTPAbstractCommand):
    """SFTP change permissions."""

    def __init__(self, file, mode):
        SFTPAbstractCommand.__init__(self)
        self.file = file
        self.mode = mode

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("Changing permissions for %(file)s to %(mode)s")
            %{ 'file' : self.file, 'mode' : self.mode })
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return
        sftp_client.chmod(self.file, self.mode)
        dispatcher.log(Logger.REMOTE, _("Permissions set successfully."))

class SFTPList(SFTPAbstractCommand):
    """Gets an SFTP listing.

    This retries an SFTP listing within an SFTP session. This command takes a
    dispatcher status object, which is updated with the latest status as the
    listing is retrieved."""

    def __init__(self, status=None):
        SFTPAbstractCommand.__init__(self)

        if status is not None and not isinstance(status, libftpcube.dispatcher.DispatchStatus):
            raise SFtpException(_("Invalid status object"))
        self.status = status

        self.data = [ ]

    def execute(self, dispatcher):
        dispatcher.log(Logger.LOCAL, _("Getting listing for current directory."))
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return

        if self.status:
            self.status.start()
        self.data = sftp_client.listdir_attr()
        # Paramiko converts to unix ls -l style when calling str()
        self.data = [ str(x) for x in self.data if x ]
        if self.status:
            self.status.setOptionalData(self.data)
            self.status.finished()
        dispatcher.log(Logger.REMOTE, _("Listing sent."))

    def getData(self):
        return self.data

class SFTPTransfer(SFTPAbstractCommand):
    """Base class for SFTP file transfers.

    This base class performs common file transfer function."""

    def __init__(self, remote_file, local_file, download=True, status=None):
        self.remote_file = remote_file
        self.local_file = local_file
        self.download = download
        self.abort_flag = threading.Event()

        if not isinstance(status, libftpcube.dispatcher.DispatchStatus):
            raise SFtpException(_("Invalid status object"))
        self.status = status

    def abort(self):
        """Aborts the current executing transfer."""
        self.abort_flag.set()

class SFTPAsciiTransfer(SFTPTransfer):
    """Performs an ASCII file transfer.

    This class performs an ASCII file transfer - both upload and download. This
    command takes a dispatcher status object, which is updated with the latest
    status as the file is transfered."""

    MODES = { True : 'r', False : 'w'}

    def __init__(self, remote_file, local_file, download=True, status=None):
        SFTPTransfer.__init__(self, remote_file, local_file, download=download,
            status=status)

    def execute(self, dispatcher):
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return

        if self.status:
            self.status.start()

        self.file = sftp_client.file(self.remote_file, self.MODES[self.download])
        local_file = open(self.local_file, self.MODES[not self.download])
        try:
            if self.download:
                dispatcher.log(Logger.LOCAL, _("Initiating ASCII download: %(remote)s")
                    %{ 'remote' : self.remote_file })
                while not self.abort_flag.isSet():
                    line = self.file.readline()
                    if not line:
                        break
                    if self.status:
                        self.status.update(len(line))
                    local_file.write(line)
                dispatcher.log(Logger.REMOTE, _("Transfer of %(file)s completed.")
                    %{ 'file' : self.remote_file })
            else:
                dispatcher.log(Logger.LOCAL, _("Initiating ASCII upload: %(remote)s")
                    %{ 'remote' : self.remote_file })
                while not self.abort_flag.isSet():
                    line = local_file.readline()
                    if not line:
                        break
                    self.file.write(line)
                    if self.status:
                        self.status.update(len(line))
                dispatcher.log(Logger.REMOTE, _("Transfer of %(file)s completed.")
                    %{ 'file' : self.remote_file })
        finally:
            if self.file:
                self.file.close()
            if local_file:
                local_file.close()

        if self.status:
            self.status.finished()

class SFTPBinaryTransfer(SFTPTransfer):
    """Performs a binary file transfer.

    This class performs a binary file transfer - both upload and download. This
    command takes a dispatcher status object, which is updated with the latest
    status as the file is transfered."""

    def __init__(self, remote_file, local_file, download=True, status=None,
                 blocksize=8192, rest=None):
        SFTPTransfer.__init__(self, remote_file, local_file, download=download,
            status=status)
        self.blocksize = blocksize
        self.rest = rest

    def execute(self, dispatcher):
        sftp_client = dispatcher.getSFTPClient()
        if sftp_client is None:
            return

        self.file = None
        local_file = None
        try:
            if self.download:
                dispatcher.log(Logger.LOCAL, _("Initiating binary download: %(remote)s")
                    %{ 'remote' : self.remote_file })
                self.file = sftp_client.file(self.remote_file, 'r')
                if self.rest is not None:
                    local_file = open(self.local_file, 'ab')
                else:
                    local_file = open(self.local_file, 'wb')

                while not self.abort_flag.isSet():
                    data = self.file.read(self.blocksize)
                    if not data:
                        break
                    if self.status:
                        self.status.update(len(data))
                    local_file.write(data)
                dispatcher.log(Logger.REMOTE, _("Transfer of %(file)s completed.")
                    %{ 'file' : self.remote_file })
            else:
                dispatcher.log(Logger.LOCAL, _("Initiating binary upload: %(remote)s")
                    %{ 'remote' : self.remote_file })
                local_file = open(self.local_file, 'rb')
                self.file = sftp_client.file(self.remote_file, 'wb')
                if self.rest is not None:
                    self.file.seek(self.rest)

                while not self.abort_flag.isSet():
                    data = local_file.read(self.blocksize)
                    if not data:
                        break
                    self.file.write(data)
                    if self.status:
                        self.status.update(len(data))
                dispatcher.log(Logger.REMOTE, _("Transfer of %(file)s completed.")
                    %{ 'file' : self.remote_file })
        finally:
            if self.file:
                self.file.close()
            if local_file:
                local_file.close()

        if self.status:
            self.status.finished()

class SFTP(libftpcube.protocol.ProtocolInterface):
    """Main interface for the SFTP protocol implementation.

    This class provides file transfer functionality over the SFTP protocol. Classes that
    are external to the transports package should only use this class as the interface
    into SFTP interactions. Each instance of this object represents an SFTP session,
    including both command and data connections."""

    def __init__(self, **kwargs):
        """Initializes the SFTP interface.

        This creates a new dispatcher thread and dispatch queue for outbound SFTP
        commands.

        This method defines the following keywords:
            'host'   : The host to connect to - default is localhost.
            'port'   : The FTP port for the control session - default is 21.
            'logger' : The console/file logger to use. May be omitted.
            'host_keys' : The path to the SSH host keys file - default
                          searches in well known places.
        """
        try:
            self.host = kwargs['host']
        except KeyError:
            raise SFtpException(_("Error opening SFTP connection: no host given"))
        try:
            self.port = kwargs['port']
        except KeyError:
            raise SFtpException(_("Error opening SFTP connection: no port given"))
        try:
            self.logger = kwargs['logger']
        except KeyError:
            self.logger = None

        self.dispatcher = SFTPDispatcher(**kwargs)
        self.dispatcher.start()

    def setPassive(self, passive):
        """This has no meaning for the SFTP."""
        pass

    def getPassive(self):
        """Always returns True."""
        return True

    def getDispatcher(self):
        """Returns the dispatcher for this SFTP session."""
        return self.dispatcher

    def destroy(self):
        """Destroys the SFTP session."""
        self.dispatcher.destroy()

    def busy(self):
        """Returns True if the dispatcher is currently busy executing a command."""
        return self.dispatcher.busy()

    def addOutgoing(self, cmd, err_handler=None):
        """Adds an outgoing SFTP command to the dispatch queue.

        If a handler is specified, then it is set as the error handler on the command
        object. Otherwise, a default error logger that prints to the console is used."""
        if err_handler is None:
            if self.logger is not None:
                handler = libftpcube.dispatcher.ErrorLogger(self.logger)
                cmd.setErrorHandler(handler)
        else:
            cmd.setErrorHandler(err_handler)
        self.dispatcher.dispatch(cmd)

    def initiateConnect(self, err_handler=None):
        """Initiates an outbound SFTP connection."""
        connect = SFTPConnect()
        self.addOutgoing(connect, err_handler)

    def getWelcomeMessage(self, err_handler=None):
        """Empty implementation.

        This command has no meaning in SFTP."""
        pass

    def login(self, username, password, err_handler=None):
        """Performs a login to the SSH session.

        The specified username and password are used for the login. As a result of the
        login, an SFTP client session is opened."""
        login = SFTPLogin(username, password)
        self.addOutgoing(login, err_handler)

    def noop(self, err_handler=None):
        """Sends a NOOP command to the SFTP session."""
        noop = SFTPNOOP()
        self.addOutgoing(noop, err_handler)

    def cwd(self, dir, err_handler=None):
        """Changes the current working directory to the specified directory."""
        cwdcmd = SFTPCwd(dir)
        self.addOutgoing(cwdcmd, err_handler)

    def pwd(self, status=None, err_handler=None):
        """Gets the current working directory.

        The specified status object is updated with the data received for the current
        working directory."""
        pwdcmd = SFTPPwd(status=status)
        self.addOutgoing(pwdcmd, err_handler)

    def delete(self, file, err_handler=None):
        delcmd = SFTPDelete(file)
        self.addOutgoing(delcmd, err_handler)

    def rename(self, name, new_name, err_handler=None):
        """Performs a file rename for a file in the current directory."""
        recmd = SFTPRename(name, new_name)
        self.addOutgoing(recmd, err_handler)

    def mkdir(self, dir, status=None, err_handler=None):
        """Creates the specified directory.

        The specified status object is updated with the new directory path."""
        mkcmd = SFTPMkdir(dir, status=status)
        self.addOutgoing(mkcmd, err_handler)

    def rmdir(self, dir, err_handler=None):
        """Removes the specified directory."""
        rmcmd = SFTPRmdir(dir)
        self.addOutgoing(rmcmd, err_handler)

    def chmod(self, mode, file, err_handler=None):
        """Changes the permissions to the specified mode on the specified file.

        Permissions are in octal form, as is used on unix."""
        chmodcmd = SFTPChmod(file, mode)
        self.addOutgoing(chmodcmd, err_handler)

    def abort(self, err_handler=None):
        """Performs an abort of the current running command if possible."""
        executing = self.dispatcher.getExecutingCommand()
        if isinstance(executing, SFTPTransfer):
            executing.abort()
        self.dispatcher.resetQueue()
        if isinstance(executing, SFTPConnect):
            self.dispatcher.destroy()

    def list(self, args=None, status=None, passive=True, err_handler=None):
        """Gets a listing of the current directory.

        This implementation ignores the 'args' and 'passive' arguments."""
        listcmd = SFTPList(status=status)
        self.addOutgoing(listcmd, err_handler)

    def retrieveAscii(self, file, local_dir, status=None, passive=True, err_handler=None):
        """Performs the retrieval of an ASCII file.

        The retrieved file is stored in the specified local directory, under the supplied
        file name. The status object is updated with the file transfer events, including
        the amount of data transfered (for each line transfered)."""
        local_file = os.path.join(local_dir, file)
        asciicmd = SFTPAsciiTransfer(file, local_file, status=status)
        self.addOutgoing(asciicmd, err_handler)

    def uploadAscii(self, file, local_dir, status=None, passive=None, err_handler=None):
        """Performs an upload of a local ASCII file.

        The specified file in the specified local directory is uploaded in ASCII format
        to the FTP server. The status object is updated with the file transfer events,
        including the amount of data transfered (for each line transfered)."""
        local_file = os.path.join(local_dir, file)
        asciicmd = SFTPAsciiTransfer(file, local_file, download=False, status=status)
        self.addOutgoing(ascicmd, err_handler)

    def retrieveBinary(self, file, local_dir, status=None, blocksize=8192, rest=None,
                       passive=True, err_handler=None):
        """Performs a download of a binary file.

        The retrieved file is stored in the specified local directory, under the supplied
        file name. The status object is updated with the file transfer events, including
        the amount of data transfered (for each block transfered). The rest argument
        is the byte offset of the file used to resume transfers. A rest of None indicates
        to download the whole file (overwriting the local copy)."""
        local_file = os.path.join(local_dir, file)
        binarycmd = SFTPBinaryTransfer(file, local_file, status=status, blocksize=blocksize,
                                       rest=rest)
        self.addOutgoing(binarycmd, err_handler)

    def uploadBinary(self, file, local_dir, status=None, blocksize=8192, rest=None,
                     passive=True, err_handler=None):
        """Performs an upload of a binary file.

        The specified file in the specified local directory is uploaded in binary format
        to the FTP server. The status object is updated with the file transfer events,
        including the amount of data transfered (for each block transfered). The rest
        argument is the byte offset of the file used to resume transfers. A rest of None
        indicates that the whole file should be uploaded (overwriting the remote copy).
        """
        local_file = os.path.join(local_dir, file)
        binarycmd = SFTPBinaryTransfer(file, local_file, download=False, status=status,
                                       blocksize=blocksize, rest=rest)
        self.addOutgoing(binarycmd, err_handler)
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.