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 |