1
0

cbi.lua 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965
  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. -- Generates the unique CBID
  1125. function AbstractValue.cbid(self, section)
  1126. return "cbid."..self.map.config.."."..section.."."..self.option
  1127. end
  1128. -- Return whether this object should be created
  1129. function AbstractValue.formcreated(self, section)
  1130. local key = "cbi.opt."..self.config.."."..section
  1131. return (self.map:formvalue(key) == self.option)
  1132. end
  1133. -- Returns the formvalue for this object
  1134. function AbstractValue.formvalue(self, section)
  1135. return self.map:formvalue(self:cbid(section))
  1136. end
  1137. function AbstractValue.additional(self, value)
  1138. self.optional = value
  1139. end
  1140. function AbstractValue.mandatory(self, value)
  1141. self.rmempty = not value
  1142. end
  1143. function AbstractValue.add_error(self, section, type, msg)
  1144. self.error = self.error or { }
  1145. self.error[section] = msg or type
  1146. self.section.error = self.section.error or { }
  1147. self.section.error[section] = self.section.error[section] or { }
  1148. table.insert(self.section.error[section], msg or type)
  1149. if type == "invalid" then
  1150. self.tag_invalid[section] = true
  1151. elseif type == "missing" then
  1152. self.tag_missing[section] = true
  1153. end
  1154. self.tag_error[section] = true
  1155. self.map.save = false
  1156. end
  1157. function AbstractValue.parse(self, section, novld)
  1158. local fvalue = self:formvalue(section)
  1159. local cvalue = self:cfgvalue(section)
  1160. -- If favlue and cvalue are both tables and have the same content
  1161. -- make them identical
  1162. if type(fvalue) == "table" and type(cvalue) == "table" then
  1163. local equal = #fvalue == #cvalue
  1164. if equal then
  1165. for i=1, #fvalue do
  1166. if cvalue[i] ~= fvalue[i] then
  1167. equal = false
  1168. end
  1169. end
  1170. end
  1171. if equal then
  1172. fvalue = cvalue
  1173. end
  1174. end
  1175. if fvalue and #fvalue > 0 then -- If we have a form value, write it to UCI
  1176. local val_err
  1177. fvalue, val_err = self:validate(fvalue, section)
  1178. fvalue = self:transform(fvalue)
  1179. if not fvalue and not novld then
  1180. self:add_error(section, "invalid", val_err)
  1181. end
  1182. if self.alias then
  1183. self.section.aliased = self.section.aliased or {}
  1184. self.section.aliased[section] = self.section.aliased[section] or {}
  1185. self.section.aliased[section][self.alias] = true
  1186. end
  1187. if fvalue and (self.forcewrite or not (fvalue == cvalue)) then
  1188. if self:write(section, fvalue) then
  1189. -- Push events
  1190. self.section.changed = true
  1191. --luci.util.append(self.map.events, self.events)
  1192. end
  1193. end
  1194. else -- Unset the UCI or error
  1195. if self.rmempty or self.optional then
  1196. if not self.alias or
  1197. not self.section.aliased or
  1198. not self.section.aliased[section] or
  1199. not self.section.aliased[section][self.alias]
  1200. then
  1201. if self:remove(section) then
  1202. -- Push events
  1203. self.section.changed = true
  1204. --luci.util.append(self.map.events, self.events)
  1205. end
  1206. end
  1207. elseif cvalue ~= fvalue and not novld then
  1208. -- trigger validator with nil value to get custom user error msg.
  1209. local _, val_err = self:validate(nil, section)
  1210. self:add_error(section, "missing", val_err)
  1211. end
  1212. end
  1213. end
  1214. -- Render if this value exists or if it is mandatory
  1215. function AbstractValue.render(self, s, scope)
  1216. if not self.optional or self.section:has_tabs() or self:cfgvalue(s) or self:formcreated(s) then
  1217. scope = scope or {}
  1218. scope.section = s
  1219. scope.cbid = self:cbid(s)
  1220. Node.render(self, scope)
  1221. end
  1222. end
  1223. -- Return the UCI value of this object
  1224. function AbstractValue.cfgvalue(self, section)
  1225. local value
  1226. if self.tag_error[section] then
  1227. value = self:formvalue(section)
  1228. else
  1229. value = self.map:get(section, self.alias or self.option)
  1230. end
  1231. if not value then
  1232. return nil
  1233. elseif not self.cast or self.cast == type(value) then
  1234. return value
  1235. elseif self.cast == "string" then
  1236. if type(value) == "table" then
  1237. return value[1]
  1238. end
  1239. elseif self.cast == "table" then
  1240. return { value }
  1241. end
  1242. end
  1243. -- Validate the form value
  1244. function AbstractValue.validate(self, value)
  1245. if self.datatype and value then
  1246. if type(value) == "table" then
  1247. local v
  1248. for _, v in ipairs(value) do
  1249. if v and #v > 0 and not verify_datatype(self.datatype, v) then
  1250. return nil
  1251. end
  1252. end
  1253. else
  1254. if not verify_datatype(self.datatype, value) then
  1255. return nil
  1256. end
  1257. end
  1258. end
  1259. return value
  1260. end
  1261. AbstractValue.transform = AbstractValue.validate
  1262. -- Write to UCI
  1263. function AbstractValue.write(self, section, value)
  1264. return self.map:set(section, self.alias or self.option, value)
  1265. end
  1266. -- Remove from UCI
  1267. function AbstractValue.remove(self, section)
  1268. return self.map:del(section, self.alias or self.option)
  1269. end
  1270. --[[
  1271. Value - A one-line value
  1272. maxlength: The maximum length
  1273. ]]--
  1274. Value = class(AbstractValue)
  1275. function Value.__init__(self, ...)
  1276. AbstractValue.__init__(self, ...)
  1277. self.template = "cbi/value"
  1278. self.keylist = {}
  1279. self.vallist = {}
  1280. self.readonly = nil
  1281. end
  1282. function Value.reset_values(self)
  1283. self.keylist = {}
  1284. self.vallist = {}
  1285. end
  1286. function Value.value(self, key, val)
  1287. val = val or key
  1288. table.insert(self.keylist, tostring(key))
  1289. table.insert(self.vallist, tostring(val))
  1290. end
  1291. function Value.parse(self, section, novld)
  1292. if self.readonly then return end
  1293. AbstractValue.parse(self, section, novld)
  1294. end
  1295. -- DummyValue - This does nothing except being there
  1296. DummyValue = class(AbstractValue)
  1297. function DummyValue.__init__(self, ...)
  1298. AbstractValue.__init__(self, ...)
  1299. self.template = "cbi/dvalue"
  1300. self.value = nil
  1301. end
  1302. function DummyValue.cfgvalue(self, section)
  1303. local value
  1304. if self.value then
  1305. if type(self.value) == "function" then
  1306. value = self:value(section)
  1307. else
  1308. value = self.value
  1309. end
  1310. else
  1311. value = AbstractValue.cfgvalue(self, section)
  1312. end
  1313. return value
  1314. end
  1315. function DummyValue.parse(self)
  1316. end
  1317. --[[
  1318. Flag - A flag being enabled or disabled
  1319. ]]--
  1320. Flag = class(AbstractValue)
  1321. function Flag.__init__(self, ...)
  1322. AbstractValue.__init__(self, ...)
  1323. self.template = "cbi/fvalue"
  1324. self.enabled = "1"
  1325. self.disabled = "0"
  1326. self.default = self.disabled
  1327. end
  1328. -- A flag can only have two states: set or unset
  1329. function Flag.parse(self, section, novld)
  1330. local fexists = self.map:formvalue(
  1331. FEXIST_PREFIX .. self.config .. "." .. section .. "." .. self.option)
  1332. if fexists then
  1333. local fvalue = self:formvalue(section) and self.enabled or self.disabled
  1334. local cvalue = self:cfgvalue(section)
  1335. local val_err
  1336. fvalue, val_err = self:validate(fvalue, section)
  1337. if not fvalue then
  1338. if not novld then
  1339. self:add_error(section, "invalid", val_err)
  1340. end
  1341. return
  1342. end
  1343. if fvalue == self.default and (self.optional or self.rmempty) then
  1344. self:remove(section)
  1345. else
  1346. self:write(section, fvalue)
  1347. end
  1348. if (fvalue ~= cvalue) then self.section.changed = true end
  1349. else
  1350. self:remove(section)
  1351. self.section.changed = true
  1352. end
  1353. end
  1354. function Flag.cfgvalue(self, section)
  1355. return AbstractValue.cfgvalue(self, section) or self.default
  1356. end
  1357. function Flag.validate(self, value)
  1358. return value
  1359. end
  1360. --[[
  1361. ListValue - A one-line value predefined in a list
  1362. widget: The widget that will be used (select, radio)
  1363. ]]--
  1364. ListValue = class(AbstractValue)
  1365. function ListValue.__init__(self, ...)
  1366. AbstractValue.__init__(self, ...)
  1367. self.template = "cbi/lvalue"
  1368. self.size = 1
  1369. self.widget = "select"
  1370. self:reset_values()
  1371. end
  1372. function ListValue.reset_values(self)
  1373. self.keylist = {}
  1374. self.vallist = {}
  1375. self.deplist = {}
  1376. end
  1377. function ListValue.value(self, key, val, ...)
  1378. if luci.util.contains(self.keylist, key) then
  1379. return
  1380. end
  1381. val = val or key
  1382. table.insert(self.keylist, tostring(key))
  1383. table.insert(self.vallist, tostring(val))
  1384. table.insert(self.deplist, {...})
  1385. end
  1386. function ListValue.validate(self, val)
  1387. if luci.util.contains(self.keylist, val) then
  1388. return val
  1389. else
  1390. return nil
  1391. end
  1392. end
  1393. --[[
  1394. MultiValue - Multiple delimited values
  1395. widget: The widget that will be used (select, checkbox)
  1396. delimiter: The delimiter that will separate the values (default: " ")
  1397. ]]--
  1398. MultiValue = class(AbstractValue)
  1399. function MultiValue.__init__(self, ...)
  1400. AbstractValue.__init__(self, ...)
  1401. self.template = "cbi/mvalue"
  1402. self.widget = "checkbox"
  1403. self.delimiter = " "
  1404. self:reset_values()
  1405. end
  1406. function MultiValue.render(self, ...)
  1407. if self.widget == "select" and not self.size then
  1408. self.size = #self.vallist
  1409. end
  1410. AbstractValue.render(self, ...)
  1411. end
  1412. function MultiValue.reset_values(self)
  1413. self.keylist = {}
  1414. self.vallist = {}
  1415. self.deplist = {}
  1416. end
  1417. function MultiValue.value(self, key, val)
  1418. if luci.util.contains(self.keylist, key) then
  1419. return
  1420. end
  1421. val = val or key
  1422. table.insert(self.keylist, tostring(key))
  1423. table.insert(self.vallist, tostring(val))
  1424. end
  1425. function MultiValue.valuelist(self, section)
  1426. local val = self:cfgvalue(section)
  1427. if not(type(val) == "string") then
  1428. return {}
  1429. end
  1430. return luci.util.split(val, self.delimiter)
  1431. end
  1432. function MultiValue.validate(self, val)
  1433. val = (type(val) == "table") and val or {val}
  1434. local result
  1435. for i, value in ipairs(val) do
  1436. if luci.util.contains(self.keylist, value) then
  1437. result = result and (result .. self.delimiter .. value) or value
  1438. end
  1439. end
  1440. return result
  1441. end
  1442. StaticList = class(MultiValue)
  1443. function StaticList.__init__(self, ...)
  1444. MultiValue.__init__(self, ...)
  1445. self.cast = "table"
  1446. self.valuelist = self.cfgvalue
  1447. if not self.override_scheme
  1448. and self.map:get_scheme(self.section.sectiontype, self.option) then
  1449. local vs = self.map:get_scheme(self.section.sectiontype, self.option)
  1450. if self.value and vs.values and not self.override_values then
  1451. for k, v in pairs(vs.values) do
  1452. self:value(k, v)
  1453. end
  1454. end
  1455. end
  1456. end
  1457. function StaticList.validate(self, value)
  1458. value = (type(value) == "table") and value or {value}
  1459. local valid = {}
  1460. for i, v in ipairs(value) do
  1461. if luci.util.contains(self.keylist, v) then
  1462. table.insert(valid, v)
  1463. end
  1464. end
  1465. return valid
  1466. end
  1467. DynamicList = class(AbstractValue)
  1468. function DynamicList.__init__(self, ...)
  1469. AbstractValue.__init__(self, ...)
  1470. self.template = "cbi/dynlist"
  1471. self.cast = "table"
  1472. self:reset_values()
  1473. end
  1474. function DynamicList.reset_values(self)
  1475. self.keylist = {}
  1476. self.vallist = {}
  1477. end
  1478. function DynamicList.value(self, key, val)
  1479. val = val or key
  1480. table.insert(self.keylist, tostring(key))
  1481. table.insert(self.vallist, tostring(val))
  1482. end
  1483. function DynamicList.write(self, section, value)
  1484. local t = { }
  1485. if type(value) == "table" then
  1486. local x
  1487. for _, x in ipairs(value) do
  1488. if x and #x > 0 then
  1489. t[#t+1] = x
  1490. end
  1491. end
  1492. else
  1493. t = { value }
  1494. end
  1495. if self.cast == "string" then
  1496. value = table.concat(t, " ")
  1497. else
  1498. value = t
  1499. end
  1500. return AbstractValue.write(self, section, value)
  1501. end
  1502. function DynamicList.cfgvalue(self, section)
  1503. local value = AbstractValue.cfgvalue(self, section)
  1504. if type(value) == "string" then
  1505. local x
  1506. local t = { }
  1507. for x in value:gmatch("%S+") do
  1508. if #x > 0 then
  1509. t[#t+1] = x
  1510. end
  1511. end
  1512. value = t
  1513. end
  1514. return value
  1515. end
  1516. function DynamicList.formvalue(self, section)
  1517. local value = AbstractValue.formvalue(self, section)
  1518. if type(value) == "string" then
  1519. if self.cast == "string" then
  1520. local x
  1521. local t = { }
  1522. for x in value:gmatch("%S+") do
  1523. t[#t+1] = x
  1524. end
  1525. value = t
  1526. else
  1527. value = { value }
  1528. end
  1529. end
  1530. return value
  1531. end
  1532. DropDown = class(MultiValue)
  1533. function DropDown.__init__(self, ...)
  1534. ListValue.__init__(self, ...)
  1535. self.template = "cbi/dropdown"
  1536. self.delimiter = " "
  1537. end
  1538. --[[
  1539. TextValue - A multi-line value
  1540. rows: Rows
  1541. ]]--
  1542. TextValue = class(AbstractValue)
  1543. function TextValue.__init__(self, ...)
  1544. AbstractValue.__init__(self, ...)
  1545. self.template = "cbi/tvalue"
  1546. end
  1547. --[[
  1548. Button
  1549. ]]--
  1550. Button = class(AbstractValue)
  1551. function Button.__init__(self, ...)
  1552. AbstractValue.__init__(self, ...)
  1553. self.template = "cbi/button"
  1554. self.inputstyle = nil
  1555. self.rmempty = true
  1556. self.unsafeupload = false
  1557. end
  1558. FileUpload = class(AbstractValue)
  1559. function FileUpload.__init__(self, ...)
  1560. AbstractValue.__init__(self, ...)
  1561. self.template = "cbi/upload"
  1562. if not self.map.upload_fields then
  1563. self.map.upload_fields = { self }
  1564. else
  1565. self.map.upload_fields[#self.map.upload_fields+1] = self
  1566. end
  1567. end
  1568. function FileUpload.formcreated(self, section)
  1569. if self.unsafeupload then
  1570. return AbstractValue.formcreated(self, section) or
  1571. self.map:formvalue("cbi.rlf."..section.."."..self.option) or
  1572. self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") or
  1573. self.map:formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
  1574. else
  1575. return AbstractValue.formcreated(self, section) or
  1576. self.map:formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
  1577. end
  1578. end
  1579. function FileUpload.cfgvalue(self, section)
  1580. local val = AbstractValue.cfgvalue(self, section)
  1581. if val and fs.access(val) then
  1582. return val
  1583. end
  1584. return nil
  1585. end
  1586. -- If we have a new value, use it
  1587. -- otherwise use old value
  1588. -- deletion should be managed by a separate button object
  1589. -- unless self.unsafeupload is set in which case if the user
  1590. -- choose to remove the old file we do so.
  1591. -- Also, allow to specify (via textbox) a file already on router
  1592. function FileUpload.formvalue(self, section)
  1593. local val = AbstractValue.formvalue(self, section)
  1594. if val then
  1595. if self.unsafeupload then
  1596. if not self.map:formvalue("cbi.rlf."..section.."."..self.option) and
  1597. not self.map:formvalue("cbi.rlf."..section.."."..self.option..".x")
  1598. then
  1599. return val
  1600. end
  1601. fs.unlink(val)
  1602. self.value = nil
  1603. return nil
  1604. elseif val ~= "" then
  1605. return val
  1606. end
  1607. end
  1608. val = luci.http.formvalue("cbid."..self.map.config.."."..section.."."..self.option..".textbox")
  1609. if val == "" then
  1610. val = nil
  1611. end
  1612. if not self.unsafeupload then
  1613. if not val then
  1614. val = self.map:formvalue("cbi.rlf."..section.."."..self.option)
  1615. end
  1616. end
  1617. return val
  1618. end
  1619. function FileUpload.remove(self, section)
  1620. if self.unsafeupload then
  1621. local val = AbstractValue.formvalue(self, section)
  1622. if val and fs.access(val) then fs.unlink(val) end
  1623. return AbstractValue.remove(self, section)
  1624. else
  1625. return nil
  1626. end
  1627. end
  1628. FileBrowser = class(AbstractValue)
  1629. function FileBrowser.__init__(self, ...)
  1630. AbstractValue.__init__(self, ...)
  1631. self.template = "cbi/browser"
  1632. end