-- @param message Custom error message (optional)#
-- @return false
function error500(message)
- luci.http.status(500, "Internal Server Error")
-
- require("luci.template")
- if not luci.util.copcall(luci.template.render, "error500", {message=message}) then
+ luci.util.perror(message)
+ if not context.template_header_sent then
+ luci.http.status(500, "Internal Server Error")
luci.http.prepare_content("text/plain")
luci.http.write(message)
+ else
+ require("luci.template")
+ if not luci.util.copcall(luci.template.render, "error500", {message=message}) then
+ luci.http.prepare_content("text/plain")
+ luci.http.write(message)
+ end
end
return false
end
function httpdispatch(request)
luci.http.context.request = request
context.request = {}
- local pathinfo = request:getenv("PATH_INFO") or ""
+ local pathinfo = http.urldecode(request:getenv("PATH_INFO") or "", true)
for node in pathinfo:gmatch("[^/]+") do
table.insert(context.request, node)
end
- local stat, err = util.copcall(dispatch, context.request)
- if not stat then
- luci.util.perror(err)
- error500(err)
- end
+ local stat, err = util.coxpcall(function()
+ dispatch(context.request)
+ end, error500)
luci.http.close()
ctx.urltoken = ctx.urltoken or {}
local conf = require "luci.config"
+ assert(conf.main,
+ "/etc/config/luci seems to be corrupt, unable to find section 'main'")
+
local lang = conf.main.lang
if lang == "auto" then
local aclang = http.getenv("HTTP_ACCEPT_LANGUAGE") or ""
- for lpat in aclang:gmatch("[%w]+") do
+ for lpat in aclang:gmatch("[%w-]+") do
+ lpat = lpat and lpat:gsub("-", "_")
if conf.languages[lpat] then
lang = lpat
break
--- Generate the dispatching index using the best possible strategy.
function createindex()
local path = luci.util.libpath() .. "/controller/"
- local suff = ".lua"
+ local suff = { ".lua", ".lua.gz" }
if luci.util.copcall(require, "luci.fastindex") then
createindex_fastindex(path, suff)
--- Generate the dispatching index using the fastindex C-indexer.
-- @param path Controller base directory
--- @param suffix Controller file suffix
-function createindex_fastindex(path, suffix)
+-- @param suffixes Controller file suffixes
+function createindex_fastindex(path, suffixes)
index = {}
if not fi then
fi = luci.fastindex.new("index")
- fi.add(path .. "*" .. suffix)
- fi.add(path .. "*/*" .. suffix)
+ for _, suffix in ipairs(suffixes) do
+ fi.add(path .. "*" .. suffix)
+ fi.add(path .. "*/*" .. suffix)
+ end
end
fi.scan()
--- Generate the dispatching index using the native file-cache based strategy.
-- @param path Controller base directory
--- @param suffix Controller file suffix
-function createindex_plain(path, suffix)
- local controllers = util.combine(
- luci.fs.glob(path .. "*" .. suffix) or {},
- luci.fs.glob(path .. "*/*" .. suffix) or {}
- )
+-- @param suffixes Controller file suffixes
+function createindex_plain(path, suffixes)
+ local controllers = { }
+ for _, suffix in ipairs(suffixes) do
+ controllers = util.combine(
+ controllers,
+ luci.fs.glob(path .. "*" .. suffix) or {},
+ luci.fs.glob(path .. "*/*" .. suffix) or {}
+ )
+ end
if indexcache then
local cachedate = fs.mtime(indexcache)
index = {}
for i,c in ipairs(controllers) do
- local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".")
+ local module = "luci.controller." .. c:sub(#path+1, #c):gsub("/", ".")
+ for _, suffix in ipairs(suffixes) do
+ module = module:gsub(suffix.."$", "")
+ end
+
local mod = require(module)
local idx = mod.index
return c
end
+--- Fetch or create a dispatching node without setting the target module or
+-- enabling the node.
+-- @param ... Virtual path
+-- @return Dispatching tree node
+function get(...)
+ return _create_node({...})
+end
+
--- Fetch or create a new dispatching node.
-- @param ... Virtual path
-- @return Dispatching tree node
local function _call(self, ...)
- if #self.argv > 0 then
+ if #self.argv > 0 then
return getfenv()[self.name](unpack(self.argv), ...)
else
return getfenv()[self.name](...)
local state = nil
for i, res in ipairs(maps) do
- if config.autoapply then
- res.autoapply = config.autoapply
- end
+ res.flow = config
local cstate = res:parse()
- if not state or cstate < state then
+ if cstate and (not state or cstate < state) then
state = cstate
end
end
local pageaction = true
http.header("X-CBI-State", state or 0)
- tpl.render("cbi/header", {state = state})
+ if not config.noheader then
+ tpl.render("cbi/header", {state = state})
+ end
for i, res in ipairs(maps) do
res:render()
if res.pageaction == false then
pageaction = false
end
end
- tpl.render("cbi/footer", {pageaction=pageaction, state = state, autoapply = config.autoapply})
+ if not config.nofooter then
+ tpl.render("cbi/footer", {flow = config, pageaction=pageaction, state = state, autoapply = config.autoapply})
+ end
end
--- Create a CBI model dispatching target.
for i, res in ipairs(maps) do
local cstate = res:parse()
- if not state or cstate < state then
+ if cstate and (not state or cstate < state) then
state = cstate
end
end