X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;f=libs%2Fuvl%2Fluasrc%2Fuvl.lua;h=7f149cf759a2917c03b43c7baecf49d6ae8bbbee;hb=281c92b1d6fa2065baa7c9e5f5cec926a2ea68e6;hp=35e5f5311dec2f51553dc2236ff92c8c847d979e;hpb=8766b050bd9e6399a75ac8604516631e7562c573;p=project%2Fluci.git diff --git a/libs/uvl/luasrc/uvl.lua b/libs/uvl/luasrc/uvl.lua index 35e5f5311..7f149cf75 100644 --- a/libs/uvl/luasrc/uvl.lua +++ b/libs/uvl/luasrc/uvl.lua @@ -8,7 +8,7 @@ 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 + http://www.apache.org/licenses/LICENSE-2.0 $Id$ @@ -19,15 +19,16 @@ $Id$ -- @class module -- @cstyle instance -local fs = require "luci.fs" +local fs = require "nixio.fs" local uci = require "luci.model.uci" local util = require "luci.util" +local nutil = require "nixio.util" local table = require "table" local string = require "string" local require, pcall, ipairs, pairs = require, pcall, ipairs, pairs local type, error, tonumber, tostring = type, error, tonumber, tostring -local unpack = unpack +local unpack, loadfile = unpack, loadfile module "luci.uvl" @@ -67,11 +68,13 @@ local default_savedir = "/tmp/.uvl" -- @class function -- @name UVL -- @param schemedir Path to the scheme directory (optional) +-- @param configdir Override config directory (optional) -- @return Instance object UVL = util.class() -function UVL.__init__( self, schemedir ) +function UVL.__init__( self, schemedir, configdir ) self.schemedir = schemedir or default_schemedir + self.configdir = configdir self.packages = { } self.beenthere = { } self.depseen = { } @@ -292,6 +295,22 @@ function UVL._validate_option( self, option, nodeps ) end elseif option:scheme() then + if not nodeps then + local ok, err = dependencies.check( self, option ) + if not ok then + if not err:is_all( + ERR.ERR_OPT_REQUIRED, + ERR.ERR_DEP_NOTEQUAL, + ERR.ERR_DEP_NOVALUE + ) then + option:error(err) + return false, option:errors() + else + return true + end + end + end + if option:scheme('required') and not option:value() then return false, option:error(ERR.OPT_REQUIRED(option)) @@ -334,12 +353,34 @@ function UVL._validate_option( self, option, nodeps ) return false, option:error(ERR.OPT_DATATYPE(option, dt)) end end - end - if not nodeps then - local ok, err = dependencies.check( self, option ) - if not ok then - option:error(err) + val = ( type(val) == "table" and val or { val } ) + for _, v in ipairs(val) do + if option:scheme('minlength') then + if #v < option:scheme('minlength') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + if option:scheme('maxlength') then + if #v > option:scheme('maxlength') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + local w = tonumber(v) + + if option:scheme('minimum') then + if not w or w < option:scheme('minimum') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end + + if option:scheme('maximum') then + if not w or w > option:scheme('maximum') then + return false, option:error(ERR.OPT_RANGE(option)) + end + end end end @@ -363,11 +404,11 @@ function UVL.read_scheme( self, shm, alias ) local bc = "%s/bytecode/%s.lua" %{ self.schemedir, shm } if not fs.access(bc) then - local files = fs.glob(self.schemedir .. '/*/' .. shm) + local files = nutil.consume((fs.glob(self.schemedir .. '/*/' .. shm))) - if files then + if #files > 0 then local ok, err - for i, file in ipairs( files ) do + for _, file in ipairs(files) do if not fs.access(file) then return false, so:error(ERR.SME_READ(so,file)) end @@ -525,8 +566,7 @@ function UVL._parse_section(self, scheme, k, v) s.named = s.named or false end - - -- Step 2: get all variables +-- Step 2: get all variables function UVL._parse_var(self, scheme, k, v) local ok, err = _req( TYPE_OPTION, k, v, { "name", "section" } ) if err then error(scheme:error(err)) end @@ -579,8 +619,13 @@ function UVL._parse_var(self, scheme, k, v) end t.type = "reference" t.values = values + t.valueof = type(v2) == "table" and v2 or {v2} elseif k == "required" then t[k] = _bool(v2) + elseif k == "minlength" or k == "maxlength" or + k == "minimum" or k == "maximum" + then + t[k] = tonumber(v2) else t[k] = t[k] or v2 end @@ -632,8 +677,10 @@ function UVL._parse_enum(self, scheme, k, v) if not t.values then t.values = { [v.value] = v.title or v.value } + t.valuelist = { {value = v.value, title = v.title} } else t.values[v.value] = v.title or v.value + t.valuelist[#t.valuelist + 1] = {value = v.value, title = v.title} end if not t.enum_depends then @@ -662,20 +709,20 @@ end -- Read a dependency specification function UVL._read_dependency( self, values, deps ) - local expr = "%$?[a-zA-Z0-9_]+" + local expr = "%$?[%w_]+" if values then values = ( type(values) == "table" and values or { values } ) for _, value in ipairs(values) do local condition = { } - for val in value:gmatch("[^%s,]+") do - local k, v = val:match("([^%s]+)%s*=%s*([^%s]+)") + for val in value:gmatch("[^,]+") do + local k, e, v = val:match("%s*([%w$_.]+)%s*(=?)%s*(.*)") if k and ( k:match("^"..expr.."%."..expr.."%."..expr.."$") or k:match("^"..expr.."%."..expr.."$") or k:match("^"..expr.."$") ) then - condition[k] = v or true + condition[k] = (e == '=') and v or true else return nil end @@ -810,7 +857,7 @@ function uvlitem.cid(self) local c = self.c if c and c[r[2]] and c[r[2]]['.anonymous'] and c[r[2]]['.index'] then r[2] = '@' .. c[r[2]]['.type'] .. - '[' .. tostring(c[r[2]]['.index']) .. ']' + '[' .. tostring(c[r[2]]['.index']) .. ']' end return table.concat( r, '.' ) end @@ -847,7 +894,7 @@ function uvlitem.config(self, opt) if #self.cref >= 3 then c = c and c[self.cref[3]] or nil end - end + end if c and opt then return c[opt] @@ -902,16 +949,16 @@ function uvlitem.parent(self) end end -function uvlitem._loadconf(self, co, c) +function uvlitem._loadconf(self, co, c, configdir) co = co or self._configcache if not co then local err - co, err = uci.cursor():get_all(c) + co, err = uci.cursor(configdir):get_all(c) if err then self:error(ERR.UCILOAD(self, err)) end - + self._configcache = co end return co @@ -939,7 +986,7 @@ function scheme.__init__(self, scheme, co, c) self.cref = { c } self.sref = { c } - self.c = self:_loadconf(co, c) + self.c = self:_loadconf(co, c, scheme.configdir) self.s = scheme self.t = TYPE_SCHEME end @@ -1003,10 +1050,9 @@ function config.__init__(self, scheme, co, c) if not c then c, co = co, nil end - self.cref = { c } self.sref = { c } - self.c = self:_loadconf(co, c) + self.c = self:_loadconf(co, c, scheme.configdir) self.s = scheme self.t = TYPE_CONFIG end @@ -1054,7 +1100,7 @@ section = util.class(uvlitem) function section.__init__(self, scheme, co, c, s) self.cref = { c, s } self.sref = { c, co and co[s] and co[s]['.type'] or s } - self.c = self:_loadconf(co, c) + self.c = self:_loadconf(co, c, scheme.configdir) self.s = scheme self.t = TYPE_SECTION end @@ -1105,7 +1151,7 @@ option = util.class(uvlitem) function option.__init__(self, scheme, co, c, s, o) self.cref = { c, s, o } self.sref = { c, co and co[s] and co[s]['.type'] or s, o } - self.c = self:_loadconf(co, c) + self.c = self:_loadconf(co, c, scheme.configdir) self.s = scheme self.t = TYPE_OPTION end @@ -1158,7 +1204,7 @@ enum = util.class(option) function enum.__init__(self, scheme, co, c, s, o, v) self.cref = { c, s, o, v } self.sref = { c, co and co[s] and co[s]['.type'] or s, o, v } - self.c = self:_loadconf(co, c) + self.c = self:_loadconf(co, c, scheme.configdir) self.s = scheme self.t = TYPE_ENUM end