libs/web: fix file caches in dispatcher, broke when introducing lua-gz support
[project/luci.git] / libs / web / luasrc / dispatcher.lua
index 5f450eb..73daeaf 100644 (file)
@@ -74,12 +74,17 @@ end
 -- @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
@@ -105,17 +110,15 @@ 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()
 
@@ -130,7 +133,22 @@ function dispatch(request)
        ctx.path = request
        ctx.urltoken   = ctx.urltoken or {}
 
-       require "luci.i18n".setlanguage(require "luci.config".main.lang)
+       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
+                       lpat = lpat and lpat:gsub("-", "_")
+                       if conf.languages[lpat] then
+                               lang = lpat
+                               break
+                       end
+               end
+        end
+       require "luci.i18n".setlanguage(lang)
 
        local c = ctx.tree
        local stat
@@ -337,7 +355,7 @@ end
 --- 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)
@@ -348,14 +366,16 @@ end
 
 --- 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()
 
@@ -366,12 +386,16 @@ end
 
 --- 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)
@@ -398,7 +422,11 @@ function createindex_plain(path, suffix)
        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
 
@@ -500,6 +528,14 @@ function entry(path, target, title, order)
        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
@@ -577,7 +613,7 @@ end
 
 
 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](...)
@@ -614,11 +650,9 @@ local function _cbi(self, ...)
        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
@@ -646,14 +680,18 @@ local function _cbi(self, ...)
 
        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.
@@ -688,7 +726,7 @@ local function _form(self, ...)
 
        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