Diff

core/xmlhandlers.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
child 7:dcc5ac721c20
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/xmlhandlers.lua	Sun Aug 24 01:51:02 2008 +0000
@@ -0,0 +1,92 @@
+
+require "util.stanza"
+
+local st = stanza;
+local tostring = tostring;
+local format = string.format;
+local m_random = math.random;
+local t_insert = table.insert;
+local t_remove = table.remove;
+local t_concat = table.concat;
+local t_concatall = function (t, sep) local tt = {}; for _, s in ipairs(t) do t_insert(tt, tostring(s)); end return t_concat(tt, sep); end
+
+local error = error;
+
+module "xmlhandlers"
+
+function init_xmlhandlers(session)
+		local ns_stack = { "" };
+		local curr_ns = "";
+		local curr_tag;
+		local chardata = {};
+		local xml_handlers = {};
+		local log = session.log;
+		local print = function (...) log("info", "xmlhandlers", t_concatall({...}, "\t")); end
+		
+		local send = session.send;
+		
+		local stanza
+		function xml_handlers:StartElement(name, attr)
+			if stanza and #chardata > 0 then
+				stanza:text(t_concat(chardata));
+				print("Char data:", t_concat(chardata));
+				chardata = {};
+			end
+			curr_ns,name = name:match("^(.+):(%w+)$");
+			print("Tag received:", name, tostring(curr_ns));
+			if not stanza then
+				if session.notopen then
+					if name == "stream" then
+						session.host = attr.to or error("Client failed to specify destination hostname");
+			                        session.version = attr.version or 0;
+			                        session.streamid = m_random(1000000, 99999999);
+			                        print(session, session.host, "Client opened stream");
+			                        send("<?xml version='1.0'?>");
+			                        send(format("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' id='%s' from='%s' >", session.streamid, session.host));
+			                        --send("<stream:features>");
+			                        --send("<mechanism>PLAIN</mechanism>");
+        			                --send [[<register xmlns="http://jabber.org/features/iq-register"/> ]]
+        			                --send("</stream:features>");
+						log("info", "core", "Stream opened successfully");
+						session.notopen = nil;
+						return;
+					end
+					error("Client failed to open stream successfully");
+				end
+				if name ~= "iq" and name ~= "presence" and name ~= "message" then
+					error("Client sent invalid top-level stanza");
+				end
+				stanza = st.stanza(name, { to = attr.to, type = attr.type, id = attr.id, xmlns = curr_ns });
+				curr_tag = stanza;
+			else
+				attr.xmlns = curr_ns;
+				stanza:tag(name, attr);
+			end
+		end
+		function xml_handlers:CharacterData(data)
+			if stanza then
+				t_insert(chardata, data);
+			end
+		end
+		function xml_handlers:EndElement(name)
+			curr_ns,name = name:match("^(.+):(%w+)$");
+			--print("<"..name.."/>", tostring(stanza), tostring(#stanza.last_add < 1), tostring(stanza.last_add[#stanza.last_add].name));
+			if (not stanza) or #stanza.last_add < 0 or (#stanza.last_add > 0 and name ~= stanza.last_add[#stanza.last_add].name) then error("XML parse error in client stream"); end
+			if stanza and #chardata > 0 then
+				stanza:text(t_concat(chardata));
+				print("Char data:", t_concat(chardata));
+				chardata = {};
+			end
+			-- Complete stanza
+			print(name, tostring(#stanza.last_add));
+			if #stanza.last_add == 0 then
+				session.stanza_dispatch(stanza);
+				stanza = nil;
+			else
+				stanza:up();
+			end
+		end
+	return xml_handlers;
+end
+
+return init_xmlhandlers;