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