diff options
author | Barry Warsaw <barry@python.org> | 2000-09-01 06:09:23 (GMT) |
---|---|---|
committer | Barry Warsaw <barry@python.org> | 2000-09-01 06:09:23 (GMT) |
commit | 100d81e8e3d06a82a6d9cefee209ac7862951720 (patch) | |
tree | 904ce1f132a2927fe801fb15415e3144b84b0012 /Lib | |
parent | e0d9a83bea5f78964217fd1f2dd82027841c9444 (diff) | |
download | cpython-100d81e8e3d06a82a6d9cefee209ac7862951720.zip cpython-100d81e8e3d06a82a6d9cefee209ac7862951720.tar.gz cpython-100d81e8e3d06a82a6d9cefee209ac7862951720.tar.bz2 |
Added support for RFC 959's REST command (restart), closing SF patch
#101187, which some modifications. Specifically,
ntransfercmd(), transfercmd(), and retrbinary() all grow an optional
`rest' argument, which if not None, is used as the argument to an FTP
REST comman dbefore the socket is returned. Differences from the SF
patch:
- always compare against None with `is' or `is not' instead of == or !=
- no parens around conditional
- RFC 959 defines the argument to REST is a string containing any
ASCII characters in the range [33..126]. Therefore, we use the %s
format character instead of %f or %d as suggested in the patch's
comments. Note that we do /not/ sanity checkthe contents of the
rest argument (but we'll document this in the library reference
manual).
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/ftplib.py | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/Lib/ftplib.py b/Lib/ftplib.py index a15c412..429e834 100644 --- a/Lib/ftplib.py +++ b/Lib/ftplib.py @@ -1,7 +1,6 @@ """An FTP client class and some helper functions. -Based on RFC 959: File Transfer Protocol -(FTP), by J. Postel and J. Reynolds +Based on RFC 959: File Transfer Protocol (FTP), by J. Postel and J. Reynolds Example: @@ -235,7 +234,9 @@ class FTP: return self.voidresp() def sendport(self, host, port): - '''Send a PORT command with the current host and the given port number.''' + '''Send a PORT command with the current host and the given + port number. + ''' hbytes = string.splitfields(host, '.') pbytes = [`port/256`, `port%256`] bytes = hbytes + pbytes @@ -253,25 +254,35 @@ class FTP: resp = self.sendport(host, port) return sock - def ntransfercmd(self, cmd): - '''Initiate a transfer over the data connection. - If the transfer is active, send a port command and - the transfer command, and accept the connection. - If the server is passive, send a pasv command, connect - to it, and start the transfer command. - Either way, return the socket for the connection and - the expected size of the transfer. The expected size - may be None if it could not be determined.''' + def ntransfercmd(self, cmd, rest=None): + """Initiate a transfer over the data connection. + + If the transfer is active, send a port command and the + transfer command, and accept the connection. If the server is + passive, send a pasv command, connect to it, and start the + transfer command. Either way, return the socket for the + connection and the expected size of the transfer. The + expected size may be None if it could not be determined. + + Optional `rest' argument can be a string that is sent as the + argument to a RESTART command. This is essentially a server + marker used to tell the server to skip over any data up to the + given marker. + """ size = None if self.passiveserver: host, port = parse227(self.sendcmd('PASV')) - conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + conn=socket.socket(socket.AF_INET, socket.SOCK_STREAM) conn.connect((host, port)) + if rest is not None: + self.sendcmd("REST %s" % rest) resp = self.sendcmd(cmd) if resp[0] <> '1': raise error_reply, resp else: sock = self.makeport() + if rest is not None: + self.sendcmd("REST %s" % rest) resp = self.sendcmd(cmd) if resp[0] <> '1': raise error_reply, resp @@ -281,10 +292,9 @@ class FTP: size = parse150(resp) return conn, size - def transfercmd(self, cmd): - '''Initiate a transfer over the data connection. Returns - the socket for the connection. See also ntransfercmd().''' - return self.ntransfercmd(cmd)[0] + def transfercmd(self, cmd, rest=None): + """Like nstransfercmd() but returns only the socket.""" + return self.ntransfercmd(cmd, rest)[0] def login(self, user = '', passwd = '', acct = ''): '''Login, default anonymous.''' @@ -312,13 +322,18 @@ class FTP: raise error_reply, resp return resp - def retrbinary(self, cmd, callback, blocksize=8192): - '''Retrieve data in binary mode. - The argument is a RETR command. - The callback function is called for each block. - This creates a new port for you''' + def retrbinary(self, cmd, callback, blocksize=8192, rest=None): + """Retrieve data in binary mode. + + `cmd' is a RETR command. `callback' is a callback function is + called for each block. No more than `blocksize' number of + bytes will be read from the socket. Optional `rest' is passed + to transfercmd(). + + A new port is created for you. Return the response code. + """ self.voidcmd('TYPE I') - conn = self.transfercmd(cmd) + conn = self.transfercmd(cmd, rest) while 1: data = conn.recv(blocksize) if not data: |