diff --git a/etc/get.lua b/etc/get.lua new file mode 100644 index 0000000..4a17cfc --- /dev/null +++ b/etc/get.lua @@ -0,0 +1,100 @@ +assert(dofile("../lua/buffer.lua")) +assert(dofile("../lua/ftp.lua")) +assert(dofile("../lua/base64.lua")) +assert(dofile("../lua/http.lua")) + +-- format a number of bytes per second into a human readable form +function strbps(b) + local l = "B/s" + if b > 1024 then + b = b / 1024 + l = "KB/s" + if b > 1024 then + b = b / 1024 + l = "MB/s" + if b > 1024 then + b = b / 1024 + l = "GB/s" -- hmmm + end + end + end + return format("%.2f%s ", b, l) +end + +-- creates a new instance of a receive_cb that saves to disk +-- kind of copied from luasocket's manual callback examples +function receive2disk(file) + local aux = { + start = _time(), + got = 0, + file = openfile(file, "wb") + } + local receive_cb = function(chunk, err) + local dt = _time() - %aux.start -- elapsed time since start + if not chunk or chunk == "" then + write("\n") + closefile(%aux.file) + return + end + write(%aux.file, chunk) + %aux.got = %aux.got + strlen(chunk) -- total bytes received + if dt < 0.1 then return 1 end -- not enough time for estimate + local rate = %aux.got / dt -- get download rate + write("\r" .. strbps(rate)) -- print estimate + return 1 + end + return receive_cb +end + +-- stolen from http implementation +function split_url(url, default) + -- initialize default parameters + local parsed = default or {} + -- get scheme + url = gsub(url, "^(.+)://", function (s) %parsed.scheme = s end) + -- get user name and password. both can be empty! + -- moreover, password can be ommited + url = gsub(url, "^([^@:/]*)(:?)([^:@/]-)@", function (u, c, p) + %parsed.user = u + -- there can be an empty password, but the ':' has to be there + -- or else there is no password + %parsed.pass = nil -- kill default password + if c == ":" then %parsed.pass = p end + end) + -- get host + url = gsub(url, "^([%w%.%-]+)", function (h) %parsed.host = h end) + -- get port if any + url = gsub(url, "^:(%d+)", function (p) %parsed.port = p end) + -- whatever is left is the path + if url ~= "" then parsed.path = url end + return parsed +end + +-- stolen from http implementation +function get_statuscode(line) + local _,_, code = strfind(line, " (%d%d%d) ") + return tonumber(code) +end + +function getbyftp(url, file) + local err = ftp_getindirect(url, receive2disk(file), "b") + if err then print(err) else print("done.") end +end + +function getbyhttp(url, file) + local hdrs, line, err = http_getindirect(url, receive2disk(file)) + if line and get_statuscode(line) == 200 then print("done.") + elseif line then print(line) else print(err) end +end + +function get(url, file) + local parsed = split_url(url) + if parsed.scheme == "ftp" then getbyftp(url, file) + else getbyhttp(url, file) end +end + +arg = arg or {} +if getn(arg) < 2 then + write("Usage:\n luasocket -f get.lua \n") + exit(1) +else get(arg[1], arg[2]) end