General optimizations, simplifications and improvements

This commit is contained in:
Steven Barth 2008-08-29 23:26:01 +00:00
parent 5cfda95377
commit ffd5c4ec65
4 changed files with 138 additions and 129 deletions

View file

@ -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.
module("luci.util", package.seeall)
module "luci.util"
--
-- Pythonic string formatting extension
@ -63,14 +76,10 @@ function class(base)
local class = {}
local create = function(class, ...)
local inst = {}
setmetatable(inst, {__index = class})
local inst = setmetatable({}, {__index = class})
if inst.__init__ then
local stat, err = copcall(inst.__init__, inst, ...)
if not stat then
error(err)
end
inst:__init__(...)
end
return inst
@ -284,8 +293,7 @@ end
-- @param str String value containing whitespace padded data
-- @return String value with leading and trailing space removed
function trim(str)
local s = str:gsub("^%s*(.-)%s*$", "%1")
return s
return (str:gsub("^%s*(.-)%s*$", "%1"))
end
--- Parse certain units from the given string and return the canonical integer
@ -413,9 +421,7 @@ function clone(object, deep)
copy[k] = v
end
setmetatable(copy, getmetatable(object))
return copy
return setmetatable(copy, getmetatable(object))
end
@ -473,11 +479,11 @@ function serialize_data(val, seen)
elseif type(val) == "number" then
return val
elseif type(val) == "string" then
return string.format("%q", val)
return "%q" % val
elseif type(val) == "boolean" then
return val and "true" or "false"
elseif type(val) == "function" then
return string.format("loadstring(%q)", get_bytecode(val))
return "loadstring(%q)" % get_bytecode(val)
elseif type(val) == "table" then
return "{ " .. _serialize_table(val, seen) .. " }"
else
@ -691,7 +697,7 @@ end
--- Returns the absolute path to LuCI base directory.
-- @return String containing the directory path
function libpath()
return luci.fs.dirname(require("luci.debug").__file__)
return require "luci.fs".dirname(require "luci.debug".__file__)
end

View file

@ -25,13 +25,13 @@ limitations under the License.
]]--
--- LuCI web dispatcher.
module("luci.dispatcher", package.seeall)
require("luci.util")
require("luci.init")
require("luci.http")
require("luci.sys")
require("luci.fs")
local fs = require "luci.fs"
local sys = require "luci.sys"
local init = require "luci.init"
local util = require "luci.util"
local http = require "luci.http"
module("luci.dispatcher", package.seeall)
context = luci.util.threadlocal()
authenticator = {}
@ -106,23 +106,28 @@ function httpdispatch(request)
table.insert(context.request, node)
end
dispatch(context.request)
local stat, err = util.copcall(dispatch, context.request)
if not stat then
error500(err)
end
luci.http.close()
end
--- Dispatches a LuCI virtual path.
-- @param request Virtual path
function dispatch(request)
context.path = request
local ctx = context
ctx.path = request
require("luci.i18n")
luci.i18n.setlanguage(require("luci.config").main.lang)
require "luci.i18n".setlanguage(require "luci.config".main.lang)
if not context.tree then
createtree()
local c = ctx.tree
local stat
if not c then
c = createtree()
end
local c = context.tree
local track = {}
local args = {}
context.args = args
@ -135,9 +140,7 @@ function dispatch(request)
break
end
for k, v in pairs(c) do
track[k] = v
end
util.update(track, c)
if c.leaf then
break
@ -155,46 +158,44 @@ function dispatch(request)
end
-- Init template engine
local tpl = require("luci.template")
local viewns = {}
tpl.context.viewns = viewns
viewns.write = luci.http.write
viewns.translate = function(...) return require("luci.i18n").translate(...) end
viewns.striptags = luci.util.striptags
viewns.controller = luci.http.getenv("SCRIPT_NAME")
viewns.media = luci.config.main.mediaurlbase
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
if not track.notemplate then
local tpl = require("luci.template")
local viewns = {}
tpl.context.viewns = viewns
viewns.write = luci.http.write
viewns.translate = function(...) return require("luci.i18n").translate(...) end
viewns.striptags = util.striptags
viewns.controller = luci.http.getenv("SCRIPT_NAME")
viewns.media = luci.config.main.mediaurlbase
viewns.resource = luci.config.main.resourcebase
viewns.REQUEST_URI = (luci.http.getenv("SCRIPT_NAME") or "") .. (luci.http.getenv("PATH_INFO") or "")
end
assert(not track.dependent or not track.auto, "Access Violation")
if track.sysauth then
require("luci.sauth")
local sauth = require "luci.sauth"
local authen = type(track.sysauth_authenticator) == "function"
and track.sysauth_authenticator
or authenticator[track.sysauth_authenticator]
local def = (type(track.sysauth) == "string") and track.sysauth
local accs = def and {track.sysauth} or track.sysauth
local sess = luci.http.getcookie("sysauth")
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
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
else
local sid = sess or luci.sys.uniqueid(16)
luci.http.header("Set-Cookie", "sysauth=" .. sid.."; path=/")
if not sess then
luci.sauth.write(sid, user)
sauth.write(sid, user)
end
end
else
@ -214,15 +215,12 @@ function dispatch(request)
if c and type(c.target) == "function" then
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))
if not stat then
error500(err)
end
util.copcall(function()
util.updfenv(c.target, require(c.module))
end)
c.target(unpack(args))
else
error404()
end
@ -262,50 +260,33 @@ end
-- @param path Controller base directory
-- @param suffix Controller file 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 = {}
local cache = nil
local controllers = luci.util.combine(
local controllers = util.combine(
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
local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".")
local cachefile
local stime
local ctime
local mod = require(module)
local idx = mod.index
if cache then
cachefile = indexcache .. "/" .. module
stime = luci.fs.mtime(c) or 0
ctime = luci.fs.mtime(cachefile) or 0
if type(idx) == "function" then
index[module] = idx
end
if not cache or stime > ctime then
stat, mod = luci.util.copcall(require, module)
end
if stat and mod and type(mod.index) == "function" then
index[module] = mod.index
if cache then
luci.fs.writefile(cachefile, luci.util.get_bytecode(mod.index))
end
end
else
index[module] = loadfile(cachefile)
end
if indexcache then
fs.writefile(indexcache, util.get_bytecode(index))
end
end
@ -316,14 +297,17 @@ function createtree()
createindex()
end
context.tree = {nodes={}}
require("luci.i18n")
-- Load default translation
luci.i18n.loadc("default")
local ctx = context
local tree = {nodes={}}
local scope = luci.util.clone(_G)
for k,v in pairs(luci.dispatcher) do
ctx.treecache = setmetatable({}, {__mode="v"})
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
scope[k] = v
end
@ -332,14 +316,10 @@ function createtree()
for k, v in pairs(index) do
scope._NAME = k
setfenv(v, scope)
local stat, err = luci.util.copcall(v)
if not stat then
error500("createtree failed: " .. k .. ": " .. err)
luci.http.close()
os.exit(1)
end
v()
end
return tree
end
--- Clone a node of the dispatching tree to another position.
@ -391,16 +371,7 @@ end
-- @param ... Virtual path
-- @return Dispatching tree node
function node(...)
local c = context.tree
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
local c = _create_node(arg)
c.module = getfenv(2)._NAME
c.path = arg
@ -409,6 +380,29 @@ function node(...)
return c
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 --
--- Create a redirect to another dispatching node.

View file

@ -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.
module("luci.http", package.seeall)
local ltn12 = require("luci.ltn12")
require("luci.http.protocol")
require("luci.util")
module "luci.http"
context = luci.util.threadlocal()
context = util.threadlocal()
Request = luci.util.class()
Request = util.class()
function Request.__init__(self, env, sourcein, sinkerr)
self.input = sourcein
self.error = sinkerr
@ -45,7 +50,7 @@ function Request.__init__(self, env, sourcein, sinkerr)
self.message = {
env = env,
headers = {},
params = luci.http.protocol.urldecode_params(env.QUERY_STRING or ""),
params = protocol.urldecode_params(env.QUERY_STRING or ""),
}
self.parsed_input = false
@ -109,7 +114,7 @@ function Request.setfilehandler(self, callback)
end
function Request._parse_input(self)
luci.http.protocol.parse_message_body(
protocol.parse_message_body(
self.input,
self.message,
self.filehandler
@ -277,10 +282,10 @@ end
-- @param no_plus Don't decode + to " "
-- @return URL-decoded string
-- @see urlencode
urldecode = luci.http.protocol.urldecode
urldecode = protocol.urldecode
--- Return the URL-encoded equivalent of a string.
-- @param str Source string
-- @return URL-encoded string
-- @see urldecode
urlencode = luci.http.protocol.urlencode
urlencode = protocol.urlencode

View file

@ -36,20 +36,24 @@ function index()
uci = entry({"rpc", "uci"}, call("rpc_uci"))
uci.sysauth = "root"
uci.sysauth_authenticator = authenticator
uci.notemplate = true
fs = entry({"rpc", "fs"}, call("rpc_fs"))
fs.sysauth = "root"
fs.sysauth_authenticator = authenticator
fs.notemplate = true
sys = entry({"rpc", "sys"}, call("rpc_sys"))
sys.sysauth = "root"
sys.sysauth_authenticator = authenticator
sys.notemplate = true
ipkg = entry({"rpc", "ipkg"}, call("rpc_ipkg"))
ipkg.sysauth = "root"
ipkg.sysauth_authenticator = authenticator
ipkg.notemplate = true
uci = entry({"rpc", "auth"}, call("rpc_auth"))
entry({"rpc", "auth"}, call("rpc_auth")).notemplate = true
end
function rpc_auth()