* luci/libs: uvl: add support for external validation commands, various cleanups
This commit is contained in:
parent
ed5c3eacf0
commit
1d08361bea
4 changed files with 102 additions and 26 deletions
|
@ -21,15 +21,16 @@ require("luci.util")
|
||||||
require("luci.model.uci")
|
require("luci.model.uci")
|
||||||
require("luci.uvl.loghelper")
|
require("luci.uvl.loghelper")
|
||||||
require("luci.uvl.datatypes")
|
require("luci.uvl.datatypes")
|
||||||
--require("luci.uvl.validation")
|
require("luci.uvl.validation")
|
||||||
require("luci.uvl.dependencies")
|
require("luci.uvl.dependencies")
|
||||||
|
|
||||||
TYPE_SECTION = 0x01
|
TYPE_SECTION = 0x01
|
||||||
TYPE_VARIABLE = 0x02
|
TYPE_VARIABLE = 0x02
|
||||||
TYPE_ENUM = 0x03
|
TYPE_ENUM = 0x03
|
||||||
|
|
||||||
STRICT_UNKNOWN_SECTIONS = true
|
STRICT_UNKNOWN_SECTIONS = true
|
||||||
STRICT_UNKNOWN_OPTIONS = true
|
STRICT_UNKNOWN_OPTIONS = true
|
||||||
|
STRICT_EXTERNAL_VALIDATORS = true
|
||||||
|
|
||||||
|
|
||||||
local default_schemedir = "/etc/scheme"
|
local default_schemedir = "/etc/scheme"
|
||||||
|
@ -242,6 +243,11 @@ function UVL._validate_option( self, option, nodeps )
|
||||||
if not nodeps then
|
if not nodeps then
|
||||||
return luci.uvl.dependencies.check( self, option )
|
return luci.uvl.dependencies.check( self, option )
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local ok, err = luci.uvl.validation.check( self, option )
|
||||||
|
if not ok and STRICT_EXTERNAL_VALIDATORS then
|
||||||
|
return false, self.log.validator_error( option, err )
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return true, nil
|
return true, nil
|
||||||
|
@ -353,6 +359,10 @@ function UVL._read_scheme_parts( self, scheme, schemes )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
s.dynamic = s.dynamic or false
|
||||||
|
s.unique = s.unique or false
|
||||||
|
s.required = s.required or false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -402,6 +412,7 @@ function UVL._read_scheme_parts( self, scheme, schemes )
|
||||||
end
|
end
|
||||||
|
|
||||||
t.type = t.type or "variable"
|
t.type = t.type or "variable"
|
||||||
|
t.datatype = t.datatype or "string"
|
||||||
t.required = t.required or false
|
t.required = t.required or false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -485,22 +496,24 @@ end
|
||||||
|
|
||||||
-- Read a validator specification
|
-- Read a validator specification
|
||||||
function UVL._read_validator( self, value, validators )
|
function UVL._read_validator( self, value, validators )
|
||||||
local validator
|
if value then
|
||||||
|
local validator
|
||||||
|
|
||||||
if value and value:match("/") and self.datatypes.file(value) then
|
if value:match("^exec:") then
|
||||||
validator = value
|
validator = value:gsub("^exec:","")
|
||||||
else
|
elseif value:match("^lua:") then
|
||||||
validator = self:_resolve_function( value )
|
validator = self:_resolve_function( (value:gsub("^lua:","") ) )
|
||||||
end
|
|
||||||
|
|
||||||
if validator then
|
|
||||||
if not validators then
|
|
||||||
validators = { validator }
|
|
||||||
else
|
|
||||||
table.insert( validators, validator )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return validators
|
if validator then
|
||||||
|
if not validators then
|
||||||
|
validators = { validator }
|
||||||
|
else
|
||||||
|
table.insert( validators, validator )
|
||||||
|
end
|
||||||
|
|
||||||
|
return validators
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -16,15 +16,6 @@ $Id$
|
||||||
|
|
||||||
module( "luci.uvl.dependencies", package.seeall )
|
module( "luci.uvl.dependencies", package.seeall )
|
||||||
|
|
||||||
local function _assert( condition, fmt, ... )
|
|
||||||
if not condition then
|
|
||||||
return assert( nil, string.format( fmt, ... ) )
|
|
||||||
else
|
|
||||||
return condition
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
function _parse_reference( r, c, s, o )
|
function _parse_reference( r, c, s, o )
|
||||||
local ref = { }
|
local ref = { }
|
||||||
local vars = {
|
local vars = {
|
||||||
|
|
|
@ -30,6 +30,13 @@ function section_error( section, message )
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function validator_error( option, message )
|
||||||
|
return string.format(
|
||||||
|
'External validator in option "%s" failed:\n%s',
|
||||||
|
option:cid(), message or "Unknown error"
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
function dump_dependency( dep, ref, v, e )
|
function dump_dependency( dep, ref, v, e )
|
||||||
local str = nil
|
local str = nil
|
||||||
|
|
||||||
|
@ -46,7 +53,7 @@ function dump_dependency( dep, ref, v, e )
|
||||||
|
|
||||||
str = string.format(
|
str = string.format(
|
||||||
'%s) failed:\n\t%s',
|
'%s) failed:\n\t%s',
|
||||||
str, e or string.format(
|
str, e and e:gsub("\n","\n\t") or string.format(
|
||||||
'Option "%s" %s',
|
'Option "%s" %s',
|
||||||
table.concat( ref, "." ), (
|
table.concat( ref, "." ), (
|
||||||
type(v) == "boolean"
|
type(v) == "boolean"
|
||||||
|
|
65
libs/uvl/luasrc/uvl/validation.lua
Normal file
65
libs/uvl/luasrc/uvl/validation.lua
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
--[[
|
||||||
|
|
||||||
|
UCI Validation Layer - Validation helper
|
||||||
|
(c) 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
|
||||||
|
(c) 2008 Steven Barth <steven@midlink.org>
|
||||||
|
|
||||||
|
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$
|
||||||
|
|
||||||
|
]]--
|
||||||
|
|
||||||
|
module( "luci.uvl.validation", package.seeall )
|
||||||
|
|
||||||
|
require("luci.fs")
|
||||||
|
require("luci.sys")
|
||||||
|
|
||||||
|
|
||||||
|
function _exec( bin, args )
|
||||||
|
local cmd, output = "", nil
|
||||||
|
|
||||||
|
for _, v in ipairs({ bin, unpack(args) }) do
|
||||||
|
cmd = cmd .. string.format("%q ",v):gsub("([%$`])","\\%1")
|
||||||
|
end
|
||||||
|
|
||||||
|
local tmpfile = "/tmp/uvl" .. luci.sys.uniqueid(8)
|
||||||
|
local retval = os.execute( cmd .. " 1>" .. tmpfile .. " 2>" .. tmpfile )
|
||||||
|
|
||||||
|
if luci.fs.access(tmpfile) then
|
||||||
|
output = luci.fs.readfile(tmpfile)
|
||||||
|
luci.fs.unlink(tmpfile)
|
||||||
|
end
|
||||||
|
|
||||||
|
return retval, output
|
||||||
|
end
|
||||||
|
|
||||||
|
function check( self, object )
|
||||||
|
local item = object:option()
|
||||||
|
|
||||||
|
if item.validators then
|
||||||
|
for _, val in ipairs(item.validators) do
|
||||||
|
local ok, err = false, nil
|
||||||
|
local args = {
|
||||||
|
item.type, unpack(object.cref), item.datatype, object:value()
|
||||||
|
}
|
||||||
|
|
||||||
|
if type(val) == "function" then
|
||||||
|
ok, err = val(unpack(args))
|
||||||
|
else
|
||||||
|
ok, err = _exec( val, args )
|
||||||
|
ok = ( ok == 0 )
|
||||||
|
end
|
||||||
|
|
||||||
|
if not ok then
|
||||||
|
return false, err
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
end
|
Loading…
Reference in a new issue