@@ -245,13 +245,16 @@ def makeport(self):
245245 resp = self .sendport (host , port )
246246 return sock
247247
248- def transfercmd (self , cmd ):
248+ def ntransfercmd (self , cmd ):
249249 '''Initiate a transfer over the data connection.
250250 If the transfer is active, send a port command and
251251 the transfer command, and accept the connection.
252252 If the server is passive, send a pasv command, connect
253253 to it, and start the transfer command.
254- Either way, return the socket for the connection'''
254+ Either way, return the socket for the connection and
255+ the expected size of the transfer. The expected size
256+ may be None if it could not be determined.'''
257+ size = None
255258 if self .passiveserver :
256259 host , port = parse227 (self .sendcmd ('PASV' ))
257260 conn = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
@@ -265,7 +268,15 @@ def transfercmd(self, cmd):
265268 if resp [0 ] <> '1' :
266269 raise error_reply , resp
267270 conn , sockaddr = sock .accept ()
268- return conn
271+ if resp [:3 ] == '150' :
272+ # this is conditional in case we received a 125
273+ size = parse150 (resp )
274+ return conn , size
275+
276+ def transfercmd (self , cmd ):
277+ '''Initiate a transfer over the data connection. Returns
278+ the socket for the connection. See also ntransfercmd().'''
279+ return self .ntransfercmd (cmd )[0 ]
269280
270281 def login (self , user = '' , passwd = '' , acct = '' ):
271282 '''Login, default anonymous.'''
@@ -450,6 +461,22 @@ def close(self):
450461 del self .file , self .sock
451462
452463
464+ import regex
465+ _150_re = regex .compile ("150 .* (\([0-9][0-9]*\) bytes)" , regex .casefold )
466+
467+ def parse150 (resp ):
468+ '''Parse the '150' response for a RETR request.
469+ Returns the expected transfer size or None; size is not guaranteed to
470+ be present in the 150 message.
471+ '''
472+ if resp [:3 ] != '150' :
473+ raise error_reply , resp
474+ length = _150_re .match (resp )
475+ if length >= 0 :
476+ return string .atoi (_150_re .group (1 ))
477+ return None
478+
479+
453480def parse227 (resp ):
454481 '''Parse the '227' response for a PASV request.
455482 Raises error_proto if it does not contain '(h1,h2,h3,h4,p1,p2)'
0 commit comments