[issue25458] ftplib: command response shift - mismatch
Peter Pan added the comment: Here is a small test for the new version. (To see the original ftplib.py version failing copy+paste the code from my initial post into a python file and run) -- Added file: http://bugs.python.org/file42100/test_ftp.py ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue25458> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue25458] ftplib: command response shift - mismatch
Peter Pan added the comment: I've updated "ftplib.py" from the 3.5.1 source code release. This should fix issues: http://bugs.python.org/issue25458 http://bugs.python.org/issue25491 -- Added file: http://bugs.python.org/file42099/ftplib.py ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue25458> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue25458] ftplib: command response shift - mismatch
Peter Pan added the comment: The problem in my example is ftplib reports a "226" response to command "NOOP" which is nonsense. ftplib received "226" before "ftp.sendcmd('NOOP')" was called. Since "transfercmd()" returns a socket, ftplib was planned to allow for manual transfer socket handling, but it is currently unable to handle the asynchronous responses from the server when the transfer is done. This is a bug or design error. Multiple changes are needed to support manual transfer socket handling. I suggest the following: Since asynchronous responses from the server are possible on the command socket, "set_debuglevel(1)" must report them at once, but this would require multithreading. A good compromise is to debug print and clear any buffered status right before sending the next command. We also need a method to check the last status code, in order to know the result of the last manual transfer. ftplib has to store it separately as an attribute. New attribute - this.last_status_code = None #has no effect to any command or debug output this.last_status_message New internal method --- #loop: look for buffered status response; if present, print debug and assign this.last_status = buffer.pop() .unbuffer(): ... New user methods #Set last status to None so we can use "get_last_status" to check/poll for the next one. .clear_last_status(): this.last_status_code = None this.last_status_message = "" return #Return the last status received from the server; if there is one on the buffer, unbuffer and return that. .get_last_status(): this.unbuffer() return [this.last_status_code, this.last_status_message] -- ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue25458> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue25458] ftplib: command response shift - mismatch
New submission from Peter Pan: When handling the transfer socket manually the asynchronous status message "226 transfer complete" on the control socket is falsely taken as response for the last sent command. ftplib reads the response too late and the command/response order becomes invalid. I can avoid that by using the undocumented ftplib internal method FTP.getline() after the transfer socket is closed and not sending more commands while the transfer socket is open. It would be useful, if ftplib empties the response socket buffer before sending the next command. But maybe the best solution is an optional function callback when the "226" response appears, while it is ignored when not matching the last sent command. Example code that triggers the problem: import ftplib import socket import re ftp = ftplib.FTP() ftp.set_debuglevel(1) ftp.connect('ftp.debian.org', timeout=10) ftp.login('anonymous','u...@example.com') ftp.sendcmd('TYPE A') s = ftp.transfercmd('LIST') ''' #manual transfer socket - should result in same behaviour r = ftp.sendcmd('EPSV') r = re.search('\|([0-9]+)\|', r) port = int( r.group(1) ) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(('ftp.debian.org', port)) ftp.sendcmd('LIST') ''' fp = s.makefile('r') fp.read() fp.close() s.close() #ftplib falsely sees "226 transfer complete" as response to next command ftp.sendcmd('NOOP') -- components: Library (Lib) messages: 253326 nosy: peterpan priority: normal severity: normal status: open title: ftplib: command response shift - mismatch type: behavior versions: Python 3.4 ___ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue25458> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com