cbi.lua 39 KB

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