summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/luasrc/cbi.lua
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-base/luasrc/cbi.lua')
-rw-r--r--modules/luci-base/luasrc/cbi.lua172
1 files changed, 109 insertions, 63 deletions
diff --git a/modules/luci-base/luasrc/cbi.lua b/modules/luci-base/luasrc/cbi.lua
index f3d4618b65..2c1bb4d226 100644
--- a/modules/luci-base/luasrc/cbi.lua
+++ b/modules/luci-base/luasrc/cbi.lua
@@ -38,7 +38,7 @@ function load(cbimap, ...)
require("luci.config")
require("luci.util")
- local upldir = "/lib/uci/upload/"
+ local upldir = "/etc/luci-uploads/"
local cbidir = luci.util.libpath() .. "/model/cbi/"
local func, err
@@ -367,63 +367,64 @@ end
-- Use optimized UCI writing
function Map.parse(self, readinput, ...)
- self.readinput = (readinput ~= false)
- self:_run_hooks("on_parse")
-
if self:formvalue("cbi.skip") then
self.state = FORM_SKIP
+ elseif not self.save then
+ self.state = FORM_INVALID
+ elseif not self:submitstate() then
+ self.state = FORM_NODATA
+ end
+
+ -- Back out early to prevent unauthorized changes on the subsequent parse
+ if self.state ~= nil then
return self:state_handler(self.state)
end
+ self.readinput = (readinput ~= false)
+ self:_run_hooks("on_parse")
+
Node.parse(self, ...)
- if self.save then
- self:_run_hooks("on_save", "on_before_save")
+ self:_run_hooks("on_save", "on_before_save")
+ for i, config in ipairs(self.parsechain) do
+ self.uci:save(config)
+ end
+ self:_run_hooks("on_after_save")
+ if (not self.proceed and self.flow.autoapply) or luci.http.formvalue("cbi.apply") then
+ self:_run_hooks("on_before_commit")
for i, config in ipairs(self.parsechain) do
- self.uci:save(config)
- end
- self:_run_hooks("on_after_save")
- if self:submitstate() and ((not self.proceed and self.flow.autoapply) or luci.http.formvalue("cbi.apply")) then
- self:_run_hooks("on_before_commit")
- for i, config in ipairs(self.parsechain) do
- self.uci:commit(config)
-
- -- Refresh data because commit changes section names
- self.uci:load(config)
- end
- self:_run_hooks("on_commit", "on_after_commit", "on_before_apply")
- if self.apply_on_parse then
- self.uci:apply(self.parsechain)
- self:_run_hooks("on_apply", "on_after_apply")
- else
- -- This is evaluated by the dispatcher and delegated to the
- -- template which in turn fires XHR to perform the actual
- -- apply actions.
- self.apply_needed = true
- end
-
- -- Reparse sections
- Node.parse(self, true)
+ self.uci:commit(config)
+ -- Refresh data because commit changes section names
+ self.uci:load(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())
+ self:_run_hooks("on_commit", "on_after_commit", "on_before_apply")
+ if self.apply_on_parse then
+ self.uci:apply(self.parsechain)
+ self:_run_hooks("on_apply", "on_after_apply")
+ else
+ -- This is evaluated by the dispatcher and delegated to the
+ -- template which in turn fires XHR to perform the actual
+ -- apply actions.
+ self.apply_needed = true
end
+
+ -- Reparse sections
+ Node.parse(self, true)
+ 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
- if self:submitstate() then
- if not self.save then
- self.state = FORM_INVALID
- elseif self.proceed then
- self.state = FORM_PROCEED
- else
- self.state = self.changed and FORM_CHANGED or FORM_VALID
- end
+ if self.proceed then
+ self.state = FORM_PROCEED
+ elseif self.changed then
+ self.state = FORM_CHANGED
else
- self.state = FORM_NODATA
+ self.state = FORM_VALID
end
return self:state_handler(self.state)
@@ -1470,6 +1471,7 @@ function Value.__init__(self, ...)
self.template = "cbi/value"
self.keylist = {}
self.vallist = {}
+ self.readonly = nil
end
function Value.reset_values(self)
@@ -1483,6 +1485,10 @@ function Value.value(self, key, val)
table.insert(self.vallist, tostring(val))
end
+function Value.parse(self, section, novld)
+ if self.readonly then return end
+ AbstractValue.parse(self, section, novld)
+end
-- DummyValue - This does nothing except being there
DummyValue = class(AbstractValue)
@@ -1527,17 +1533,25 @@ function Flag.__init__(self, ...)
end
-- A flag can only have two states: set or unset
-function Flag.parse(self, section)
+function Flag.parse(self, section, novld)
local fexists = self.map:formvalue(
FEXIST_PREFIX .. self.config .. "." .. section .. "." .. self.option)
if fexists then
local fvalue = self:formvalue(section) and self.enabled or self.disabled
local cvalue = self:cfgvalue(section)
- if fvalue ~= self.default or (not self.optional and not self.rmempty) then
- self:write(section, fvalue)
- else
+ local val_err
+ fvalue, val_err = self:validate(fvalue, section)
+ if not fvalue then
+ if not novld then
+ self:add_error(section, "invalid", val_err)
+ end
+ return
+ end
+ if fvalue == self.default and (self.optional or self.rmempty) then
self:remove(section)
+ else
+ self:write(section, fvalue)
end
if (fvalue ~= cvalue) then self.section.changed = true end
else
@@ -1549,7 +1563,9 @@ end
function Flag.cfgvalue(self, section)
return AbstractValue.cfgvalue(self, section) or self.default
end
-
+function Flag.validate(self, value)
+ return value
+end
--[[
ListValue - A one-line value predefined in a list
@@ -1795,6 +1811,7 @@ function Button.__init__(self, ...)
self.template = "cbi/button"
self.inputstyle = nil
self.rmempty = true
+ self.unsafeupload = false
end
@@ -1811,9 +1828,15 @@ function FileUpload.__init__(self, ...)
end
function FileUpload.formcreated(self, section)
- return AbstractValue.formcreated(self, section) or
- self.map:formvalue("cbi.rlf."..section.."."..self.option) or
- self.map:formvalue("cbi.rlf."..section.."."..self.option..".x")
+ if self.unsafeupload then
+ return AbstractValue.formcreated(self, section) or
+ self.map:formvalue("cbi.rlf."..section.."."..self.option) or
+ self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") or
+ self.map:formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
+ else
+ return AbstractValue.formcreated(self, section) or
+ self.map:formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
+ end
end
function FileUpload.cfgvalue(self, section)
@@ -1824,27 +1847,50 @@ function FileUpload.cfgvalue(self, section)
return nil
end
+-- If we have a new value, use it
+-- otherwise use old value
+-- deletion should be managed by a separate button object
+-- unless self.unsafeupload is set in which case if the user
+-- choose to remove the old file we do so.
+-- Also, allow to specify (via textbox) a file already on router
function FileUpload.formvalue(self, section)
local val = AbstractValue.formvalue(self, section)
if val then
- if not self.map:formvalue("cbi.rlf."..section.."."..self.option) and
- not self.map:formvalue("cbi.rlf."..section.."."..self.option..".x")
- then
+ if self.unsafeupload then
+ if not self.map:formvalue("cbi.rlf."..section.."."..self.option) and
+ not self.map:formvalue("cbi.rlf."..section.."."..self.option..".x")
+ then
+ return val
+ end
+ fs.unlink(val)
+ self.value = nil
+ return nil
+ elseif val ~= "" then
return val
- end
- fs.unlink(val)
- self.value = nil
+ end
end
- return nil
+ val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
+ if val == "" then
+ val = nil
+ end
+ if not self.unsafeupload then
+ if not val then
+ val = self.map:formvalue("cbi.rlf."..section.."."..self.option)
+ end
+ end
+ return val
end
function FileUpload.remove(self, section)
- local val = AbstractValue.formvalue(self, section)
- if val and fs.access(val) then fs.unlink(val) end
- return AbstractValue.remove(self, section)
+ if self.unsafeupload then
+ local val = AbstractValue.formvalue(self, section)
+ if val and fs.access(val) then fs.unlink(val) end
+ return AbstractValue.remove(self, section)
+ else
+ return nil
+ end
end
-
FileBrowser = class(AbstractValue)
function FileBrowser.__init__(self, ...)