Skip to content

Lua backend for OpenWRT added. #354

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions bridges/openwrt-lua/etc/config/filemanager
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

config filemanager 'config'
option basedir '/mnt'
option tmpdir '/tmp'
120 changes: 120 additions & 0 deletions bridges/openwrt-lua/usr/lib/lua/cgi.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
-- cgi util module

local uci = require("uci")
local u_c = uci.cursor()
local tmppath = u_c.get("filemanager","config","tmpdir")

local prevbuf = ""
local blocksize = 4096
local _M = {}

_M.statusmsg = {
[200] = "OK",
[206] = "Partial Content",
[301] = "Moved Permanently",
[302] = "Found",
[304] = "Not Modified",
[400] = "Bad Request",
[403] = "Forbidden",
[404] = "Not Found",
[405] = "Method Not Allowed",
[408] = "Request Time-out",
[411] = "Length Required",
[412] = "Precondition Failed",
[416] = "Requested range not satisfiable",
[500] = "Internal Server Error",
[503] = "Server Unavailable",
}

-- call this function passing an empy table. use that table for successive calls.
function _M.new(req)
req.content_length = os.getenv("CONTENT_LENGTH")
req.request_method = os.getenv("REQUEST_METHOD")
if req.request_method == "POST" then
req.content_type, req.boundary = string.match(os.getenv("CONTENT_TYPE"),"^(multipart/form%-data); boundary=\"?(.+)\"?$")
req.boundary = "--" .. req.boundary
end
-- this is useful only if you have /tmp on tmpfs like in openwrt. otherwise can be set to ""
req.tempdir = tmppath
req.post = {}
end

-- this function is needed to clean temp file since and hide implementation details
function _M.cleanup(req)
for k, v in pairs(req.post) do
for j, v in pairs(req.post[k]) do
if req.post[k][j].tempname then
os.remove(req.post[k][j].tempname) -- if file unused
os.remove("/tmp/" .. string.match(req.post[k][j].tempname,"^" .. req.tempdir .. "(.+)"))
end
end
end
end

-- del: delimiter
-- return chunk (string), found (boolean)
local function chunkread(del)
local buf, found = 0
local del = del or "\r\n"

buf = io.read(math.max(0,blocksize + #del - #prevbuf))
if prevbuf ~= "" then buf = prevbuf .. ( buf or "" ); prevbuf = "" end
if not buf then return end

s, e = string.find(buf,del,1,true)
if s and e then
found = 1
prevbuf = string.sub(buf,e+1)
buf = string.sub(buf,1,s-1)
else
prevbuf = string.sub(buf,math.min(blocksize,#buf)+1)
buf = string.sub(buf,1,math.min(blocksize,#buf))
end

return buf, found
end


function _M.parse_request_body (req)
local chunk, found, type, tempname, tempfile
local param = {}

-- read first boundary line
chunk, found = chunkread(req.boundary)
chunk, found = chunkread("\r\n")
while chunk == "" do
-- read part headers and get parameters value
repeat
chunk, found = chunkread("\r\n")
if not found then return 400, "Malformed POST. Missing Part Header or Part Header too long." end
string.gsub(chunk, ';%s*([^%s=]+)="(.-[^\\])"', function(k, v) param[k] = v end)
param.type = param.type or string.match(chunk, "^Content%-Type: (.+)$")
until chunk == ""

-- prepare file data read
if not param.name then return 400, "Malformed POST. Check Header parameters." end
param.size=0
param.tempname = req.tempdir .. string.match(os.tmpname(), "^/tmp(.+)")
tempfile = io.open(param.tempname, "w")

-- read part body content until boundary
repeat
chunk, found = chunkread("\r\n" .. req.boundary)
if not chunk then return 400, "Malformed POST. Incomplete Part received." end
tempfile:write(chunk)
param.size = param.size + #chunk
until found
tempfile:close()
req.post[param.name] = req.post[param.name] or {}
table.insert(req.post[param.name], 1, param)
param = {}

-- read after boundary. if CRLF ("") repeat. if "--" end POST processing
chunk, found = chunkread("\r\n")
end

if found and chunk == "--" then return 0, "OK" end
return 400, "Malformed POST. Boundary not properly ended with CRLF or --."
end

return _M
102 changes: 102 additions & 0 deletions bridges/openwrt-lua/usr/lib/lua/luafm.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#!/usr/bin/lua

local uci = require "uci"
local fs = require "nixio.fs"
local u_c = uci.cursor()
local basepath = u_c.get("filemanager","config","basedir")

local _M = {}

local bp = basepath:match("(.*)/")
if bp and bp ~= "" then
basepath = bp
end
_M.basepath = basepath;

function _M.is_in_dir(file, dir)
if file == dir then
return true
else
return file:sub(1, #dir) == dir
end
end

function _M.path_valid(path)
return _M.is_in_dir(path,_M.basepath) and fs.access(path,"r")
end

function _M.dir_path_valid(path)
return _M.is_in_dir(path,_M.basepath) and fs.stat(path,"type")=="dir" and fs.access(path,"w")
end

function _M.new_path_valid(path)
local dirpath = fs.dirname(path)
return _M.is_in_dir(dirpath,_M.basepath) and fs.access(dirpath,"w")
end

function _M.make_path(path)
local realpath = fs.realpath(_M.basepath..'/'..path)
if _M.path_valid(realpath) then
return realpath
else
return nil
end
end

function _M.make_new_path(path)
local realpath = fs.realpath(fs.dirname(_M.basepath..'/'..path))..'/'..fs.basename(path)
if _M.new_path_valid(realpath) then
return realpath
else
return nil
end
end

function _M.make_dir_path(path)
local realpath = fs.realpath(_M.basepath..'/'..path)
if _M.dir_path_valid(realpath) then
return realpath
else
return nil
end
end

function _M.rm(item)
local ftype = fs.stat(item,"type")
if ftype == "reg" then
return fs.remove(item)
elseif ftype == "dir" then
local dir = fs.dir(item)
for file in dir do
if not _M.rm(item..'/'..file) then
return false
end
end
return fs.rmdir(item)
else
return false
end
end

function _M.chmod(item,mode,recursive)
local result = fs.chmod(item,mode)
if result and recursive then
local dir = fs.dir(item)
if dir then
for file in dir do
local ftype = fs.stat(item..'/'..file,"type")
if ftype == "dir" then
result = _M.chmod(item..'/'..file,mode,recursive)
elseif ftype == "reg" then
result = _M.chmod(item..'/'..file,string.gsub(mode,"x","-"),false)
end
if not result then
break
end
end
end
end
return result
end

return _M
Loading