libs/web: add missing parts of previous commit
[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 network(val)
158 return uciname(val) or host(val)
159 end
160
161 function wpakey(val)
162 if #val == 64 then
163 return (val:match("^[a-fA-F0-9]+$") ~= nil)
164 else
165 return (#val >= 8) and (#val <= 63)
166 end
167 end
168
169 function wepkey(val)
170 if val:sub(1, 2) == "s:" then
171 val = val:sub(3)
172 end
173
174 if (#val == 10) or (#val == 26) then
175 return (val:match("^[a-fA-F0-9]+$") ~= nil)
176 else
177 return (#val == 5) or (#val == 13)
178 end
179 end
180
181 function string(val)
182 return true -- Everything qualifies as valid string
183 end
184
185 function directory( val, seen )
186 local s = fs.stat(val)
187 seen = seen or { }
188
189 if s and not seen[s.ino] then
190 seen[s.ino] = true
191 if s.type == "dir" then
192 return true
193 elseif s.type == "lnk" then
194 return directory( fs.readlink(val), seen )
195 end
196 end
197
198 return false
199 end
200
201 function file( val, seen )
202 local s = fs.stat(val)
203 seen = seen or { }
204
205 if s and not seen[s.ino] then
206 seen[s.ino] = true
207 if s.type == "reg" then
208 return true
209 elseif s.type == "lnk" then
210 return file( fs.readlink(val), seen )
211 end
212 end
213
214 return false
215 end
216
217 function device( val, seen )
218 local s = fs.stat(val)
219 seen = seen or { }
220
221 if s and not seen[s.ino] then
222 seen[s.ino] = true
223 if s.type == "chr" or s.type == "blk" then
224 return true
225 elseif s.type == "lnk" then
226 return device( fs.readlink(val), seen )
227 end
228 end
229
230 return false
231 end
232
233 function uciname(val)
234 return (val:match("^[a-zA-Z0-9_]+$") ~= nil)
235 end
236
237 function neg_network_ip4addr(val)
238 if type(v) == "string" then
239 v = v:gsub("^%s*!", "")
240 return (uciname(v) or ip4addr(v))
241 end
242 end
243
244 function range(val, min, max)
245 val = tonumber(val)
246 min = tonumber(min)
247 max = tonumber(max)
248
249 if val ~= nil and min ~= nil and max ~= nil then
250 return ((val >= min) and (val <= max))
251 end
252
253 return false
254 end
255
256 function min(val, min)
257 val = tonumber(val)
258 min = tonumber(min)
259
260 if val ~= nil and min ~= nil then
261 return (val >= min)
262 end
263
264 return false
265 end
266
267 function max(val, max)
268 val = tonumber(val)
269 max = tonumber(max)
270
271 if val ~= nil and max ~= nil then
272 return (val <= max)
273 end
274
275 return false
276 end
277
278 function neg(val, what)
279 if what and type(_M[what]) == "function" then
280 return _M[what](val:gsub("^%s*!%s*", ""))
281 end
282
283 return false
284 end