Question

I'm trying to use ftplib.FTP_TLS, but I can't list the directories.

Everything is OK with Filezilla, but when I'm on iPython, it fails.

import ftplib
from django.conf import settings  # just a config file


client = ftplib.FTP_TLS(timeout=10)
client.connect(settings.HOST, 21)
client.auth()
client.prot_p()
client.login(settings.USER,settings.PWD)
client.set_debuglevel(2)
client.retrlines('LIST')

Here is the return of this last command :

*cmd* 'TYPE A'
*put* 'TYPE A\r\n'
*get* '200 Type set to A.\r\n'
*resp* '200 Type set to A.'
*cmd* 'PASV'
*put* 'PASV\r\n'
*get* '227 Entering Passive Mode (10,191,x,x,238,54).\r\n'
*resp* '227 Entering Passive Mode (10,191,x,x,238,54).'
---------------------------------------------------------------------------
timeout                                   Traceback (most recent call last)
/usr/local/lib/python2.7/dist-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 client.retrlines('LIST')

/usr/lib/python2.7/ftplib.pyc in retrlines(self, cmd, callback)
704             if callback is None: callback = print_line
705             resp = self.sendcmd('TYPE A')
--> 706             conn = self.transfercmd(cmd)
707             fp = conn.makefile('rb')
708             try:

/usr/lib/python2.7/ftplib.pyc in transfercmd(self, cmd, rest)
366     def transfercmd(self, cmd, rest=None):
367         """Like ntransfercmd() but returns only the socket."""
--> 368         return self.ntransfercmd(cmd, rest)[0]
369 
370     def login(self, user = '', passwd = '', acct = ''):

/usr/lib/python2.7/ftplib.pyc in ntransfercmd(self, cmd, rest)
679 
680         def ntransfercmd(self, cmd, rest=None):
--> 681             conn, size = FTP.ntransfercmd(self, cmd, rest)
682             if self._prot_p:
683                 conn = ssl.wrap_socket(conn, self.keyfile, self.certfile,

/usr/lib/python2.7/ftplib.pyc in ntransfercmd(self, cmd, rest)
325         if self.passiveserver:
326             host, port = self.makepasv()
--> 327             conn = socket.create_connection((host, port), self.timeout)
328             try:
329                 if rest is not None:

/usr/lib/python2.7/socket.pyc in create_connection(address, timeout, source_address)
569 
570     if err is not None:
--> 571         raise err
572     else:
573         raise error("getaddrinfo returns an empty list")

timeout: timed out

Like I said, it works fine with Filezilla. But I can see something special :

Commande :  PASV
Réponse :   227 Entering Passive Mode (10,191,x,x,236,94).
Statut :    Le serveur a envoyé une réponse passive avec une adresse non routable. Adresse remplacée par celle du serveur.

The «Statut» lines means something like: «Server send a passive response with a non routable address. Address replaced by the server one».

It seem this is the way to make it work.

My question is: How can I do the same with ftplib? Or is there another option for me?

Thanks!

Was it helpful?

Solution

Suppose you know where to connect to. I think the key may be in this line 326:

325         if self.passiveserver:
326             host, port = self.makepasv()
--> 327             conn = socket.create_connection((host, port), self.timeout)
328             try:
329                 if rest is not None:

You can subclass and replace the makepasv() method and return the right address. Maybe you can use the output of filezilla or wireshark to get to know the right address.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top