lua-users home
lua-l archive

[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