lua-users home
lua-l archive

luasocket passive ftp hack

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


The support for passive ftp in luasocket is partial, at least in what I
downloaded at the end of last month. Since passive ftp is all I can do
from behind my firewall, I had to come up with a cheap trick. In case
anyone else can use it, I explain it below.
The new function is Private.pasv, which is based on Private.port:
 function Private.pasv(control)
 local code,answer = Private.command(control, "pasv", nil, {227})
 if not code then
 print("Private.pasv(): not code: "..answer)
 control:close()
 end
 local host,port = Private.get_pasv(answer)
 if not host or not port then
 return nil,"couldn't extract host/port from: "..answer
 end
 server,answer = socket.tcp()
 if not server then return nil,answer end
 ret,err = server:connect(host,port)
 if not ret then return nil,err end
 return server
 end
Private.get_pasv() is the support for passive ftp that exists in my
copy of luasocket. Private.pasv gets called in Private.download:
@@ -488,7 +499,7 @@
 		return "Invalid file path" 
 	end
 	-- setup passive connection
-	local server, answer = Private.port(control)
+	local server, answer = Private.pasv(control)
 	if not server then return answer end
 	-- ask server to send file or directory listing
 	code, answer = Private.retrieve(control, server, name, 
Note the comment just before the line I changed. When I first read it
I thought: Maybe an honest implementation of passive ftp is planned
sometime! :) But no, the *connection* *is* passive, so the comment's
correct. The passive ftp I mean is getting the server to play the
passive role in the data connection. Anyway, the hackery really shows
in Private.retrieve:
@@ -292,18 +309,12 @@
 		code, answer = Private.command(control, "retr", name, {150, 125}) 
 	end
 	if not code then return nil, answer end
-	data, answer = server:accept()
-	server:close()
-	if not data then 
-		control:close()
-		return answer 
-	end
-	answer = Private.receive_indirect(data, content_cb)
+	answer = Private.receive_indirect(server, content_cb)
 	if answer then 
 		control:close()
 		return answer
 	end
-	data:close()
+	server:close() -- perhaps unnecessary
 	-- make sure file transfered ok
 	return Private.check_answer(control, {226, 250})
 end
Pretty icky/lazy, but it Works For Me and uploading should be similar
when needed.
Cheers,
Steve

AltStyle によって変換されたページ (->オリジナル) /