libs/web: fix "port" datatype to allow port 0
[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
21 local tonumber = tonumber
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 val.match(val, "^[a-zA-Z0-9][a-zA-Z0-9%-%.]*[a-zA-Z0-9]$") then
131 return true
132 end
133 return false
134 end
135
136 function host(val)
137 return hostname(val) or ipaddr(val)
138 end
139
140 function wpakey(val)
141 if #val == 64 then
142 return (val:match("^[a-fA-F0-9]+$") ~= nil)
143 else
144 return (#val >= 8) and (#val <= 63)
145 end
146 end
147
148 function wepkey(val)
149 if val:sub(1, 2) == "s:" then
150 val = val:sub(3)
151 end
152
153 if (#val == 10) or (#val == 26) then
154 return (val:match("^[a-fA-F0-9]+$") ~= nil)
155 else
156 return (#val == 5) or (#val == 13)
157 end
158 end
159
160 function string(val)
161 return true -- Everything qualifies as valid string
162 end
163
164 function directory( val, seen )
165 local s = fs.stat(val)
166 seen = seen or { }
167
168 if s and not seen[s.ino] then
169 seen[s.ino] = true
170 if s.type == "dir" then
171 return true
172 elseif s.type == "lnk" then
173 return directory( fs.readlink(val), seen )
174 end
175 end
176
177 return false
178 end
179
180 function file( val, seen )
181 local s = fs.stat(val)
182 seen = seen or { }
183
184 if s and not seen[s.ino] then
185 seen[s.ino] = true
186 if s.type == "reg" then
187 return true
188 elseif s.type == "lnk" then
189 return file( fs.readlink(val), seen )
190 end
191 end
192
193 return false
194 end
195
196 function device( val, seen )
197 local s = fs.stat(val)
198 seen = seen or { }
199
200 if s and not seen[s.ino] then
201 seen[s.ino] = true
202 if s.type == "chr" or s.type == "blk" then
203 return true
204 elseif s.type == "lnk" then
205 return device( fs.readlink(val), seen )
206 end
207 end
208
209 return false
210 end
211
212 function uciname(val)
213 return (val:match("^[a-zA-Z0-9_]+$") ~= nil)
214 end
215
216 function range(val, min, max)
217 val = tonumber(val)
218 min = tonumber(min)
219 max = tonumber(max)
220
221 if val ~= nil and min ~= nil and max ~= nil then
222 return ((val >= min) and (val <= max))
223 end
224
225 return false
226 end