X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fweb%2Fluasrc%2Fdispatcher.lua;h=e3d8ac0d483e490791b21cda527b679e8cf3014f;hp=fc551a4bdeb54efa83985742e7c83e3998d1f0c8;hb=561b0cfaa3fb8163d9ec74a3f96fd5b22ad54f33;hpb=776f9957d0376670e9d3e43677dbe3ba19ded193 diff --git a/libs/web/luasrc/dispatcher.lua b/libs/web/luasrc/dispatcher.lua index fc551a4bd..e3d8ac0d4 100644 --- a/libs/web/luasrc/dispatcher.lua +++ b/libs/web/luasrc/dispatcher.lua @@ -28,6 +28,11 @@ require("luci.http") require("luci.sys") require("luci.fs") +-- Dirty OpenWRT fix +if (os.time() < luci.fs.mtime(luci.sys.libpath() .. "/dispatcher.lua")) then + os.execute('date -s '..os.date('%m%d%H%M%Y', luci.fs.mtime(luci.sys.libpath() .. "/dispatcher.lua"))..' > /dev/null 2>&1') +end + -- Local dispatch database local tree = {nodes={}} @@ -44,12 +49,27 @@ dispatched = nil built_index = false built_tree = false +-- Fastindex +local fi + -- Builds a URL function build_url(...) return luci.http.dispatcher() .. "/" .. table.concat(arg, "/") end +-- Prints an error message or renders the "error401" template if available +function error401(message) + message = message or "Unauthorized" + + require("luci.template") + if not pcall(luci.template.render, "error401") then + luci.http.prepare_content("text/plain") + print(message) + end + return false +end + -- Sends a 404 error code and renders the "error404" template if available function error404(message) luci.http.status(404, "Not Found") @@ -80,7 +100,7 @@ function httpdispatch() local pathinfo = luci.http.env.PATH_INFO or "" local c = tree - for s in pathinfo:gmatch("([%w_]+)") do + for s in pathinfo:gmatch("([%w-]+)") do table.insert(request, s) end @@ -98,7 +118,7 @@ function dispatch() for i, s in ipairs(request) do c = c.nodes[s] - if not c then + if not c or c.leaf then break end @@ -107,6 +127,20 @@ function dispatch() end end + if track.sysauth then + local accs = track.sysauth + accs = (type(accs) == "string") and {accs} or accs + + local function sysauth(user, password) + return (luci.util.contains(accs, user) + and luci.sys.user.checkpasswd(user, password)) + end + + if not luci.http.basic_auth(sysauth) then + error401() + return + end + end if track.i18n then require("luci.i18n").loadc(track.i18n) @@ -122,14 +156,12 @@ function dispatch() -- Init template engine local tpl = require("luci.template") - tpl.viewns.translate = function(...) return require("luci.i18n").translate(...) end - tpl.viewns.controller = luci.http.dispatcher() - tpl.viewns.uploadctrl = luci.http.dispatcher_upload() - tpl.viewns.media = luci.config.main.mediaurlbase - tpl.viewns.resource = luci.config.main.resourcebase - - -- Load default translation - require("luci.i18n").loadc("default") + tpl.viewns.translate = function(...) return require("luci.i18n").translate(...) end + tpl.viewns.controller = luci.http.dispatcher() + tpl.viewns.uploadctrl = luci.http.dispatcher_upload() + tpl.viewns.media = luci.config.main.mediaurlbase + tpl.viewns.resource = luci.config.main.resourcebase + tpl.viewns.REQUEST_URI = luci.http.env.SCRIPT_NAME .. luci.http.env.PATH_INFO if c and type(c.target) == "function" then @@ -154,7 +186,7 @@ function createindex() local path = luci.sys.libpath() .. "/controller/" local suff = ".lua" - if pcall(require, "fastindex") then + if pcall(require, "luci.fastindex") then createindex_fastindex(path, suff) else createindex_plain(path, suff) @@ -165,9 +197,11 @@ end -- Uses fastindex to create the dispatching tree function createindex_fastindex(path, suffix) - local fi = fastindex.new("index") - fi.add(path .. "*" .. suffix) - fi.add(path .. "*/*" .. suffix) + if not fi then + fi = luci.fastindex.new("index") + fi.add(path .. "*" .. suffix) + fi.add(path .. "*/*" .. suffix) + end fi.scan() for k, v in pairs(fi.indexes) do @@ -176,8 +210,13 @@ function createindex_fastindex(path, suffix) end -- Calls the index function of all available controllers +-- Fallback for transition purposes / Leave it in as long as it works otherwise throw it away function createindex_plain(path, suffix) - local cachetime = nil + if built_index then + return + end + + local cache = nil local controllers = luci.util.combine( luci.fs.glob(path .. "*" .. suffix) or {}, @@ -185,32 +224,39 @@ function createindex_plain(path, suffix) ) if indexcache then - cachetime = luci.fs.mtime(indexcache) + cache = luci.fs.mtime(indexcache) - if not cachetime then + if not cache then luci.fs.mkdir(indexcache) luci.fs.chmod(indexcache, "a=,u=rwx") + cache = luci.fs.mtime(indexcache) end end - if not cachetime then - for i,c in ipairs(controllers) do - c = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".") - stat, mod = pcall(require, c) + for i,c in ipairs(controllers) do + local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".") + local cachefile + local stime + local ctime + + if cache then + cachefile = indexcache .. "/" .. module + stime = luci.fs.mtime(c) or 0 + ctime = luci.fs.mtime(cachefile) or 0 + end + + if not cache or stime > ctime then + stat, mod = pcall(require, module) if stat and mod and type(mod.index) == "function" then - index[c] = mod.index + index[module] = mod.index - if indexcache then - luci.fs.writefile(indexcache .. "/" .. c, string.dump(mod.index)) + if cache then + luci.fs.writefile(cachefile, luci.util.dump(mod.index)) end end - end - else - for i,c in ipairs(luci.fs.dir(indexcache)) do - if c:sub(1) ~= "." then - index[c] = loadfile(indexcache .. "/" .. c) - end + else + index[module] = loadfile(cachefile) end end end @@ -220,30 +266,56 @@ function createtree() if not built_index then createindex() end + + require("luci.i18n") + + -- Load default translation + luci.i18n.loadc("default") + + local scope = luci.util.clone(_G) + for k,v in pairs(_M) do + if type(v) == "function" then + scope[k] = v + end + end for k, v in pairs(index) do - luci.util.updfenv(v, _M) - luci.util.extfenv(v, "_NAME", k) - pcall(v) + scope._NAME = k + setfenv(v, scope) + + local stat, err = pcall(v) + if not stat then + error500(err) + os.exit(1) + end end built_tree = true end --- Shortcut for creating a dispatching node -function entry(path, target, title, order, add) - add = add or {} +-- Reassigns a node to another position +function assign(path, clone, title, order) + local obj = node(path) + obj.nodes = nil + obj.module = nil + + obj.title = title + obj.order = order + + setmetatable(obj, {__index = clone}) + + return obj +end +-- Shortcut for creating a dispatching node +function entry(path, target, title, order) local c = node(path) + c.target = target c.title = title c.order = order c.module = getfenv(2)._NAME - for k,v in pairs(add) do - c[k] = v - end - return c end @@ -275,6 +347,21 @@ function alias(...) end end +function rewrite(n, ...) + local req = arg + return function() + for i=1,n do + table.remove(request, 1) + end + + for i,r in ipairs(req) do + table.insert(request, i, r) + end + + dispatch() + end +end + function call(name) return function() getfenv()[name]() end end