[Twisted-Python] FTP server with credentials
Mayne, Peter
peter.mayne at hp.com
Wed Oct 12 17:50:28 MDT 2005
I'm trying to write a simple FTP server that a client can connect and
authenticate to, then upload a file, which the server buffers in memory
and processes, and then returns a status result to the client depending
on the result of the processing. (Twisted 2.0.1, Python 2.4.1, Windws XP
SP2)
So far I've done this:
<code>
import sys
from twisted.cred import checkers, portal
from twisted.internet import reactor, protocol
from twisted.protocols import ftp
from twisted.python import components, log
class IProtocolUser(components.Interface):
def getPrivileges(self):
"""Return a list of privileges this user has."""
def logout(self):
"""Cleanup per-login resources allocated to this avatar"""
class RegularUser:
__implements__ = (IProtocolUser,)
def getPrivileges(self):
return [1, 2, 3, 5, 6]
def logout(self):
print "Cleaning up regular user resources"
class Realm:
__implements__ = portal.IRealm
def requestAvatar(self, avatarId, mind, *interfaces):
if ftp.IFTPShell in interfaces:
av = RegularUser()
return ftp.IFTPShell, av, av.logout
else:
raise NotImplementedError("Only IFTPShell interface is
supported by this realm")
class MyFtpServer(ftp.FTP):
'''My custom FTP server.'''
def __init__(self, *args, **kw):
super(ftp.FTP, self).__init__(*args, **kw)
self.blockingCommands.remove('PORT')
print 'Removed PORT to allow non-PASV'
def dataReceived(self, data):
'As soon as any data is received, send it to stdout for
debugging.'
sys.stdout.write('\n **[%s]\n' % data)
self.transport.write(data)
def main():
r = Realm()
p = portal.Portal(r)
c = checkers.InMemoryUsernamePasswordDatabaseDontUse()
c.addUser("u", "p")
p.registerChecker(c)
p.registerChecker(checkers.AllowAnonymousAccess())
#log.startLogging(sys.stdout)
factory = ftp.FTPFactory(MyFtpServer())
factory.portal = p
reactor.listenTCP(2121, factory)
reactor.run()
if __name__ == '__main__':
main()
</code>
I can connect and authenticate (using the Windows comman line FTP client
running on the same system), but when I "put myfile.txt" on the client,
the server produces the following:
<output>
C:\>mockftp.py
Removed PORT to allow non-PASV
C:\opt\Python24\lib\site-packages\twisted\protocols\ftp.py:625:
DeprecationWarni
ng: IPv4Address.__getitem__ is deprecated. Use attributes instead.
phost = self.transport.getPeer()[1]
Traceback (most recent call last):
Failure: exceptions.IndexError: tuple index out of range
Traceback (most recent call last):
File
"C:\opt\Python24\lib\site-packages\twisted\internet\selectreactor.py",
li
ne 133, in doSelect
_logrun(selectable, _drdw, selectable, method, dict)
File "C:\opt\Python24\Lib\site-packages\twisted\python\log.py", line
56, in ca
llWithLogger
return callWithContext({"system": lp}, func, *args, **kw)
File "C:\opt\Python24\Lib\site-packages\twisted\python\log.py", line
41, in ca
llWithContext
return context.call({ILogContext: newCtx}, func, *args, **kw)
File "C:\opt\Python24\Lib\site-packages\twisted\python\context.py",
line 31, i
n callWithContext
return func(*args,**kw)
--- <exception caught here> ---
File
"C:\opt\Python24\lib\site-packages\twisted\internet\selectreactor.py",
li
ne 139, in _doReadOrWrite
why = getattr(selectable, method)()
File "C:\opt\Python24\Lib\site-packages\twisted\internet\tcp.py", line
351, in
doRead
return self.protocol.dataReceived(data)
File "C:\opt\Python24\Lib\site-packages\twisted\protocols\basic.py",
line 221,
in dataReceived
why = self.lineReceived(line)
File "C:\opt\Python24\lib\site-packages\twisted\protocols\ftp.py",
line 550, i
n lineReceived
self.processCommand(*cmdAndArgs)
File "C:\opt\Python24\lib\site-packages\twisted\protocols\ftp.py",
line 608, i
n processCommand
return method(*args)
File "C:\opt\Python24\lib\site-packages\twisted\protocols\ftp.py",
line 940, i
n ftp_PORT
self._createDTP()
File "C:\opt\Python24\lib\site-packages\twisted\protocols\ftp.py",
line 632, i
n _createDTP
self.dtpPort = reactor.connectTCP(self.dtpHostPort[1],
self.dtpHostPort[2])
exceptions.IndexError: tuple index out of range
Cleaning up regular user resources
</output>
At this point I'm lost. What am I doing wrong?
Thanks.
PJDM
--
Peter Mayne
Technology Consultant
Hewlett-Packard Australia
7-11 Barry Drive, Turner, ACT, 2612
More information about the Twisted-Python
mailing list