summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorSteven Barth <steven@midlink.org>2008-06-14 14:12:12 +0000
committerSteven Barth <steven@midlink.org>2008-06-14 14:12:12 +0000
commit855b7582d3576f45693e3a48fdb253c813cf4dce (patch)
treeb912f63dc43f3b696385083542c801dba8c53976
parent50fd29841540bb8b1735291b72853454679e9e62 (diff)
* Rewrote Luci to be coroutine-safe allowing the use of non-forking webservers
* Setting base version to 0.7
-rw-r--r--Makefile2
-rw-r--r--NOTICE6
-rw-r--r--applications/luci-splash/luasrc/controller/splash/splash.lua2
-rw-r--r--applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua12
-rw-r--r--applications/luci-statistics/luasrc/statistics/rrdtool.lua4
-rw-r--r--build/config.mk7
-rw-r--r--build/module.mk6
-rw-r--r--contrib/luaposix/Makefile4
-rw-r--r--contrib/package/luci/Makefile2
-rw-r--r--libs/cbi/luasrc/view/cbi/header.htm2
-rw-r--r--libs/core/luasrc/init.lua2
-rw-r--r--libs/core/luasrc/util.lua79
-rw-r--r--libs/fastindex/Makefile4
-rw-r--r--libs/sgi-haserl/luasrc/sgi/haserl.lua107
-rwxr-xr-xlibs/sgi-haserl/root/www/cgi-bin/luci4
-rw-r--r--libs/sgi-webuci/luasrc/sgi/webuci.lua113
-rw-r--r--libs/sgi-webuci/root/usr/lib/boa/luci.lua3
-rw-r--r--libs/uci/luasrc/model/uci.lua2
-rw-r--r--libs/web/luasrc/dispatcher.lua116
-rw-r--r--libs/web/luasrc/http.lua136
-rw-r--r--libs/web/luasrc/i18n.lua29
-rw-r--r--libs/web/luasrc/template.lua14
-rw-r--r--modules/admin-core/luasrc/view/admin_system/upgrade.htm2
-rw-r--r--modules/admin-core/luasrc/view/error404.htm2
-rw-r--r--modules/freifunk/luasrc/controller/freifunk/luciinfo.lua22
-rw-r--r--themes/fledermaus/luasrc/view/themes/fledermaus/header.htm4
-rw-r--r--themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm4
27 files changed, 415 insertions, 275 deletions
diff --git a/Makefile b/Makefile
index 435d59c59..796bb4154 100644
--- a/Makefile
+++ b/Makefile
@@ -32,7 +32,7 @@ hostcopy:
mkdir -p host
for i in $(MODULES); do cp -a $$i/dist/* host/ -R 2>/dev/null || true; done
rm -f host/luci
- ln -s .$(LUCI_INSTALLDIR) host/luci
+ ln -s .$(LUCI_MODULEDIR) host/luci
run: host
libs/sgi-webuci/host/buildconfig.sh `pwd`/host > host/etc/boa/boa.conf
diff --git a/NOTICE b/NOTICE
index b9784e4a0..e2c3383e3 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,7 +1,13 @@
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
+Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0.
+Contains code from:
+BinDecHex - Copyright 2007 Tim Kelly/Dialectronics
+coxpcall - Copyright 2005 - Kepler Project (www.keplerproject.org)
+
+
Luci-Statistics - Statistics for LuCI
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
Licensed under the Apache License, Version 2.0.
diff --git a/applications/luci-splash/luasrc/controller/splash/splash.lua b/applications/luci-splash/luasrc/controller/splash/splash.lua
index e7448d7fb..617e0f877 100644
--- a/applications/luci-splash/luasrc/controller/splash/splash.lua
+++ b/applications/luci-splash/luasrc/controller/splash/splash.lua
@@ -12,7 +12,7 @@ function index()
end
function action_activate()
- local mac = luci.sys.net.ip4mac(luci.http.env.REMOTE_ADDR)
+ local mac = luci.sys.net.ip4mac(luci.http.getenv("REMOTE_ADDR"))
if mac and luci.http.formvalue("accept") then
os.execute("luci-splash add "..mac.." >/dev/null 2>&1")
luci.http.redirect(luci.model.uci.get("freifunk", "community", "homepage"))
diff --git a/applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua b/applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua
index be6430eed..36c6d9b57 100644
--- a/applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua
+++ b/applications/luci-statistics/luasrc/controller/luci_statistics/luci_statistics.lua
@@ -149,8 +149,8 @@ function statistics_render()
require("luci.model.uci")
local vars = luci.http.formvalues()
- local req = luci.dispatcher.request
- local path = luci.dispatcher.dispatched.path
+ local req = luci.dispatcher.context.request
+ local path = luci.dispatcher.context.dispatched.path
local uci = luci.model.uci
local spans = luci.util.split( uci.get( "luci_statistics", "collectd_rrdtool", "RRATimespans" ), "%s+", nil, true )
local span = vars.timespan or uci.get( "luci_statistics", "rrdtool", "default_timespan" ) or spans[1]
@@ -160,10 +160,10 @@ function statistics_render()
local images = { }
-- find requested plugin and instance
- for i, p in ipairs( luci.dispatcher.dispatched.path ) do
- if luci.dispatcher.dispatched.path[i] == "graph" then
- plugin = luci.dispatcher.dispatched.path[i+1]
- instances = { luci.dispatcher.dispatched.path[i+2] }
+ for i, p in ipairs( luci.dispatcher.context.dispatched.path ) do
+ if luci.dispatcher.context.dispatched.path[i] == "graph" then
+ plugin = luci.dispatcher.context.dispatched.path[i+1]
+ instances = { luci.dispatcher.context.dispatched.path[i+2] }
end
end
diff --git a/applications/luci-statistics/luasrc/statistics/rrdtool.lua b/applications/luci-statistics/luasrc/statistics/rrdtool.lua
index 69fb5cff6..433524583 100644
--- a/applications/luci-statistics/luasrc/statistics/rrdtool.lua
+++ b/applications/luci-statistics/luasrc/statistics/rrdtool.lua
@@ -500,7 +500,7 @@ function Graph.render( self, plugin, plugin_instance )
-- check for a whole graph handler
local plugin_def = "luci.statistics.rrdtool.definitions." .. plugin
- local stat, def = pcall( require, plugin_def )
+ local stat, def = luci.util.copcall( require, plugin_def )
if stat and def and type(def.rrdargs) == "function" then
@@ -539,7 +539,7 @@ function Graph.render( self, plugin, plugin_instance )
-- check for data type handler
local dtype_def = plugin_def .. "." .. dtype
- local stat, def = pcall( require, dtype_def )
+ local stat, def = luci.util.copcall( require, dtype_def )
if stat and def and type(def.rrdargs) == "function" then
diff --git a/build/config.mk b/build/config.mk
index 1755974f2..81d3e0836 100644
--- a/build/config.mk
+++ b/build/config.mk
@@ -1,4 +1,9 @@
LUAC = luac
LUAC_OPTIONS = -s
-LUCI_INSTALLDIR = /usr/lib/lua/luci
+
+LUA_MODULEDIR = /usr/lib/lua
+LUA_LIBRARYDIR = /usr/lib/lua
+
+LUCI_MODULEDIR = $(LUA_MODULEDIR)/luci
+LUCI_LIBRARYDIR = $(LUA_LIBRARYDIR)/luci
diff --git a/build/module.mk b/build/module.mk
index 7fe96cac5..4ef3668c8 100644
--- a/build/module.mk
+++ b/build/module.mk
@@ -12,9 +12,11 @@ compile:
clean: luaclean
luasource:
- mkdir -p dist$(LUCI_INSTALLDIR)
+ mkdir -p dist$(LUA_MODULEDIR)
+ mkdir -p dist$(LUCI_MODULEDIR)
cp -a root/* dist -R 2>/dev/null || true
- cp -a luasrc/* dist$(LUCI_INSTALLDIR) -R 2>/dev/null || true
+ cp -a luasrc/* dist$(LUCI_MODULEDIR) -R 2>/dev/null || true
+ cp -a lua/* dist$(LUA_MODULEDIR) -R 2>/dev/null || true
for i in $$(find dist -name .svn); do rm $$i -rf; done
luacompile: luasource
diff --git a/contrib/luaposix/Makefile b/contrib/luaposix/Makefile
index ec832cc2d..c357f5d2c 100644
--- a/contrib/luaposix/Makefile
+++ b/contrib/luaposix/Makefile
@@ -34,8 +34,8 @@ $(LUAPOSIX_DIR)/.patched: $(LUAPOSIX_DIR)/.prepared $(LUAPOSIX_PATCHDIR)/series
compile: $(LUAPOSIX_DIR)/.patched
$(MAKE) -C $(LUAPOSIX_DIR) CC=$(CC) CFLAGS="$(CFLAGS) $(LUA_CFLAGS)" LDFLAGS="$(LDFLAGS) $(LUA_SHLIBS)" OS="$(OS)"
- mkdir -p dist/usr/lib/lua
- cp $(LUAPOSIX_DIR)/posix.so dist/usr/lib/lua/
+ mkdir -p dist$(LUA_LIBRARYDIR)
+ cp $(LUAPOSIX_DIR)/posix.so dist$(LUA_LIBRARYDIR)
luasource:
compile-all: compile
diff --git a/contrib/package/luci/Makefile b/contrib/package/luci/Makefile
index af662f8cb..04229dac5 100644
--- a/contrib/package/luci/Makefile
+++ b/contrib/package/luci/Makefile
@@ -5,7 +5,7 @@ PKG_SOURCE_URL:=https://dev.leipzig.freifunk.net/svn/ff-luci/$(PKG_BRANCH)
PKG_REV:=$(shell LC_ALL=C svn info ${PKG_SOURCE_URL} | sed -ne's/^Last Changed Rev: //p')
PKG_NAME:=luci
-PKG_VERSION:=0.6+svn$(PKG_REV)
+PKG_VERSION:=0.7+svn$(PKG_REV)
PKG_RELEASE:=1
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_VERSION)
diff --git a/libs/cbi/luasrc/view/cbi/header.htm b/libs/cbi/luasrc/view/cbi/header.htm
index 0af52b49e..ca6ef2fdd 100644
--- a/libs/cbi/luasrc/view/cbi/header.htm
+++ b/libs/cbi/luasrc/view/cbi/header.htm
@@ -1,5 +1,5 @@
<%+header%>
- <form method="post" action="<%=luci.http.env.REQUEST_URI%>">
+ <form method="post" action="<%=luci.http.getenv("REQUEST_URI")%>">
<div>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<input type="hidden" name="cbi.submit" value="1" />
diff --git a/libs/core/luasrc/init.lua b/libs/core/luasrc/init.lua
index b390df3ac..b4ecb93c1 100644
--- a/libs/core/luasrc/init.lua
+++ b/libs/core/luasrc/init.lua
@@ -25,5 +25,5 @@ limitations under the License.
]]--
module("luci", package.seeall)
-__version__ = "0.6"
+__version__ = "0.7"
__appname__ = "LuCI"
diff --git a/libs/core/luasrc/util.lua b/libs/core/luasrc/util.lua
index ad53138e6..fda4563ad 100644
--- a/libs/core/luasrc/util.lua
+++ b/libs/core/luasrc/util.lua
@@ -36,7 +36,7 @@ function class(base)
setmetatable(inst, {__index = class})
if inst.__init__ then
- local stat, err = pcall(inst.__init__, inst, ...)
+ local stat, err = copcall(inst.__init__, inst, ...)
if not stat then
error(err)
end
@@ -152,6 +152,12 @@ function pcdata(value)
end
+-- Returns an error message to stdout
+function perror(obj)
+ io.stderr:write(tostring(obj) .. "\n")
+end
+
+
-- Resets the scope of f doing a shallow copy of its scope into a new table
function resfenv(f)
setfenv(f, clone(getfenv(f)))
@@ -255,6 +261,34 @@ function strip_bytecode(dump)
end
+-- Creates a new threadlocal store
+function threadlocal()
+ local tbl = {}
+
+ local function get(self, key)
+ local c = coroutine.running()
+ local thread = coxpt[c] or c or 0
+ if not rawget(self, thread) then
+ rawset(self, thread, {})
+ end
+ return rawget(self, thread)[key]
+ end
+
+ local function set(self, key, value)
+ local c = coroutine.running()
+ local thread = coxpt[c] or c or 0
+ if not rawget(self, thread) then
+ rawset(self, thread, {})
+ end
+ rawget(self, thread)[key] = value
+ end
+
+ setmetatable(tbl, {__index = get, __newindex = set})
+
+ return tbl
+end
+
+
-- Removes whitespace from beginning and end of a string
function trim(str)
local s = str:gsub("^%s*(.-)%s*$", "%1")
@@ -355,3 +389,46 @@ end
function vspairs(t)
return _sortiter( t, function (a,b) return t[a] < t[b] end )
end
+
+
+-- Coroutine safe xpcall and pcall versions modified for Luci
+-- original version:
+-- coxpcall 1.13 - Copyright 2005 - Kepler Project (www.keplerproject.org)
+local performResume, handleReturnValue
+local oldpcall, oldxpcall = pcall, xpcall
+coxpt = {}
+
+function handleReturnValue(err, co, status, ...)
+ if not status then
+ return false, err(debug.traceback(co, (...)), ...)
+ end
+ if coroutine.status(co) == 'suspended' then
+ return performResume(err, co, coroutine.yield(...))
+ else
+ return true, ...
+ end
+end
+
+function performResume(err, co, ...)
+ return handleReturnValue(err, co, coroutine.resume(co, ...))
+end
+
+function coxpcall(f, err, ...)
+ local res, co = oldpcall(coroutine.create, f)
+ if not res then
+ local params = {...}
+ local newf = function() return f(unpack(params)) end
+ co = coroutine.create(newf)
+ end
+ local c = coroutine.running()
+ coxpt[co] = coxpt[c] or c or 0
+ return performResume(err, co, ...)
+end
+
+local function id(trace, ...)
+ return ...
+end
+
+function copcall(f, ...)
+ return coxpcall(f, id, ...)
+end
diff --git a/libs/fastindex/Makefile b/libs/fastindex/Makefile
index 566b38d0b..ee1a40ea8 100644
--- a/libs/fastindex/Makefile
+++ b/libs/fastindex/Makefile
@@ -6,8 +6,8 @@ include ../../build/gccconfig.mk
$(COMPILE) $(LUA_CFLAGS) $(FPIC) -c -o $@ $<
compile: src/fastindex.o
- mkdir -p dist$(LUCI_INSTALLDIR)
- $(LINK) $(SHLIB_FLAGS) -o dist$(LUCI_INSTALLDIR)/fastindex.so src/fastindex.o $(LUA_SHLIBS)
+ mkdir -p dist$(LUCI_LIBRARYDIR)
+ $(LINK) $(SHLIB_FLAGS) -o dist$(LUCI_LIBRARYDIR)/fastindex.so src/fastindex.o $(LUA_SHLIBS)
clean:
rm -f src/*.o
diff --git a/libs/sgi-haserl/luasrc/sgi/haserl.lua b/libs/sgi-haserl/luasrc/sgi/haserl.lua
index 35bc1c902..315b4da73 100644
--- a/libs/sgi-haserl/luasrc/sgi/haserl.lua
+++ b/libs/sgi-haserl/luasrc/sgi/haserl.lua
@@ -24,80 +24,49 @@ limitations under the License.
]]--
module("luci.sgi.haserl", package.seeall)
-require("luci.fs")
-
--- Environment Table
-luci.http.env = ENV
-
--- Enforces user authentification
-function luci.http.basic_auth(verify_callback, realm)
- -- Dummy for Haserl
- return true
-end
-
--- Returns the main dispatcher URL
-function luci.http.dispatcher()
- return luci.http.env.SCRIPT_NAME or ""
-end
-
--- Returns the upload dispatcher URL
-function luci.http.dispatcher_upload()
- return luci.http.dispatcher() .. "-upload"
-end
-
--- Returns a table of all COOKIE, GET and POST Parameters
-function luci.http.formvalues()
- return FORM
-end
-
--- Gets form value from key
-function luci.http.formvalue(key, default)
- local c = luci.http.formvalues()
+require("luci.http")
+require("luci.util")
+require("luci.dispatcher")
+
+function run()
+ local r = luci.http.Request()
+ r.env = ENV
+ r.request = normalize_table(FORM)
- for match in key:gmatch("[%w-_]+") do
- c = c[match]
- if c == nil then
- return default
+ local x = coroutine.create(luci.dispatcher.httpdispatch)
+ while coroutine.status(x) ~= "dead" do
+ local res, id, data1, data2 = coroutine.resume(x, r)
+
+ if not res then
+ print("Status: 500 Internal Server Error")
+ print("Content-Type: text/plain\n")
+ print(id)
+ break;
+ end
+
+ if id == 1 then
+ io.write("Status: " .. tostring(data1) .. " " .. data2 .. "\n")
+ elseif id == 2 then
+ io.write(data1 .. ": " .. data2 .. "\n")
+ elseif id == 3 then
+ io.write("\n")
+ elseif id == 4 then
+ io.write(data1)
end
end
-
- return c
end
--- Gets a table of values with a certain prefix
-function luci.http.formvaluetable(prefix)
- return luci.http.formvalue(prefix, {})
-end
-
--- Sends a custom HTTP-Header
-function luci.http.header(key, value)
- print(key .. ": " .. value)
-end
-
--- Set Content-Type
-function luci.http.prepare_content(type)
- print("Content-Type: "..type.."\n")
-end
-
--- Asks the browser to redirect to "url"
-function luci.http.redirect(url)
- luci.http.status(302, "Found")
- luci.http.header("Location", url)
- print()
-end
-
--- Returns the path of an uploaded file
--- WARNING! File uploads can be easily spoofed! Do additional sanity checks!
-function luci.http.upload(name)
- local fpath = luci.http.formvalue(name)
- local fname = luci.http.formvalue(name .. "_name")
+function normalize_table(table, prefix)
+ prefix = prefix and prefix .. "." or ""
+ local new = {}
- if fpath and fname and luci.fs.isfile(fpath) then
- return fpath
+ for k,v in pairs(table) do
+ if type(v) == "table" and #v == 0 then
+ luci.util.update(new, normalize_table(v, prefix .. k))
+ else
+ new[prefix .. k] = v
+ end
end
-end
-
--- Sets HTTP-Status-Header
-function luci.http.status(code, message)
- print("Status: " .. tostring(code) .. " " .. message)
+
+ return new
end
diff --git a/libs/sgi-haserl/root/www/cgi-bin/luci b/libs/sgi-haserl/root/www/cgi-bin/luci
index ab2a3e18f..fd8e5941a 100755
--- a/libs/sgi-haserl/root/www/cgi-bin/luci
+++ b/libs/sgi-haserl/root/www/cgi-bin/luci
@@ -1,4 +1,4 @@
#!/usr/bin/haserl --shell=luac
-require("luci.dispatcher")
+require("luci.sgi.haserl")
luci.dispatcher.indexcache = "/tmp/.luciindex"
-luci.dispatcher.httpdispatch() \ No newline at end of file
+luci.sgi.haserl.run() \ No newline at end of file
diff --git a/libs/sgi-webuci/luasrc/sgi/webuci.lua b/libs/sgi-webuci/luasrc/sgi/webuci.lua
index a40888e7e..abe279d05 100644
--- a/libs/sgi-webuci/luasrc/sgi/webuci.lua
+++ b/libs/sgi-webuci/luasrc/sgi/webuci.lua
@@ -24,93 +24,36 @@ limitations under the License.
]]--
module("luci.sgi.webuci", package.seeall)
-
-local status_set = false
-
--- Initialize the environment
-function initenv(env, vars)
- luci.http.env = env
- luci.http.vars = vars
-end
-
--- Enforces user authentification
-function luci.http.basic_auth(verify_callback, realm)
- local user = luci.http.env.auth_user
- local pass = luci.http.env.auth_password
- realm = realm or ""
+require("luci.http")
+require("luci.util")
+require("luci.dispatcher")
+
+function run(env, vars)
+ local r = luci.http.Request()
+ r.env = env
+ r.request = vars
- if not user or not verify_callback(user, pass) then
- luci.http.status("401", "Unauthorized")
- luci.http.header("WWW-Authenticate", string.format('Basic realm="%s"', realm))
- return false
- else
- return true
- end
-end
-
--- Returns the main dispatcher URL
-function luci.http.dispatcher()
- return luci.http.env.SCRIPT_NAME or ""
-end
-
--- Returns the upload dispatcher URL
-function luci.http.dispatcher_upload()
- -- To be implemented
-end
-
--- Returns a table of all COOKIE, GET and POST Parameters
-function luci.http.formvalues()
- return luci.http.vars
-end
-
--- Gets form value from key
-function luci.http.formvalue(key, default)
- return luci.http.formvalues()[key] or default
-end
-
--- Gets a table of values with a certain prefix
-function luci.http.formvaluetable(prefix)
- local vals = {}
- prefix = prefix and prefix .. "." or "."
+ local x = coroutine.create(luci.dispatcher.httpdispatch)
- for k, v in pairs(luci.http.formvalues()) do
- if k:find(prefix, 1, true) == 1 then
- vals[k:sub(#prefix + 1)] = v
+ while coroutine.status(x) ~= "dead" do
+ local res, id, data1, data2 = coroutine.resume(x, r)
+
+ if not res then
+ print(env.SERVER_PROTOCOL .. " 500 Internal Server Error")
+ print("Content-Type: text/plain\n")
+ print(id)
+ break;
end
+
+ if id == 1 then
+ io.write(env.SERVER_PROTOCOL .. " " .. tostring(data1) .. " " .. data2 .. "\n")
+ elseif id == 2 then
+ io.write(data1 .. ": " .. data2 .. "\n")
+ elseif id == 3 then
+ io.write("\n")
+ elseif id == 4 then
+ io.write(data1)
+ end
+
end
-
- return vals
-end
-
--- Sends a custom HTTP-Header
-function luci.http.header(key, value)
- print(key .. ": " .. value)
-end
-
--- Set Content-Type
-function luci.http.prepare_content(type)
- if not status_set then
- luci.http.status(200, "OK")
- end
-
- print("Content-Type: "..type.."\n")
-end
-
--- Asks the browser to redirect to "url"
-function luci.http.redirect(url)
- luci.http.status(302, "Found")
- luci.http.header("Location", url)
- print()
-end
-
--- Returns the path of an uploaded file
--- WARNING! File uploads can be easily spoofed! Do additional sanity checks!
-function luci.http.upload(name)
- -- To be implemented
-end
-
--- Sets HTTP-Status-Header
-function luci.http.status(code, message)
- print(luci.http.env.SERVER_PROTOCOL .. " " .. tostring(code) .. " " .. message)
- status_set = true
end
diff --git a/libs/sgi-webuci/root/usr/lib/boa/luci.lua b/libs/sgi-webuci/root/usr/lib/boa/luci.lua
index 39cee1c60..879ef19b4 100644
--- a/libs/sgi-webuci/root/usr/lib/boa/luci.lua
+++ b/libs/sgi-webuci/root/usr/lib/boa/luci.lua
@@ -60,6 +60,5 @@ function handle_req(context)
env.SERVER_ADDR = context.server_addr
env.SCRIPT_NAME = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO)
- luci.sgi.webuci.initenv(env, vars)
- luci.dispatcher.httpdispatch()
+ luci.sgi.webuci.run(env, vars)
end
diff --git a/libs/uci/luasrc/model/uci.lua b/libs/uci/luasrc/model/uci.lua
index bd6aba41a..6662943cf 100644
--- a/libs/uci/luasrc/model/uci.lua
+++ b/libs/uci/luasrc/model/uci.lua
@@ -27,7 +27,7 @@ local uci = require("uci")
local util = require("luci.util")
local setmetatable, rawget, rawset = setmetatable, rawget, rawset
local error, pairs, ipairs, tostring = error, pairs, ipairs, tostring
-local table, print = table, print
+local table = table
module("luci.model.uci", function(m) setmetatable(m, {__index = uci}) end)
diff --git a/libs/web/luasrc/dispatcher.lua b/libs/web/luasrc/dispatcher.lua
index 64355439b..8516c6f1b 100644
--- a/libs/web/luasrc/dispatcher.lua
+++ b/libs/web/luasrc/dispatcher.lua
@@ -34,21 +34,10 @@ if (os.time() < 1000000000) then
os.execute('date -s '..os.date('%m%d%H%M%Y', luci.fs.mtime(luci.sys.libpath() .. "/dispatcher.lua"))..' > /dev/null 2>&1')
end
--- Local dispatch database
-local tree = {nodes={}}
+context = luci.util.threadlocal()
-- Index table
-local index = {}
-
--- Global request object
-request = {}
-
--- Active dispatched node
-dispatched = nil
-
--- Status fields
-built_index = false
-built_tree = false
+local index = nil
-- Fastindex
local fi
@@ -64,9 +53,9 @@ function error401(message)
message = message or "Unauthorized"
require("luci.template")
- if not pcall(luci.template.render, "error401") then
+ if not luci.util.copcall(luci.template.render, "error401") then
luci.http.prepare_content("text/plain")
- print(message)
+ luci.http.write(message)
end
return false
end
@@ -77,9 +66,9 @@ function error404(message)
message = message or "Not Found"
require("luci.template")
- if not pcall(luci.template.render, "error404") then
+ if not luci.util.copcall(luci.template.render, "error404") then
luci.http.prepare_content("text/plain")
- print(message)
+ luci.http.write(message)
end
return false
end
@@ -89,31 +78,39 @@ function error500(message)
luci.http.status(500, "Internal Server Error")
require("luci.template")
- if not pcall(luci.template.render, "error500", {message=message}) then
+ if not luci.util.copcall(luci.template.render, "error500", {message=message}) then
luci.http.prepare_content("text/plain")
- print(message)
+ luci.http.write(message)
end
return false
end
-- Creates a request object for dispatching
-function httpdispatch()
- local pathinfo = luci.http.env.PATH_INFO or ""
+function httpdispatch(request)
+ luci.http.context.request = request
+ context.request = {}
+ local pathinfo = request.env.PATH_INFO or ""
for node in pathinfo:gmatch("[^/]+") do
- table.insert(request, node)
+ table.insert(context.request, node)
end
- dispatch()
+ dispatch(context.request)
+ luci.http.close()
end
-- Dispatches a request
-function dispatch()
- if not built_tree then
+function dispatch(request)
+ context.path = request
+
+ require("luci.i18n")
+ luci.i18n.setlanguage(require("luci.config").main.lang)
+
+ if not context.tree then
createtree()
end
-
- local c = tree
+
+ local c = context.tree
local track = {}
for i, s in ipairs(request) do
@@ -131,6 +128,7 @@ function dispatch()
local accs = track.sysauth
accs = (type(accs) == "string") and {accs} or accs
+ --[[
local function sysauth(user, password)
return (luci.util.contains(accs, user)
and luci.sys.user.checkpasswd(user, password))
@@ -140,6 +138,7 @@ function dispatch()
error401()
return
end
+ ]]--
end
if track.i18n then
@@ -156,22 +155,24 @@ function dispatch()
-- Init template engine
local tpl = require("luci.template")
- tpl.viewns.translate = function(...) return require("luci.i18n").translate(...) end
- tpl.viewns.controller = luci.http.dispatcher()
- tpl.viewns.uploadctrl = luci.http.dispatcher_upload() -- DEPRECATED
- tpl.viewns.media = luci.config.main.mediaurlbase
- tpl.viewns.resource = luci.config.main.resourcebase
- tpl.viewns.REQUEST_URI = luci.http.env.SCRIPT_NAME .. (luci.http.env.PATH_INFO or "")
+ local viewns = {}
+ tpl.context.viewns = viewns
+ viewns.write = luci.http.write
+ viewns.translate = function(...) return require("luci.i18n").translate(...) end
+ 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") .. (luci.http.getenv("PATH_INFO") or "")
if c and type(c.target) == "function" then
- dispatched = c
- stat, mod = pcall(require, c.module)
+ context.dispatched = c
+ stat, mod = luci.util.copcall(require, c.module)
if stat then
luci.util.updfenv(c.target, mod)
end
- stat, err = pcall(c.target)
+ stat, err = luci.util.copcall(c.target)
if not stat then
error500(err)
end
@@ -182,21 +183,20 @@ end
-- Generates the dispatching tree
function createindex()
- index = {}
local path = luci.sys.libpath() .. "/controller/"
local suff = ".lua"
- if pcall(require, "luci.fastindex") then
+ if luci.util.copcall(require, "luci.fastindex") then
createindex_fastindex(path, suff)
else
createindex_plain(path, suff)
end
-
- built_index = true
end
-- Uses fastindex to create the dispatching tree
-function createindex_fastindex(path, suffix)
+function createindex_fastindex(path, suffix)
+ index = {}
+
if not fi then
fi = luci.fastindex.new("index")
fi.add(path .. "*" .. suffix)
@@ -212,9 +212,7 @@ end
-- Calls the index function of all available controllers
-- Fallback for transition purposes / Leave it in as long as it works otherwise throw it away
function createindex_plain(path, suffix)
- if built_index then
- return
- end
+ index = {}
local cache = nil
@@ -246,7 +244,7 @@ function createindex_plain(path, suffix)
end
if not cache or stime > ctime then
- stat, mod = pcall(require, module)
+ stat, mod = luci.util.copcall(require, module)
if stat and mod and type(mod.index) == "function" then
index[module] = mod.index
@@ -263,10 +261,11 @@ end
-- Creates the dispatching tree from the index
function createtree()
- if not built_index then
+ if not index then
createindex()
end
+ context.tree = {nodes={}}
require("luci.i18n")
-- Load default translation
@@ -283,14 +282,12 @@ function createtree()
scope._NAME = k
setfenv(v, scope)
- local stat, err = pcall(v)
+ local stat, err = luci.util.copcall(v)
if not stat then
error500(err)
os.exit(1)
end
end
-
- built_tree = true
end
-- Reassigns a node to another position
@@ -302,7 +299,7 @@ function assign(path, clone, title, order)
obj.title = title
obj.order = order
- local c = tree
+ local c = context.tree
for k, v in ipairs(clone) do
if not c.nodes[v] then
c.nodes[v] = {nodes={}}
@@ -330,8 +327,7 @@ end
-- Fetch a dispatching node
function node(...)
- local c = tree
-
+ local c = context.tree
arg.n = nil
if arg[1] then
if type(arg[1]) == "table" then
@@ -357,8 +353,7 @@ end
function alias(...)
local req = arg
return function()
- request = req
- dispatch()
+ dispatch(req)
end
end
@@ -366,19 +361,20 @@ function rewrite(n, ...)
local req = arg
return function()
for i=1,n do
- table.remove(request, 1)
+ table.remove(context.path, 1)
end
for i,r in ipairs(req) do
- table.insert(request, i, r)
+ table.insert(context.path, i, r)
end
dispatch()
end
end
-function call(name)
- return function() getfenv()[name]() end
+function call(name, ...)
+ local argv = {...}
+ return function() return getfenv()[name](unpack(argv)) end
end
function template(name)
@@ -391,13 +387,13 @@ function cbi(model)
require("luci.template")
return function()
- local stat, res = pcall(luci.cbi.load, model)
+ local stat, res = luci.util.copcall(luci.cbi.load, model)
if not stat then
error500(res)
return true
end
- local stat, err = pcall(res.parse, res)
+ local stat, err = luci.util.copcall(res.parse, res)
if not stat then
error500(err)
return true
diff --git a/libs/web/luasrc/http.lua b/libs/web/luasrc/http.lua
index 3bff28add..8ee864ac7 100644
--- a/libs/web/luasrc/http.lua
+++ b/libs/web/luasrc/http.lua
@@ -28,13 +28,141 @@ limitations under the License.
]]--
module("luci.http", package.seeall)
+require("luci.util")
+context = luci.util.threadlocal()
-if ENV and ENV.HASERLVER then
- require("luci.sgi.haserl")
-elseif webuci then
- require("luci.sgi.webuci")
+
+Request = luci.util.class()
+function Request.__init__(self)
+ self.headers = {}
+ self.request = {}
+ self.uploads = {}
+ self.env = {}
+ self.data = ""
+end
+
+function Request.formvalue(self, name, default)
+ return self.request[name] or default
+end
+
+function Request.formvalues(self)
+ return self.request
+end
+
+function Request.formvaluetable(self, prefix)
+ local vals = {}
+ prefix = prefix and prefix .. "." or "."
+
+ for k, v in pairs(self.request) do
+ if k:find(prefix, 1, true) == 1 then
+ vals[k:sub(#prefix + 1)] = v
+ end
+ end
+
+ return vals
+end
+
+function Request.getenv(self, name)
+ return self.env[name]
+end
+
+function Request.upload(self, name)
+ return self.uploads[name]
+end
+
+
+function close()
+ if not context.eoh then
+ context.eoh = true
+ coroutine.yield(3)
+ end
+
+ if not context.closed then
+ context.closed = true
+ coroutine.yield(5)
+ end
+end
+
+function formvalue(...)
+ return context.request:formvalue(...)
+end
+
+function formvalues(...)
+ return context.request:formvalues(...)
+end
+
+function formvaluetable(...)
+ return context.request:formvaluetable(...)
end
+function getenv(...)
+ return context.request:getenv(...)
+end
+
+function header(key, value)
+ if not context.status then
+ status()
+ end
+ if not context.headers then
+ context.headers = {}
+ end
+ context.headers[key:lower()] = value
+ coroutine.yield(2, key, value)
+end
+
+function prepare_content(mime)
+ header("Content-Type", mime)
+end
+
+function status(code, message)
+ code = code or 200
+ message = message or "OK"
+ context.status = code
+ coroutine.yield(1, code, message)
+end
+
+function write(content)
+ if not content or #content == 0 then
+ return
+ end
+ if not context.eoh then
+ if not context.status then
+ status()
+ end
+ if not context.headers or not context.headers["content-type"] then
+ header("Content-Type", "text/html; charset=utf-8")
+ end
+
+ context.eoh = true
+ coroutine.yield(3)
+ end
+ coroutine.yield(4, content)
+end
+
+
+function basic_auth(realm, errorpage)
+ header("Status", "401 Unauthorized")
+ header("WWW-Authenticate", string.format('Basic realm="%s"', realm or ""))
+
+ if errorpage then
+ errorpage()
+ end
+
+ close()
+end
+
+function redirect(url)
+ header("Status", "302 Found")
+ header("Location", url)
+ close()
+end
+
+function upload(...)
+ return context.request:upload(...)
+end
+
+
+
function build_querystring(table)
local s="?"
diff --git a/libs/web/luasrc/i18n.lua b/libs/web/luasrc/i18n.lua
index 3ed1ce017..35ad0965d 100644
--- a/libs/web/luasrc/i18n.lua
+++ b/libs/web/luasrc/i18n.lua
@@ -30,6 +30,8 @@ require("luci.sys")
table = {}
i18ndir = luci.sys.libpath() .. "/i18n/"
loaded = {}
+context = luci.util.threadlocal()
+default = "en"
-- Clears the translation table
function clear()
@@ -37,13 +39,17 @@ function clear()
end
-- Loads a translation and copies its data into the global translation table
-function load(file, force)
- if force or not loaded[file] then
- local f = loadfile(i18ndir..file..".lua") or loadfile(i18ndir..file)
+function load(file, lang, force)
+ lang = lang or ""
+ if force or not loaded[lang] or not loaded[lang][file] then
+ local f = loadfile(i18ndir .. file .. "." .. lang .. ".lua")
+ or loadfile(i18ndir .. file .. "." .. lang)
if f then
- setfenv(f, table)
+ table[lang] = table[lang] or {}
+ setfenv(f, table[lang])
f()
- loaded[file] = true
+ loaded[lang] = loaded[lang] or {}
+ loaded[lang][file] = true
return true
else
return false
@@ -55,13 +61,20 @@ end
-- Same as load but autocompletes the filename with .LANG from config.lang
function loadc(file, force)
- load(file .. ".en", force)
- return load(file .. "." .. require("luci.config").main.lang, force)
+ load(file, default, force)
+ return load(file, context.lang, force)
+end
+
+-- Sets the context language
+function setlanguage(lang)
+ context.lang = lang
end
-- Returns the i18n-value defined by "key" or if there is no such: "default"
function translate(key, default)
- return table[key] or default
+ return (table[context.lang] and table[context.lang][key])
+ or (table[default] and table[default][key])
+ or default
end
-- Translate shourtcut with sprintf/string.format inclusion
diff --git a/libs/web/luasrc/template.lua b/libs/web/luasrc/template.lua
index 61e4e39ec..29aedcdad 100644
--- a/libs/web/luasrc/template.lua
+++ b/libs/web/luasrc/template.lua
@@ -44,9 +44,10 @@ compiler_mode = luci.config.template.compiler_mode or "memory"
-- Define the namespace for template modules
+context = luci.util.threadlocal()
+
viewns = {
- write = io.write,
- include = function(name) Template(name):render(getfenv(2)) end,
+ include = function(name) Template(name):render(getfenv(2)) end,
}
-- Compiles a given template into an executable Lua module
@@ -113,7 +114,7 @@ end
-- Oldstyle render shortcut
function render(name, scope, ...)
scope = scope or getfenv(2)
- local s, t = pcall(Template, name)
+ local s, t = luci.util.copcall(Template, name)
if not s then
error(t)
else
@@ -141,9 +142,10 @@ function Template.__init__(self, name)
self.viewns = {}
-- Copy over from general namespace
- for k, v in pairs(viewns) do
- self.viewns[k] = v
- end
+ luci.util.update(self.viewns, viewns)
+ if context.viewns then
+ luci.util.update(self.viewns, context.viewns)
+ end
-- If we have a cached template, skip compiling and loading
if self.template then
diff --git a/modules/admin-core/luasrc/view/admin_system/upgrade.htm b/modules/admin-core/luasrc/view/admin_system/upgrade.htm
index 7e23c5400..cc7438655 100644
--- a/modules/admin-core/luasrc/view/admin_system/upgrade.htm
+++ b/modules/admin-core/luasrc/view/admin_system/upgrade.htm
@@ -4,7 +4,7 @@
<p><%:a_s_flash_upgrade1%></p>
<br />
<% if sysupgrade and not ret then %>
-<form method="post" action="<%=uploadctrl%><%=luci.http.env.PATH_INFO%>" enctype="multipart/form-data">
+<form method="post" action="<%=luci.http.getenv("REQUEST_URI")%>" enctype="multipart/form-data">
<div class="cbi-section-node">
<div class="cbi-value clear">
<div class="cbi-value-title left"><%:a_s_flash_fwimage%></div>
diff --git a/modules/admin-core/luasrc/view/error404.htm b/modules/admin-core/luasrc/view/error404.htm
index 60daee2cb..03f6c54f3 100644
--- a/modules/admin-core/luasrc/view/error404.htm
+++ b/modules/admin-core/luasrc/view/error404.htm
@@ -1,5 +1,5 @@
<%+header%>
<h1>404 Not Found</h1>
<p>Sorry, the object you requested was not found.</p>
-<tt>Unable to dispatch: <%=luci.http.env.PATH_INFO%></tt>
+<tt>Unable to dispatch: <%=luci.http.request.env.PATH_INFO%></tt>
<%+footer%> \ No newline at end of file
diff --git a/modules/freifunk/luasrc/controller/freifunk/luciinfo.lua b/modules/freifunk/luasrc/controller/freifunk/luciinfo.lua
index 4c24c5732..4ab63a068 100644
--- a/modules/freifunk/luasrc/controller/freifunk/luciinfo.lua
+++ b/modules/freifunk/luasrc/controller/freifunk/luciinfo.lua
@@ -22,8 +22,8 @@ function action_index()
luci.http.prepare_content("text/plain")
-- General
- print("luciinfo.api=1")
- print("luciinfo.version=" .. tostring(require("luci").__version__))
+ luci.http.write("luciinfo.api=1\n")
+ luci.http.write("luciinfo.version=" .. tostring(require("luci").__version__) .. "\n")
-- Sysinfo
local s, m, r = luci.sys.sysinfo()
@@ -31,14 +31,14 @@ function action_index()
dr = dr and luci.sys.net.hexip4(dr.Gateway) or ""
local l1, l5, l15 = luci.sys.loadavg()
- print("sysinfo.system=" .. sanitize(s))
- print("sysinfo.cpu=" .. sanitize(m))
- print("sysinfo.ram=" .. sanitize(r))
- print("sysinfo.hostname=" .. sanitize(luci.sys.hostname()))
- print("sysinfo.load1=" .. tostring(l1))
- print("sysinfo.load5=" .. tostring(l5))
- print("sysinfo.load15=" .. tostring(l15))
- print("sysinfo.defaultgw=" .. dr)
+ luci.http.write("sysinfo.system=" .. sanitize(s) .. "\n")
+ luci.http.write("sysinfo.cpu=" .. sanitize(m) .. "\n")
+ luci.http.write("sysinfo.ram=" .. sanitize(r) .. "\n")
+ luci.http.write("sysinfo.hostname=" .. sanitize(luci.sys.hostname()) .. "\n")
+ luci.http.write("sysinfo.load1=" .. tostring(l1) .. "\n")
+ luci.http.write("sysinfo.load5=" .. tostring(l5) .. "\n")
+ luci.http.write("sysinfo.load15=" .. tostring(l15) .. "\n")
+ luci.http.write("sysinfo.defaultgw=" .. dr .. "\n")
-- Freifunk
@@ -46,7 +46,7 @@ function action_index()
for k, v in pairs(ff) do
for i, j in pairs(v) do
if i:sub(1, 1) ~= "." then
- print("freifunk." .. k .. "." .. i .. "=" .. j)
+ luci.http.write("freifunk." .. k .. "." .. i .. "=" .. j .. "\n")
end
end
end
diff --git a/themes/fledermaus/luasrc/view/themes/fledermaus/header.htm b/themes/fledermaus/luasrc/view/themes/fledermaus/header.htm
index 327e33964..7f625fd38 100644
--- a/themes/fledermaus/luasrc/view/themes/fledermaus/header.htm
+++ b/themes/fledermaus/luasrc/view/themes/fledermaus/header.htm
@@ -1,11 +1,11 @@
<%
require("luci.sys")
local load1, load5, load15 = luci.sys.loadavg()
-local request = require("luci.dispatcher").request
+local request = require("luci.dispatcher").context.path
local category = request[1]
local tree = luci.dispatcher.node()
local cattree = category and luci.dispatcher.node(category)
-local node = luci.dispatcher.dispatched
+local node = luci.dispatcher.context.dispatched
local c = tree
for i,r in ipairs(request) do
diff --git a/themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm b/themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm
index 889fdd01f..d1b751871 100644
--- a/themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm
+++ b/themes/openwrt.org/luasrc/view/themes/openwrt.org/header.htm
@@ -1,11 +1,11 @@
<%
require("luci.sys")
local load1, load5, load15 = luci.sys.loadavg()
-local request = require("luci.dispatcher").request
+local request = require("luci.dispatcher").context.path
local category = request[1]
local tree = luci.dispatcher.node()
local cattree = category and luci.dispatcher.node(category)
-local node = luci.dispatcher.dispatched
+local node = luci.dispatcher.context.dispatched
local c = tree
for i,r in ipairs(request) do