]]--
-local fs = require"luci.fs"
+local fs = require "nixio.fs"
local sys = require "luci.sys"
local util = require "luci.util"
local table = require "table"
local string = require "string"
local config = require "luci.config"
local coroutine = require "coroutine"
+local nixio = require "nixio", require "nixio.util"
local tostring, pairs, loadstring = tostring, pairs, loadstring
local setmetatable, loadfile = setmetatable, loadfile
-local getfenv, setfenv = getfenv, setfenv
+local getfenv, setfenv, rawget = getfenv, setfenv, rawget
local assert, type, error = assert, type, error
--- LuCI template library.
-- Define the namespace for template modules
context = util.threadlocal()
-viewns = {
- include = function(name) Template(name):render(getfenv(2)) end,
-}
-
--- Manually compile a given template into an executable Lua function
-- @param template LuCI template
-- @return Lua template function
-- Search all <% %> expressions
local function expr_add(ws1, skip1, command, skip2, ws2)
- table.insert(expr, command)
+ expr[#expr+1] = command
return ( #skip1 > 0 and "" or ws1 ) ..
"<%" .. tostring(#expr) .. "%>" ..
( #skip2 > 0 and "" or ws2 )
-- Replacements
local r_include = '")\ninclude("%s")\nwrite("'
- local r_i18n = '"..translate("%1","%2").."'
- local r_i18n2 = '"..translate("%1", "").."'
- local r_pexec = '"..(%s or "").."'
+ local r_i18n = '")\nwrite(translate("%1","%2"))\nwrite("'
+ local r_i18n2 = '")\nwrite(translate("%1", ""))\nwrite("'
+ local r_pexec = '")\nwrite(tostring(%s or ""))\nwrite("'
local r_exec = '")\n%s\nwrite("'
-- Parse the expressions
self.name = name
-- Create a new namespace for this template
- self.viewns = {sink=self.sink}
-
- -- Copy over from general namespace
- util.update(self.viewns, viewns)
- if context.viewns then
- util.update(self.viewns, context.viewns)
- end
+ self.viewns = context.viewns
-- If we have a cached template, skip compiling and loading
if self.template then
local err
if compiler_mode == "file" then
- local tplmt = fs.mtime(sourcefile) or fs.mtime(sourcefile .. ".htm")
- local commt = fs.mtime(compiledfile)
+ local tplmt = fs.stat(sourcefile, "mtime") or fs.stat(sourcefile .. ".htm", "mtime")
+ local commt = fs.stat(compiledfile, "mtime")
if not fs.mtime(cdir) then
- fs.mkdir(cdir, true)
- fs.chmod(fs.dirname(cdir), "a+rxw")
+ fs.mkdirr(cdir)
+ fs.chmod(fs.dirname(cdir), 777)
end
assert(tplmt or commt, "No such template: " .. name)
-- Build if there is no compiled file or if compiled file is outdated
- if not commt or (commt and tplmt and commt < tplmt) then
+ if not commt or (commt and tplmt and commt < tplmt) then
local source
source, err = fs.readfile(sourcefile) or fs.readfile(sourcefile .. ".htm")
if source then
local compiled, err = compile(source)
- fs.writefile(compiledfile, util.get_bytecode(compiled))
- fs.chmod(compiledfile, "a-rwx,u+rw")
+ local f = nixio.open(compiledfile, "w", 600)
+ f:writeall(util.get_bytecode(compiled))
+ f:close()
self.template = compiled
end
else
assert(
sys.process.info("uid") == fs.stat(compiledfile, "uid")
- and fs.stat(compiledfile, "mode") == "rw-------",
+ and fs.stat(compiledfile, "modestr") == "rw-------",
"Fatal: Cachefile is not sane!"
)
self.template, err = loadfile(compiledfile)
function Template.render(self, scope)
scope = scope or getfenv(2)
- -- Save old environment
- local oldfenv = getfenv(self.template)
-
-- Put our predefined objects in the scope of the template
- util.resfenv(self.template)
- util.updfenv(self.template, scope)
- util.updfenv(self.template, self.viewns)
+ setfenv(self.template, setmetatable({}, {__index =
+ function(tbl, key)
+ return rawget(tbl, key) or self.viewns[key] or scope[key]
+ end}))
-- Now finally render the thing
local stat, err = util.copcall(self.template)
if not stat then
- setfenv(self.template, oldfenv)
error("Error in template %s: %s" % {self.name, err})
end
-
- -- Reset environment
- setfenv(self.template, oldfenv)
end