2
0

cbi.lua 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942
  1. -- Copyright 2008 Steven Barth <steven@midlink.org>
  2. -- Licensed to the public under the Apache License 2.0.
  3. module("luci.cbi", package.seeall)
  4. require("luci.template")
  5. local util = require("luci.util")
  6. require("luci.http")
  7. --local event = require "luci.sys.event"
  8. local fs = require("nixio.fs")
  9. local uci = require("luci.model.uci")
  10. local datatypes = require("luci.cbi.datatypes")
  11. local dispatcher = require("luci.dispatcher")
  12. local class = util.class
  13. local instanceof = util.instanceof
  14. FORM_NODATA = 0
  15. FORM_PROCEED = 0
  16. FORM_VALID = 1
  17. FORM_DONE = 1
  18. FORM_INVALID = -1
  19. FORM_CHANGED = 2
  20. FORM_SKIP = 4
  21. AUTO = true
  22. CREATE_PREFIX = "cbi.cts."
  23. REMOVE_PREFIX = "cbi.rts."
  24. RESORT_PREFIX = "cbi.sts."
  25. FEXIST_PREFIX = "cbi.cbe."
  26. -- Loads a CBI map from given file, creating an environment and returns it
  27. function load(cbimap, ...)
  28. local fs = require "nixio.fs"
  29. local i18n = require "luci.i18n"
  30. require("luci.config")
  31. require("luci.util")
  32. local upldir = "/etc/luci-uploads/"
  33. local cbidir = luci.util.libpath() .. "/model/cbi/"
  34. local func, err
  35. if fs.access(cbidir..cbimap..".lua") then
  36. func, err = loadfile(cbidir..cbimap..".lua")
  37. elseif fs.access(cbimap) then
  38. func, err = loadfile(cbimap)
  39. else
  40. func, err = nil, "Model '" .. cbimap .. "' not found!"
  41. end
  42. assert(func, err)
  43. local env = {
  44. translate=i18n.translate,
  45. translatef=i18n.translatef,
  46. arg={...}
  47. }
  48. setfenv(func, setmetatable(env, {__index =
  49. function(tbl, key)
  50. return rawget(tbl, key) or _M[key] or _G[key]
  51. end}))
  52. local maps = { func() }
  53. local uploads = { }
  54. local has_upload = false
  55. for i, map in ipairs(maps) do
  56. if not instanceof(map, Node) then
  57. error("CBI map returns no valid map object!")
  58. return nil
  59. else
  60. map:prepare()
  61. if map.upload_fields then
  62. has_upload = true
  63. for _, field in ipairs(map.upload_fields) do
  64. uploads[
  65. field.config .. '.' ..
  66. (field.section.sectiontype or '1') .. '.' ..
  67. field.option
  68. ] = true
  69. end
  70. end
  71. end
  72. end
  73. if has_upload then
  74. local uci = luci.model.uci.cursor()
  75. local prm = luci.http.context.request.message.params
  76. local fd, cbid
  77. luci.http.setfilehandler(
  78. function( field, chunk, eof )
  79. if not field then return end
  80. if field.name and not cbid then
  81. local c, s, o = field.name:gmatch(
  82. "cbid%.([^%.]+)%.([^%.]+)%.([^%.]+)"
  83. )()
  84. if c and s and o then
  85. local t = uci:get( c, s ) or s
  86. if uploads[c.."."..t.."."..o] then
  87. local path = upldir .. field.name
  88. fd = io.open(path, "w")
  89. if fd then
  90. cbid = field.name
  91. prm[cbid] = path
  92. end
  93. end
  94. end
  95. end
  96. if field.name == cbid and fd then
  97. fd:write(chunk)
  98. end
  99. if eof and fd then
  100. fd:close()
  101. fd = nil
  102. cbid = nil
  103. end
  104. end
  105. )
  106. end
  107. return maps
  108. end
  109. --
  110. -- Compile a datatype specification into a parse tree for evaluation later on
  111. --
  112. local cdt_cache = { }
  113. function compile_datatype(code)
  114. local i
  115. local pos = 0
  116. local esc = false
  117. local depth = 0
  118. local stack = { }
  119. for i = 1, #code+1 do
  120. local byte = code:byte(i) or 44
  121. if esc then
  122. esc = false
  123. elseif byte == 92 then
  124. esc = true
  125. elseif byte == 40 or byte == 44 then
  126. if depth <= 0 then
  127. if pos < i then
  128. local label = code:sub(pos, i-1)
  129. :gsub("\\(.)", "%1")
  130. :gsub("^%s+", "")
  131. :gsub("%s+$", "")
  132. if #label > 0 and tonumber(label) then
  133. stack[#stack+1] = tonumber(label)
  134. elseif label:match("^'.*'$") or label:match('^".*"$') then
  135. stack[#stack+1] = label:gsub("[\"'](.*)[\"']", "%1")
  136. elseif type(datatypes[label]) == "function" then
  137. stack[#stack+1] = datatypes[label]
  138. stack[#stack+1] = { }
  139. else
  140. error("Datatype error, bad token %q" % label)
  141. end
  142. end
  143. pos = i + 1
  144. end
  145. depth = depth + (byte == 40 and 1 or 0)
  146. elseif byte == 41 then
  147. depth = depth - 1
  148. if depth <= 0 then
  149. if type(stack[#stack-1]) ~= "function" then
  150. error("Datatype error, argument list follows non-function")
  151. end
  152. stack[#stack] = compile_datatype(code:sub(pos, i-1))
  153. pos = i + 1
  154. end
  155. end
  156. end
  157. return stack
  158. end
  159. function verify_datatype(dt, value)
  160. if dt and #dt > 0 then
  161. if not cdt_cache[dt] then
  162. local c = compile_datatype(dt)
  163. if c and type(c[1]) == "function" then
  164. cdt_cache[dt] = c
  165. else
  166. error("Datatype error, not a function expression")
  167. end
  168. end
  169. if cdt_cache[dt] then
  170. return cdt_cache[dt][1](value, unpack(cdt_cache[dt][2]))
  171. end
  172. end
  173. return true
  174. end
  175. -- Node pseudo abstract class
  176. Node = class()
  177. function Node.__init__(self, title, description)
  178. self.children = {}
  179. self.title = title or ""
  180. self.description = description or ""
  181. self.template = "cbi/node"
  182. end
  183. -- hook helper
  184. function Node._run_hook(self, hook)
  185. if type(self[hook]) == "function" then
  186. return self[hook](self)
  187. end
  188. end
  189. function Node._run_hooks(self, ...)
  190. local f
  191. local r = false
  192. for _, f in ipairs(arg) do
  193. if type(self[f]) == "function" then
  194. self[f](self)
  195. r = true
  196. end
  197. end
  198. return r
  199. end
  200. -- Prepare nodes
  201. function Node.prepare(self, ...)
  202. for k, child in ipairs(self.children) do
  203. child:prepare(...)
  204. end
  205. end
  206. -- Append child nodes
  207. function Node.append(self, obj)
  208. table.insert(self.children, obj)
  209. end
  210. -- Parse this node and its children
  211. function Node.parse(self, ...)
  212. for k, child in ipairs(self.children) do
  213. child:parse(...)
  214. end
  215. end
  216. -- Render this node
  217. function Node.render(self, scope)
  218. scope = scope or {}
  219. scope.self = self
  220. luci.template.render(self.template, scope)
  221. end
  222. -- Render the children
  223. function Node.render_children(self, ...)
  224. local k, node
  225. for k, node in ipairs(self.children) do
  226. node.last_child = (k == #self.children)
  227. node.index = k
  228. node:render(...)
  229. end
  230. end
  231. --[[
  232. A simple template element
  233. ]]--
  234. Template = class(Node)
  235. function Template.__init__(self, template)
  236. Node.__init__(self)
  237. self.template = template
  238. end
  239. function Template.render(self)
  240. luci.template.render(self.template, {self=self})
  241. end
  242. function Template.parse(self, readinput)
  243. self.readinput = (readinput ~= false)
  244. return Map.formvalue(self, "cbi.submit") and FORM_DONE or FORM_NODATA
  245. end
  246. --[[
  247. Map - A map describing a configuration file
  248. ]]--
  249. Map = class(Node)
  250. function Map.__init__(self, config, ...)
  251. Node.__init__(self, ...)
  252. self.config = config
  253. self.parsechain = {self.config}
  254. self.template = "cbi/map"
  255. self.apply_on_parse = nil
  256. self.readinput = true
  257. self.proceed = false
  258. self.flow = {}
  259. self.uci = uci.cursor()
  260. self.save = true
  261. self.changed = false
  262. local path = "%s/%s" %{ self.uci:get_confdir(), self.config }
  263. if fs.stat(path, "type") ~= "reg" then
  264. fs.writefile(path, "")
  265. end
  266. local ok, err = self.uci:load(self.config)
  267. if not ok then
  268. local url = dispatcher.build_url(unpack(dispatcher.context.request))
  269. local source = self:formvalue("cbi.source")
  270. if type(source) == "string" then
  271. fs.writefile(path, source:gsub("\r\n", "\n"))
  272. ok, err = self.uci:load(self.config)
  273. if ok then
  274. luci.http.redirect(url)
  275. end
  276. end
  277. self.save = false
  278. end
  279. if not ok then
  280. self.template = "cbi/error"
  281. self.error = err
  282. self.source = fs.readfile(path) or ""
  283. self.pageaction = false
  284. end
  285. end
  286. function Map.formvalue(self, key)
  287. return self.readinput and luci.http.formvalue(key) or nil
  288. end
  289. function Map.formvaluetable(self, key)
  290. return self.readinput and luci.http.formvaluetable(key) or {}
  291. end
  292. function Map.get_scheme(self, sectiontype, option)
  293. if not option then
  294. return self.scheme and self.scheme.sections[sectiontype]
  295. else
  296. return self.scheme and self.scheme.variables[sectiontype]
  297. and self.scheme.variables[sectiontype][option]
  298. end
  299. end
  300. function Map.submitstate(self)
  301. return self:formvalue("cbi.submit")
  302. end
  303. -- Chain foreign config
  304. function Map.chain(self, config)
  305. table.insert(self.parsechain, config)
  306. end
  307. function Map.state_handler(self, state)
  308. return state
  309. end
  310. -- Use optimized UCI writing
  311. function Map.parse(self, readinput, ...)
  312. if self:formvalue("cbi.skip") then
  313. self.state = FORM_SKIP
  314. elseif not self.save then
  315. self.state = FORM_INVALID
  316. elseif not self:submitstate() then
  317. self.state = FORM_NODATA
  318. end
  319. -- Back out early to prevent unauthorized changes on the subsequent parse
  320. if self.state ~= nil then
  321. return self:state_handler(self.state)
  322. end
  323. self.readinput = (readinput ~= false)
  324. self:_run_hooks("on_parse")
  325. Node.parse(self, ...)
  326. if self.save then
  327. self:_run_hooks("on_save", "on_before_save")
  328. for i, config in ipairs(self.parsechain) do
  329. self.uci:save(config)
  330. end
  331. self:_run_hooks("on_after_save")
  332. if (not self.proceed and self.flow.autoapply) or luci.http.formvalue("cbi.apply") then
  333. self:_run_hooks("on_before_commit")
  334. for i, config in ipairs(self.parsechain) do
  335. self.uci:commit(config)
  336. -- Refresh data because commit changes section names
  337. self.uci:load(config)
  338. end
  339. self:_run_hooks("on_commit", "on_after_commit", "on_before_apply")
  340. if self.apply_on_parse then
  341. self.uci:apply(self.parsechain)
  342. self:_run_hooks("on_apply", "on_after_apply")
  343. else
  344. -- This is evaluated by the dispatcher and delegated to the
  345. -- template which in turn fires XHR to perform the actual
  346. -- apply actions.
  347. self.apply_needed = true
  348. end
  349. -- Reparse sections
  350. Node.parse(self, true)
  351. end
  352. for i, config in ipairs(self.parsechain) do
  353. self.uci:unload(config)
  354. end
  355. if type(self.commit_handler) == "function" then
  356. self:commit_handler(self:submitstate())
  357. end
  358. end
  359. if not self.save then
  360. self.state = FORM_INVALID
  361. elseif self.proceed then
  362. self.state = FORM_PROCEED
  363. elseif self.changed then
  364. self.state = FORM_CHANGED
  365. else
  366. self.state = FORM_VALID
  367. end
  368. return self:state_handler(self.state)
  369. end
  370. function Map.render(self, ...)
  371. self:_run_hooks("on_init")
  372. Node.render(self, ...)
  373. end
  374. -- Creates a child section
  375. function Map.section(self, class, ...)
  376. if instanceof(class, AbstractSection) then
  377. local obj = class(self, ...)
  378. self:append(obj)
  379. return obj
  380. else
  381. error("class must be a descendent of AbstractSection")
  382. end
  383. end
  384. -- UCI add
  385. function Map.add(self, sectiontype)
  386. return self.uci:add(self.config, sectiontype)
  387. end
  388. -- UCI set
  389. function Map.set(self, section, option, value)
  390. if type(value) ~= "table" or #value > 0 then
  391. if option then
  392. return self.uci:set(self.config, section, option, value)
  393. else
  394. return self.uci:set(self.config, section, value)
  395. end
  396. else
  397. return Map.del(self, section, option)
  398. end
  399. end
  400. -- UCI del
  401. function Map.del(self, section, option)
  402. if option then
  403. return self.uci:delete(self.config, section, option)
  404. else
  405. return self.uci:delete(self.config, section)
  406. end
  407. end
  408. -- UCI get
  409. function Map.get(self, section, option)
  410. if not section then
  411. return self.uci:get_all(self.config)
  412. elseif option then
  413. return self.uci:get(self.config, section, option)
  414. else
  415. return self.uci:get_all(self.config, section)
  416. end
  417. end
  418. --[[
  419. Compound - Container
  420. ]]--
  421. Compound = class(Node)
  422. function Compound.__init__(self, ...)
  423. Node.__init__(self)
  424. self.template = "cbi/compound"
  425. self.children = {...}
  426. end
  427. function Compound.populate_delegator(self, delegator)
  428. for _, v in ipairs(self.children) do
  429. v.delegator = delegator
  430. end
  431. end
  432. function Compound.parse(self, ...)
  433. local cstate, state = 0
  434. for k, child in ipairs(self.children) do
  435. cstate = child:parse(...)
  436. state = (not state or cstate < state) and cstate or state
  437. end
  438. return state
  439. end
  440. --[[
  441. Delegator - Node controller
  442. ]]--
  443. Delegator = class(Node)
  444. function Delegator.__init__(self, ...)
  445. Node.__init__(self, ...)
  446. self.nodes = {}
  447. self.defaultpath = {}
  448. self.pageaction = false
  449. self.readinput = true
  450. self.allow_reset = false
  451. self.allow_cancel = false
  452. self.allow_back = false
  453. self.allow_finish = false
  454. self.template = "cbi/delegator"
  455. end
  456. function Delegator.set(self, name, node)
  457. assert(not self.nodes[name], "Duplicate entry")
  458. self.nodes[name] = node
  459. end
  460. function Delegator.add(self, name, node)
  461. node = self:set(name, node)
  462. self.defaultpath[#self.defaultpath+1] = name
  463. end
  464. function Delegator.insert_after(self, name, after)
  465. local n = #self.chain + 1
  466. for k, v in ipairs(self.chain) do
  467. if v == after then
  468. n = k + 1
  469. break
  470. end
  471. end
  472. table.insert(self.chain, n, name)
  473. end
  474. function Delegator.set_route(self, ...)
  475. local n, chain, route = 0, self.chain, {...}
  476. for i = 1, #chain do
  477. if chain[i] == self.current then
  478. n = i
  479. break
  480. end
  481. end
  482. for i = 1, #route do
  483. n = n + 1
  484. chain[n] = route[i]
  485. end
  486. for i = n + 1, #chain do
  487. chain[i] = nil
  488. end
  489. end
  490. function Delegator.get(self, name)
  491. local node = self.nodes[name]
  492. if type(node) == "string" then
  493. node = load(node, name)
  494. end
  495. if type(node) == "table" and getmetatable(node) == nil then
  496. node = Compound(unpack(node))
  497. end
  498. return node
  499. end
  500. function Delegator.parse(self, ...)
  501. if self.allow_cancel and Map.formvalue(self, "cbi.cancel") then
  502. if self:_run_hooks("on_cancel") then
  503. return FORM_DONE
  504. end
  505. end
  506. if not Map.formvalue(self, "cbi.delg.current") then
  507. self:_run_hooks("on_init")
  508. end
  509. local newcurrent
  510. self.chain = self.chain or self:get_chain()
  511. self.current = self.current or self:get_active()
  512. self.active = self.active or self:get(self.current)
  513. assert(self.active, "Invalid state")
  514. local stat = FORM_DONE
  515. if type(self.active) ~= "function" then
  516. self.active:populate_delegator(self)
  517. stat = self.active:parse()
  518. else
  519. self:active()
  520. end
  521. if stat > FORM_PROCEED then
  522. if Map.formvalue(self, "cbi.delg.back") then
  523. newcurrent = self:get_prev(self.current)
  524. else
  525. newcurrent = self:get_next(self.current)
  526. end
  527. elseif stat < FORM_PROCEED then
  528. return stat
  529. end
  530. if not Map.formvalue(self, "cbi.submit") then
  531. return FORM_NODATA
  532. elseif stat > FORM_PROCEED
  533. and (not newcurrent or not self:get(newcurrent)) then
  534. return self:_run_hook("on_done") or FORM_DONE
  535. else
  536. self.current = newcurrent or self.current
  537. self.active = self:get(self.current)
  538. if type(self.active) ~= "function" then
  539. self.active:populate_delegator(self)
  540. local stat = self.active:parse(false)
  541. if stat == FORM_SKIP then
  542. return self:parse(...)
  543. else
  544. return FORM_PROCEED
  545. end
  546. else
  547. return self:parse(...)
  548. end
  549. end
  550. end
  551. function Delegator.get_next(self, state)
  552. for k, v in ipairs(self.chain) do
  553. if v == state then
  554. return self.chain[k+1]
  555. end
  556. end
  557. end
  558. function Delegator.get_prev(self, state)
  559. for k, v in ipairs(self.chain) do
  560. if v == state then
  561. return self.chain[k-1]
  562. end
  563. end
  564. end
  565. function Delegator.get_chain(self)
  566. local x = Map.formvalue(self, "cbi.delg.path") or self.defaultpath
  567. return type(x) == "table" and x or {x}
  568. end
  569. function Delegator.get_active(self)
  570. return Map.formvalue(self, "cbi.delg.current") or self.chain[1]
  571. end
  572. --[[
  573. Page - A simple node
  574. ]]--
  575. Page = class(Node)
  576. Page.__init__ = Node.__init__
  577. Page.parse = function() end
  578. --[[
  579. SimpleForm - A Simple non-UCI form
  580. ]]--
  581. SimpleForm = class(Node)
  582. function SimpleForm.__init__(self, config, title, description, data)
  583. Node.__init__(self, title, description)
  584. self.config = config
  585. self.data = data or {}
  586. self.template = "cbi/simpleform"
  587. self.dorender = true
  588. self.pageaction = false
  589. self.readinput = true
  590. end
  591. SimpleForm.formvalue = Map.formvalue
  592. SimpleForm.formvaluetable = Map.formvaluetable
  593. function SimpleForm.parse(self, readinput, ...)
  594. self.readinput = (readinput ~= false)
  595. if self:formvalue("cbi.skip") then
  596. return FORM_SKIP
  597. end
  598. if self:formvalue("cbi.cancel") and self:_run_hooks("on_cancel") then
  599. return FORM_DONE
  600. end
  601. if self:submitstate() then
  602. Node.parse(self, 1, ...)
  603. end
  604. local valid = true
  605. for k, j in ipairs(self.children) do
  606. for i, v in ipairs(j.children) do
  607. valid = valid
  608. and (not v.tag_missing or not v.tag_missing[1])
  609. and (not v.tag_invalid or not v.tag_invalid[1])
  610. and (not v.error)
  611. end
  612. end
  613. local state =
  614. not self:submitstate() and FORM_NODATA
  615. or valid and FORM_VALID
  616. or FORM_INVALID
  617. self.dorender = not self.handle
  618. if self.handle then
  619. local nrender, nstate = self:handle(state, self.data)
  620. self.dorender = self.dorender or (nrender ~= false)
  621. state = nstate or state
  622. end
  623. return state
  624. end
  625. function SimpleForm.render(self, ...)
  626. if self.dorender then
  627. Node.render(self, ...)
  628. end
  629. end
  630. function SimpleForm.submitstate(self)
  631. return self:formvalue("cbi.submit")
  632. end
  633. function SimpleForm.section(self, class, ...)
  634. if instanceof(class, AbstractSection) then
  635. local obj = class(self, ...)
  636. self:append(obj)
  637. return obj
  638. else
  639. error("class must be a descendent of AbstractSection")
  640. end
  641. end
  642. -- Creates a child field
  643. function SimpleForm.field(self, class, ...)
  644. local section
  645. for k, v in ipairs(self.children) do
  646. if instanceof(v, SimpleSection) then
  647. section = v
  648. break
  649. end
  650. end
  651. if not section then
  652. section = self:section(SimpleSection)
  653. end
  654. if instanceof(class, AbstractValue) then
  655. local obj = class(self, section, ...)
  656. obj.track_missing = true
  657. section:append(obj)
  658. return obj
  659. else
  660. error("class must be a descendent of AbstractValue")
  661. end
  662. end
  663. function SimpleForm.set(self, section, option, value)
  664. self.data[option] = value
  665. end
  666. function SimpleForm.del(self, section, option)
  667. self.data[option] = nil
  668. end
  669. function SimpleForm.get(self, section, option)
  670. return self.data[option]
  671. end
  672. function SimpleForm.get_scheme()
  673. return nil
  674. end
  675. Form = class(SimpleForm)
  676. function Form.__init__(self, ...)
  677. SimpleForm.__init__(self, ...)
  678. self.embedded = true
  679. end
  680. --[[
  681. AbstractSection
  682. ]]--
  683. AbstractSection = class(Node)
  684. function AbstractSection.__init__(self, map, sectiontype, ...)
  685. Node.__init__(self, ...)
  686. self.sectiontype = sectiontype
  687. self.map = map
  688. self.config = map.config
  689. self.optionals = {}
  690. self.defaults = {}
  691. self.fields = {}
  692. self.tag_error = {}
  693. self.tag_invalid = {}
  694. self.tag_deperror = {}
  695. self.changed = false
  696. self.optional = true
  697. self.addremove = false
  698. self.dynamic = false
  699. end
  700. -- Define a tab for the section
  701. function AbstractSection.tab(self, tab, title, desc)
  702. self.tabs = self.tabs or { }
  703. self.tab_names = self.tab_names or { }
  704. self.tab_names[#self.tab_names+1] = tab
  705. self.tabs[tab] = {
  706. title = title,
  707. description = desc,
  708. childs = { }
  709. }
  710. end
  711. -- Check whether the section has tabs
  712. function AbstractSection.has_tabs(self)
  713. return (self.tabs ~= nil) and (next(self.tabs) ~= nil)
  714. end
  715. -- Appends a new option
  716. function AbstractSection.option(self, class, option, ...)
  717. if instanceof(class, AbstractValue) then
  718. local obj = class(self.map, self, option, ...)
  719. self:append(obj)
  720. self.fields[option] = obj
  721. return obj
  722. elseif class == true then
  723. error("No valid class was given and autodetection failed.")
  724. else
  725. error("class must be a descendant of AbstractValue")
  726. end
  727. end
  728. -- Appends a new tabbed option
  729. function AbstractSection.taboption(self, tab, ...)
  730. assert(tab and self.tabs and self.tabs[tab],
  731. "Cannot assign option to not existing tab %q" % tostring(tab))
  732. local l = self.tabs[tab].childs
  733. local o = AbstractSection.option(self, ...)
  734. if o then l[#l+1] = o end
  735. return o
  736. end
  737. -- Render a single tab
  738. function AbstractSection.render_tab(self, tab, ...)
  739. assert(tab and self.tabs and self.tabs[tab],
  740. "Cannot render not existing tab %q" % tostring(tab))
  741. local k, node
  742. for k, node in ipairs(self.tabs[tab].childs) do
  743. node.last_child = (k == #self.tabs[tab].childs)
  744. node.index = k
  745. node:render(...)
  746. end
  747. end
  748. -- Parse optional options
  749. function AbstractSection.parse_optionals(self, section, noparse)
  750. if not self.optional then
  751. return
  752. end
  753. self.optionals[section] = {}
  754. local field = nil
  755. if not noparse then
  756. field = self.map:formvalue("cbi.opt."..self.config.."."..section)
  757. end
  758. for k,v in ipairs(self.children) do
  759. if v.optional and not v:cfgvalue(section) and not self:has_tabs() then
  760. if field == v.option then
  761. field = nil
  762. self.map.proceed = true
  763. else
  764. table.insert(self.optionals[section], v)
  765. end
  766. end
  767. end
  768. if field and #field > 0 and self.dynamic then
  769. self:add_dynamic(field)
  770. end
  771. end
  772. -- Add a dynamic option
  773. function AbstractSection.add_dynamic(self, field, optional)
  774. local o = self:option(Value, field, field)
  775. o.optional = optional
  776. end
  777. -- Parse all dynamic options
  778. function AbstractSection.parse_dynamic(self, section)
  779. if not self.dynamic then
  780. return
  781. end
  782. local arr = luci.util.clone(self:cfgvalue(section))
  783. local form = self.map:formvaluetable("cbid."..self.config.."."..section)
  784. for k, v in pairs(form) do
  785. arr[k] = v
  786. end
  787. for key,val in pairs(arr) do
  788. local create = true
  789. for i,c in ipairs(self.children) do
  790. if c.option == key then
  791. create = false
  792. end
  793. end
  794. if create and key:sub(1, 1) ~= "." then
  795. self.map.proceed = true
  796. self:add_dynamic(key, true)
  797. end
  798. end
  799. end
  800. -- Returns the section's UCI table
  801. function AbstractSection.cfgvalue(self, section)
  802. return self.map:get(section)
  803. end
  804. -- Push events
  805. function AbstractSection.push_events(self)
  806. --luci.util.append(self.map.events, self.events)
  807. self.map.changed = true
  808. end
  809. -- Removes the section
  810. function AbstractSection.remove(self, section)
  811. self.map.proceed = true
  812. return self.map:del(section)
  813. end
  814. -- Creates the section
  815. function AbstractSection.create(self, section)
  816. local stat
  817. if section then
  818. stat = section:match("^[%w_]+$") and self.map:set(section, nil, self.sectiontype)
  819. else
  820. section = self.map:add(self.sectiontype)
  821. stat = section
  822. end
  823. if stat then
  824. for k,v in pairs(self.children) do
  825. if v.default then
  826. self.map:set(section, v.option, v.default)
  827. end
  828. end
  829. for k,v in pairs(self.defaults) do
  830. self.map:set(section, k, v)
  831. end
  832. end
  833. self.map.proceed = true
  834. return stat
  835. end
  836. SimpleSection = class(AbstractSection)
  837. function SimpleSection.__init__(self, form, ...)
  838. AbstractSection.__init__(self, form, nil, ...)
  839. self.template = "cbi/nullsection"
  840. end
  841. Table = class(AbstractSection)
  842. function Table.__init__(self, form, data, ...)
  843. local datasource = {}
  844. local tself = self
  845. datasource.config = "table"
  846. self.data = data or {}
  847. datasource.formvalue = Map.formvalue
  848. datasource.formvaluetable = Map.formvaluetable
  849. datasource.readinput = true
  850. function datasource.get(self, section, option)
  851. return tself.data[section] and tself.data[section][option]
  852. end
  853. function datasource.submitstate(self)
  854. return Map.formvalue(self, "cbi.submit")
  855. end
  856. function datasource.del(...)
  857. return true
  858. end
  859. function datasource.get_scheme()
  860. return nil
  861. end
  862. AbstractSection.__init__(self, datasource, "table", ...)
  863. self.template = "cbi/tblsection"
  864. self.rowcolors = true
  865. self.anonymous = true
  866. end
  867. function Table.parse(self, readinput)
  868. self.map.readinput = (readinput ~= false)
  869. for i, k in ipairs(self:cfgsections()) do
  870. if self.map:submitstate() then
  871. Node.parse(self, k)
  872. end
  873. end
  874. end
  875. function Table.cfgsections(self)
  876. local sections = {}
  877. for i, v in luci.util.kspairs(self.data) do
  878. table.insert(sections, i)
  879. end
  880. return sections
  881. end
  882. function Table.update(self, data)
  883. self.data = data
  884. end
  885. --[[
  886. NamedSection - A fixed configuration section defined by its name
  887. ]]--
  888. NamedSection = class(AbstractSection)
  889. function NamedSection.__init__(self, map, section, stype, ...)
  890. AbstractSection.__init__(self, map, stype, ...)
  891. -- Defaults
  892. self.addremove = false
  893. self.template = "cbi/nsection"
  894. self.section = section
  895. end
  896. function NamedSection.prepare(self)
  897. AbstractSection.prepare(self)
  898. AbstractSection.parse_optionals(self, self.section, true)
  899. end
  900. function NamedSection.parse(self, novld)
  901. local s = self.section
  902. local active = self:cfgvalue(s)
  903. if self.addremove then
  904. local path = self.config.."."..s
  905. if active then -- Remove the section
  906. if self.map:formvalue("cbi.rns."..path) and self:remove(s) then
  907. self:push_events()
  908. return
  909. end
  910. else -- Create and apply default values
  911. if self.map:formvalue("cbi.cns."..path) then
  912. self:create(s)
  913. return
  914. end
  915. end
  916. end
  917. if active then
  918. AbstractSection.parse_dynamic(self, s)
  919. if self.map:submitstate() then
  920. Node.parse(self, s)
  921. end
  922. AbstractSection.parse_optionals(self, s)
  923. if self.changed then
  924. self:push_events()
  925. end
  926. end
  927. end
  928. --[[
  929. TypedSection - A (set of) configuration section(s) defined by the type
  930. addremove: Defines whether the user can add/remove sections of this type
  931. anonymous: Allow creating anonymous sections
  932. validate: a validation function returning nil if the section is invalid
  933. ]]--
  934. TypedSection = class(AbstractSection)
  935. function TypedSection.__init__(self, map, type, ...)
  936. AbstractSection.__init__(self, map, type, ...)
  937. self.template = "cbi/tsection"
  938. self.deps = {}
  939. self.anonymous = false
  940. end
  941. function TypedSection.prepare(self)
  942. AbstractSection.prepare(self)
  943. local i, s
  944. for i, s in ipairs(self:cfgsections()) do
  945. AbstractSection.parse_optionals(self, s, true)
  946. end
  947. end
  948. -- Return all matching UCI sections for this TypedSection
  949. function TypedSection.cfgsections(self)
  950. local sections = {}
  951. self.map.uci:foreach(self.map.config, self.sectiontype,
  952. function (section)
  953. if self:checkscope(section[".name"]) then
  954. table.insert(sections, section[".name"])
  955. end
  956. end)
  957. return sections
  958. end
  959. -- Limits scope to sections that have certain option => value pairs
  960. function TypedSection.depends(self, option, value)
  961. table.insert(self.deps, {option=option, value=value})
  962. end
  963. function TypedSection.parse(self, novld)
  964. if self.addremove then
  965. -- Remove
  966. local crval = REMOVE_PREFIX .. self.config
  967. local name = self.map:formvaluetable(crval)
  968. for k,v in pairs(name) do
  969. if k:sub(-2) == ".x" then
  970. k = k:sub(1, #k - 2)
  971. end
  972. if self:cfgvalue(k) and self:checkscope(k) then
  973. self:remove(k)
  974. end
  975. end
  976. end
  977. local co
  978. for i, k in ipairs(self:cfgsections()) do
  979. AbstractSection.parse_dynamic(self, k)
  980. if self.map:submitstate() then
  981. Node.parse(self, k, novld)
  982. end
  983. AbstractSection.parse_optionals(self, k)
  984. end
  985. if self.addremove then
  986. -- Create
  987. local created
  988. local crval = CREATE_PREFIX .. self.config .. "." .. self.sectiontype
  989. local origin, name = next(self.map:formvaluetable(crval))
  990. if self.anonymous then
  991. if name then
  992. created = self:create(nil, origin)
  993. end
  994. else
  995. if name then
  996. -- Ignore if it already exists
  997. if self:cfgvalue(name) then
  998. name = nil;
  999. end
  1000. name = self:checkscope(name)
  1001. if not name then
  1002. self.err_invalid = true
  1003. end
  1004. if name and #name > 0 then
  1005. created = self:create(name, origin) and name
  1006. if not created then
  1007. self.invalid_cts = true
  1008. end
  1009. end
  1010. end
  1011. end
  1012. if created then
  1013. AbstractSection.parse_optionals(self, created)
  1014. end
  1015. end
  1016. if self.sortable then
  1017. local stval = RESORT_PREFIX .. self.config .. "." .. self.sectiontype
  1018. local order = self.map:formvalue(stval)
  1019. if order and #order > 0 then
  1020. local sid
  1021. local num = 0
  1022. for sid in util.imatch(order) do
  1023. self.map.uci:reorder(self.config, sid, num)
  1024. num = num + 1
  1025. end
  1026. self.changed = (num > 0)
  1027. end
  1028. end
  1029. if created or self.changed then
  1030. self:push_events()
  1031. end
  1032. end
  1033. -- Verifies scope of sections
  1034. function TypedSection.checkscope(self, section)
  1035. -- Check if we are not excluded
  1036. if self.filter and not self:filter(section) then
  1037. return nil
  1038. end
  1039. -- Check if at least one dependency is met
  1040. if #self.deps > 0 and self:cfgvalue(section) then
  1041. local stat = false
  1042. for k, v in ipairs(self.deps) do
  1043. if self:cfgvalue(section)[v.option] == v.value then
  1044. stat = true
  1045. end
  1046. end
  1047. if not stat then
  1048. return nil
  1049. end
  1050. end
  1051. return self:validate(section)
  1052. end
  1053. -- Dummy validate function
  1054. function TypedSection.validate(self, section)
  1055. return section
  1056. end
  1057. --[[
  1058. AbstractValue - An abstract Value Type
  1059. null: Value can be empty
  1060. valid: A function returning the value if it is valid otherwise nil
  1061. depends: A table of option => value pairs of which one must be true
  1062. default: The default value
  1063. size: The size of the input fields
  1064. rmempty: Unset value if empty
  1065. optional: This value is optional (see AbstractSection.optionals)
  1066. ]]--
  1067. AbstractValue = class(Node)
  1068. function AbstractValue.__init__(self, map, section, option, ...)
  1069. Node.__init__(self, ...)
  1070. self.section = section
  1071. self.option = option
  1072. self.map = map
  1073. self.config = map.config
  1074. self.tag_invalid = {}
  1075. self.tag_missing = {}
  1076. self.tag_reqerror = {}
  1077. self.tag_error = {}
  1078. self.deps = {}
  1079. --self.cast = "string"
  1080. self.track_missing = false
  1081. self.rmempty = true
  1082. self.default = nil
  1083. self.size = nil
  1084. self.optional = false
  1085. end
  1086. function AbstractValue.prepare(self)
  1087. self.cast = self.cast or "string"
  1088. end
  1089. -- Add a dependencie to another section field
  1090. function AbstractValue.depends(self, field, value)
  1091. local deps
  1092. if type(field) == "string" then
  1093. deps = {}
  1094. deps[field] = value
  1095. else
  1096. deps = field
  1097. end
  1098. table.insert(self.deps, deps)
  1099. end
  1100. -- Serialize dependencies
  1101. function AbstractValue.deplist2json(self, section, deplist)
  1102. local deps, i, d = { }
  1103. if type(self.deps) == "table" then
  1104. for i, d in ipairs(deplist or self.deps) do
  1105. local a, k, v = { }
  1106. for k, v in pairs(d) do
  1107. if k:find("!", 1, true) then
  1108. a[k] = v
  1109. elseif k:find(".", 1, true) then
  1110. a['cbid.%s' % k] = v
  1111. else
  1112. a['cbid.%s.%s.%s' %{ self.config, section, k }] = v
  1113. end
  1114. end
  1115. deps[#deps+1] = a
  1116. end
  1117. end
  1118. return util.serialize_json(deps)
  1119. end
  1120. -- Generates the unique CBID
  1121. function AbstractValue.cbid(self, section)
  1122. return "cbid."..self.map.config.."."..section.."."..self.option
  1123. end
  1124. -- Return whether this object should be created
  1125. function AbstractValue.formcreated(self, section)
  1126. local key = "cbi.opt."..self.config.."."..section
  1127. return (self.map:formvalue(key) == self.option)
  1128. end
  1129. -- Returns the formvalue for this object
  1130. function AbstractValue.formvalue(self, section)
  1131. return self.map:formvalue(self:cbid(section))
  1132. end
  1133. function AbstractValue.additional(self, value)
  1134. self.optional = value
  1135. end
  1136. function AbstractValue.mandatory(self, value)
  1137. self.rmempty = not value
  1138. end
  1139. function AbstractValue.add_error(self, section, type, msg)
  1140. self.error = self.error or { }
  1141. self.error[section] = msg or type
  1142. self.section.error = self.section.error or { }
  1143. self.section.error[section] = self.section.error[section] or { }
  1144. table.insert(self.section.error[section], msg or type)
  1145. if type == "invalid" then
  1146. self.tag_invalid[section] = true
  1147. elseif type == "missing" then
  1148. self.tag_missing[section] = true
  1149. end
  1150. self.tag_error[section] = true
  1151. self.map.save = false
  1152. end
  1153. function AbstractValue.parse(self, section, novld)
  1154. local fvalue = self:formvalue(section)
  1155. local cvalue = self:cfgvalue(section)
  1156. -- If favlue and cvalue are both tables and have the same content
  1157. -- make them identical
  1158. if type(fvalue) == "table" and type(cvalue) == "table" then
  1159. local equal = #fvalue == #cvalue
  1160. if equal then
  1161. for i=1, #fvalue do
  1162. if cvalue[i] ~= fvalue[i] then
  1163. equal = false
  1164. end
  1165. end
  1166. end
  1167. if equal then
  1168. fvalue = cvalue
  1169. end
  1170. end
  1171. if fvalue and #fvalue > 0 then -- If we have a form value, write it to UCI
  1172. local val_err
  1173. fvalue, val_err = self:validate(fvalue, section)
  1174. fvalue = self:transform(fvalue)
  1175. if not fvalue and not novld then
  1176. self:add_error(section, "invalid", val_err)
  1177. end
  1178. if fvalue and (self.forcewrite or not (fvalue == cvalue)) then
  1179. if self:write(section, fvalue) then
  1180. -- Push events
  1181. self.section.changed = true
  1182. --luci.util.append(self.map.events, self.events)
  1183. end
  1184. end
  1185. else -- Unset the UCI or error
  1186. if self.rmempty or self.optional then
  1187. if self:remove(section) then
  1188. -- Push events
  1189. self.section.changed = true
  1190. --luci.util.append(self.map.events, self.events)
  1191. end
  1192. elseif cvalue ~= fvalue and not novld then
  1193. -- trigger validator with nil value to get custom user error msg.
  1194. local _, val_err = self:validate(nil, section)
  1195. self:add_error(section, "missing", val_err)
  1196. end
  1197. end
  1198. end
  1199. -- Render if this value exists or if it is mandatory
  1200. function AbstractValue.render(self, s, scope)
  1201. if not self.optional or self.section:has_tabs() or self:cfgvalue(s) or self:formcreated(s) then
  1202. scope = scope or {}
  1203. scope.section = s
  1204. scope.cbid = self:cbid(s)
  1205. Node.render(self, scope)
  1206. end
  1207. end
  1208. -- Return the UCI value of this object
  1209. function AbstractValue.cfgvalue(self, section)
  1210. local value
  1211. if self.tag_error[section] then
  1212. value = self:formvalue(section)
  1213. else
  1214. value = self.map:get(section, self.option)
  1215. end
  1216. if not value then
  1217. return nil
  1218. elseif not self.cast or self.cast == type(value) then
  1219. return value
  1220. elseif self.cast == "string" then
  1221. if type(value) == "table" then
  1222. return value[1]
  1223. end
  1224. elseif self.cast == "table" then
  1225. return { value }
  1226. end
  1227. end
  1228. -- Validate the form value
  1229. function AbstractValue.validate(self, value)
  1230. if self.datatype and value then
  1231. if type(value) == "table" then
  1232. local v
  1233. for _, v in ipairs(value) do
  1234. if v and #v > 0 and not verify_datatype(self.datatype, v) then
  1235. return nil
  1236. end
  1237. end
  1238. else
  1239. if not verify_datatype(self.datatype, value) then
  1240. return nil
  1241. end
  1242. end
  1243. end
  1244. return value
  1245. end
  1246. AbstractValue.transform = AbstractValue.validate
  1247. -- Write to UCI
  1248. function AbstractValue.write(self, section, value)
  1249. return self.map:set(section, self.option, value)
  1250. end
  1251. -- Remove from UCI
  1252. function AbstractValue.remove(self, section)
  1253. return self.map:del(section, self.option)
  1254. end
  1255. --[[
  1256. Value - A one-line value
  1257. maxlength: The maximum length
  1258. ]]--
  1259. Value = class(AbstractValue)
  1260. function Value.__init__(self, ...)
  1261. AbstractValue.__init__(self, ...)
  1262. self.template = "cbi/value"
  1263. self.keylist = {}
  1264. self.vallist = {}
  1265. self.readonly = nil
  1266. end
  1267. function Value.reset_values(self)
  1268. self.keylist = {}
  1269. self.vallist = {}
  1270. end
  1271. function Value.value(self, key, val)
  1272. val = val or key
  1273. table.insert(self.keylist, tostring(key))
  1274. table.insert(self.vallist, tostring(val))
  1275. end
  1276. function Value.parse(self, section, novld)
  1277. if self.readonly then return end
  1278. AbstractValue.parse(self, section, novld)
  1279. end
  1280. -- DummyValue - This does nothing except being there
  1281. DummyValue = class(AbstractValue)
  1282. function DummyValue.__init__(self, ...)
  1283. AbstractValue.__init__(self, ...)
  1284. self.template = "cbi/dvalue"
  1285. self.value = nil
  1286. end
  1287. function DummyValue.cfgvalue(self, section)
  1288. local value
  1289. if self.value then
  1290. if type(self.value) == "function" then
  1291. value = self:value(section)
  1292. else
  1293. value = self.value
  1294. end
  1295. else
  1296. value = AbstractValue.cfgvalue(self, section)
  1297. end
  1298. return value
  1299. end
  1300. function DummyValue.parse(self)
  1301. end
  1302. --[[
  1303. Flag - A flag being enabled or disabled
  1304. ]]--
  1305. Flag = class(AbstractValue)
  1306. function Flag.__init__(self, ...)
  1307. AbstractValue.__init__(self, ...)
  1308. self.template = "cbi/fvalue"
  1309. self.enabled = "1"
  1310. self.disabled = "0"
  1311. self.default = self.disabled
  1312. end
  1313. -- A flag can only have two states: set or unset
  1314. function Flag.parse(self, section, novld)
  1315. local fexists = self.map:formvalue(
  1316. FEXIST_PREFIX .. self.config .. "." .. section .. "." .. self.option)
  1317. if fexists then
  1318. local fvalue = self:formvalue(section) and self.enabled or self.disabled
  1319. local cvalue = self:cfgvalue(section)
  1320. local val_err
  1321. fvalue, val_err = self:validate(fvalue, section)
  1322. if not fvalue then
  1323. if not novld then
  1324. self:add_error(section, "invalid", val_err)
  1325. end
  1326. return
  1327. end
  1328. if fvalue == self.default and (self.optional or self.rmempty) then
  1329. self:remove(section)
  1330. else
  1331. self:write(section, fvalue)
  1332. end
  1333. if (fvalue ~= cvalue) then self.section.changed = true end
  1334. else
  1335. self:remove(section)
  1336. self.section.changed = true
  1337. end
  1338. end
  1339. function Flag.cfgvalue(self, section)
  1340. return AbstractValue.cfgvalue(self, section) or self.default
  1341. end
  1342. function Flag.validate(self, value)
  1343. return value
  1344. end
  1345. --[[
  1346. ListValue - A one-line value predefined in a list
  1347. widget: The widget that will be used (select, radio)
  1348. ]]--
  1349. ListValue = class(AbstractValue)
  1350. function ListValue.__init__(self, ...)
  1351. AbstractValue.__init__(self, ...)
  1352. self.template = "cbi/lvalue"
  1353. self.size = 1
  1354. self.widget = "select"
  1355. self:reset_values()
  1356. end
  1357. function ListValue.reset_values(self)
  1358. self.keylist = {}
  1359. self.vallist = {}
  1360. self.deplist = {}
  1361. end
  1362. function ListValue.value(self, key, val, ...)
  1363. if luci.util.contains(self.keylist, key) then
  1364. return
  1365. end
  1366. val = val or key
  1367. table.insert(self.keylist, tostring(key))
  1368. table.insert(self.vallist, tostring(val))
  1369. table.insert(self.deplist, {...})
  1370. end
  1371. function ListValue.validate(self, val)
  1372. if luci.util.contains(self.keylist, val) then
  1373. return val
  1374. else
  1375. return nil
  1376. end
  1377. end
  1378. --[[
  1379. MultiValue - Multiple delimited values
  1380. widget: The widget that will be used (select, checkbox)
  1381. delimiter: The delimiter that will separate the values (default: " ")
  1382. ]]--
  1383. MultiValue = class(AbstractValue)
  1384. function MultiValue.__init__(self, ...)
  1385. AbstractValue.__init__(self, ...)
  1386. self.template = "cbi/mvalue"
  1387. self.widget = "checkbox"
  1388. self.delimiter = " "
  1389. self:reset_values()
  1390. end
  1391. function MultiValue.render(self, ...)
  1392. if self.widget == "select" and not self.size then
  1393. self.size = #self.vallist
  1394. end
  1395. AbstractValue.render(self, ...)
  1396. end
  1397. function MultiValue.reset_values(self)
  1398. self.keylist = {}
  1399. self.vallist = {}
  1400. self.deplist = {}
  1401. end
  1402. function MultiValue.value(self, key, val)
  1403. if luci.util.contains(self.keylist, key) then
  1404. return
  1405. end
  1406. val = val or key
  1407. table.insert(self.keylist, tostring(key))
  1408. table.insert(self.vallist, tostring(val))
  1409. end
  1410. function MultiValue.valuelist(self, section)
  1411. local val = self:cfgvalue(section)
  1412. if not(type(val) == "string") then
  1413. return {}
  1414. end
  1415. return luci.util.split(val, self.delimiter)
  1416. end
  1417. function MultiValue.validate(self, val)
  1418. val = (type(val) == "table") and val or {val}
  1419. local result
  1420. for i, value in ipairs(val) do
  1421. if luci.util.contains(self.keylist, value) then
  1422. result = result and (result .. self.delimiter .. value) or value
  1423. end
  1424. end
  1425. return result
  1426. end
  1427. StaticList = class(MultiValue)
  1428. function StaticList.__init__(self, ...)
  1429. MultiValue.__init__(self, ...)
  1430. self.cast = "table"
  1431. self.valuelist = self.cfgvalue
  1432. if not self.override_scheme
  1433. and self.map:get_scheme(self.section.sectiontype, self.option) then
  1434. local vs = self.map:get_scheme(self.section.sectiontype, self.option)
  1435. if self.value and vs.values and not self.override_values then
  1436. for k, v in pairs(vs.values) do
  1437. self:value(k, v)
  1438. end
  1439. end
  1440. end
  1441. end
  1442. function StaticList.validate(self, value)
  1443. value = (type(value) == "table") and value or {value}
  1444. local valid = {}
  1445. for i, v in ipairs(value) do
  1446. if luci.util.contains(self.keylist, v) then
  1447. table.insert(valid, v)
  1448. end
  1449. end
  1450. return valid
  1451. end
  1452. DynamicList = class(AbstractValue)
  1453. function DynamicList.__init__(self, ...)
  1454. AbstractValue.__init__(self, ...)
  1455. self.template = "cbi/dynlist"
  1456. self.cast = "table"
  1457. self:reset_values()
  1458. end
  1459. function DynamicList.reset_values(self)
  1460. self.keylist = {}
  1461. self.vallist = {}
  1462. end
  1463. function DynamicList.value(self, key, val)
  1464. val = val or key
  1465. table.insert(self.keylist, tostring(key))
  1466. table.insert(self.vallist, tostring(val))
  1467. end
  1468. function DynamicList.write(self, section, value)
  1469. local t = { }
  1470. if type(value) == "table" then
  1471. local x
  1472. for _, x in ipairs(value) do
  1473. if x and #x > 0 then
  1474. t[#t+1] = x
  1475. end
  1476. end
  1477. else
  1478. t = { value }
  1479. end
  1480. if self.cast == "string" then
  1481. value = table.concat(t, " ")
  1482. else
  1483. value = t
  1484. end
  1485. return AbstractValue.write(self, section, value)
  1486. end
  1487. function DynamicList.cfgvalue(self, section)
  1488. local value = AbstractValue.cfgvalue(self, section)
  1489. if type(value) == "string" then
  1490. local x
  1491. local t = { }
  1492. for x in value:gmatch("%S+") do
  1493. if #x > 0 then
  1494. t[#t+1] = x
  1495. end
  1496. end
  1497. value = t
  1498. end
  1499. return value
  1500. end
  1501. function DynamicList.formvalue(self, section)
  1502. local value = AbstractValue.formvalue(self, section)
  1503. if type(value) == "string" then
  1504. if self.cast == "string" then
  1505. local x
  1506. local t = { }
  1507. for x in value:gmatch("%S+") do
  1508. t[#t+1] = x
  1509. end
  1510. value = t
  1511. else
  1512. value = { value }
  1513. end
  1514. end
  1515. return value
  1516. end
  1517. --[[
  1518. TextValue - A multi-line value
  1519. rows: Rows
  1520. ]]--
  1521. TextValue = class(AbstractValue)
  1522. function TextValue.__init__(self, ...)
  1523. AbstractValue.__init__(self, ...)
  1524. self.template = "cbi/tvalue"
  1525. end
  1526. --[[
  1527. Button
  1528. ]]--
  1529. Button = class(AbstractValue)
  1530. function Button.__init__(self, ...)
  1531. AbstractValue.__init__(self, ...)
  1532. self.template = "cbi/button"
  1533. self.inputstyle = nil
  1534. self.rmempty = true
  1535. self.unsafeupload = false
  1536. end
  1537. FileUpload = class(AbstractValue)
  1538. function FileUpload.__init__(self, ...)
  1539. AbstractValue.__init__(self, ...)
  1540. self.template = "cbi/upload"
  1541. if not self.map.upload_fields then
  1542. self.map.upload_fields = { self }
  1543. else
  1544. self.map.upload_fields[#self.map.upload_fields+1] = self
  1545. end
  1546. end
  1547. function FileUpload.formcreated(self, section)
  1548. if self.unsafeupload then
  1549. return AbstractValue.formcreated(self, section) or
  1550. self.map:formvalue("cbi.rlf."..section.."."..self.option) or
  1551. self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") or
  1552. self.map:formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
  1553. else
  1554. return AbstractValue.formcreated(self, section) or
  1555. self.map:formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
  1556. end
  1557. end
  1558. function FileUpload.cfgvalue(self, section)
  1559. local val = AbstractValue.cfgvalue(self, section)
  1560. if val and fs.access(val) then
  1561. return val
  1562. end
  1563. return nil
  1564. end
  1565. -- If we have a new value, use it
  1566. -- otherwise use old value
  1567. -- deletion should be managed by a separate button object
  1568. -- unless self.unsafeupload is set in which case if the user
  1569. -- choose to remove the old file we do so.
  1570. -- Also, allow to specify (via textbox) a file already on router
  1571. function FileUpload.formvalue(self, section)
  1572. local val = AbstractValue.formvalue(self, section)
  1573. if val then
  1574. if self.unsafeupload then
  1575. if not self.map:formvalue("cbi.rlf."..section.."."..self.option) and
  1576. not self.map:formvalue("cbi.rlf."..section.."."..self.option..".x")
  1577. then
  1578. return val
  1579. end
  1580. fs.unlink(val)
  1581. self.value = nil
  1582. return nil
  1583. elseif val ~= "" then
  1584. return val
  1585. end
  1586. end
  1587. val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
  1588. if val == "" then
  1589. val = nil
  1590. end
  1591. if not self.unsafeupload then
  1592. if not val then
  1593. val = self.map:formvalue("cbi.rlf."..section.."."..self.option)
  1594. end
  1595. end
  1596. return val
  1597. end
  1598. function FileUpload.remove(self, section)
  1599. if self.unsafeupload then
  1600. local val = AbstractValue.formvalue(self, section)
  1601. if val and fs.access(val) then fs.unlink(val) end
  1602. return AbstractValue.remove(self, section)
  1603. else
  1604. return nil
  1605. end
  1606. end
  1607. FileBrowser = class(AbstractValue)
  1608. function FileBrowser.__init__(self, ...)
  1609. AbstractValue.__init__(self, ...)
  1610. self.template = "cbi/browser"
  1611. end