-
Notifications
You must be signed in to change notification settings - Fork 206
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
…-2015-1833) (ported to 2.4) git-svn-id: https://svn.apache.org/repos/asf/jackrabbit/branches/2.4@1680798 13f79535-47bb-0310-9956-ffa450edef68
- Loading branch information
Showing
4 changed files
with
234 additions
and
26 deletions.
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
...bbit-webdav/src/main/java/org/apache/jackrabbit/webdav/xml/DavDocumentBuilderFactory.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* | ||
* 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.jackrabbit.webdav.xml; | ||
|
||
import java.io.IOException; | ||
|
||
import javax.xml.XMLConstants; | ||
import javax.xml.parsers.DocumentBuilder; | ||
import javax.xml.parsers.DocumentBuilderFactory; | ||
import javax.xml.parsers.ParserConfigurationException; | ||
|
||
import org.slf4j.Logger; | ||
import org.slf4j.LoggerFactory; | ||
import org.xml.sax.EntityResolver; | ||
import org.xml.sax.InputSource; | ||
import org.xml.sax.helpers.DefaultHandler; | ||
|
||
/** | ||
* Custom {@link DocumentBuilderFactory} extended for use in WebDAV. | ||
*/ | ||
public class DavDocumentBuilderFactory { | ||
|
||
private static final Logger LOG = LoggerFactory.getLogger(DomUtil.class); | ||
|
||
private final DocumentBuilderFactory DEFAULT_FACTORY = createFactory(); | ||
|
||
private DocumentBuilderFactory BUILDER_FACTORY = DEFAULT_FACTORY; | ||
|
||
private DocumentBuilderFactory createFactory() { | ||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); | ||
factory.setNamespaceAware(true); | ||
factory.setIgnoringComments(true); | ||
factory.setIgnoringElementContentWhitespace(true); | ||
factory.setCoalescing(true); | ||
try { | ||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); | ||
} catch (ParserConfigurationException e) { | ||
LOG.warn("Secure XML processing is not supported", e); | ||
} catch (AbstractMethodError e) { | ||
LOG.warn("Secure XML processing is not supported", e); | ||
} | ||
return factory; | ||
} | ||
|
||
public void setFactory(DocumentBuilderFactory documentBuilderFactory) { | ||
LOG.debug("DocumentBuilderFactory changed to: " + documentBuilderFactory); | ||
BUILDER_FACTORY = documentBuilderFactory != null ? documentBuilderFactory : DEFAULT_FACTORY; | ||
} | ||
|
||
/** | ||
* An entity resolver that does not allow external entity resolution. See | ||
* RFC 4918, Section 20.6 | ||
*/ | ||
private static final EntityResolver DEFAULT_ENTITY_RESOLVER = new EntityResolver() { | ||
@Override | ||
public InputSource resolveEntity(String publicId, String systemId) throws IOException { | ||
LOG.debug("Resolution of external entities in XML payload not supported - publicId: " + publicId + ", systemId: " | ||
+ systemId); | ||
throw new IOException("This parser does not support resolution of external entities (publicId: " + publicId | ||
+ ", systemId: " + systemId + ")"); | ||
} | ||
}; | ||
|
||
public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { | ||
DocumentBuilder db = BUILDER_FACTORY.newDocumentBuilder(); | ||
if (BUILDER_FACTORY == DEFAULT_FACTORY) { | ||
// if this is the default factory: set the default entity resolver as well | ||
db.setEntityResolver(DEFAULT_ENTITY_RESOLVER); | ||
} | ||
db.setErrorHandler(new DefaultHandler()); | ||
return db; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/xml/ParserTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
/* | ||
* 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.jackrabbit.webdav.xml; | ||
|
||
import java.io.ByteArrayInputStream; | ||
import java.io.File; | ||
import java.io.FileOutputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.io.OutputStream; | ||
import java.io.UnsupportedEncodingException; | ||
|
||
import javax.xml.parsers.DocumentBuilder; | ||
import javax.xml.parsers.DocumentBuilderFactory; | ||
import javax.xml.parsers.ParserConfigurationException; | ||
|
||
import junit.framework.TestCase; | ||
|
||
import org.w3c.dom.Document; | ||
import org.w3c.dom.Element; | ||
import org.xml.sax.EntityResolver; | ||
import org.xml.sax.InputSource; | ||
import org.xml.sax.SAXException; | ||
|
||
public class ParserTest extends TestCase { | ||
|
||
// see <http://en.wikipedia.org/wiki/Billion_laughs#Details> | ||
public void testBillionLaughs() throws UnsupportedEncodingException { | ||
|
||
String testBody = "<?xml version=\"1.0\"?>" + "<!DOCTYPE lolz [" + " <!ENTITY lol \"lol\">" + " <!ELEMENT lolz (#PCDATA)>" | ||
+ " <!ENTITY lol1 \"&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;\">" | ||
+ " <!ENTITY lol2 \"&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;\">" | ||
+ " <!ENTITY lol3 \"&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;\">" | ||
+ " <!ENTITY lol4 \"&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;\">" | ||
+ " <!ENTITY lol5 \"&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;\">" | ||
+ " <!ENTITY lol6 \"&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;\">" | ||
+ " <!ENTITY lol7 \"&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;\">" | ||
+ " <!ENTITY lol8 \"&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;\">" | ||
+ " <!ENTITY lol9 \"&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;\">" + "]>" + "<lolz>&lol9;</lolz>"; | ||
InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); | ||
|
||
try { | ||
DomUtil.parseDocument(is); | ||
fail("parsing this document should cause an exception"); | ||
} catch (Exception expected) { | ||
} | ||
} | ||
|
||
public void testExternalEntities() throws IOException { | ||
|
||
String dname = "target"; | ||
String fname = "test.xml"; | ||
|
||
File f = new File(dname, fname); | ||
OutputStream os = new FileOutputStream(f); | ||
os.write("testdata".getBytes()); | ||
os.close(); | ||
|
||
String testBody = "<?xml version='1.0'?>\n<!DOCTYPE foo [" + " <!ENTITY test SYSTEM \"file:" + dname + "/" + fname + "\">" | ||
+ "]>\n<foo>&test;</foo>"; | ||
InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); | ||
|
||
try { | ||
Document d = DomUtil.parseDocument(is); | ||
Element root = d.getDocumentElement(); | ||
String text = DomUtil.getText(root); | ||
fail("parsing this document should cause an exception, but the following external content was included: " + text); | ||
} catch (Exception expected) { | ||
} | ||
} | ||
|
||
public void testCustomEntityResolver() throws ParserConfigurationException, SAXException, IOException { | ||
|
||
try { | ||
DocumentBuilderFactory dbf = new DocumentBuilderFactory() { | ||
|
||
DocumentBuilderFactory def = DocumentBuilderFactory.newInstance(); | ||
|
||
@Override | ||
public void setFeature(String name, boolean value) throws ParserConfigurationException { | ||
def.setFeature(name, value); | ||
} | ||
|
||
@Override | ||
public void setAttribute(String name, Object value) throws IllegalArgumentException { | ||
def.setAttribute(name, value); | ||
} | ||
|
||
@Override | ||
public DocumentBuilder newDocumentBuilder() throws ParserConfigurationException { | ||
DocumentBuilder db = def.newDocumentBuilder(); | ||
db.setEntityResolver(new EntityResolver() { | ||
@Override | ||
public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { | ||
if ("foo:test".equals(systemId)) { | ||
return new InputSource(new ByteArrayInputStream("foo&bar".getBytes("UTF-8"))); | ||
} else { | ||
return null; | ||
} | ||
} | ||
}); | ||
return db; | ||
} | ||
|
||
@Override | ||
public boolean getFeature(String name) throws ParserConfigurationException { | ||
return def.getFeature(name); | ||
} | ||
|
||
@Override | ||
public Object getAttribute(String name) throws IllegalArgumentException { | ||
return def.getAttribute(name); | ||
} | ||
}; | ||
|
||
DomUtil.setBuilderFactory(dbf); | ||
String testBody = "<?xml version='1.0'?>\n<!DOCTYPE foo [" + " <!ENTITY test SYSTEM \"foo:test\">" | ||
+ "]>\n<foo>&test;</foo>"; | ||
InputStream is = new ByteArrayInputStream(testBody.getBytes("UTF-8")); | ||
|
||
Document d = DomUtil.parseDocument(is); | ||
Element root = d.getDocumentElement(); | ||
String text = DomUtil.getText(root); | ||
assertEquals("custom entity resolver apparently not called", "foo&bar", text); | ||
} finally { | ||
DomUtil.setBuilderFactory(null); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters