aboutsummaryrefslogtreecommitdiff
path: root/src/ftp.lua
diff options
context:
space:
mode:
Diffstat (limited to 'src/ftp.lua')
-rw-r--r--src/ftp.lua51
1 files changed, 26 insertions, 25 deletions
diff --git a/src/ftp.lua b/src/ftp.lua
index 1fa48f7..f6fffbb 100644
--- a/src/ftp.lua
+++ b/src/ftp.lua
@@ -8,7 +8,7 @@
8----------------------------------------------------------------------------- 8-----------------------------------------------------------------------------
9 9
10local Public, Private = {}, {} 10local Public, Private = {}, {}
11FTP = Public 11socket.ftp = Public
12 12
13----------------------------------------------------------------------------- 13-----------------------------------------------------------------------------
14-- Program constants 14-- Program constants
@@ -47,7 +47,7 @@ end
47----------------------------------------------------------------------------- 47-----------------------------------------------------------------------------
48function Private.try_receive(...) 48function Private.try_receive(...)
49 local sock = arg[1] 49 local sock = arg[1]
50 local data, err = call(sock.receive, arg) 50 local data, err = sock.receive(unpack(arg))
51 if err then sock:close() end 51 if err then sock:close() end
52 return data, err 52 return data, err
53end 53end
@@ -64,9 +64,9 @@ function Private.get_pasv(pasv)
64 local a, b, c, d, p1, p2, _ 64 local a, b, c, d, p1, p2, _
65 local ip, port 65 local ip, port
66 _,_, a, b, c, d, p1, p2 = 66 _,_, a, b, c, d, p1, p2 =
67 strfind(pasv, "(%d*),(%d*),(%d*),(%d*),(%d*),(%d*)") 67 string.find(pasv, "(%d*),(%d*),(%d*),(%d*),(%d*),(%d*)")
68 if not (a and b and c and d and p1 and p2) then return nil, nil end 68 if not (a and b and c and d and p1 and p2) then return nil, nil end
69 ip = format("%d.%d.%d.%d", a, b, c, d) 69 ip = string.format("%d.%d.%d.%d", a, b, c, d)
70 port = tonumber(p1)*256 + tonumber(p2) 70 port = tonumber(p1)*256 + tonumber(p2)
71 return ip, port 71 return ip, port
72end 72end
@@ -100,13 +100,13 @@ function Private.get_answer(control)
100 local line, err = Private.try_receive(control) 100 local line, err = Private.try_receive(control)
101 local answer = line 101 local answer = line
102 if err then return nil, err end 102 if err then return nil, err end
103 _,_, code, sep = strfind(line, "^(%d%d%d)(.)") 103 _,_, code, sep = string.find(line, "^(%d%d%d)(.)")
104 if not code or not sep then return nil, answer end 104 if not code or not sep then return nil, answer end
105 if sep == "-" then -- answer is multiline 105 if sep == "-" then -- answer is multiline
106 repeat 106 repeat
107 line, err = Private.try_receive(control) 107 line, err = Private.try_receive(control)
108 if err then return nil, err end 108 if err then return nil, err end
109 _,_, lastcode, sep = strfind(line, "^(%d%d%d)(.)") 109 _,_, lastcode, sep = string.find(line, "^(%d%d%d)(.)")
110 answer = answer .. "\n" .. line 110 answer = answer .. "\n" .. line
111 until code == lastcode and sep == " " -- answer ends with same code 111 until code == lastcode and sep == " " -- answer ends with same code
112 end 112 end
@@ -126,8 +126,8 @@ function Private.check_answer(control, success)
126 local answer, code = Private.get_answer(control) 126 local answer, code = Private.get_answer(control)
127 if not answer then return nil, code end 127 if not answer then return nil, code end
128 if type(success) ~= "table" then success = {success} end 128 if type(success) ~= "table" then success = {success} end
129 for i = 1, getn(success) do 129 for _, s in ipairs(success) do
130 if code == success[i] then 130 if code == s then
131 return code, answer 131 return code, answer
132 end 132 end
133 end 133 end
@@ -213,13 +213,13 @@ function Private.port(control)
213 local code, answer 213 local code, answer
214 local server, ctl_ip 214 local server, ctl_ip
215 ctl_ip, answer = control:getsockname() 215 ctl_ip, answer = control:getsockname()
216 server, answer = bind(ctl_ip, 0) 216 server, answer = socket.bind(ctl_ip, 0)
217 server:timeout(Public.TIMEOUT) 217 server:timeout(Public.TIMEOUT)
218 local ip, p, ph, pl 218 local ip, p, ph, pl
219 ip, p = server:getsockname() 219 ip, p = server:getsockname()
220 pl = mod(p, 256) 220 pl = math.mod(p, 256)
221 ph = (p - pl)/256 221 ph = (p - pl)/256
222 local arg = gsub(format("%s,%d,%d", ip, ph, pl), "%.", ",") 222 local arg = string.gsub(string.format("%s,%d,%d", ip, ph, pl), "%.", ",")
223 code, answer = Private.command(control, "port", arg, {200}) 223 code, answer = Private.command(control, "port", arg, {200})
224 if not code then 224 if not code then
225 server:close() 225 server:close()
@@ -321,7 +321,7 @@ function Private.send_indirect(data, send_cb, chunk, size)
321 data:close() 321 data:close()
322 return err 322 return err
323 end 323 end
324 sent = sent + strlen(chunk) 324 sent = sent + string.len(chunk)
325 if sent >= size then break end 325 if sent >= size then break end
326 chunk, size = send_cb() 326 chunk, size = send_cb()
327 end 327 end
@@ -374,7 +374,7 @@ end
374----------------------------------------------------------------------------- 374-----------------------------------------------------------------------------
375function Private.change_type(control, params) 375function Private.change_type(control, params)
376 local type, _ 376 local type, _
377 _, _, type = strfind(params or "", "type=(.)") 377 _, _, type = string.find(params or "", "type=(.)")
378 if type == "a" or type == "i" then 378 if type == "a" or type == "i" then
379 local code, err = Private.command(control, "type", type, {200}) 379 local code, err = Private.command(control, "type", type, {200})
380 if not code then return err end 380 if not code then return err end
@@ -391,7 +391,7 @@ end
391----------------------------------------------------------------------------- 391-----------------------------------------------------------------------------
392function Private.open(parsed) 392function Private.open(parsed)
393 -- start control connection 393 -- start control connection
394 local control, err = connect(parsed.host, parsed.port) 394 local control, err = socket.connect(parsed.host, parsed.port)
395 if not control then return nil, err end 395 if not control then return nil, err end
396 -- make sure we don't block forever 396 -- make sure we don't block forever
397 control:timeout(Public.TIMEOUT) 397 control:timeout(Public.TIMEOUT)
@@ -423,7 +423,7 @@ end
423-- err: error message if any 423-- err: error message if any
424----------------------------------------------------------------------------- 424-----------------------------------------------------------------------------
425function Private.change_dir(control, segment) 425function Private.change_dir(control, segment)
426 local n = getn(segment) 426 local n = table.getn(segment)
427 for i = 1, n-1 do 427 for i = 1, n-1 do
428 local code, answer = Private.cwd(control, segment[i]) 428 local code, answer = Private.cwd(control, segment[i])
429 if not code then return answer end 429 if not code then return answer end
@@ -443,7 +443,7 @@ end
443function Private.upload(control, request, segment) 443function Private.upload(control, request, segment)
444 local code, name, content_cb 444 local code, name, content_cb
445 -- get remote file name 445 -- get remote file name
446 name = segment[getn(segment)] 446 name = segment[table.getn(segment)]
447 if not name then 447 if not name then
448 control:close() 448 control:close()
449 return "Invalid file path" 449 return "Invalid file path"
@@ -472,7 +472,7 @@ function Private.download(control, request, segment)
472 is_directory = segment.is_directory 472 is_directory = segment.is_directory
473 content_cb = request.content_cb 473 content_cb = request.content_cb
474 -- get remote file name 474 -- get remote file name
475 name = segment[getn(segment)] 475 name = segment[table.getn(segment)]
476 if not name and not is_directory then 476 if not name and not is_directory then
477 control:close() 477 control:close()
478 return "Invalid file path" 478 return "Invalid file path"
@@ -498,7 +498,7 @@ end
498-- parsed: a table with parsed components 498-- parsed: a table with parsed components
499----------------------------------------------------------------------------- 499-----------------------------------------------------------------------------
500function Private.parse_url(request) 500function Private.parse_url(request)
501 local parsed = URL.parse_url(request.url, { 501 local parsed = socket.url.parse(request.url, {
502 host = "", 502 host = "",
503 user = "anonymous", 503 user = "anonymous",
504 port = 21, 504 port = 21,
@@ -521,9 +521,10 @@ end
521-- Returns 521-- Returns
522-- dirs: a table with parsed directory components 522-- dirs: a table with parsed directory components
523----------------------------------------------------------------------------- 523-----------------------------------------------------------------------------
524function Private.parse_path(parsed) 524function Private.parse_path(parsed_url)
525 local segment = URL.parse_path(parsed.path) 525 local segment = socket.url.parse_path(parsed_url.path)
526 segment.is_directory = segment.is_directory or (parsed.params == "type=d") 526 segment.is_directory = segment.is_directory or
527 (parsed_url.params == "type=d")
527 return segment 528 return segment
528end 529end
529 530
@@ -560,7 +561,7 @@ end
560function Public.get_cb(request) 561function Public.get_cb(request)
561 local parsed = Private.parse_url(request) 562 local parsed = Private.parse_url(request)
562 if parsed.scheme ~= "ftp" then 563 if parsed.scheme ~= "ftp" then
563 return format("unknown scheme '%s'", parsed.scheme) 564 return string.format("unknown scheme '%s'", parsed.scheme)
564 end 565 end
565 local control, err = Private.open(parsed) 566 local control, err = Private.open(parsed)
566 if not control then return err end 567 if not control then return err end
@@ -586,7 +587,7 @@ end
586function Public.put_cb(request) 587function Public.put_cb(request)
587 local parsed = Private.parse_url(request) 588 local parsed = Private.parse_url(request)
588 if parsed.scheme ~= "ftp" then 589 if parsed.scheme ~= "ftp" then
589 return format("unknown scheme '%s'", parsed.scheme) 590 return string.format("unknown scheme '%s'", parsed.scheme)
590 end 591 end
591 local control, err = Private.open(parsed) 592 local control, err = Private.open(parsed)
592 if not control then return err end 593 if not control then return err end
@@ -612,7 +613,7 @@ end
612function Public.put(url_or_request, content) 613function Public.put(url_or_request, content)
613 local request = Private.build_request(url_or_request) 614 local request = Private.build_request(url_or_request)
614 request.content_cb = function() 615 request.content_cb = function()
615 return content, strlen(content) 616 return content, string.len(content)
616 end 617 end
617 return Public.put_cb(request) 618 return Public.put_cb(request)
618end 619end
@@ -630,7 +631,7 @@ end
630-- err: error message in case of error, nil otherwise 631-- err: error message in case of error, nil otherwise
631----------------------------------------------------------------------------- 632-----------------------------------------------------------------------------
632function Public.get(url_or_request) 633function Public.get(url_or_request)
633 local cat = Concat.create() 634 local cat = socket.concat.create()
634 local request = Private.build_request(url_or_request) 635 local request = Private.build_request(url_or_request)
635 request.content_cb = function(chunk, err) 636 request.content_cb = function(chunk, err)
636 if chunk then cat:addstring(chunk) end 637 if chunk then cat:addstring(chunk) end