util/xml.lua
branch0.11
changeset 12185 783056b4e448
parent 8558 4f0f5b49bb03
child 12205 e5e0ab93d7f4
equal deleted inserted replaced
12094:e77735354fad 12185:783056b4e448
     1 
     1 
     2 local st = require "util.stanza";
     2 local st = require "util.stanza";
     3 local lxp = require "lxp";
     3 local lxp = require "lxp";
     4 local t_insert = table.insert;
     4 local t_insert = table.insert;
     5 local t_remove = table.remove;
     5 local t_remove = table.remove;
       
     6 local error = error;
     6 
     7 
     7 local _ENV = nil;
     8 local _ENV = nil;
     8 -- luacheck: std none
     9 -- luacheck: std none
     9 
    10 
    10 local parse_xml = (function()
    11 local parse_xml = (function()
    11 	local ns_prefixes = {
    12 	local ns_prefixes = {
    12 		["http://www.w3.org/XML/1998/namespace"] = "xml";
    13 		["http://www.w3.org/XML/1998/namespace"] = "xml";
    13 	};
    14 	};
    14 	local ns_separator = "\1";
    15 	local ns_separator = "\1";
    15 	local ns_pattern = "^([^"..ns_separator.."]*)"..ns_separator.."?(.*)$";
    16 	local ns_pattern = "^([^"..ns_separator.."]*)"..ns_separator.."?(.*)$";
    16 	return function(xml)
    17 	return function(xml, options)
    17 		--luacheck: ignore 212/self
    18 		--luacheck: ignore 212/self
    18 		local handler = {};
    19 		local handler = {};
    19 		local stanza = st.stanza("root");
    20 		local stanza = st.stanza("root");
    20 		local namespaces = {};
    21 		local namespaces = {};
    21 		local prefixes = {};
    22 		local prefixes = {};
    62 			stanza:text(data);
    63 			stanza:text(data);
    63 		end
    64 		end
    64 		function handler:EndElement()
    65 		function handler:EndElement()
    65 			stanza:up();
    66 			stanza:up();
    66 		end
    67 		end
    67 		local parser = lxp.new(handler, "\1");
    68 		local parser;
       
    69 		-- SECURITY: These two handlers, especially the Doctype one, are required to prevent exploits such as Billion Laughs.
       
    70 		function handler:StartDoctypeDecl()
       
    71 			if not parser.stop or not parser:stop() then
       
    72 				error("Failed to abort parsing");
       
    73 			end
       
    74 		end
       
    75 		function handler:ProcessingInstruction()
       
    76 			if not parser.stop or not parser:stop() then
       
    77 				error("Failed to abort parsing");
       
    78 			end
       
    79 		end
       
    80 		if not options or not options.allow_comments then
       
    81 			-- NOTE: comments are generally harmless and can be useful when parsing configuration files or other data, even user-provided data
       
    82 			function handler:Comment()
       
    83 				if not parser.stop or not parser:stop() then
       
    84 					error("Failed to abort parsing");
       
    85 				end
       
    86 			end
       
    87 		end
       
    88 		parser = lxp.new(handler, ns_separator);
    68 		local ok, err, line, col = parser:parse(xml);
    89 		local ok, err, line, col = parser:parse(xml);
    69 		if ok then ok, err, line, col = parser:parse(); end
    90 		if ok then ok, err, line, col = parser:parse(); end
    70 		--parser:close();
    91 		--parser:close();
    71 		if ok then
    92 		if ok then
    72 			return stanza.tags[1];
    93 			return stanza.tags[1];