File

util/stanza.lua @ 1:b8787e859fd2

Switched to new connection framework, courtesy of the luadch project Now supports SSL on 5223 Beginning support for presence (aka. the proper routing of stanzas)
author matthew
date Sun, 24 Aug 2008 01:51:02 +0000
parent 0:3e3171b59028
child 2:9bb397205f26
line wrap: on
line source

local t_insert      =  table.insert;
local t_remove      =  table.remove;
local format        = string.format;
local tostring      =      tostring;
local setmetatable  =  setmetatable;
local pairs         =         pairs;
local ipairs        =        ipairs;
local type          =          type;

module "stanza"

stanza_mt = {};
stanza_mt.__index = stanza_mt;

function stanza(name, attr)
	local stanza = { name = name, attr = attr or {}, tags = {}, last_add = {}};
	return setmetatable(stanza, stanza_mt);
end

function stanza_mt:iq(attrs)
	return self + stanza("iq", attrs)
end
function stanza_mt:message(attrs)
	return self + stanza("message", attrs)
end
function stanza_mt:presence(attrs)
	return self + stanza("presence", attrs)
end
function stanza_mt:query(xmlns)
	return self:tag("query", { xmlns = xmlns });
end
function stanza_mt:tag(name, attrs)
	local s = stanza(name, attrs);
	(self.last_add[#self.last_add] or self):add_child(s);
	t_insert(self.last_add, s);
	return self;
end

function stanza_mt:text(text)
	(self.last_add[#self.last_add] or self):add_child(text);
	return self; 
end

function stanza_mt:up()
	t_remove(self.last_add);
	return self;
end

function stanza_mt:add_child(child)
	if type(child) == "table" then
		t_insert(self.tags, child);
	end
	t_insert(self, child);
end

function stanza_mt:child_with_name(name)
	for _, child in ipairs(self) do	
		if child.name == name then return child; end
	end
end

function stanza_mt:children()
	local i = 0;
	return function (a)
			i = i + 1
			local v = a[i]
			if v then return v; end
		end, self, i;
	                                    
end

function stanza_mt.__tostring(t)
	local children_text = "";
	for n, child in ipairs(t) do
		children_text = children_text .. tostring(child);
	end

	local attr_string = "";
	if t.attr then
		for k, v in pairs(t.attr) do if type(k) == "string" then attr_string = attr_string .. format(" %s='%s'", k, tostring(v)); end end
	end

	return format("<%s%s>%s</%s>", t.name, attr_string, children_text, t.name);
end

function stanza_mt.__add(s1, s2)
	return s1:add_child(s2);
end


do
        local id = 0;
        function new_id()
                id = id + 1;
                return "lx"..id;
        end
end

function message(attr, body)
	if not body then
		return stanza("message", attr);
	else
		return stanza("message", attr):tag("body"):text(body);
	end
end
function iq(attr)
	if attr and not attr.id then attr.id = new_id(); end
	return stanza("iq", attr or { id = new_id() });
end

function reply(orig)
	return stanza(orig.name, orig.attr and { to = orig.attr.from, from = orig.attr.to, id = orig.attr.id, type = ((orig.name == "iq" and "result") or nil) });
end

function presence(attr)
	return stanza("presence", attr);
end