Mercurial > prosody-modules
comparison mod_captcha_registration/util/dataforms.lua @ 1373:985bfc6e8cad
mod_captcha_registration: initial commit
| author | mrDoctorWho <mrdoctorwho@gmail.com> |
|---|---|
| date | Sat, 29 Mar 2014 22:56:24 +0700 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 1372:a573d64968e9 | 1373:985bfc6e8cad |
|---|---|
| 1 -- Prosody IM | |
| 2 -- Copyright (C) 2008-2010 Matthew Wild | |
| 3 -- Copyright (C) 2008-2010 Waqas Hussain | |
| 4 -- | |
| 5 -- This project is MIT/X11 licensed. Please see the | |
| 6 -- COPYING file in the source package for more information. | |
| 7 -- | |
| 8 | |
| 9 local setmetatable = setmetatable; | |
| 10 local pairs, ipairs = pairs, ipairs; | |
| 11 local tostring, type, next = tostring, type, next; | |
| 12 local t_concat = table.concat; | |
| 13 local st = require "util.stanza"; | |
| 14 local jid_prep = require "util.jid".prep; | |
| 15 | |
| 16 module "dataforms" | |
| 17 | |
| 18 local xmlns_forms = 'jabber:x:data'; | |
| 19 | |
| 20 local form_t = {}; | |
| 21 local form_mt = { __index = form_t }; | |
| 22 | |
| 23 function new(layout) | |
| 24 return setmetatable(layout, form_mt); | |
| 25 end | |
| 26 | |
| 27 function form_t.form(layout, data, formtype) | |
| 28 local form = st.stanza("x", { xmlns = xmlns_forms, type = formtype or "form" }); | |
| 29 if layout.title then | |
| 30 form:tag("title"):text(layout.title):up(); | |
| 31 end | |
| 32 if layout.instructions then | |
| 33 form:tag("instructions"):text(layout.instructions):up(); | |
| 34 end | |
| 35 for n, field in ipairs(layout) do | |
| 36 local field_type = field.type or "text-single"; | |
| 37 -- Add field tag | |
| 38 form:tag("field", { type = field_type, var = field.name, label = field.label }); | |
| 39 | |
| 40 local value = (data and data[field.name]) or field.value; | |
| 41 | |
| 42 if value then | |
| 43 -- Add value, depending on type | |
| 44 if field_type == "hidden" then | |
| 45 if type(value) == "table" then | |
| 46 -- Assume an XML snippet | |
| 47 form:tag("value") | |
| 48 :add_child(value) | |
| 49 :up(); | |
| 50 else | |
| 51 form:tag("value"):text(tostring(value)):up(); | |
| 52 end | |
| 53 elseif field_type == "boolean" then | |
| 54 form:tag("value"):text((value and "1") or "0"):up(); | |
| 55 elseif field_type == "fixed" then | |
| 56 form:tag("value"):text(value):up(); | |
| 57 elseif field_type == "jid-multi" then | |
| 58 for _, jid in ipairs(value) do | |
| 59 form:tag("value"):text(jid):up(); | |
| 60 end | |
| 61 elseif field_type == "jid-single" then | |
| 62 form:tag("value"):text(value):up(); | |
| 63 elseif field_type == "text-single" or field_type == "text-private" then | |
| 64 form:tag("value"):text(value):up(); | |
| 65 elseif field_type == "text-multi" then | |
| 66 -- Split into multiple <value> tags, one for each line | |
| 67 for line in value:gmatch("([^\r\n]+)\r?\n*") do | |
| 68 form:tag("value"):text(line):up(); | |
| 69 end | |
| 70 elseif field_type == "list-single" then | |
| 71 local has_default = false; | |
| 72 for _, val in ipairs(value) do | |
| 73 if type(val) == "table" then | |
| 74 form:tag("option", { label = val.label }):tag("value"):text(val.value):up():up(); | |
| 75 if val.default and (not has_default) then | |
| 76 form:tag("value"):text(val.value):up(); | |
| 77 has_default = true; | |
| 78 end | |
| 79 else | |
| 80 form:tag("option", { label= val }):tag("value"):text(tostring(val)):up():up(); | |
| 81 end | |
| 82 end | |
| 83 elseif field_type == "list-multi" then | |
| 84 for _, val in ipairs(value) do | |
| 85 if type(val) == "table" then | |
| 86 form:tag("option", { label = val.label }):tag("value"):text(val.value):up():up(); | |
| 87 if val.default then | |
| 88 form:tag("value"):text(val.value):up(); | |
| 89 end | |
| 90 else | |
| 91 form:tag("option", { label= val }):tag("value"):text(tostring(val)):up():up(); | |
| 92 end | |
| 93 end | |
| 94 elseif field_type == "media" then | |
| 95 form:tag("media", { xmlns = "urn:xmpp:media-element" }); | |
| 96 for _, val in ipairs(value) do | |
| 97 form:tag("uri", { type = val.type }):text(val.uri):up() | |
| 98 end | |
| 99 form:up(); | |
| 100 end | |
| 101 end | |
| 102 | |
| 103 if field.required then | |
| 104 form:tag("required"):up(); | |
| 105 end | |
| 106 | |
| 107 -- Jump back up to list of fields | |
| 108 form:up(); | |
| 109 end | |
| 110 return form; | |
| 111 end | |
| 112 | |
| 113 local field_readers = {}; | |
| 114 | |
| 115 function form_t.data(layout, stanza) | |
| 116 local data = {}; | |
| 117 local errors = {}; | |
| 118 | |
| 119 for _, field in ipairs(layout) do | |
| 120 local tag; | |
| 121 for field_tag in stanza:childtags() do | |
| 122 if field.name == field_tag.attr.var then | |
| 123 tag = field_tag; | |
| 124 break; | |
| 125 end | |
| 126 end | |
| 127 | |
| 128 if not tag then | |
| 129 if field.required then | |
| 130 errors[field.name] = "Required value missing"; | |
| 131 end | |
| 132 else | |
| 133 local reader = field_readers[field.type]; | |
| 134 if reader then | |
| 135 data[field.name], errors[field.name] = reader(tag, field.required); | |
| 136 end | |
| 137 end | |
| 138 end | |
| 139 if next(errors) then | |
| 140 return data, errors; | |
| 141 end | |
| 142 return data; | |
| 143 end | |
| 144 | |
| 145 field_readers["text-single"] = | |
| 146 function (field_tag, required) | |
| 147 local data = field_tag:get_child_text("value"); | |
| 148 if data and #data > 0 then | |
| 149 return data | |
| 150 elseif required then | |
| 151 return nil, "Required value missing"; | |
| 152 end | |
| 153 end | |
| 154 | |
| 155 field_readers["text-private"] = | |
| 156 field_readers["text-single"]; | |
| 157 | |
| 158 field_readers["jid-single"] = | |
| 159 function (field_tag, required) | |
| 160 local raw_data = field_tag:get_child_text("value") | |
| 161 local data = jid_prep(raw_data); | |
| 162 if data and #data > 0 then | |
| 163 return data | |
| 164 elseif raw_data then | |
| 165 return nil, "Invalid JID: " .. raw_data; | |
| 166 elseif required then | |
| 167 return nil, "Required value missing"; | |
| 168 end | |
| 169 end | |
| 170 | |
| 171 field_readers["jid-multi"] = | |
| 172 function (field_tag, required) | |
| 173 local result = {}; | |
| 174 local err = {}; | |
| 175 for value_tag in field_tag:childtags("value") do | |
| 176 local raw_value = value_tag:get_text(); | |
| 177 local value = jid_prep(raw_value); | |
| 178 result[#result+1] = value; | |
| 179 if raw_value and not value then | |
| 180 err[#err+1] = ("Invalid JID: " .. raw_value); | |
| 181 end | |
| 182 end | |
| 183 if #result > 0 then | |
| 184 return result, (#err > 0 and t_concat(err, "\n") or nil); | |
| 185 elseif required then | |
| 186 return nil, "Required value missing"; | |
| 187 end | |
| 188 end | |
| 189 | |
| 190 field_readers["list-multi"] = | |
| 191 function (field_tag, required) | |
| 192 local result = {}; | |
| 193 for value in field_tag:childtags("value") do | |
| 194 result[#result+1] = value:get_text(); | |
| 195 end | |
| 196 if #result > 0 then | |
| 197 return result; | |
| 198 elseif required then | |
| 199 return nil, "Required value missing"; | |
| 200 end | |
| 201 end | |
| 202 | |
| 203 field_readers["text-multi"] = | |
| 204 function (field_tag, required) | |
| 205 local data, err = field_readers["list-multi"](field_tag, required); | |
| 206 if data then | |
| 207 data = t_concat(data, "\n"); | |
| 208 end | |
| 209 return data, err; | |
| 210 end | |
| 211 | |
| 212 field_readers["list-single"] = | |
| 213 field_readers["text-single"]; | |
| 214 | |
| 215 local boolean_values = { | |
| 216 ["1"] = true, ["true"] = true, | |
| 217 ["0"] = false, ["false"] = false, | |
| 218 }; | |
| 219 | |
| 220 field_readers["boolean"] = | |
| 221 function (field_tag, required) | |
| 222 local raw_value = field_tag:get_child_text("value"); | |
| 223 local value = boolean_values[raw_value ~= nil and raw_value]; | |
| 224 if value ~= nil then | |
| 225 return value; | |
| 226 elseif raw_value then | |
| 227 return nil, "Invalid boolean representation"; | |
| 228 elseif required then | |
| 229 return nil, "Required value missing"; | |
| 230 end | |
| 231 end | |
| 232 | |
| 233 field_readers["hidden"] = | |
| 234 function (field_tag) | |
| 235 return field_tag:get_child_text("value"); | |
| 236 end | |
| 237 | |
| 238 field_readers["media"] = field_readers["text-single"] | |
| 239 | |
| 240 return _M; | |
| 241 | |
| 242 | |
| 243 --[=[ | |
| 244 | |
| 245 Layout: | |
| 246 { | |
| 247 | |
| 248 title = "MUC Configuration", | |
| 249 instructions = [[Use this form to configure options for this MUC room.]], | |
| 250 | |
| 251 { name = "FORM_TYPE", type = "hidden", required = true }; | |
| 252 { name = "field-name", type = "field-type", required = false }; | |
| 253 } | |
| 254 | |
| 255 | |
| 256 --]=] |
