From ede4aca4b95c9e664e4830fd43c54b627b122538 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Tue, 12 Oct 2010 05:15:32 +0000 Subject: libs: merge libs/cbi into libs/web --- libs/web/luasrc/cbi.lua | 1707 ++++++++++++++++++++++++ libs/web/luasrc/cbi/datatypes.lua | 206 +++ libs/web/luasrc/view/cbi/browser.htm | 23 + libs/web/luasrc/view/cbi/button.htm | 21 + libs/web/luasrc/view/cbi/cell_valuefooter.htm | 34 + libs/web/luasrc/view/cbi/cell_valueheader.htm | 17 + libs/web/luasrc/view/cbi/compound.htm | 14 + libs/web/luasrc/view/cbi/delegator.htm | 37 + libs/web/luasrc/view/cbi/dvalue.htm | 22 + libs/web/luasrc/view/cbi/dynlist.htm | 52 + libs/web/luasrc/view/cbi/filebrowser.htm | 123 ++ libs/web/luasrc/view/cbi/firewall_zonelist.htm | 89 ++ libs/web/luasrc/view/cbi/footer.htm | 29 + libs/web/luasrc/view/cbi/full_valuefooter.htm | 74 + libs/web/luasrc/view/cbi/full_valueheader.htm | 24 + libs/web/luasrc/view/cbi/fvalue.htm | 17 + libs/web/luasrc/view/cbi/header.htm | 22 + libs/web/luasrc/view/cbi/lvalue.htm | 32 + libs/web/luasrc/view/cbi/map.htm | 63 + libs/web/luasrc/view/cbi/mvalue.htm | 35 + libs/web/luasrc/view/cbi/network_ifacelist.htm | 54 + libs/web/luasrc/view/cbi/network_netlist.htm | 61 + libs/web/luasrc/view/cbi/nsection.htm | 46 + libs/web/luasrc/view/cbi/nullsection.htm | 32 + libs/web/luasrc/view/cbi/simpleform.htm | 66 + libs/web/luasrc/view/cbi/tabcontainer.htm | 21 + libs/web/luasrc/view/cbi/tabmenu.htm | 27 + libs/web/luasrc/view/cbi/tblsection.htm | 135 ++ libs/web/luasrc/view/cbi/tsection.htm | 62 + libs/web/luasrc/view/cbi/tvalue.htm | 19 + libs/web/luasrc/view/cbi/ucisection.htm | 90 ++ libs/web/luasrc/view/cbi/upload.htm | 29 + libs/web/luasrc/view/cbi/value.htm | 44 + libs/web/luasrc/view/cbi/valuefooter.htm | 16 + libs/web/luasrc/view/cbi/valueheader.htm | 16 + 35 files changed, 3359 insertions(+) create mode 100644 libs/web/luasrc/cbi.lua create mode 100644 libs/web/luasrc/cbi/datatypes.lua create mode 100644 libs/web/luasrc/view/cbi/browser.htm create mode 100644 libs/web/luasrc/view/cbi/button.htm create mode 100644 libs/web/luasrc/view/cbi/cell_valuefooter.htm create mode 100644 libs/web/luasrc/view/cbi/cell_valueheader.htm create mode 100644 libs/web/luasrc/view/cbi/compound.htm create mode 100644 libs/web/luasrc/view/cbi/delegator.htm create mode 100644 libs/web/luasrc/view/cbi/dvalue.htm create mode 100644 libs/web/luasrc/view/cbi/dynlist.htm create mode 100644 libs/web/luasrc/view/cbi/filebrowser.htm create mode 100644 libs/web/luasrc/view/cbi/firewall_zonelist.htm create mode 100644 libs/web/luasrc/view/cbi/footer.htm create mode 100644 libs/web/luasrc/view/cbi/full_valuefooter.htm create mode 100644 libs/web/luasrc/view/cbi/full_valueheader.htm create mode 100644 libs/web/luasrc/view/cbi/fvalue.htm create mode 100644 libs/web/luasrc/view/cbi/header.htm create mode 100644 libs/web/luasrc/view/cbi/lvalue.htm create mode 100644 libs/web/luasrc/view/cbi/map.htm create mode 100644 libs/web/luasrc/view/cbi/mvalue.htm create mode 100644 libs/web/luasrc/view/cbi/network_ifacelist.htm create mode 100644 libs/web/luasrc/view/cbi/network_netlist.htm create mode 100644 libs/web/luasrc/view/cbi/nsection.htm create mode 100644 libs/web/luasrc/view/cbi/nullsection.htm create mode 100644 libs/web/luasrc/view/cbi/simpleform.htm create mode 100644 libs/web/luasrc/view/cbi/tabcontainer.htm create mode 100644 libs/web/luasrc/view/cbi/tabmenu.htm create mode 100644 libs/web/luasrc/view/cbi/tblsection.htm create mode 100644 libs/web/luasrc/view/cbi/tsection.htm create mode 100644 libs/web/luasrc/view/cbi/tvalue.htm create mode 100644 libs/web/luasrc/view/cbi/ucisection.htm create mode 100644 libs/web/luasrc/view/cbi/upload.htm create mode 100644 libs/web/luasrc/view/cbi/value.htm create mode 100644 libs/web/luasrc/view/cbi/valuefooter.htm create mode 100644 libs/web/luasrc/view/cbi/valueheader.htm (limited to 'libs/web/luasrc') diff --git a/libs/web/luasrc/cbi.lua b/libs/web/luasrc/cbi.lua new file mode 100644 index 0000000000..8dd16b181e --- /dev/null +++ b/libs/web/luasrc/cbi.lua @@ -0,0 +1,1707 @@ +--[[ +LuCI - Configuration Bind Interface + +Description: +Offers an interface for binding configuration values to certain +data types. Supports value and range validation and basic dependencies. + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("luci.cbi", package.seeall) + +require("luci.template") +local util = require("luci.util") +require("luci.http") + + +--local event = require "luci.sys.event" +local fs = require("nixio.fs") +local uci = require("luci.model.uci") +local datatypes = require("luci.cbi.datatypes") +local class = util.class +local instanceof = util.instanceof + +FORM_NODATA = 0 +FORM_PROCEED = 0 +FORM_VALID = 1 +FORM_DONE = 1 +FORM_INVALID = -1 +FORM_CHANGED = 2 +FORM_SKIP = 4 + +AUTO = true + +CREATE_PREFIX = "cbi.cts." +REMOVE_PREFIX = "cbi.rts." + +-- Loads a CBI map from given file, creating an environment and returns it +function load(cbimap, ...) + local fs = require "nixio.fs" + local i18n = require "luci.i18n" + require("luci.config") + require("luci.util") + + local upldir = "/lib/uci/upload/" + local cbidir = luci.util.libpath() .. "/model/cbi/" + local func, err + + if fs.access(cbidir..cbimap..".lua") then + func, err = loadfile(cbidir..cbimap..".lua") + elseif fs.access(cbimap) then + func, err = loadfile(cbimap) + else + func, err = nil, "Model '" .. cbimap .. "' not found!" + end + + assert(func, err) + + luci.i18n.loadc("base") + + local env = { + translate=i18n.translate, + translatef=i18n.translatef, + arg={...} + } + + setfenv(func, setmetatable(env, {__index = + function(tbl, key) + return rawget(tbl, key) or _M[key] or _G[key] + end})) + + local maps = { func() } + local uploads = { } + local has_upload = false + + for i, map in ipairs(maps) do + if not instanceof(map, Node) then + error("CBI map returns no valid map object!") + return nil + else + map:prepare() + if map.upload_fields then + has_upload = true + for _, field in ipairs(map.upload_fields) do + uploads[ + field.config .. '.' .. + field.section.sectiontype .. '.' .. + field.option + ] = true + end + end + end + end + + if has_upload then + local uci = luci.model.uci.cursor() + local prm = luci.http.context.request.message.params + local fd, cbid + + luci.http.setfilehandler( + function( field, chunk, eof ) + if not field then return end + if field.name and not cbid then + local c, s, o = field.name:gmatch( + "cbid%.([^%.]+)%.([^%.]+)%.([^%.]+)" + )() + + if c and s and o then + local t = uci:get( c, s ) + if t and uploads[c.."."..t.."."..o] then + local path = upldir .. field.name + fd = io.open(path, "w") + if fd then + cbid = field.name + prm[cbid] = path + end + end + end + end + + if field.name == cbid and fd then + fd:write(chunk) + end + + if eof and fd then + fd:close() + fd = nil + cbid = nil + end + end + ) + end + + return maps +end + + +-- Node pseudo abstract class +Node = class() + +function Node.__init__(self, title, description) + self.children = {} + self.title = title or "" + self.description = description or "" + self.template = "cbi/node" +end + +-- hook helper +function Node._run_hook(self, hook) + if type(self[hook]) == "function" then + return self[hook](self) + end +end + +function Node._run_hooks(self, ...) + local f + local r = false + for _, f in ipairs(arg) do + if type(self[f]) == "function" then + self[f](self) + r = true + end + end + return r +end + +-- Prepare nodes +function Node.prepare(self, ...) + for k, child in ipairs(self.children) do + child:prepare(...) + end +end + +-- Append child nodes +function Node.append(self, obj) + table.insert(self.children, obj) +end + +-- Parse this node and its children +function Node.parse(self, ...) + for k, child in ipairs(self.children) do + child:parse(...) + end +end + +-- Render this node +function Node.render(self, scope) + scope = scope or {} + scope.self = self + + luci.template.render(self.template, scope) +end + +-- Render the children +function Node.render_children(self, ...) + for k, node in ipairs(self.children) do + node:render(...) + end +end + + +--[[ +A simple template element +]]-- +Template = class(Node) + +function Template.__init__(self, template) + Node.__init__(self) + self.template = template +end + +function Template.render(self) + luci.template.render(self.template, {self=self}) +end + +function Template.parse(self, readinput) + self.readinput = (readinput ~= false) + return Map.formvalue(self, "cbi.submit") and FORM_DONE or FORM_NODATA +end + + +--[[ +Map - A map describing a configuration file +]]-- +Map = class(Node) + +function Map.__init__(self, config, ...) + Node.__init__(self, ...) + + self.config = config + self.parsechain = {self.config} + self.template = "cbi/map" + self.apply_on_parse = nil + self.readinput = true + self.proceed = false + self.flow = {} + + self.uci = uci.cursor() + self.save = true + + self.changed = false + + if not self.uci:load(self.config) then + error("Unable to read UCI data: " .. self.config) + end +end + +function Map.formvalue(self, key) + return self.readinput and luci.http.formvalue(key) +end + +function Map.formvaluetable(self, key) + return self.readinput and luci.http.formvaluetable(key) or {} +end + +function Map.get_scheme(self, sectiontype, option) + if not option then + return self.scheme and self.scheme.sections[sectiontype] + else + return self.scheme and self.scheme.variables[sectiontype] + and self.scheme.variables[sectiontype][option] + end +end + +function Map.submitstate(self) + return self:formvalue("cbi.submit") +end + +-- Chain foreign config +function Map.chain(self, config) + table.insert(self.parsechain, config) +end + +function Map.state_handler(self, state) + return state +end + +-- Use optimized UCI writing +function Map.parse(self, readinput, ...) + self.readinput = (readinput ~= false) + self:_run_hooks("on_parse") + + if self:formvalue("cbi.skip") then + self.state = FORM_SKIP + return self:state_handler(self.state) + end + + Node.parse(self, ...) + + if self.save then + for i, config in ipairs(self.parsechain) do + self.uci:save(config) + end + if self:submitstate() and ((not self.proceed and self.flow.autoapply) or luci.http.formvalue("cbi.apply")) then + self:_run_hooks("on_before_commit") + for i, config in ipairs(self.parsechain) do + self.uci:commit(config) + + -- Refresh data because commit changes section names + self.uci:load(config) + end + self:_run_hooks("on_commit", "on_after_commit", "on_before_apply") + if self.apply_on_parse then + self.uci:apply(self.parsechain) + self:_run_hooks("on_apply", "on_after_apply") + else + self._apply = function() + local cmd = self.uci:apply(self.parsechain, true) + return io.popen(cmd) + end + end + + -- Reparse sections + Node.parse(self, true) + + end + for i, config in ipairs(self.parsechain) do + self.uci:unload(config) + end + if type(self.commit_handler) == "function" then + self:commit_handler(self:submitstate()) + end + end + + if self:submitstate() then + if not self.save then + self.state = FORM_INVALID + elseif self.proceed then + self.state = FORM_PROCEED + else + self.state = self.changed and FORM_CHANGED or FORM_VALID + end + else + self.state = FORM_NODATA + end + + return self:state_handler(self.state) +end + +function Map.render(self, ...) + self:_run_hooks("on_init") + Node.render(self, ...) + if false and self._apply then + local fp = self._apply() + fp:read("*a") + fp:close() + self:_run_hooks("on_apply") + end +end + +-- Creates a child section +function Map.section(self, class, ...) + if instanceof(class, AbstractSection) then + local obj = class(self, ...) + self:append(obj) + return obj + else + error("class must be a descendent of AbstractSection") + end +end + +-- UCI add +function Map.add(self, sectiontype) + return self.uci:add(self.config, sectiontype) +end + +-- UCI set +function Map.set(self, section, option, value) + if option then + return self.uci:set(self.config, section, option, value) + else + return self.uci:set(self.config, section, value) + end +end + +-- UCI del +function Map.del(self, section, option) + if option then + return self.uci:delete(self.config, section, option) + else + return self.uci:delete(self.config, section) + end +end + +-- UCI get +function Map.get(self, section, option) + if not section then + return self.uci:get_all(self.config) + elseif option then + return self.uci:get(self.config, section, option) + else + return self.uci:get_all(self.config, section) + end +end + +--[[ +Compound - Container +]]-- +Compound = class(Node) + +function Compound.__init__(self, ...) + Node.__init__(self) + self.template = "cbi/compound" + self.children = {...} +end + +function Compound.populate_delegator(self, delegator) + for _, v in ipairs(self.children) do + v.delegator = delegator + end +end + +function Compound.parse(self, ...) + local cstate, state = 0 + + for k, child in ipairs(self.children) do + cstate = child:parse(...) + state = (not state or cstate < state) and cstate or state + end + + return state +end + + +--[[ +Delegator - Node controller +]]-- +Delegator = class(Node) +function Delegator.__init__(self, ...) + Node.__init__(self, ...) + self.nodes = {} + self.defaultpath = {} + self.pageaction = false + self.readinput = true + self.allow_reset = false + self.allow_cancel = false + self.allow_back = false + self.allow_finish = false + self.template = "cbi/delegator" +end + +function Delegator.set(self, name, node) + assert(not self.nodes[name], "Duplicate entry") + + self.nodes[name] = node +end + +function Delegator.add(self, name, node) + node = self:set(name, node) + self.defaultpath[#self.defaultpath+1] = name +end + +function Delegator.insert_after(self, name, after) + local n = #self.chain + 1 + for k, v in ipairs(self.chain) do + if v == after then + n = k + 1 + break + end + end + table.insert(self.chain, n, name) +end + +function Delegator.set_route(self, ...) + local n, chain, route = 0, self.chain, {...} + for i = 1, #chain do + if chain[i] == self.current then + n = i + break + end + end + for i = 1, #route do + n = n + 1 + chain[n] = route[i] + end + for i = n + 1, #chain do + chain[i] = nil + end +end + +function Delegator.get(self, name) + local node = self.nodes[name] + + if type(node) == "string" then + node = load(node, name) + end + + if type(node) == "table" and getmetatable(node) == nil then + node = Compound(unpack(node)) + end + + return node +end + +function Delegator.parse(self, ...) + if self.allow_cancel and Map.formvalue(self, "cbi.cancel") then + if self:_run_hooks("on_cancel") then + return FORM_DONE + end + end + + if not Map.formvalue(self, "cbi.delg.current") then + self:_run_hooks("on_init") + end + + local newcurrent + self.chain = self.chain or self:get_chain() + self.current = self.current or self:get_active() + self.active = self.active or self:get(self.current) + assert(self.active, "Invalid state") + + local stat = FORM_DONE + if type(self.active) ~= "function" then + self.active:populate_delegator(self) + stat = self.active:parse() + else + self:active() + end + + if stat > FORM_PROCEED then + if Map.formvalue(self, "cbi.delg.back") then + newcurrent = self:get_prev(self.current) + else + newcurrent = self:get_next(self.current) + end + elseif stat < FORM_PROCEED then + return stat + end + + + if not Map.formvalue(self, "cbi.submit") then + return FORM_NODATA + elseif stat > FORM_PROCEED + and (not newcurrent or not self:get(newcurrent)) then + return self:_run_hook("on_done") or FORM_DONE + else + self.current = newcurrent or self.current + self.active = self:get(self.current) + if type(self.active) ~= "function" then + self.active:populate_delegator(self) + local stat = self.active:parse(false) + if stat == FORM_SKIP then + return self:parse(...) + else + return FORM_PROCEED + end + else + return self:parse(...) + end + end +end + +function Delegator.get_next(self, state) + for k, v in ipairs(self.chain) do + if v == state then + return self.chain[k+1] + end + end +end + +function Delegator.get_prev(self, state) + for k, v in ipairs(self.chain) do + if v == state then + return self.chain[k-1] + end + end +end + +function Delegator.get_chain(self) + local x = Map.formvalue(self, "cbi.delg.path") or self.defaultpath + return type(x) == "table" and x or {x} +end + +function Delegator.get_active(self) + return Map.formvalue(self, "cbi.delg.current") or self.chain[1] +end + +--[[ +Page - A simple node +]]-- + +Page = class(Node) +Page.__init__ = Node.__init__ +Page.parse = function() end + + +--[[ +SimpleForm - A Simple non-UCI form +]]-- +SimpleForm = class(Node) + +function SimpleForm.__init__(self, config, title, description, data) + Node.__init__(self, title, description) + self.config = config + self.data = data or {} + self.template = "cbi/simpleform" + self.dorender = true + self.pageaction = false + self.readinput = true +end + +SimpleForm.formvalue = Map.formvalue +SimpleForm.formvaluetable = Map.formvaluetable + +function SimpleForm.parse(self, readinput, ...) + self.readinput = (readinput ~= false) + + if self:formvalue("cbi.skip") then + return FORM_SKIP + end + + if self:formvalue("cbi.cancel") and self:_run_hooks("on_cancel") then + return FORM_DONE + end + + if self:submitstate() then + Node.parse(self, 1, ...) + end + + local valid = true + for k, j in ipairs(self.children) do + for i, v in ipairs(j.children) do + valid = valid + and (not v.tag_missing or not v.tag_missing[1]) + and (not v.tag_invalid or not v.tag_invalid[1]) + and (not v.error) + end + end + + local state = + not self:submitstate() and FORM_NODATA + or valid and FORM_VALID + or FORM_INVALID + + self.dorender = not self.handle + if self.handle then + local nrender, nstate = self:handle(state, self.data) + self.dorender = self.dorender or (nrender ~= false) + state = nstate or state + end + return state +end + +function SimpleForm.render(self, ...) + if self.dorender then + Node.render(self, ...) + end +end + +function SimpleForm.submitstate(self) + return self:formvalue("cbi.submit") +end + +function SimpleForm.section(self, class, ...) + if instanceof(class, AbstractSection) then + local obj = class(self, ...) + self:append(obj) + return obj + else + error("class must be a descendent of AbstractSection") + end +end + +-- Creates a child field +function SimpleForm.field(self, class, ...) + local section + for k, v in ipairs(self.children) do + if instanceof(v, SimpleSection) then + section = v + break + end + end + if not section then + section = self:section(SimpleSection) + end + + if instanceof(class, AbstractValue) then + local obj = class(self, section, ...) + obj.track_missing = true + section:append(obj) + return obj + else + error("class must be a descendent of AbstractValue") + end +end + +function SimpleForm.set(self, section, option, value) + self.data[option] = value +end + + +function SimpleForm.del(self, section, option) + self.data[option] = nil +end + + +function SimpleForm.get(self, section, option) + return self.data[option] +end + + +function SimpleForm.get_scheme() + return nil +end + + +Form = class(SimpleForm) + +function Form.__init__(self, ...) + SimpleForm.__init__(self, ...) + self.embedded = true +end + + +--[[ +AbstractSection +]]-- +AbstractSection = class(Node) + +function AbstractSection.__init__(self, map, sectiontype, ...) + Node.__init__(self, ...) + self.sectiontype = sectiontype + self.map = map + self.config = map.config + self.optionals = {} + self.defaults = {} + self.fields = {} + self.tag_error = {} + self.tag_invalid = {} + self.tag_deperror = {} + self.changed = false + + self.optional = true + self.addremove = false + self.dynamic = false +end + +-- Define a tab for the section +function AbstractSection.tab(self, tab, title, desc) + self.tabs = self.tabs or { } + self.tab_names = self.tab_names or { } + + self.tab_names[#self.tab_names+1] = tab + self.tabs[tab] = { + title = title, + description = desc, + childs = { } + } +end + +-- Check whether the section has tabs +function AbstractSection.has_tabs(self) + return (self.tabs ~= nil) and (next(self.tabs) ~= nil) +end + +-- Appends a new option +function AbstractSection.option(self, class, option, ...) + if instanceof(class, AbstractValue) then + local obj = class(self.map, self, option, ...) + self:append(obj) + self.fields[option] = obj + return obj + elseif class == true then + error("No valid class was given and autodetection failed.") + else + error("class must be a descendant of AbstractValue") + end +end + +-- Appends a new tabbed option +function AbstractSection.taboption(self, tab, ...) + + assert(tab and self.tabs and self.tabs[tab], + "Cannot assign option to not existing tab %q" % tostring(tab)) + + local l = self.tabs[tab].childs + local o = AbstractSection.option(self, ...) + + if o then l[#l+1] = o end + + return o +end + +-- Render a single tab +function AbstractSection.render_tab(self, tab, ...) + + assert(tab and self.tabs and self.tabs[tab], + "Cannot render not existing tab %q" % tostring(tab)) + + for _, node in ipairs(self.tabs[tab].childs) do + node:render(...) + end +end + +-- Parse optional options +function AbstractSection.parse_optionals(self, section) + if not self.optional then + return + end + + self.optionals[section] = {} + + local field = self.map:formvalue("cbi.opt."..self.config.."."..section) + for k,v in ipairs(self.children) do + if v.optional and not v:cfgvalue(section) and not self:has_tabs() then + if field == v.option then + field = nil + self.map.proceed = true + else + table.insert(self.optionals[section], v) + end + end + end + + if field and #field > 0 and self.dynamic then + self:add_dynamic(field) + end +end + +-- Add a dynamic option +function AbstractSection.add_dynamic(self, field, optional) + local o = self:option(Value, field, field) + o.optional = optional +end + +-- Parse all dynamic options +function AbstractSection.parse_dynamic(self, section) + if not self.dynamic then + return + end + + local arr = luci.util.clone(self:cfgvalue(section)) + local form = self.map:formvaluetable("cbid."..self.config.."."..section) + for k, v in pairs(form) do + arr[k] = v + end + + for key,val in pairs(arr) do + local create = true + + for i,c in ipairs(self.children) do + if c.option == key then + create = false + end + end + + if create and key:sub(1, 1) ~= "." then + self.map.proceed = true + self:add_dynamic(key, true) + end + end +end + +-- Returns the section's UCI table +function AbstractSection.cfgvalue(self, section) + return self.map:get(section) +end + +-- Push events +function AbstractSection.push_events(self) + --luci.util.append(self.map.events, self.events) + self.map.changed = true +end + +-- Removes the section +function AbstractSection.remove(self, section) + self.map.proceed = true + return self.map:del(section) +end + +-- Creates the section +function AbstractSection.create(self, section) + local stat + + if section then + stat = section:match("^[%w_]+$") and self.map:set(section, nil, self.sectiontype) + else + section = self.map:add(self.sectiontype) + stat = section + end + + if stat then + for k,v in pairs(self.children) do + if v.default then + self.map:set(section, v.option, v.default) + end + end + + for k,v in pairs(self.defaults) do + self.map:set(section, k, v) + end + end + + self.map.proceed = true + + return stat +end + + +SimpleSection = class(AbstractSection) + +function SimpleSection.__init__(self, form, ...) + AbstractSection.__init__(self, form, nil, ...) + self.template = "cbi/nullsection" +end + + +Table = class(AbstractSection) + +function Table.__init__(self, form, data, ...) + local datasource = {} + local tself = self + datasource.config = "table" + self.data = data or {} + + datasource.formvalue = Map.formvalue + datasource.formvaluetable = Map.formvaluetable + datasource.readinput = true + + function datasource.get(self, section, option) + return tself.data[section] and tself.data[section][option] + end + + function datasource.submitstate(self) + return Map.formvalue(self, "cbi.submit") + end + + function datasource.del(...) + return true + end + + function datasource.get_scheme() + return nil + end + + AbstractSection.__init__(self, datasource, "table", ...) + self.template = "cbi/tblsection" + self.rowcolors = true + self.anonymous = true +end + +function Table.parse(self, readinput) + self.map.readinput = (readinput ~= false) + for i, k in ipairs(self:cfgsections()) do + if self.map:submitstate() then + Node.parse(self, k) + end + end +end + +function Table.cfgsections(self) + local sections = {} + + for i, v in luci.util.kspairs(self.data) do + table.insert(sections, i) + end + + return sections +end + +function Table.update(self, data) + self.data = data +end + + + +--[[ +NamedSection - A fixed configuration section defined by its name +]]-- +NamedSection = class(AbstractSection) + +function NamedSection.__init__(self, map, section, stype, ...) + AbstractSection.__init__(self, map, stype, ...) + + -- Defaults + self.addremove = false + self.template = "cbi/nsection" + self.section = section +end + +function NamedSection.parse(self, novld) + local s = self.section + local active = self:cfgvalue(s) + + if self.addremove then + local path = self.config.."."..s + if active then -- Remove the section + if self.map:formvalue("cbi.rns."..path) and self:remove(s) then + self:push_events() + return + end + else -- Create and apply default values + if self.map:formvalue("cbi.cns."..path) then + self:create(s) + return + end + end + end + + if active then + AbstractSection.parse_dynamic(self, s) + if self.map:submitstate() then + Node.parse(self, s) + end + AbstractSection.parse_optionals(self, s) + + if self.changed then + self:push_events() + end + end +end + + +--[[ +TypedSection - A (set of) configuration section(s) defined by the type + addremove: Defines whether the user can add/remove sections of this type + anonymous: Allow creating anonymous sections + validate: a validation function returning nil if the section is invalid +]]-- +TypedSection = class(AbstractSection) + +function TypedSection.__init__(self, map, type, ...) + AbstractSection.__init__(self, map, type, ...) + + self.template = "cbi/tsection" + self.deps = {} + self.anonymous = false +end + +-- Return all matching UCI sections for this TypedSection +function TypedSection.cfgsections(self) + local sections = {} + self.map.uci:foreach(self.map.config, self.sectiontype, + function (section) + if self:checkscope(section[".name"]) then + table.insert(sections, section[".name"]) + end + end) + + return sections +end + +-- Limits scope to sections that have certain option => value pairs +function TypedSection.depends(self, option, value) + table.insert(self.deps, {option=option, value=value}) +end + +function TypedSection.parse(self, novld) + if self.addremove then + -- Remove + local crval = REMOVE_PREFIX .. self.config + local name = self.map:formvaluetable(crval) + for k,v in pairs(name) do + if k:sub(-2) == ".x" then + k = k:sub(1, #k - 2) + end + if self:cfgvalue(k) and self:checkscope(k) then + self:remove(k) + end + end + end + + local co + for i, k in ipairs(self:cfgsections()) do + AbstractSection.parse_dynamic(self, k) + if self.map:submitstate() then + Node.parse(self, k, novld) + end + AbstractSection.parse_optionals(self, k) + end + + if self.addremove then + -- Create + local created + local crval = CREATE_PREFIX .. self.config .. "." .. self.sectiontype + local name = self.map:formvalue(crval) + if self.anonymous then + if name then + created = self:create() + end + else + if name then + -- Ignore if it already exists + if self:cfgvalue(name) then + name = nil; + end + + name = self:checkscope(name) + + if not name then + self.err_invalid = true + end + + if name and #name > 0 then + created = self:create(name) and name + if not created then + self.invalid_cts = true + end + end + end + end + + if created then + AbstractSection.parse_optionals(self, created) + end + end + + if created or self.changed then + self:push_events() + end +end + +-- Verifies scope of sections +function TypedSection.checkscope(self, section) + -- Check if we are not excluded + if self.filter and not self:filter(section) then + return nil + end + + -- Check if at least one dependency is met + if #self.deps > 0 and self:cfgvalue(section) then + local stat = false + + for k, v in ipairs(self.deps) do + if self:cfgvalue(section)[v.option] == v.value then + stat = true + end + end + + if not stat then + return nil + end + end + + return self:validate(section) +end + + +-- Dummy validate function +function TypedSection.validate(self, section) + return section +end + + +--[[ +AbstractValue - An abstract Value Type + null: Value can be empty + valid: A function returning the value if it is valid otherwise nil + depends: A table of option => value pairs of which one must be true + default: The default value + size: The size of the input fields + rmempty: Unset value if empty + optional: This value is optional (see AbstractSection.optionals) +]]-- +AbstractValue = class(Node) + +function AbstractValue.__init__(self, map, section, option, ...) + Node.__init__(self, ...) + self.section = section + self.option = option + self.map = map + self.config = map.config + self.tag_invalid = {} + self.tag_missing = {} + self.tag_reqerror = {} + self.tag_error = {} + self.deps = {} + self.subdeps = {} + --self.cast = "string" + + self.track_missing = false + self.rmempty = true + self.default = nil + self.size = nil + self.optional = false +end + +function AbstractValue.prepare(self) + self.cast = self.cast or "string" +end + +-- Add a dependencie to another section field +function AbstractValue.depends(self, field, value) + local deps + if type(field) == "string" then + deps = {} + deps[field] = value + else + deps = field + end + + table.insert(self.deps, {deps=deps, add=""}) +end + +-- Generates the unique CBID +function AbstractValue.cbid(self, section) + return "cbid."..self.map.config.."."..section.."."..self.option +end + +-- Return whether this object should be created +function AbstractValue.formcreated(self, section) + local key = "cbi.opt."..self.config.."."..section + return (self.map:formvalue(key) == self.option) +end + +-- Returns the formvalue for this object +function AbstractValue.formvalue(self, section) + return self.map:formvalue(self:cbid(section)) +end + +function AbstractValue.additional(self, value) + self.optional = value +end + +function AbstractValue.mandatory(self, value) + self.rmempty = not value +end + +function AbstractValue.parse(self, section, novld) + local fvalue = self:formvalue(section) + local cvalue = self:cfgvalue(section) + + -- If favlue and cvalue are both tables and have the same content + -- make them identical + if type(fvalue) == "table" and type(cvalue) == "table" then + local equal = #fvalue == #cvalue + if equal then + for i=1, #fvalue do + if cvalue[i] ~= fvalue[i] then + equal = false + end + end + end + if equal then + fvalue = cvalue + end + end + + if fvalue and #fvalue > 0 then -- If we have a form value, write it to UCI + fvalue = self:transform(self:validate(fvalue, section)) + if not fvalue and not novld then + if self.error then + self.error[section] = "invalid" + else + self.error = { [section] = "invalid" } + end + if self.section.error then + table.insert(self.section.error[section], "invalid") + else + self.section.error = {[section] = {"invalid"}} + end + self.map.save = false + end + if fvalue and not (fvalue == cvalue) then + if self:write(section, fvalue) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end + end + else -- Unset the UCI or error + if self.rmempty or self.optional then + if self:remove(section) then + -- Push events + self.section.changed = true + --luci.util.append(self.map.events, self.events) + end + elseif cvalue ~= fvalue and not novld then + self:write(section, fvalue or "") + if self.error then + self.error[section] = "missing" + else + self.error = { [section] = "missing" } + end + self.map.save = false + end + end +end + +-- Render if this value exists or if it is mandatory +function AbstractValue.render(self, s, scope) + if not self.optional or self.section:has_tabs() or self:cfgvalue(s) or self:formcreated(s) then + scope = scope or {} + scope.section = s + scope.cbid = self:cbid(s) + scope.striptags = luci.util.striptags + scope.pcdata = luci.util.pcdata + + scope.ifattr = function(cond,key,val) + if cond then + return string.format( + ' %s="%s"', tostring(key), + luci.util.pcdata(tostring( val + or scope[key] + or (type(self[key]) ~= "function" and self[key]) + or "" )) + ) + else + return '' + end + end + + scope.attr = function(...) + return scope.ifattr( true, ... ) + end + + Node.render(self, scope) + end +end + +-- Return the UCI value of this object +function AbstractValue.cfgvalue(self, section) + local value = (self.error and self.error[section] == "invalid") + and self:formvalue(section) or self.map:get(section, self.option) + if not value then + return nil + elseif not self.cast or self.cast == type(value) then + return value + elseif self.cast == "string" then + if type(value) == "table" then + return value[1] + end + elseif self.cast == "table" then + return luci.util.split(value, "%s+", nil, true) + end +end + +-- Validate the form value +function AbstractValue.validate(self, value) + if self.datatype and value and datatypes[self.datatype] then + if type(value) == "table" then + local v + for _, v in ipairs(value) do + if v and #v > 0 and not datatypes[self.datatype](v) then + return nil + end + end + else + if not datatypes[self.datatype](value) then + return nil + end + end + end + return value +end + +AbstractValue.transform = AbstractValue.validate + + +-- Write to UCI +function AbstractValue.write(self, section, value) + return self.map:set(section, self.option, value) +end + +-- Remove from UCI +function AbstractValue.remove(self, section) + return self.map:del(section, self.option) +end + + + + +--[[ +Value - A one-line value + maxlength: The maximum length +]]-- +Value = class(AbstractValue) + +function Value.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/value" + self.keylist = {} + self.vallist = {} +end + +function Value.value(self, key, val) + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + + +-- DummyValue - This does nothing except being there +DummyValue = class(AbstractValue) + +function DummyValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/dvalue" + self.value = nil +end + +function DummyValue.cfgvalue(self, section) + local value + if self.value then + if type(self.value) == "function" then + value = self:value(section) + else + value = self.value + end + else + value = AbstractValue.cfgvalue(self, section) + end + return value +end + +function DummyValue.parse(self) + +end + + +--[[ +Flag - A flag being enabled or disabled +]]-- +Flag = class(AbstractValue) + +function Flag.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/fvalue" + + self.enabled = "1" + self.disabled = "0" +end + +-- A flag can only have two states: set or unset +function Flag.parse(self, section) + local fvalue = self:formvalue(section) + + if fvalue then + fvalue = self.enabled + else + fvalue = self.disabled + end + + if fvalue == self.enabled or (not self.optional and not self.rmempty) then + if not(fvalue == self:cfgvalue(section)) then + self:write(section, fvalue) + end + else + self:remove(section) + end +end + + + +--[[ +ListValue - A one-line value predefined in a list + widget: The widget that will be used (select, radio) +]]-- +ListValue = class(AbstractValue) + +function ListValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/lvalue" + + self.keylist = {} + self.vallist = {} + self.size = 1 + self.widget = "select" +end + +function ListValue.value(self, key, val, ...) + if luci.util.contains(self.keylist, key) then + return + end + + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) + + for i, deps in ipairs({...}) do + self.subdeps[#self.subdeps + 1] = {add = "-"..key, deps=deps} + end +end + +function ListValue.validate(self, val) + if luci.util.contains(self.keylist, val) then + return val + else + return nil + end +end + + + +--[[ +MultiValue - Multiple delimited values + widget: The widget that will be used (select, checkbox) + delimiter: The delimiter that will separate the values (default: " ") +]]-- +MultiValue = class(AbstractValue) + +function MultiValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/mvalue" + + self.keylist = {} + self.vallist = {} + + self.widget = "checkbox" + self.delimiter = " " +end + +function MultiValue.render(self, ...) + if self.widget == "select" and not self.size then + self.size = #self.vallist + end + + AbstractValue.render(self, ...) +end + +function MultiValue.value(self, key, val) + if luci.util.contains(self.keylist, key) then + return + end + + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + +function MultiValue.valuelist(self, section) + local val = self:cfgvalue(section) + + if not(type(val) == "string") then + return {} + end + + return luci.util.split(val, self.delimiter) +end + +function MultiValue.validate(self, val) + val = (type(val) == "table") and val or {val} + + local result + + for i, value in ipairs(val) do + if luci.util.contains(self.keylist, value) then + result = result and (result .. self.delimiter .. value) or value + end + end + + return result +end + + +StaticList = class(MultiValue) + +function StaticList.__init__(self, ...) + MultiValue.__init__(self, ...) + self.cast = "table" + self.valuelist = self.cfgvalue + + if not self.override_scheme + and self.map:get_scheme(self.section.sectiontype, self.option) then + local vs = self.map:get_scheme(self.section.sectiontype, self.option) + if self.value and vs.values and not self.override_values then + for k, v in pairs(vs.values) do + self:value(k, v) + end + end + end +end + +function StaticList.validate(self, value) + value = (type(value) == "table") and value or {value} + + local valid = {} + for i, v in ipairs(value) do + if luci.util.contains(self.keylist, v) then + table.insert(valid, v) + end + end + return valid +end + + +DynamicList = class(AbstractValue) + +function DynamicList.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/dynlist" + self.cast = "table" + self.keylist = {} + self.vallist = {} +end + +function DynamicList.value(self, key, val) + val = val or key + table.insert(self.keylist, tostring(key)) + table.insert(self.vallist, tostring(val)) +end + +function DynamicList.write(self, ...) + self.map.proceed = true + return AbstractValue.write(self, ...) +end + +function DynamicList.formvalue(self, section) + local value = AbstractValue.formvalue(self, section) + value = (type(value) == "table") and value or {value} + + local valid = {} + for i, v in ipairs(value) do + if v and #v > 0 + and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i) + and not self.map:formvalue("cbi.rle."..section.."."..self.option.."."..i..".x") then + table.insert(valid, v) + end + end + + return valid +end + + +--[[ +TextValue - A multi-line value + rows: Rows +]]-- +TextValue = class(AbstractValue) + +function TextValue.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/tvalue" +end + +--[[ +Button +]]-- +Button = class(AbstractValue) + +function Button.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/button" + self.inputstyle = nil + self.rmempty = true +end + + +FileUpload = class(AbstractValue) + +function FileUpload.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/upload" + if not self.map.upload_fields then + self.map.upload_fields = { self } + else + self.map.upload_fields[#self.map.upload_fields+1] = self + end +end + +function FileUpload.formcreated(self, section) + return AbstractValue.formcreated(self, section) or + self.map:formvalue("cbi.rlf."..section.."."..self.option) or + self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") +end + +function FileUpload.cfgvalue(self, section) + local val = AbstractValue.cfgvalue(self, section) + if val and fs.access(val) then + return val + end + return nil +end + +function FileUpload.formvalue(self, section) + local val = AbstractValue.formvalue(self, section) + if val then + if not self.map:formvalue("cbi.rlf."..section.."."..self.option) and + not self.map:formvalue("cbi.rlf."..section.."."..self.option..".x") + then + return val + end + fs.unlink(val) + self.value = nil + end + return nil +end + +function FileUpload.remove(self, section) + local val = AbstractValue.formvalue(self, section) + if val and fs.access(val) then fs.unlink(val) end + return AbstractValue.remove(self, section) +end + + +FileBrowser = class(AbstractValue) + +function FileBrowser.__init__(self, ...) + AbstractValue.__init__(self, ...) + self.template = "cbi/browser" +end diff --git a/libs/web/luasrc/cbi/datatypes.lua b/libs/web/luasrc/cbi/datatypes.lua new file mode 100644 index 0000000000..53a34547ba --- /dev/null +++ b/libs/web/luasrc/cbi/datatypes.lua @@ -0,0 +1,206 @@ +--[[ + +LuCI - Configuration Bind Interface - Datatype Tests +(c) 2010 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +]]-- + +local fs = require "nixio.fs" +local ip = require "luci.ip" +local math = require "math" +local util = require "luci.util" + +local tonumber = tonumber + +module "luci.cbi.datatypes" + + +function bool(val) + if val == "1" or val == "yes" or val == "on" or val == "true" then + return true + elseif val == "0" or val == "no" or val == "off" or val == "false" then + return true + elseif val == "" or val == nil then + return true + end + + return false +end + +function uint(val) + local n = tonumber(val) + if n ~= nil and math.floor(n) == n and n >= 0 then + return true + end + + return false +end + +function int(val) + local n = tonumber(val) + if n ~= nil and math.floor(n) == n then + return true + end + + return false +end + +function float(val) + return ( tonumber(val) ~= nil ) +end + +function ipaddr(val) + return ip4addr(val) or ip6addr(val) +end + +function ip4addr(val) + if val then + return ip.IPv4(val) and true or false + end + + return false +end + +function ip4prefix(val) + val = tonumber(val) + return ( val and val >= 0 and val <= 32 ) +end + +function ip6addr(val) + if val then + return ip.IPv6(val) and true or false + end + + return false +end + +function ip6prefix(val) + val = tonumber(val) + return ( val and val >= 0 and val <= 128 ) +end + +function port(val) + val = tonumber(val) + return ( val and val >= 1 and val <= 65535 ) +end + +function portrange(val) + local p1, p2 = val:match("^(%d+)%-(%d+)$") + if p1 and p2 and port(p1) and port(p2) then + return true + else + return port(val) + end +end + +function macaddr(val) + if val and val:match( + "^[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+:" .. + "[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+$" + ) then + local parts = util.split( val, ":" ) + + for i = 1,6 do + parts[i] = tonumber( parts[i], 16 ) + if parts[i] < 0 or parts[i] > 255 then + return false + end + end + + return true + end + + return false +end + +function hostname(val) + if val and val:match("[a-zA-Z0-9_][a-zA-Z0-9_%-%.]*") then + return true -- XXX: ToDo: need better solution + end + + return false +end + +function host(val) + return hostname(val) or ipaddr(val) +end + +function wpakey(val) + if #val == 64 then + return (val:match("^[a-fA-F0-9]+$") ~= nil) + else + return (#val >= 8) and (#val <= 63) + end +end + +function wepkey(val) + if val:sub(1, 2) == "s:" then + val = val:sub(3) + end + + if (#val == 10) or (#val == 26) then + return (val:match("^[a-fA-F0-9]+$") ~= nil) + else + return (#v == 5) or (#v == 13) + end +end + +function string(val) + return true -- Everything qualifies as valid string +end + +function directory( val, seen ) + local s = fs.stat(val) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "dir" then + return true + elseif s.type == "lnk" then + return directory( fs.readlink(val), seen ) + end + end + + return false +end + +function file( val, seen ) + local s = fs.stat(val) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "reg" then + return true + elseif s.type == "lnk" then + return file( fs.readlink(val), seen ) + end + end + + return false +end + +function device( val, seen ) + local s = fs.stat(val) + seen = seen or { } + + if s and not seen[s.ino] then + seen[s.ino] = true + if s.type == "chr" or s.type == "blk" then + return true + elseif s.type == "lnk" then + return device( fs.readlink(val), seen ) + end + end + + return false +end diff --git a/libs/web/luasrc/view/cbi/browser.htm b/libs/web/luasrc/view/cbi/browser.htm new file mode 100644 index 0000000000..3b7b23f5d2 --- /dev/null +++ b/libs/web/luasrc/view/cbi/browser.htm @@ -0,0 +1,23 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<% + local t = require("luci.tools.webadmin") + local v = self:cfgvalue(section) +-%> +<%+cbi/valueheader%> + /> + '<%=self.default_path and ", '"..self.default_path.."'"%>);return false" alt="<%:Search file...%>" title="<%:Search file...%>" src="<%=resource%>/cbi/folder.png" style="vertical-align:bottom" /> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/button.htm b/libs/web/luasrc/view/cbi/button.htm new file mode 100644 index 0000000000..5a5189794a --- /dev/null +++ b/libs/web/luasrc/view/cbi/button.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> + <% if self:cfgvalue(section) ~= false then %> + " type="submit"<%= attr("name", cbid) .. attr("id", cbid) .. attr("value", self.title)%> /> + <% else %> + - + <% end %> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/cell_valuefooter.htm b/libs/web/luasrc/view/cbi/cell_valuefooter.htm new file mode 100644 index 0000000000..c325e49cb4 --- /dev/null +++ b/libs/web/luasrc/view/cbi/cell_valuefooter.htm @@ -0,0 +1,34 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +
">
+ + +<% if #self.deps > 0 then -%> + +<%- end %> \ No newline at end of file diff --git a/libs/web/luasrc/view/cbi/cell_valueheader.htm b/libs/web/luasrc/view/cbi/cell_valueheader.htm new file mode 100644 index 0000000000..0f24f1f764 --- /dev/null +++ b/libs/web/luasrc/view/cbi/cell_valueheader.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + + +
"> diff --git a/libs/web/luasrc/view/cbi/compound.htm b/libs/web/luasrc/view/cbi/compound.htm new file mode 100644 index 0000000000..fbd5a0a073 --- /dev/null +++ b/libs/web/luasrc/view/cbi/compound.htm @@ -0,0 +1,14 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Steven Barth + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%- self:render_children() %> \ No newline at end of file diff --git a/libs/web/luasrc/view/cbi/delegator.htm b/libs/web/luasrc/view/cbi/delegator.htm new file mode 100644 index 0000000000..ed7c6b4ea2 --- /dev/null +++ b/libs/web/luasrc/view/cbi/delegator.htm @@ -0,0 +1,37 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Steven Barth + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%- self.active:render() %> +
+ +<% for _, x in ipairs(self.chain) do %> + +<% end %> +<% if not self.disallow_pageactions then %> +<% if self.allow_finish and not self:get_next(self.current) then %> + +<% elseif self:get_next(self.current) then %> + +<% end %> +<% if self.allow_cancel then %> + +<% end %> +<% if self.allow_reset then %> + +<% end %> +<% if self.allow_back and self:get_prev(self.current) then %> + +<% end %> +<% end %> + +
\ No newline at end of file diff --git a/libs/web/luasrc/view/cbi/dvalue.htm b/libs/web/luasrc/view/cbi/dvalue.htm new file mode 100644 index 0000000000..9745fff4cb --- /dev/null +++ b/libs/web/luasrc/view/cbi/dvalue.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<%+cbi/valueheader%> +<% if self.href then %><% end -%> + <%=pcdata(self:cfgvalue(section) or self.default or "")%> +<%- if self.href then %><%end%> +  +" /> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/dynlist.htm b/libs/web/luasrc/view/cbi/dynlist.htm new file mode 100644 index 0000000000..826e2e698e --- /dev/null +++ b/libs/web/luasrc/view/cbi/dynlist.htm @@ -0,0 +1,52 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008-2010 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> +<% + local vals = self:cfgvalue(section) or {} + for i=1, #vals + 1 do + local val = vals[i] +%> + /> + <% if i <= #vals then %> + " alt="<%:Delete%>" title="<%:Delete%>" src="<%=resource%>/cbi/remove.gif" /> + <% else %> + " alt="<%:Add%>" title="<%:Add%>" src="<%=resource%>/cbi/add.gif" /> + <% end %> + <% if #self.keylist > 0 then -%> + + <% end -%> +<% if i <= #vals then %>
+<% end end %> +<% if self.datatype then -%> + +<% end -%> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/filebrowser.htm b/libs/web/luasrc/view/cbi/filebrowser.htm new file mode 100644 index 0000000000..f82957221c --- /dev/null +++ b/libs/web/luasrc/view/cbi/filebrowser.htm @@ -0,0 +1,123 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + + + + + + Filebrowser - LuCI + + + + + + <% + require("nixio.fs") + require("nixio.util") + require("luci.http") + require("luci.dispatcher") + + local field = luci.http.formvalue('field') + local request = luci.dispatcher.context.path + local path = { '' } + + for i = 3, #request do + if request[i] ~= '..' and #request[i] > 0 then + path[#path+1] = request[i] + end + end + + local filepath = table.concat( path, '/' ) + local filestat = nixio.fs.stat( filepath ) + local baseurl = luci.dispatcher.build_url('admin', 'filebrowser') + + if filestat and filestat.type == "reg" then + table.remove( path, #path ) + filepath = table.concat( path, '/' ) .. '/' + elseif not ( filestat and filestat.type == "dir" ) then + path = { '' } + filepath = '/' + else + filepath = filepath .. '/' + end + + local entries = nixio.util.consume((nixio.fs.dir(filepath))) + -%> +
+ Location: + <% for i, dir in ipairs(path) do %> + <% if i == 1 then %> + (root) + <% elseif next(path, i) then %> + <% baseurl = baseurl .. '/' .. dir %> + / <%=dir%> + <% else %> + <% baseurl = baseurl .. '/' .. dir %> + / <%=dir%> + <% end %> + <% end %> +
+ +
+ +
+
    + <% for _, e in luci.util.vspairs(entries) do + local stat = nixio.fs.stat(filepath..e) + if stat and stat.type == 'dir' then + -%> +
  • + Directory + <%=e%>/ +
  • + <% end end -%> + + <% for _, e in luci.util.vspairs(entries) do + local stat = nixio.fs.stat(filepath..e) + if stat and stat.type ~= 'dir' then + -%> +
  • + File + <%=e%> +
  • + <% end end -%> +
+
+ + diff --git a/libs/web/luasrc/view/cbi/firewall_zonelist.htm b/libs/web/luasrc/view/cbi/firewall_zonelist.htm new file mode 100644 index 0000000000..4f4106b87a --- /dev/null +++ b/libs/web/luasrc/view/cbi/firewall_zonelist.htm @@ -0,0 +1,89 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> + +<%- + local utl = require "luci.util" + local fwm = require "luci.model.firewall" + local nwm = require "luci.model.network" + + local zone, net, iface + local zones = fwm:get_zones() + local value = self:formvalue(section) + if not value or value == "-" then value = self:cfgvalue(section) or self.default end + + local selected = false + local checked = { } + + if value and #value == 0 then + value = nil + elseif type(value) == "table" then + for _, value in ipairs(value) do + checked[value] = true + end + elseif value then + checked[value] = true + end +-%> + +
    + <% + for _, zone in utl.spairs(zones, function(a,b) return (zones[a]:name() < zones[b]:name()) end) do + if zone:name() ~= self.exclude then + selected = selected or (value == zone:name()) + %> +
  • + />   + style="background-color:<%=zone:get_color()%>; padding:0.5em"> + <%=zone:name()%>: + <% + local zempty = true + for _, net in ipairs(zone:get_networks()) do + net = nwm:get_network(net) + if net then + zempty = false + %> +   + <%- if net:name() == self.network then -%> + <%=net:name()%>: + <%- else -%> + <%=net:name()%>: + <%- end -%> + <% + local nempty = true + for _, iface in ipairs(net and net:get_interfaces() or {}) do + nempty = false + %> + style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" /> + <% end %> + <% if nempty then %><%:(no interfaces attached)%><% end %> + + <% end end %> + <% if zempty then %><%:(no interfaces attached)%><% end %> + +
  • + <% end end %> + + <% if self.widget ~= "checkbox" and not self.nocreate then %> +
  • + />   +
    + ><%:unspecified -or- create:%>  + onfocus="document.getElementById('<%=cbid%>_new').checked=true" /> +
    +
  • + <% end %> +
+ +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/footer.htm b/libs/web/luasrc/view/cbi/footer.htm new file mode 100644 index 0000000000..fe5b6881c2 --- /dev/null +++ b/libs/web/luasrc/view/cbi/footer.htm @@ -0,0 +1,29 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + <%- if pageaction then -%> +
+ <% if flow.skip then %> + + <% end %> + <% if not autoapply then%> + + <% end %> + + + +
+ <%- end -%> + +<%+footer%> diff --git a/libs/web/luasrc/view/cbi/full_valuefooter.htm b/libs/web/luasrc/view/cbi/full_valuefooter.htm new file mode 100644 index 0000000000..c069b7f92c --- /dev/null +++ b/libs/web/luasrc/view/cbi/full_valuefooter.htm @@ -0,0 +1,74 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + + <% if self.description and #self.description > 0 then -%> + <% if not luci.util.instanceof( self, luci.cbi.Flag ) or self.orientation == "horizontal" then -%> +
+ <%- end %> +
+ <%:help%> + <%=self.description%> +
+ <%- end %> + <%- if self.title and #self.title > 0 then -%> +
+ <%- end -%> + + + +<% if #self.deps > 0 or #self.subdeps > 0 then -%> + +<%- end %> diff --git a/libs/web/luasrc/view/cbi/full_valueheader.htm b/libs/web/luasrc/view/cbi/full_valueheader.htm new file mode 100644 index 0000000000..ecd4014983 --- /dev/null +++ b/libs/web/luasrc/view/cbi/full_valueheader.htm @@ -0,0 +1,24 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +
"> + <%- if self.title and #self.title > 0 then -%> + +
+ <%- end -%> diff --git a/libs/web/luasrc/view/cbi/fvalue.htm b/libs/web/luasrc/view/cbi/fvalue.htm new file mode 100644 index 0000000000..35ebac6e1c --- /dev/null +++ b/libs/web/luasrc/view/cbi/fvalue.htm @@ -0,0 +1,17 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> + value="1" /> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/header.htm b/libs/web/luasrc/view/cbi/header.htm new file mode 100644 index 0000000000..fd1ab8bd1a --- /dev/null +++ b/libs/web/luasrc/view/cbi/header.htm @@ -0,0 +1,22 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008-2010 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<%+header%> +
+
+ + + +
diff --git a/libs/web/luasrc/view/cbi/lvalue.htm b/libs/web/luasrc/view/cbi/lvalue.htm new file mode 100644 index 0000000000..8c7581a2ca --- /dev/null +++ b/libs/web/luasrc/view/cbi/lvalue.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> +<% if self.widget == "select" then %> + +<% elseif self.widget == "radio" then + local c = 0 + for i, key in pairs(self.keylist) do + c = c + 1 +%> + /> + ><%=self.vallist[i]%> +<% if c == self.size then c = 0 %><% if self.orientation == "horizontal" then %> <% else %>
<% end %> +<% end end %> +<% end %> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/map.htm b/libs/web/luasrc/view/cbi/map.htm new file mode 100644 index 0000000000..be0c37aa77 --- /dev/null +++ b/libs/web/luasrc/view/cbi/map.htm @@ -0,0 +1,63 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +
+ <% if self.title and #self.title > 0 then %>

<%=self.title%>

<% end %> + <% if self.description and #self.description > 0 then %>
<%=self.description%>
<% end %> + <%- if self._apply then -%> +
+ <%:Applying changes%> + + + <%:Loading%> + <%:Waiting for router...%> +
+ <%- end -%> + <%- self:render_children() %> +
+
diff --git a/libs/web/luasrc/view/cbi/mvalue.htm b/libs/web/luasrc/view/cbi/mvalue.htm new file mode 100644 index 0000000000..3812a3f7ef --- /dev/null +++ b/libs/web/luasrc/view/cbi/mvalue.htm @@ -0,0 +1,35 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<% +local v = self:valuelist(section) or {} +%> +<%+cbi/valueheader%> +<% if self.widget == "select" then %> + +<% elseif self.widget == "checkbox" then + local c = 0; + for i, key in pairs(self.keylist) do + c = c + 1 +%> + /> + ><%=self.vallist[i]%>
+<% if c == self.size then c = 0 %>
+<% end end %> +<% end %> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/network_ifacelist.htm b/libs/web/luasrc/view/cbi/network_ifacelist.htm new file mode 100644 index 0000000000..2f98218170 --- /dev/null +++ b/libs/web/luasrc/view/cbi/network_ifacelist.htm @@ -0,0 +1,54 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> + +<%- + local utl = require "luci.util" + local net = require "luci.model.network" + + local iface + local ifaces = net:get_interfaces() + local value = (self:formvalue(section) or self.default or "") + local checked = { } + + if value and #value > 0 then + if type(value) == "table" then value = table.concat(value, " ") end + for value in value:gmatch("%S+") do + checked[value] = true + end + else + local n = self.network and net:get_network(self.network) + if n then + local i + for _, i in ipairs(n:get_interfaces()) do + checked[i:name()] = true + end + end + end +-%> + +
    + <% for _, iface in utl.spairs(ifaces, function(a,b) return (ifaces[a]:type() < ifaces[b]:type()) end) do + if not self.nobridges or not iface:is_bridge() then %> +
  • + " onclick="cbi_d_update(this.id)" onchange="cbi_d_update(this.id)"<%=attr("type", self.widget or "radio") .. attr("id", cbid .. "." .. iface:name()) .. attr("name", cbid) .. attr("value", iface:name()) .. ifattr(checked[iface:name()], "checked", "checked")%> />   + > + .png" /> + <%=iface:get_i18n()%><% local n = iface:get_network(); if n then %> (<%=n:name()%>)<% end %> + +
  • + <% end end %> +
+ +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/network_netlist.htm b/libs/web/luasrc/view/cbi/network_netlist.htm new file mode 100644 index 0000000000..c47b3a70ee --- /dev/null +++ b/libs/web/luasrc/view/cbi/network_netlist.htm @@ -0,0 +1,61 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> + +<%- + local utl = require "luci.util" + local nwm = require "luci.model.network" + + local net, iface + local networks = nwm:get_networks() + local value = self:formvalue(section) + + if not value or value == "-" then + value = self:cfgvalue(section) or self.default + end +-%> + +
    + <% for _, net in utl.spairs(networks, function(a,b) return (networks[a]:name() < networks[b]:name()) end) do + if net:name() ~= "loopback" then %> +
  • + />   + > +  <%=net:name()%>: + <% + local empty = true + for _, iface in ipairs(net:get_interfaces()) do + if not iface:is_bridge() then + empty = false + %> + style="width:16px; height:16px; vertical-align:middle" src="<%=resource%>/icons/<%=iface:type()%><%=iface:is_up() and "" or "_disabled"%>.png" /> + <% end end %> + <% if empty then %><%:(no interfaces attached)%><% end %> + + +
  • + <% end end %> + + <% if self.widget ~= "checkbox" and not self.nocreate then %> +
  • + />   +
    + ><%:unspecified -or- create:%>  + onfocus="document.getElementById('<%=cbid%>_new').checked=true" /> +
    +
  • + <% end %> +
+ +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/nsection.htm b/libs/web/luasrc/view/cbi/nsection.htm new file mode 100644 index 0000000000..1d231c5424 --- /dev/null +++ b/libs/web/luasrc/view/cbi/nsection.htm @@ -0,0 +1,46 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008-2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<% if self:cfgvalue(self.section) then section = self.section %> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> + <% if self.description and #self.description > 0 then -%> +
<%=self.description%>
+ <%- end %> + <% if self.addremove then -%> +
+ +
+ <%- end %> + <%+cbi/tabmenu%> +
+ <%+cbi/ucisection%> +
+
+
+<% elseif self.addremove then %> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+ +
+ <%- end %> +<% end %> + diff --git a/libs/web/luasrc/view/cbi/nullsection.htm b/libs/web/luasrc/view/cbi/nullsection.htm new file mode 100644 index 0000000000..f1c715b408 --- /dev/null +++ b/libs/web/luasrc/view/cbi/nullsection.htm @@ -0,0 +1,32 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
+ <% self:render_children(1, scope or {}) %> +
+
+
+ <%- + if type(self.hidden) == "table" then + for k, v in pairs(self.hidden) do + -%> + + <%- + end + end + %> diff --git a/libs/web/luasrc/view/cbi/simpleform.htm b/libs/web/luasrc/view/cbi/simpleform.htm new file mode 100644 index 0000000000..9c40f8290c --- /dev/null +++ b/libs/web/luasrc/view/cbi/simpleform.htm @@ -0,0 +1,66 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<% if not self.embedded then %> + +
+ + +
+<% end %> +
+ <% if self.title and #self.title > 0 then %>

<%=self.title%>

<% end %> + <% if self.description and #self.description > 0 then %>
<%=self.description%>
<% end %> + <% self:render_children() %> +
+
+<%- if self.message then %> +
<%=self.message%>
+<%- end %> +<%- if self.errmessage then %> +
<%=self.errmessage%>
+<%- end %> +<% if not self.embedded then %> +
+<%- + if type(self.hidden) == "table" then + for k, v in pairs(self.hidden) do +-%> + +<%- + end + end +%> +<%- if self.flow and self.flow.skip then %> + +<% end %> +<%- if self.submit ~= false then %> + +<% end %> +<%- if self.reset ~= false then %> + +<% end %> +<%- if self.cancel ~= false and self.on_cancel then %> + +<% end %> + +
+ +<% end %> diff --git a/libs/web/luasrc/view/cbi/tabcontainer.htm b/libs/web/luasrc/view/cbi/tabcontainer.htm new file mode 100644 index 0000000000..9b2c7980a8 --- /dev/null +++ b/libs/web/luasrc/view/cbi/tabcontainer.htm @@ -0,0 +1,21 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<% for tab, data in pairs(self.tabs) do %> +
style="display:none"<% end %>> + <% if data.description then %>
<%=data.description%>
<% end %> + <% self:render_tab(tab, section, scope or {}) %> +
+ +<% end %> diff --git a/libs/web/luasrc/view/cbi/tabmenu.htm b/libs/web/luasrc/view/cbi/tabmenu.htm new file mode 100644 index 0000000000..7648fe011b --- /dev/null +++ b/libs/web/luasrc/view/cbi/tabmenu.htm @@ -0,0 +1,27 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<%- if self.tabs then %> +
    + <%- self.selected_tab = luci.http.formvalue("tab." .. self.config .. "." .. section) %> + <%- for _, tab in ipairs(self.tab_names) do if #self.tabs[tab].childs > 0 then %> + + <%- if not self.selected_tab then self.selected_tab = tab end %> +
  • + <%=self.tabs[tab].title%> + <% if tab == self.selected_tab then %><% end %> +
  • + <% end end -%> +
+<% end -%> diff --git a/libs/web/luasrc/view/cbi/tblsection.htm b/libs/web/luasrc/view/cbi/tblsection.htm new file mode 100644 index 0000000000..0224610674 --- /dev/null +++ b/libs/web/luasrc/view/cbi/tblsection.htm @@ -0,0 +1,135 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%- +local rowcnt = 1 +function rowstyle() + rowcnt = rowcnt + 1 + return (rowcnt % 2) + 1 +end +-%> + + +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+
+ <%- local count = 0 -%> + + + <%- if not self.anonymous then -%> + <%- if self.sectionhead then -%> + + <%- else -%> + + <%- end -%> + <%- end -%> + <%- for i, k in pairs(self.children) do if not k.optional then -%> + + <%- count = count + 1; end; end; if self.extedit or self.addremove then -%> + + <%- count = count + 1; end -%> + + + <%- if not self.anonymous then -%> + <%- if self.sectiondesc then -%> + + <%- else -%> + + <%- end -%> + <%- end -%> + <%- for i, k in pairs(self.children) do if not k.optional then -%> + + <%- end; end; if self.extedit or self.addremove then -%> + + <%- end -%> + + <%- local isempty = true + for i, k in ipairs(self:cfgsections()) do + section = k + isempty = false + scope = { valueheader = "cbi/cell_valueheader", valuefooter = "cbi/cell_valuefooter" } + -%> + + <% if not self.anonymous then -%> + + <%- end %> + + + <%- + for k, node in ipairs(self.children) do + if not node.optional then + node:render(section, scope or {}) + end + end + -%> + + <%- if self.extedit or self.addremove then -%> + + <%- end -%> + + <%- end -%> + + <%- if isempty then -%> + + + + <%- end -%> +
<%=self.sectionhead%>  + <%- if k.titleref then -%><%- end -%> + <%-=k.title-%> + <%- if k.titleref then -%><%- end -%> +  
<%=self.sectiondesc%><%=k.description%>

<%=(type(self.sectiontitle) == "function") and self:sectiontitle(section) or k%>

+ <%- if self.extedit then -%> + + <%=self.extedit:format(section)%> + <%- elseif type(self.extedit) == "function" then -%> + <%=self:extedit(section)%> + <%- end -%> + " title="<%:Edit%>"><%:Edit%> + <%- end; if self.addremove then %> + + <%- end -%> +

<%:This section contains no values yet%>
+ + <% if self.error then %> +
+
    <% for _, c in pairs(self.error) do for _, e in ipairs(c) do -%> +
  • <%=pcdata(e):gsub("\n","
    ")%>
  • + <%- end end %>
+
+ <% end %> + + <%- if self.addremove then -%> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.anonymous then %> + + <% else %> + <% if self.invalid_cts then -%>
<% end %> + + + <% if self.invalid_cts then -%> +
<%:Invalid%>
+ <%- end %> + <% end %> +
+ <%- end %> + <%- end -%> +
+
+ diff --git a/libs/web/luasrc/view/cbi/tsection.htm b/libs/web/luasrc/view/cbi/tsection.htm new file mode 100644 index 0000000000..0fa285c160 --- /dev/null +++ b/libs/web/luasrc/view/cbi/tsection.htm @@ -0,0 +1,62 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +
+ <% if self.title and #self.title > 0 then -%> + <%=self.title%> + <%- end %> +
<%=self.description%>
+ <% local isempty = true for i, k in ipairs(self:cfgsections()) do -%> + <% if self.addremove then -%> +
+ +
+ <%- end %> + + <%- section = k; isempty = false -%> + + <% if not self.anonymous then -%> +

<%=section:upper()%>

+ <%- end %> + + <%+cbi/tabmenu%> + +
+ <%+cbi/ucisection%> +
+
+ <%- end %> + + <% if isempty then -%> + <%:This section contains no values yet%>

+ <%- end %> + + <% if self.addremove then -%> + <% if self.template_addremove then include(self.template_addremove) else -%> +
+ <% if self.anonymous then -%> + + <%- else -%> + <% if self.invalid_cts then -%>
<% end %> + + + <% if self.invalid_cts then -%> +
<%:Invalid%>
+ <%- end %> + <%- end %> +
+ <%- end %> + <%- end %> +
diff --git a/libs/web/luasrc/view/cbi/tvalue.htm b/libs/web/luasrc/view/cbi/tvalue.htm new file mode 100644 index 0000000000..b628c5c524 --- /dev/null +++ b/libs/web/luasrc/view/cbi/tvalue.htm @@ -0,0 +1,19 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> + +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/ucisection.htm b/libs/web/luasrc/view/cbi/ucisection.htm new file mode 100644 index 0000000000..db32c90439 --- /dev/null +++ b/libs/web/luasrc/view/cbi/ucisection.htm @@ -0,0 +1,90 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<%- + if type(self.hidden) == "table" then + for k, v in pairs(self.hidden) do +-%> + +<%- + end + end +%> + +<% if self.tabs then %> + <%+cbi/tabcontainer%> +<% else %> + <% self:render_children(section, scope or {}) %> +<% end %> + +<% if self.error and self.error[section] then -%> +
+
    <% for _, e in ipairs(self.error[section]) do -%> +
  • + <%- if e == "invalid" then -%> + <%:One or more fields contain invalid values!%> + <%- elseif e == "missing" then -%> + <%:One or more required fields have no value!%> + <%- else -%> + <%=pcdata(e)%> + <%- end -%> +
  • + <%- end %>
+
+<%- end %> + +<% if self.optionals[section] and #self.optionals[section] > 0 or self.dynamic then %> +
+ <% if self.dynamic then %> + + <% if self.optionals[section] and #self.optionals[section] > 0 then %> + + <% end %> + <% else %> + + + <% end %> + +
+<% end %> diff --git a/libs/web/luasrc/view/cbi/upload.htm b/libs/web/luasrc/view/cbi/upload.htm new file mode 100644 index 0000000000..f5baa33fe4 --- /dev/null +++ b/libs/web/luasrc/view/cbi/upload.htm @@ -0,0 +1,29 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008-2009 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<% + local t = require("luci.tools.webadmin") + local v = self:cfgvalue(section) + local s = v and nixio.fs.stat(v) +-%> +<%+cbi/valueheader%> + <% if s then %> + <%:Uploaded File%> (<%=t.byte_format(s.size)%>) + /> + " alt="<%:Replace entry%>" title="<%:Replace entry%>" src="<%=resource%>/cbi/reload.gif" /> + <% else %> + /> + <% end %> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/value.htm b/libs/web/luasrc/view/cbi/value.htm new file mode 100644 index 0000000000..a7b49de7ff --- /dev/null +++ b/libs/web/luasrc/view/cbi/value.htm @@ -0,0 +1,44 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008-2010 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> +<%+cbi/valueheader%> + /> + <% if self.password then %><% end %> + <% if #self.keylist > 0 or self.datatype then -%> + + <% end -%> +<%+cbi/valuefooter%> diff --git a/libs/web/luasrc/view/cbi/valuefooter.htm b/libs/web/luasrc/view/cbi/valuefooter.htm new file mode 100644 index 0000000000..a65c7a3874 --- /dev/null +++ b/libs/web/luasrc/view/cbi/valuefooter.htm @@ -0,0 +1,16 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<% include( valuefooter or "cbi/full_valuefooter" ) %> diff --git a/libs/web/luasrc/view/cbi/valueheader.htm b/libs/web/luasrc/view/cbi/valueheader.htm new file mode 100644 index 0000000000..f3da909e66 --- /dev/null +++ b/libs/web/luasrc/view/cbi/valueheader.htm @@ -0,0 +1,16 @@ +<%# +LuCI - Lua Configuration Interface +Copyright 2008 Steven Barth +Copyright 2008 Jo-Philipp Wich + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +$Id$ + +-%> + +<% include( valueheader or "cbi/full_valueheader" ) %> -- cgit v1.2.3