2008-03-02 21:52:58 +00:00
|
|
|
--[[
|
2008-05-25 17:00:30 +00:00
|
|
|
LuCI - Dispatcher
|
2008-03-02 21:52:58 +00:00
|
|
|
|
|
|
|
Description:
|
|
|
|
The request dispatcher and module dispatcher generators
|
|
|
|
|
|
|
|
FileId:
|
|
|
|
$Id$
|
|
|
|
|
|
|
|
License:
|
|
|
|
Copyright 2008 Steven Barth <steven@midlink.org>
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
2008-05-24 22:58:45 +00:00
|
|
|
You may obtain a copy of the License at
|
2008-03-02 21:52:58 +00:00
|
|
|
|
2008-05-24 22:58:45 +00:00
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
2008-03-02 21:52:58 +00:00
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
|
|
|
|
]]--
|
2008-05-25 17:00:30 +00:00
|
|
|
module("luci.dispatcher", package.seeall)
|
|
|
|
require("luci.http")
|
|
|
|
require("luci.sys")
|
|
|
|
require("luci.fs")
|
2008-06-02 15:35:57 +00:00
|
|
|
require("luci.fastindex")
|
2008-03-02 21:52:58 +00:00
|
|
|
|
2008-06-01 17:22:21 +00:00
|
|
|
-- Dirty OpenWRT fix
|
|
|
|
if (os.time() < luci.fs.mtime(luci.sys.libpath() .. "/dispatcher.lua")) then
|
2008-06-01 17:25:07 +00:00
|
|
|
os.execute('date -s '..os.date('%m%d%H%M%Y', luci.fs.mtime(luci.sys.libpath() .. "/dispatcher.lua"))..' > /dev/null 2>&1')
|
2008-06-01 17:22:21 +00:00
|
|
|
end
|
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
-- Local dispatch database
|
|
|
|
local tree = {nodes={}}
|
2008-03-29 18:22:21 +00:00
|
|
|
|
2008-05-26 12:16:16 +00:00
|
|
|
-- Index table
|
|
|
|
local index = {}
|
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
-- Global request object
|
|
|
|
request = {}
|
2008-05-05 19:27:30 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
-- Active dispatched node
|
|
|
|
dispatched = nil
|
2008-05-05 19:27:30 +00:00
|
|
|
|
2008-05-26 12:16:16 +00:00
|
|
|
-- Status fields
|
|
|
|
built_index = false
|
|
|
|
built_tree = false
|
|
|
|
|
2008-06-02 15:35:57 +00:00
|
|
|
-- Fastindex cache
|
|
|
|
local fi = nil
|
2008-05-05 19:27:30 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
-- Builds a URL
|
2008-05-29 13:51:32 +00:00
|
|
|
function build_url(...)
|
2008-05-25 17:00:30 +00:00
|
|
|
return luci.http.dispatcher() .. "/" .. table.concat(arg, "/")
|
2008-03-02 21:52:58 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Sends a 404 error code and renders the "error404" template if available
|
|
|
|
function error404(message)
|
2008-05-25 17:00:30 +00:00
|
|
|
luci.http.status(404, "Not Found")
|
2008-03-02 21:52:58 +00:00
|
|
|
message = message or "Not Found"
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-25 17:00:30 +00:00
|
|
|
require("luci.template")
|
|
|
|
if not pcall(luci.template.render, "error404") then
|
|
|
|
luci.http.prepare_content("text/plain")
|
2008-03-17 18:06:41 +00:00
|
|
|
print(message)
|
2008-03-02 21:52:58 +00:00
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
return false
|
2008-03-02 21:52:58 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
-- Sends a 500 error code and renders the "error500" template if available
|
|
|
|
function error500(message)
|
2008-05-25 17:00:30 +00:00
|
|
|
luci.http.status(500, "Internal Server Error")
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-25 17:00:30 +00:00
|
|
|
require("luci.template")
|
|
|
|
if not pcall(luci.template.render, "error500", {message=message}) then
|
|
|
|
luci.http.prepare_content("text/plain")
|
2008-03-02 21:52:58 +00:00
|
|
|
print(message)
|
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
return false
|
2008-03-02 21:52:58 +00:00
|
|
|
end
|
|
|
|
|
2008-05-26 12:16:16 +00:00
|
|
|
-- Creates a request object for dispatching
|
2008-03-02 21:52:58 +00:00
|
|
|
function httpdispatch()
|
2008-05-25 17:00:30 +00:00
|
|
|
local pathinfo = luci.http.env.PATH_INFO or ""
|
2008-05-22 14:04:03 +00:00
|
|
|
local c = tree
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-29 18:52:22 +00:00
|
|
|
for s in pathinfo:gmatch("([%w-]+)") do
|
2008-05-22 14:04:03 +00:00
|
|
|
table.insert(request, s)
|
2008-03-02 21:52:58 +00:00
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
dispatch()
|
2008-05-04 20:53:31 +00:00
|
|
|
end
|
|
|
|
|
2008-05-26 12:16:16 +00:00
|
|
|
-- Dispatches a request
|
2008-05-22 14:04:03 +00:00
|
|
|
function dispatch()
|
2008-05-26 12:16:16 +00:00
|
|
|
if not built_tree then
|
|
|
|
createtree()
|
|
|
|
end
|
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
local c = tree
|
|
|
|
local track = {}
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
for i, s in ipairs(request) do
|
|
|
|
c = c.nodes[s]
|
2008-05-29 19:18:49 +00:00
|
|
|
if not c or c.leaf then
|
2008-05-22 14:04:03 +00:00
|
|
|
break
|
2008-05-24 22:58:45 +00:00
|
|
|
end
|
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
for k, v in pairs(c) do
|
|
|
|
track[k] = v
|
|
|
|
end
|
2008-05-04 20:53:31 +00:00
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
if track.i18n then
|
2008-05-25 17:00:30 +00:00
|
|
|
require("luci.i18n").loadc(track.i18n)
|
2008-05-04 20:53:31 +00:00
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
if track.setgroup then
|
2008-05-25 17:00:30 +00:00
|
|
|
luci.sys.process.setgroup(track.setgroup)
|
2008-05-04 20:53:31 +00:00
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
|
|
|
if track.setuser then
|
2008-05-25 17:00:30 +00:00
|
|
|
luci.sys.process.setuser(track.setuser)
|
2008-05-24 22:58:45 +00:00
|
|
|
end
|
2008-05-26 09:45:12 +00:00
|
|
|
|
|
|
|
-- Init template engine
|
|
|
|
local tpl = require("luci.template")
|
2008-05-31 13:57:30 +00:00
|
|
|
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
|
2008-05-27 08:14:24 +00:00
|
|
|
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
if c and type(c.target) == "function" then
|
|
|
|
dispatched = c
|
2008-05-27 20:39:48 +00:00
|
|
|
stat, mod = pcall(require, c.module)
|
|
|
|
if stat then
|
|
|
|
luci.util.updfenv(c.target, mod)
|
|
|
|
end
|
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
stat, err = pcall(c.target)
|
|
|
|
if not stat then
|
|
|
|
error500(err)
|
|
|
|
end
|
2008-03-21 19:30:53 +00:00
|
|
|
else
|
2008-05-22 14:04:03 +00:00
|
|
|
error404()
|
2008-03-02 21:52:58 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2008-05-26 09:45:12 +00:00
|
|
|
-- Generates the dispatching tree
|
2008-05-22 14:04:03 +00:00
|
|
|
function createindex()
|
2008-05-26 12:16:16 +00:00
|
|
|
index = {}
|
2008-05-26 09:45:12 +00:00
|
|
|
local path = luci.sys.libpath() .. "/controller/"
|
2008-06-02 15:35:57 +00:00
|
|
|
local suffix = ".lua"
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-06-02 15:35:57 +00:00
|
|
|
if fi == nil then
|
|
|
|
fi = luci.fastindex.new("index")
|
|
|
|
fi.add(path .. "*" .. suffix)
|
|
|
|
fi.add(path .. "*/*" .. suffix)
|
|
|
|
end
|
2008-05-26 09:45:12 +00:00
|
|
|
fi.scan()
|
2008-06-02 15:35:57 +00:00
|
|
|
|
2008-05-26 09:45:12 +00:00
|
|
|
for k, v in pairs(fi.indexes) do
|
2008-05-26 12:16:16 +00:00
|
|
|
index[v[2]] = v[1]
|
2008-05-26 09:45:12 +00:00
|
|
|
end
|
|
|
|
|
2008-06-02 15:35:57 +00:00
|
|
|
built_index = true
|
2008-03-21 19:30:53 +00:00
|
|
|
end
|
|
|
|
|
2008-05-26 12:16:16 +00:00
|
|
|
-- Creates the dispatching tree from the index
|
|
|
|
function createtree()
|
|
|
|
if not built_index then
|
|
|
|
createindex()
|
|
|
|
end
|
2008-05-29 18:27:12 +00:00
|
|
|
|
|
|
|
require("luci.i18n")
|
2008-05-31 08:04:49 +00:00
|
|
|
|
|
|
|
-- Load default translation
|
|
|
|
luci.i18n.loadc("default")
|
|
|
|
|
2008-06-01 12:12:18 +00:00
|
|
|
local scope = luci.util.clone(_G)
|
2008-05-31 08:04:49 +00:00
|
|
|
for k,v in pairs(_M) do
|
|
|
|
if type(v) == "function" then
|
|
|
|
scope[k] = v
|
|
|
|
end
|
|
|
|
end
|
2008-05-26 12:16:16 +00:00
|
|
|
|
|
|
|
for k, v in pairs(index) do
|
2008-05-31 08:04:49 +00:00
|
|
|
scope._NAME = k
|
|
|
|
setfenv(v, scope)
|
2008-05-29 18:27:12 +00:00
|
|
|
|
|
|
|
local stat, err = pcall(v)
|
|
|
|
if not stat then
|
|
|
|
error500(err)
|
|
|
|
os.exit(1)
|
|
|
|
end
|
2008-05-26 12:16:16 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
built_tree = true
|
|
|
|
end
|
|
|
|
|
2008-05-22 17:21:30 +00:00
|
|
|
-- Shortcut for creating a dispatching node
|
|
|
|
function entry(path, target, title, order, add)
|
|
|
|
add = add or {}
|
|
|
|
|
|
|
|
local c = node(path)
|
|
|
|
c.target = target
|
|
|
|
c.title = title
|
|
|
|
c.order = order
|
2008-05-27 20:39:48 +00:00
|
|
|
c.module = getfenv(2)._NAME
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 17:21:30 +00:00
|
|
|
for k,v in pairs(add) do
|
|
|
|
c[k] = v
|
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 17:21:30 +00:00
|
|
|
return c
|
|
|
|
end
|
2008-05-04 20:53:31 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
-- Fetch a dispatching node
|
|
|
|
function node(...)
|
|
|
|
local c = tree
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 17:21:30 +00:00
|
|
|
if arg[1] and type(arg[1]) == "table" then
|
|
|
|
arg = arg[1]
|
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
for k,v in ipairs(arg) do
|
|
|
|
if not c.nodes[v] then
|
2008-05-27 20:39:48 +00:00
|
|
|
c.nodes[v] = {nodes={}, module=getfenv(2)._NAME}
|
2008-05-22 14:04:03 +00:00
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
c = c.nodes[v]
|
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
return c
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Subdispatchers --
|
|
|
|
function alias(...)
|
|
|
|
local req = arg
|
|
|
|
return function()
|
|
|
|
request = req
|
|
|
|
dispatch()
|
2008-05-04 20:53:31 +00:00
|
|
|
end
|
2008-03-21 19:30:53 +00:00
|
|
|
end
|
|
|
|
|
2008-05-29 19:18:49 +00:00
|
|
|
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
|
|
|
|
|
2008-05-27 20:39:48 +00:00
|
|
|
function call(name)
|
|
|
|
return function() getfenv()[name]() end
|
|
|
|
end
|
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
function template(name)
|
2008-05-25 17:00:30 +00:00
|
|
|
require("luci.template")
|
|
|
|
return function() luci.template.render(name) end
|
2008-05-22 14:04:03 +00:00
|
|
|
end
|
2008-05-04 20:53:31 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
function cbi(model)
|
2008-05-25 17:00:30 +00:00
|
|
|
require("luci.cbi")
|
|
|
|
require("luci.template")
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
return function()
|
2008-05-25 17:00:30 +00:00
|
|
|
local stat, res = pcall(luci.cbi.load, model)
|
2008-05-22 14:04:03 +00:00
|
|
|
if not stat then
|
|
|
|
error500(res)
|
|
|
|
return true
|
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-22 14:04:03 +00:00
|
|
|
local stat, err = pcall(res.parse, res)
|
|
|
|
if not stat then
|
|
|
|
error500(err)
|
|
|
|
return true
|
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
|
2008-05-25 17:00:30 +00:00
|
|
|
luci.template.render("cbi/header")
|
2008-05-22 14:04:03 +00:00
|
|
|
res:render()
|
2008-05-25 17:00:30 +00:00
|
|
|
luci.template.render("cbi/footer")
|
2008-03-02 21:52:58 +00:00
|
|
|
end
|
2008-05-24 22:58:45 +00:00
|
|
|
end
|