General optimizations, simplifications and improvements
This commit is contained in:
parent
5cfda95377
commit
ffd5c4ec65
4 changed files with 138 additions and 129 deletions
|
@ -24,8 +24,21 @@ limitations under the License.
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
local io = require "io"
|
||||||
|
local table = require "table"
|
||||||
|
local debug = require "debug"
|
||||||
|
local string = require "string"
|
||||||
|
local coroutine = require "coroutine"
|
||||||
|
|
||||||
|
local getmetatable, setmetatable = getmetatable, setmetatable
|
||||||
|
local getfenv, setfenv = getfenv, setfenv
|
||||||
|
local rawget, rawset, unpack = rawget, rawset, unpack
|
||||||
|
local tostring, type, assert = tostring, type, assert
|
||||||
|
local ipairs, pairs, loadstring = ipairs, pairs, loadstring
|
||||||
|
local require, pcall, xpcall = require, pcall, xpcall
|
||||||
|
|
||||||
--- LuCI utility functions.
|
--- LuCI utility functions.
|
||||||
module("luci.util", package.seeall)
|
module "luci.util"
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Pythonic string formatting extension
|
-- Pythonic string formatting extension
|
||||||
|
@ -63,14 +76,10 @@ function class(base)
|
||||||
local class = {}
|
local class = {}
|
||||||
|
|
||||||
local create = function(class, ...)
|
local create = function(class, ...)
|
||||||
local inst = {}
|
local inst = setmetatable({}, {__index = class})
|
||||||
setmetatable(inst, {__index = class})
|
|
||||||
|
|
||||||
if inst.__init__ then
|
if inst.__init__ then
|
||||||
local stat, err = copcall(inst.__init__, inst, ...)
|
inst:__init__(...)
|
||||||
if not stat then
|
|
||||||
error(err)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return inst
|
return inst
|
||||||
|
@ -284,8 +293,7 @@ end
|
||||||
-- @param str String value containing whitespace padded data
|
-- @param str String value containing whitespace padded data
|
||||||
-- @return String value with leading and trailing space removed
|
-- @return String value with leading and trailing space removed
|
||||||
function trim(str)
|
function trim(str)
|
||||||
local s = str:gsub("^%s*(.-)%s*$", "%1")
|
return (str:gsub("^%s*(.-)%s*$", "%1"))
|
||||||
return s
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Parse certain units from the given string and return the canonical integer
|
--- Parse certain units from the given string and return the canonical integer
|
||||||
|
@ -413,9 +421,7 @@ function clone(object, deep)
|
||||||
copy[k] = v
|
copy[k] = v
|
||||||
end
|
end
|
||||||
|
|
||||||
setmetatable(copy, getmetatable(object))
|
return setmetatable(copy, getmetatable(object))
|
||||||
|
|
||||||
return copy
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
@ -473,11 +479,11 @@ function serialize_data(val, seen)
|
||||||
elseif type(val) == "number" then
|
elseif type(val) == "number" then
|
||||||
return val
|
return val
|
||||||
elseif type(val) == "string" then
|
elseif type(val) == "string" then
|
||||||
return string.format("%q", val)
|
return "%q" % val
|
||||||
elseif type(val) == "boolean" then
|
elseif type(val) == "boolean" then
|
||||||
return val and "true" or "false"
|
return val and "true" or "false"
|
||||||
elseif type(val) == "function" then
|
elseif type(val) == "function" then
|
||||||
return string.format("loadstring(%q)", get_bytecode(val))
|
return "loadstring(%q)" % get_bytecode(val)
|
||||||
elseif type(val) == "table" then
|
elseif type(val) == "table" then
|
||||||
return "{ " .. _serialize_table(val, seen) .. " }"
|
return "{ " .. _serialize_table(val, seen) .. " }"
|
||||||
else
|
else
|
||||||
|
@ -691,7 +697,7 @@ end
|
||||||
--- Returns the absolute path to LuCI base directory.
|
--- Returns the absolute path to LuCI base directory.
|
||||||
-- @return String containing the directory path
|
-- @return String containing the directory path
|
||||||
function libpath()
|
function libpath()
|
||||||
return luci.fs.dirname(require("luci.debug").__file__)
|
return require "luci.fs".dirname(require "luci.debug".__file__)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,13 +25,13 @@ limitations under the License.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
--- LuCI web dispatcher.
|
--- LuCI web dispatcher.
|
||||||
module("luci.dispatcher", package.seeall)
|
local fs = require "luci.fs"
|
||||||
require("luci.util")
|
local sys = require "luci.sys"
|
||||||
require("luci.init")
|
local init = require "luci.init"
|
||||||
require("luci.http")
|
local util = require "luci.util"
|
||||||
require("luci.sys")
|
local http = require "luci.http"
|
||||||
require("luci.fs")
|
|
||||||
|
|
||||||
|
module("luci.dispatcher", package.seeall)
|
||||||
context = luci.util.threadlocal()
|
context = luci.util.threadlocal()
|
||||||
|
|
||||||
authenticator = {}
|
authenticator = {}
|
||||||
|
@ -106,23 +106,28 @@ function httpdispatch(request)
|
||||||
table.insert(context.request, node)
|
table.insert(context.request, node)
|
||||||
end
|
end
|
||||||
|
|
||||||
dispatch(context.request)
|
local stat, err = util.copcall(dispatch, context.request)
|
||||||
|
if not stat then
|
||||||
|
error500(err)
|
||||||
|
end
|
||||||
|
|
||||||
luci.http.close()
|
luci.http.close()
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Dispatches a LuCI virtual path.
|
--- Dispatches a LuCI virtual path.
|
||||||
-- @param request Virtual path
|
-- @param request Virtual path
|
||||||
function dispatch(request)
|
function dispatch(request)
|
||||||
context.path = request
|
local ctx = context
|
||||||
|
ctx.path = request
|
||||||
|
|
||||||
require("luci.i18n")
|
require "luci.i18n".setlanguage(require "luci.config".main.lang)
|
||||||
luci.i18n.setlanguage(require("luci.config").main.lang)
|
|
||||||
|
|
||||||
if not context.tree then
|
local c = ctx.tree
|
||||||
createtree()
|
local stat
|
||||||
|
if not c then
|
||||||
|
c = createtree()
|
||||||
end
|
end
|
||||||
|
|
||||||
local c = context.tree
|
|
||||||
local track = {}
|
local track = {}
|
||||||
local args = {}
|
local args = {}
|
||||||
context.args = args
|
context.args = args
|
||||||
|
@ -135,9 +140,7 @@ function dispatch(request)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
for k, v in pairs(c) do
|
util.update(track, c)
|
||||||
track[k] = v
|
|
||||||
end
|
|
||||||
|
|
||||||
if c.leaf then
|
if c.leaf then
|
||||||
break
|
break
|
||||||
|
@ -155,46 +158,44 @@ function dispatch(request)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Init template engine
|
-- Init template engine
|
||||||
local tpl = require("luci.template")
|
if not track.notemplate then
|
||||||
local viewns = {}
|
local tpl = require("luci.template")
|
||||||
tpl.context.viewns = viewns
|
local viewns = {}
|
||||||
viewns.write = luci.http.write
|
tpl.context.viewns = viewns
|
||||||
viewns.translate = function(...) return require("luci.i18n").translate(...) end
|
viewns.write = luci.http.write
|
||||||
viewns.striptags = luci.util.striptags
|
viewns.translate = function(...) return require("luci.i18n").translate(...) end
|
||||||
viewns.controller = luci.http.getenv("SCRIPT_NAME")
|
viewns.striptags = util.striptags
|
||||||
viewns.media = luci.config.main.mediaurlbase
|
viewns.controller = luci.http.getenv("SCRIPT_NAME")
|
||||||
viewns.resource = luci.config.main.resourcebase
|
viewns.media = luci.config.main.mediaurlbase
|
||||||
viewns.REQUEST_URI = (luci.http.getenv("SCRIPT_NAME") or "") .. (luci.http.getenv("PATH_INFO") or "")
|
viewns.resource = luci.config.main.resourcebase
|
||||||
|
viewns.REQUEST_URI = (luci.http.getenv("SCRIPT_NAME") or "") .. (luci.http.getenv("PATH_INFO") or "")
|
||||||
if track.dependent then
|
|
||||||
local stat, err = pcall(assert, not track.auto)
|
|
||||||
if not stat then
|
|
||||||
error500(err)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert(not track.dependent or not track.auto, "Access Violation")
|
||||||
|
|
||||||
if track.sysauth then
|
if track.sysauth then
|
||||||
require("luci.sauth")
|
local sauth = require "luci.sauth"
|
||||||
|
|
||||||
local authen = type(track.sysauth_authenticator) == "function"
|
local authen = type(track.sysauth_authenticator) == "function"
|
||||||
and track.sysauth_authenticator
|
and track.sysauth_authenticator
|
||||||
or authenticator[track.sysauth_authenticator]
|
or authenticator[track.sysauth_authenticator]
|
||||||
|
|
||||||
local def = (type(track.sysauth) == "string") and track.sysauth
|
local def = (type(track.sysauth) == "string") and track.sysauth
|
||||||
local accs = def and {track.sysauth} or track.sysauth
|
local accs = def and {track.sysauth} or track.sysauth
|
||||||
local sess = luci.http.getcookie("sysauth")
|
local sess = luci.http.getcookie("sysauth")
|
||||||
sess = sess and sess:match("^[A-F0-9]+$")
|
sess = sess and sess:match("^[A-F0-9]+$")
|
||||||
local user = luci.sauth.read(sess)
|
local user = sauth.read(sess)
|
||||||
|
|
||||||
if not luci.util.contains(accs, user) then
|
if not util.contains(accs, user) then
|
||||||
if authen then
|
if authen then
|
||||||
local user, sess = authen(luci.sys.user.checkpasswd, accs, def)
|
local user, sess = authen(luci.sys.user.checkpasswd, accs, def)
|
||||||
if not user or not luci.util.contains(accs, user) then
|
if not user or not util.contains(accs, user) then
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
local sid = sess or luci.sys.uniqueid(16)
|
local sid = sess or luci.sys.uniqueid(16)
|
||||||
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
|
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
|
||||||
if not sess then
|
if not sess then
|
||||||
luci.sauth.write(sid, user)
|
sauth.write(sid, user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
@ -214,15 +215,12 @@ function dispatch(request)
|
||||||
|
|
||||||
if c and type(c.target) == "function" then
|
if c and type(c.target) == "function" then
|
||||||
context.dispatched = c
|
context.dispatched = c
|
||||||
stat, mod = luci.util.copcall(require, c.module)
|
|
||||||
if stat then
|
|
||||||
luci.util.updfenv(c.target, mod)
|
|
||||||
end
|
|
||||||
|
|
||||||
stat, err = luci.util.copcall(c.target, unpack(args))
|
util.copcall(function()
|
||||||
if not stat then
|
util.updfenv(c.target, require(c.module))
|
||||||
error500(err)
|
end)
|
||||||
end
|
|
||||||
|
c.target(unpack(args))
|
||||||
else
|
else
|
||||||
error404()
|
error404()
|
||||||
end
|
end
|
||||||
|
@ -262,50 +260,33 @@ end
|
||||||
-- @param path Controller base directory
|
-- @param path Controller base directory
|
||||||
-- @param suffix Controller file suffix
|
-- @param suffix Controller file suffix
|
||||||
function createindex_plain(path, suffix)
|
function createindex_plain(path, suffix)
|
||||||
|
if indexcache then
|
||||||
|
local cachedate = fs.mtime(indexcache)
|
||||||
|
if cachedate and cachedate > fs.mtime(path) then
|
||||||
|
index = loadfile(indexcache)()
|
||||||
|
return index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
index = {}
|
index = {}
|
||||||
|
|
||||||
local cache = nil
|
local controllers = util.combine(
|
||||||
|
|
||||||
local controllers = luci.util.combine(
|
|
||||||
luci.fs.glob(path .. "*" .. suffix) or {},
|
luci.fs.glob(path .. "*" .. suffix) or {},
|
||||||
luci.fs.glob(path .. "*/*" .. suffix) or {}
|
luci.fs.glob(path .. "*/*" .. suffix) or {}
|
||||||
)
|
)
|
||||||
|
|
||||||
if indexcache then
|
|
||||||
cache = luci.fs.mtime(indexcache)
|
|
||||||
|
|
||||||
if not cache then
|
|
||||||
luci.fs.mkdir(indexcache)
|
|
||||||
luci.fs.chmod(indexcache, "a=,u=rwx")
|
|
||||||
cache = luci.fs.mtime(indexcache)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for i,c in ipairs(controllers) do
|
for i,c in ipairs(controllers) do
|
||||||
local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".")
|
local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".")
|
||||||
local cachefile
|
local mod = require(module)
|
||||||
local stime
|
local idx = mod.index
|
||||||
local ctime
|
|
||||||
|
|
||||||
if cache then
|
if type(idx) == "function" then
|
||||||
cachefile = indexcache .. "/" .. module
|
index[module] = idx
|
||||||
stime = luci.fs.mtime(c) or 0
|
|
||||||
ctime = luci.fs.mtime(cachefile) or 0
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
if not cache or stime > ctime then
|
|
||||||
stat, mod = luci.util.copcall(require, module)
|
|
||||||
|
|
||||||
if stat and mod and type(mod.index) == "function" then
|
if indexcache then
|
||||||
index[module] = mod.index
|
fs.writefile(indexcache, util.get_bytecode(index))
|
||||||
|
|
||||||
if cache then
|
|
||||||
luci.fs.writefile(cachefile, luci.util.get_bytecode(mod.index))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
index[module] = loadfile(cachefile)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -316,14 +297,17 @@ function createtree()
|
||||||
createindex()
|
createindex()
|
||||||
end
|
end
|
||||||
|
|
||||||
context.tree = {nodes={}}
|
local ctx = context
|
||||||
require("luci.i18n")
|
local tree = {nodes={}}
|
||||||
|
|
||||||
-- Load default translation
|
|
||||||
luci.i18n.loadc("default")
|
|
||||||
|
|
||||||
local scope = luci.util.clone(_G)
|
ctx.treecache = setmetatable({}, {__mode="v"})
|
||||||
for k,v in pairs(luci.dispatcher) do
|
ctx.tree = tree
|
||||||
|
|
||||||
|
-- Load default translation
|
||||||
|
require "luci.i18n".loadc("default")
|
||||||
|
|
||||||
|
local scope = setmetatable({}, {__index = _G})
|
||||||
|
for k,v in pairs(_M) do
|
||||||
if type(v) == "function" then
|
if type(v) == "function" then
|
||||||
scope[k] = v
|
scope[k] = v
|
||||||
end
|
end
|
||||||
|
@ -332,14 +316,10 @@ function createtree()
|
||||||
for k, v in pairs(index) do
|
for k, v in pairs(index) do
|
||||||
scope._NAME = k
|
scope._NAME = k
|
||||||
setfenv(v, scope)
|
setfenv(v, scope)
|
||||||
|
v()
|
||||||
local stat, err = luci.util.copcall(v)
|
|
||||||
if not stat then
|
|
||||||
error500("createtree failed: " .. k .. ": " .. err)
|
|
||||||
luci.http.close()
|
|
||||||
os.exit(1)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
return tree
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Clone a node of the dispatching tree to another position.
|
--- Clone a node of the dispatching tree to another position.
|
||||||
|
@ -391,16 +371,7 @@ end
|
||||||
-- @param ... Virtual path
|
-- @param ... Virtual path
|
||||||
-- @return Dispatching tree node
|
-- @return Dispatching tree node
|
||||||
function node(...)
|
function node(...)
|
||||||
local c = context.tree
|
local c = _create_node(arg)
|
||||||
arg.n = nil
|
|
||||||
|
|
||||||
for k,v in ipairs(arg) do
|
|
||||||
if not c.nodes[v] then
|
|
||||||
c.nodes[v] = {nodes={}, auto=true}
|
|
||||||
end
|
|
||||||
|
|
||||||
c = c.nodes[v]
|
|
||||||
end
|
|
||||||
|
|
||||||
c.module = getfenv(2)._NAME
|
c.module = getfenv(2)._NAME
|
||||||
c.path = arg
|
c.path = arg
|
||||||
|
@ -409,6 +380,29 @@ function node(...)
|
||||||
return c
|
return c
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function _create_node(path, cache)
|
||||||
|
if #path == 0 then
|
||||||
|
return context.tree
|
||||||
|
end
|
||||||
|
|
||||||
|
cache = cache or context.treecache
|
||||||
|
local name = table.concat(path, ".")
|
||||||
|
local c = cache[name]
|
||||||
|
|
||||||
|
if not c then
|
||||||
|
local last = table.remove(path)
|
||||||
|
c = _create_node(path, cache)
|
||||||
|
|
||||||
|
local new = {nodes={}, auto=true}
|
||||||
|
c.nodes[last] = new
|
||||||
|
cache[name] = new
|
||||||
|
|
||||||
|
return new
|
||||||
|
else
|
||||||
|
return c
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Subdispatchers --
|
-- Subdispatchers --
|
||||||
|
|
||||||
--- Create a redirect to another dispatching node.
|
--- Create a redirect to another dispatching node.
|
||||||
|
|
|
@ -24,15 +24,20 @@ limitations under the License.
|
||||||
|
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
|
local ltn12 = require "luci.ltn12"
|
||||||
|
local proto = require "luci.http.protocol"
|
||||||
|
local util = require "luci.util"
|
||||||
|
local string = require "string"
|
||||||
|
local coroutine = require "coroutine"
|
||||||
|
|
||||||
|
local pairs, tostring, error = pairs, tostring, error
|
||||||
|
|
||||||
--- LuCI Web Framework high-level HTTP functions.
|
--- LuCI Web Framework high-level HTTP functions.
|
||||||
module("luci.http", package.seeall)
|
module "luci.http"
|
||||||
local ltn12 = require("luci.ltn12")
|
|
||||||
require("luci.http.protocol")
|
|
||||||
require("luci.util")
|
|
||||||
|
|
||||||
context = luci.util.threadlocal()
|
context = util.threadlocal()
|
||||||
|
|
||||||
Request = luci.util.class()
|
Request = util.class()
|
||||||
function Request.__init__(self, env, sourcein, sinkerr)
|
function Request.__init__(self, env, sourcein, sinkerr)
|
||||||
self.input = sourcein
|
self.input = sourcein
|
||||||
self.error = sinkerr
|
self.error = sinkerr
|
||||||
|
@ -45,7 +50,7 @@ function Request.__init__(self, env, sourcein, sinkerr)
|
||||||
self.message = {
|
self.message = {
|
||||||
env = env,
|
env = env,
|
||||||
headers = {},
|
headers = {},
|
||||||
params = luci.http.protocol.urldecode_params(env.QUERY_STRING or ""),
|
params = protocol.urldecode_params(env.QUERY_STRING or ""),
|
||||||
}
|
}
|
||||||
|
|
||||||
self.parsed_input = false
|
self.parsed_input = false
|
||||||
|
@ -109,7 +114,7 @@ function Request.setfilehandler(self, callback)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Request._parse_input(self)
|
function Request._parse_input(self)
|
||||||
luci.http.protocol.parse_message_body(
|
protocol.parse_message_body(
|
||||||
self.input,
|
self.input,
|
||||||
self.message,
|
self.message,
|
||||||
self.filehandler
|
self.filehandler
|
||||||
|
@ -277,10 +282,10 @@ end
|
||||||
-- @param no_plus Don't decode + to " "
|
-- @param no_plus Don't decode + to " "
|
||||||
-- @return URL-decoded string
|
-- @return URL-decoded string
|
||||||
-- @see urlencode
|
-- @see urlencode
|
||||||
urldecode = luci.http.protocol.urldecode
|
urldecode = protocol.urldecode
|
||||||
|
|
||||||
--- Return the URL-encoded equivalent of a string.
|
--- Return the URL-encoded equivalent of a string.
|
||||||
-- @param str Source string
|
-- @param str Source string
|
||||||
-- @return URL-encoded string
|
-- @return URL-encoded string
|
||||||
-- @see urldecode
|
-- @see urldecode
|
||||||
urlencode = luci.http.protocol.urlencode
|
urlencode = protocol.urlencode
|
||||||
|
|
|
@ -36,20 +36,24 @@ function index()
|
||||||
uci = entry({"rpc", "uci"}, call("rpc_uci"))
|
uci = entry({"rpc", "uci"}, call("rpc_uci"))
|
||||||
uci.sysauth = "root"
|
uci.sysauth = "root"
|
||||||
uci.sysauth_authenticator = authenticator
|
uci.sysauth_authenticator = authenticator
|
||||||
|
uci.notemplate = true
|
||||||
|
|
||||||
fs = entry({"rpc", "fs"}, call("rpc_fs"))
|
fs = entry({"rpc", "fs"}, call("rpc_fs"))
|
||||||
fs.sysauth = "root"
|
fs.sysauth = "root"
|
||||||
fs.sysauth_authenticator = authenticator
|
fs.sysauth_authenticator = authenticator
|
||||||
|
fs.notemplate = true
|
||||||
|
|
||||||
sys = entry({"rpc", "sys"}, call("rpc_sys"))
|
sys = entry({"rpc", "sys"}, call("rpc_sys"))
|
||||||
sys.sysauth = "root"
|
sys.sysauth = "root"
|
||||||
sys.sysauth_authenticator = authenticator
|
sys.sysauth_authenticator = authenticator
|
||||||
|
sys.notemplate = true
|
||||||
|
|
||||||
ipkg = entry({"rpc", "ipkg"}, call("rpc_ipkg"))
|
ipkg = entry({"rpc", "ipkg"}, call("rpc_ipkg"))
|
||||||
ipkg.sysauth = "root"
|
ipkg.sysauth = "root"
|
||||||
ipkg.sysauth_authenticator = authenticator
|
ipkg.sysauth_authenticator = authenticator
|
||||||
|
ipkg.notemplate = true
|
||||||
|
|
||||||
uci = entry({"rpc", "auth"}, call("rpc_auth"))
|
entry({"rpc", "auth"}, call("rpc_auth")).notemplate = true
|
||||||
end
|
end
|
||||||
|
|
||||||
function rpc_auth()
|
function rpc_auth()
|
||||||
|
|
Loading…
Reference in a new issue