ebd7e594f7a13ee630f089861656366e66aa6713
1 -- Copyright 2010 Jo-Philipp Wich <jow@openwrt.org>
4 local fs = require "nixio.fs"
5 local ip = require "luci.ip"
6 local math = require "math"
7 local util = require "luci.util"
8 local tonumber, tostring, type, unpack, select = tonumber, tostring, type, unpack, select
11 module "luci.cbi.datatypes"
14 _M['or'] = function(v, ...)
15         local i
16         for i = 1, select('#', ...), 2 do
17                 local f = select(i, ...)
18                 local a = select(i+1, ...)
19                 if type(f) ~= "function" then
20                         if f == v then
21                                 return true
22                         end
23                         i = i - 1
24                 elseif f(v, unpack(a)) then
25                         return true
26                 end
27         end
28         return false
29 end
31 _M['and'] = function(v, ...)
32         local i
33         for i = 1, select('#', ...), 2 do
34                 local f = select(i, ...)
35                 local a = select(i+1, ...)
36                 if type(f) ~= "function" then
37                         if f ~= v then
38                                 return false
39                         end
40                         i = i - 1
41                 elseif not f(v, unpack(a)) then
42                         return false
43                 end
44         end
45         return true
46 end
48 function neg(v, ...)
49         return _M['or'](v:gsub("^%s*!%s*", ""), ...)
50 end
52 function list(v, subvalidator, subargs)
53         if type(subvalidator) ~= "function" then
54                 return false
55         end
56         local token
57         for token in v:gmatch("%S+") do
58                 if not subvalidator(token, unpack(subargs)) then
59                         return false
60                 end
61         end
62         return true
63 end
65 function bool(val)
66         if val == "1" or val == "yes" or val == "on" or val == "true" then
67                 return true
68         elseif val == "0" or val == "no" or val == "off" or val == "false" then
69                 return true
70         elseif val == "" or val == nil then
71                 return true
72         end
74         return false
75 end
77 function uinteger(val)
78         local n = tonumber(val)
79         if n ~= nil and math.floor(n) == n and n >= 0 then
80                 return true
81         end
83         return false
84 end
86 function integer(val)
87         local n = tonumber(val)
88         if n ~= nil and math.floor(n) == n then
89                 return true
90         end
92         return false
93 end
95 function ufloat(val)
96         local n = tonumber(val)
97         return ( n ~= nil and n >= 0 )
98 end
100 function float(val)
101         return ( tonumber(val) ~= nil )
102 end
106 end
109         if val then
110                 return ip.IPv4(val) and true or false
111         end
113         return false
114 end
116 function ip4prefix(val)
117         val = tonumber(val)
118         return ( val and val >= 0 and val <= 32 )
119 end
122         if val then
123                 return ip.IPv6(val) and true or false
124         end
126         return false
127 end
129 function ip6prefix(val)
130         val = tonumber(val)
131         return ( val and val >= 0 and val <= 128 )
132 end
134 function port(val)
135         val = tonumber(val)
136         return ( val and val >= 0 and val <= 65535 )
137 end
139 function portrange(val)
140         local p1, p2 = val:match("^(%d+)%-(%d+)\$")
141         if p1 and p2 and port(p1) and port(p2) then
142                 return true
143         else
144                 return port(val)
145         end
146 end
149         if val and val:match(
150                 "^[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+:" ..
151                  "[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+\$"
152         ) then
153                 local parts = util.split( val, ":" )
155                 for i = 1,6 do
156                         parts[i] = tonumber( parts[i], 16 )
157                         if parts[i] < 0 or parts[i] > 255 then
158                                 return false
159                         end
160                 end
162                 return true
163         end
165         return false
166 end
168 function hostname(val)
169         if val and (#val < 254) and (
170            val:match("^[a-zA-Z_]+\$") or
171            (val:match("^[a-zA-Z0-9_][a-zA-Z0-9_%-%.]*[a-zA-Z0-9]\$") and
172             val:match("[^0-9%.]"))
173         ) then
174                 return true
175         end
176         return false
177 end
179 function host(val)
181 end
183 function network(val)
184         return uciname(val) or host(val)
185 end
187 function wpakey(val)
188         if #val == 64 then
189                 return (val:match("^[a-fA-F0-9]+\$") ~= nil)
190         else
191                 return (#val >= 8) and (#val <= 63)
192         end
193 end
195 function wepkey(val)
196         if val:sub(1, 2) == "s:" then
197                 val = val:sub(3)
198         end
200         if (#val == 10) or (#val == 26) then
201                 return (val:match("^[a-fA-F0-9]+\$") ~= nil)
202         else
203                 return (#val == 5) or (#val == 13)
204         end
205 end
207 function string(val)
208         return true             -- Everything qualifies as valid string
209 end
211 function directory( val, seen )
212         local s = fs.stat(val)
213         seen = seen or { }
215         if s and not seen[s.ino] then
216                 seen[s.ino] = true
217                 if s.type == "dir" then
218                         return true
219                 elseif s.type == "lnk" then
221                 end
222         end
224         return false
225 end
227 function file( val, seen )
228         local s = fs.stat(val)
229         seen = seen or { }
231         if s and not seen[s.ino] then
232                 seen[s.ino] = true
233                 if s.type == "reg" then
234                         return true
235                 elseif s.type == "lnk" then
237                 end
238         end
240         return false
241 end
243 function device( val, seen )
244         local s = fs.stat(val)
245         seen = seen or { }
247         if s and not seen[s.ino] then
248                 seen[s.ino] = true
249                 if s.type == "chr" or s.type == "blk" then
250                         return true
251                 elseif s.type == "lnk" then
253                 end
254         end
256         return false
257 end
259 function uciname(val)
260         return (val:match("^[a-zA-Z0-9_]+\$") ~= nil)
261 end
263 function range(val, min, max)
264         val = tonumber(val)
265         min = tonumber(min)
266         max = tonumber(max)
268         if val ~= nil and min ~= nil and max ~= nil then
269                 return ((val >= min) and (val <= max))
270         end
272         return false
273 end
275 function min(val, min)
276         val = tonumber(val)
277         min = tonumber(min)
279         if val ~= nil and min ~= nil then
280                 return (val >= min)
281         end
283         return false
284 end
286 function max(val, max)
287         val = tonumber(val)
288         max = tonumber(max)
290         if val ~= nil and max ~= nil then
291                 return (val <= max)
292         end
294         return false
295 end
297 function rangelength(val, min, max)
298         val = tostring(val)
299         min = tonumber(min)
300         max = tonumber(max)
302         if val ~= nil and min ~= nil and max ~= nil then
303                 return ((#val >= min) and (#val <= max))
304         end
306         return false
307 end
309 function minlength(val, min)
310         val = tostring(val)
311         min = tonumber(min)
313         if val ~= nil and min ~= nil then
314                 return (#val >= min)
315         end
317         return false
318 end
320 function maxlength(val, max)
321         val = tostring(val)
322         max = tonumber(max)
324         if val ~= nil and max ~= nil then
325                 return (#val <= max)
326         end
328         return false
329 end
331 function phonedigit(val)
332         return (val:match("^[0-9\*#!%.]+\$") ~= nil)
333 end