Commit c5d09ac3 by willmcgugan

Docstrings and fixes for sftp server

parent 742ff4a6
...@@ -57,6 +57,16 @@ Serves the contents of PATH with one of a number of methods""" ...@@ -57,6 +57,16 @@ Serves the contents of PATH with one of a number of methods"""
elif options.type == 'sftp': elif options.type == 'sftp':
from fs.expose.sftp import BaseSFTPServer from fs.expose.sftp import BaseSFTPServer
import logging
log = logging.getLogger('paramiko')
if options.debug:
log.setLevel(logging.DEBUG)
elif options.verbose:
log.setLevel(logging.INFO)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
log.addHandler(ch)
if port is None: if port is None:
port = 22 port = 22
server = BaseSFTPServer((options.addr, port), fs) server = BaseSFTPServer((options.addr, port), fs)
......
__all__ = ["serve_fs"]
import SimpleHTTPServer import SimpleHTTPServer
import SocketServer import SocketServer
from fs.path import pathjoin, dirname from fs.path import pathjoin, dirname
...@@ -126,7 +128,15 @@ class FSHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): ...@@ -126,7 +128,15 @@ class FSHTTPRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
return path return path
def serve_fs(fs, address='', port=8000): def serve_fs(fs, address='', port=8000):
"""Serve an FS instance over http
:param fs: an FS object
:param address: IP address to serve on
:param port: port number
"""
def Handler(request, client_address, server): def Handler(request, client_address, server):
return FSHTTPRequestHandler(fs, request, client_address, server) return FSHTTPRequestHandler(fs, request, client_address, server)
......
...@@ -37,6 +37,7 @@ from fs.path import * ...@@ -37,6 +37,7 @@ from fs.path import *
from fs.errors import * from fs.errors import *
from fs.local_functools import wraps from fs.local_functools import wraps
from fs.filelike import StringIO from fs.filelike import StringIO
from fs.utils import isdir
# Default host key used by BaseSFTPServer # Default host key used by BaseSFTPServer
...@@ -52,8 +53,8 @@ def report_sftp_errors(func): ...@@ -52,8 +53,8 @@ def report_sftp_errors(func):
""" """
@wraps(func) @wraps(func)
def wrapper(*args,**kwds): def wrapper(*args,**kwds):
try: try:
return func(*args,**kwds) return func(*args,**kwds)
except ResourceNotFoundError, e: except ResourceNotFoundError, e:
return paramiko.SFTP_NO_SUCH_FILE return paramiko.SFTP_NO_SUCH_FILE
except UnsupportedError, e: except UnsupportedError, e:
...@@ -94,23 +95,38 @@ class SFTPServerInterface(paramiko.SFTPServerInterface): ...@@ -94,23 +95,38 @@ class SFTPServerInterface(paramiko.SFTPServerInterface):
path = path.decode(self.encoding) path = path.decode(self.encoding)
stats = [] stats = []
for entry in self.fs.listdir(path,absolute=True): for entry in self.fs.listdir(path,absolute=True):
stats.append(self.stat(entry)) stat = self.stat(entry)
if not isinstance(stat, int):
stats.append(stat)
return stats return stats
@report_sftp_errors @report_sftp_errors
def stat(self, path): def stat(self, path):
if not isinstance(path, unicode): if not isinstance(path, unicode):
path = path.decode(self.encoding) path = path.decode(self.encoding)
info = self.fs.getinfo(path) info = self.fs.getinfo(path)
get = info.get
stat = paramiko.SFTPAttributes() stat = paramiko.SFTPAttributes()
stat.filename = basename(path).encode(self.encoding) stat.filename = basename(path).encode(self.encoding)
stat.st_size = info.get("size") stat.st_size = info.get("size")
stat.st_atime = time.mktime(info.get("accessed_time").timetuple())
stat.st_mtime = time.mktime(info.get("modified_time").timetuple()) if 'st_atime' in info:
if self.fs.isdir(path): stat.st_atime = get('st_atime')
elif 'accessed_time' in info:
stat.st_atime = time.mktime(get("accessed_time").timetuple())
if 'st_mtime' in info:
stat.st_mtime = get('st_mtime')
else:
if 'modified_time' in info:
stat.st_mtime = time.mktime(get("modified_time").timetuple())
if isdir(self.fs, path, info):
stat.st_mode = 0777 | statinfo.S_IFDIR stat.st_mode = 0777 | statinfo.S_IFDIR
else: else:
stat.st_mode = 0777 | statinfo.S_IFREG stat.st_mode = 0777 | statinfo.S_IFREG
return stat return stat
def lstat(self, path): def lstat(self, path):
...@@ -288,11 +304,11 @@ class BaseSFTPServer(sockserv.TCPServer,paramiko.ServerInterface): ...@@ -288,11 +304,11 @@ class BaseSFTPServer(sockserv.TCPServer,paramiko.ServerInterface):
return paramiko.AUTH_FAILED return paramiko.AUTH_FAILED
def get_allowed_auths(self,username): def get_allowed_auths(self,username):
"""Return list of allowed auth modes. """Return string containing a comma separated list of allowed auth modes.
The available modes are "node", "password" and "publickey". The available modes are "node", "password" and "publickey".
""" """
return ("none",) return "none"
# When called from the command-line, expose a TempFS for testing purposes # When called from the command-line, expose a TempFS for testing purposes
......
...@@ -143,15 +143,18 @@ class SFTPFS(FS): ...@@ -143,15 +143,18 @@ class SFTPFS(FS):
if not connection.is_authenticated(): if not connection.is_authenticated():
try: try:
if pkey: if pkey:
connection.auth_publickey(username, pkey) connection.auth_publickey(username, pkey)
if not connection.is_authenticated() and password: if not connection.is_authenticated() and password:
connection.auth_password(username, password) connection.auth_password(username, password)
if agent_auth and not connection.is_authenticated(): if agent_auth and not connection.is_authenticated():
self._agent_auth(connection, username) self._agent_auth(connection, username)
if not connection.is_authenticated():
connection.auth_none('')
if not connection.is_authenticated(): if not connection.is_authenticated():
connection.close() connection.close()
raise RemoteConnectionError('no auth') raise RemoteConnectionError('no auth')
...@@ -327,7 +330,7 @@ class SFTPFS(FS): ...@@ -327,7 +330,7 @@ class SFTPFS(FS):
raise ResourceNotFoundError(path) raise ResourceNotFoundError(path)
elif self.isfile(path): elif self.isfile(path):
raise ResourceInvalidError(path,msg="Can't list directory contents of a file: %(path)s") raise ResourceInvalidError(path,msg="Can't list directory contents of a file: %(path)s")
raise raise
if attrs_map: if attrs_map:
if dirs_only: if dirs_only:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment