* 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 d7bc74b..4b1849b 100644 (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();
+}
index d2de868..94ac964 100644 (file)
@@ -30,6 +30,7 @@ require("luci.template")
 require("luci.util")
 require("luci.http")
 require("luci.uvl")
 require("luci.util")
 require("luci.http")
 require("luci.uvl")
+require("luci.fs")
 
 local uci        = require("luci.model.uci")
 local class      = luci.util.class
 
 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_NODATA  =  0
 FORM_VALID   =  1
 FORM_INVALID = -1
+FORM_CHANGED =  2
 
 AUTO = true
 
 
 AUTO = true
 
@@ -51,6 +53,7 @@ function load(cbimap, ...)
        require("luci.config")
        require("luci.util")
 
        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)
        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}))
 
                        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
 
        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()
                        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
 
                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
 
        return maps
 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
 function Map.chain(self, config)
 
 -- 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
                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
 
        end
 end
 
@@ -383,11 +453,12 @@ function SimpleForm.parse(self, ...)
        end
 
        local state =
        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
 
        self.dorender = not self.handle or self:handle(state, self.data) ~= false
+       return state
 end
 
 function SimpleForm.render(self, ...)
 end
 
 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, ...)
        if instanceof(class, AbstractSection) then
                local obj  = class(self, ...)
 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.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
 
        function datasource.del(...)
                return true
@@ -632,7 +711,7 @@ end
 
 function Table.parse(self)
        for i, k in ipairs(self:cfgsections()) do
 
 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
                        Node.parse(self, k)
                end
        end
@@ -695,7 +774,7 @@ function NamedSection.parse(self, novld)
 
        if active then
                AbstractSection.parse_dynamic(self, s)
 
        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
                        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)
        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
                        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
        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 c660662..5a51897 100644 (file)
@@ -14,7 +14,7 @@ $Id$
 -%>
 <%+cbi/valueheader%>
        <% if self:cfgvalue(section) ~= false then %>
 -%>
 <%+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 %>
        <% else %>
                -
        <% end %>
index a688fcd..da59266 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%>" />
                <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 ce5d66d..3f60baf 100644 (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>
                <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
                <input type="hidden" name="cbi.submit" value="1" />
        <div>
                <script type="text/javascript" src="<%=resource%>/cbi.js"></script>
                <input type="hidden" name="cbi.submit" value="1" />
index 156137e..d766464 100644 (file)
@@ -32,6 +32,7 @@ $Id$
                <br />
        </fieldset>
 <% elseif self.addremove then %>
                <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>
        <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>
                <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 -->
 <% end %>
 <!-- /nsection -->
index 70c44aa..db723f9 100644 (file)
@@ -41,6 +41,7 @@ $Id$
        <%- end %>
 
        <% if self.addremove then -%>
        <%- 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%>" />
                <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 %>
                </div>
+               <%- end %>
        <%- end %>
 </fieldset>
        <%- end %>
 </fieldset>
index 51f6224..77c763d 100644 (file)
@@ -33,7 +33,6 @@ local string = require "string"
 local coroutine = require "coroutine"
 
 local getmetatable, setmetatable = getmetatable, setmetatable
 local coroutine = require "coroutine"
 
 local getmetatable, setmetatable = getmetatable, setmetatable
-local getfenv, setfenv = getfenv, setfenv
 local rawget, rawset, unpack = rawget, rawset, unpack
 local tostring, type, assert = tostring, type, assert
 local ipairs, pairs, loadstring = ipairs, pairs, loadstring
 local rawget, rawset, unpack = rawget, rawset, unpack
 local tostring, type, assert = tostring, type, assert
 local ipairs, pairs, loadstring = ipairs, pairs, loadstring
index c455784..e0c1501 100644 (file)
@@ -131,7 +131,7 @@ function urlencode_params( tbl )
        return enc
 end
 
        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
 -- 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
 
        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
 -- 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
 
        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.
 -- 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'];
                        -- 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
                                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
                        }
 
                        -- 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
 
        -- 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 )
 
        then
                return urldecode_message_body( src, msg, filecb )
 
index d31a474..015cf45 100644 (file)
@@ -118,7 +118,7 @@ function if_none_match( req, stat )
        return true
 end
 
        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.
 -- 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
 
        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
 -- 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 c7f70eb..81ed3fe 100644 (file)
@@ -36,7 +36,7 @@ $(BOA_DIR)/.configured: $(BOA_DIR)/.patched
        touch $@
 
 boa-compile: $(BOA_DIR)/.configured
        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 $@ $< 
 
 %.o: %.c
        $(COMPILE) $(LUA_CFLAGS) -I$(BOA_DIR)/src $(FPIC) -c -o $@ $< 
index 6cb019d..2bb9313 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.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)
        env.SCRIPT_NAME     = env.REQUEST_URI:sub(1, #env.REQUEST_URI - #env.PATH_INFO)
 
        luci.sgi.webuci.run(env, vars)
index dd373f8..3b78725 100644 (file)
@@ -267,6 +267,15 @@ config variable
        option datatype 'string'
        option required false
 
        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'
 # Variable validators (schema.@variable.validator)
 config variable
        option name             'validator'
index cbbb749..d58987a 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")
 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
        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
        require("luci.i18n")
        require("luci.template")
        context.path = {}
        luci.template.render("sysauth", {duser=default, fuser=user})
        return false
-       
+
 end
 
 --- Dispatch an HTTP request.
 end
 
 --- Dispatch an HTTP request.
@@ -110,7 +110,7 @@ function httpdispatch(request)
        if not stat then
                error500(err)
        end
        if not stat then
                error500(err)
        end
-       
+
        luci.http.close()
 
        --context._disable_memtrace()
        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
        --context._disable_memtrace = require "luci.debug".trap_memtrace()
        local ctx = context
        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 stat
        if not c then
                c = createtree()
        end
        local c = ctx.tree
        local stat
        if not c then
                c = createtree()
        end
-       
+
        local track = {}
        local args = {}
        context.args = args
        local track = {}
        local args = {}
        context.args = args
@@ -144,7 +144,7 @@ function dispatch(request)
                end
 
                util.update(track, c)
                end
 
                util.update(track, c)
-               
+
                if c.leaf then
                        break
                end
                if c.leaf then
                        break
                end
@@ -159,11 +159,11 @@ function dispatch(request)
        if track.i18n then
                require("luci.i18n").loadc(track.i18n)
        end
        if track.i18n then
                require("luci.i18n").loadc(track.i18n)
        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
                        media = nil
                        for name, theme in pairs(luci.config.themes) do
                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.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
                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")
        track.dependent = (track.dependent ~= false)
        assert(not track.dependent or not track.auto, "Access Violation")
-       
+
        if track.sysauth then
                local sauth = require "luci.sauth"
        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 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)
                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)
                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
 
                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
        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=
                util.copcall(function()
                        local oldenv = getfenv(c.target)
                        local module = require(c.module)
                        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})
 
                        setfenv(c.target, env)
                end)
                        end})
 
                        setfenv(c.target, env)
                end)
-               
+
                c.target(unpack(args))
        else
                error404()
                c.target(unpack(args))
        else
                error404()
@@ -256,7 +268,7 @@ end
 function createindex()
        local path = luci.util.libpath() .. "/controller/"
        local suff = ".lua"
 function createindex()
        local path = luci.util.libpath() .. "/controller/"
        local suff = ".lua"
-       
+
        if luci.util.copcall(require, "luci.fastindex") then
                createindex_fastindex(path, suff)
        else
        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 = {}
 -- @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()
        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
        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
 
                        index = loadfile(indexcache)()
                        return index
-               end             
+               end
        end
        end
-       
+
        index = {}
 
        local controllers = util.combine(
        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
                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 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")
        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
        if not index then
                createindex()
        end
-       
+
        local ctx  = context
        local tree = {nodes={}}
        local ctx  = context
        local tree = {nodes={}}
-       
+
        ctx.treecache = setmetatable({}, {__mode="v"})
        ctx.tree = tree
        ctx.treecache = setmetatable({}, {__mode="v"})
        ctx.tree = tree
-       
+
        -- Load default translation
        require "luci.i18n".loadc("default")
        -- Load default translation
        require "luci.i18n".loadc("default")
-       
+
        local scope = setmetatable({}, {__index = luci.dispatcher})
 
        for k, v in pairs(index) do
        local scope = setmetatable({}, {__index = luci.dispatcher})
 
        for k, v in pairs(index) do
@@ -347,7 +359,7 @@ function createtree()
                setfenv(v, scope)
                v()
        end
                setfenv(v, scope)
                v()
        end
-       
+
        return tree
 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
        local obj  = node(unpack(path))
        obj.nodes  = nil
        obj.module = nil
-       
+
        obj.title = title
        obj.order = order
 
        setmetatable(obj, {__index = _create_node(clone)})
        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
        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))
 -- @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
        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
        if #path == 0 then
                return context.tree
        end
-       
+
        cache = cache or context.treecache
        local name = table.concat(path, ".")
        local c = cache[name]
        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)
        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
                local new = {nodes={}, auto=true}
                c.nodes[last] = new
                cache[name] = new
-               
+
                return new
        else
                return c
                return new
        else
                return c
@@ -440,24 +452,30 @@ end
 function rewrite(n, ...)
        local req = arg
        return function()
 function rewrite(n, ...)
        local req = arg
        return function()
-               for i=1,n do 
+               for i=1,n do
                        table.remove(context.path, 1)
                end
                        table.remove(context.path, 1)
                end
-               
+
                for i,r in ipairs(req) do
                        table.insert(context.path, i, r)
                end
                for i,r in ipairs(req) do
                        table.insert(context.path, i, r)
                end
-               
+
                dispatch()
        end
 end
 
 --- Create a function-call dispatching target.
                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 = {...}
 -- @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.
 end
 
 --- Create a template render dispatching target.
@@ -475,13 +493,20 @@ function cbi(model)
        return function(...)
                require("luci.cbi")
                require("luci.template")
        return function(...)
                require("luci.cbi")
                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")
                for i, res in ipairs(maps) do
                        res:render()
                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")
        return function(...)
                require("luci.cbi")
                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")
                for i, res in ipairs(maps) do
                        res:render()
                luci.template.render("header")
                for i, res in ipairs(maps) do
                        res:render()
index 6b73b94..c5a85ea 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)
 --- 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
                end
-               header("Vary", "Accept")
+               header("Content-Type", mime)
        end
        end
-       header("Content-Type", mime)
 end
 
 --- Get the RAW HTTP input source
 end
 
 --- Get the RAW HTTP input source
index 84a8695..4b3adf7 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.
 
 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,
 
 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)
 -- @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
        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)
 --- 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.
 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(...)
 -- @return                     Translated and formatted string
 function translatef(key, default, ...)
        return translate(key, default):format(...)
-end
\ No newline at end of file
+end