lm.lua
changeset 0 84fdfb0344c9
child 6 90073cbb535d
equal deleted inserted replaced
-1:000000000000 0:84fdfb0344c9
       
     1 
       
     2 require ( 'loudmouth' )
       
     3 
       
     4 -- argument is a table with keys,
       
     5 -- corresponding to method names.
       
     6 function lm.proxy.create ( a )
       
     7 	if type ( a ) ~= "table" then
       
     8 		error ( "arguments should be in a table" )
       
     9 	end
       
    10 	local p = lm.proxy.new ()
       
    11 	if a.server then
       
    12 		p:server ( a.server )
       
    13 	end
       
    14 	if a.port then
       
    15 		p:port ( a.port )
       
    16 	end
       
    17 	if a['type'] then
       
    18 		p:type ( a['type'] )
       
    19 	end
       
    20 	if a.username then
       
    21 		p:username ( a.username )
       
    22 	end
       
    23 	if a.password then
       
    24 		p:password ( a.password )
       
    25 	end
       
    26 	return p
       
    27 end
       
    28 
       
    29 -- argument is a table with two keys:
       
    30 -- callback and fingerprint
       
    31 function lm.ssl.create ( a )
       
    32 	if not lm.ssl.supported () then
       
    33 		-- XXX
       
    34 		-- error ( "ssl is not supported by your loudmouth library" )
       
    35 		return nil
       
    36 	end
       
    37 	local fp, cb
       
    38 	local st = type ( a )
       
    39 	if st == "table" then
       
    40 		fp = a.fingerprint
       
    41 		cb = a.callback
       
    42 	elseif st == "function" then
       
    43 		cb = a
       
    44 	elseif st == "string" then
       
    45 		fp = a
       
    46 	elseif st ~= "nil" then
       
    47 		error ( "unexpected type of argument" )
       
    48 	end
       
    49 	if fp then
       
    50 		if cb then
       
    51 			return lm.ssl.new ( fp, cb )
       
    52 		else
       
    53 			return lm.ssl.new ( fp )
       
    54 		end
       
    55 	else
       
    56 		if cb then
       
    57 			return lm.ssl.new ( cb )
       
    58 		else
       
    59 			return lm.ssl.new ()
       
    60 		end
       
    61 	end
       
    62 end
       
    63 
       
    64 -- basically, it just provides a way
       
    65 -- to initialize many parameters at once.
       
    66 -- keys in a table correspond to methods
       
    67 -- of connection object, except for handlers,
       
    68 -- where format is {
       
    69 --     "type/priority" = function/object,
       
    70 --     ...
       
    71 -- }
       
    72 -- two extra keys - server and context.
       
    73 -- ssl and proxy objects can either be objects
       
    74 -- or tables, directly passed to corresponding
       
    75 -- create routine.
       
    76 function lm.connection.create ( a )
       
    77 	local at = type (a)
       
    78 	if at == "string" then
       
    79 		return lm.connection.new ( a )
       
    80 	elseif at == "table" then
       
    81 		local server = a.server
       
    82 		if not server then
       
    83 			error ( "server name parameter required" )
       
    84 		end
       
    85 
       
    86 		-- create connection object
       
    87 		local c
       
    88 		if a.context then
       
    89 			c = lm.connection.new ( server, a.context )
       
    90 		else
       
    91 			c = lm.connection.new ( server )
       
    92 		end
       
    93 
       
    94 		-- connection parameters
       
    95 		if a.port then
       
    96 			c:port ( a.port )
       
    97 		end
       
    98 		if a.jid then
       
    99 			c:jid ( a.jid )
       
   100 		end
       
   101 		if a.keep_alive_rate then
       
   102 			c:keep_alive_rate ( a.keep_alive_rate )
       
   103 		end
       
   104 
       
   105 		-- proxy
       
   106 		if a.proxy then
       
   107 			local pt = type ( a.proxy )
       
   108 			if pt == "userdata" then
       
   109 				c:proxy ( a.proxy )
       
   110 			else
       
   111 				local proxy = lm.proxy.create ( a.proxy )
       
   112 				c:proxy ( proxy )
       
   113 			end
       
   114 		end
       
   115 
       
   116 		-- ssl
       
   117 		if a.ssl then
       
   118 			local st = type ( a.ssl )
       
   119 			if st == "userdata" then
       
   120 				c:ssl ( a.ssl )
       
   121 			else
       
   122 				local ssl = lm.ssl.create ( a.ssl )
       
   123 				c:ssl ( ssl )
       
   124 			end
       
   125 		end
       
   126 
       
   127 		-- disconnect callback
       
   128 		if a.ondisconnect then
       
   129 			c:ondisconnect ( a.ondisconnect )
       
   130 		end
       
   131 
       
   132 		-- message handlers
       
   133 		if a.handlers then
       
   134 			if type ( a.handlers ) ~= "table" then
       
   135 				error ( "handlers parameter expected to be a table " ..
       
   136 				        "of the form { \"type/priority\" = function/object }" )
       
   137 			end
       
   138 			for mhtype, handler in pairs ( a.handlers ) do
       
   139 				local mtype, prio = mhtype:match ( "(.-)/(%d+)" )
       
   140 				if not mtype then
       
   141 					mtype = mhtype
       
   142 					prio = 0
       
   143 				else
       
   144 					prio = tonumber ( prio )
       
   145 				end
       
   146 				c:handler ( handler, mtype, prio )
       
   147 			end
       
   148 		end
       
   149 
       
   150 		return c
       
   151 	else
       
   152 		error ( "at least server name parameter required" )
       
   153 	end
       
   154 end
       
   155 
       
   156 -- recursively fills a node, see lm.message.create
       
   157 function lm.message_node.fill ( n, a )
       
   158 	for name, value in pairs ( a ) do
       
   159 		if type ( value ) == "table" then
       
   160 			if type ( value[1] ) == "table" then
       
   161 				for index, instance in ipairs ( value ) do
       
   162 					lm.message_node.fill ( n:child ( name, "" ), instance )
       
   163 				end
       
   164 			else
       
   165 				lm.message_node.fill ( n:child ( name, "" ), value )
       
   166 			end
       
   167 		elseif name == 1 then
       
   168 			n:value ( value )
       
   169 		else
       
   170 			n:attribute ( name, value )
       
   171 		end
       
   172 	end
       
   173 end
       
   174 
       
   175 --[[
       
   176 -- recursively fills a message
       
   177 lm.message.create { mtype = 'iq-result', to = 'foo@bar.xyz',
       
   178 	command = { xmlns = 'http://jabber.org/protocol/commands', node = 'http://jabber.org/protocol/rc#set-status', status = 'executing', sessionid = 'set-status:aaa3',
       
   179 		x = { xmlns = 'jabber:x:data', type = 'form',
       
   180 			title = { "Change Status" },
       
   181 			instructions = { "Choose the status and status message" },
       
   182 			field = {{ type = 'hidden', var = 'FORM_TYPE',
       
   183 				value = { "http://jabber.org/protocol/rc" },
       
   184 			},{ type = 'list-single', label = 'Status', var = 'status',
       
   185 				required = { },
       
   186 				value = { "online" },
       
   187 				option = {{ label = 'Chat',
       
   188 					value = { "chat" },
       
   189 				},{ label = 'Online',
       
   190 					value = { "online" },
       
   191 				},{ label = 'Away',
       
   192 					value = { "away" },
       
   193 				},{ label = 'Extended Away',
       
   194 					value = { "xa" },
       
   195 				},{ label = 'Do Not Disturb',
       
   196 					value = { "dnd" },
       
   197 				},{ label = 'Invisible',
       
   198 					value = { "invisible" },
       
   199 				},{ label = 'Offline',
       
   200 					value = { "offline" },
       
   201 				}},
       
   202 			},{ type = 'text-single', label = 'Priority', var = 'status-priority',
       
   203 				value = { "5" },
       
   204 			},{ type = 'text-multi', label = 'Message', var = 'status-message' }},
       
   205 		},
       
   206 	},
       
   207 }
       
   208 --]]
       
   209 function lm.message.create ( a )
       
   210 	if type ( a ) ~= "table" then
       
   211 		error ( "table expected as argument" )
       
   212 	end
       
   213 	if not a.mtype or not a.to then
       
   214 		error ( "you must specify message type and destination" )
       
   215 	end
       
   216 	local mtype, subtype = a.mtype:match ( "(.-)%-(.+)" )
       
   217 	local m
       
   218 	if not mtype then
       
   219 		m = lm.message.new ( a.to, a.mtype )
       
   220 	else
       
   221 		m = lm.message.new ( a.to, mtype, subtype )
       
   222 	end
       
   223 	a.to = nil
       
   224 	a.mtype = nil
       
   225 	lm.message_node.fill ( m:node(), a )
       
   226 	return m
       
   227 end
       
   228 
       
   229 -- TODO: multiple nodes with same name
       
   230 function lm.message_node.parse ( node, r )
       
   231 	local n = node:children ()
       
   232 	while n do
       
   233 		local name = n:name ()
       
   234 		r[name] = { }
       
   235 		local value = n:value ()
       
   236 		if value then
       
   237 			r[name][1] = value
       
   238 		end
       
   239 		lm.message_node.parse ( n, r[name] )
       
   240 		n = n:next ()
       
   241 	end
       
   242 end
       
   243 
       
   244 -- There are NO WAY to get a list of node attributes,
       
   245 -- except brute force...
       
   246 function lm.message.parse ( message )
       
   247 	local node = message:node ()
       
   248 	local mtype, subtype = message:type ()
       
   249 	if subtype then
       
   250 		mtype = mtype .. '-' .. subtype
       
   251 	end
       
   252 	local r = { mtype = mtype }
       
   253 	local value = node:value ()
       
   254 	if value then
       
   255 		r[1] = value
       
   256 	end
       
   257 	lm.message_node.parse ( node, r )
       
   258 	return r
       
   259 end
       
   260 
       
   261 -- the same table, as for lm.connection.create, but with few more fields:
       
   262 -- ssl.validate
       
   263 -- onconnect
       
   264 -- onopen
       
   265 -- username
       
   266 -- password
       
   267 -- resource
       
   268 function lm.connect ( a )
       
   269 	if type ( a ) ~= "table" then
       
   270 		error ( "table expected as argument" )
       
   271 	end
       
   272 	if a.ssl then
       
   273 		if a.ssl.validate and not a.ssl.callback then
       
   274 			a.ssl.callback =
       
   275 				function ( obj, status )
       
   276 					return false
       
   277 				end
       
   278 		end
       
   279 	end
       
   280 	local c = lm.connection.create ( a )
       
   281 	c:open (
       
   282 		function ( obj, status )
       
   283 			if status then
       
   284 				if type ( a.onopen ) == "function" then
       
   285 					a.onopen ( obj )
       
   286 				end
       
   287 				c:authenticate ( a.username, a.password, a.resource,
       
   288 					function ( obj, status )
       
   289 						if type ( a.onconnect ) == "function" then
       
   290 							a.onconnect ( obj )
       
   291 						end
       
   292 					end )
       
   293 			end
       
   294 		end )
       
   295 	return c
       
   296 end
       
   297 
       
   298 -- vim: se ts=4: --