}
}
- private static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ static final DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
static {
documentBuilderFactory.setNamespaceAware(true);
documentBuilderFactory.setValidating(false);
+
trySetSAXFeature(documentBuilderFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ trySetSAXFeature(documentBuilderFactory, POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR, false);
+ trySetSAXFeature(documentBuilderFactory, POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD, false);
trySetXercesSecurityManager(documentBuilderFactory);
}
Object mgr = Class.forName(securityManagerClassName).newInstance();
Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
setLimit.invoke(mgr, 4096);
- dbf.setAttribute("http://apache.org/xml/properties/security-manager", mgr);
+ dbf.setAttribute(POIXMLConstants.PROPERTY_SECURITY_MANAGER, mgr);
// Stop once one can be setup without error
return;
} catch (ClassNotFoundException e) {
}
// separate old version of Xerces not found => use the builtin way of setting the property
- dbf.setAttribute("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit", 4096);
+ dbf.setAttribute(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT, 4096);
}
/**
--- /dev/null
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ooxml.util;
+
+public class POIXMLConstants {
+ public static final String FEATURE_LOAD_DTD_GRAMMAR = "http://apache.org/xml/features/nonvalidating/load-dtd-grammar";
+ public static final String FEATURE_LOAD_EXTERNAL_DTD = "http://apache.org/xml/features/nonvalidating/load-external-dtd";
+ public static final String PROPERTY_ENTITY_EXPANSION_LIMIT = "http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit";
+ public static final String PROPERTY_SECURITY_MANAGER = "http://apache.org/xml/properties/security-manager";
+}
saxFactory = SAXParserFactory.newInstance();
saxFactory.setValidating(false);
saxFactory.setNamespaceAware(true);
+ trySetSAXFeature(saxFactory, XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ trySetSAXFeature(saxFactory, POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR, false);
+ trySetSAXFeature(saxFactory, POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD, false);
} catch (RuntimeException | Error re) { // NOSONAR
// this also catches NoClassDefFoundError, which may be due to a local class path issue
// This may occur if the code is run inside a web container
}
}
+ private static void trySetSAXFeature(SAXParserFactory spf, String feature, boolean flag) {
+ try {
+ spf.setFeature(feature, flag);
+ } catch (Exception e) {
+ logger.log(POILogger.WARN, "SAX Feature unsupported", feature, e);
+ } catch (AbstractMethodError ame) {
+ logger.log(POILogger.WARN, "Cannot set SAX feature because outdated XML parser in classpath", feature, ame);
+ }
+ }
+
private static void trySetSAXFeature(XMLReader xmlReader, String feature) {
try {
xmlReader.setFeature(feature, true);
Object mgr = Class.forName(securityManagerClassName).newInstance();
Method setLimit = mgr.getClass().getMethod("setEntityExpansionLimit", Integer.TYPE);
setLimit.invoke(mgr, 4096);
- xmlReader.setProperty("http://apache.org/xml/properties/security-manager", mgr);
+ xmlReader.setProperty(POIXMLConstants.PROPERTY_SECURITY_MANAGER, mgr);
// Stop once one can be setup without error
return;
} catch (ClassNotFoundException e) {
// separate old version of Xerces not found => use the builtin way of setting the property
try {
- xmlReader.setProperty("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit", 4096);
+ xmlReader.setProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT, 4096);
} catch (SAXException e) { // NOSONAR - also catch things like NoClassDefError here
// throttle the log somewhat as it can spam the log otherwise
if(System.currentTimeMillis() > lastLog + TimeUnit.MINUTES.toMillis(5)) {
--- /dev/null
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+package org.apache.poi.ooxml.util;
+
+import org.junit.Test;
+import org.xml.sax.InputSource;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import java.io.ByteArrayInputStream;
+
+import static org.junit.Assert.*;
+
+public class TestDocumentHelper {
+ @Test
+ public void testDocumentBuilder() throws Exception {
+ DocumentBuilder documentBuilder = DocumentHelper.newDocumentBuilder();
+ assertNotSame(documentBuilder, DocumentHelper.newDocumentBuilder());
+ assertTrue(documentBuilder.isNamespaceAware());
+ assertFalse(documentBuilder.isValidating());
+ documentBuilder.parse(new InputSource(new ByteArrayInputStream("<xml></xml>".getBytes("UTF-8"))));
+ }
+
+ @Test
+ public void testDocumentBuilderFactory() throws Exception {
+ assertTrue(DocumentHelper.documentBuilderFactory.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
+ assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
+ assertFalse(DocumentHelper.documentBuilderFactory.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
+ }
+}
==================================================================== */
package org.apache.poi.ooxml.util;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.io.ByteArrayInputStream;
XMLReader reader = SAXHelper.newXMLReader();
assertNotSame(reader, SAXHelper.newXMLReader());
assertTrue(reader.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING));
+ assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_DTD_GRAMMAR));
+ assertFalse(reader.getFeature(POIXMLConstants.FEATURE_LOAD_EXTERNAL_DTD));
assertEquals(SAXHelper.IGNORING_ENTITY_RESOLVER, reader.getEntityResolver());
- assertNotNull(reader.getProperty("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit"));
- assertEquals("4096", reader.getProperty("http://www.oracle.com/xml/jaxp/properties/entityExpansionLimit"));
- assertNotNull(reader.getProperty("http://apache.org/xml/properties/security-manager"));
+ assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
+ assertEquals("4096", reader.getProperty(POIXMLConstants.PROPERTY_ENTITY_EXPANSION_LIMIT));
+ assertNotNull(reader.getProperty(POIXMLConstants.PROPERTY_SECURITY_MANAGER));
reader.parse(new InputSource(new ByteArrayInputStream("<xml></xml>".getBytes("UTF-8"))));
}