1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
-- Prosody IM
-- Copyright (C) 2008-2009 Matthew Wild
-- Copyright (C) 2008-2009 Waqas Hussain
--
-- This project is MIT/X11 licensed. Please see the
-- COPYING file in the source package for more information.
--
local setmetatable = setmetatable;
local pairs, ipairs = pairs, ipairs;
local tostring, type = tostring, type;
local t_concat = table.concat;
local st = require "util.stanza";
module "dataforms"
local xmlns_forms = 'jabber:x:data';
local form_t = {};
local form_mt = { __index = form_t };
function new(layout)
return setmetatable(layout, form_mt);
end
function form_t.form(layout, data, formtype)
local form = st.stanza("x", { xmlns = xmlns_forms, type = formtype or "form" });
if layout.title then
form:tag("title"):text(layout.title):up();
end
if layout.instructions then
form:tag("instructions"):text(layout.instructions):up();
end
for n, field in ipairs(layout) do
local field_type = field.type or "text-single";
-- Add field tag
form:tag("field", { type = field_type, var = field.name, label = field.label });
local value = (data and data[field.name]) or field.value;
if value then
-- Add value, depending on type
if field_type == "hidden" then
if type(value) == "table" then
-- Assume an XML snippet
form:tag("value")
:add_child(value)
:up();
else
form:tag("value"):text(tostring(value)):up();
end
elseif field_type == "boolean" then
form:tag("value"):text((value and "1") or "0"):up();
elseif field_type == "fixed" then
elseif field_type == "jid-multi" then
for _, jid in ipairs(value) do
form:tag("value"):text(jid):up();
end
elseif field_type == "jid-single" then
form:tag("value"):text(value):up();
elseif field_type == "text-single" or field_type == "text-private" then
form:tag("value"):text(value):up();
elseif field_type == "text-multi" then
-- Split into multiple <value> tags, one for each line
for line in value:gmatch("([^\r\n]+)\r?\n*") do
form:tag("value"):text(line):up();
end
elseif field_type == "list-single" then
for _, val in ipairs(value) do
if type(val) == "table" then
form:tag("option", { label = val.label }):tag("value"):text(val.value):up():up();
else
form:tag("option", { label= val }):tag("value"):text(tostring(val)):up():up();
end
end
end
end
if field.required then
form:tag("required"):up();
end
-- Jump back up to list of fields
form:up();
end
return form;
end
local field_readers = {};
function form_t.data(layout, stanza)
local data = {};
for field_tag in stanza:childtags() do
local field_type;
for n, field in ipairs(layout) do
if field.name == field_tag.attr.var then
field_type = field.type;
break;
end
end
local reader = field_readers[field_type];
if reader then
data[field_tag.attr.var] = reader(field_tag);
end
end
return data;
end
field_readers["text-single"] =
function (field_tag)
local value = field_tag:child_with_name("value");
if value then
return value[1];
end
end
field_readers["text-private"] =
field_readers["text-single"];
field_readers["jid-single"] =
field_readers["text-single"];
field_readers["jid-multi"] =
function (field_tag)
local result = {};
for value_tag in field_tag:childtags() do
if value_tag.name == "value" then
result[#result+1] = value_tag[1];
end
end
return result;
end
field_readers["text-multi"] =
function (field_tag)
local result = {};
for value_tag in field_tag:childtags() do
if value_tag.name == "value" then
result[#result+1] = value_tag[1];
end
end
return t_concat(result, "\n");
end
field_readers["list-single"] =
field_readers["text-single"];
field_readers["boolean"] =
function (field_tag)
local value = field_tag:child_with_name("value");
if value then
if value[1] == "1" or value[1] == "true" then
return true;
else
return false;
end
end
end
field_readers["hidden"] =
function (field_tag)
local value = field_tag:child_with_name("value");
if value then
return value[1];
end
end
return _M;
--[=[
Layout:
{
title = "MUC Configuration",
instructions = [[Use this form to configure options for this MUC room.]],
{ name = "FORM_TYPE", type = "hidden", required = true };
{ name = "field-name", type = "field-type", required = false };
}
--]=]
|