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