+from types import NoneType
+
from zope.interface import implements
from twisted.application import service, strports
from twisted.internet import defer
from twisted.internet.interfaces import IConsumer
from twisted.cred import portal
+from twisted.python import filepath
from twisted.protocols import ftp
from allmydata.interfaces import IDirectoryNode, ExistingChildError, \
NoSuchChildError
from allmydata.immutable.upload import FileHandle
from allmydata.util.fileutil import EncryptedTemporaryFile
+from allmydata.util.assertutil import precondition
class ReadFile:
implements(ftp.IReadFile)
class NoParentError(Exception):
pass
+# filepath.Permissions was added in Twisted-11.1.0, which we require. Twisted
+# <15.0.0 expected an int, and only does '&' on it. Twisted >=15.0.0 expects
+# a filepath.Permissions. This satisfies both.
+
+class IntishPermissions(filepath.Permissions):
+ def __init__(self, statModeInt):
+ self._tahoe_statModeInt = statModeInt
+ filepath.Permissions.__init__(self, statModeInt)
+ def __and__(self, other):
+ return self._tahoe_statModeInt & other
+
class Handler:
implements(ftp.IFTPShell)
def __init__(self, client, rootnode, username, convergence):
elif key == "directory":
value = isdir
elif key == "permissions":
- value = 0600
+ # Twisted-14.0.2 (and earlier) expected an int, and used it
+ # in a rendering function that did (mode & NUMBER).
+ # Twisted-15.0.0 expects a
+ # twisted.python.filepath.Permissions , and calls its
+ # .shorthand() method. This provides both.
+ value = IntishPermissions(0600)
elif key == "hardlinks":
value = 1
elif key == "modified":
class FTPServer(service.MultiService):
def __init__(self, client, accountfile, accounturl, ftp_portstr):
+ precondition(isinstance(accountfile, (unicode, NoneType)), accountfile)
service.MultiService.__init__(self)
r = Dispatcher(client)