local minitel = require "minitel" local serial = require "serialization" local cfg = {["path"]="/boot/srv/frequest",["port"]=70} local function loadConfig(cfgpath) local f=io.open(cfgpath or "/boot/cfg/fserv.cfg","rb") if f then local ncfg = serial.unserialize(f:read("*a")) f:close() for k,v in pairs(ncfg) do cfg[k] = v end end end local function fileHandler(socket,rtype,path) syslog(string.format("[%s:%d] %s %s",socket.addr,socket.port,rtype,path),syslog.info,"fserv") if rtype == "t" then if fs.exists(path) and fs.isDirectory(path) then socket:write("d") for _,file in ipairs(fs.list(path)) do socket:write(file.."\n") end elseif fs.exists(path) and not fs.isDirectory(path) then local f,err = io.open(path,"rb") if f then socket:write("y") while true do local c = f:read(4096) if not c or c == "" then break end socket:write(c) end else socket:write("fFailed to open file: "..err) end else socket:write("nFile not found") end elseif rtype == "s" then if fs.exists(path) then local ftype = "f" if fs.isDirectory(path) then ftype = "d" end socket:write(string.format("y%s\n%d",ftype,fs.size(path))) else socket:write("nFile not found.") end else socket:write("fUnknown request type") end end local function httpHandler(socket,rtype,path) local tPath = fs.segments(path) local proto = table.remove(tPath,1) local url = string.format("%s://%s",proto,table.concat(tPath,"/")) local request = component.invoke(component.list("internet")(),"request",url) repeat coroutine.yield() until request.finishConnect() local code, message, headers = request.response() if code < 200 or code > 299 then socket:write(string.format("f%d\n%s",code,message)) else socket:write("y") local data = "" repeat coroutine.yield() data = request.read() if data then socket:write(data) end until not data end end local function socketHandler(socket) return function() local line = nil repeat coroutine.yield() line = socket:read() until line local rtype, path = line:match("(.)(.+)") if fs.segments(path)[1] == "http" or fs.segments(path)[1] == "https" then httpHandler(socket,rtype,path) else path = (cfg.path .. "/" .. path:gsub("../","")):gsub("/+","/") fileHandler(socket,rtype,path) end socket:close() end end local function fileServer() while true do os.spawn(socketHandler(minitel.listen(70)),"fserv worker process") end end function start(cfgpath) loadConfig(cfgpath) return os.spawn(fileServer,"fserv") end return {start=start}