luci-base: error404: do not access request env directly
[project/luci.git] / modules / luci-base / luasrc / ccache.lua
1 -- Copyright 2008 Steven Barth <steven@midlink.org>
2 -- Copyright 2008 Jo-Philipp Wich <jow@openwrt.org>
3 -- Licensed to the public under the Apache License 2.0.
4
5 local io = require "io"
6 local fs = require "nixio.fs"
7 local util = require "luci.util"
8 local nixio = require "nixio"
9 local debug = require "debug"
10 local string = require "string"
11 local package = require "package"
12
13 local type, loadfile = type, loadfile
14
15
16 module "luci.ccache"
17
18 function cache_ondemand(...)
19         if debug.getinfo(1, 'S').source ~= "=?" then
20                 cache_enable(...)
21         end
22 end
23
24 function cache_enable(cachepath, mode)
25         cachepath = cachepath or "/tmp/luci-modulecache"
26         mode = mode or "r--r--r--"
27
28         local loader = package.loaders[2]
29         local uid    = nixio.getuid()
30
31         if not fs.stat(cachepath) then
32                 fs.mkdir(cachepath)
33         end
34
35         local function _encode_filename(name)
36                 local encoded = ""
37                 for i=1, #name do
38                         encoded = encoded .. ("%2X" % string.byte(name, i))
39                 end
40                 return encoded
41         end
42
43         local function _load_sane(file)
44                 local stat = fs.stat(file)
45                 if stat and stat.uid == uid and stat.modestr == mode then
46                         return loadfile(file)
47                 end
48         end
49
50         local function _write_sane(file, func)
51                 if nixio.getuid() == uid then
52                         local fp = io.open(file, "w")
53                         if fp then
54                                 fp:write(util.get_bytecode(func))
55                                 fp:close()
56                                 fs.chmod(file, mode)
57                         end
58                 end
59         end
60
61         package.loaders[2] = function(mod)
62                 local encoded = cachepath .. "/" .. _encode_filename(mod)
63                 local modcons = _load_sane(encoded)
64                 
65                 if modcons then
66                         return modcons
67                 end
68
69                 -- No cachefile
70                 modcons = loader(mod)
71                 if type(modcons) == "function" then
72                         _write_sane(encoded, modcons)
73                 end
74                 return modcons
75         end
76 end