aboutsummaryrefslogtreecommitdiff
path: root/src/ftp.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/ftp.lua')
-rw-r--r--src/ftp.lua53
1 files changed, 43 insertions, 10 deletions
diff --git a/src/ftp.lua b/src/ftp.lua
index 9902c88..4529acd 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -8,13 +8,15 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9-- Declare module and import dependencies 9-- Declare module and import dependencies
10----------------------------------------------------------------------------- 10-----------------------------------------------------------------------------
11local base = require("base")
12local table = require("table")
13local string = require("string")
14local math = require("math")
11local socket = require("socket") 15local socket = require("socket")
12local url = require("socket.url") 16local url = require("socket.url")
13local tp = require("socket.tp") 17local tp = require("socket.tp")
14
15local ltn12 = require("ltn12") 18local ltn12 = require("ltn12")
16 19local ftp = module("socket.ftp")
17module("socket.ftp")
18 20
19----------------------------------------------------------------------------- 21-----------------------------------------------------------------------------
20-- Program constants 22-- Program constants
@@ -35,7 +37,7 @@ local metat = { __index = {} }
35 37
36function open(server, port) 38function open(server, port)
37 local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT)) 39 local tp = socket.try(tp.connect(server, port or PORT, TIMEOUT))
38 local f = setmetatable({ tp = tp }, metat) 40 local f = base.setmetatable({ tp = tp }, metat)
39 -- make sure everything gets closed in an exception 41 -- make sure everything gets closed in an exception
40 f.try = socket.newtry(function() f:close() end) 42 f.try = socket.newtry(function() f:close() end)
41 return f 43 return f
@@ -102,7 +104,8 @@ function metat.__index:send(sendt)
102 -- we just get the data connection into self.data 104 -- we just get the data connection into self.data
103 if self.pasvt then self:pasvconnect() end 105 if self.pasvt then self:pasvconnect() end
104 -- get the transfer argument and command 106 -- get the transfer argument and command
105 local argument = sendt.argument or string.gsub(sendt.path, "^/", "") 107 local argument = sendt.argument or
108 url.unescape(string.gsub(sendt.path or "", "^/", ""))
106 if argument == "" then argument = nil end 109 if argument == "" then argument = nil end
107 local command = sendt.command or "stor" 110 local command = sendt.command or "stor"
108 -- send the transfer command and check the reply 111 -- send the transfer command and check the reply
@@ -134,7 +137,8 @@ end
134function metat.__index:receive(recvt) 137function metat.__index:receive(recvt)
135 self.try(self.pasvt or self.server, "need port or pasv first") 138 self.try(self.pasvt or self.server, "need port or pasv first")
136 if self.pasvt then self:pasvconnect() end 139 if self.pasvt then self:pasvconnect() end
137 local argument = recvt.argument or string.gsub(recvt.path, "^/", "") 140 local argument = recvt.argument or
141 url.unescape(string.gsub(recvt.path or "", "^/", ""))
138 if argument == "" then argument = nil end 142 if argument == "" then argument = nil end
139 local command = recvt.command or "retr" 143 local command = recvt.command or "retr"
140 self.try(self.tp:command(command, argument)) 144 self.try(self.tp:command(command, argument))
@@ -182,7 +186,19 @@ end
182----------------------------------------------------------------------------- 186-----------------------------------------------------------------------------
183-- High level FTP API 187-- High level FTP API
184----------------------------------------------------------------------------- 188-----------------------------------------------------------------------------
189function override(t)
190 if t.url then
191 u = url.parse(t.url)
192 for i,v in base.pairs(t) do
193 u[i] = v
194 end
195 return u
196 else return t end
197end
198
185local function tput(putt) 199local function tput(putt)
200 putt = override(putt)
201 socket.try(putt.host, "missing hostname")
186 local f = open(putt.host, putt.port) 202 local f = open(putt.host, putt.port)
187 f:greet() 203 f:greet()
188 f:login(putt.user, putt.password) 204 f:login(putt.user, putt.password)
@@ -201,8 +217,8 @@ local default = {
201 217
202local function parse(u) 218local function parse(u)
203 local t = socket.try(url.parse(u, default)) 219 local t = socket.try(url.parse(u, default))
204 socket.try(t.scheme == "ftp", "invalid scheme '" .. t.scheme .. "'") 220 socket.try(t.scheme == "ftp", "wrong scheme '" .. t.scheme .. "'")
205 socket.try(t.host, "invalid host") 221 socket.try(t.host, "missing hostname")
206 local pat = "^type=(.)$" 222 local pat = "^type=(.)$"
207 if t.params then 223 if t.params then
208 t.type = socket.skip(2, string.find(t.params, pat)) 224 t.type = socket.skip(2, string.find(t.params, pat))
@@ -219,11 +235,13 @@ local function sput(u, body)
219end 235end
220 236
221put = socket.protect(function(putt, body) 237put = socket.protect(function(putt, body)
222 if type(putt) == "string" then return sput(putt, body) 238 if base.type(putt) == "string" then return sput(putt, body)
223 else return tput(putt) end 239 else return tput(putt) end
224end) 240end)
225 241
226local function tget(gett) 242local function tget(gett)
243 gett = override(gett)
244 socket.try(gett.host, "missing hostname")
227 local f = open(gett.host, gett.port) 245 local f = open(gett.host, gett.port)
228 f:greet() 246 f:greet()
229 f:login(gett.user, gett.password) 247 f:login(gett.user, gett.password)
@@ -242,7 +260,22 @@ local function sget(u)
242 return table.concat(t) 260 return table.concat(t)
243end 261end
244 262
263command = socket.protect(function(cmdt)
264 cmdt = override(cmdt)
265 socket.try(cmdt.host, "missing hostname")
266 socket.try(cmdt.command, "missing command")
267 local f = open(cmdt.host, cmdt.port)
268 f:greet()
269 f:login(cmdt.user, cmdt.password)
270 f.try(f.tp:command(cmdt.command, cmdt.argument))
271 if cmdt.check then f.try(f.tp:check(cmdt.check)) end
272 f:quit()
273 return f:close()
274end)
275
245get = socket.protect(function(gett) 276get = socket.protect(function(gett)
246 if type(gett) == "string" then return sget(gett) 277 if base.type(gett) == "string" then return sget(gett)
247 else return tget(gett) end 278 else return tget(gett) end
248end) 279end)
280
281base.setmetatable(ftp, nil)