Operating system for OpenComputers
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

134 lines
3.6KB

  1. local net = require "minitel"
  2. local dl = {}
  3. dl.protos = {}
  4. -- Stolen from the old exec/fget
  5. local function parseURL(url)
  6. local proto,addr = url:match("(.-)://(.+)")
  7. addr = addr or url
  8. local hp, path = addr:match("(.-)(/.*)")
  9. hp, path = hp or addr, path or "/"
  10. local host, port = hp:match("(.+):(.+)")
  11. host = host or hp
  12. return proto, host, port, path
  13. end
  14. 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.
  15. local socket = assert(net.open(host, optPort or 70))
  16. socket:write(string.format("t%s\n", path))
  17. local status
  18. repeat
  19. coroutine.yield()
  20. status = socket:read(1)
  21. until status ~= ""
  22. if status == "d" then
  23. io.write("Directory Listing:\n")
  24. local tmp = ""
  25. repeat
  26. coroutine.yield()
  27. tmp = socket:read("*a")
  28. io.write(tmp)
  29. until socket.state == "closed" and tmp == ""
  30. return true
  31. elseif status == "y" then
  32. if not dest then
  33. error("Must provide local path to save remote files.")
  34. end
  35. io.write(string.format("Saving %s to %s...\n", path, dest))
  36. local f = assert(io.open(dest, "wb"))
  37. local tmp = ""
  38. repeat
  39. coroutine.yield()
  40. tmp = socket:read("*a")
  41. f:write(tmp)
  42. until socket.state == "closed" and tmp == ""
  43. f:close()
  44. print("Done.")
  45. return true
  46. else
  47. local err, tmp = "", ""
  48. repeat
  49. coroutine.yield()
  50. tmp = socket:read("*a")
  51. err = err .. tmp
  52. until socket.state == "closed" and tmp == ""
  53. error(string.format("Got error from remote host: %s", err))
  54. end
  55. end
  56. function dl.protos.http(host, optPort, path, dest, url) -- string string string number -- boolean -- Downloads *url* to *dest* via the internet card, if available.
  57. if not component.list("internet")() then
  58. local proto,host,sPort,path = parseURL(url)
  59. local proxy = os.getenv(proto:upper().."_PROXY")
  60. if not proxy and fs.exists("/boot/cfg/"..proto.."_proxy") then
  61. local f = io.open("/boot/cfg/"..proto.."_proxy","rb")
  62. proxy = f:read()
  63. f:close()
  64. end
  65. if not proxy then error("No internet card or HTTP(S) proxy available") end
  66. print("Internet card unavailable, falling back to proxy "..proxy)
  67. if optPort then host=string.format("%s:%i",host,optPort) end
  68. return dl.wget(string.format("%s/%s%s",proxy,host,path),dest)
  69. end
  70. if not dest then
  71. error("Must provide local path to save remote files.")
  72. end
  73. local R,r=component.invoke(component.list("internet")(),"request",url)
  74. if not R then error(r) end
  75. repeat
  76. ok, err = R.finishConnect()
  77. if type(ok) ~= "boolean" then
  78. if err == url then
  79. return 404, "This is a bug in OC, I think?"
  80. end
  81. return -1, err or "Connection Error"
  82. end
  83. coroutine.yield()
  84. until ok
  85. local code, messsage, headers
  86. repeat
  87. coroutine.yield()
  88. code, message, headers = R.response()
  89. until code or message
  90. if code > 299 or code < 200 then
  91. return false, code, message
  92. end
  93. local f=io.open(dest,"wb")
  94. if not f then error("Unable to open file "..dest) end
  95. io.write(string.format("Saving %s to %s...\n", url, dest))
  96. repeat
  97. coroutine.yield()
  98. ns = R.read()
  99. f:write(ns or "")
  100. until not ns
  101. f:close()
  102. print("Done.")
  103. return true
  104. end
  105. dl.protos.https = dl.protos.http
  106. function dl.wget(remotePath, dest) -- string string -- -- Downloads from remote *remotePath* to *dest*
  107. local proto, host, sPort, path = parseURL(remotePath)
  108. if dl.protos[proto] then
  109. local port
  110. if sPort then
  111. port = tonumber(sPort)
  112. end
  113. dl.protos[proto](host, port, path, dest, remotePath)
  114. else
  115. error("Unsupported protocol: " .. tostring(proto))
  116. end
  117. end
  118. return setmetatable(dl,{__call=function(_,path,dest) return dl.wget(path,dest) end})