cbi.lua 39 KB

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