-- DATA FORMS (XEP-0004)
-- library
require 'lm'
-- public
x_data = { }
-- iq_register should encapsulate x_data in results, so, looks like we need callbacks again?
-- though, it can redefine method... but it is not too pretty. for now it will be so.
-- result needs separate routine? (reported & item's)
function x_data.format ( form, root )
root.x = { xmlns = 'jabber:x:data', type = form.type }
local fields = { }
for i, field in ipairs ( form ) do
if field.type ~= 'fixed' then
local value
if field.type == 'list-multi' or field.type == 'text-multi' or field.type == 'jid-multi' then
value = { }
for j, v in ipairs ( field.value ) do
table.insert ( value, { v } )
end
else
value = { field.value }
end
table.insert ( fields, { type = field.type, var = field.var, value = value } )
end
end
root.x.field = fields
return root
end
function x_data.parse ( x )
local f = { xmlns = 'jabber:x:data', type = x:attribute ( 'type' ) }
local title = x:child ( 'title' )
if title then
f.title = title:value ()
end
local instructions = x:child ( 'instructions' )
if instructions then
f.instructions = instructions:value ()
end
local field = x:children ()
while field do
if field:name () == 'field' then
local ftype = field:attribute ( 'type' ) or 'text-single'
local r = {
type = ftype,
var = field:attribute ( 'var' ), -- may be absent on 'fixed' fields
label = field:attribute ( 'label' ),
}
local desc = field:child ( 'desc' )
if desc then
r.decs = desc:value ()
end
if field:child ( 'required' ) then
r.required = true
end
if ftype == 'jid-multi' or ftype == 'list-multi' or ftype == 'text-multi' or ftype == 'list-single' then
local values = { }
local options = { }
local item = field:children ()
while item do
local name = item:name ()
if name == 'value' then
table.insert ( values, item:value () )
elseif name == 'option' then
table.insert ( options, item:child( 'value' ):value () ) -- FIXME labels
end
item = item:next ()
end
if ftype == 'list-single' then
local value = field:child ( 'value' )
if value then
r.value = value:value ()
end
else
r.value = values
end
if ftype == 'list-multi' or ftype == 'list-single' then
r.options = options
end
else
local value = field:child ( 'value' )
if value then
r.value = value:value ()
end
end
table.insert ( f, r )
end
field = field:next ()
end
f.format = x_data.format
return f
end
function x_data.set ( f, name, value )
for i, field in ipairs ( f ) do
if field.var == name then
if field.type == 'jid-multi' or field.type == 'list-multi' or field.type == 'text-multi' then
if value == nil then
field.value = { }
else
table.insert ( field.value, value )
end
else
field.value = value
end
end
end
end
-- mcabber
local form_cid = main.add_category { 'del', 'send' }
forms = { }
function insert_form ( form )
table.insert ( forms, form )
main.add_completion ( form_cid, tostring(#forms) )
return #forms
end
main.command ( 'form',
function ( args )
local id, action = tonumber (args[1]), args[2]
if forms[id] then
local form = forms[id].form
if action == 'send' then
forms[id].submit ( form )
elseif action == 'reject' then
forms[id].reject ( form )
elseif action == 'del' then
main.del_completion ( form_cid, id )
forms[id] = nil
elseif action == 'set' then
x_data.set ( form, args[3], args[4] )
elseif action then
x_data.set ( form, action, args[3] )
else
local desc = 'Form ' .. id
local fields = 'Fields:'
for index, field in pairs ( form ) do
if type(index) == 'number' then
fields = fields .. '\n - '
if field.required then
fields = fields .. '* '
end
if field.label then
fields = fields .. field.label .. ' (' .. ( field.var or '' ) .. ')'
else
fields = fields .. ( field.var or '<no name>' )
end
fields = fields .. ' [' .. field.type .. ']'
if field.desc then
fields = fields .. ': ' .. desc
end
if field.options then
fields = fields .. '\n Options:'
for i, opt in ipairs ( field.options ) do
fields = fields .. ' ' .. opt
end
end
if field.type == 'list-multi' or field.type == 'text-multi' or field.type == 'jid-multi' then
fields = fields .. '\n Values: '
for vin, value in ipairs ( field.value ) do
fields = fields .. '\n * ' .. value
end
else
fields = fields .. '\n Value: ' .. ( field.value or '' )
end
else
if type(field) ~= 'function' then -- skip any methods
desc = desc .. '\n - ' .. index .. ': ' .. field
end
end
end
print ( desc .. '\n' .. fields )
end
else
local text = ''
for id, form in pairs ( forms ) do
text = text .. '\n - ' .. id .. ' ' .. ( form.form.title or 'Untitled' ) .. ' [' .. form.form.xmlns .. ', ' .. form.form.type .. ']'
end
if text ~= '' then
print ( 'Forms list:' .. text )
else
print ( 'No forms' )
end
end
end, true, form_cid )
commands_help['form'] = "[del form_id | send form_id | form_id [field_name {clear | [set] value}]\n\nWith bare form id prints info on that form.\nWith field name sets or clears field value. Set subcommand is optional, just to allow values, starting with 'clear'.\nWithout arguments prints form list."
-- vim: se ts=4: --