X-Git-Url: http://git.archive.openwrt.org/?a=blobdiff_plain;f=libs%2Fweb%2Fluasrc%2Fdispatcher.lua;h=99ba9adca3a425024b929f4ebed4b52f895f8349;hb=932280107232706c4605e475a6d969f0adf2e22d;hp=6a6bceb29b5a9e4e125d009317953e0b78ee5a17;hpb=6a0da42befb970b56f93c0bf109a9cb7475e8e0c;p=project%2Fluci.git diff --git a/libs/web/luasrc/dispatcher.lua b/libs/web/luasrc/dispatcher.lua index 6a6bceb29..99ba9adca 100644 --- a/libs/web/luasrc/dispatcher.lua +++ b/libs/web/luasrc/dispatcher.lua @@ -24,19 +24,22 @@ limitations under the License. ]]-- module("luci.dispatcher", package.seeall) +require("luci.init") 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={}} -- Index table local index = {} --- Indexdump -local indexcache = "/tmp/.luciindex" - -- Global request object request = {} @@ -47,12 +50,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") @@ -81,10 +99,9 @@ end -- Creates a request object for dispatching function httpdispatch() local pathinfo = luci.http.env.PATH_INFO or "" - local c = tree - for s in pathinfo:gmatch("([%w_]+)") do - table.insert(request, s) + for node in pathinfo:gmatch("[^/]+") do + table.insert(request, node) end dispatch() @@ -101,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 @@ -110,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) @@ -125,19 +156,22 @@ 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.uci = require("luci.model.uci").config + tpl.viewns.REQUEST_URI = luci.http.env.SCRIPT_NAME .. (luci.http.env.PATH_INFO or "") if c and type(c.target) == "function" then dispatched = c - + stat, mod = pcall(require, c.module) + if stat then + luci.util.updfenv(c.target, mod) + end + stat, err = pcall(c.target) if not stat then error500(err) @@ -153,7 +187,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) @@ -164,9 +198,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 @@ -175,8 +211,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 {}, @@ -184,32 +225,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 @@ -219,33 +267,64 @@ 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) + scope._NAME = k + setfenv(v, scope) - local stat, mod = pcall(require, k) - if stat then - luci.util.updfenv(v, mod) + local stat, err = pcall(v) + if not stat then + error500(err) + os.exit(1) end - - pcall(v) 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 + + local c = tree + for k, v in ipairs(clone) do + if not c.nodes[v] then + c.nodes[v] = {nodes={}} + end + c = c.nodes[v] + end + + setmetatable(obj, {__index = c}) + + 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 - - for k,v in pairs(add) do - c[k] = v - end + c.module = getfenv(2)._NAME return c end @@ -254,8 +333,11 @@ end function node(...) local c = tree - if arg[1] and type(arg[1]) == "table" then - arg = arg[1] + arg.n = nil + if arg[1] then + if type(arg[1]) == "table" then + arg = arg[1] + end end for k,v in ipairs(arg) do @@ -266,6 +348,9 @@ function node(...) c = c.nodes[v] end + c.module = getfenv(2)._NAME + c.path = arg + return c end @@ -278,6 +363,25 @@ 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 + function template(name) require("luci.template") return function() luci.template.render(name) end