examples/evil.lua
author Myhailo Danylenko <isbear@ukrpost.net>
Fri, 27 Mar 2009 01:46:53 +0200
changeset 64 bf7521ed96eb
parent 63 423555c07763
child 66 542f61e113cb
permissions -rw-r--r--
Rewrite of ibb in object style


-- MALICIOUS STANZAS (XEP-0076)

-- FIXME for now we only can send evil messages
--       also we cannot detect stream-level evil :(

-- library

require 'lm'
local iq = require 'iq'

-- public

evil = {
	handler =
		function ( mess )
			return false
		end,
}

function evil.message ( conn, to, mtype, message )
	conn:send ( lm.message.create { mtype = 'message-' .. mtype, to = to,
			body = { message },
			evil = { xmlns = 'http://jabber.org/protocol/evil' },
		} )
end

function evil.presence ( conn, to, status, message )
	local mtype = 'presence-available'
	if status == 'unavailable' then
		mtype = 'presence-unavailable'
		status = ''
	end
	conn:send ( lm.message.create { mtype = mtype, from = conn:jid (), to = to,
			show   = { status },
			status = { message },
			evil   = { xmlns = 'http://jabber.org/protocol/evil' },
		} )
end

-- private

local evil_incoming_stanza_handler = lm.message_handler.new (
	function ( conn, mess )
		local e = mess:child ( 'evil' )
		if e and e:attribute ( 'xmlns' ) == 'http://jabber.org/protocol/evil' then
			return evil.handler ( mess )
		end
	end )

-- mcabber

evil.handler =
	function ( mess )
		local evillevel = tonumber(main.option ( 'lua_evil_sensibility' ))
		local mtype, smtype = mess:type ()
		if evillevel > 1 then
			main.print_info ( mess:attribute ( 'from' ), 'Evil stanza of type ' .. mtype .. '.' .. smtype .. ' detected!' )
		elseif evillevel > 0 then
			print ( 'Tainted by evil stanza of type ' .. mtype .. '.' .. smtype .. ' from ' .. ( mess:attribute ( 'from' ) or '... unknown in black' ) )
		end
		return main.yesno ( main.option ( 'lua_filter_evil' ) )
	end

local stat2xmpp = {
	free     = 'chat',
	online   = '',
	away     = 'away',
	dnd      = 'dnd',
	notavail = 'xa',
	offline  = 'unavailable',
}

-- TODO improve interface, check if we sending right thing for offline
main.command ( 'evil',
	function ( args )
		local conn = lm.connection.bless ( main.connection () )
		if args[1] == 'status' then
			local text = ''
			for i, mesg in ipairs ( args ) do
				if i > 2 then
					text = text .. ' ' .. mesg
				end
			end
			local st = stat2xmpp[args[2]]
			if not st then
				st = ''
			end
			evil.presence ( conn, args.t, st, text:sub ( 2 ) )
		else
			local text = ''
			if args[1] == 'message' then
				for i, mesg in ipairs ( args ) do
					if i > 1 then
						text = text .. ' ' .. mesg
					end
				end
			else
				for i, mesg in ipairs ( args ) do
					text = text .. ' ' .. mesg
				end
			end
			local mtype = 'chat'
			if args.k then
				mtype = args.k
			end
			local who
			if args.t then
				who = args.t
			else
				who = main.current_buddy ()
			end
			evil.message ( conn, who, mtype, text:sub ( 2 ) )
		end
	end, true )

commands_help['evil'] = "[-t jid] [status stat [message] | [-k message_type] [message] message]\n\nSends evil message or presence.\nmessage_type may be chat, normal, headline.\nNote, that for now it will not change mcabber's status."

local evil_handler_registered = false

hooks_d['hook-post-connect'].evil =
	function ( args )
		lm.connection.bless( main.connection () ):handler ( evil_incoming_stanza_handler, 'iq',       'first' )
		lm.connection.bless( main.connection () ):handler ( evil_incoming_stanza_handler, 'message',  'first' )
		lm.connection.bless( main.connection () ):handler ( evil_incoming_stanza_handler, 'presence', 'first' )
		evil_handler_registered = true
		hooks_d['hook-post-connect'].evil = nil
		hooks_d['hook-quit'].evil =
			function ( args )
				if evil_handler_registered then
					lm.connection.bless( main.connection () ):handler ( evil_incoming_stanza_handler, 'iq'       )
					lm.connection.bless( main.connection () ):handler ( evil_incoming_stanza_handler, 'message'  )
					lm.connection.bless( main.connection () ):handler ( evil_incoming_stanza_handler, 'presence' )
				end
			end
	end

local char2xmpp = {
	f = 'chat',
	o = '',
	a = 'away',
	d = 'dnd',
	n = 'xa',
	_ = 'unavailable',
}

-- hack, but working ;)
hooks_d['hook-my-status-change'].evil =
	function ( args )
		if main.yesno ( main.option ( 'lua_evil_mode' ) ) then
			evil.presence ( lm.connection.bless ( main.connection () ), nil, char2xmpp[args.new_status], args.message )
		end
	end

main.add_feature ( 'http://jabber.org/protocol/evil' )

-- vim: se ts=4: --