mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 10:04:21 +00:00
Merge pull request #11030 from kshepherd/saf-xml-fix-2
Improve SAF Import XML handling
This commit is contained in:
@@ -10,7 +10,6 @@ package org.dspace.administer;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -18,6 +17,7 @@ import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
@@ -49,8 +49,9 @@ public class RegistryImporter {
|
||||
*/
|
||||
public static Document loadXML(String filename)
|
||||
throws IOException, ParserConfigurationException, SAXException {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder();
|
||||
// This XML builder will *not* disable external entities as XML
|
||||
// registries are considered trusted content
|
||||
DocumentBuilder builder = XMLUtils.getTrustedDocumentBuilder();
|
||||
|
||||
Document document = builder.parse(new File(filename));
|
||||
|
||||
|
@@ -13,7 +13,6 @@ import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -29,6 +28,7 @@ import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.BitstreamFormat;
|
||||
import org.dspace.content.factory.ContentServiceFactory;
|
||||
@@ -266,8 +266,9 @@ public class RegistryLoader {
|
||||
*/
|
||||
private static Document loadXML(String filename) throws IOException,
|
||||
ParserConfigurationException, SAXException {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder();
|
||||
// This XML builder will *not* disable external entities as XML
|
||||
// registries are considered trusted content
|
||||
DocumentBuilder builder = XMLUtils.getTrustedDocumentBuilder();
|
||||
|
||||
return builder.parse(new File(filename));
|
||||
}
|
||||
|
@@ -27,7 +27,6 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -43,6 +42,7 @@ import org.apache.commons.cli.Option;
|
||||
import org.apache.commons.cli.Options;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
@@ -613,8 +613,8 @@ public class StructBuilder {
|
||||
*/
|
||||
private static org.w3c.dom.Document loadXML(InputStream input)
|
||||
throws IOException, ParserConfigurationException, SAXException {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder();
|
||||
// This builder factory does not disable external DTD, entities, etc.
|
||||
DocumentBuilder builder = XMLUtils.getTrustedDocumentBuilder();
|
||||
|
||||
org.w3c.dom.Document document = builder.parse(input);
|
||||
|
||||
|
@@ -29,6 +29,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.sql.SQLException;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
@@ -48,7 +49,6 @@ import java.util.UUID;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -68,6 +68,7 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.itemimport.service.ItemImportService;
|
||||
import org.dspace.app.util.LocalSchemaFilenameFilter;
|
||||
import org.dspace.app.util.RelationshipUtils;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.authorize.ResourcePolicy;
|
||||
import org.dspace.authorize.service.AuthorizeService;
|
||||
@@ -180,6 +181,8 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
@Autowired(required = true)
|
||||
protected MetadataValueService metadataValueService;
|
||||
|
||||
protected DocumentBuilder builder;
|
||||
|
||||
protected String tempWorkDir;
|
||||
|
||||
protected boolean isTest = false;
|
||||
@@ -743,15 +746,22 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
myitem = wi.getItem();
|
||||
}
|
||||
|
||||
// normalize and validate path to make sure itemname doesn't contain path traversal
|
||||
Path itemPath = new File(path + File.separatorChar + itemname + File.separatorChar)
|
||||
.toPath().normalize();
|
||||
if (!itemPath.startsWith(path)) {
|
||||
throw new IOException("Illegal item metadata path: '" + itemPath);
|
||||
}
|
||||
// Normalization chops off the last separator, and we need to put it back
|
||||
String itemPathDir = itemPath.toString() + File.separatorChar;
|
||||
|
||||
// now fill out dublin core for item
|
||||
loadMetadata(c, myitem, path + File.separatorChar + itemname
|
||||
+ File.separatorChar);
|
||||
loadMetadata(c, myitem, itemPathDir);
|
||||
|
||||
// and the bitstreams from the contents file
|
||||
// process contents file, add bistreams and bundles, return any
|
||||
// non-standard permissions
|
||||
List<String> options = processContentsFile(c, myitem, path
|
||||
+ File.separatorChar + itemname, "contents");
|
||||
List<String> options = processContentsFile(c, myitem, itemPathDir, "contents");
|
||||
|
||||
if (useWorkflow) {
|
||||
// don't process handle file
|
||||
@@ -769,8 +779,7 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
}
|
||||
} else {
|
||||
// only process handle file if not using workflow system
|
||||
String myhandle = processHandleFile(c, myitem, path
|
||||
+ File.separatorChar + itemname, "handle");
|
||||
String myhandle = processHandleFile(c, myitem, itemPathDir, "handle");
|
||||
|
||||
// put item in system
|
||||
if (!isTest) {
|
||||
@@ -1889,9 +1898,7 @@ public class ItemImportServiceImpl implements ItemImportService, InitializingBea
|
||||
*/
|
||||
protected Document loadXML(String filename) throws IOException,
|
||||
ParserConfigurationException, SAXException {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
|
||||
.newDocumentBuilder();
|
||||
|
||||
DocumentBuilder builder = XMLUtils.getDocumentBuilder();
|
||||
return builder.parse(new File(filename));
|
||||
}
|
||||
|
||||
|
@@ -23,8 +23,6 @@ import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
@@ -33,6 +31,7 @@ import javax.xml.transform.TransformerFactory;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.LocalSchemaFilenameFilter;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
@@ -52,7 +51,6 @@ public class ItemArchive {
|
||||
|
||||
public static final String DUBLIN_CORE_XML = "dublin_core.xml";
|
||||
|
||||
protected static DocumentBuilder builder = null;
|
||||
protected Transformer transformer = null;
|
||||
|
||||
protected List<DtoMetadata> dtomList = null;
|
||||
@@ -95,14 +93,14 @@ public class ItemArchive {
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(new File(dir, DUBLIN_CORE_XML));
|
||||
itarch.dtomList = MetadataUtilities.loadDublinCore(getDocumentBuilder(), is);
|
||||
itarch.dtomList = MetadataUtilities.loadDublinCore(XMLUtils.getDocumentBuilder(), is);
|
||||
|
||||
//The code to search for local schema files was copied from org.dspace.app.itemimport
|
||||
// .ItemImportServiceImpl.java
|
||||
File file[] = dir.listFiles(new LocalSchemaFilenameFilter());
|
||||
for (int i = 0; i < file.length; i++) {
|
||||
is = new FileInputStream(file[i]);
|
||||
itarch.dtomList.addAll(MetadataUtilities.loadDublinCore(getDocumentBuilder(), is));
|
||||
itarch.dtomList.addAll(MetadataUtilities.loadDublinCore(XMLUtils.getDocumentBuilder(), is));
|
||||
}
|
||||
} finally {
|
||||
if (is != null) {
|
||||
@@ -126,14 +124,6 @@ public class ItemArchive {
|
||||
return itarch;
|
||||
}
|
||||
|
||||
protected static DocumentBuilder getDocumentBuilder()
|
||||
throws ParserConfigurationException {
|
||||
if (builder == null) {
|
||||
builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
}
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for Transformer
|
||||
*
|
||||
@@ -318,7 +308,7 @@ public class ItemArchive {
|
||||
|
||||
try {
|
||||
out = new FileOutputStream(new File(dir, "dublin_core.xml"));
|
||||
Document doc = MetadataUtilities.writeDublinCore(getDocumentBuilder(), undoDtomList);
|
||||
Document doc = MetadataUtilities.writeDublinCore(XMLUtils.getDocumentBuilder(), undoDtomList);
|
||||
MetadataUtilities.writeDocument(doc, getTransformer(), out);
|
||||
|
||||
// if undo has delete bitstream
|
||||
|
@@ -19,6 +19,7 @@ import java.util.TreeMap;
|
||||
import org.apache.commons.cli.ParseException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.core.Context;
|
||||
import org.dspace.scripts.DSpaceRunnable;
|
||||
import org.dspace.scripts.DSpaceRunnable.StepResult;
|
||||
@@ -314,7 +315,7 @@ public class ScriptLauncher {
|
||||
String config = kernelImpl.getConfigurationService().getProperty("dspace.dir") +
|
||||
System.getProperty("file.separator") + "config" +
|
||||
System.getProperty("file.separator") + "launcher.xml";
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document doc = null;
|
||||
try {
|
||||
doc = saxBuilder.build(config);
|
||||
|
@@ -18,6 +18,7 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.sfx.service.SFXFileReaderService;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.DCPersonName;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.content.MetadataValue;
|
||||
@@ -79,9 +80,9 @@ public class SFXFileReaderServiceImpl implements SFXFileReaderService {
|
||||
log.info("Parsing XML file... " + fileName);
|
||||
DocumentBuilder docBuilder;
|
||||
Document doc = null;
|
||||
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||
docBuilderFactory.setIgnoringElementContentWhitespace(true);
|
||||
try {
|
||||
DocumentBuilderFactory docBuilderFactory = XMLUtils.getDocumentBuilderFactory();
|
||||
docBuilderFactory.setIgnoringElementContentWhitespace(true);
|
||||
docBuilder = docBuilderFactory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException e) {
|
||||
log.error("Wrong parser configuration: " + e.getMessage());
|
||||
|
@@ -15,7 +15,6 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.FactoryConfigurationError;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -118,15 +117,17 @@ public class DCInputsReader {
|
||||
formDefns = new HashMap<String, List<List<Map<String, String>>>>();
|
||||
valuePairs = new HashMap<String, List<String>>();
|
||||
|
||||
String uri = "file:" + new File(fileName).getAbsolutePath();
|
||||
File inputFile = new File(fileName);
|
||||
String inputFileDir = inputFile.toPath().normalize().getParent().toString();
|
||||
|
||||
String uri = "file:" + inputFile.getAbsolutePath();
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setValidating(false);
|
||||
factory.setIgnoringComments(true);
|
||||
factory.setIgnoringElementContentWhitespace(true);
|
||||
|
||||
DocumentBuilder db = factory.newDocumentBuilder();
|
||||
// This document builder will *not* disable external
|
||||
// entities as they can be useful in managing large forms, but
|
||||
// it will restrict them to be within the directory that the
|
||||
// current input form XML file exists (or a sub-directory)
|
||||
DocumentBuilder db = XMLUtils.getTrustedDocumentBuilder(inputFileDir);
|
||||
Document doc = db.parse(uri);
|
||||
doNodes(doc);
|
||||
checkValues();
|
||||
|
@@ -11,7 +11,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import org.apache.commons.cli.CommandLine;
|
||||
@@ -139,8 +138,9 @@ public class InitializeEntities {
|
||||
private void parseXMLToRelations(Context context, String fileLocation) throws AuthorizeException {
|
||||
try {
|
||||
File fXmlFile = new File(fileLocation);
|
||||
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
|
||||
// This XML builder will allow external entities, so the relationship types XML should
|
||||
// be considered trusted by administrators
|
||||
DocumentBuilder dBuilder = XMLUtils.getTrustedDocumentBuilder();
|
||||
Document doc = dBuilder.parse(fXmlFile);
|
||||
|
||||
doc.getDocumentElement().normalize();
|
||||
|
@@ -16,7 +16,6 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.FactoryConfigurationError;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -170,13 +169,10 @@ public class SubmissionConfigReader {
|
||||
String uri = "file:" + new File(fileName).getAbsolutePath();
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory
|
||||
.newInstance();
|
||||
factory.setValidating(false);
|
||||
factory.setIgnoringComments(true);
|
||||
factory.setIgnoringElementContentWhitespace(true);
|
||||
|
||||
DocumentBuilder db = factory.newDocumentBuilder();
|
||||
// This document builder factory will *not* disable external
|
||||
// entities as they can be useful in managing large forms, but
|
||||
// it will restrict them to the config dir containing submission definitions
|
||||
DocumentBuilder db = XMLUtils.getTrustedDocumentBuilder(configDir);
|
||||
Document doc = db.parse(uri);
|
||||
doNodes(doc);
|
||||
} catch (FactoryConfigurationError fe) {
|
||||
|
@@ -7,12 +7,26 @@
|
||||
*/
|
||||
package org.dspace.app.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.stream.XMLInputFactory;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.jdom2.input.SAXBuilder;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.EntityResolver;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Simple class to read information from small XML using DOM manipulation
|
||||
@@ -161,4 +175,195 @@ public class XMLUtils {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and return a javax DocumentBuilderFactory with NO security
|
||||
* applied. This is intended only for internal, administrative/configuration
|
||||
* use where external entities and other dangerous features are actually
|
||||
* purposefully included.
|
||||
* The method here is tiny, but may be expanded with other features like
|
||||
* whitespace handling, and calling this method name helps to document
|
||||
* the fact that the caller knows it is trusting the XML source / factory.
|
||||
*
|
||||
* @return document builder factory to generate new builders
|
||||
* @throws ParserConfigurationException
|
||||
*/
|
||||
public static DocumentBuilderFactory getTrustedDocumentBuilderFactory()
|
||||
throws ParserConfigurationException {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and return the javax DocumentBuilderFactory with some basic security
|
||||
* applied to avoid XXE attacks and other unwanted content inclusion
|
||||
* @return document builder factory to generate new builders
|
||||
* @throws ParserConfigurationException
|
||||
*/
|
||||
public static DocumentBuilderFactory getDocumentBuilderFactory()
|
||||
throws ParserConfigurationException {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
// No DOCTYPE / DTDs
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
// No external general entities
|
||||
factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
// No external parameter entities
|
||||
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
// No external DTDs
|
||||
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
// Even if entities somehow get defined, they will not be expanded
|
||||
factory.setExpandEntityReferences(false);
|
||||
// Disable "XInclude" markup processing
|
||||
factory.setXIncludeAware(false);
|
||||
|
||||
return factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and return a javax DocumentBuilder with less security
|
||||
* applied. This is intended only for internal, administrative/configuration
|
||||
* use where external entities and other dangerous features are actually
|
||||
* purposefully included, but are only allowed from specified paths, e.g.
|
||||
* dspace.dir or some other path specified by the java caller.
|
||||
* The method here is tiny, but may be expanded with other features like
|
||||
* whitespace handling, and calling this method name helps to document
|
||||
* the fact that the caller knows it is trusting the XML source / builder
|
||||
* <p>
|
||||
* If no allowedPaths are passed, then all external entities are rejected
|
||||
*
|
||||
* @return document builder with no security features set
|
||||
* @throws ParserConfigurationException if the builder can not be configured
|
||||
*/
|
||||
public static DocumentBuilder getTrustedDocumentBuilder(String... allowedPaths)
|
||||
throws ParserConfigurationException {
|
||||
DocumentBuilderFactory factory = getTrustedDocumentBuilderFactory();
|
||||
factory.setValidating(false);
|
||||
factory.setIgnoringComments(true);
|
||||
factory.setIgnoringElementContentWhitespace(true);
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
builder.setEntityResolver(new PathRestrictedEntityResolver(allowedPaths));
|
||||
return factory.newDocumentBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and return the javax DocumentBuilder with some basic security applied
|
||||
* to avoid XXE attacks and other unwanted content inclusion
|
||||
* @return document builder for use in XML parsing
|
||||
* @throws ParserConfigurationException if the builder can not be configured
|
||||
*/
|
||||
public static DocumentBuilder getDocumentBuilder()
|
||||
throws ParserConfigurationException {
|
||||
return getDocumentBuilderFactory().newDocumentBuilder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and return the SAX document builder with some basic security applied
|
||||
* to avoid XXE attacks and other unwanted content inclusion
|
||||
* @return SAX document builder for use in XML parsing
|
||||
*/
|
||||
public static SAXBuilder getSAXBuilder() {
|
||||
return getSAXBuilder(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and return the SAX document builder with some basic security applied
|
||||
* to avoid XXE attacks and other unwanted content inclusion
|
||||
* @param validate whether to use JDOM XSD validation
|
||||
* @return SAX document builder for use in XML parsing
|
||||
*/
|
||||
public static SAXBuilder getSAXBuilder(boolean validate) {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
if (validate) {
|
||||
saxBuilder.setValidation(true);
|
||||
}
|
||||
// No DOCTYPE / DTDs
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
// No external general entities
|
||||
saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
// No external parameter entities
|
||||
saxBuilder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
// No external DTDs
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
|
||||
// Don't expand entities
|
||||
saxBuilder.setExpandEntities(false);
|
||||
|
||||
return saxBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize and return the Java XML Input Factory with some basic security applied
|
||||
* to avoid XXE attacks and other unwanted content inclusion
|
||||
* @return XML input factory for use in XML parsing
|
||||
*/
|
||||
public static XMLInputFactory getXMLInputFactory() {
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
|
||||
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
|
||||
return xmlInputFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* This entity resolver accepts one or more path strings in its
|
||||
* constructor and throws a SAXException if the entity systemID
|
||||
* is not within the allowed path (or a subdirectory).
|
||||
* If no parameters are passed, then this effectively disallows
|
||||
* any external entity resolution.
|
||||
*/
|
||||
public static class PathRestrictedEntityResolver implements EntityResolver {
|
||||
private final List<String> allowedBasePaths;
|
||||
|
||||
public PathRestrictedEntityResolver(String... allowedBasePaths) {
|
||||
this.allowedBasePaths = Arrays.asList(allowedBasePaths);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputSource resolveEntity(String publicId, String systemId)
|
||||
throws SAXException, IOException {
|
||||
|
||||
if (systemId == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String filePath;
|
||||
if (systemId.startsWith("file://")) {
|
||||
filePath = systemId.substring(7);
|
||||
} else if (systemId.startsWith("file:")) {
|
||||
filePath = systemId.substring(5);
|
||||
} else if (!systemId.contains("://")) {
|
||||
filePath = systemId;
|
||||
} else {
|
||||
throw new SAXException("External resources not allowed: " + systemId +
|
||||
". Only local file paths are permitted.");
|
||||
}
|
||||
|
||||
Path resolvedPath;
|
||||
try {
|
||||
resolvedPath = Paths.get(filePath).toAbsolutePath().normalize();
|
||||
} catch (Exception e) {
|
||||
throw new SAXException("Invalid path: " + systemId, e);
|
||||
}
|
||||
|
||||
boolean isAllowed = false;
|
||||
for (String basePath : allowedBasePaths) {
|
||||
Path allowedPath = Paths.get(basePath).toAbsolutePath().normalize();
|
||||
if (resolvedPath.startsWith(allowedPath)) {
|
||||
isAllowed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAllowed) {
|
||||
throw new SAXException("Access denied to path: " + resolvedPath);
|
||||
}
|
||||
|
||||
File file = resolvedPath.toFile();
|
||||
if (!file.exists() || !file.canRead()) {
|
||||
throw new SAXException("File not found or not readable: " + resolvedPath);
|
||||
}
|
||||
|
||||
return new InputSource(new FileInputStream(file));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.packager.PackageDisseminator;
|
||||
@@ -129,7 +130,7 @@ public class METSDisseminationCrosswalk
|
||||
|
||||
try {
|
||||
//Return just the root Element of the METS file
|
||||
SAXBuilder builder = new SAXBuilder();
|
||||
SAXBuilder builder = XMLUtils.getSAXBuilder();
|
||||
Document metsDocument = builder.build(tempFile);
|
||||
return metsDocument.getRootElement();
|
||||
} catch (JDOMException je) {
|
||||
|
@@ -22,6 +22,7 @@ import java.util.Properties;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
@@ -144,7 +145,7 @@ public class MODSDisseminationCrosswalk extends SelfNamedPlugin
|
||||
MODS_NS.getURI() + " " + MODS_XSD;
|
||||
|
||||
private static final XMLOutputter outputUgly = new XMLOutputter();
|
||||
private static final SAXBuilder builder = new SAXBuilder();
|
||||
private static final SAXBuilder builder = XMLUtils.getSAXBuilder();
|
||||
|
||||
private Map<String, modsTriple> modsMap = null;
|
||||
|
||||
|
@@ -22,6 +22,7 @@ import java.util.Properties;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
@@ -125,7 +126,7 @@ public class QDCCrosswalk extends SelfNamedPlugin
|
||||
// XML schemaLocation fragment for this crosswalk, from config.
|
||||
private String schemaLocation = null;
|
||||
|
||||
private static final SAXBuilder builder = new SAXBuilder();
|
||||
private static final SAXBuilder builder = XMLUtils.getSAXBuilder();
|
||||
|
||||
protected ItemService itemService = ContentServiceFactory.getInstance().getItemService();
|
||||
|
||||
|
@@ -13,6 +13,7 @@ import java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.packager.PackageDisseminator;
|
||||
@@ -208,7 +209,7 @@ public class RoleCrosswalk
|
||||
|
||||
try {
|
||||
//Try to parse our XML results (which were disseminated by the Packager)
|
||||
SAXBuilder builder = new SAXBuilder();
|
||||
SAXBuilder builder = XMLUtils.getSAXBuilder();
|
||||
Document xmlDocument = builder.build(tempFile);
|
||||
//If XML parsed successfully, return root element of doc
|
||||
if (xmlDocument != null && xmlDocument.hasRootElement()) {
|
||||
|
@@ -18,6 +18,7 @@ import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
@@ -297,7 +298,7 @@ public class XSLTIngestionCrosswalk
|
||||
"Failed to initialize transformer, probably error loading stylesheet.");
|
||||
}
|
||||
|
||||
SAXBuilder builder = new SAXBuilder();
|
||||
SAXBuilder builder = XMLUtils.getSAXBuilder();
|
||||
Document inDoc = builder.build(new FileInputStream(argv[i + 1]));
|
||||
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
|
||||
List dimList;
|
||||
|
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Bitstream;
|
||||
import org.dspace.content.Bundle;
|
||||
@@ -265,12 +266,13 @@ public class METSManifest {
|
||||
public static METSManifest create(InputStream is, boolean validate, String configName)
|
||||
throws IOException,
|
||||
MetadataValidationException {
|
||||
SAXBuilder builder = new SAXBuilder(validate);
|
||||
|
||||
SAXBuilder builder = XMLUtils.getSAXBuilder();
|
||||
builder.setIgnoringElementContentWhitespace(true);
|
||||
|
||||
// Set validation feature
|
||||
if (validate) {
|
||||
builder.setValidation(true);
|
||||
builder.setFeature("http://apache.org/xml/features/validation/schema", true);
|
||||
|
||||
// Tell the parser where local copies of schemas are, to speed up
|
||||
@@ -278,10 +280,6 @@ public class METSManifest {
|
||||
if (localSchemas.length() > 0) {
|
||||
builder.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation", localSchemas);
|
||||
}
|
||||
} else {
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur.
|
||||
// See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
|
||||
builder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
}
|
||||
|
||||
// Parse the METS file
|
||||
|
@@ -21,6 +21,7 @@ import javax.xml.parsers.ParserConfigurationException;
|
||||
import org.apache.commons.codec.DecoderException;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.Collection;
|
||||
import org.dspace.content.Community;
|
||||
@@ -385,7 +386,7 @@ public class RoleIngester implements PackageIngester {
|
||||
Document document;
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilderFactory dbf = XMLUtils.getDocumentBuilderFactory();
|
||||
dbf.setIgnoringComments(true);
|
||||
dbf.setCoalescing(true);
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
@@ -419,7 +420,7 @@ public class RoleIngester implements PackageIngester {
|
||||
Document document;
|
||||
|
||||
try {
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilderFactory dbf = XMLUtils.getDocumentBuilderFactory();
|
||||
dbf.setIgnoringComments(true);
|
||||
dbf.setCoalescing(true);
|
||||
DocumentBuilder db = dbf.newDocumentBuilder();
|
||||
|
@@ -37,6 +37,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.client.DSpaceHttpClientFactory;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.Item;
|
||||
@@ -204,13 +205,9 @@ public class MetadataWebService extends AbstractCurationTask implements Namespac
|
||||
}
|
||||
}
|
||||
// initialize response document parser
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setNamespaceAware(true);
|
||||
try {
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
// See https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html
|
||||
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
|
||||
factory.setXIncludeAware(false);
|
||||
DocumentBuilderFactory factory = XMLUtils.getDocumentBuilderFactory();
|
||||
factory.setNamespaceAware(true);
|
||||
docBuilder = factory.newDocumentBuilder();
|
||||
} catch (ParserConfigurationException pcE) {
|
||||
log.error("caught exception: " + pcE);
|
||||
|
@@ -16,6 +16,7 @@ import javax.xml.stream.XMLStreamReader;
|
||||
import jakarta.xml.bind.JAXBContext;
|
||||
import jakarta.xml.bind.JAXBException;
|
||||
import jakarta.xml.bind.Unmarshaller;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
@@ -31,9 +32,7 @@ public abstract class Converter<T> {
|
||||
|
||||
protected Object unmarshall(InputStream input, Class<?> type) throws SAXException, URISyntaxException {
|
||||
try {
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
XMLInputFactory xmlInputFactory = XMLUtils.getXMLInputFactory();
|
||||
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(input);
|
||||
|
||||
JAXBContext context = JAXBContext.newInstance(type);
|
||||
|
@@ -40,6 +40,7 @@ import org.apache.http.util.EntityUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.client.DSpaceHttpClientFactory;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.authorize.AuthorizeException;
|
||||
import org.dspace.content.DSpaceObject;
|
||||
import org.dspace.content.crosswalk.CrosswalkException;
|
||||
@@ -829,7 +830,7 @@ public class DataCiteConnector
|
||||
}
|
||||
|
||||
// parse the XML
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document doc = null;
|
||||
try {
|
||||
doc = saxBuilder.build(new ByteArrayInputStream(content.getBytes("UTF-8")));
|
||||
|
@@ -22,6 +22,7 @@ import jakarta.ws.rs.client.WebTarget;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
@@ -218,7 +219,7 @@ public class ArXivImportMetadataSourceServiceImpl extends AbstractImportMetadata
|
||||
if (response.getStatus() == 200) {
|
||||
String responseString = response.readEntity(String.class);
|
||||
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(responseString));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
@@ -399,7 +400,7 @@ public class ArXivImportMetadataSourceServiceImpl extends AbstractImportMetadata
|
||||
private List<Element> splitToRecords(String recordsSrc) {
|
||||
|
||||
try {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(recordsSrc));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
|
@@ -26,6 +26,7 @@ import org.apache.http.HttpException;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
@@ -301,9 +302,7 @@ public class CiniiImportMetadataSourceServiceImpl extends AbstractImportMetadata
|
||||
|
||||
private List<Element> splitToRecords(String recordsSrc) {
|
||||
try {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(recordsSrc));
|
||||
Element root = document.getRootElement();
|
||||
return root.getChildren();
|
||||
@@ -356,9 +355,7 @@ public class CiniiImportMetadataSourceServiceImpl extends AbstractImportMetadata
|
||||
Map<String, Map<String, String>> params = new HashMap<String, Map<String,String>>();
|
||||
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
|
||||
int url_len = this.url.length() - 1;
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(response));
|
||||
Element root = document.getRootElement();
|
||||
List<Namespace> namespaces = Arrays.asList(
|
||||
@@ -420,9 +417,7 @@ public class CiniiImportMetadataSourceServiceImpl extends AbstractImportMetadata
|
||||
Map<String, Map<String, String>> params = new HashMap<String, Map<String,String>>();
|
||||
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
|
||||
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(response));
|
||||
Element root = document.getRootElement();
|
||||
List<Namespace> namespaces = Arrays
|
||||
|
@@ -12,7 +12,6 @@ import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
@@ -21,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.importer.external.metadatamapping.contributor.JsonPathMetadataProcessor;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
@@ -64,10 +64,9 @@ public class CrossRefAbstractProcessor implements JsonPathMetadataProcessor {
|
||||
}
|
||||
|
||||
String xmlString = "<root>" + abstractValue + "</root>";
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
Document xmlDoc;
|
||||
try {
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
DocumentBuilder builder = XMLUtils.getDocumentBuilder();
|
||||
InputSource is = new InputSource(new StringReader(xmlString));
|
||||
xmlDoc = builder.parse(is);
|
||||
} catch (SAXException | IOException | ParserConfigurationException e) {
|
||||
|
@@ -32,6 +32,7 @@ import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.xerces.impl.dv.util.Base64;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
@@ -397,9 +398,11 @@ public class EpoImportMetadataSourceServiceImpl extends AbstractImportMetadataSo
|
||||
|
||||
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
|
||||
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
// To properly parse EPO responses, we must allow DOCTYPEs overall. But, we can still apply all the
|
||||
// other default XXE protections, including disabling external entities and entity expansion.
|
||||
// NOTE: we only need to allow DOCTYPEs for this initial API call. All other calls have them disabled.
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
|
||||
Document document = saxBuilder.build(new StringReader(response));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
@@ -436,9 +439,7 @@ public class EpoImportMetadataSourceServiceImpl extends AbstractImportMetadataSo
|
||||
|
||||
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
|
||||
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(response));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
@@ -489,9 +490,7 @@ public class EpoImportMetadataSourceServiceImpl extends AbstractImportMetadataSo
|
||||
|
||||
private List<Element> splitToRecords(String recordsSrc) {
|
||||
try {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(recordsSrc));
|
||||
Element root = document.getRootElement();
|
||||
List<Namespace> namespaces = Arrays.asList(Namespace.getNamespace("ns", "http://www.epo.org/exchange"));
|
||||
|
@@ -20,6 +20,7 @@ import jakarta.ws.rs.client.ClientBuilder;
|
||||
import jakarta.ws.rs.client.Invocation;
|
||||
import jakarta.ws.rs.client.WebTarget;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
@@ -248,7 +249,7 @@ public class OpenAireImportMetadataSourceServiceImpl extends AbstractImportMetad
|
||||
if (response.getStatus() == 200) {
|
||||
String responseString = response.readEntity(String.class);
|
||||
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(responseString));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
@@ -330,7 +331,7 @@ public class OpenAireImportMetadataSourceServiceImpl extends AbstractImportMetad
|
||||
private List<Element> splitToRecords(String recordsSrc) {
|
||||
|
||||
try {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(recordsSrc));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
|
@@ -25,6 +25,7 @@ import java.util.concurrent.Callable;
|
||||
import com.google.common.io.CharStreams;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
@@ -234,11 +235,10 @@ public class PubmedImportMetadataSourceServiceImpl extends AbstractImportMetadat
|
||||
String value = null;
|
||||
|
||||
try {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// Disallow external entities & entity expansion to protect against XXE attacks
|
||||
// (NOTE: We receive errors if we disable all DTDs for PubMed, so this is the best we can do)
|
||||
saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
saxBuilder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
// To properly parse PubMed responses, we must allow DOCTYPEs overall. But, we can still apply all the
|
||||
// other default XXE protections, including disabling external entities and entity expansion.
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
|
||||
Document document = saxBuilder.build(new StringReader(src));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
@@ -355,12 +355,10 @@ public class PubmedImportMetadataSourceServiceImpl extends AbstractImportMetadat
|
||||
|
||||
private List<Element> splitToRecords(String recordsSrc) {
|
||||
try {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// Disallow external entities & entity expansion to protect against XXE attacks
|
||||
// (NOTE: We receive errors if we disable all DTDs for PubMed, so this is the best we can do)
|
||||
saxBuilder.setFeature("http://xml.org/sax/features/external-general-entities", false);
|
||||
saxBuilder.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
|
||||
saxBuilder.setExpandEntities(false);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
// To properly parse PubMed responses, we must allow DOCTYPEs overall. But, we can still apply all the
|
||||
// other default XXE protections, including disabling external entities and entity expansion.
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl", false);
|
||||
Document document = saxBuilder.build(new StringReader(recordsSrc));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
|
@@ -24,6 +24,7 @@ import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.utils.URIBuilder;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
@@ -292,9 +293,7 @@ public class PubmedEuropeMetadataSourceServiceImpl extends AbstractImportMetadat
|
||||
Map<String, Map<String, String>> params = new HashMap<String, Map<String,String>>();
|
||||
String response = liveImportClient.executeHttpGetRequest(1000, buildURI(1, query), params);
|
||||
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(response));
|
||||
Element root = document.getRootElement();
|
||||
Element element = root.getChild("hitCount");
|
||||
@@ -365,9 +364,7 @@ public class PubmedEuropeMetadataSourceServiceImpl extends AbstractImportMetadat
|
||||
String response = liveImportClient.executeHttpGetRequest(1000, uriBuilder.toString(), params);
|
||||
String cursorMark = StringUtils.EMPTY;
|
||||
if (StringUtils.isNotBlank(response)) {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(response));
|
||||
XPathFactory xpfac = XPathFactory.instance();
|
||||
XPathExpression<Element> xPath = xpfac.compile("//responseWrapper/resultList/result",
|
||||
|
@@ -26,6 +26,7 @@ import java.util.regex.Pattern;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
@@ -208,9 +209,7 @@ public class ScopusImportMetadataSourceServiceImpl extends AbstractImportMetadat
|
||||
return 0;
|
||||
}
|
||||
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(response));
|
||||
Element root = document.getRootElement();
|
||||
|
||||
@@ -397,9 +396,7 @@ public class ScopusImportMetadataSourceServiceImpl extends AbstractImportMetadat
|
||||
|
||||
private List<Element> splitToRecords(String recordsSrc) {
|
||||
try {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(recordsSrc));
|
||||
Element root = document.getRootElement();
|
||||
String totalResults = root.getChildText("totalResults", Namespace.getNamespace("http://a9.com/-/spec/opensearch/1.1/"));
|
||||
|
@@ -26,6 +26,7 @@ import org.apache.commons.collections.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.content.Item;
|
||||
import org.dspace.importer.external.datamodel.ImportRecord;
|
||||
import org.dspace.importer.external.datamodel.Query;
|
||||
@@ -145,9 +146,7 @@ public class WOSImportMetadataSourceServiceImpl extends AbstractImportMetadataSo
|
||||
params.put(HEADER_PARAMETERS, getRequestParameters());
|
||||
String response = liveImportClient.executeHttpGetRequest(timeout, url, params);
|
||||
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(response));
|
||||
Element root = document.getRootElement();
|
||||
XPathExpression<Element> xpath = XPathFactory.instance().compile("//*[@name=\"RecordsFound\"]",
|
||||
@@ -288,9 +287,7 @@ public class WOSImportMetadataSourceServiceImpl extends AbstractImportMetadataSo
|
||||
|
||||
private List<Element> splitToRecords(String recordsSrc) {
|
||||
try {
|
||||
SAXBuilder saxBuilder = new SAXBuilder();
|
||||
// disallow DTD parsing to ensure no XXE attacks can occur
|
||||
saxBuilder.setFeature("http://apache.org/xml/features/disallow-doctype-decl",true);
|
||||
SAXBuilder saxBuilder = XMLUtils.getSAXBuilder();
|
||||
Document document = saxBuilder.build(new StringReader(recordsSrc));
|
||||
Element root = document.getRootElement();
|
||||
String cData = XPathFactory.instance().compile("//*[@name=\"Records\"]",
|
||||
|
@@ -28,6 +28,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.dspace.app.client.DSpaceHttpClientFactory;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.jdom2.Attribute;
|
||||
import org.jdom2.Document;
|
||||
@@ -50,7 +51,7 @@ public class CCLicenseConnectorServiceImpl implements CCLicenseConnectorService,
|
||||
private Logger log = org.apache.logging.log4j.LogManager.getLogger(CCLicenseConnectorServiceImpl.class);
|
||||
|
||||
private CloseableHttpClient client;
|
||||
protected SAXBuilder parser = new SAXBuilder();
|
||||
protected SAXBuilder parser = XMLUtils.getSAXBuilder();
|
||||
|
||||
private String postArgument = "answers";
|
||||
private String postAnswerFormat =
|
||||
|
@@ -43,6 +43,7 @@ import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.dspace.app.client.DSpaceHttpClientFactory;
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.orcid.OrcidToken;
|
||||
import org.dspace.orcid.exception.OrcidClientException;
|
||||
import org.dspace.orcid.model.OrcidEntityType;
|
||||
@@ -351,8 +352,7 @@ public class OrcidClientImpl implements OrcidClient {
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T unmarshall(HttpEntity entity, Class<T> clazz) throws Exception {
|
||||
JAXBContext jaxbContext = JAXBContext.newInstance(clazz);
|
||||
XMLInputFactory xmlInputFactory = XMLInputFactory.newFactory();
|
||||
xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
|
||||
XMLInputFactory xmlInputFactory = XMLUtils.getXMLInputFactory();
|
||||
XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(entity.getContent());
|
||||
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||
return (T) unmarshaller.unmarshal(xmlStreamReader);
|
||||
|
@@ -12,7 +12,6 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.xpath.XPath;
|
||||
@@ -20,6 +19,7 @@ import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathExpressionException;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
|
||||
import org.dspace.app.util.XMLUtils;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.dspace.services.factory.DSpaceServicesFactory;
|
||||
import org.w3c.dom.Document;
|
||||
@@ -71,7 +71,7 @@ public class ControlledVocabulary {
|
||||
|
||||
File controlledVocFile = new File(filePath.toString());
|
||||
if (controlledVocFile.exists()) {
|
||||
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
DocumentBuilder builder = XMLUtils.getDocumentBuilder();
|
||||
Document document = builder.parse(controlledVocFile);
|
||||
XPath xPath = XPathFactory.newInstance().newXPath();
|
||||
Node node = (Node) xPath.compile("node").evaluate(document, XPathConstants.NODE);
|
||||
|
Reference in New Issue
Block a user