* luci-0.8: backport library fixes

This commit is contained in:
Jo-Philipp Wich 2008-10-29 19:41:33 +00:00
parent 8a690a0614
commit bb63ae4647
16 changed files with 272 additions and 79 deletions

View file

@ -167,3 +167,13 @@ function cbi_combobox_init(id, values, def, man) {
}); });
cbi_combobox(id, values, def, man); cbi_combobox(id, values, def, man);
} }
function cbi_filebrowser(id, url, defpath) {
var field = document.getElementById(id);
var browser = window.open(
url + ( field.value || defpath || '' ) + '?field=' + id,
"luci_filebrowser", "width=300,height=400,left=100,top=200,scrollbars=yes"
);
browser.focus();
}

View file

@ -30,6 +30,7 @@ require("luci.template")
require("luci.util") require("luci.util")
require("luci.http") require("luci.http")
require("luci.uvl") require("luci.uvl")
require("luci.fs")
local uci = require("luci.model.uci") local uci = require("luci.model.uci")
local class = luci.util.class local class = luci.util.class
@ -38,6 +39,7 @@ local instanceof = luci.util.instanceof
FORM_NODATA = 0 FORM_NODATA = 0
FORM_VALID = 1 FORM_VALID = 1
FORM_INVALID = -1 FORM_INVALID = -1
FORM_CHANGED = 2
AUTO = true AUTO = true
@ -51,6 +53,7 @@ function load(cbimap, ...)
require("luci.config") require("luci.config")
require("luci.util") require("luci.util")
local upldir = "/lib/uci/upload/"
local cbidir = luci.util.libpath() .. "/model/cbi/" local cbidir = luci.util.libpath() .. "/model/cbi/"
local func, err = loadfile(cbimap) or loadfile(cbidir..cbimap..".lua") local func, err = loadfile(cbimap) or loadfile(cbidir..cbimap..".lua")
assert(func, err) assert(func, err)
@ -69,7 +72,9 @@ function load(cbimap, ...)
return rawget(tbl, key) or _M[key] or _G[key] return rawget(tbl, key) or _M[key] or _G[key]
end})) end}))
local maps = {func()} local maps = { func() }
local uploads = { }
local has_upload = false
for i, map in ipairs(maps) do for i, map in ipairs(maps) do
if not instanceof(map, Node) then if not instanceof(map, Node) then
@ -77,9 +82,58 @@ function load(cbimap, ...)
return nil return nil
else else
map:prepare() map:prepare()
if map.upload_fields then
has_upload = true
for _, field in ipairs(map.upload_fields) do
uploads[
field.config .. '.' ..
field.section.sectiontype .. '.' ..
field.option
] = true
end
end
end end
end end
if has_upload then
local uci = luci.model.uci.cursor()
local prm = luci.http.context.request.message.params
local fd, cbid
luci.http.setfilehandler(
function( field, chunk, eof )
if not field then return end
if field.name and not cbid then
local c, s, o = field.name:gmatch(
"cbid%.([^%.]+)%.([^%.]+)%.([^%.]+)"
)()
if c and s and o then
local t = uci:get( c, s )
if t and uploads[c.."."..t.."."..o] then
local path = upldir .. field.name
fd = io.open(path, "w")
if fd then
cbid = field.name
prm[cbid] = path
end
end
end
end
if field.name == cbid and fd then
fd:write(chunk)
end
if eof and fd then
fd:close()
fd = nil
cbid = nil
end
end
)
end
return maps return maps
end end
@ -251,6 +305,9 @@ function Map.get_scheme(self, sectiontype, option)
end end
end end
function Map.submitstate(self)
return luci.http.formvalue("cbi.submit")
end
-- Chain foreign config -- Chain foreign config
function Map.chain(self, config) function Map.chain(self, config)
@ -288,6 +345,19 @@ function Map.parse(self)
for i, config in ipairs(self.parsechain) do for i, config in ipairs(self.parsechain) do
self.uci:unload(config) self.uci:unload(config)
end end
if type(self.commit_handler) == "function" then
self:commit_handler(self:submitstate())
end
end
if self:submitstate() then
if self.save then
return self.changed and FORM_CHANGED or FORM_VALID
else
return FORM_INVALID
end
else
return FORM_NODATA
end end
end end
@ -383,11 +453,12 @@ function SimpleForm.parse(self, ...)
end end
local state = local state =
not luci.http.formvalue("cbi.submit") and 0 not self:submitstate() and FORM_NODATA
or valid and 1 or valid and FORM_VALID
or -1 or FORM_INVALID
self.dorender = not self.handle or self:handle(state, self.data) ~= false self.dorender = not self.handle or self:handle(state, self.data) ~= false
return state
end end
function SimpleForm.render(self, ...) function SimpleForm.render(self, ...)
@ -396,6 +467,10 @@ function SimpleForm.render(self, ...)
end end
end end
function SimpleForm.submitstate(self)
return luci.http.formvalue("cbi.submit")
end
function SimpleForm.section(self, class, ...) function SimpleForm.section(self, class, ...)
if instanceof(class, AbstractSection) then if instanceof(class, AbstractSection) then
local obj = class(self, ...) local obj = class(self, ...)
@ -615,6 +690,10 @@ function Table.__init__(self, form, data, ...)
function datasource.get(self, section, option) function datasource.get(self, section, option)
return data[section] and data[section][option] return data[section] and data[section][option]
end end
function datasource.submitstate(self)
return luci.http.formvalue("cbi.submit")
end
function datasource.del(...) function datasource.del(...)
return true return true
@ -632,7 +711,7 @@ end
function Table.parse(self) function Table.parse(self)
for i, k in ipairs(self:cfgsections()) do for i, k in ipairs(self:cfgsections()) do
if luci.http.formvalue("cbi.submit") then if self.map:submitstate() then
Node.parse(self, k) Node.parse(self, k)
end end
end end
@ -695,7 +774,7 @@ function NamedSection.parse(self, novld)
if active then if active then
AbstractSection.parse_dynamic(self, s) AbstractSection.parse_dynamic(self, s)
if luci.http.formvalue("cbi.submit") then if self.map:submitstate() then
Node.parse(self, s) Node.parse(self, s)
if not novld and not self.override_scheme and self.map.scheme then if not novld and not self.override_scheme and self.map.scheme then
@ -770,7 +849,7 @@ function TypedSection.parse(self, novld)
local co local co
for i, k in ipairs(self:cfgsections()) do for i, k in ipairs(self:cfgsections()) do
AbstractSection.parse_dynamic(self, k) AbstractSection.parse_dynamic(self, k)
if luci.http.formvalue("cbi.submit") then if self.map:submitstate() then
Node.parse(self, k) Node.parse(self, k)
if not novld and not self.override_scheme and self.map.scheme then if not novld and not self.override_scheme and self.map.scheme then
@ -1325,3 +1404,58 @@ function Button.__init__(self, ...)
self.inputstyle = nil self.inputstyle = nil
self.rmempty = true self.rmempty = true
end end
FileUpload = class(AbstractValue)
function FileUpload.__init__(self, ...)
AbstractValue.__init__(self, ...)
self.template = "cbi/upload"
if not self.map.upload_fields then
self.map.upload_fields = { self }
else
self.map.upload_fields[#self.map.upload_fields+1] = self
end
end
function FileUpload.formcreated(self, section)
return AbstractValue.formcreated(self, section) or
luci.http.formvalue("cbi.rlf."..section.."."..self.option) or
luci.http.formvalue("cbi.rlf."..section.."."..self.option..".x")
end
function FileUpload.cfgvalue(self, section)
local val = AbstractValue.cfgvalue(self, section)
if val and luci.fs.access(val) then
return val
end
return nil
end
function FileUpload.formvalue(self, section)
local val = AbstractValue.formvalue(self, section)
if val then
if not luci.http.formvalue("cbi.rlf."..section.."."..self.option) and
not luci.http.formvalue("cbi.rlf."..section.."."..self.option..".x")
then
return val
end
luci.fs.unlink(val)
self.value = nil
end
return nil
end
function FileUpload.remove(self, section)
local val = AbstractValue.formvalue(self, section)
if val and luci.fs.access(val) then luci.fs.unlink(val) end
return AbstractValue.remove(self, section)
end
FileBrowser = class(AbstractValue)
function FileBrowser.__init__(self, ...)
AbstractValue.__init__(self, ...)
self.template = "cbi/browser"
end

View file

@ -14,7 +14,7 @@ $Id$
-%> -%>
<%+cbi/valueheader%> <%+cbi/valueheader%>
<% if self:cfgvalue(section) ~= false then %> <% if self:cfgvalue(section) ~= false then %>
<input class="cbi-input-<% self.inputstyle or "button" %>" type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.title)%> /> <input class="cbi-input-<%=self.inputstyle or "button" %>" type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.title)%> />
<% else %> <% else %>
- -
<% end %> <% end %>

View file

@ -13,7 +13,7 @@ $Id$
-%> -%>
<div> <div class="cbi-page-actions">
<input class="cbi-button cbi-button-apply" type="submit" name="cbi.apply" value="<%:saveapply%>" /> <input class="cbi-button cbi-button-apply" type="submit" name="cbi.apply" value="<%:saveapply%>" />
<input class="cbi-button cbi-button-save" type="submit" value="<%:save%>" /> <input class="cbi-button cbi-button-save" type="submit" value="<%:save%>" />
<input class="cbi-button cbi-button-reset" type="reset" value="<%:reset%>" /> <input class="cbi-button cbi-button-reset" type="reset" value="<%:reset%>" />

View file

@ -14,7 +14,7 @@ $Id$
-%> -%>
<%+header%> <%+header%>
<form method="post" action="<%=luci.http.getenv("REQUEST_URI")%>"> <form method="post" action="<%=luci.http.getenv("REQUEST_URI")%>" enctype="multipart/form-data">
<div> <div>
<script type="text/javascript" src="<%=resource%>/cbi.js"></script> <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
<input type="hidden" name="cbi.submit" value="1" /> <input type="hidden" name="cbi.submit" value="1" />

View file

@ -32,6 +32,7 @@ $Id$
<br /> <br />
</fieldset> </fieldset>
<% elseif self.addremove then %> <% elseif self.addremove then %>
<% if self.template_addremove then include(self.template_addremove) else -%>
<fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.section%>"> <fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.section%>">
<% if self.title and #self.title > 0 then -%> <% if self.title and #self.title > 0 then -%>
<legend><%=self.title%></legend> <legend><%=self.title%></legend>
@ -39,5 +40,6 @@ $Id$
<div class="cbi-section-descr"><%=self.description%></div> <div class="cbi-section-descr"><%=self.description%></div>
<input type="submit" class="cbi-button-add" name="cbi.cns.<%=self.config%>.<%=self.section%>" value="<%:cbi_add%>" /> <input type="submit" class="cbi-button-add" name="cbi.cns.<%=self.config%>.<%=self.section%>" value="<%:cbi_add%>" />
</fieldset> </fieldset>
<%- end %>
<% end %> <% end %>
<!-- /nsection --> <!-- /nsection -->

View file

@ -41,6 +41,7 @@ $Id$
<%- end %> <%- end %>
<% if self.addremove then -%> <% if self.addremove then -%>
<% if self.template_addremove then include(self.template_addremove) else -%>
<div class="cbi-section-create"> <div class="cbi-section-create">
<% if self.anonymous then -%> <% if self.anonymous then -%>
<input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>" value="<%:cbi_add%>" /> <input type="submit" class="cbi-button cbi-button-add" name="cbi.cts.<%=self.config%>.<%=self.sectiontype%>" value="<%:cbi_add%>" />
@ -53,5 +54,6 @@ $Id$
<%- end %> <%- end %>
<%- end %> <%- end %>
</div> </div>
<%- end %>
<%- end %> <%- end %>
</fieldset> </fieldset>

View file

@ -33,7 +33,6 @@ local string = require "string"
local coroutine = require "coroutine" local coroutine = require "coroutine"
local getmetatable, setmetatable = getmetatable, setmetatable local getmetatable, setmetatable = getmetatable, setmetatable
local getfenv, setfenv = getfenv, setfenv
local rawget, rawset, unpack = rawget, rawset, unpack local rawget, rawset, unpack = rawget, rawset, unpack
local tostring, type, assert = tostring, type, assert local tostring, type, assert = tostring, type, assert
local ipairs, pairs, loadstring = ipairs, pairs, loadstring local ipairs, pairs, loadstring = ipairs, pairs, loadstring

View file

@ -131,7 +131,7 @@ function urlencode_params( tbl )
return enc return enc
end end
--- (Internal function) -- (Internal function)
-- Initialize given parameter and coerce string into table when the parameter -- Initialize given parameter and coerce string into table when the parameter
-- already exists. -- already exists.
-- @param tbl Table where parameter should be created -- @param tbl Table where parameter should be created
@ -147,7 +147,7 @@ local function __initval( tbl, key )
end end
end end
--- (Internal function) -- (Internal function)
-- Append given data to given parameter, either by extending the string value -- Append given data to given parameter, either by extending the string value
-- or by appending it to the last string in the parameter's value table. -- or by appending it to the last string in the parameter's value table.
-- @param tbl Table containing the previously initialized parameter value -- @param tbl Table containing the previously initialized parameter value
@ -163,7 +163,7 @@ local function __appendval( tbl, key, chunk )
end end
end end
--- (Internal function) -- (Internal function)
-- Finish the value of given parameter, either by transforming the string value -- Finish the value of given parameter, either by transforming the string value
-- or - in the case of multi value parameters - the last element in the -- or - in the case of multi value parameters - the last element in the
-- associated values table. -- associated values table.
@ -563,12 +563,14 @@ function parse_message_header( src )
-- Populate common environment variables -- Populate common environment variables
msg.env = { msg.env = {
CONTENT_LENGTH = msg.headers['Content-Length']; CONTENT_LENGTH = msg.headers['Content-Length'];
CONTENT_TYPE = msg.headers['Content-Type']; CONTENT_TYPE = msg.headers['Content-Type'] or msg.headers['Content-type'];
REQUEST_METHOD = msg.request_method:upper(); REQUEST_METHOD = msg.request_method:upper();
REQUEST_URI = msg.request_uri; REQUEST_URI = msg.request_uri;
SCRIPT_NAME = msg.request_uri:gsub("?.+$",""); SCRIPT_NAME = msg.request_uri:gsub("?.+$","");
SCRIPT_FILENAME = ""; -- XXX implement me SCRIPT_FILENAME = ""; -- XXX implement me
SERVER_PROTOCOL = "HTTP/" .. string.format("%.1f", msg.http_version) SERVER_PROTOCOL = "HTTP/" .. string.format("%.1f", msg.http_version);
QUERY_STRING = msg.request_uri:match("?")
and msg.request_uri:gsub("^.+?","") or ""
} }
-- Populate HTTP_* environment variables -- Populate HTTP_* environment variables
@ -617,7 +619,7 @@ function parse_message_body( src, msg, filecb )
-- Is it application/x-www-form-urlencoded ? -- Is it application/x-www-form-urlencoded ?
elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and elseif msg.env.REQUEST_METHOD == "POST" and msg.env.CONTENT_TYPE and
msg.env.CONTENT_TYPE == "application/x-www-form-urlencoded" msg.env.CONTENT_TYPE:match("^application/x%-www%-form%-urlencoded")
then then
return urldecode_message_body( src, msg, filecb ) return urldecode_message_body( src, msg, filecb )

View file

@ -118,7 +118,7 @@ function if_none_match( req, stat )
return true return true
end end
-- 14.27 / If-Range --- 14.27 / If-Range
-- The If-Range header is currently not implemented due to the lack of general -- The If-Range header is currently not implemented due to the lack of general
-- byte range stuff in luci.http.protocol . This function will always return -- byte range stuff in luci.http.protocol . This function will always return
-- false, 412 to indicate a failed precondition. -- false, 412 to indicate a failed precondition.
@ -131,7 +131,7 @@ function if_range( req, stat )
return false, 412 return false, 412
end end
-- 14.28 / If-Unmodified-Since --- 14.28 / If-Unmodified-Since
-- Test whether the given message object contains an "If-Unmodified-Since" -- Test whether the given message object contains an "If-Unmodified-Since"
-- header and compare it against the given stat object. -- header and compare it against the given stat object.
-- @param req HTTP request message object -- @param req HTTP request message object

View file

@ -36,7 +36,7 @@ $(BOA_DIR)/.configured: $(BOA_DIR)/.patched
touch $@ touch $@
boa-compile: $(BOA_DIR)/.configured boa-compile: $(BOA_DIR)/.configured
$(MAKE) -C $(BOA_DIR)/src CC=$(CC) CFLAGS="$(CFLAGS)" $(MAKE) -C $(BOA_DIR)/src CC=$(CC) CFLAGS="$(CFLAGS) -DINET6 -DACCEPT_ON -DWHEN_DOES_THIS_APPLY"
%.o: %.c %.o: %.c
$(COMPILE) $(LUA_CFLAGS) -I$(BOA_DIR)/src $(FPIC) -c -o $@ $< $(COMPILE) $(LUA_CFLAGS) -I$(BOA_DIR)/src $(FPIC) -c -o $@ $<

View file

@ -59,6 +59,7 @@ function handle_req(context)
env.REMOTE_PORT = context.remote_port env.REMOTE_PORT = context.remote_port
env.SERVER_ADDR = context.server_addr env.SERVER_ADDR = context.server_addr
env.HTTP_COOKIE = context.cookie env.HTTP_COOKIE = context.cookie
env.HTTP_ACCEPT = context.http_accept
env.SCRIPT_NAME = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO) env.SCRIPT_NAME = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO)
luci.sgi.webuci.run(env, vars) luci.sgi.webuci.run(env, vars)

View file

@ -267,6 +267,15 @@ config variable
option datatype 'string' option datatype 'string'
option required false option required false
# Variable default value (schema.@variable.default)
config variable
option name 'default'
option title 'Default value of this variable'
option section 'schema.variable'
option type 'variable'
option datatype 'string'
option required false
# Variable validators (schema.@variable.validator) # Variable validators (schema.@variable.validator)
config variable config variable
option name 'validator' option name 'validator'

View file

@ -82,17 +82,17 @@ end
function authenticator.htmlauth(validator, accs, default) function authenticator.htmlauth(validator, accs, default)
local user = luci.http.formvalue("username") local user = luci.http.formvalue("username")
local pass = luci.http.formvalue("password") local pass = luci.http.formvalue("password")
if user and validator(user, pass) then if user and validator(user, pass) then
return user return user
end end
require("luci.i18n") require("luci.i18n")
require("luci.template") require("luci.template")
context.path = {} context.path = {}
luci.template.render("sysauth", {duser=default, fuser=user}) luci.template.render("sysauth", {duser=default, fuser=user})
return false return false
end end
--- Dispatch an HTTP request. --- Dispatch an HTTP request.
@ -110,7 +110,7 @@ function httpdispatch(request)
if not stat then if not stat then
error500(err) error500(err)
end end
luci.http.close() luci.http.close()
--context._disable_memtrace() --context._disable_memtrace()
@ -122,15 +122,15 @@ function dispatch(request)
--context._disable_memtrace = require "luci.debug".trap_memtrace() --context._disable_memtrace = require "luci.debug".trap_memtrace()
local ctx = context local ctx = context
ctx.path = request ctx.path = request
require "luci.i18n".setlanguage(require "luci.config".main.lang) require "luci.i18n".setlanguage(require "luci.config".main.lang)
local c = ctx.tree local c = ctx.tree
local stat local stat
if not c then if not c then
c = createtree() c = createtree()
end end
local track = {} local track = {}
local args = {} local args = {}
context.args = args context.args = args
@ -144,7 +144,7 @@ function dispatch(request)
end end
util.update(track, c) util.update(track, c)
if c.leaf then if c.leaf then
break break
end end
@ -159,11 +159,11 @@ function dispatch(request)
if track.i18n then if track.i18n then
require("luci.i18n").loadc(track.i18n) require("luci.i18n").loadc(track.i18n)
end end
-- Init template engine -- Init template engine
if not track.notemplate then if (c and c.index) or not track.notemplate then
local tpl = require("luci.template") local tpl = require("luci.template")
local media = luci.config.main.mediaurlbase local media = track.mediaurlbase or luci.config.main.mediaurlbase
if not pcall(tpl.Template, "themes/%s/header" % fs.basename(media)) then if not pcall(tpl.Template, "themes/%s/header" % fs.basename(media)) then
media = nil media = nil
for name, theme in pairs(luci.config.themes) do for name, theme in pairs(luci.config.themes) do
@ -183,26 +183,27 @@ function dispatch(request)
viewns.striptags = util.striptags viewns.striptags = util.striptags
viewns.controller = luci.http.getenv("SCRIPT_NAME") viewns.controller = luci.http.getenv("SCRIPT_NAME")
viewns.media = media viewns.media = media
viewns.theme = fs.basename(media)
viewns.resource = luci.config.main.resourcebase viewns.resource = luci.config.main.resourcebase
viewns.REQUEST_URI = (luci.http.getenv("SCRIPT_NAME") or "") .. (luci.http.getenv("PATH_INFO") or "") viewns.REQUEST_URI = (luci.http.getenv("SCRIPT_NAME") or "") .. (luci.http.getenv("PATH_INFO") or "")
end end
track.dependent = (track.dependent ~= false) track.dependent = (track.dependent ~= false)
assert(not track.dependent or not track.auto, "Access Violation") assert(not track.dependent or not track.auto, "Access Violation")
if track.sysauth then if track.sysauth then
local sauth = 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 = ctx.authsession or luci.http.getcookie("sysauth") local sess = ctx.authsession or luci.http.getcookie("sysauth")
sess = sess and sess:match("^[A-F0-9]+$") sess = sess and sess:match("^[A-F0-9]+$")
local user = sauth.read(sess) local user = sauth.read(sess)
if not 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)
@ -231,21 +232,32 @@ function dispatch(request)
luci.sys.process.setuser(track.setuser) luci.sys.process.setuser(track.setuser)
end end
if c and (c.index or type(c.target) == "function") then
ctx.dispatched = c
ctx.requested = ctx.requested or ctx.dispatched
end
if c and c.index then
local tpl = require "luci.template"
if util.copcall(tpl.render, "indexer", {}) then
return true
end
end
if c and type(c.target) == "function" then if c and type(c.target) == "function" then
context.dispatched = c
util.copcall(function() util.copcall(function()
local oldenv = getfenv(c.target) local oldenv = getfenv(c.target)
local module = require(c.module) local module = require(c.module)
local env = setmetatable({}, {__index= local env = setmetatable({}, {__index=
function(tbl, key) function(tbl, key)
return rawget(tbl, key) or module[key] or oldenv[key] return rawget(tbl, key) or module[key] or oldenv[key]
end}) end})
setfenv(c.target, env) setfenv(c.target, env)
end) end)
c.target(unpack(args)) c.target(unpack(args))
else else
error404() error404()
@ -256,7 +268,7 @@ end
function createindex() function createindex()
local path = luci.util.libpath() .. "/controller/" local path = luci.util.libpath() .. "/controller/"
local suff = ".lua" local suff = ".lua"
if luci.util.copcall(require, "luci.fastindex") then if luci.util.copcall(require, "luci.fastindex") then
createindex_fastindex(path, suff) createindex_fastindex(path, suff)
else else
@ -269,14 +281,14 @@ end
-- @param suffix Controller file suffix -- @param suffix Controller file suffix
function createindex_fastindex(path, suffix) function createindex_fastindex(path, suffix)
index = {} index = {}
if not fi then if not fi then
fi = luci.fastindex.new("index") fi = luci.fastindex.new("index")
fi.add(path .. "*" .. suffix) fi.add(path .. "*" .. suffix)
fi.add(path .. "*/*" .. suffix) fi.add(path .. "*/*" .. suffix)
end end
fi.scan() fi.scan()
for k, v in pairs(fi.indexes) do for k, v in pairs(fi.indexes) do
index[v[2]] = v[1] index[v[2]] = v[1]
end end
@ -298,9 +310,9 @@ function createindex_plain(path, suffix)
index = loadfile(indexcache)() index = loadfile(indexcache)()
return index return index
end end
end end
index = {} index = {}
local controllers = util.combine( local controllers = util.combine(
@ -312,12 +324,12 @@ function createindex_plain(path, suffix)
local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".") local module = "luci.controller." .. c:sub(#path+1, #c-#suffix):gsub("/", ".")
local mod = require(module) local mod = require(module)
local idx = mod.index local idx = mod.index
if type(idx) == "function" then if type(idx) == "function" then
index[module] = idx index[module] = idx
end end
end end
if indexcache then if indexcache then
fs.writefile(indexcache, util.get_bytecode(index)) fs.writefile(indexcache, util.get_bytecode(index))
fs.chmod(indexcache, "a-rwx,u+rw") fs.chmod(indexcache, "a-rwx,u+rw")
@ -330,16 +342,16 @@ function createtree()
if not index then if not index then
createindex() createindex()
end end
local ctx = context local ctx = context
local tree = {nodes={}} local tree = {nodes={}}
ctx.treecache = setmetatable({}, {__mode="v"}) ctx.treecache = setmetatable({}, {__mode="v"})
ctx.tree = tree ctx.tree = tree
-- Load default translation -- Load default translation
require "luci.i18n".loadc("default") require "luci.i18n".loadc("default")
local scope = setmetatable({}, {__index = luci.dispatcher}) local scope = setmetatable({}, {__index = luci.dispatcher})
for k, v in pairs(index) do for k, v in pairs(index) do
@ -347,7 +359,7 @@ function createtree()
setfenv(v, scope) setfenv(v, scope)
v() v()
end end
return tree return tree
end end
@ -361,24 +373,24 @@ function assign(path, clone, title, order)
local obj = node(unpack(path)) local obj = node(unpack(path))
obj.nodes = nil obj.nodes = nil
obj.module = nil obj.module = nil
obj.title = title obj.title = title
obj.order = order obj.order = order
setmetatable(obj, {__index = _create_node(clone)}) setmetatable(obj, {__index = _create_node(clone)})
return obj return obj
end end
--- Create a new dispatching node and define common parameters. --- Create a new dispatching node and define common parameters.
-- @param path Virtual path -- @param path Virtual path
-- @param target Target function to call when dispatched. -- @param target Target function to call when dispatched.
-- @param title Destination node title -- @param title Destination node title
-- @param order Destination node order value (optional) -- @param order Destination node order value (optional)
-- @return Dispatching tree node -- @return Dispatching tree node
function entry(path, target, title, order) function entry(path, target, title, order)
local c = node(unpack(path)) local c = node(unpack(path))
c.target = target c.target = target
c.title = title c.title = title
c.order = order c.order = order
@ -404,19 +416,19 @@ function _create_node(path, cache)
if #path == 0 then if #path == 0 then
return context.tree return context.tree
end end
cache = cache or context.treecache cache = cache or context.treecache
local name = table.concat(path, ".") local name = table.concat(path, ".")
local c = cache[name] local c = cache[name]
if not c then if not c then
local last = table.remove(path) local last = table.remove(path)
c = _create_node(path, cache) c = _create_node(path, cache)
local new = {nodes={}, auto=true} local new = {nodes={}, auto=true}
c.nodes[last] = new c.nodes[last] = new
cache[name] = new cache[name] = new
return new return new
else else
return c return c
@ -440,24 +452,30 @@ end
function rewrite(n, ...) function rewrite(n, ...)
local req = arg local req = arg
return function() return function()
for i=1,n do for i=1,n do
table.remove(context.path, 1) table.remove(context.path, 1)
end end
for i,r in ipairs(req) do for i,r in ipairs(req) do
table.insert(context.path, i, r) table.insert(context.path, i, r)
end end
dispatch() dispatch()
end end
end end
--- Create a function-call dispatching target. --- Create a function-call dispatching target.
-- @param name Target function of local controller -- @param name Target function of local controller
-- @param ... Additional parameters passed to the function -- @param ... Additional parameters passed to the function
function call(name, ...) function call(name, ...)
local argv = {...} local argv = {...}
return function() return getfenv()[name](unpack(argv)) end return function(...)
if #argv > 0 then
return getfenv()[name](unpack(argv), ...)
else
return getfenv()[name](...)
end
end
end end
--- Create a template render dispatching target. --- Create a template render dispatching target.
@ -475,13 +493,20 @@ function cbi(model)
return function(...) return function(...)
require("luci.cbi") require("luci.cbi")
require("luci.template") require("luci.template")
local http = require "luci.http"
maps = luci.cbi.load(model, ...) maps = luci.cbi.load(model, ...)
local state = nil
for i, res in ipairs(maps) do for i, res in ipairs(maps) do
res:parse() local cstate = res:parse()
if not state or cstate < state then
state = cstate
end
end end
http.header("X-CBI-State", state or 0)
luci.template.render("cbi/header") luci.template.render("cbi/header")
for i, res in ipairs(maps) do for i, res in ipairs(maps) do
res:render() res:render()
@ -496,13 +521,20 @@ function form(model)
return function(...) return function(...)
require("luci.cbi") require("luci.cbi")
require("luci.template") require("luci.template")
local http = require "luci.http"
maps = luci.cbi.load(model, ...) maps = luci.cbi.load(model, ...)
local state = nil
for i, res in ipairs(maps) do for i, res in ipairs(maps) do
res:parse() local cstate = res:parse()
if not state or cstate < state then
state = cstate
end
end end
http.header("X-CBI-State", state or 0)
luci.template.render("header") luci.template.render("header")
for i, res in ipairs(maps) do for i, res in ipairs(maps) do
res:render() res:render()

View file

@ -192,14 +192,16 @@ end
--- Set the mime type of following content data. --- Set the mime type of following content data.
-- @param mime Mimetype of following content -- @param mime Mimetype of following content
function prepare_content(mime) function prepare_content(mime)
if mime == "application/xhtml+xml" then if not context.headers or not context.headers["content-type"] then
if not getenv("HTTP_ACCEPT") or if mime == "application/xhtml+xml" then
not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then if not getenv("HTTP_ACCEPT") or
mime = "text/html; charset=UTF-8" not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then
mime = "text/html; charset=UTF-8"
end
header("Vary", "Accept")
end end
header("Vary", "Accept") header("Content-Type", mime)
end end
header("Content-Type", mime)
end end
--- Get the RAW HTTP input source --- Get the RAW HTTP input source

View file

@ -12,9 +12,9 @@ Copyright 2008 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
@ -45,7 +45,7 @@ end
-- @param force Force reload even if already loaded (optional) -- @param force Force reload even if already loaded (optional)
-- @return Success status -- @return Success status
function load(file, lang, force) function load(file, lang, force)
lang = lang or "" lang = lang and lang:gsub("_", "-") or ""
if force or not loaded[lang] or not loaded[lang][file] then if force or not loaded[lang] or not loaded[lang][file] then
local f = loadfile(i18ndir .. file .. "." .. lang .. ".lua") local f = loadfile(i18ndir .. file .. "." .. lang .. ".lua")
if f then if f then
@ -75,7 +75,7 @@ end
--- Set the context default translation language. --- Set the context default translation language.
-- @param lang Two-letter language code -- @param lang Two-letter language code
function setlanguage(lang) function setlanguage(lang)
context.lang = lang context.lang = lang:gsub("_", "-")
end end
--- Return the translated value for a specific translation key. --- Return the translated value for a specific translation key.
@ -95,4 +95,4 @@ end
-- @return Translated and formatted string -- @return Translated and formatted string
function translatef(key, default, ...) function translatef(key, default, ...)
return translate(key, default):format(...) return translate(key, default):format(...)
end end