examples/x_data.lua
changeset 49 95f3bf77c598
child 53 2162188b20cf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/examples/x_data.lua	Sun Mar 22 04:14:36 2009 +0200
@@ -0,0 +1,211 @@
+
+-- 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
+						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: --