util/stanza.lua
changeset 6780 5de6b93d0190
parent 6504 71b6e8b48a12
child 6824 5de30376bf98
equal deleted inserted replaced
6777:3965662ae091 6780:5de6b93d0190
    33 	end
    33 	end
    34 end
    34 end
    35 
    35 
    36 local xmlns_stanzas = "urn:ietf:params:xml:ns:xmpp-stanzas";
    36 local xmlns_stanzas = "urn:ietf:params:xml:ns:xmpp-stanzas";
    37 
    37 
    38 module "stanza"
    38 local _ENV = nil;
    39 
    39 
    40 stanza_mt = { __type = "stanza" };
    40 local stanza_mt = { __type = "stanza" };
    41 stanza_mt.__index = stanza_mt;
    41 stanza_mt.__index = stanza_mt;
    42 local stanza_mt = stanza_mt;
    42 
    43 
    43 local function stanza(name, attr)
    44 function stanza(name, attr)
       
    45 	local stanza = { name = name, attr = attr or {}, tags = {} };
    44 	local stanza = { name = name, attr = attr or {}, tags = {} };
    46 	return setmetatable(stanza, stanza_mt);
    45 	return setmetatable(stanza, stanza_mt);
    47 end
    46 end
    48 local stanza = stanza;
    47 local stanza = stanza;
    49 
    48 
   198 		self = self:get_child(name, xmlns);
   197 		self = self:get_child(name, xmlns);
   199 	until not self
   198 	until not self
   200 end
   199 end
   201 
   200 
   202 
   201 
   203 local xml_escape
   202 local escape_table = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" };
   204 do
   203 local function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end
   205 	local escape_table = { ["'"] = "&apos;", ["\""] = "&quot;", ["<"] = "&lt;", [">"] = "&gt;", ["&"] = "&amp;" };
       
   206 	function xml_escape(str) return (s_gsub(str, "['&<>\"]", escape_table)); end
       
   207 	_M.xml_escape = xml_escape;
       
   208 end
       
   209 
   204 
   210 local function _dostring(t, buf, self, xml_escape, parentns)
   205 local function _dostring(t, buf, self, xml_escape, parentns)
   211 	local nsid = 0;
   206 	local nsid = 0;
   212 	local name = t.name
   207 	local name = t.name
   213 	t_insert(buf, "<"..name);
   208 	t_insert(buf, "<"..name);
   278 		end
   273 		end
   279 	end
   274 	end
   280 	return type, condition or "undefined-condition", text;
   275 	return type, condition or "undefined-condition", text;
   281 end
   276 end
   282 
   277 
   283 do
   278 local id = 0;
   284 	local id = 0;
   279 local function new_id()
   285 	function new_id()
   280 	id = id + 1;
   286 		id = id + 1;
   281 	return "lx"..id;
   287 		return "lx"..id;
   282 end
   288 	end
   283 
   289 end
   284 local function preserialize(stanza)
   290 
       
   291 function preserialize(stanza)
       
   292 	local s = { name = stanza.name, attr = stanza.attr };
   285 	local s = { name = stanza.name, attr = stanza.attr };
   293 	for _, child in ipairs(stanza) do
   286 	for _, child in ipairs(stanza) do
   294 		if type(child) == "table" then
   287 		if type(child) == "table" then
   295 			t_insert(s, preserialize(child));
   288 			t_insert(s, preserialize(child));
   296 		else
   289 		else
   298 		end
   291 		end
   299 	end
   292 	end
   300 	return s;
   293 	return s;
   301 end
   294 end
   302 
   295 
   303 function deserialize(stanza)
   296 local function deserialize(stanza)
   304 	-- Set metatable
   297 	-- Set metatable
   305 	if stanza then
   298 	if stanza then
   306 		local attr = stanza.attr;
   299 		local attr = stanza.attr;
   307 		for i=1,#attr do attr[i] = nil; end
   300 		for i=1,#attr do attr[i] = nil; end
   308 		local attrx = {};
   301 		local attrx = {};
   335 	end
   328 	end
   336 
   329 
   337 	return stanza;
   330 	return stanza;
   338 end
   331 end
   339 
   332 
   340 local function _clone(stanza)
   333 local function clone(stanza)
   341 	local attr, tags = {}, {};
   334 	local attr, tags = {}, {};
   342 	for k,v in pairs(stanza.attr) do attr[k] = v; end
   335 	for k,v in pairs(stanza.attr) do attr[k] = v; end
   343 	local new = { name = stanza.name, attr = attr, tags = tags };
   336 	local new = { name = stanza.name, attr = attr, tags = tags };
   344 	for i=1,#stanza do
   337 	for i=1,#stanza do
   345 		local child = stanza[i];
   338 		local child = stanza[i];
   346 		if child.name then
   339 		if child.name then
   347 			child = _clone(child);
   340 			child = clone(child);
   348 			t_insert(tags, child);
   341 			t_insert(tags, child);
   349 		end
   342 		end
   350 		t_insert(new, child);
   343 		t_insert(new, child);
   351 	end
   344 	end
   352 	return setmetatable(new, stanza_mt);
   345 	return setmetatable(new, stanza_mt);
   353 end
   346 end
   354 clone = _clone;
   347 
   355 
   348 local function message(attr, body)
   356 function message(attr, body)
       
   357 	if not body then
   349 	if not body then
   358 		return stanza("message", attr);
   350 		return stanza("message", attr);
   359 	else
   351 	else
   360 		return stanza("message", attr):tag("body"):text(body):up();
   352 		return stanza("message", attr):tag("body"):text(body):up();
   361 	end
   353 	end
   362 end
   354 end
   363 function iq(attr)
   355 local function iq(attr)
   364 	if attr and not attr.id then attr.id = new_id(); end
   356 	if attr and not attr.id then attr.id = new_id(); end
   365 	return stanza("iq", attr or { id = new_id() });
   357 	return stanza("iq", attr or { id = new_id() });
   366 end
   358 end
   367 
   359 
   368 function reply(orig)
   360 local function reply(orig)
   369 	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 orig.attr.type) });
   361 	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 orig.attr.type) });
   370 end
   362 end
   371 
   363 
   372 do
   364 local xmpp_stanzas_attr = { xmlns = xmlns_stanzas };
   373 	local xmpp_stanzas_attr = { xmlns = xmlns_stanzas };
   365 local function error_reply(orig, type, condition, message)
   374 	function error_reply(orig, type, condition, message)
   366 	local t = reply(orig);
   375 		local t = reply(orig);
   367 	t.attr.type = "error";
   376 		t.attr.type = "error";
   368 	t:tag("error", {type = type}) --COMPAT: Some day xmlns:stanzas goes here
   377 		t:tag("error", {type = type}) --COMPAT: Some day xmlns:stanzas goes here
   369 	:tag(condition, xmpp_stanzas_attr):up();
   378 			:tag(condition, xmpp_stanzas_attr):up();
   370 	if (message) then t:tag("text", xmpp_stanzas_attr):text(message):up(); end
   379 		if (message) then t:tag("text", xmpp_stanzas_attr):text(message):up(); end
   371 	return t; -- stanza ready for adding app-specific errors
   380 		return t; -- stanza ready for adding app-specific errors
   372 end
   381 	end
   373 
   382 end
   374 local function presence(attr)
   383 
       
   384 function presence(attr)
       
   385 	return stanza("presence", attr);
   375 	return stanza("presence", attr);
   386 end
   376 end
   387 
   377 
   388 if do_pretty_printing then
   378 if do_pretty_printing then
   389 	local style_attrk = getstyle("yellow");
   379 	local style_attrk = getstyle("yellow");
   423 	-- Sorry, fresh out of colours for you guys ;)
   413 	-- Sorry, fresh out of colours for you guys ;)
   424 	stanza_mt.pretty_print = stanza_mt.__tostring;
   414 	stanza_mt.pretty_print = stanza_mt.__tostring;
   425 	stanza_mt.pretty_top_tag = stanza_mt.top_tag;
   415 	stanza_mt.pretty_top_tag = stanza_mt.top_tag;
   426 end
   416 end
   427 
   417 
   428 return _M;
   418 return {
       
   419 	stanza_mt = stanza_mt;
       
   420 	stanza = stanza;
       
   421 	new_id = new_id;
       
   422 	preserialize = preserialize;
       
   423 	deserialize = deserialize;
       
   424 	clone = clone;
       
   425 	message = message;
       
   426 	iq = iq;
       
   427 	reply = reply;
       
   428 	error_reply = error_reply;
       
   429 	presence = presence;
       
   430 };