libs: drop uvl and uvldoc

This commit is contained in:
Jo-Philipp Wich 2011-01-02 19:26:37 +00:00
parent 800a263049
commit 052f65950c
18 changed files with 0 additions and 3060 deletions

View file

@ -1,2 +0,0 @@
include ../../build/config.mk
include ../../build/module.mk

File diff suppressed because it is too large Load diff

View file

@ -1,187 +0,0 @@
--[[
UCI Validation Layer - Datatype Tests
(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$
]]--
local fs = require "nixio.fs"
local ip = require "luci.ip"
local math = require "math"
local util = require "luci.util"
local tonumber = tonumber
module "luci.uvl.datatypes"
function boolean( 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 integer( 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 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

View file

@ -1,196 +0,0 @@
--[[
UCI Validation Layer - Dependency 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$
]]--
local uvl = require "luci.uvl"
local ERR = require "luci.uvl.errors".error
local util = require "luci.util"
local table = require "table"
local type, unpack = type, unpack
local ipairs, pairs = ipairs, pairs
module "luci.uvl.dependencies"
function _parse_reference( r, c, s, o )
local ref = { }
local vars = {
config = c,
section = s,
option = o
}
for v in r:gmatch("[^.]+") do
ref[#ref+1] = (v:gsub( "%$(.+)", vars ))
end
if #ref < 2 then
table.insert(ref, 1, s or '$section')
end
if #ref < 3 then
table.insert(ref, 1, c or '$config')
end
return ref
end
function _serialize_dependency( dep, v )
local str
for k, v in util.spairs( dep,
function(a,b)
a = ( type(dep[a]) ~= "boolean" and "_" or "" ) .. a
b = ( type(dep[b]) ~= "boolean" and "_" or "" ) .. b
return a < b
end
) do
str = ( str and str .. " and " or "" ) .. k ..
( type(v) ~= "boolean" and "=" .. v or "" )
end
return str
end
function check( self, object, nodeps )
local derr = ERR('DEPENDENCY', object)
if not self.depseen[object:cid()] then
self.depseen[object:cid()] = true
else
return false, derr:child(ERR('DEP_RECURSIVE', object))
end
if object:scheme('depends') then
local ok = true
local valid = false
for _, dep in ipairs(object:scheme('depends')) do
local subcondition = true
for k, v in pairs(dep) do
-- XXX: better error
local ref = _parse_reference( k, unpack(object.cref) )
if not ref then
return false, derr:child(ERR('SME_BADDEP',object,k))
end
local option = uvl.option( self, object.c, unpack(ref) )
valid, err = self:_validate_option( option, true )
if valid then
if not (
( type(v) == "boolean" and option:value() ) or
( ref[3] and option:value() ) == v
) then
subcondition = false
local depstr = _serialize_dependency( dep, v )
derr:child(
type(v) == "boolean"
and ERR('DEP_NOVALUE', option, depstr)
or ERR('DEP_NOTEQUAL', option, {depstr, v})
)
break
end
else
subcondition = false
local depstr = _serialize_dependency( dep, v )
derr:child(ERR('DEP_NOTVALID', option, depstr):child(err))
break
end
end
if subcondition then
ok = true
break
else
ok = false
end
end
if not ok then
return false, derr
end
else
return true
end
if object:scheme("type") == "enum" and
object:scheme("enum_depends")[object:value()]
then
local ok = true
local valid = false
local enum = object:enum()
local eerr = ERR('DEP_BADENUM', enum)
for _, dep in ipairs(enum:scheme('enum_depends')[object:value()]) do
local subcondition = true
for k, v in pairs(dep) do
-- XXX: better error
local ref = _parse_reference( k, unpack(object.cref) )
if not ref then
return false, derr:child(eerr:child(ERR('SME_BADDEP',enum,k)))
end
local option = luci.uvl.option( self, object.c, unpack(ref) )
valid, err = self:_validate_option( option, true )
if valid then
if not (
( type(v) == "boolean" and object.config[ref[2]][ref[3]] ) or
( ref[3] and object:config() ) == v
) then
subcondition = false
local depstr = _serialize_dependency( dep, v )
eerr:child(
type(v) == "boolean"
and ERR('DEP_NOVALUE', option, depstr)
or ERR('DEP_NOTEQUAL', option, {depstr, v})
)
break
end
else
subcondition = false
local depstr = _serialize_dependency( dep, v )
eerr:child(ERR('DEP_NOTVALID', option, depstr):child(err))
break
end
end
if subcondition then
return true
else
ok = false
end
end
if not ok then
return false, derr:child(eerr)
end
end
return true
end

View file

@ -1,188 +0,0 @@
--[[
UCI Validation Layer - Error handling
(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$
]]--
local uci = require "luci.model.uci"
local uvl = require "luci.uvl"
local util = require "luci.util"
local string = require "string"
local luci, tonumber, unpack, ipairs, type =
luci, tonumber, unpack, ipairs, type
module "luci.uvl.errors"
ERRCODES = {
UCILOAD = 'Unable to load config "%p": %1',
SCHEME = 'Error in scheme "%p":\n%c',
CONFIG = 'Error in config "%p":\n%c',
SECTION = 'Error in section "%i" (%I):\n%c',
OPTION = 'Error in option "%i" (%I):\n%c',
REFERENCE = 'Option "%i" has invalid reference specification %1:\n%c',
DEPENDENCY = 'In dependency check for %t "%i":\n%c',
SME_FIND = 'Can not find scheme "%p" in "%1"',
SME_READ = 'Can not access file "%1"',
SME_REQFLD = 'Missing required scheme field "%1" in "%i"',
SME_INVREF = 'Illegal reference "%1" to an anonymous section',
SME_BADREF = 'Malformed reference in "%1"',
SME_BADDEP = 'Malformed dependency specification "%1" in "%i"',
SME_BADVAL = 'Malformed validator specification "%1" in "%i"',
SME_ERRVAL = 'External validator "%1" failed: %2',
SME_VBADPACK = 'Variable "%o" in scheme "%p" references unknown package "%1"',
SME_VBADSECT = 'Variable "%o" in scheme "%p" references unknown section "%1"',
SME_EBADPACK = 'Enum "%v" in scheme "%p" references unknown package "%1"',
SME_EBADSECT = 'Enum "%v" in scheme "%p" references unknown section "%1"',
SME_EBADOPT = 'Enum "%v" in scheme "%p" references unknown option "%1"',
SME_EBADTYPE = 'Enum "%v" in scheme "%p" references non-enum option "%I"',
SME_EBADDEF = 'Enum "%v" in scheme "%p" redeclares the default value of "%I"',
SECT_UNKNOWN = 'Section "%i" (%I) not found in scheme',
SECT_REQUIRED = 'Required section "%p.%S" not found in config',
SECT_UNIQUE = 'Unique section "%p.%S" occurs multiple times in config',
SECT_NAMED = 'The section of type "%p.%S" is stored anonymously in config but must be named',
SECT_NOTFOUND = 'Section "%p.%s" not found in config',
OPT_UNKNOWN = 'Option "%i" (%I) not found in scheme',
OPT_REQUIRED = 'Required option "%i" has no value',
OPT_BADVALUE = 'Value "%1" of option "%i" is not defined in enum %2',
OPT_INVVALUE = 'Value "%1" of option "%i" does not validate as datatype "%2"',
OPT_NOTLIST = 'Option "%i" is defined as list but stored as plain value',
OPT_DATATYPE = 'Option "%i" has unknown datatype "%1"',
OPT_NOTFOUND = 'Option "%p.%s.%o" not found in config',
OPT_RANGE = 'Option "%p.%s.%o" is not within the specified range',
DEP_NOTEQUAL = 'Dependency (%1) failed:\nOption "%i" is not eqal "%2"',
DEP_NOVALUE = 'Dependency (%1) failed:\nOption "%i" has no value',
DEP_NOTVALID = 'Dependency (%1) failed:\n%c',
DEP_RECURSIVE = 'Recursive dependency for option "%i" detected',
DEP_BADENUM = 'In dependency check for enum value "%i":\n%c'
}
function i18n(key)
if luci.i18n then
return luci.i18n.translate(key)
else
return key
end
end
error = util.class()
function error.__init__(self, code, pso, args)
self.code = code
self.args = ( type(args) == "table" and args or { args } )
if util.instanceof( pso, uvl.uvlitem ) then
self.stype = pso.sref[2]
self.package, self.section, self.option, self.value = unpack(pso.cref)
self.object = pso
self.value = self.value or ( pso.value and pso:value() )
else
pso = ( type(pso) == "table" and pso or { pso } )
if pso[2] then
local uci = uci.cursor()
self.stype = uci:get(pso[1], pso[2]) or pso[2]
end
self.package, self.section, self.option, self.value = unpack(pso)
end
end
function error.child(self, err)
if not self.childs then
self.childs = { err }
else
self.childs[#self.childs+1] = err
end
return self
end
function error.string(self,pad)
pad = pad or " "
local str = i18n(ERRCODES[self.code] or self.code)
:gsub("\n", "\n"..pad)
:gsub("%%i", self:cid())
:gsub("%%I", self:sid())
:gsub("%%p", self.package or '(nil)')
:gsub("%%s", self.section or '(nil)')
:gsub("%%S", self.stype or '(nil)')
:gsub("%%o", self.option or '(nil)')
:gsub("%%v", self.value or '(nil)')
:gsub("%%t", self.object and self.object:type() or '(nil)' )
:gsub("%%T", self.object and self.object:title() or '(nil)' )
:gsub("%%([1-9])", function(n) return self.args[tonumber(n)] or '(nil)' end)
:gsub("%%c",
function()
local s = ""
for _, err in ipairs(self.childs or {}) do
s = s .. err:string(pad.." ") .. "\n" .. pad
end
return s
end
)
return (str:gsub("%s+$",""))
end
function error.cid(self)
return self.object and self.object:cid() or self.package ..
( self.section and '.' .. self.section or '' ) ..
( self.option and '.' .. self.option or '' ) ..
( self.value and '.' .. self.value or '' )
end
function error.sid(self)
return self.object and self.object:sid() or self.package ..
( self.stype and '.' .. self.stype or '' ) ..
( self.option and '.' .. self.option or '' ) ..
( self.value and '.' .. self.value or '' )
end
function error.is(self, code)
if self.code == code then
return true
elseif self.childs then
for _, c in ipairs(self.childs) do
if c:is(code) then
return true
end
end
end
return false
end
function error.is_all(self, ...)
local codes = { ... }
if util.contains(codes, self.code) then
return true
else
local equal = false
for _, c in ipairs(self.childs) do
if c.childs then
equal = c:is_all(...)
else
equal = util.contains(codes, c.code)
end
end
return equal
end
end

View file

@ -1,72 +0,0 @@
--[[
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$
]]--
local os = require "os"
local fs = require "nixio.fs"
local sys = require "luci.sys"
local ERR = require "luci.uvl.errors".error
local ipairs, unpack, type, tostring = ipairs, unpack, type, tostring
module "luci.uvl.validation"
function _exec( bin, args )
local cmd, output = "", nil
for _, v in ipairs({ bin, unpack(args) }) do
cmd = cmd .. ("%q " % v):gsub("([%$`])","\\%1")
end
local tmpfile = "/tmp/uvl" .. sys.uniqueid(8)
local retval = os.execute( cmd .. " 1>" .. tmpfile .. " 2>" .. tmpfile )
if fs.access(tmpfile) then
output = fs.readfile(tmpfile)
fs.unlink(tmpfile)
end
return retval, output
end
function check( self, object )
if object:scheme('validators') then
for _, val in ipairs(object:scheme('validators')) do
local ok, err = false, nil
local values = object:value()
values = type(values) == "table" and values or { values }
local args = {
object:scheme('type'), object:scheme('datatype'),
object.cref[1], object.cref[2], object.cref[3] or '',
unpack(values)
}
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('SME_ERRVAL', object, {tostring(val), err})
end
end
end
return true, nil
end

View file

@ -1,403 +0,0 @@
# UVL - Reference-Spec
# This is a meta scheme defining the format of uci schemes.
# $Id$
package schema
#-------------------------------------------------------------------------------
# Central package definition
#
# config package
# option ...
#-------------------------------------------------------------------------------
# Section definition (schema.@package)
config section
option name 'package'
option title 'Definition of uci package'
option package 'schema'
option required false
option named false
option unique true
option dynamic false
# Section title (schema.@package.title)
config variable
option name 'title'
option title 'Title of the defined package'
option section 'schema.package'
option type 'variable'
option datatype 'string'
option required false
# Section description (schema.@package.description)
config variable
option name 'description'
option title 'Description of the defined package'
option section 'schema.package'
option type 'lazylist'
option datatype 'string'
option required false
#-------------------------------------------------------------------------------
# Central section definition
#
# config section
# option ...
#-------------------------------------------------------------------------------
# Section definition (schema.@section)
config section
option name 'section'
option title 'Definition of uci section'
option package 'schema'
option required false
option named false
option unique false
option dynamic false
# Section name (schema.@section.name)
config variable
option name 'name'
option title 'Name of the defined section'
option section 'schema.section'
option type 'variable'
option datatype 'string'
option required true
# Section package (schema.@section.package)
config variable
option name 'package'
option title 'Parent package of the defined section'
option section 'schema.section'
option type 'variable'
option datatype 'string'
option required true
# Section title (schema.@section.title)
config variable
option name 'title'
option title 'Title of the defined section'
option section 'schema.section'
option type 'variable'
option datatype 'string'
option required false
# Section description (schema.@section.description)
config variable
option name 'description'
option title 'Description of the defined section'
option section 'schema.section'
option type 'lazylist'
option datatype 'string'
option required false
# Section dependencies (schema.@section.depends)
config variable
option name 'depends'
option title 'List of dependencies within and between defined sections'
option section 'schema.section'
option type 'lazylist'
option datatype 'string'
option required false
# Section required flag (schema.@section.required)
config variable
option name 'required'
option title 'Specify whether at least one instance of this section type must be defined in config'
option section 'schema.section'
option type 'variable'
option datatype 'boolean'
option required false
# Section unique flag (schema.@section.unique)
config variable
option name 'unique'
option title 'Specify whether only one instance of this section type is allowed in config'
option section 'schema.section'
option type 'variable'
option datatype 'boolean'
option required false
# Section named flag (schema.@section.named)
config variable
option name 'named'
option title 'Specify whether sections of this type must have a name set (are not anonymous)'
option section 'schema.section'
option type 'variable'
option datatype 'boolean'
option required false
# Section dynamic flag (schema.@section.dynamic)
config variable
option name 'dynamic'
option title 'Specify whether sections of this type may contain arbitary, not specified options'
option section 'schema.section'
option type 'variable'
option datatype 'boolean'
option required false
#-------------------------------------------------------------------------------
# Central variable definition
#
# config variable
# option ...
#-------------------------------------------------------------------------------
# Variable definition (schema.@variable)
config section
option name 'variable'
option title 'Definition of uci variable'
option package 'schema'
option required false
option named false
option unique false
option dynamic false
# Variable name (schema.@variable.name)
config variable
option name 'name'
option title 'Name of the defined variable'
option section 'schema.variable'
option type 'variable'
option datatype 'string'
option required true
# Variable section (schema.@variable.section)
config variable
option name 'section'
option title 'Parent section of the defined variable'
option section 'schema.variable'
option type 'variable'
option datatype 'string'
option required true
# Variable title (schema.@variable.title)
config variable
option name 'title'
option title 'Title of the defined variable'
option section 'schema.variable'
option type 'variable'
option datatype 'string'
option required false
# Variable description (schema.@variable.description)
config variable
option name 'description'
option title 'Description of the defined variable'
option section 'schema.variable'
option type 'lazylist'
option datatype 'string'
option required false
# Variable dependencies (schema.@variable.depends)
config variable
option name 'depends'
option title 'List of dependencies between defined variables'
option section 'schema.variable'
option type 'lazylist'
option datatype 'string'
option required false
# Variable required flag (schema.@variable.required)
config variable
option name 'required'
option title 'Specify whether this variable must be set in config'
option section 'schema.variable'
option type 'variable'
option datatype 'boolean'
option required false
# Variable multiple values flag (schema.@variable.multival)
config variable
option name 'multival'
option title 'Specify whether this variable may contain multiple values separated by space'
option section 'schema.variable'
option type 'variable'
option datatype 'boolean'
option required false
# Variable type (schema.@variable.type)
config variable
option name 'type'
option title 'Type of this variable'
option section 'schema.variable'
option type 'enum'
option datatype 'string'
option required false
# Plain variable type (schema.@variable.type=variable)
config enum
option value 'variable'
option title 'This is a plain variable'
option variable 'schema.variable.type'
# Enum variable type (schema.@variable.type=enum)
config enum
option value 'enum'
option title 'This is a enum variable'
option variable 'schema.variable.type'
# List variable type (schema.@variable.type=list)
config enum
option value 'list'
option title 'This is a list variable'
option variable 'schema.variable.type'
# List-or-Option variable type (schema.@variable.type=lazylist)
config enum
option value 'lazylist'
option title 'This is a list or option variable'
option variable 'schema.variable.type'
# Reference variable type (schema.@variable.type=reference)
config enum
option value 'reference'
option title 'This is a reference (valueof) variable'
option variable 'schema.variable.type'
# Variable datatype (schema.@variable.datatype)
config variable
option name 'datatype'
option title 'Datatype of this variable'
option section 'schema.variable'
option type 'variable'
option datatype 'string'
option required false
# Variable default value (schema.@variable.default)
config variable
option name 'default'
option title 'Default value of this variable'
option section 'schema.variable'
option type 'variable'
option datatype 'string'
option required false
# Variable minimum length (schema.@variable.minlength)
config variable
option name 'minlength'
option title 'Minimum length of this variable'
option section 'schema.variable'
option type 'variable'
option datatype 'uint'
option required false
# Variable maximum length (schema.@variable.minlength)
config variable
option name 'maxlength'
option title 'Maximum length of this variable'
option section 'schema.variable'
option type 'variable'
option datatype 'uint'
option required false
# Variable minimum value (schema.@variable.minlength)
config variable
option name 'minimum'
option title 'Minimum value of this variable'
option section 'schema.variable'
option type 'variable'
option datatype 'integer'
option required false
# Variable maximum value (schema.@variable.minlength)
config variable
option name 'maximum'
option title 'Maximum value of this variable'
option section 'schema.variable'
option type 'variable'
option datatype 'integer'
option required false
# Variable validators (schema.@variable.validator)
config variable
option name 'validator'
option title 'Datatype of this variable'
option section 'schema.variable'
option type 'lazylist'
option datatype 'string'
option required false
# Variable value references (schema.@variable.valueof)
config variable
option name 'valueof'
option title 'Reference to section or option to read values from'
option section 'schema.variable'
option type 'lazylist'
option datatype 'string'
option required false
#-------------------------------------------------------------------------------
# Central enum definition
#
# config enum
# option ...
#-------------------------------------------------------------------------------
# Enum definition (schema.@enum)
config section
option name 'enum'
option title 'Definition of uci enum value'
option package 'schema'
option required false
option named false
option unique false
option dynamic false
# Enum value (schema.@enum.value)
config variable
option name 'value'
option title 'Value of the defined enum value'
option section 'schema.enum'
option type 'variable'
option datatype 'string'
option required true
# Enum variable (schema.@enum.variable)
config variable
option name 'variable'
option title 'Parent variable of the defined enum value'
option section 'schema.enum'
option type 'variable'
option datatype 'string'
option required true
# Enum value title (schema.@enum.title)
config variable
option name 'title'
option title 'Title of the defined enum value'
option section 'schema.enum'
option type 'variable'
option datatype 'string'
option required false
# Enum value description (schema.@enum.description)
config variable
option name 'description'
option title 'Description of the defined enum value'
option section 'schema.enum'
option type 'lazylist'
option datatype 'string'
option required false
# Enum value dependencies (schema.@enum.depends)
config variable
option name 'depends'
option title 'List of dependencies on defined variables'
option section 'schema.enum'
option type 'lazylist'
option datatype 'string'
option required false
# Enum value default flag (schema.@enum.default)
config variable
option name 'default'
option title 'Specify whether this value is the default value of the parent enum'
option section 'schema.enum'
option type 'variable'
option datatype 'boolean'
option required false

View file

@ -1,241 +0,0 @@
#!/usr/bin/lua
--[[
UCI Validation Layer - Command Line Utility
(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$
]]--
require("luci.uvl")
require("luci.util")
function getopt( arg, options )
options = options or ""
local tab = {}
local args = {}
for k, v in ipairs(arg) do
if v:sub(1, 2) == "--" then
local x = v:find( "=", 1, true )
if x then
tab[ v:sub( 3, x-1 ) ] = v:sub( x+1 )
else
tab[ v:sub( 3 ) ] = true
end
elseif v:sub( 1, 1 ) == "-" then
local y = 2
local l = #v
local jopt
while ( y <= l ) do
jopt = v:sub( y, y )
if options:find( jopt, 1, true ) then
if y < l then
tab[ jopt ] = v:sub( y+1 )
y = l
else
tab[ jopt ] = arg[ k + 1 ]
arg[ k + 1 ] = ""
end
else
tab[ jopt ] = true
end
y = y + 1
end
elseif #v > 0 then
table.insert(args, v)
end
end
return tab, args
end
function genspec(conf)
require("luci.model.uci")
require("luci.uvl.datatypes")
local uci = luci.model.uci.cursor()
local ok, err = uci:load(conf)
if not ok then
print("Can not load config:", err)
os.exit(1)
else
local function _guess_datatype(v)
if type(v) == "table" then v = v[1] end
for _, type in ipairs({
"boolean", "integer", "float", "ip4addr", "ip6addr",
"macaddr", "directory", "file"
}) do
if luci.uvl.datatypes[type](v) then
return type
end
end
return "string"
end
local co = uci:get_all(conf)
local ct = { }
local ca = { }
local so = { }
local to = { }
-- count section types
for _, section in pairs(co) do
ct[section['.type']] = ( ct[section['.type']] or 0 ) + 1
ca[section['.type']] = section['.anonymous']
so[section['.type']] = so[section['.type']] or { }
to[section['.type']] = to[section['.type']] or { }
for option, value in pairs(section) do
if option:sub(1,1) ~= "." then
so[section['.type']][option] = _guess_datatype(value)
to[section['.type']][option] = ( type(value) == "table" and "list" or "variable" )
end
end
end
-- package name
print( "package %s" % conf )
-- write section schemes
for type, count in luci.util.kspairs(ct) do
print( "\nconfig section" )
print( "\toption name '%s'" % type )
print( "\toption title 'Section %s'" % type )
print( "\toption package '%s'"% conf )
print( "\toption named %s" % ( ca[type] and 'false' or 'true' ) )
print( "\toption unique %s" % ( ct[type] > 1 and 'false' or ( ca[type] and 'false' or 'true' ) ) )
print( "\toption dynamic false" )
print( "\toption required false" )
-- write option schemes
for opt, val in luci.util.kspairs(so[type]) do
print( "\nconfig variable" )
print( "\toption name '%s'" % opt )
print( "\toption title 'Option %s'" % opt )
print( "\toption section '%s.%s'" %{ conf, type } )
print( "\toption datatype '%s'" % so[type][opt] )
if to[type][opt] ~= "variable" then
print( "\toption type '%s'" % to[type][opt] )
end
end
print("")
end
end
end
local options, arguments = getopt( arg )
if #arguments ~= 2 or options.help then
print([=[
uvl - UCI Validation Layer
$Id$
(c) 2008 Jo-Philipp Wich, Steven Barth
Usage:
uvl --help
uvl [--silent] [--schemedir=DIR] [--configdir=DIR] [--no-strict-sections] \
[--no-strict-options] [--no-strict-validators] [--no-strict-lists] \
{verify|verify-scheme|genspec} config[.section[.option]]
Options:
--help
Display this help message.
--silent
Don't produce any output.
--schemedir=DIR
Use DIR as scheme directory.
--configdir=DIR
Use DIR as config directory.
--no-strict-sections
Don't treat sections found in config but not in scheme as error.
--no-strict-options
Don't treat options found in config but not in scheme as error.
--no-strict-validators
Don't invalidate config if an external validator fails.
--no-strict-lists
Don't invalidate lists that are stored options.
Actions:
verify
Validate given configuration, section or option.
verify-scheme
Validate given scheme against the reference meta scheme.
genspec
Generate a scheme skeleton from given configuration.
]=])
os.exit(255)
elseif arguments[1] == "verify" or arguments[1] == "verify-scheme" then
luci.uvl.STRICT_UNKNOWN_SECTIONS =
( not options['no-strict-sections'] and true or false )
luci.uvl.STRICT_UNKNOWN_OPTIONS =
( not options['no-strict-options'] and true or false )
luci.uvl.STRICT_EXTERNAL_VALIDATORS =
( not options['no-strict-validators'] and true or false )
luci.uvl.STRICT_LIST_TYPE =
( not options['no-strict-lists'] and true or false )
local uvl = luci.uvl.UVL(
type(options.schemedir) == "string" and options.schemedir,
type(options.configdir) == "string" and options.configdir
)
local cso = luci.util.split( arguments[2], "." )
local ok, err
if arguments[1] == "verify-scheme" then
uvl:read_scheme( 'schema', cso[1] )
local uci = uvl.uci.cursor(
type(options.configdir) == "string"
and options.configdir or uvl.schemedir .. '/default'
)
ok, err = uvl:validate_config( cso[1], uci:get_all(cso[1]) )
if err then err.code = luci.uvl.errors.ERR_SCHEME end
else
ok, err = uvl:validate( unpack(cso) )
end
if ok then
if not options.silent then
print( string.format(
'%s "%s" validates fine!',
( arguments[1] == "verify-scheme" and "Scheme" or
( #cso == 1 and "Config" or
( #cso == 2 and "Section" or "Option" ) ) ),
table.concat(cso, ".")
) )
end
os.exit( 0 )
else
if not options.silent then print( err and err:string() or "Unknown error" ) end
os.exit( 1 )
end
else
genspec( arguments[2] )
end

View file

@ -1,23 +0,0 @@
#!/usr/bin/lua
if arg[1] then
require("luci.util")
require("luci.uvl")
require("nixio.fs")
local uvl = luci.uvl.UVL()
local scheme, err = uvl:get_scheme( arg[1] )
if scheme then
nixio.fs.writefile(
"%s/bytecode/%s.lua" %{ uvl.schemedir, arg[1] },
luci.util.get_bytecode(scheme)
)
elseif err then
print("Error:", err:string())
else
print("Error: Can not find scheme:", arg[1])
end
else
print( "Usage: uvlc <scheme>" )
end

View file

@ -1,2 +0,0 @@
include ../../build/config.mk
include ../../build/module.mk

View file

@ -1,11 +0,0 @@
<div id="copy">
<hr />
generated on <%=require "os".date("%c")%> with <a href="http://luci.freifunk-halle.net"><abbr title="Lua Configuration Interface">LuCI</abbr> UVLDoc</a> - written by Steven Barth and Jo-Philipp Wich
</div>
</div>
<div class="clear">&nbsp;</div>
</body>
</html>

View file

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" type="text/css" href="uvldoc.css" />
<meta http-equiv="content-type" content="application/xhtml+xml; charset=utf-8" />
<title><% if title then %><%=title%> - <% end %>LuCI UVLDoc</title>
</head>
<body>
<div id="menu">
<%+menu.xml%>
</div>
<div id="content">

View file

@ -1,12 +0,0 @@
<%+header.xml%>
<h1 class="index-title">UCI Documentation</h1>
<h3 class="index-subtitle">Schemes</h3>
<table class="index">
<% for k, v in luci.util.kspairs(self.schemes) do %>
<tr>
<th><a href="<%=self:_scheme_filename(k)%>"><%=k%></a></th>
<td><%=self.schemes[k].title%></td>
</tr>
<% end %>
</table>
<%+footer.xml%>

View file

@ -1,22 +0,0 @@
<div class="menu-title">LuCI UVLDoc</div>
<ul class="menu-index">
<li<%-if not scheme then%> class="menu-active"<%-end-%>>
<a href="<%=self:_index_filename()%>">Index</a>
</li>
</ul>
<div class="menu-title">Schemes</div>
<ul class="menu-index">
<% for k, v in luci.util.kspairs(self.schemes) do %>
<li<%-if scheme == k then%> class="menu-active"<%-end-%>>
<a href="<%=self:_scheme_filename(k)%>"><%=k%></a>
<%-if scheme == k then-%>
<ul>
<%-for k2, v2 in luci.util.kspairs(v.sections) do%>
<li<%-if k2 == section then%> class="menu-active"<%-end-%>><a href="<%=self:_section_filename(k, k2)%>"><%=k2%></a></li>
<%end-%>
</ul>
<%-end%>
</li>
<%-end%>
</ul>

View file

@ -1,16 +0,0 @@
<%- title = scheme -%>
<%+header.xml%>
<h1 class="section-title"><%=scheme-%>
<%-if package.title then%><dfn> - <%=package.title%></dfn><%end%></h1>
<div class="scheme-description"><%=package.description%></div>
<h3 class="scheme-title">Sections:</h3>
<table class="scheme-index">
<% for k, v in luci.util.kspairs(package.sections) do %>
<tr>
<th><a href="<%=self:_section_filename(scheme, k)%>"><%=k%></a></th>
<td><%=v.title%></td>
</tr>
<% end %>
</table>
<%+footer.xml%>

View file

@ -1,198 +0,0 @@
<%- title = scheme .. "." .. type -%>
<%+header.xml%>
<%
local table = require "table"
types = {
list = "List",
variable = "Variable",
lazylist = "Mixed",
enum = "Enumerator",
reference = "Reference"
}
datatypes = {
boolean = "Boolean",
string = "String",
uint = "Unsigned Integer",
integer = "Integer",
float = "Real Number",
ipaddr = "IP-Address",
ip4addr = "IPv4-Address",
ip6addr = "IPv6-Address",
ip4prefix = "IPv4-Prefix",
ip6prefix = "IPv6-Prefix",
hostname = "Hostname",
host = "Host (Hostname or IP-Address)",
directory = "Filesystem path (to directory)",
file = "Filesystem path (to file)",
macaddr = "MAC-Address",
port = "Port",
portrange = "Single Port or Portrange (First-Last)"
}
function _parse_ref( r )
local k, v, h = r:match("([^.]+)%.([^.]+)%.([^.]+)")
if not k then
k, v = r:match("([^.]+)%.([^.]+)")
end
if k then
if h then
return self:_variable_target(k, v, h), true
else
return self:_section_filename(k, v)
end
end
end
function _parse_dep( r, c, s, o )
local ref = { }
local vars = {
config = c,
section = s,
option = o
}
for v in r:gmatch("[^.]+") do
ref[#ref+1] = (v:gsub( "%$(.+)", vars ))
end
if #ref < 2 then
table.insert(ref, 1, s or '$section')
end
if #ref < 3 then
table.insert(ref, 1, c or '$config')
end
return self:_variable_target(unpack(ref))
end
%>
<a name="top"></a>
<h1 class="section-title"><%=scheme-%>
<%-if package.title then%><dfn> - <%=package.title%></dfn><%end%></h1>
<h2 class="section-subtitle"><%=type-%>
<%-if section.title then%><dfn> - <%=section.title%></dfn><%end%></h2>
<div class="section-description"><%=section.description%></div>
<h3 class="section-attributes">Attributes:</h3>
<ul class="section-attributes-index">
<%-
if section.required then %>
<li class="section-attributes-required">required: <dfn>A section of this type is required.</dfn></li>
<% end
if section.unique then %>
<li class="section-attributes-unique">unique: <dfn>There can be only one section of this type.</dfn></li>
<%- else -%>
<li class="section-attributes-multiple">multiple: <dfn>There can be more than one section of this type.</dfn></li>
<% end
if section.dynamic then %>
<li class="section-attributes-dynamic">dynamic: <dfn>Sections of this type may contain user-defined options.</dfn></li>
<% end
if section.named then %>
<li class="section-attributes-named">named: <dfn>Sections of this type require a name.</dfn></li>
<% end -%>
</ul>
<% if section.depends then %>
<h3 class="section-depends">Requirements (one of):</h3>
<ul class="section-depends-index">
<% for i, d in ipairs(section.depends) do
local nf = false%>
<li>
<% for k2, v in luci.util.kspairs(d) do
local t = _parse_dep(k2, scheme, type)
%>
<% if nf then %>and<% end %>
<%if t then%><a href="<%=t%>"><%end%><%=k2%><%if t then%></a><%end%><%if v~=true then%>=<%=v%><%end%>
<% nf = true
end %>
</li>
<% end %>
</ul>
<% end %>
<h3 class="section-variables">Variable Overview:</h3>
<table class="section-variables-index">
<% for k, v in luci.util.kspairs(package.variables[type]) do
if v.required then%>
<tr class="section-variable-required">
<th><a href="#variable.<%=k%>"><%=k%></a></th>
<td><%=v.title%></td>
</tr>
<% end end
for k, v in luci.util.kspairs(package.variables[type]) do
if not v.required then%>
<tr class="section-variable-mixed">
<th><a href="#variable.<%=k%>"><%=k%></a></th>
<td><%=v.title%></td>
</tr>
<% end end %>
</table>
<h3 class="section-variables">Options:</h3>
<%-
for i=0, 1 do
for k, v in luci.util.kspairs(package.variables[type]) do
if (i==0) == v.required then
%>
<hr />
<div class="variable-documentation">
<a name="variable.<%=k%>"></a>
<h4 class="variable-title"><%=k-%>
<%-if v.title then%><dfn> - <%=v.title%></dfn><%end%></h4>
<div class="variable-declaration">
<div class="variable-description"><%=v.description%></div>
<h5 class="variable-attributes">Attributes:</h5>
<ul class="varaible-attributes-index">
<% if v.required then %>
<li class="variable-attribute-required"><strong>required</strong></li>
<% end %>
<li class="variable-attribute-type"><strong>Type:</strong> <%=types[v.type] or v.type%></li>
<li class="variable-attribute-datatype"><strong>Datatype:</strong> <%=datatypes[v.datatype] or v.datatype%></li>
<% if v.multival then %>
<li class="variable-attribute-multiple"><strong>multiple values:</strong> space-separated</li>
<% end %>
</ul>
<% if v.depends then %>
<h5 class="variable-depends">Dependencies (one of):</h5>
<ul class="variable-depends-index">
<% for i, d in ipairs(v.depends) do
local nf = false %>
<li>
<% for k2, v in luci.util.kspairs(d) do
local t = _parse_dep(k2, scheme, type, k)
%>
<% if nf then %>and<% end %>
<%if t then%><a href="<%=t%>"><%end%><%=k2%><%if t then%></a><%end%><%if v~=true then%>=<%=v%><%end%>
<% nf = true
end %>
</li>
<% end %>
</ul>
<% end %>
<% if v.type == "enum" then %>
<h5 class="variable-values">Possible Values:</h5>
<ul class="variable-values-index">
<% for k, d in pairs(v.values) do %>
<li><strong><%=k%></strong><%if d then%> (<%=d%>)<%end%></li>
<% end %>
</ul>
<% elseif v.type == "reference" then %>
<h5 class="variable-reference">Value references:</h5>
<ul class="variable-reference-index">
<% for k, d in ipairs(v.valueof) do %>
<li>
<% local t, x = _parse_ref(d)
if t then %><%=x and "Value of" or "Section of type"%> <a href="<%=t%>"><% end %>
<%=d%>
<% if t then%></a><% end %>
</li>
<% end %>
</ul>
<% end %>
</div>
<a href="#top">&#8657;</a>
</div>
<% end end end -%>
<%+footer.xml%>

View file

@ -1,135 +0,0 @@
body {
font-family: sans-serif;
font-size: 0.85em;
color: #101010;
}
h1, h2, h3, h4, h5, h6 {
margin-top: 0;
font-weight: bold;
}
h1 {
font-size: 1.5em;
}
h2 {
font-size: 1.4em;
}
h3 {
font-size: 1.2em;
}
h4 {
font-size: 1.1em;
}
h5 {
font-size: 1.0em;
}
dfn {
font-weight: normal;
font-size: 0.9em;
}
table {
border-collapse: collapse;
}
tr, td, th {
border: 1px solid #e0e0ff;
padding: 3px;
}
th {
background-color: #f0f0ff;
text-align: left;
}
hr {
border: none;
background-color: #cccccc;
height: 1px;
}
ul, li {
margin-top: 0;
}
div.clear {
clear: both;
}
div.variable-declaration {
padding-left: 2em;
}
div.variable-description {
margin-bottom: 1em;
}
h3.section-variables {
margin-top: 2em;
}
h4.variable-title {
margin-bottom: 0;
}
div#menu {
float: left;
background-color: #f0f0ff;
margin: 0;
padding: 0;
border: 1px solid #e0e0ff;
width: 11.5em;
}
#menu ul {
list-style-type: none;
margin-bottom: 0.5em;
padding-left: 1em;
}
#menu ul li {
margin-left: 0;
}
div.menu-title {
background-color: #e0e0ff;
color: #000000;
font-weight: bold;
padding: 2px;
}
div#content {
margin-top: 0;
padding-top: 0;
margin-left: 12.5em;
}
div#copy {
margin-top: 2.5em;
font-size: 0.7em;
text-align: center;
font-size: bold;
}
a:link {
font-weight: bold;
color: #004080;
text-decoration: none;
}
a:visited {
font-weight:bold;
color: #006699;
text-decoration: none;
}
a:hover {
text-decoration:underline;
}

View file

@ -1,124 +0,0 @@
--[[
LuCI - Lua Configuration Interface
Copyright 2008 Steven Barth <steven@midlink.org>
Copyright 2008 Jo-Philipp Wich <xm@leipzig.freifunk.net>
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 io = require "io"
local fs = require "nixio.fs"
local uvl = require "luci.uvl"
local util = require "luci.util"
local ltn12 = require "luci.ltn12"
local template = require "luci.template"
local ipairs, getfenv, pairs, require, unpack = ipairs, getfenv, pairs, require, unpack
local luci = luci
module "luci.uvldoc.renderer"
Generator = util.class()
function Generator.__init__(self, schemes, output, uvlpath)
self.names = schemes
self.output = output or "doc"
self.schemes = {}
self.uvl = uvl.UVL(uvlpath)
self.extension = ".xml"
self.additionals = {"uvldoc.css"}
self.sourcedir = util.libpath() .. "/uvldoc/proto/xhtml/"
end
function Generator.make(self)
for i, scheme in ipairs(self.names) do
self.schemes[scheme] = self.uvl:get_scheme(scheme)
end
fs.mkdir(self.output)
for i, file in ipairs(self.additionals) do
fs.datacopy(self.sourcedir .. file, self.output .. "/" .. file)
end
template.compiler_mode = "memory"
template.viewdir = self.sourcedir
template.context.viewns = {
include = function(name) template.Template(name):render(getfenv(2)) end,
pairs = pairs,
ipairs = ipairs,
unpack = unpack,
luci = luci,
require = require
}
self:_make_index()
for scheme, package in pairs(self.schemes) do
self:_make_package(scheme)
for type, section in pairs(package.sections) do
self:_make_section(scheme, type)
end
end
end
function Generator._make_index(self)
local t = template.Template("index.xml")
local sink = ltn12.sink.file(
io.open(self.output .. "/" .. self:_index_filename(), "w")
)
t:render({self = self, write = sink})
sink()
end
function Generator._make_package(self, scheme)
local t = template.Template("scheme.xml")
local sink = ltn12.sink.file(
io.open(self.output .. "/" .. self:_scheme_filename(scheme), "w")
)
t:render({self = self, package = self.schemes[scheme], scheme = scheme, write = sink})
sink()
end
function Generator._make_section(self, scheme, section)
local t = template.Template("section.xml")
local sink = ltn12.sink.file(
io.open(self.output .. "/" .. self:_section_filename(scheme, section), "w")
)
local pkg = self.schemes[scheme]
t:render({self = self, package = pkg,
scheme = scheme, type=section, section=pkg.sections[section],
write = sink})
sink()
end
function Generator._index_filename(self)
return "index%s" % self.extension
end
function Generator._scheme_filename(self, scheme)
return "scheme.%s%s" % {scheme, self.extension}
end
function Generator._section_filename(self, scheme, section)
if self.schemes[scheme] and self.schemes[scheme].sections[section] then
return "section.%s.%s%s" % {scheme, section, self.extension}
end
end
function Generator._variable_target(self, scheme, section, variable)
if self.schemes[scheme] and self.schemes[scheme].variables[section] and
self.schemes[scheme].variables[section][variable] then
return "section.%s.%s%s#variable.%s" % {scheme, section, self.extension, variable}
end
end