3c768ab7623e03885eb8a3b735541d7b1a0d2e5e
[project/luci.git] / libs / web / luasrc / cbi / datatypes.lua
1 --[[
2
3 LuCI - Configuration Bind Interface - Datatype Tests
4 (c) 2010 Jo-Philipp Wich <xm@subsignal.org>
5
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
12 $Id$
13
14 ]]--
15
16 local fs = require "nixio.fs"
17 local ip = require "luci.ip"
18 local math = require "math"
19 local util = require "luci.util"
20 local tonumber, type = tonumber, type
21
22
23 module "luci.cbi.datatypes"
24
25
26 function bool(val)
27 if val == "1" or val == "yes" or val == "on" or val == "true" then
28 return true
29 elseif val == "0" or val == "no" or val == "off" or val == "false" then
30 return true
31 elseif val == "" or val == nil then
32 return true
33 end
34
35 return false
36 end
37
38 function uinteger(val)
39 local n = tonumber(val)
40 if n ~= nil and math.floor(n) == n and n >= 0 then
41 return true
42 end
43
44 return false
45 end
46
47 function integer(val)
48 local n = tonumber(val)
49 if n ~= nil and math.floor(n) == n then
50 return true
51 end
52
53 return false
54 end
55
56 function ufloat(val)
57 local n = tonumber(val)
58 return ( n ~= nil and n >= 0 )
59 end
60
61 function float(val)
62 return ( tonumber(val) ~= nil )
63 end
64
65 function ipaddr(val)
66 return ip4addr(val) or ip6addr(val)
67 end
68
69 function neg_ipaddr(v)
70 if type(v) == "string" then
71 v = v:gsub("^%s*!", "")
72 end
73 return v and ipaddr(v)
74 end
75
76 function ip4addr(val)
77 if val then
78 return ip.IPv4(val) and true or false
79 end
80
81 return false
82 end
83
84 function neg_ip4addr(v)
85 if type(v) == "string" then
86 v = v:gsub("^%s*!", "")
87 end
88 return v and ip4addr(v)
89 end
90
91 function ip4prefix(val)
92 val = tonumber(val)
93 return ( val and val >= 0 and val <= 32 )
94 end
95
96 function ip6addr(val)
97 if val then
98 return ip.IPv6(val) and true or false
99 end
100
101 return false
102 end
103
104 function ip6prefix(val)
105 val = tonumber(val)
106 return ( val and val >= 0 and val <= 128 )
107 end
108
109 function port(val)
110 val = tonumber(val)
111 return ( val and val >= 0 and val <= 65535 )
112 end
113
114 function portrange(val)
115 local p1, p2 = val:match("^(%d+)%-(%d+)$")
116 if p1 and p2 and port(p1) and port(p2) then
117 return true
118 else
119 return port(val)
120 end
121 end
122
123 function macaddr(val)
124 if val and val:match(
125 "^[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+:" ..
126 "[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+$"
127 ) then
128 local parts = util.split( val, ":" )
129
130 for i = 1,6 do
131 parts[i] = tonumber( parts[i], 16 )
132 if parts[i] < 0 or parts[i] > 255 then
133 return false
134 end
135 end
136
137 return true
138 end
139
140 return false
141 end
142
143 function hostname(val)
144 if val and (#val < 254) and (
145 val:match("^[a-zA-Z0-9]+$") or
146 val:match("^[a-zA-Z0-9][a-zA-Z0-9%-%.]*[a-zA-Z0-9]$")
147 ) then
148 return true
149 end
150 return false
151 end
152
153 function host(val)
154 return hostname(val) or ipaddr(val)
155 end
156
157 function wpakey(val)
158 if #val == 64 then
159 return (val:match("^[a-fA-F0-9]+$") ~= nil)
160 else
161 return (#val >= 8) and (#val <= 63)
162 end
163 end
164
165 function wepkey(val)
166 if val:sub(1, 2) == "s:" then
167 val = val:sub(3)
168 end
169
170 if (#val == 10) or (#val == 26) then
171 return (val:match("^[a-fA-F0-9]+$") ~= nil)
172 else
173 return (#val == 5) or (#val == 13)
174 end
175 end
176
177 function string(val)
178 return true -- Everything qualifies as valid string
179 end
180
181 function directory( val, seen )
182 local s = fs.stat(val)
183 seen = seen or { }
184
185 if s and not seen[s.ino] then
186 seen[s.ino] = true
187 if s.type == "dir" then
188 return true
189 elseif s.type == "lnk" then
190 return directory( fs.readlink(val), seen )
191 end
192 end
193
194 return false
195 end
196
197 function file( val, seen )
198 local s = fs.stat(val)
199 seen = seen or { }
200
201 if s and not seen[s.ino] then
202 seen[s.ino] = true
203 if s.type == "reg" then
204 return true
205 elseif s.type == "lnk" then
206 return file( fs.readlink(val), seen )
207 end
208 end
209
210 return false
211 end
212
213 function device( val, seen )
214 local s = fs.stat(val)
215 seen = seen or { }
216
217 if s and not seen[s.ino] then
218 seen[s.ino] = true
219 if s.type == "chr" or s.type == "blk" then
220 return true
221 elseif s.type == "lnk" then
222 return device( fs.readlink(val), seen )
223 end
224 end
225
226 return false
227 end
228
229 function uciname(val)
230 return (val:match("^[a-zA-Z0-9_]+$") ~= nil)
231 end
232
233 function neg_network_ip4addr(val)
234 if type(v) == "string" then
235 v = v:gsub("^%s*!", "")
236 return (uciname(v) or ip4addr(v))
237 end
238 end
239
240 function range(val, min, max)
241 val = tonumber(val)
242 min = tonumber(min)
243 max = tonumber(max)
244
245 if val ~= nil and min ~= nil and max ~= nil then
246 return ((val >= min) and (val <= max))
247 end
248
249 return false
250 end
251
252 function min(val, min)
253 val = tonumber(val)
254 min = tonumber(min)
255
256 if val ~= nil and min ~= nil then
257 return (val >= min)
258 end
259
260 return false
261 end
262
263 function max(val, max)
264 val = tonumber(val)
265 max = tonumber(max)
266
267 if val ~= nil and max ~= nil then
268 return (val <= max)
269 end
270
271 return false
272 end
273
274 function neg(val, what)
275 if what and type(_M[what]) == "function" then
276 return _M[what](val:gsub("^%s*!%s*", ""))
277 end
278
279 return false
280 end