* luci-0.8: backport library fixes
authorJo-Philipp Wich <jow@openwrt.org>
Wed, 29 Oct 2008 19:41:33 +0000 (19:41 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Wed, 29 Oct 2008 19:41:33 +0000 (19:41 +0000)
16 files changed:
libs/cbi/htdocs/luci-static/resources/cbi.js
libs/cbi/luasrc/cbi.lua
libs/cbi/luasrc/view/cbi/button.htm
libs/cbi/luasrc/view/cbi/footer.htm
libs/cbi/luasrc/view/cbi/header.htm
libs/cbi/luasrc/view/cbi/nsection.htm
libs/cbi/luasrc/view/cbi/tsection.htm
libs/core/luasrc/util.lua
libs/http/luasrc/http/protocol.lua
libs/http/luasrc/http/protocol/conditionals.lua
libs/sgi-webuci/Makefile
libs/sgi-webuci/root/usr/lib/boa/luci.lua
libs/uvl/root/lib/uci/schema/meta/schema
libs/web/luasrc/dispatcher.lua
libs/web/luasrc/http.lua
libs/web/luasrc/i18n.lua

index d7bc74bc5f7d53ee639316a8beb87c3e6894ed70..4b1849beab9cfe083b0d7ec360c6dd488dc4e6d6 100644 (file)
@@ -167,3 +167,13 @@ function cbi_combobox_init(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();
+}
index d2de8685b5303c9e8a56c039df8ac9e2829ea608..94ac9648376aada809be5f200e2f10bd0595c3fb 100644 (file)
@@ -30,6 +30,7 @@ require("luci.template")
 require("luci.util")
 require("luci.http")
 require("luci.uvl")
+require("luci.fs")
 
 local uci        = require("luci.model.uci")
 local class      = luci.util.class
@@ -38,6 +39,7 @@ local instanceof = luci.util.instanceof
 FORM_NODATA  =  0
 FORM_VALID   =  1
 FORM_INVALID = -1
+FORM_CHANGED =  2
 
 AUTO = true
 
@@ -51,6 +53,7 @@ function load(cbimap, ...)
        require("luci.config")
        require("luci.util")
 
+       local upldir = "/lib/uci/upload/"
        local cbidir = luci.util.libpath() .. "/model/cbi/"
        local func, err = loadfile(cbimap) or loadfile(cbidir..cbimap..".lua")
        assert(func, err)
@@ -69,7 +72,9 @@ function load(cbimap, ...)
                        return rawget(tbl, key) or _M[key] or _G[key]
                end}))
 
-       local maps = {func()}
+       local maps       = { func() }
+       local uploads    = { }
+       local has_upload = false
 
        for i, map in ipairs(maps) do
                if not instanceof(map, Node) then
@@ -77,9 +82,58 @@ function load(cbimap, ...)
                        return nil
                else
                        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
 
+       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
 end
 
@@ -251,6 +305,9 @@ function Map.get_scheme(self, sectiontype, option)
        end
 end
 
+function Map.submitstate(self)
+       return luci.http.formvalue("cbi.submit")
+end
 
 -- Chain foreign config
 function Map.chain(self, config)
@@ -288,6 +345,19 @@ function Map.parse(self)
                for i, config in ipairs(self.parsechain) do
                        self.uci:unload(config)
                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
 
@@ -383,11 +453,12 @@ function SimpleForm.parse(self, ...)
        end
 
        local state =
-               not luci.http.formvalue("cbi.submit") and 0
-               or valid and 1
-               or -1
+               not self:submitstate() and FORM_NODATA
+               or valid and FORM_VALID
+               or FORM_INVALID
 
        self.dorender = not self.handle or self:handle(state, self.data) ~= false
+       return state
 end
 
 function SimpleForm.render(self, ...)
@@ -396,6 +467,10 @@ function SimpleForm.render(self, ...)
        end
 end
 
+function SimpleForm.submitstate(self)
+       return luci.http.formvalue("cbi.submit")
+end
+
 function SimpleForm.section(self, class, ...)
        if instanceof(class, AbstractSection) then
                local obj  = class(self, ...)
@@ -615,6 +690,10 @@ function Table.__init__(self, form, data, ...)
        function datasource.get(self, section, option)
                return data[section] and data[section][option]
        end
+       
+       function datasource.submitstate(self)
+               return luci.http.formvalue("cbi.submit")
+       end
 
        function datasource.del(...)
                return true
@@ -632,7 +711,7 @@ end
 
 function Table.parse(self)
        for i, k in ipairs(self:cfgsections()) do
-               if luci.http.formvalue("cbi.submit") then
+               if self.map:submitstate() then
                        Node.parse(self, k)
                end
        end
@@ -695,7 +774,7 @@ function NamedSection.parse(self, novld)
 
        if active then
                AbstractSection.parse_dynamic(self, s)
-               if luci.http.formvalue("cbi.submit") then
+               if self.map:submitstate() then
                        Node.parse(self, s)
 
                        if not novld and not self.override_scheme and self.map.scheme then
@@ -770,7 +849,7 @@ function TypedSection.parse(self, novld)
        local co
        for i, k in ipairs(self:cfgsections()) do
                AbstractSection.parse_dynamic(self, k)
-               if luci.http.formvalue("cbi.submit") then
+               if self.map:submitstate() then
                        Node.parse(self, k)
 
                        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.rmempty = true
 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
index c6606622d693ddd586317b1c3525017206a1b846..5a5189794adfe71080be3e550949d516adba0512 100644 (file)
@@ -14,7 +14,7 @@ $Id$
 -%>
 <%+cbi/valueheader%>
        <% 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 %>
                -
        <% end %>
index a688fcddde0b640d5ca93eedf78e945d97094436..da592660183708cbff762f53d71286e220aa87b7 100644 (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-save" type="submit" value="<%:save%>" />
                <input class="cbi-button cbi-button-reset" type="reset" value="<%:reset%>" />
index ce5d66d77a513322b70b27e34679d16d4691d0c2..3f60baf52cd50605dd532706990b2bfef50afe1b 100644 (file)
@@ -14,7 +14,7 @@ $Id$
 -%>
 
 <%+header%>
-<form method="post" action="<%=luci.http.getenv("REQUEST_URI")%>">
+<form method="post" action="<%=luci.http.getenv("REQUEST_URI")%>" enctype="multipart/form-data">
        <div>
                <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
                <input type="hidden" name="cbi.submit" value="1" />
index 156137eeba8addc2f7bb431c6b13a76aa4163942..d766464bd17d10e67c8312e63de988cf51dd4ef1 100644 (file)
@@ -32,6 +32,7 @@ $Id$
                <br />
        </fieldset>
 <% elseif self.addremove then %>
+       <% if self.template_addremove then include(self.template_addremove) else -%>
        <fieldset class="cbi-section" id="cbi-<%=self.config%>-<%=self.section%>">
                <% if self.title and #self.title > 0 then -%>
                        <legend><%=self.title%></legend>
@@ -39,5 +40,6 @@ $Id$
                <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%>" />
        </fieldset>
+       <%- end %>
 <% end %>
 <!-- /nsection -->
index 70c44aaf6b5e16f283a02998fc20081f6dc18866..db723f92aad5224eeb028e2d982a04d5860875aa 100644 (file)
@@ -41,6 +41,7 @@ $Id$
        <%- end %>
 
        <% if self.addremove then -%>
+               <% if self.template_addremove then include(self.template_addremove) else -%>
                <div class="cbi-section-create">
                        <% if self.anonymous then -%>
                                <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 %>
                </div>
+               <%- end %>
        <%- end %>
 </fieldset>
index 51f6224093cff264741c7e221741c879e0774e63..77c763d149d7b580a826d85a134e31bebf4eef22 100644 (file)
@@ -33,7 +33,6 @@ 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
index c455784706fe867ee7b3746dd45448b656e8d146..e0c15015b28890330406210cc22d47d52a7aff80 100644 (file)
@@ -131,7 +131,7 @@ function urlencode_params( tbl )
        return enc
 end
 
---- (Internal function)
+-- (Internal function)
 -- Initialize given parameter and coerce string into table when the parameter
 -- already exists.
 -- @param tbl  Table where parameter should be created
@@ -147,7 +147,7 @@ local function __initval( tbl, key )
        end
 end
 
---- (Internal function)
+-- (Internal function)
 -- 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.
 -- @param tbl  Table containing the previously initialized parameter value
@@ -163,7 +163,7 @@ local function __appendval( tbl, key, chunk )
        end
 end
 
---- (Internal function)
+-- (Internal function)
 -- 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
 -- associated values table.
@@ -563,12 +563,14 @@ function parse_message_header( src )
                        -- Populate common environment variables
                        msg.env = {
                                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_URI       = msg.request_uri;
                                SCRIPT_NAME       = msg.request_uri:gsub("?.+$","");
                                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
@@ -617,7 +619,7 @@ function parse_message_body( src, msg, filecb )
 
        -- Is it application/x-www-form-urlencoded ?
        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
                return urldecode_message_body( src, msg, filecb )
 
index d31a47454cc2e7b33a6959e4f386b3b2daffb28b..015cf4518b40de49226661e7dd99e9d3d43ffe19 100644 (file)
@@ -118,7 +118,7 @@ function if_none_match( req, stat )
        return true
 end
 
--- 14.27 / If-Range
+--- 14.27 / If-Range
 -- 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
 -- false, 412 to indicate a failed precondition.
@@ -131,7 +131,7 @@ function if_range( req, stat )
        return false, 412
 end
 
--- 14.28 / If-Unmodified-Since
+--- 14.28 / If-Unmodified-Since
 -- Test whether the given message object contains an "If-Unmodified-Since"
 -- header and compare it against the given stat object.
 -- @param req  HTTP request message object
index c7f70eb5c8a6063fd9524e3ed0bc9968053c7e27..81ed3fe236564ddb0cae30d62d4d5a185b4c228b 100644 (file)
@@ -36,7 +36,7 @@ $(BOA_DIR)/.configured: $(BOA_DIR)/.patched
        touch $@
 
 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
        $(COMPILE) $(LUA_CFLAGS) -I$(BOA_DIR)/src $(FPIC) -c -o $@ $< 
index 6cb019d16ad6e601b321ef5c590d966825414639..2bb9313a66cf9eff6b62a0418bf3d8c993186b32 100644 (file)
@@ -59,6 +59,7 @@ function handle_req(context)
        env.REMOTE_PORT     = context.remote_port
        env.SERVER_ADDR     = context.server_addr
        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)
 
        luci.sgi.webuci.run(env, vars)
index dd373f8ae0e6992e8bd6be3d19ee8fd778977f0b..3b78725d5382acc6513da36bf4002f77d540d371 100644 (file)
@@ -267,6 +267,15 @@ config variable
        option datatype 'string'
        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)
 config variable
        option name             'validator'
index cbbb7492104662b15c912524668e17e3dff0ac27..d58987a3f2f4a5ec394f1bd73646e428c8e2da3f 100644 (file)
@@ -82,17 +82,17 @@ end
 function authenticator.htmlauth(validator, accs, default)
        local user = luci.http.formvalue("username")
        local pass = luci.http.formvalue("password")
-       
+
        if user and validator(user, pass) then
                return user
        end
-       
+
        require("luci.i18n")
        require("luci.template")
        context.path = {}
        luci.template.render("sysauth", {duser=default, fuser=user})
        return false
-       
+
 end
 
 --- Dispatch an HTTP request.
@@ -110,7 +110,7 @@ function httpdispatch(request)
        if not stat then
                error500(err)
        end
-       
+
        luci.http.close()
 
        --context._disable_memtrace()
@@ -122,15 +122,15 @@ function dispatch(request)
        --context._disable_memtrace = require "luci.debug".trap_memtrace()
        local ctx = context
        ctx.path = request
-       
+
        require "luci.i18n".setlanguage(require "luci.config".main.lang)
-       
+
        local c = ctx.tree
        local stat
        if not c then
                c = createtree()
        end
-       
+
        local track = {}
        local args = {}
        context.args = args
@@ -144,7 +144,7 @@ function dispatch(request)
                end
 
                util.update(track, c)
-               
+
                if c.leaf then
                        break
                end
@@ -159,11 +159,11 @@ function dispatch(request)
        if track.i18n then
                require("luci.i18n").loadc(track.i18n)
        end
-       
+
        -- Init template engine
-       if not track.notemplate then
+       if (c and c.index) or not track.notemplate then
                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
                        media = nil
                        for name, theme in pairs(luci.config.themes) do
@@ -183,26 +183,27 @@ function dispatch(request)
                viewns.striptags   = util.striptags
                viewns.controller  = luci.http.getenv("SCRIPT_NAME")
                viewns.media       = media
+               viewns.theme       = fs.basename(media)
                viewns.resource    = luci.config.main.resourcebase
                viewns.REQUEST_URI = (luci.http.getenv("SCRIPT_NAME") or "") .. (luci.http.getenv("PATH_INFO") or "")
        end
-       
+
        track.dependent = (track.dependent ~= false)
        assert(not track.dependent or not track.auto, "Access Violation")
-       
+
        if track.sysauth then
                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 = ctx.authsession or luci.http.getcookie("sysauth")
                sess = sess and sess:match("^[A-F0-9]+$")
                local user = sauth.read(sess)
-               
+
                if not util.contains(accs, user) then
                        if authen then
                                local user, sess = authen(luci.sys.user.checkpasswd, accs, def)
@@ -231,21 +232,32 @@ function dispatch(request)
                luci.sys.process.setuser(track.setuser)
        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
-               context.dispatched = c
-               
                util.copcall(function()
                        local oldenv = getfenv(c.target)
                        local module = require(c.module)
                        local env = setmetatable({}, {__index=
-                               
+
                        function(tbl, key)
-                               return rawget(tbl, key) or module[key] or oldenv[key] 
+                               return rawget(tbl, key) or module[key] or oldenv[key]
                        end})
 
                        setfenv(c.target, env)
                end)
-               
+
                c.target(unpack(args))
        else
                error404()
@@ -256,7 +268,7 @@ end
 function createindex()
        local path = luci.util.libpath() .. "/controller/"
        local suff = ".lua"
-       
+
        if luci.util.copcall(require, "luci.fastindex") then
                createindex_fastindex(path, suff)
        else
@@ -269,14 +281,14 @@ end
 -- @param suffix       Controller file suffix
 function createindex_fastindex(path, suffix)
        index = {}
-               
+
        if not fi then
                fi = luci.fastindex.new("index")
                fi.add(path .. "*" .. suffix)
                fi.add(path .. "*/*" .. suffix)
        end
        fi.scan()
-       
+
        for k, v in pairs(fi.indexes) do
                index[v[2]] = v[1]
        end
@@ -298,9 +310,9 @@ function createindex_plain(path, suffix)
 
                        index = loadfile(indexcache)()
                        return index
-               end             
+               end
        end
-       
+
        index = {}
 
        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 mod = require(module)
                local idx = mod.index
-               
+
                if type(idx) == "function" then
                        index[module] = idx
                end
        end
-       
+
        if indexcache then
                fs.writefile(indexcache, util.get_bytecode(index))
                fs.chmod(indexcache, "a-rwx,u+rw")
@@ -330,16 +342,16 @@ function createtree()
        if not index then
                createindex()
        end
-       
+
        local ctx  = context
        local tree = {nodes={}}
-       
+
        ctx.treecache = setmetatable({}, {__mode="v"})
        ctx.tree = tree
-       
+
        -- Load default translation
        require "luci.i18n".loadc("default")
-       
+
        local scope = setmetatable({}, {__index = luci.dispatcher})
 
        for k, v in pairs(index) do
@@ -347,7 +359,7 @@ function createtree()
                setfenv(v, scope)
                v()
        end
-       
+
        return tree
 end
 
@@ -361,24 +373,24 @@ function assign(path, clone, title, order)
        local obj  = node(unpack(path))
        obj.nodes  = nil
        obj.module = nil
-       
+
        obj.title = title
        obj.order = order
 
        setmetatable(obj, {__index = _create_node(clone)})
-       
+
        return obj
 end
 
 --- Create a new dispatching node and define common parameters.
 -- @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      order   Destination node order value (optional)
 -- @return                     Dispatching tree node
 function entry(path, target, title, order)
        local c = node(unpack(path))
-       
+
        c.target = target
        c.title  = title
        c.order  = order
@@ -404,19 +416,19 @@ 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
@@ -440,24 +452,30 @@ end
 function rewrite(n, ...)
        local req = arg
        return function()
-               for i=1,n do 
+               for i=1,n do
                        table.remove(context.path, 1)
                end
-               
+
                for i,r in ipairs(req) do
                        table.insert(context.path, i, r)
                end
-               
+
                dispatch()
        end
 end
 
 --- 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
 function call(name, ...)
        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
 
 --- Create a template render dispatching target.
@@ -475,13 +493,20 @@ function cbi(model)
        return function(...)
                require("luci.cbi")
                require("luci.template")
+               local http = require "luci.http"
 
                maps = luci.cbi.load(model, ...)
 
+               local state = nil
+
                for i, res in ipairs(maps) do
-                       res:parse()
+                       local cstate = res:parse()
+                       if not state or cstate < state then
+                               state = cstate
+                       end
                end
 
+               http.header("X-CBI-State", state or 0)
                luci.template.render("cbi/header")
                for i, res in ipairs(maps) do
                        res:render()
@@ -496,13 +521,20 @@ function form(model)
        return function(...)
                require("luci.cbi")
                require("luci.template")
+               local http = require "luci.http"
 
                maps = luci.cbi.load(model, ...)
 
+               local state = nil
+
                for i, res in ipairs(maps) do
-                       res:parse()
+                       local cstate = res:parse()
+                       if not state or cstate < state then
+                               state = cstate
+                       end
                end
 
+               http.header("X-CBI-State", state or 0)
                luci.template.render("header")
                for i, res in ipairs(maps) do
                        res:render()
index 6b73b9414cf0c129a1596ac4144b64d12fc529da..c5a85ea4d9f777187855549adabf0c18e199f32a 100644 (file)
@@ -192,14 +192,16 @@ end
 --- Set the mime type of following content data.
 -- @param mime Mimetype of following content
 function prepare_content(mime)
-       if mime == "application/xhtml+xml" then
-               if not getenv("HTTP_ACCEPT") or
-                 not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then
-                       mime = "text/html; charset=UTF-8"
+       if not context.headers or not context.headers["content-type"] then
+               if mime == "application/xhtml+xml" then
+                       if not getenv("HTTP_ACCEPT") or
+                         not getenv("HTTP_ACCEPT"):find("application/xhtml+xml", nil, true) then
+                               mime = "text/html; charset=UTF-8"
+                       end
+                       header("Vary", "Accept")
                end
-               header("Vary", "Accept")
+               header("Content-Type", mime)
        end
-       header("Content-Type", mime)
 end
 
 --- Get the RAW HTTP input source
index 84a869539715096a55007bf9e90ee0ebab1c8090..4b3adf7ebb635418be484ec6275d6dc457101dfc 100644 (file)
@@ -12,9 +12,9 @@ Copyright 2008 Steven Barth <steven@midlink.org>
 
 Licensed under the Apache License, Version 2.0 (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
 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)
 -- @return             Success status
 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
                local f = loadfile(i18ndir .. file .. "." .. lang .. ".lua")
                if f then
@@ -75,7 +75,7 @@ end
 --- Set the context default translation language.
 -- @param lang Two-letter language code
 function setlanguage(lang)
-       context.lang = lang
+       context.lang = lang:gsub("_", "-")
 end
 
 --- Return the translated value for a specific translation key.
@@ -95,4 +95,4 @@ end
 -- @return                     Translated and formatted string
 function translatef(key, default, ...)
        return translate(key, default):format(...)
-end
\ No newline at end of file
+end