util/xmppstream.lua
changeset 5776 bd0ff8ae98a8
parent 5311 86fe6e2fa5ae
child 6054 7a5ddbaf758d
equal deleted inserted replaced
5775:a6c2b8933507 5776:bd0ff8ae98a8
     1 -- Prosody IM
     1 -- Prosody IM
     2 -- Copyright (C) 2008-2010 Matthew Wild
     2 -- Copyright (C) 2008-2010 Matthew Wild
     3 -- Copyright (C) 2008-2010 Waqas Hussain
     3 -- Copyright (C) 2008-2010 Waqas Hussain
     4 -- 
     4 --
     5 -- This project is MIT/X11 licensed. Please see the
     5 -- This project is MIT/X11 licensed. Please see the
     6 -- COPYING file in the source package for more information.
     6 -- COPYING file in the source package for more information.
     7 --
     7 --
     8 
     8 
     9 
     9 
    40 _M.ns_separator = ns_separator;
    40 _M.ns_separator = ns_separator;
    41 _M.ns_pattern = ns_pattern;
    41 _M.ns_pattern = ns_pattern;
    42 
    42 
    43 function new_sax_handlers(session, stream_callbacks)
    43 function new_sax_handlers(session, stream_callbacks)
    44 	local xml_handlers = {};
    44 	local xml_handlers = {};
    45 	
    45 
    46 	local cb_streamopened = stream_callbacks.streamopened;
    46 	local cb_streamopened = stream_callbacks.streamopened;
    47 	local cb_streamclosed = stream_callbacks.streamclosed;
    47 	local cb_streamclosed = stream_callbacks.streamclosed;
    48 	local cb_error = stream_callbacks.error or function(session, e, stanza) error("XML stream error: "..tostring(e)..(stanza and ": "..tostring(stanza) or ""),2); end;
    48 	local cb_error = stream_callbacks.error or function(session, e, stanza) error("XML stream error: "..tostring(e)..(stanza and ": "..tostring(stanza) or ""),2); end;
    49 	local cb_handlestanza = stream_callbacks.handlestanza;
    49 	local cb_handlestanza = stream_callbacks.handlestanza;
    50 	
    50 
    51 	local stream_ns = stream_callbacks.stream_ns or xmlns_streams;
    51 	local stream_ns = stream_callbacks.stream_ns or xmlns_streams;
    52 	local stream_tag = stream_callbacks.stream_tag or "stream";
    52 	local stream_tag = stream_callbacks.stream_tag or "stream";
    53 	if stream_ns ~= "" then
    53 	if stream_ns ~= "" then
    54 		stream_tag = stream_ns..ns_separator..stream_tag;
    54 		stream_tag = stream_ns..ns_separator..stream_tag;
    55 	end
    55 	end
    56 	local stream_error_tag = stream_ns..ns_separator..(stream_callbacks.error_tag or "error");
    56 	local stream_error_tag = stream_ns..ns_separator..(stream_callbacks.error_tag or "error");
    57 	
    57 
    58 	local stream_default_ns = stream_callbacks.default_ns;
    58 	local stream_default_ns = stream_callbacks.default_ns;
    59 	
    59 
    60 	local stack = {};
    60 	local stack = {};
    61 	local chardata, stanza = {};
    61 	local chardata, stanza = {};
    62 	local non_streamns_depth = 0;
    62 	local non_streamns_depth = 0;
    63 	function xml_handlers:StartElement(tagname, attr)
    63 	function xml_handlers:StartElement(tagname, attr)
    64 		if stanza and #chardata > 0 then
    64 		if stanza and #chardata > 0 then
    73 
    73 
    74 		if curr_ns ~= stream_default_ns or non_streamns_depth > 0 then
    74 		if curr_ns ~= stream_default_ns or non_streamns_depth > 0 then
    75 			attr.xmlns = curr_ns;
    75 			attr.xmlns = curr_ns;
    76 			non_streamns_depth = non_streamns_depth + 1;
    76 			non_streamns_depth = non_streamns_depth + 1;
    77 		end
    77 		end
    78 		
    78 
    79 		for i=1,#attr do
    79 		for i=1,#attr do
    80 			local k = attr[i];
    80 			local k = attr[i];
    81 			attr[i] = nil;
    81 			attr[i] = nil;
    82 			local xmlk = xml_namespace[k];
    82 			local xmlk = xml_namespace[k];
    83 			if xmlk then
    83 			if xmlk then
    84 				attr[xmlk] = attr[k];
    84 				attr[xmlk] = attr[k];
    85 				attr[k] = nil;
    85 				attr[k] = nil;
    86 			end
    86 			end
    87 		end
    87 		end
    88 		
    88 
    89 		if not stanza then --if we are not currently inside a stanza
    89 		if not stanza then --if we are not currently inside a stanza
    90 			if session.notopen then
    90 			if session.notopen then
    91 				if tagname == stream_tag then
    91 				if tagname == stream_tag then
    92 					non_streamns_depth = 0;
    92 					non_streamns_depth = 0;
    93 					if cb_streamopened then
    93 					if cb_streamopened then
   100 				return;
   100 				return;
   101 			end
   101 			end
   102 			if curr_ns == "jabber:client" and name ~= "iq" and name ~= "presence" and name ~= "message" then
   102 			if curr_ns == "jabber:client" and name ~= "iq" and name ~= "presence" and name ~= "message" then
   103 				cb_error(session, "invalid-top-level-element");
   103 				cb_error(session, "invalid-top-level-element");
   104 			end
   104 			end
   105 			
   105 
   106 			stanza = setmetatable({ name = name, attr = attr, tags = {} }, stanza_mt);
   106 			stanza = setmetatable({ name = name, attr = attr, tags = {} }, stanza_mt);
   107 		else -- we are inside a stanza, so add a tag
   107 		else -- we are inside a stanza, so add a tag
   108 			t_insert(stack, stanza);
   108 			t_insert(stack, stanza);
   109 			local oldstanza = stanza;
   109 			local oldstanza = stanza;
   110 			stanza = setmetatable({ name = name, attr = attr, tags = {} }, stanza_mt);
   110 			stanza = setmetatable({ name = name, attr = attr, tags = {} }, stanza_mt);
   149 		cb_error(session, "parse-error", "restricted-xml", "Restricted XML, see RFC 6120 section 11.1.");
   149 		cb_error(session, "parse-error", "restricted-xml", "Restricted XML, see RFC 6120 section 11.1.");
   150 		if not parser.stop or not parser:stop() then
   150 		if not parser.stop or not parser:stop() then
   151 			error("Failed to abort parsing");
   151 			error("Failed to abort parsing");
   152 		end
   152 		end
   153 	end
   153 	end
   154 	
   154 
   155 	if lxp_supports_doctype then
   155 	if lxp_supports_doctype then
   156 		xml_handlers.StartDoctypeDecl = restricted_handler;
   156 		xml_handlers.StartDoctypeDecl = restricted_handler;
   157 	end
   157 	end
   158 	xml_handlers.Comment = restricted_handler;
   158 	xml_handlers.Comment = restricted_handler;
   159 	xml_handlers.ProcessingInstruction = restricted_handler;
   159 	xml_handlers.ProcessingInstruction = restricted_handler;
   160 	
   160 
   161 	local function reset()
   161 	local function reset()
   162 		stanza, chardata = nil, {};
   162 		stanza, chardata = nil, {};
   163 		stack = {};
   163 		stack = {};
   164 	end
   164 	end
   165 	
   165 
   166 	local function set_session(stream, new_session)
   166 	local function set_session(stream, new_session)
   167 		session = new_session;
   167 		session = new_session;
   168 	end
   168 	end
   169 	
   169 
   170 	return xml_handlers, { reset = reset, set_session = set_session };
   170 	return xml_handlers, { reset = reset, set_session = set_session };
   171 end
   171 end
   172 
   172 
   173 function new(session, stream_callbacks)
   173 function new(session, stream_callbacks)
   174 	local handlers, meta = new_sax_handlers(session, stream_callbacks);
   174 	local handlers, meta = new_sax_handlers(session, stream_callbacks);