convert luci.fs users to nixio.fs api
[project/luci.git] / libs / web / luasrc / template.lua
index e78bfb6..e8f65e3 100644 (file)
@@ -24,17 +24,18 @@ limitations under the License.
 
 ]]--
 
-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.
@@ -55,10 +56,6 @@ compiler_mode = config.template.compiler_mode or "memory"
 -- 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
@@ -67,7 +64,7 @@ function compile(template)
 
        -- 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 )
@@ -92,9 +89,9 @@ function compile(template)
        
        -- 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
@@ -139,7 +136,7 @@ Template.cache = setmetatable({}, {__mode = "v"})
 
 
 -- Constructor - Reads and compiles the template on-demand
-function Template.__init__(self, name, srcfile, comfile)       
+function Template.__init__(self, name) 
        local function _encode_filename(str)
 
                local function __chrenc( chr )
@@ -160,13 +157,7 @@ function Template.__init__(self, name, srcfile, comfile)
        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
@@ -177,36 +168,38 @@ function Template.__init__(self, name, srcfile, comfile)
        local cdir = compiledir .. "/" .. sys.process.info("uid")
        
        -- Compile and build
-       local sourcefile   = srcfile or (viewdir    .. "/" .. name .. ".htm")
-       local compiledfile = comfile or (cdir .. "/" .. _encode_filename(name) .. ".lua")
+       local sourcefile   = viewdir    .. "/" .. name
+       local compiledfile = cdir .. "/" .. _encode_filename(name) .. ".lua"
        local err       
        
        if compiler_mode == "file" then
-               local tplmt = fs.mtime(sourcefile)
-               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 ((commt == nil) and not (tplmt == nil))
-               or (not (commt == nil) and not (tplmt == nil) and commt < tplmt) then
+               if not commt or (commt and tplmt and commt < tplmt) then
                        local source
-                       source, err = fs.readfile(sourcefile)
+                       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)
@@ -214,7 +207,7 @@ function Template.__init__(self, name, srcfile, comfile)
                
        elseif compiler_mode == "memory" then
                local source
-               source, err = fs.readfile(sourcefile)
+               source, err = fs.readfile(sourcefile) or fs.readfile(sourcefile .. ".htm")
                if source then
                        self.template, err = compile(source)
                end
@@ -234,21 +227,15 @@ end
 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, chunk})
+               error("Error in template %s: %s" % {self.name, err})
        end
-       
-       -- Reset environment
-       setfenv(self.template, oldfenv)
 end