From ef5d3a714f79ee33ec3c86b8caf3cd3331758bf2 Mon Sep 17 00:00:00 2001 From: "Yamel Senih (http://erpya.com/)" Date: Wed, 5 Dec 2018 20:43:26 -0430 Subject: [PATCH] #2169, Improve default feature for XML parser and builder, reference to issue: https://github.com/adempiere/adempiere/issues/2169 (cherry picked from commit 7978cd9695f35c4780276b4aa2e8299f4b7726a6) --- .../akunagroup/uk/postcode/AddressLookup.java | 3 + base/src/org/adempiere/pipo/PackIn.java | 3 + .../src/org/adempiere/pipo/PackInHandler.java | 4 +- .../org/adempiere/process/rpl/XMLHelper.java | 6 +- base/src/org/compiere/model/MArchive.java | 13 +- base/src/org/compiere/model/MAttachment.java | 11 +- .../compiere/process/MigrationFromXML.java | 2 + base/src/org/compiere/util/ImpExpUtil.java | 5 +- base/src/org/spin/util/XMLUtils.java | 134 ++++++++++++++++++ .../com/_3e/ADInterface/ADServiceImpl.java | 2 + .../org/compiere/cm/xml/XSLTProcessor.java | 3 + 11 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 base/src/org/spin/util/XMLUtils.java diff --git a/base/src/com/akunagroup/uk/postcode/AddressLookup.java b/base/src/com/akunagroup/uk/postcode/AddressLookup.java index 642d7e020b..8c4e7881eb 100644 --- a/base/src/com/akunagroup/uk/postcode/AddressLookup.java +++ b/base/src/com/akunagroup/uk/postcode/AddressLookup.java @@ -39,6 +39,7 @@ import org.adempiere.util.GenerateModel; import org.compiere.util.CLogger; +import org.spin.util.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -338,6 +339,8 @@ private Document fetchResult(URL cgiUrl) { // Get document builder. DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory .newInstance(); + // Add default features + XMLUtils.setDefaultFeatures(docBuilderFactory); DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder(); // Get the connection. URLConnection URLconnection = cgiUrl.openConnection(); diff --git a/base/src/org/adempiere/pipo/PackIn.java b/base/src/org/adempiere/pipo/PackIn.java index 5c2d85d233..ea49c15334 100644 --- a/base/src/org/adempiere/pipo/PackIn.java +++ b/base/src/org/adempiere/pipo/PackIn.java @@ -37,6 +37,7 @@ import org.compiere.util.Env; import org.compiere.util.Ini; import org.compiere.util.Trx; +import org.spin.util.XMLUtils; /** * IntPackIn Tool. @@ -132,6 +133,8 @@ public String importXML(String fileName, Properties ctx, String trxName) throws handler.setCtx(ctx); handler.setProcess(this); SAXParserFactory factory = SAXParserFactory.newInstance(); + // Set default features + XMLUtils.setDefaultFeatures(factory); SAXParser parser = factory.newSAXParser(); String msg = "Start Parser"; log.info(msg); diff --git a/base/src/org/adempiere/pipo/PackInHandler.java b/base/src/org/adempiere/pipo/PackInHandler.java index e66d9f9583..6c9e8581a9 100644 --- a/base/src/org/adempiere/pipo/PackInHandler.java +++ b/base/src/org/adempiere/pipo/PackInHandler.java @@ -101,6 +101,7 @@ import org.compiere.util.Trx; import org.compiere.wf.MWFNode; import org.compiere.wf.MWorkflow; +import org.spin.util.XMLUtils; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; @@ -172,7 +173,8 @@ private void init() throws SAXException { } streamResult_document = new StreamResult(fw_document); tf_document = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); - + // Default features + XMLUtils.setDefaultFeatures(tf_document); try { logDocument = tf_document.newTransformerHandler(); } catch (TransformerConfigurationException e2) { diff --git a/base/src/org/adempiere/process/rpl/XMLHelper.java b/base/src/org/adempiere/process/rpl/XMLHelper.java index 1d4f77eb1e..99b67619fc 100755 --- a/base/src/org/adempiere/process/rpl/XMLHelper.java +++ b/base/src/org/adempiere/process/rpl/XMLHelper.java @@ -40,6 +40,7 @@ import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.spin.util.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -105,7 +106,8 @@ public static Document createDocumentFromFile(String pathToXmlFile) DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); // validate against XML Schema in dbsql2xml.xsd // documentBuilderFactory.setNamespaceAware(true); - + // Add default features + XMLUtils.setDefaultFeatures(documentBuilderFactory); //INFO change validation to true. Someday when xsd file is complete... documentBuilderFactory.setValidating(false); documentBuilderFactory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); @@ -124,6 +126,8 @@ public static Document createDocumentFromString(String str) // String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource"; DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); + // Add default features + XMLUtils.setDefaultFeatures(documentBuilderFactory); // validate against XML Schema in dbsql2xml.xsd // documentBuilderFactory.setNamespaceAware(true); diff --git a/base/src/org/compiere/model/MArchive.java b/base/src/org/compiere/model/MArchive.java index 2992e9a01c..b7b5ee546e 100644 --- a/base/src/org/compiere/model/MArchive.java +++ b/base/src/org/compiere/model/MArchive.java @@ -48,6 +48,7 @@ import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.Env; +import org.spin.util.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; @@ -246,9 +247,11 @@ private byte[] getBinaryDataFromFileSystem() { return null; } - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { + // Add default features + XMLUtils.setDefaultFeatures(factory); final DocumentBuilder builder = factory.newDocumentBuilder(); final Document document = builder.parse(new ByteArrayInputStream(data)); final NodeList entries = document.getElementsByTagName("entry"); @@ -407,9 +410,11 @@ private void saveBinaryDataIntoFileSystem(byte[] inflatedData) { throw new IllegalArgumentException("unable to save MArchive"); } } - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); BufferedOutputStream out = null; try { + // Add default features + XMLUtils.setDefaultFeatures(factory); // create destination folder final File destFolder = new File(m_archivePathRoot + File.separator + getArchivePathSnippet()); @@ -438,7 +443,9 @@ private void saveBinaryDataIntoFileSystem(byte[] inflatedData) { final Source source = new DOMSource(document); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); final Result result = new StreamResult(bos); - final Transformer xformer = TransformerFactory.newInstance().newTransformer(); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + XMLUtils.setDefaultFeatures(transformerFactory); + final Transformer xformer = transformerFactory.newTransformer(); xformer.transform(source, result); final byte[] xmlData = bos.toByteArray(); log.fine(bos.toString()); diff --git a/base/src/org/compiere/model/MAttachment.java b/base/src/org/compiere/model/MAttachment.java index 78c2d34c4c..7e63859ef2 100644 --- a/base/src/org/compiere/model/MAttachment.java +++ b/base/src/org/compiere/model/MAttachment.java @@ -45,6 +45,7 @@ import org.compiere.util.Env; import org.compiere.util.MimeType; +import org.spin.util.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; @@ -560,8 +561,10 @@ private boolean saveLOBDataToFileSystem() setBinaryData(null); return true; } - final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { + // Add default features + XMLUtils.setDefaultFeatures(factory); final DocumentBuilder builder = factory.newDocumentBuilder(); final Document document = builder.newDocument(); final Element root = document.createElement("attachments"); @@ -627,7 +630,9 @@ private boolean saveLOBDataToFileSystem() final Source source = new DOMSource(document); final ByteArrayOutputStream bos = new ByteArrayOutputStream(); final Result result = new StreamResult(bos); - final Transformer xformer = TransformerFactory.newInstance().newTransformer(); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + XMLUtils.setDefaultFeatures(transformerFactory); + final Transformer xformer = transformerFactory.newTransformer(); xformer.transform(source, result); final byte[] xmlData = bos.toByteArray(); log.fine(bos.toString()); @@ -734,6 +739,8 @@ private boolean loadLOBDataFromFileSystem(){ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); try { + // Add default features + XMLUtils.setDefaultFeatures(factory); final DocumentBuilder builder = factory.newDocumentBuilder(); final Document document = builder.parse(new ByteArrayInputStream(data)); final NodeList entries = document.getElementsByTagName("entry"); diff --git a/base/src/org/compiere/process/MigrationFromXML.java b/base/src/org/compiere/process/MigrationFromXML.java index d5e7e6840c..172ce697c9 100644 --- a/base/src/org/compiere/process/MigrationFromXML.java +++ b/base/src/org/compiere/process/MigrationFromXML.java @@ -25,6 +25,7 @@ import org.compiere.util.Msg; import org.compiere.util.Trx; import org.eevolution.service.dsl.ProcessBuilder; +import org.spin.util.XMLUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; @@ -80,6 +81,7 @@ private void loadXML() File file = new File(getFilePathOrName()); try { + XMLUtils.setDefaultFeatures(dbf); builder = dbf.newDocumentBuilder(); List migrationFiles = new ArrayList(); diff --git a/base/src/org/compiere/util/ImpExpUtil.java b/base/src/org/compiere/util/ImpExpUtil.java index 40fdac9299..9a0785d12c 100644 --- a/base/src/org/compiere/util/ImpExpUtil.java +++ b/base/src/org/compiere/util/ImpExpUtil.java @@ -17,6 +17,7 @@ import org.compiere.model.X_AD_Package_Exp_Detail; import org.compiere.print.MPrintFormat; import org.compiere.print.ReportEngine; +import org.spin.util.XMLUtils; import org.xml.sax.helpers.AttributesImpl; @@ -40,7 +41,9 @@ public static File exportPrintFormat(File file, ReportEngine reportEngine) FileOutputStream fos = new FileOutputStream(file); StreamResult streamResult_document = new StreamResult(new OutputStreamWriter(fos,"ISO-8859-1")); PrintFormatElementHandler printFormatHandler = new PrintFormatElementHandler(); - SAXTransformerFactory tf_menu = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); + SAXTransformerFactory tf_menu = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); + // Default features + XMLUtils.setDefaultFeatures(tf_menu); tf_menu.setAttribute("indent-number", new Integer(4)); TransformerHandler packOutDocument = tf_menu.newTransformerHandler(); Transformer serializer_document = packOutDocument.getTransformer(); diff --git a/base/src/org/spin/util/XMLUtils.java b/base/src/org/spin/util/XMLUtils.java new file mode 100644 index 0000000000..46931f049c --- /dev/null +++ b/base/src/org/spin/util/XMLUtils.java @@ -0,0 +1,134 @@ +/************************************************************************************* + * Product: Adempiere ERP & CRM Smart Business Solution * + * This program is free software; you can redistribute it and/or modify it * + * under the terms version 2 or later of the GNU General Public License as published * + * by the Free Software Foundation. This program is distributed in the hope * + * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * + * See the GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License along * + * with this program; if not, write to the Free Software Foundation, Inc., * + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * + * For the text or an alternative of this public license, you may reach us * + * Copyright (C) 2012-2018 E.R.P. Consultores y Asociados, S.A. All Rights Reserved. * + * Contributor(s): Yamel Senih www.erpya.com * + *************************************************************************************/ +package org.spin.util; + +import javax.xml.XMLConstants; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParserFactory; +import javax.xml.stream.XMLInputFactory; +import javax.xml.transform.TransformerFactory; +import javax.xml.validation.Validator; + +import org.xml.sax.SAXNotRecognizedException; +import org.xml.sax.SAXNotSupportedException; +import javax.xml.validation.SchemaFactory; +import javax.xml.transform.sax.SAXTransformerFactory; +import org.xml.sax.XMLReader; + + +/** + * Class for handle XML securitu and other utilities + * @author Yamel Senih, ysenih@erpya.com , http://www.erpya.com + *
  • FR [ 2169 ] Improve default features for XML importer + * @see https://github.com/adempiere/adempiere/issues/2169 + */ +public class XMLUtils { + + /** + * Default features + * @param builder + * @throws ParserConfigurationException + */ + public static void setDefaultFeatures(DocumentBuilderFactory builder) throws ParserConfigurationException { + // Disable external DTDs as well + String FEATURE = "http://apache.org/xml/features/disallow-doctype-decl"; + builder.setFeature(FEATURE, true); + FEATURE = "http://xml.org/sax/features/external-general-entities"; + builder.setFeature(FEATURE, false); + FEATURE = "http://xml.org/sax/features/external-parameter-entities"; + builder.setFeature(FEATURE, false); + FEATURE = "http://apache.org/xml/features/nonvalidating/load-external-dtd"; + builder.setFeature(FEATURE, false); + builder.setXIncludeAware(false); + builder.setExpandEntityReferences(false); + } + + /** + * Set default features + * @param transformerFactory + */ + public static void setDefaultFeatures(TransformerFactory transformerFactory) { + transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + transformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + } + + /** + * Default features for input factory + * @param xmlInputFactory + */ + public static void setDefaultFeatures(XMLInputFactory xmlInputFactory) { + xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false); + xmlInputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", false); + } + + /** + * Default features for validator + * @param validator + * @throws SAXNotRecognizedException + * @throws SAXNotSupportedException + */ + public static void setDefaultFeatures(Validator validator) throws SAXNotRecognizedException, SAXNotSupportedException { + validator.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + validator.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + } + + /** + * Set default features for Schema factory + * @param factory + * @throws SAXNotSupportedException + * @throws SAXNotRecognizedException + */ + public static void setDefaultFeatures(SchemaFactory factory) throws SAXNotRecognizedException, SAXNotSupportedException { + factory.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + factory.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, ""); + } + + /** + * Set default features for SAX Transformer Factory + * @param saxTransformerFactory + */ + public static void setDefaultFeatures(SAXTransformerFactory saxTransformerFactory) { + saxTransformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, ""); + saxTransformerFactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, ""); + } + + /** + * Default Features + * @param reader + * @throws SAXNotRecognizedException + * @throws SAXNotSupportedException + */ + public static void setDefaultFeatures(XMLReader reader) throws SAXNotRecognizedException, SAXNotSupportedException { + reader.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); + reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + reader.setFeature("http://xml.org/sax/features/external-general-entities", false); + reader.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + } + + /** + * Set Default features + * @param saxParserFactory + * @throws SAXNotRecognizedException + * @throws SAXNotSupportedException + * @throws ParserConfigurationException + */ + public static void setDefaultFeatures(SAXParserFactory saxParserFactory) throws SAXNotRecognizedException, SAXNotSupportedException, ParserConfigurationException { + saxParserFactory.setFeature("http://xml.org/sax/features/external-general-entities", false); + saxParserFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); + saxParserFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); + } +} diff --git a/org.adempiere.webservice/WEB-INF/src/com/_3e/ADInterface/ADServiceImpl.java b/org.adempiere.webservice/WEB-INF/src/com/_3e/ADInterface/ADServiceImpl.java index c7f761537c..7a953c4023 100644 --- a/org.adempiere.webservice/WEB-INF/src/com/_3e/ADInterface/ADServiceImpl.java +++ b/org.adempiere.webservice/WEB-INF/src/com/_3e/ADInterface/ADServiceImpl.java @@ -38,6 +38,7 @@ import org.compiere.util.Language; import org.compiere.util.Login; import org.compiere.util.ValueNamePair; +import org.spin.util.XMLUtils; import org.w3c.dom.Document; import pl.x3E.adInterface.ADLoginRequest; @@ -328,6 +329,7 @@ public String getStringFromDocument(Document doc) StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); TransformerFactory tf = TransformerFactory.newInstance(); + XMLUtils.setDefaultFeatures(tf); Transformer transformer = tf.newTransformer(); transformer.transform(domSource, result); return writer.toString(); diff --git a/webCM/src/main/servlet/org/compiere/cm/xml/XSLTProcessor.java b/webCM/src/main/servlet/org/compiere/cm/xml/XSLTProcessor.java index 88e9283dfe..d15d610412 100644 --- a/webCM/src/main/servlet/org/compiere/cm/xml/XSLTProcessor.java +++ b/webCM/src/main/servlet/org/compiere/cm/xml/XSLTProcessor.java @@ -28,6 +28,8 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.spin.util.XMLUtils; + /** * @author YS * @version $Id$ @@ -62,6 +64,7 @@ public static StringBuffer run (HttpServletRequest request, { Calendar myCal = Calendar.getInstance (); TransformerFactory tFactory = TransformerFactory.newInstance (); + XMLUtils.setDefaultFeatures(tFactory); Transformer transformer = tFactory.newTransformer (new StreamSource ( new StringReader (xslStream))); Enumeration e = request.getParameterNames ();