X-Git-Url: http://git.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fweb%2Fluasrc%2Fdispatcher.lua;h=3ee42d72bbaca3aa9b524ee9ff426c4c7acbe584;hp=9ba74c49c91e09ed25dc101d007c73918c3a1678;hb=4fc00fead31332769eb9c584460beda1f076d98d;hpb=e72a526984982f6fa2b6f2ed5ce01523094bfe43 diff --git a/libs/web/luasrc/dispatcher.lua b/libs/web/luasrc/dispatcher.lua index 9ba74c49c9..3ee42d72bb 100644 --- a/libs/web/luasrc/dispatcher.lua +++ b/libs/web/luasrc/dispatcher.lua @@ -26,6 +26,7 @@ limitations under the License. --- LuCI web dispatcher. module("luci.dispatcher", package.seeall) +require("luci.util") require("luci.init") require("luci.http") require("luci.sys") @@ -33,6 +34,8 @@ require("luci.fs") context = luci.util.threadlocal() +authenticator = {} + -- Index table local index = nil @@ -76,25 +79,20 @@ function error500(message) return false end ---- Render and evaluate the system authentication login form. --- @param default Default username --- @return Authentication status -function sysauth(default) +function authenticator.htmlauth(validator, accs, default) local user = luci.http.formvalue("username") local pass = luci.http.formvalue("password") - if user and luci.sys.user.checkpasswd(user, pass) then - local sid = luci.sys.uniqueid(16) - luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") - luci.sauth.write(sid, user) - return true - else - require("luci.i18n") - require("luci.template") - context.path = {} - luci.template.render("sysauth", {duser=default, fuser=user}) - return false + if user and validator(user, pass) then + return user end + + require("luci.i18n") + require("luci.template") + context.path = {} + luci.template.render("sysauth", {duser=default, fuser=user}) + return false + end --- Dispatch an HTTP request. @@ -127,18 +125,23 @@ function dispatch(request) local c = context.tree local track = {} local args = {} + context.args = args local n for i, s in ipairs(request) do c = c.nodes[s] n = i - if not c or c.leaf then + if not c then break end for k, v in pairs(c) do track[k] = v end + + if c.leaf then + break + end end if c and c.leaf then @@ -157,10 +160,11 @@ function dispatch(request) tpl.context.viewns = viewns viewns.write = luci.http.write viewns.translate = function(...) return require("luci.i18n").translate(...) end + viewns.striptags = luci.util.striptags viewns.controller = luci.http.getenv("SCRIPT_NAME") viewns.media = luci.config.main.mediaurlbase viewns.resource = luci.config.main.resourcebase - viewns.REQUEST_URI = luci.http.getenv("SCRIPT_NAME") .. (luci.http.getenv("PATH_INFO") or "") + viewns.REQUEST_URI = (luci.http.getenv("SCRIPT_NAME") or "") .. (luci.http.getenv("PATH_INFO") or "") if track.dependent then local stat, err = pcall(assert, not track.auto) @@ -172,13 +176,27 @@ function dispatch(request) if track.sysauth then require("luci.sauth") + local authen = type(track.sysauth_authenticator) == "function" + and track.sysauth_authenticator + or authenticator[track.sysauth_authenticator] local def = (type(track.sysauth) == "string") and track.sysauth local accs = def and {track.sysauth} or track.sysauth - local user = luci.sauth.read(luci.http.getcookie("sysauth")) - + local sess = luci.http.getcookie("sysauth") + sess = sess and sess:match("^[A-F0-9]+$") + local user = luci.sauth.read(sess) if not luci.util.contains(accs, user) then - if not sysauth(def) then + if authen then + local user = authen(luci.sys.user.checkpasswd, accs, def) + if not user or not luci.util.contains(accs, user) then + return + else + local sid = luci.sys.uniqueid(16) + luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/") + luci.sauth.write(sid, user) + end + else + luci.http.status(403, "Forbidden") return end end @@ -461,3 +479,32 @@ function cbi(model) luci.template.render("cbi/footer") end end + +--- Create a CBI form model dispatching target. +-- @param model CBI form model tpo be rendered +function form(model) + require("luci.cbi") + require("luci.template") + + return function(...) + local stat, maps = luci.util.copcall(luci.cbi.load, model, ...) + if not stat then + error500(maps) + return true + end + + for i, res in ipairs(maps) do + local stat, err = luci.util.copcall(res.parse, res) + if not stat then + error500(err) + return true + end + end + + luci.template.render("header") + for i, res in ipairs(maps) do + res:render() + end + luci.template.render("footer") + end +end