2022-08-27 16:38:20 +02:00
|
|
|
|
|
|
|
package.cpath = __api__.apiroot..'/?.so'
|
|
|
|
require("antd")
|
|
|
|
|
|
|
|
local readline = function()
|
|
|
|
local s = ""
|
|
|
|
repeat
|
|
|
|
local c = modules.std().antd_recv(HTTP_REQUEST.id,1)
|
|
|
|
if c ~= 0 and c ~= 10 then
|
|
|
|
s = s..utf8.char(c)
|
|
|
|
end
|
|
|
|
until(c == 0 or c == 10)
|
|
|
|
return s
|
|
|
|
end
|
|
|
|
local read_header =function()
|
|
|
|
repeat
|
|
|
|
local l = readline()
|
|
|
|
if l ~= '\r' then
|
|
|
|
if l == "HTTP_REQUEST" or l == "request" or l == "COOKIE" or l == "REQUEST_HEADER" or l == "REQUEST_DATA" then
|
|
|
|
coroutine.yield(l, "LUA_TABLE")
|
|
|
|
else
|
|
|
|
local l1 = readline()
|
|
|
|
if l1 ~= '\r' then
|
|
|
|
coroutine.yield(l, l1)
|
|
|
|
end
|
|
|
|
l = l1
|
|
|
|
end
|
|
|
|
end
|
|
|
|
until l == '\r'
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
local read_headers = function()
|
|
|
|
local co = coroutine.create(function () read_header() end)
|
|
|
|
return function () -- iterator
|
|
|
|
local code, k, v = coroutine.resume(co)
|
|
|
|
return k,v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local parse_headers =function()
|
|
|
|
local lut = {
|
|
|
|
HTTP_REQUEST = HTTP_REQUEST
|
|
|
|
}
|
|
|
|
local curr_tbl = "HTTP_REQUEST"
|
|
|
|
for k,v in read_headers() do
|
|
|
|
if v == "LUA_TABLE" then
|
|
|
|
if not lut[k] then
|
|
|
|
lut[k] = {}
|
|
|
|
end
|
|
|
|
curr_tbl = k
|
|
|
|
else
|
|
|
|
lut[curr_tbl][k] = v
|
|
|
|
end
|
|
|
|
end
|
|
|
|
HTTP_REQUEST.request = lut.request
|
|
|
|
HTTP_REQUEST.request.COOKIE = lut.COOKIE
|
|
|
|
HTTP_REQUEST.request.REQUEST_HEADER = lut.REQUEST_HEADER
|
|
|
|
HTTP_REQUEST.request.REQUEST_DATA = lut.REQUEST_DATA
|
|
|
|
end
|
|
|
|
|
|
|
|
-- parsing the header
|
|
|
|
parse_headers()
|
2018-09-19 15:08:49 +02:00
|
|
|
-- root dir
|
2022-08-27 16:38:20 +02:00
|
|
|
__ROOT__ = HTTP_REQUEST.request.SERVER_WWW_ROOT
|
2018-09-19 15:08:49 +02:00
|
|
|
-- set require path
|
|
|
|
package.path = __ROOT__ .. '/?.lua;'..__api__.apiroot..'/?.lua'
|
2018-10-05 19:02:35 +02:00
|
|
|
require("std")
|
|
|
|
require("utils")
|
|
|
|
require("extra_mime")
|
2019-12-04 19:52:26 +01:00
|
|
|
ulib = require("ulib")
|
2018-09-19 15:08:49 +02:00
|
|
|
-- set session
|
|
|
|
SESSION = {}
|
2018-10-05 19:02:35 +02:00
|
|
|
|
|
|
|
REQUEST = HTTP_REQUEST.request.REQUEST_DATA
|
|
|
|
REQUEST.method = HTTP_REQUEST.request.METHOD
|
|
|
|
if HTTP_REQUEST.request.COOKIE then
|
|
|
|
SESSION = HTTP_REQUEST.request.COOKIE
|
2018-09-19 15:08:49 +02:00
|
|
|
end
|
2018-10-05 19:02:35 +02:00
|
|
|
HEADER = HTTP_REQUEST.request.REQUEST_HEADER
|
2018-09-19 15:08:49 +02:00
|
|
|
HEADER.mobile = false
|
|
|
|
|
|
|
|
if HEADER["User-Agent"] and HEADER["User-Agent"]:match("Mobi") then
|
|
|
|
HEADER.mobile = true
|
|
|
|
end
|
|
|
|
|
2022-08-27 16:38:20 +02:00
|
|
|
function LOG_INFO(fmt,...)
|
|
|
|
ulib.syslog(5,string.format(fmt, table.unpack({...})))
|
|
|
|
end
|
|
|
|
|
|
|
|
function LOG_ERROR(fmt,...)
|
|
|
|
ulib.syslog(3,string.format(fmt, table.unpack({...})))
|
|
|
|
end
|
|
|
|
|
2018-09-19 15:08:49 +02:00
|
|
|
function has_module(m)
|
|
|
|
if utils.file_exists(__ROOT__..'/'..m) then
|
|
|
|
if m:find("%.ls$") then
|
|
|
|
return true, true, __ROOT__..'/'..m
|
|
|
|
else
|
|
|
|
return true, false, m:gsub(".lua$","")
|
|
|
|
end
|
|
|
|
elseif utils.file_exists(__ROOT__..'/'..string.gsub(m,'%.','/')..'.lua') then
|
|
|
|
return true, false, m
|
|
|
|
elseif utils.file_exists(__ROOT__..'/'..string.gsub(m,'%.','/')..'.ls') then
|
|
|
|
return true, true, __ROOT__..'/'..string.gsub(m,'%.','/')..'.ls'
|
|
|
|
end
|
|
|
|
return false, false, nil
|
|
|
|
end
|
|
|
|
|
|
|
|
function echo(m)
|
|
|
|
if m then std.t(m) else std.t("Undefined value") end
|
|
|
|
end
|
|
|
|
|
|
|
|
function loadscript(file, args)
|
|
|
|
local f = io.open(file, "rb")
|
|
|
|
local content = ""
|
|
|
|
if f then
|
|
|
|
local html = ""
|
|
|
|
local pro = "local fn = function(...)"
|
|
|
|
local s,e, mt
|
|
|
|
local mtbegin = true -- find begin of scrit, 0 end of scrit
|
|
|
|
local i = 1
|
|
|
|
if args then
|
|
|
|
pro = "local fn = function("..table.concat( args, ",")..")"
|
|
|
|
end
|
|
|
|
for line in io.lines(file) do
|
|
|
|
line = std.trim(line, " ")
|
|
|
|
if(line ~= "") then
|
|
|
|
if(mtbegin) then
|
|
|
|
mt = "^%s*<%?lua"
|
|
|
|
else
|
|
|
|
mt = "%?>%s*$"
|
|
|
|
end
|
|
|
|
s,e = line:find(mt)
|
|
|
|
if(s) then
|
|
|
|
if mtbegin then
|
|
|
|
if html ~= "" then
|
|
|
|
pro= pro.."echo(\""..utils.escape(html).."\")\n"
|
|
|
|
html = ""
|
|
|
|
end
|
|
|
|
local b,f = line:find("%?>%s*$")
|
|
|
|
if b then
|
|
|
|
pro = pro..line:sub(e+1,b-1).."\n"
|
|
|
|
else
|
|
|
|
pro = pro..line:sub(e+1).."\n"
|
|
|
|
mtbegin = not mtbegin
|
|
|
|
end
|
|
|
|
else
|
|
|
|
pro = pro..line:sub(0,s-1).."\n"
|
|
|
|
mtbegin = not mtbegin
|
|
|
|
end
|
|
|
|
else -- no match
|
|
|
|
if mtbegin then
|
|
|
|
-- detect if we have inline lua with format <?=..?>
|
|
|
|
local b,f = line:find("<%?=")
|
|
|
|
if b then
|
|
|
|
local tmp = line
|
|
|
|
pro= pro.."echo("
|
|
|
|
while(b) do
|
|
|
|
-- find the close
|
|
|
|
local x,y = tmp:find("%?>")
|
|
|
|
if x then
|
|
|
|
pro = pro.."\""..utils.escape(html..tmp:sub(0,b-1):gsub("%%","%%%%")).."\".."
|
|
|
|
pro = pro..tmp:sub(f+1,x-1)..".."
|
|
|
|
html = ""
|
|
|
|
tmp = tmp:sub(y+1)
|
|
|
|
b,f = tmp:find("<%?=")
|
|
|
|
else
|
|
|
|
error("Syntax error near line "..i)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
pro = pro.."\""..utils.escape(tmp:gsub("%%","%%%%")).."\")\n"
|
|
|
|
else
|
|
|
|
html = html..std.trim(line," "):gsub("%%","%%%%").."\n"
|
|
|
|
end
|
|
|
|
else
|
|
|
|
if line ~= "" then pro = pro..line.."\n" end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
i = i+ 1
|
|
|
|
end
|
|
|
|
f:close()
|
|
|
|
if(html ~= "") then
|
|
|
|
pro = pro.."echo(\""..utils.escape(html).."\")\n"
|
|
|
|
end
|
|
|
|
pro = pro.."\nend \n return fn"
|
|
|
|
local r,e = load(pro)
|
|
|
|
if r then return r(), e else return nil,e end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2022-08-27 16:38:20 +02:00
|
|
|
local decode_post_data = function(ctype, clen, is_url)
|
|
|
|
local raw_data,size = std.antd_recv(HTTP_REQUEST.id, clen)
|
|
|
|
if not raw_data or size ~= clen then
|
|
|
|
LOG_ERROR("Unable to read request data: received %d bytes expected %d bytes", size, clen)
|
|
|
|
return 400, "Unable to read request data"
|
|
|
|
end
|
|
|
|
if is_url then
|
|
|
|
local str = tostring(raw)
|
|
|
|
local arr = explode(str, "&")
|
|
|
|
LOG_INFO("encoded POST URI: %s", str)
|
|
|
|
for i,v in ipairs(arr) do
|
|
|
|
local assoc = explode(v,"=")
|
|
|
|
if #assoc == 2 then
|
|
|
|
REQUEST[assoc[1]] = untils.decodeURI(assoc[2])
|
|
|
|
else
|
|
|
|
REQUEST[assoc[1]] = ""
|
|
|
|
end
|
|
|
|
end
|
|
|
|
else
|
|
|
|
local key = ctype:gsub("^[^/]*", "")
|
|
|
|
REQUEST[key] = raw_data
|
|
|
|
end
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
|
|
|
|
local decode_multi_part = function(ctype, clen)
|
|
|
|
--[[
|
|
|
|
local arr = explode(ctype, "=")
|
|
|
|
if #arr ~= 2 then
|
|
|
|
LOG_ERROR("Unable to parsed boundary for: %s", ctype)
|
|
|
|
return 400, "Multipart Boundary not found"
|
|
|
|
end
|
|
|
|
local boundary = std.trim(arr[2]," ")
|
|
|
|
local boundary_end = boundary.."--"
|
|
|
|
LOG_INFO("Boundary found: %s", boundary)
|
|
|
|
local line = nil
|
|
|
|
repeat
|
|
|
|
line = readline()
|
|
|
|
until not line or line:find(boundary) or line == ""
|
|
|
|
if not line or line == "" then
|
|
|
|
LOG_ERROR("Cannot find first match for boundary %s", boundary)
|
|
|
|
return 400, "Unable to decode data based on content boundary"
|
|
|
|
end
|
|
|
|
repeat
|
|
|
|
line = readline()
|
|
|
|
until not line or line:find("Content-Disposition:") or line == ""
|
|
|
|
if not line or line == "" then
|
|
|
|
LOG_ERROR("Content-Disposition meta data not fond")
|
|
|
|
return 400, "Unable to query Content-Disposition from request"
|
|
|
|
end
|
|
|
|
line = line:gsub("Content-Disposition:",""):gsub("\r\n","")
|
|
|
|
-- extract parameters from header
|
|
|
|
arr = explode(line,";")
|
|
|
|
local part_name, part_file = nil, nil
|
|
|
|
for i,v in ipairs(arr) do
|
|
|
|
LOG_INFO('Decoding: %s', v)
|
|
|
|
local assoc = explode(v, "=")
|
|
|
|
local key = std.trim(assoc[1])
|
|
|
|
local val = assoc[1]
|
|
|
|
if val then
|
|
|
|
val = std.trim(val, " ")
|
|
|
|
if key == "name" then
|
|
|
|
LOG_INFO("Part name: %s", val)
|
|
|
|
part_name = val
|
|
|
|
end
|
|
|
|
if key == "filename" then
|
|
|
|
LOG_INFO("Part file: %s", val)
|
|
|
|
part_file = val
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- TODO: to be continue
|
|
|
|
]]
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
-- decode post data if any
|
|
|
|
local decode_request = function()
|
|
|
|
LOG_INFO("Request method %s", REQUEST.method)
|
|
|
|
if (not REQUEST.method)
|
|
|
|
or (REQUEST.method ~= "POST"
|
|
|
|
and REQUEST.method ~= "PUT"
|
|
|
|
and REQUEST.method ~= "PATCH") then
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
local ctype = HEADER['Content-Type']
|
|
|
|
local clen = HEADER['Content-Length'] or -1
|
|
|
|
if clen then
|
|
|
|
clen = tonumber(clen)
|
|
|
|
end
|
|
|
|
if not ctype or clen == -1 then
|
|
|
|
LOG_ERROR("Invalid content type %s or content length %d", ctype, clen)
|
|
|
|
return 400, "Bad Request, missing content description"
|
|
|
|
end
|
|
|
|
if ctype == "application/x-www-form-urlencoded" then
|
|
|
|
return decode_post_data(ctype, clen, true)
|
|
|
|
elseif ctype == "multipart/form-data" then
|
|
|
|
return decode_multi_part(ctype, clen)
|
|
|
|
else
|
|
|
|
return decode_post_data(ctype, clen, false)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local code, error = decode_request()
|
|
|
|
|
|
|
|
if code ~= 0 then
|
|
|
|
LOG_ERROR(error)
|
|
|
|
std.error(code, error)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2018-09-19 15:08:49 +02:00
|
|
|
-- OOP support
|
|
|
|
--require("OOP")
|
|
|
|
-- load sqlite helper
|
|
|
|
--require("sqlite")
|
|
|
|
-- enable extra mime
|
|
|
|
|
|
|
|
-- run the file
|
|
|
|
|
|
|
|
|
2018-10-05 19:02:35 +02:00
|
|
|
local m, s, p = has_module(HTTP_REQUEST.request.RESOURCE_PATH)
|
2018-09-19 15:08:49 +02:00
|
|
|
if m then
|
|
|
|
-- run the correct module
|
|
|
|
if s then
|
|
|
|
local r,e = loadscript(p)
|
|
|
|
if r then r() else unknow(e) end
|
|
|
|
else
|
|
|
|
require(p)
|
|
|
|
end
|
|
|
|
else
|
2018-10-05 19:02:35 +02:00
|
|
|
unknow("Resource not found for request "..HTTP_REQUEST.request.RESOURCE_PATH)
|
2018-09-19 15:08:49 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
--require('router')
|