5 The request dispatcher and module dispatcher generators
11 Copyright 2008 Steven Barth <steven@midlink.org>
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at
17 http://www.apache.org/licenses/LICENSE-2.0
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
26 module("luci.dispatcher", package.seeall)
31 -- Local dispatch database
32 local tree = {nodes={}}
38 local indexcache = "/tmp/.luciindex"
40 -- Global request object
43 -- Active dispatched node
52 function build_url(...)
53 return luci.http.dispatcher() .. "/" .. table.concat(arg, "/")
56 -- Sends a 404 error code and renders the "error404" template if available
57 function error404(message)
58 luci.http.status(404, "Not Found")
59 message = message or "Not Found"
61 require("luci.template")
62 if not pcall(luci.template.render, "error404") then
63 luci.http.prepare_content("text/plain")
69 -- Sends a 500 error code and renders the "error500" template if available
70 function error500(message)
71 luci.http.status(500, "Internal Server Error")
73 require("luci.template")
74 if not pcall(luci.template.render, "error500", {message=message}) then
75 luci.http.prepare_content("text/plain")
81 -- Creates a request object for dispatching
82 function httpdispatch()
83 local pathinfo = luci.http.env.PATH_INFO or ""
86 for s in pathinfo:gmatch("([%w_]+)") do
87 table.insert(request, s)
93 -- Dispatches a request
95 if not built_tree then
102 for i, s in ipairs(request) do
108 for k, v in pairs(c) do
115 require("luci.i18n").loadc(track.i18n)
118 if track.setgroup then
119 luci.sys.process.setgroup(track.setgroup)
122 if track.setuser then
123 luci.sys.process.setuser(track.setuser)
126 -- Init template engine
127 local tpl = require("luci.template")
128 tpl.viewns.translate = function(...) return require("luci.i18n").translate(...) end
129 tpl.viewns.controller = luci.http.dispatcher()
130 tpl.viewns.uploadctrl = luci.http.dispatcher_upload()
131 tpl.viewns.media = luci.config.main.mediaurlbase
132 tpl.viewns.resource = luci.config.main.resourcebase
134 -- Load default translation
135 require("luci.i18n").loadc("default")
138 if c and type(c.target) == "function" then
140 stat, mod = pcall(require, c.module)
142 luci.util.updfenv(c.target, mod)
145 stat, err = pcall(c.target)
154 -- Generates the dispatching tree
155 function createindex()
157 local path = luci.sys.libpath() .. "/controller/"
160 if pcall(require, "fastindex") then
161 createindex_fastindex(path, suff)
163 createindex_plain(path, suff)
169 -- Uses fastindex to create the dispatching tree
170 function createindex_fastindex(path, suffix)
171 local fi = fastindex.new("index")
172 fi.add(path .. "*" .. suffix)
173 fi.add(path .. "*/*" .. suffix)
176 for k, v in pairs(fi.indexes) do
181 -- Calls the index function of all available controllers
182 function createindex_plain(path, suffix)
183 local cachetime = nil
185 local controllers = luci.util.combine(
186 luci.fs.glob(path .. "*" .. suffix) or {},
187 luci.fs.glob(path .. "*/*" .. suffix) or {}
191 cachetime = luci.fs.mtime(indexcache)
193 if not cachetime then
194 luci.fs.mkdir(indexcache)
195 luci.fs.chmod(indexcache, "a=,u=rwx")
199 if not cachetime then
200 for i,c in ipairs(controllers) do
201 c = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".")
202 stat, mod = pcall(require, c)
204 if stat and mod and type(mod.index) == "function" then
208 luci.fs.writefile(indexcache .. "/" .. c, string.dump(mod.index))
213 for i,c in ipairs(luci.fs.dir(indexcache)) do
214 if c:sub(1) ~= "." then
215 index[c] = loadfile(indexcache .. "/" .. c)
221 -- Creates the dispatching tree from the index
222 function createtree()
223 if not built_index then
227 for k, v in pairs(index) do
228 luci.util.updfenv(v, _M)
229 luci.util.extfenv(v, "_NAME", k)
236 -- Shortcut for creating a dispatching node
237 function entry(path, target, title, order, add)
244 c.module = getfenv(2)._NAME
246 for k,v in pairs(add) do
253 -- Fetch a dispatching node
257 if arg[1] and type(arg[1]) == "table" then
261 for k,v in ipairs(arg) do
262 if not c.nodes[v] then
263 c.nodes[v] = {nodes={}, module=getfenv(2)._NAME}
282 return function() getfenv()[name]() end
285 function template(name)
286 require("luci.template")
287 return function() luci.template.render(name) end
292 require("luci.template")
295 local stat, res = pcall(luci.cbi.load, model)
301 local stat, err = pcall(res.parse, res)
307 luci.template.render("cbi/header")
309 luci.template.render("cbi/footer")