luci-firewall: Add support for negations for ip addresses/nets (#218)
[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 range(val, min, max)
231         val = tonumber(val)
232         min = tonumber(min)
233         max = tonumber(max)
234
235         if val ~= nil and min ~= nil and max ~= nil then
236                 return ((val >= min) and (val <= max))
237         end
238
239         return false
240 end