134 lines
3.6 KiB
Lua
134 lines
3.6 KiB
Lua
local net = require "minitel"
|
|
local dl = {}
|
|
dl.protos = {}
|
|
|
|
-- Stolen from the old exec/fget
|
|
local function parseURL(url)
|
|
local proto,addr = url:match("(.-)://(.+)")
|
|
addr = addr or url
|
|
local hp, path = addr:match("(.-)(/.*)")
|
|
hp, path = hp or addr, path or "/"
|
|
local host, port = hp:match("(.+):(.+)")
|
|
host = host or hp
|
|
return proto, host, port, path
|
|
end
|
|
|
|
function dl.protos.fget(host, optPort, path, dest) -- string string string number -- boolean -- Downloads path from host (on optPort or 70), printing the directory listing, or saving the file to dest.
|
|
local socket = assert(net.open(host, optPort or 70))
|
|
socket:write(string.format("t%s\n", path))
|
|
local status
|
|
repeat
|
|
coroutine.yield()
|
|
status = socket:read(1)
|
|
until status ~= ""
|
|
|
|
if status == "d" then
|
|
io.write("Directory Listing:\n")
|
|
local tmp = ""
|
|
repeat
|
|
coroutine.yield()
|
|
tmp = socket:read("*a")
|
|
|
|
io.write(tmp)
|
|
until socket.state == "closed" and tmp == ""
|
|
|
|
return true
|
|
elseif status == "y" then
|
|
if not dest then
|
|
error("Must provide local path to save remote files.")
|
|
end
|
|
|
|
io.write(string.format("Saving %s to %s...\n", path, dest))
|
|
local f = assert(io.open(dest, "wb"))
|
|
local tmp = ""
|
|
repeat
|
|
coroutine.yield()
|
|
tmp = socket:read("*a")
|
|
|
|
f:write(tmp)
|
|
until socket.state == "closed" and tmp == ""
|
|
|
|
f:close()
|
|
print("Done.")
|
|
|
|
return true
|
|
else
|
|
local err, tmp = "", ""
|
|
repeat
|
|
coroutine.yield()
|
|
tmp = socket:read("*a")
|
|
|
|
err = err .. tmp
|
|
until socket.state == "closed" and tmp == ""
|
|
|
|
error(string.format("Got error from remote host: %s", err))
|
|
end
|
|
end
|
|
|
|
function dl.protos.http(host, optPort, path, dest, url) -- string string string number -- boolean -- Downloads *url* to *dest* via the internet card, if available.
|
|
if not component.list("internet")() then
|
|
local proto,host,sPort,path = parseURL(url)
|
|
local proxy = os.getenv(proto:upper().."_PROXY")
|
|
if not proxy and fs.exists("/boot/cfg/"..proto.."_proxy") then
|
|
local f = io.open("/boot/cfg/"..proto.."_proxy","rb")
|
|
proxy = f:read()
|
|
f:close()
|
|
end
|
|
if not proxy then error("No internet card or HTTP(S) proxy available") end
|
|
print("Internet card unavailable, falling back to proxy "..proxy)
|
|
if optPort then host=string.format("%s:%i",host,optPort) end
|
|
return dl.wget(string.format("%s/%s%s",proxy,host,path),dest)
|
|
end
|
|
if not dest then
|
|
error("Must provide local path to save remote files.")
|
|
end
|
|
local R,r=component.invoke(component.list("internet")(),"request",url)
|
|
if not R then error(r) end
|
|
repeat
|
|
ok, err = R.finishConnect()
|
|
if type(ok) ~= "boolean" then
|
|
if err == url then
|
|
return 404, "This is a bug in OC, I think?"
|
|
end
|
|
return -1, err or "Connection Error"
|
|
end
|
|
coroutine.yield()
|
|
until ok
|
|
local code, messsage, headers
|
|
repeat
|
|
coroutine.yield()
|
|
code, message, headers = R.response()
|
|
until code or message
|
|
if code > 299 or code < 200 then
|
|
return false, code, message
|
|
end
|
|
local f=io.open(dest,"wb")
|
|
if not f then error("Unable to open file "..dest) end
|
|
io.write(string.format("Saving %s to %s...\n", url, dest))
|
|
repeat
|
|
coroutine.yield()
|
|
ns = R.read()
|
|
f:write(ns or "")
|
|
until not ns
|
|
f:close()
|
|
print("Done.")
|
|
return true
|
|
end
|
|
dl.protos.https = dl.protos.http
|
|
|
|
function dl.wget(remotePath, dest) -- string string -- -- Downloads from remote *remotePath* to *dest*
|
|
local proto, host, sPort, path = parseURL(remotePath)
|
|
if dl.protos[proto] then
|
|
local port
|
|
if sPort then
|
|
port = tonumber(sPort)
|
|
end
|
|
|
|
dl.protos[proto](host, port, path, dest, remotePath)
|
|
else
|
|
error("Unsupported protocol: " .. tostring(proto))
|
|
end
|
|
end
|
|
|
|
return setmetatable(dl,{__call=function(_,path,dest) return dl.wget(path,dest) end})
|