[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-157]

change SubsystemHandler/SFTPServerInterface API
change the API of SubsystemHandler to accept a reference to the
ServerInstance object during construction.  this will break all code
that currently creates subsystem handlers (like sftp servers) -- sorry!

lots of little doc fixups (mostly indenting).
This commit is contained in:
Robey Pointer 2005-04-06 07:24:28 +00:00
parent 5d8d1938fa
commit 71a337ee08
5 changed files with 80 additions and 59 deletions

View File

@ -72,10 +72,10 @@ class ServerInterface (object):
C{OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED}.
@param kind: the kind of channel the client would like to open
(usually C{"session"}).
(usually C{"session"}).
@type kind: str
@param chanid: ID of the channel, required to create a new L{Channel}
object.
object.
@type chanid: int
@return: a success or failure code (listed above).
@rtype: int
@ -115,7 +115,7 @@ class ServerInterface (object):
@param username: the username of the client.
@type username: str
@return: L{AUTH_FAILED} if the authentication fails;
L{AUTH_SUCCESSFUL} if it succeeds.
L{AUTH_SUCCESSFUL} if it succeeds.
@rtype: int
"""
return AUTH_FAILED
@ -140,9 +140,9 @@ class ServerInterface (object):
@param password: the password given by the client.
@type password: str
@return: L{AUTH_FAILED} if the authentication fails;
L{AUTH_SUCCESSFUL} if it succeeds;
L{AUTH_PARTIALLY_SUCCESSFUL} if the password auth is
successful, but authentication must continue.
L{AUTH_SUCCESSFUL} if it succeeds;
L{AUTH_PARTIALLY_SUCCESSFUL} if the password auth is
successful, but authentication must continue.
@rtype: int
"""
return AUTH_FAILED
@ -173,9 +173,9 @@ class ServerInterface (object):
@param key: the key object provided by the client.
@type key: L{PKey <pkey.PKey>}
@return: L{AUTH_FAILED} if the client can't authenticate
with this key; L{AUTH_SUCCESSFUL} if it can;
L{AUTH_PARTIALLY_SUCCESSFUL} if it can authenticate with
this key but must continue with authentication.
with this key; L{AUTH_SUCCESSFUL} if it can;
L{AUTH_PARTIALLY_SUCCESSFUL} if it can authenticate with
this key but must continue with authentication.
@rtype: int
"""
return AUTH_FAILED
@ -230,13 +230,13 @@ class ServerInterface (object):
@param height: height of screen in characters.
@type height: int
@param pixelwidth: width of screen in pixels, if known (may be C{0} if
unknown).
unknown).
@type pixelwidth: int
@param pixelheight: height of screen in pixels, if known (may be C{0}
if unknown).
if unknown).
@type pixelheight: int
@return: C{True} if the psuedo-terminal has been allocated; C{False}
otherwise.
otherwise.
@rtype: bool
"""
return False
@ -253,7 +253,7 @@ class ServerInterface (object):
@param channel: the L{Channel} the pty request arrived on.
@type channel: L{Channel}
@return: C{True} if this channel is now hooked up to a shell; C{False}
if a shell can't or won't be provided.
if a shell can't or won't be provided.
@rtype: bool
"""
return False
@ -292,21 +292,21 @@ class ServerInterface (object):
C{True}. Otherwise it returns C{False}.
@note: Because the default implementation uses the L{Transport} to
identify valid subsystems, you probably won't need to override this
method.
identify valid subsystems, you probably won't need to override this
method.
@param channel: the L{Channel} the pty request arrived on.
@type channel: L{Channel}
@param name: name of the requested subsystem.
@type name: str
@return: C{True} if this channel is now hooked up to the requested
subsystem; C{False} if that subsystem can't or won't be provided.
subsystem; C{False} if that subsystem can't or won't be provided.
@rtype: bool
"""
handler_class, larg, kwarg = channel.get_transport()._get_subsystem_handler(name)
if handler_class is None:
return False
handler = handler_class(channel, name, *larg, **kwarg)
handler = handler_class(channel, name, self, *larg, **kwarg)
handler.start()
return True
@ -324,10 +324,10 @@ class ServerInterface (object):
@param height: height of screen in characters.
@type height: int
@param pixelwidth: width of screen in pixels, if known (may be C{0} if
unknown).
unknown).
@type pixelwidth: int
@param pixelheight: height of screen in pixels, if known (may be C{0}
if unknown).
if unknown).
@type pixelheight: int
@return: C{True} if the terminal was resized; C{False} if not.
@rtype: bool
@ -353,7 +353,7 @@ class SubsystemHandler (threading.Thread):
@since: ivysaur
"""
def __init__(self, channel, name):
def __init__(self, channel, name, server):
"""
Create a new handler for a channel. This is used by L{ServerInterface}
to start up a new handler when a channel requests this subsystem. You
@ -365,11 +365,24 @@ class SubsystemHandler (threading.Thread):
@type channel: L{Channel}
@param name: name of the requested subsystem.
@type name: str
@param server: the server object for the session that started this
subsystem
@rtype server: L{ServerInterface}
"""
threading.Thread.__init__(self, target=self._run)
self.__channel = channel
self.__transport = channel.get_transport()
self.__name = name
self.__server = server
def get_server(self):
"""
Return the L{ServerInterface} object associated with this channel and
subsystem.
@rtype: L{ServerInterface}
"""
return self.__server
def _run(self):
try:
@ -396,12 +409,11 @@ class SubsystemHandler (threading.Thread):
corresponds to exactly one L{Channel} on one L{Transport}.
@note: It is the responsibility of this method to exit if the
underlying L{Transport} is closed. This can be done by checking
L{Transport.is_active <BaseTransport.is_active>} or noticing an EOF
on the L{Channel}.
If this method loops forever without checking for this case, your
python interpreter may refuse to exit because this thread will still
be running.
underlying L{Transport} is closed. This can be done by checking
L{Transport.is_active <BaseTransport.is_active>} or noticing an EOF
on the L{Channel}. If this method loops forever without checking
for this case, your python interpreter may refuse to exit because
this thread will still be running.
@param name: name of the requested subsystem.
@type name: str

View File

@ -37,37 +37,35 @@ class SFTPServer (BaseSFTP, SubsystemHandler):
Use L{Transport.set_subsystem_handler} to activate this class.
"""
def __init__(self, channel, name, server=SFTPServerInterface, server_args=None):
def __init__(self, channel, name, server, sftp_si=SFTPServerInterface, *largs, **kwargs):
"""
The constructor for SFTPServer is meant to be called from within the
L{Transport} as a subsystem handler. The C{server} and C{server_args}
parameters are passed from the original call to
L{Transport} as a subsystem handler. C{server} and any additional
parameters or keyword parameters are passed from the original call to
L{Transport.set_subsystem_handler}.
@param channel: channel passed from the L{Transport}.
@type channel: L{Channel}
@param name: name of the requested subsystem.
@type name: str
@param server: a subclass of L{SFTPServerInterface} to use for handling
individual requests.
@type server: class
@param server_args: keyword parameters to pass to C{server} when it's
constructed.
@type server_args: dict
"""
@param server: the server object associated with this channel and
subsystem
@type server: L{ServerInterface}
@param sftp_si: a subclass of L{SFTPServerInterface} to use for handling
individual requests.
@type sftp_si: class
"""
BaseSFTP.__init__(self)
SubsystemHandler.__init__(self, channel, name)
SubsystemHandler.__init__(self, channel, name, server)
transport = channel.get_transport()
self.logger = util.get_logger(transport.get_log_channel() + '.' +
channel.get_name() + '.sftp')
channel.get_name() + '.sftp')
self.ultra_debug = transport.ultra_debug
self.next_handle = 1
# map of handle-string to SFTPHandle for files & folders:
self.file_table = { }
self.folder_table = { }
if server_args is None:
server_args = {}
self.server = server(**server_args)
self.server = sftp_si(server, *largs, **kwargs)
def start_subsystem(self, name, transport, channel):
self.sock = channel

View File

@ -37,6 +37,17 @@ class SFTPServerInterface (object):
session to abruptly end, so you will usually want to catch exceptions and
return an appropriate error code.
"""
def __init__ (self, server, *largs, **kwargs):
"""
Create a new SFTPServerInterface object. This method does nothing by
default and is meant to be overridden by subclasses.
@param server: the server object associated with this channel and
SFTP subsystem
@type server: L{ServerInterface}
"""
super(SFTPServerInterface, self).__init__(*largs, **kwargs)
def session_started(self):
"""
@ -80,13 +91,13 @@ class SFTPServerInterface (object):
the client didn't specify them.
@note: The SFTP protocol defines all files to be in "binary" mode.
There is no equivalent to python's "text" mode.
There is no equivalent to python's "text" mode.
@param path: the requested path (relative or absolute) of the file
to be opened.
to be opened.
@type path: str
@param flags: flags or'd together from the C{os} module indicating the
requested mode for opening the file.
requested mode for opening the file.
@type flags: int
@param attr: requested attributes of the file if it is newly created.
@type attr: L{SFTPAttributes}
@ -114,7 +125,7 @@ class SFTPServerInterface (object):
@param path: the requested path (relative or absolute) to be listed.
@type path: str
@return: a list of the files in the given folder, using
L{SFTPAttributes} objects.
L{SFTPAttributes} objects.
@rtype: list of L{SFTPAttributes} I{or error code}
@note: You should normalize the given C{path} first (see the
@ -133,10 +144,10 @@ class SFTPServerInterface (object):
call that doesn't follow symlinks/aliases.)
@param path: the requested path (relative or absolute) to fetch
file statistics for.
file statistics for.
@type path: str
@return: an attributes object for the given file, or an SFTP error
code (like L{SFTP_PERMISSION_DENIED}).
code (like L{SFTP_PERMISSION_DENIED}).
@rtype: L{SFTPAttributes} I{or error code}
"""
return SFTP_OP_UNSUPPORTED
@ -150,10 +161,10 @@ class SFTPServerInterface (object):
corresponding call that follows symlinks/aliases.)
@param path: the requested path (relative or absolute) to fetch
file statistics for.
file statistics for.
@type path: str
@return: an attributes object for the given file, or an SFTP error
code (like L{SFTP_PERMISSION_DENIED}).
code (like L{SFTP_PERMISSION_DENIED}).
@rtype: L{SFTPAttributes} I{or error code}
"""
return SFTP_OP_UNSUPPORTED
@ -163,7 +174,7 @@ class SFTPServerInterface (object):
Delete a file, if possible.
@param path: the requested path (relative or absolute) of the file
to delete.
to delete.
@type path: str
@return: an SFTP error code like L{SFTP_OK}.
@rtype: int
@ -179,11 +190,11 @@ class SFTPServerInterface (object):
files that cross disk partition boundaries, if at all possible.
@note: You should return an error if a file with the same name as
C{newpath} already exists. (The rename operation should be
non-desctructive.)
C{newpath} already exists. (The rename operation should be
non-desctructive.)
@param oldpath: the requested path (relative or absolute) of the
existing file.
existing file.
@type oldpath: str
@param newpath: the requested new path of the file.
@type newpath: str
@ -203,7 +214,7 @@ class SFTPServerInterface (object):
object may be completely empty.
@param path: requested path (relative or absolute) of the new
folder.
folder.
@type path: str
@param attr: requested attributes of the new folder.
@type attr: L{SFTPAttributes}
@ -219,7 +230,7 @@ class SFTPServerInterface (object):
error.
@param path: requested path (relative or absolute) of the folder
to remove.
to remove.
@type path: str
@return: an SFTP error code like L{SFTP_OK}.
@rtype: int
@ -233,7 +244,7 @@ class SFTPServerInterface (object):
should check for the presence of fields before using them.
@param path: requested path (relative or absolute) of the file to
change.
change.
@type path: str
@param attr: requested attributes to change on the file.
@type attr: L{SFTPAttributes}

View File

@ -762,7 +762,7 @@ class BaseTransport (threading.Thread):
def set_subsystem_handler(self, name, handler, *larg, **kwarg):
"""
Set the handler class for a subsystem in server mode. If a reqeuest
Set the handler class for a subsystem in server mode. If a request
for this subsystem is made on an open ssh channel later, this handler
will be constructed and called -- see L{SubsystemHandler} for more
detailed documentation.
@ -773,7 +773,7 @@ class BaseTransport (threading.Thread):
@param name: name of the subsystem.
@type name: str
@param handler: subclass of L{SubsystemHandler} that handles this
subsystem.
subsystem.
@type handler: class
"""
try:

View File

@ -56,7 +56,7 @@ class StubSFTPServer (SFTPServerInterface):
# assume current folder is a fine root
# (the tests always create and eventualy delete a subfolder, so there shouldn't be any mess)
ROOT = os.getcwd()
def _realpath(self, path):
return self.ROOT + self.canonicalize(path)