libs/web: remove neg_ipaddr, neg_ip4addr and neg_network_ip4addr datatypes, can be...
[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 ip4addr(val)
70 if val then
71 return ip.IPv4(val) and true or false
72 end
73
74 return false
75 end
76
77 function ip4prefix(val)
78 val = tonumber(val)
79 return ( val and val >= 0 and val <= 32 )
80 end
81
82 function ip6addr(val)
83 if val then
84 return ip.IPv6(val) and true or false
85 end
86
87 return false
88 end
89
90 function ip6prefix(val)
91 val = tonumber(val)
92 return ( val and val >= 0 and val <= 128 )
93 end
94
95 function port(val)
96 val = tonumber(val)
97 return ( val and val >= 0 and val <= 65535 )
98 end
99
100 function portrange(val)
101 local p1, p2 = val:match("^(%d+)%-(%d+)$")
102 if p1 and p2 and port(p1) and port(p2) then
103 return true
104 else
105 return port(val)
106 end
107 end
108
109 function macaddr(val)
110 if val and val:match(
111 "^[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+:" ..
112 "[a-fA-F0-9]+:[a-fA-F0-9]+:[a-fA-F0-9]+$"
113 ) then
114 local parts = util.split( val, ":" )
115
116 for i = 1,6 do
117 parts[i] = tonumber( parts[i], 16 )
118 if parts[i] < 0 or parts[i] > 255 then
119 return false
120 end
121 end
122
123 return true
124 end
125
126 return false
127 end
128
129 function hostname(val)
130 if val and (#val < 254) and (
131 val:match("^[a-zA-Z]+$") or
132 (val:match("^[a-zA-Z0-9][a-zA-Z0-9%-%.]*[a-zA-Z0-9]$") and
133 val:match("[^0-9%.]"))
134 ) then
135 return true
136 end
137 return false
138 end
139
140 function host(val)
141 return hostname(val) or ipaddr(val)
142 end
143
144 function network(val)
145 return uciname(val) or host(val)
146 end
147
148 function wpakey(val)
149 if #val == 64 then
150 return (val:match("^[a-fA-F0-9]+$") ~= nil)
151 else
152 return (#val >= 8) and (#val <= 63)
153 end
154 end
155
156 function wepkey(val)
157 if val:sub(1, 2) == "s:" then
158 val = val:sub(3)
159 end
160
161 if (#val == 10) or (#val == 26) then
162 return (val:match("^[a-fA-F0-9]+$") ~= nil)
163 else
164 return (#val == 5) or (#val == 13)
165 end
166 end
167
168 function string(val)
169 return true -- Everything qualifies as valid string
170 end
171
172 function directory( val, seen )
173 local s = fs.stat(val)
174 seen = seen or { }
175
176 if s and not seen[s.ino] then
177 seen[s.ino] = true
178 if s.type == "dir" then
179 return true
180 elseif s.type == "lnk" then
181 return directory( fs.readlink(val), seen )
182 end
183 end
184
185 return false
186 end
187
188 function file( val, seen )
189 local s = fs.stat(val)
190 seen = seen or { }
191
192 if s and not seen[s.ino] then
193 seen[s.ino] = true
194 if s.type == "reg" then
195 return true
196 elseif s.type == "lnk" then
197 return file( fs.readlink(val), seen )
198 end
199 end
200
201 return false
202 end
203
204 function device( val, seen )
205 local s = fs.stat(val)
206 seen = seen or { }
207
208 if s and not seen[s.ino] then
209 seen[s.ino] = true
210 if s.type == "chr" or s.type == "blk" then
211 return true
212 elseif s.type == "lnk" then
213 return device( fs.readlink(val), seen )
214 end
215 end
216
217 return false
218 end
219
220 function uciname(val)
221 return (val:match("^[a-zA-Z0-9_]+$") ~= nil)
222 end
223
224 function range(val, min, max)
225 val = tonumber(val)
226 min = tonumber(min)
227 max = tonumber(max)
228
229 if val ~= nil and min ~= nil and max ~= nil then
230 return ((val >= min) and (val <= max))
231 end
232
233 return false
234 end
235
236 function min(val, min)
237 val = tonumber(val)
238 min = tonumber(min)
239
240 if val ~= nil and min ~= nil then
241 return (val >= min)
242 end
243
244 return false
245 end
246
247 function max(val, max)
248 val = tonumber(val)
249 max = tonumber(max)
250
251 if val ~= nil and max ~= nil then
252 return (val <= max)
253 end
254
255 return false
256 end
257
258 function neg(val, what)
259 if what and type(_M[what]) == "function" then
260 return _M[what](val:gsub("^%s*!%s*", ""))
261 end
262
263 return false
264 end
265
266 function list(val, what, ...)
267 if type(val) == "string" and what and type(_M[what]) == "function" then
268 for val in val:gmatch("%S+") do
269 if not _M[what](val, ...) then
270 return false
271 end
272 end
273
274 return true
275 end
276
277 return false
278 end