X-Git-Url: https://git.archive.openwrt.org/?p=project%2Fluci.git;a=blobdiff_plain;f=libs%2Fcbi%2Fluasrc%2Fcbi.lua;h=78f6b7d5efac6f157dcb16d3061c1e1d7d40c345;hp=6432a2590d034782121e85d14b144e6905511cf5;hb=14a2e32142cc2bba58de79de8b2b410be21b7ac7;hpb=d0442f8aab131cb53deaed1da81e09001cc33a82 diff --git a/libs/cbi/luasrc/cbi.lua b/libs/cbi/luasrc/cbi.lua index 6432a2590..78f6b7d5e 100644 --- a/libs/cbi/luasrc/cbi.lua +++ b/libs/cbi/luasrc/cbi.lua @@ -30,14 +30,18 @@ require("luci.template") require("luci.util") require("luci.http") require("luci.uvl") +require("luci.fs") +--local event = require "luci.sys.event" local uci = require("luci.model.uci") local class = luci.util.class local instanceof = luci.util.instanceof FORM_NODATA = 0 +FORM_PROCEED = 0 FORM_VALID = 1 FORM_INVALID = -1 +FORM_CHANGED = 2 AUTO = true @@ -51,6 +55,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 +74,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 +84,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 @@ -233,6 +289,9 @@ function Map.__init__(self, config, ...) self.apply_on_parse = nil self.uci = uci.cursor() self.save = true + + self.changed = false + if not self.uci:load(self.config) then error("Unable to read UCI data: " .. self.config) end @@ -251,6 +310,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) @@ -265,7 +327,7 @@ function Map.parse(self) for i, config in ipairs(self.parsechain) do self.uci:save(config) end - if luci.http.formvalue("cbi.apply") then + if self:submitstate() and (self.autoapply or luci.http.formvalue("cbi.apply")) then for i, config in ipairs(self.parsechain) do self.uci:commit(config) @@ -288,7 +350,22 @@ 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 + self.state = self.changed and FORM_CHANGED or FORM_VALID + else + self.state = FORM_INVALID + end + else + self.state = FORM_NODATA end + + return self.state end function Map.render(self, ...) @@ -366,6 +443,7 @@ function SimpleForm.__init__(self, config, title, description, data) self.data = data or {} self.template = "cbi/simpleform" self.dorender = true + self.pageaction = false end function SimpleForm.parse(self, ...) @@ -383,11 +461,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 +475,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, ...) @@ -466,6 +549,7 @@ function AbstractSection.__init__(self, map, sectiontype, ...) self.tag_error = {} self.tag_invalid = {} self.tag_deperror = {} + self.changed = false self.optional = true self.addremove = false @@ -565,6 +649,12 @@ function AbstractSection.cfgvalue(self, section) return self.map:get(section) end +-- Push events +function AbstractSection.push_events(self) + --luci.util.append(self.map.events, self.events) + self.map.changed = true +end + -- Removes the section function AbstractSection.remove(self, section) return self.map:del(section) @@ -615,6 +705,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 +726,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 +789,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 @@ -703,6 +797,10 @@ function NamedSection.parse(self, novld) end end AbstractSection.parse_optionals(self, s) + + if self.changed then + self:push_events() + end end end @@ -770,7 +868,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 @@ -815,6 +913,10 @@ function TypedSection.parse(self, novld) AbstractSection.parse_optionals(self, created) end end + + if created or self.changed then + self:push_events() + end end -- Verifies scope of sections @@ -958,11 +1060,19 @@ function AbstractValue.parse(self, section) self.tag_invalid[section] = true end if fvalue and not (fvalue == cvalue) then - self:write(section, fvalue) + if self:write(section, fvalue) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end end else -- Unset the UCI or error if self.rmempty or self.optional then - self:remove(section) + if self:remove(section) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end elseif self.track_missing and (not fvalue or fvalue ~= cvalue) then self.tag_missing[section] = true end @@ -1011,7 +1121,7 @@ function AbstractValue.cfgvalue(self, section) return value[1] end elseif self.cast == "table" then - return {value} + return luci.util.split(value, "%s+", nil, true) end end @@ -1065,6 +1175,20 @@ function DummyValue.__init__(self, ...) self.value = nil end +function DummyValue.cfgvalue(self, section) + local value + if self.value then + if type(self.value) == "function" then + value = self:value(section) + else + value = self.value + end + else + value = AbstractValue.cfgvalue(self, section) + end + return value +end + function DummyValue.parse(self) end @@ -1311,3 +1435,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