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.

108 lines
2.6KB

  1. local minitel = require "minitel"
  2. local serial = require "serialization"
  3. local cfg = {["path"]="/boot/srv/frequest",["port"]=70}
  4. local function loadConfig(cfgpath)
  5. local f=io.open(cfgpath or "/boot/cfg/fserv.cfg","rb")
  6. if f then
  7. local ncfg = serial.unserialize(f:read("*a"))
  8. f:close()
  9. for k,v in pairs(ncfg) do
  10. cfg[k] = v
  11. end
  12. end
  13. end
  14. local function fileHandler(socket,rtype,path)
  15. syslog(string.format("[%s:%d] %s %s",socket.addr,socket.port,rtype,path),syslog.info,"fserv")
  16. if rtype == "t" then
  17. if fs.exists(path) and fs.isDirectory(path) then
  18. socket:write("d")
  19. for _,file in ipairs(fs.list(path)) do
  20. socket:write(file.."\n")
  21. end
  22. elseif fs.exists(path) and not fs.isDirectory(path) then
  23. local f,err = io.open(path,"rb")
  24. if f then
  25. socket:write("y")
  26. while true do
  27. local c = f:read(4096)
  28. if not c or c == "" then break end
  29. socket:write(c)
  30. end
  31. else
  32. socket:write("fFailed to open file: "..err)
  33. end
  34. else
  35. socket:write("nFile not found")
  36. end
  37. elseif rtype == "s" then
  38. if fs.exists(path) then
  39. local ftype = "f"
  40. if fs.isDirectory(path) then
  41. ftype = "d"
  42. end
  43. socket:write(string.format("y%s\n%d",ftype,fs.size(path)))
  44. else
  45. socket:write("nFile not found.")
  46. end
  47. else
  48. socket:write("fUnknown request type")
  49. end
  50. end
  51. local function httpHandler(socket,rtype,path)
  52. local tPath = fs.segments(path)
  53. local proto = table.remove(tPath,1)
  54. local url = string.format("%s://%s",proto,table.concat(tPath,"/"))
  55. local request = component.invoke(component.list("internet")(),"request",url)
  56. repeat
  57. coroutine.yield()
  58. until request.finishConnect()
  59. local code, message, headers = request.response()
  60. if code < 200 or code > 299 then
  61. socket:write(string.format("f%d\n%s",code,message))
  62. else
  63. socket:write("y")
  64. local data = ""
  65. repeat
  66. coroutine.yield()
  67. data = request.read()
  68. if data then
  69. socket:write(data)
  70. end
  71. until not data
  72. end
  73. end
  74. local function socketHandler(socket)
  75. return function()
  76. local line = nil
  77. repeat
  78. coroutine.yield()
  79. line = socket:read()
  80. until line
  81. local rtype, path = line:match("(.)(.+)")
  82. if fs.segments(path)[1] == "http" or fs.segments(path)[1] == "https" then
  83. httpHandler(socket,rtype,path)
  84. else
  85. path = (cfg.path .. "/" .. path:gsub("../","")):gsub("/+","/")
  86. fileHandler(socket,rtype,path)
  87. end
  88. socket:close()
  89. end
  90. end
  91. local function fileServer()
  92. while true do
  93. os.spawn(socketHandler(minitel.listen(70)),"fserv worker process")
  94. end
  95. end
  96. function start(cfgpath)
  97. loadConfig(cfgpath)
  98. return os.spawn(fileServer,"fserv")
  99. end
  100. return {start=start}