Software /
code /
prosody
Comparison
util/dataforms.lua @ 9243:a4c52e304e6f
util.dataforms: Add support for XEP-0122: Data Forms Validation
Initially only basic validation of xs:integer
author | Kim Alvefur <zash@zash.se> |
---|---|
date | Sat, 01 Sep 2018 03:10:09 +0200 |
parent | 9242:68694c1bd960 |
child | 9246:397e8e5a2f1f |
comparison
equal
deleted
inserted
replaced
9242:68694c1bd960 | 9243:a4c52e304e6f |
---|---|
7 -- | 7 -- |
8 | 8 |
9 local setmetatable = setmetatable; | 9 local setmetatable = setmetatable; |
10 local ipairs = ipairs; | 10 local ipairs = ipairs; |
11 local type, next = type, next; | 11 local type, next = type, next; |
12 local tonumber = tonumber; | |
12 local t_concat = table.concat; | 13 local t_concat = table.concat; |
13 local st = require "util.stanza"; | 14 local st = require "util.stanza"; |
14 local jid_prep = require "util.jid".prep; | 15 local jid_prep = require "util.jid".prep; |
15 | 16 |
16 local _ENV = nil; | 17 local _ENV = nil; |
17 -- luacheck: std none | 18 -- luacheck: std none |
18 | 19 |
19 local xmlns_forms = 'jabber:x:data'; | 20 local xmlns_forms = 'jabber:x:data'; |
21 local xmlns_validate = 'http://jabber.org/protocol/xdata-validate'; | |
20 | 22 |
21 local form_t = {}; | 23 local form_t = {}; |
22 local form_mt = { __index = form_t }; | 24 local form_mt = { __index = form_t }; |
23 | 25 |
24 local function new(layout) | 26 local function new(layout) |
47 if formtype ~= "submit" then | 49 if formtype ~= "submit" then |
48 if field.desc then | 50 if field.desc then |
49 form:text_tag("desc", field.desc); | 51 form:text_tag("desc", field.desc); |
50 end | 52 end |
51 end | 53 end |
54 | |
55 if formtype == "form" and field.datatype then | |
56 form:tag("validate", { xmlns = xmlns_validate, datatype = field.datatype }); | |
57 -- <basic/> assumed | |
58 form:up(); | |
59 end | |
60 | |
52 | 61 |
53 local value = field.value; | 62 local value = field.value; |
54 local options = field.options; | 63 local options = field.options; |
55 | 64 |
56 if data and data[field.name] ~= nil then | 65 if data and data[field.name] ~= nil then |
83 end | 92 end |
84 end | 93 end |
85 end | 94 end |
86 | 95 |
87 if value ~= nil then | 96 if value ~= nil then |
97 if type(value) == "number" then | |
98 -- TODO validate that this is ok somehow, eg check field.datatype | |
99 value = ("%g"):format(value); | |
100 end | |
88 -- Add value, depending on type | 101 -- Add value, depending on type |
89 if field_type == "hidden" then | 102 if field_type == "hidden" then |
90 if type(value) == "table" then | 103 if type(value) == "table" then |
91 -- Assume an XML snippet | 104 -- Assume an XML snippet |
92 form:tag("value") | 105 form:tag("value") |
139 end | 152 end |
140 return form; | 153 return form; |
141 end | 154 end |
142 | 155 |
143 local field_readers = {}; | 156 local field_readers = {}; |
157 local data_validators = {}; | |
144 | 158 |
145 function form_t.data(layout, stanza, current) | 159 function form_t.data(layout, stanza, current) |
146 local data = {}; | 160 local data = {}; |
147 local errors = {}; | 161 local errors = {}; |
148 local present = {}; | 162 local present = {}; |
164 end | 178 end |
165 elseif field.name then | 179 elseif field.name then |
166 present[field.name] = true; | 180 present[field.name] = true; |
167 local reader = field_readers[field.type]; | 181 local reader = field_readers[field.type]; |
168 if reader then | 182 if reader then |
169 data[field.name], errors[field.name] = reader(tag, field.required); | 183 local value, err = reader(tag, field.required); |
184 local validator = field.datatype and data_validators[field.datatype]; | |
185 if value ~= nil and validator then | |
186 local valid, ret = validator(value, field); | |
187 if valid then | |
188 value = ret; | |
189 else | |
190 value, err = nil, ret or field.datatype; | |
191 end | |
192 end | |
193 data[field.name], errors[field.name] = value, err; | |
170 end | 194 end |
171 end | 195 end |
172 end | 196 end |
173 if next(errors) then | 197 if next(errors) then |
174 return data, errors, present; | 198 return data, errors, present; |
263 field_readers["hidden"] = | 287 field_readers["hidden"] = |
264 function (field_tag) | 288 function (field_tag) |
265 return field_tag:get_child_text("value"); | 289 return field_tag:get_child_text("value"); |
266 end | 290 end |
267 | 291 |
292 data_validators["xs:integer"] = | |
293 function (data) | |
294 local n = tonumber(data); | |
295 if not n then | |
296 return false, "not a number"; | |
297 elseif n % 1 ~= 0 then | |
298 return false, "not an integer"; | |
299 end | |
300 return true, n; | |
301 end | |
302 | |
268 | 303 |
269 local function get_form_type(form) | 304 local function get_form_type(form) |
270 if not st.is_stanza(form) then | 305 if not st.is_stanza(form) then |
271 return nil, "not a stanza object"; | 306 return nil, "not a stanza object"; |
272 elseif form.attr.xmlns ~= "jabber:x:data" or form.name ~= "x" then | 307 elseif form.attr.xmlns ~= "jabber:x:data" or form.name ~= "x" then |