self.config = config
self.template = "cbi/map"
self.uci = ffluci.model.uci.Session()
- self.ucidata = self.uci:sections(self.config)
- if not self.ucidata then
+ self.ucidata, self.uciorder = self.uci:sections(self.config)
+ if not self.ucidata or not self.uciorder then
error("Unable to read UCI data: " .. self.config)
end
end
+-- Use optimized UCI writing
+function Map.parse(self, ...)
+ self.uci:t_load(self.config)
+ Node.parse(self, ...)
+ self.uci:t_save(self.config)
+end
+
-- Creates a child section
function Map.section(self, class, ...)
if instanceof(class, AbstractSection) then
-- UCI add
function Map.add(self, sectiontype)
- local name = self.uci:add(self.config, sectiontype)
+ local name = self.uci:t_add(self.config, sectiontype)
if name then
self.ucidata[name] = {}
self.ucidata[name][".type"] = sectiontype
- self.ucidata[".order"] = self.ucidata[".order"] or {}
- table.insert(self.ucidata[".order"], name)
+ table.insert(self.uciorder, name)
end
return name
end
-- UCI set
function Map.set(self, section, option, value)
- local stat = self.uci:set(self.config, section, option, value)
+ local stat = self.uci:t_set(self.config, section, option, value)
if stat then
- local val = self.uci:get(self.config, section, option)
+ local val = self.uci:t_get(self.config, section, option)
if option then
self.ucidata[section][option] = val
else
self.ucidata[section] = {}
end
self.ucidata[section][".type"] = val
- self.ucidata[".order"] = self.ucidata[".order"] or {}
- table.insert(self.ucidata[".order"], section)
+ table.insert(self.uciorder, section)
end
end
return stat
-- UCI del
function Map.del(self, section, option)
- local stat = self.uci:del(self.config, section, option)
+ local stat = self.uci:t_del(self.config, section, option)
if stat then
if option then
self.ucidata[section][option] = nil
else
self.ucidata[section] = nil
- for i, k in ipairs(self.ucidata[".order"]) do
+ for i, k in ipairs(self.uciorder) do
if section == k then
- table.remove(self.ucidata[".order"], i)
+ table.remove(self.uciorder, i)
end
end
end
-- UCI get (cached)
function Map.get(self, section, option)
if not section then
- return self.ucidata
+ return self.ucidata, self.uciorder
elseif option and self.ucidata[section] then
return self.ucidata[section][option]
else
-- Return all matching UCI sections for this TypedSection
function TypedSection.cfgsections(self)
local sections = {}
+ local map, order = self.map:get()
- local map = self.map:get()
- if not map[".order"] then
- return sections
- end
-
- for i, k in pairs(map[".order"]) do
+ for i, k in ipairs(order) do
if map[k][".type"] == self.sectiontype then
if self:checkscope(k) then
table.insert(sections, k)
end
end
end
+
return sections
end
module("ffluci.model.uci.libuci", package.seeall)
+require("uci")
require("ffluci.util")
-require("ffluci.fs")
require("ffluci.sys")
--- The OS uci command
-ucicmd = "uci"
-
-- Session class
Session = ffluci.util.class()
-- Session constructor
-function Session.__init__(self, path, uci)
- uci = uci or ucicmd
- if path then
- self.ucicmd = uci .. " -P " .. path
- else
- self.ucicmd = uci
- end
+function Session.__init__(self, savedir)
+ self.ucicmd = savedir and "uci -P " .. savedir or "uci"
+ self.savedir = savedir or ffluci.model.uci.savedir
end
function Session.add(self, config, section_type)
end
function Session.commit(self, config)
- return self:_uci2("commit " .. _path(config))
+ self:t_load(config)
+ return self:t_commit(config)
end
function Session.del(self, config, section, option)
end
function Session.get(self, config, section, option)
- return self:_uci("get " .. _path(config, section, option))
+ self:t_load(config)
+ return self:t_get(config, section, option)
end
function Session.revert(self, config)
- return self:_uci2("revert " .. _path(config))
+ self:t_load(config)
+ return self:t_revert(config)
end
-function Session.sections(self, config)
- if not config then
- return nil
- end
-
- local r1, r2 = self:_uci3("show " .. _path(config))
- if type(r1) == "table" then
- return r1[config]
+function Session.sections(self, config)
+ self:t_load(config)
+ return self:t_sections(config)
+end
+
+function Session.set(self, config, section, option, value)
+ self:t_load(config)
+ return self:t_set(config, section, option, value) and self:t_save(config)
+end
+
+function Session.synchronize(self)
+ return uci.set_savedir(self.savedir)
+end
+
+
+-- UCI-Transactions
+
+function Session.t_load(self, config)
+ return self:synchronize() and uci.load(config)
+end
+
+function Session.t_save(self, config)
+ return uci.save(config)
+end
+
+function Session.t_add(self, config, type)
+ self:t_save(config)
+ local r = self:add(config, type)
+ self:t_load(config)
+ return r
+end
+
+function Session.t_commit(self, config)
+ return uci.commit(config)
+end
+
+function Session.t_del(self, config, section, option)
+ self:t_save(config)
+ local r = self:del(config, section, option)
+ self:t_load(config)
+ return r
+end
+
+function Session.t_get(self, config, section, option)
+ if option then
+ return uci.get(config, section, option)
else
- return nil, r2
+ return uci.get(config, section)
end
end
-function Session.set(self, config, section, option, value)
- return self:_uci2("set " .. _path(config, section, option, value))
+function Session.t_revert(self, config)
+ return uci.revert(config)
end
+function Session.t_sections(self, config)
+ local raw = uci.get_all(config)
+ if not raw then
+ return nil
+ end
+
+ local s = {}
+ local o = {}
+
+ for i, sec in ipairs(raw) do
+ table.insert(o, sec.name)
+
+ s[sec.name] = sec.options
+ s[sec.name][".type"] = sec.type
+ end
+
+ return s, o
+end
+function Session.t_set(self, config, section, option, value)
+ if option then
+ return uci.set(config.."."..section.."."..option.."="..value)
+ else
+ return uci.set(config.."."..section.."="..value)
+ end
+end
-- Internal functions --
end
end
-function Session._uci3(self, cmd)
- local res = ffluci.sys.execl(self.ucicmd .. " 2>&1 " .. cmd)
- if res[1] and res[1]:sub(1, self.ucicmd:len()+1) == self.ucicmd..":" then
- return nil, res[1]
- end
-
- tbl = {}
-
- for k,line in pairs(res) do
- c, s, t = line:match("^([^.]-)%.([^.]-)=(.-)$")
- if c then
- tbl[c] = tbl[c] or {}
- tbl[c][".order"] = tbl[c][".order"] or {}
-
- tbl[c][s] = {}
- table.insert(tbl[c][".order"], s)
- tbl[c][s][".type"] = t
- end
-
- c, s, o, v = line:match("^([^.]-)%.([^.]-)%.([^.]-)=(.-)$")
- if c then
- tbl[c][s][o] = v
- end
- end
-
- return tbl
-end
-
-- Build path (config.section.option=value) and prevent command injection
function _path(...)
local result = ""
local ip = ffluci.http.formvalue("ip")
local uci = ffluci.model.uci.Session()
+ -- Load UCI
+ uci:t_load("network")
+ uci:t_load("dhcp")
+ uci:t_load("freifunk")
+ uci:t_load("luci_splash")
+ uci:t_load("olsr")
+ uci:t_load("wireless")
+
+
-- Configure FF-Interface
- uci:del("network", "ff")
- uci:del("network", "ffdhcp")
+ uci:t_del("network", "ff")
+ uci:t_del("network", "ffdhcp")
- uci:set("network", "ff", nil, "interface")
- uci:set("network", "ff", "type", "bridge")
- uci:set("network", "ff", "proto", "static")
- uci:set("network", "ff", "ipaddr", ip)
- uci:set("network", "ff", "netmask", uci:get("freifunk", "community", "mask"))
- uci:set("network", "ff", "dns", uci:get("freifunk", "community", "dns"))
+ uci:t_set("network", "ff", nil, "interface")
+ uci:t_set("network", "ff", "type", "bridge")
+ uci:t_set("network", "ff", "proto", "static")
+ uci:t_set("network", "ff", "ipaddr", ip)
+ uci:t_set("network", "ff", "netmask", uci:t_get("freifunk", "community", "mask"))
+ uci:t_set("network", "ff", "dns", uci:t_get("freifunk", "community", "dns"))
-- Enable internal routing
- uci:set("freifunk", "routing", "internal", "1")
+ uci:t_set("freifunk", "routing", "internal", "1")
-- Enable internet routing
if ffluci.http.formvalue("shareinet") then
- uci:set("freifunk", "routing", "internet", "1")
+ uci:t_set("freifunk", "routing", "internet", "1")
else
- uci:set("freifunk", "routing", "internet", "0")
+ uci:t_set("freifunk", "routing", "internet", "0")
end
-- Configure DHCP
if ffluci.http.formvalue("dhcp") then
- local dhcpnet = uci:get("freifunk", "community", "dhcp"):match("^([0-9]+)")
+ local dhcpnet = uci:t_get("freifunk", "community", "dhcp"):match("^([0-9]+)")
local dhcpip = ip:gsub("^[0-9]+", dhcpnet)
- uci:set("network", "ffdhcp", nil, "interface")
- uci:set("network", "ffdhcp", "proto", "static")
- uci:set("network", "ffdhcp", "ifname", "br-ff:dhcp")
- uci:set("network", "ffdhcp", "ipaddr", dhcpip)
- uci:set("network", "ffdhcp", "netmask", uci:get("freifunk", "community", "dhcpmask"))
+ uci:t_set("network", "ffdhcp", nil, "interface")
+ uci:t_set("network", "ffdhcp", "proto", "static")
+ uci:t_set("network", "ffdhcp", "ifname", "br-ff:dhcp")
+ uci:t_set("network", "ffdhcp", "ipaddr", dhcpip)
+ uci:t_set("network", "ffdhcp", "netmask", uci:t_get("freifunk", "community", "dhcpmask"))
- local dhcp = uci:sections("dhcp")
+ local dhcp = uci:t_sections("dhcp")
if dhcp then
for k, v in pairs(dhcp) do
if v[".type"] == "dhcp" and v.interface == "ffdhcp" then
- uci:del("dhcp", k)
+ uci:t_del("dhcp", k)
end
end
local dhcpbeg = 48 + tonumber(ip:match("[0-9]+$")) * 4
- local sk = uci:add("dhcp", "dhcp")
- uci:set("dhcp", sk, "interface", "ffdhcp")
- uci:set("dhcp", sk, "start", dhcpbeg)
- uci:set("dhcp", sk, "limit", (dhcpbeg < 252) and 3 or 2)
- uci:set("dhcp", sk, "leasetime", "30m")
+ local sk = uci:t_add("dhcp", "dhcp")
+ uci:t_set("dhcp", sk, "interface", "ffdhcp")
+ uci:t_set("dhcp", sk, "start", dhcpbeg)
+ uci:t_set("dhcp", sk, "limit", (dhcpbeg < 252) and 3 or 2)
+ uci:t_set("dhcp", sk, "leasetime", "30m")
end
- local splash = uci:sections("luci_splash")
+ local splash = uci:t_sections("luci_splash")
if splash then
for k, v in pairs(splash) do
if v[".type"] == "iface" then
- uci:del("luci_splash", k)
+ uci:t_del("luci_splash", k)
end
end
- local sk = uci:add("luci_splash", "iface")
- uci:set("luci_splash", sk, "network", "ffdhcp")
+ local sk = uci:t_add("luci_splash", "iface")
+ uci:t_set("luci_splash", sk, "network", "ffdhcp")
end
end
-- Configure OLSR
- if ffluci.http.formvalue("olsr") and uci:sections("olsr") then
- for k, v in pairs(uci:sections("olsr")) do
+ if ffluci.http.formvalue("olsr") and uci:t_sections("olsr") then
+ for k, v in pairs(uci:t_sections("olsr")) do
if v[".type"] == "Interface" or v[".type"] == "LoadPlugin" then
- uci:del("olsr", k)
+ uci:t_del("olsr", k)
end
end
if ffluci.http.formvalue("shareinet") then
- uci:set("olsr", "dyn_gw", nil, "LoadPlugin")
- uci:set("olsr", "dyn_gw", "Library", "olsrd_dyn_gw.so.0.4")
+ uci:t_set("olsr", "dyn_gw", nil, "LoadPlugin")
+ uci:t_set("olsr", "dyn_gw", "Library", "olsrd_dyn_gw.so.0.4")
end
- uci:set("olsr", "nameservice", nil, "LoadPlugin")
- uci:set("olsr", "nameservice", "Library", "olsrd_nameservice.so.0.3")
- uci:set("olsr", "nameservice", "name", ip:gsub("%.", "-"))
- uci:set("olsr", "nameservice", "hosts_file", "/var/etc/hosts")
- uci:set("olsr", "nameservice", "suffix", ".olsr")
- uci:set("olsr", "nameservice", "latlon_infile", "/tmp/latlon.txt")
+ uci:t_set("olsr", "nameservice", nil, "LoadPlugin")
+ uci:t_set("olsr", "nameservice", "Library", "olsrd_nameservice.so.0.3")
+ uci:t_set("olsr", "nameservice", "name", ip:gsub("%.", "-"))
+ uci:t_set("olsr", "nameservice", "hosts_file", "/var/etc/hosts")
+ uci:t_set("olsr", "nameservice", "suffix", ".olsr")
+ uci:t_set("olsr", "nameservice", "latlon_infile", "/tmp/latlon.txt")
- uci:set("olsr", "txtinfo", nil, "LoadPlugin")
- uci:set("olsr", "txtinfo", "Library", "olsrd_txtinfo.so.0.1")
- uci:set("olsr", "txtinfo", "Accept", "127.0.0.1")
+ uci:t_set("olsr", "txtinfo", nil, "LoadPlugin")
+ uci:t_set("olsr", "txtinfo", "Library", "olsrd_txtinfo.so.0.1")
+ uci:t_set("olsr", "txtinfo", "Accept", "127.0.0.1")
- local oif = uci:add("olsr", "Interface")
- uci:set("olsr", oif, "Interface", "ff")
- uci:set("olsr", oif, "HelloInterval", "6.0")
- uci:set("olsr", oif, "HelloValidityTime", "108.0")
- uci:set("olsr", oif, "TcInterval", "4.0")
- uci:set("olsr", oif, "TcValidityTime", "324.0")
- uci:set("olsr", oif, "MidInterval", "18.0")
- uci:set("olsr", oif, "MidValidityTime", "324.0")
- uci:set("olsr", oif, "HnaInterval", "18.0")
- uci:set("olsr", oif, "HnaValidityTime", "108.0")
+ local oif = uci:t_add("olsr", "Interface")
+ uci:t_set("olsr", oif, "Interface", "ff")
+ uci:t_set("olsr", oif, "HelloInterval", "6.0")
+ uci:t_set("olsr", oif, "HelloValidityTime", "108.0")
+ uci:t_set("olsr", oif, "TcInterval", "4.0")
+ uci:t_set("olsr", oif, "TcValidityTime", "324.0")
+ uci:t_set("olsr", oif, "MidInterval", "18.0")
+ uci:t_set("olsr", oif, "MidValidityTime", "324.0")
+ uci:t_set("olsr", oif, "HnaInterval", "18.0")
+ uci:t_set("olsr", oif, "HnaValidityTime", "108.0")
end
-- Configure Wifi
- local wcfg = uci:sections("wireless")
+ local wcfg = uci:t_sections("wireless")
if wcfg then
for iface, v in pairs(wcfg) do
if v[".type"] == "wifi-device" and ffluci.http.formvalue("wifi."..iface) then
-- Cleanup
for k, j in pairs(wcfg) do
if j[".type"] == "wifi-iface" and j.device == iface then
- uci:del("wireless", k)
+ uci:t_del("wireless", k)
end
end
- uci:set("wireless", iface, "disabled", "0")
- uci:set("wireless", iface, "mode", "11g")
- uci:set("wireless", iface, "txantenna", 1)
- uci:set("wireless", iface, "rxantenna", 1)
- uci:set("wireless", iface, "channel", uci:get("freifunk", "community", "channel"))
+ uci:t_set("wireless", iface, "disabled", "0")
+ uci:t_set("wireless", iface, "mode", "11g")
+ uci:t_set("wireless", iface, "txantenna", 1)
+ uci:t_set("wireless", iface, "rxantenna", 1)
+ uci:t_set("wireless", iface, "channel", uci:t_get("freifunk", "community", "channel"))
- local wif = uci:add("wireless", "wifi-iface")
- uci:set("wireless", wif, "device", iface)
- uci:set("wireless", wif, "network", "ff")
- uci:set("wireless", wif, "mode", "adhoc")
- uci:set("wireless", wif, "ssid", uci:get("freifunk", "community", "essid"))
- uci:set("wireless", wif, "bssid", uci:get("freifunk", "community", "bssid"))
- uci:set("wireless", wif, "txpower", 13)
+ local wif = uci:t_add("wireless", "wifi-iface")
+ uci:t_set("wireless", wif, "device", iface)
+ uci:t_set("wireless", wif, "network", "ff")
+ uci:t_set("wireless", wif, "mode", "adhoc")
+ uci:t_set("wireless", wif, "ssid", uci:t_get("freifunk", "community", "essid"))
+ uci:t_set("wireless", wif, "bssid", uci:t_get("freifunk", "community", "bssid"))
+ uci:t_set("wireless", wif, "txpower", 13)
end
end
end
-
+
+ -- Save UCI
+ uci:t_save("network")
+ uci:t_save("dhcp")
+ uci:t_save("freifunk")
+ uci:t_save("luci_splash")
+ uci:t_save("olsr")
+ uci:t_save("wireless")
ffluci.http.redirect(ffluci.dispatcher.build_url("admin", "uci", "changes"))
end
\ No newline at end of file