cbi.lua 43 KB

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