|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.sun.org.apache.xml.internal.security.utils; |
|
|
|
import java.io.IOException; |
|
import java.io.InputStream; |
|
import java.io.OutputStream; |
|
import java.lang.reflect.InvocationTargetException; |
|
import java.math.BigInteger; |
|
import java.security.AccessController; |
|
import java.security.PrivilegedAction; |
|
import java.util.ArrayList; |
|
import java.util.Base64; |
|
import java.util.HashSet; |
|
import java.util.List; |
|
import java.util.Set; |
|
import java.util.stream.Collectors; |
|
|
|
import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException; |
|
import com.sun.org.apache.xml.internal.security.c14n.Canonicalizer; |
|
import com.sun.org.apache.xml.internal.security.c14n.InvalidCanonicalizerException; |
|
import com.sun.org.apache.xml.internal.security.parser.XMLParser; |
|
import com.sun.org.apache.xml.internal.security.parser.XMLParserException; |
|
import com.sun.org.apache.xml.internal.security.parser.XMLParserImpl; |
|
import org.w3c.dom.Attr; |
|
import org.w3c.dom.Document; |
|
import org.w3c.dom.Element; |
|
import org.w3c.dom.NamedNodeMap; |
|
import org.w3c.dom.Node; |
|
import org.w3c.dom.NodeList; |
|
import org.w3c.dom.Text; |
|
|
|
|
|
|
|
|
|
*/ |
|
public final class XMLUtils { |
|
|
|
@SuppressWarnings("removal") |
|
private static boolean ignoreLineBreaks = |
|
AccessController.doPrivileged( |
|
(PrivilegedAction<Boolean>) () -> Boolean.getBoolean("com.sun.org.apache.xml.internal.security.ignoreLineBreaks")); |
|
|
|
private static final com.sun.org.slf4j.internal.Logger LOG = |
|
com.sun.org.slf4j.internal.LoggerFactory.getLogger(XMLUtils.class); |
|
|
|
@SuppressWarnings("removal") |
|
private static XMLParser xmlParserImpl = |
|
AccessController.doPrivileged( |
|
(PrivilegedAction<XMLParser>) () -> { |
|
String xmlParserClass = System.getProperty("com.sun.org.apache.xml.internal.security.XMLParser"); |
|
if (xmlParserClass != null) { |
|
try { |
|
return (XMLParser) JavaUtils.newInstanceWithEmptyConstructor( |
|
ClassLoaderUtils.loadClass(xmlParserClass, XMLUtils.class)); |
|
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | InvocationTargetException e) { |
|
LOG.error("Error instantiating XMLParser. Falling back to XMLParserImpl"); |
|
} |
|
} |
|
return new XMLParserImpl(); |
|
}); |
|
|
|
private static volatile String dsPrefix = "ds"; |
|
private static volatile String ds11Prefix = "dsig11"; |
|
private static volatile String xencPrefix = "xenc"; |
|
private static volatile String xenc11Prefix = "xenc11"; |
|
|
|
|
|
|
|
|
|
*/ |
|
private XMLUtils() { |
|
// we don't allow instantiation |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void setDsPrefix(String prefix) { |
|
JavaUtils.checkRegisterPermission(); |
|
dsPrefix = prefix; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void setDs11Prefix(String prefix) { |
|
JavaUtils.checkRegisterPermission(); |
|
ds11Prefix = prefix; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void setXencPrefix(String prefix) { |
|
JavaUtils.checkRegisterPermission(); |
|
xencPrefix = prefix; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void setXenc11Prefix(String prefix) { |
|
JavaUtils.checkRegisterPermission(); |
|
xenc11Prefix = prefix; |
|
} |
|
|
|
public static Element getNextElement(Node el) { |
|
Node node = el; |
|
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) { |
|
node = node.getNextSibling(); |
|
} |
|
return (Element)node; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void getSet(Node rootNode, Set<Node> result, Node exclude, boolean com) { |
|
if (exclude != null && isDescendantOrSelf(exclude, rootNode)) { |
|
return; |
|
} |
|
getSetRec(rootNode, result, exclude, com); |
|
} |
|
|
|
@SuppressWarnings("fallthrough") |
|
private static void getSetRec(final Node rootNode, final Set<Node> result, |
|
final Node exclude, final boolean com) { |
|
if (rootNode == exclude) { |
|
return; |
|
} |
|
switch (rootNode.getNodeType()) { |
|
case Node.ELEMENT_NODE: |
|
result.add(rootNode); |
|
Element el = (Element)rootNode; |
|
if (el.hasAttributes()) { |
|
NamedNodeMap nl = el.getAttributes(); |
|
int length = nl.getLength(); |
|
for (int i = 0; i < length; i++) { |
|
result.add(nl.item(i)); |
|
} |
|
} |
|
|
|
case Node.DOCUMENT_NODE: |
|
for (Node r = rootNode.getFirstChild(); r != null; r = r.getNextSibling()) { |
|
if (r.getNodeType() == Node.TEXT_NODE) { |
|
result.add(r); |
|
while (r != null && r.getNodeType() == Node.TEXT_NODE) { |
|
r = r.getNextSibling(); |
|
} |
|
if (r == null) { |
|
return; |
|
} |
|
} |
|
getSetRec(r, result, exclude, com); |
|
} |
|
break; |
|
case Node.COMMENT_NODE: |
|
if (com) { |
|
result.add(rootNode); |
|
} |
|
break; |
|
case Node.DOCUMENT_TYPE_NODE: |
|
break; |
|
default: |
|
result.add(rootNode); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void outputDOM(Node contextNode, OutputStream os) { |
|
XMLUtils.outputDOM(contextNode, os, false); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void outputDOM(Node contextNode, OutputStream os, boolean addPreamble) { |
|
try { |
|
if (addPreamble) { |
|
os.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n".getBytes(java.nio.charset.StandardCharsets.UTF_8)); |
|
} |
|
|
|
Canonicalizer.getInstance( |
|
Canonicalizer.ALGO_ID_C14N_PHYSICAL).canonicalizeSubtree(contextNode, os); |
|
} catch (IOException | InvalidCanonicalizerException | CanonicalizationException ex) { |
|
LOG.debug(ex.getMessage(), ex); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void outputDOMc14nWithComments(Node contextNode, OutputStream os) { |
|
try { |
|
Canonicalizer.getInstance( |
|
Canonicalizer.ALGO_ID_C14N_WITH_COMMENTS).canonicalizeSubtree(contextNode, os); |
|
} catch (InvalidCanonicalizerException | CanonicalizationException ex) { |
|
LOG.debug(ex.getMessage(), ex); |
|
// throw new RuntimeException(ex.getMessage()); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static String getFullTextChildrenFromNode(Node node) { |
|
StringBuilder sb = new StringBuilder(); |
|
|
|
Node child = node.getFirstChild(); |
|
while (child != null) { |
|
if (child.getNodeType() == Node.TEXT_NODE) { |
|
sb.append(((Text)child).getData()); |
|
} |
|
child = child.getNextSibling(); |
|
} |
|
|
|
return sb.toString(); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element createElementInSignatureSpace(Document doc, String elementName) { |
|
if (doc == null) { |
|
throw new RuntimeException("Document is null"); |
|
} |
|
|
|
if (dsPrefix == null || dsPrefix.length() == 0) { |
|
return doc.createElementNS(Constants.SignatureSpecNS, elementName); |
|
} |
|
return doc.createElementNS(Constants.SignatureSpecNS, dsPrefix + ":" + elementName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element createElementInSignature11Space(Document doc, String elementName) { |
|
if (doc == null) { |
|
throw new RuntimeException("Document is null"); |
|
} |
|
|
|
if (ds11Prefix == null || ds11Prefix.length() == 0) { |
|
return doc.createElementNS(Constants.SignatureSpec11NS, elementName); |
|
} |
|
return doc.createElementNS(Constants.SignatureSpec11NS, ds11Prefix + ":" + elementName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element createElementInEncryptionSpace(Document doc, String elementName) { |
|
if (doc == null) { |
|
throw new RuntimeException("Document is null"); |
|
} |
|
|
|
if (xencPrefix == null || xencPrefix.length() == 0) { |
|
return doc.createElementNS(EncryptionConstants.EncryptionSpecNS, elementName); |
|
} |
|
return |
|
doc.createElementNS( |
|
EncryptionConstants.EncryptionSpecNS, xencPrefix + ":" + elementName |
|
); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element createElementInEncryption11Space(Document doc, String elementName) { |
|
if (doc == null) { |
|
throw new RuntimeException("Document is null"); |
|
} |
|
|
|
if (xenc11Prefix == null || xenc11Prefix.length() == 0) { |
|
return doc.createElementNS(EncryptionConstants.EncryptionSpec11NS, elementName); |
|
} |
|
return |
|
doc.createElementNS( |
|
EncryptionConstants.EncryptionSpec11NS, xenc11Prefix + ":" + elementName |
|
); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean elementIsInSignatureSpace(Element element, String localName) { |
|
if (element == null){ |
|
return false; |
|
} |
|
|
|
return Constants.SignatureSpecNS.equals(element.getNamespaceURI()) |
|
&& element.getLocalName().equals(localName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean elementIsInSignature11Space(Element element, String localName) { |
|
if (element == null) { |
|
return false; |
|
} |
|
|
|
return Constants.SignatureSpec11NS.equals(element.getNamespaceURI()) |
|
&& element.getLocalName().equals(localName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean elementIsInEncryptionSpace(Element element, String localName) { |
|
if (element == null){ |
|
return false; |
|
} |
|
return EncryptionConstants.EncryptionSpecNS.equals(element.getNamespaceURI()) |
|
&& element.getLocalName().equals(localName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean elementIsInEncryption11Space(Element element, String localName) { |
|
if (element == null){ |
|
return false; |
|
} |
|
return EncryptionConstants.EncryptionSpec11NS.equals(element.getNamespaceURI()) |
|
&& element.getLocalName().equals(localName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Document getOwnerDocument(Node node) { |
|
if (node.getNodeType() == Node.DOCUMENT_NODE) { |
|
return (Document) node; |
|
} |
|
try { |
|
return node.getOwnerDocument(); |
|
} catch (NullPointerException npe) { |
|
throw new NullPointerException(I18n.translate("endorsed.jdk1.4.0") |
|
+ " Original message was \"" |
|
+ npe.getMessage() + "\""); |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Document getOwnerDocument(Set<Node> xpathNodeSet) { |
|
NullPointerException npe = null; |
|
for (Node node : xpathNodeSet) { |
|
int nodeType = node.getNodeType(); |
|
if (nodeType == Node.DOCUMENT_NODE) { |
|
return (Document) node; |
|
} |
|
try { |
|
if (nodeType == Node.ATTRIBUTE_NODE) { |
|
return ((Attr)node).getOwnerElement().getOwnerDocument(); |
|
} |
|
return node.getOwnerDocument(); |
|
} catch (NullPointerException e) { |
|
npe = e; |
|
} |
|
} |
|
|
|
throw new NullPointerException(I18n.translate("endorsed.jdk1.4.0") |
|
+ " Original message was \"" |
|
+ (npe == null ? "" : npe.getMessage()) + "\""); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void addReturnToElement(Element e) { |
|
if (!ignoreLineBreaks) { |
|
Document doc = e.getOwnerDocument(); |
|
e.appendChild(doc.createTextNode("\n")); |
|
} |
|
} |
|
|
|
public static void addReturnToElement(Document doc, HelperNodeList nl) { |
|
if (!ignoreLineBreaks) { |
|
nl.appendChild(doc.createTextNode("\n")); |
|
} |
|
} |
|
|
|
public static void addReturnBeforeChild(Element e, Node child) { |
|
if (!ignoreLineBreaks) { |
|
Document doc = e.getOwnerDocument(); |
|
e.insertBefore(doc.createTextNode("\n"), child); |
|
} |
|
} |
|
|
|
public static String encodeToString(byte[] bytes) { |
|
if (ignoreLineBreaks) { |
|
return Base64.getEncoder().encodeToString(bytes); |
|
} |
|
return Base64.getMimeEncoder().encodeToString(bytes); |
|
} |
|
|
|
public static byte[] decode(String encodedString) { |
|
return Base64.getMimeDecoder().decode(encodedString); |
|
} |
|
|
|
public static byte[] decode(byte[] encodedBytes) { |
|
return Base64.getMimeDecoder().decode(encodedBytes); |
|
} |
|
|
|
public static boolean isIgnoreLineBreaks() { |
|
return ignoreLineBreaks; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Set<Node> convertNodelistToSet(NodeList xpathNodeSet) { |
|
if (xpathNodeSet == null) { |
|
return new HashSet<>(); |
|
} |
|
|
|
int length = xpathNodeSet.getLength(); |
|
Set<Node> set = new HashSet<>(length); |
|
|
|
for (int i = 0; i < length; i++) { |
|
set.add(xpathNodeSet.item(i)); |
|
} |
|
|
|
return set; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static void circumventBug2650(Document doc) { |
|
|
|
Element documentElement = doc.getDocumentElement(); |
|
|
|
|
|
Attr xmlnsAttr = |
|
documentElement.getAttributeNodeNS(Constants.NamespaceSpecNS, "xmlns"); |
|
|
|
if (xmlnsAttr == null) { |
|
documentElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns", ""); |
|
} |
|
|
|
XMLUtils.circumventBug2650internal(doc); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@SuppressWarnings("fallthrough") |
|
private static void circumventBug2650internal(Node node) { |
|
Node parent = null; |
|
Node sibling = null; |
|
final String namespaceNs = Constants.NamespaceSpecNS; |
|
do { |
|
switch (node.getNodeType()) { |
|
case Node.ELEMENT_NODE : |
|
Element element = (Element) node; |
|
if (!element.hasChildNodes()) { |
|
break; |
|
} |
|
if (element.hasAttributes()) { |
|
NamedNodeMap attributes = element.getAttributes(); |
|
int attributesLength = attributes.getLength(); |
|
|
|
for (Node child = element.getFirstChild(); child!=null; |
|
child = child.getNextSibling()) { |
|
|
|
if (child.getNodeType() != Node.ELEMENT_NODE) { |
|
continue; |
|
} |
|
Element childElement = (Element) child; |
|
|
|
for (int i = 0; i < attributesLength; i++) { |
|
Attr currentAttr = (Attr) attributes.item(i); |
|
if (!namespaceNs.equals(currentAttr.getNamespaceURI())) { |
|
continue; |
|
} |
|
if (childElement.hasAttributeNS(namespaceNs, |
|
currentAttr.getLocalName())) { |
|
continue; |
|
} |
|
childElement.setAttributeNS(namespaceNs, |
|
currentAttr.getName(), |
|
currentAttr.getNodeValue()); |
|
} |
|
} |
|
} |
|
case Node.ENTITY_REFERENCE_NODE : |
|
case Node.DOCUMENT_NODE : |
|
parent = node; |
|
sibling = node.getFirstChild(); |
|
break; |
|
} |
|
while (sibling == null && parent != null) { |
|
sibling = parent.getNextSibling(); |
|
parent = parent.getParentNode(); |
|
} |
|
if (sibling == null) { |
|
return; |
|
} |
|
|
|
node = sibling; |
|
sibling = node.getNextSibling(); |
|
} while (true); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element selectDsNode(Node sibling, String nodeName, int number) { |
|
while (sibling != null) { |
|
if (Constants.SignatureSpecNS.equals(sibling.getNamespaceURI()) |
|
&& sibling.getLocalName().equals(nodeName)) { |
|
if (number == 0) { |
|
return (Element)sibling; |
|
} |
|
number--; |
|
} |
|
sibling = sibling.getNextSibling(); |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element selectDs11Node(Node sibling, String nodeName, int number) { |
|
while (sibling != null) { |
|
if (Constants.SignatureSpec11NS.equals(sibling.getNamespaceURI()) |
|
&& sibling.getLocalName().equals(nodeName)) { |
|
if (number == 0) { |
|
return (Element)sibling; |
|
} |
|
number--; |
|
} |
|
sibling = sibling.getNextSibling(); |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element selectXencNode(Node sibling, String nodeName, int number) { |
|
while (sibling != null) { |
|
if (EncryptionConstants.EncryptionSpecNS.equals(sibling.getNamespaceURI()) |
|
&& sibling.getLocalName().equals(nodeName)) { |
|
if (number == 0){ |
|
return (Element)sibling; |
|
} |
|
number--; |
|
} |
|
sibling = sibling.getNextSibling(); |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element selectNode(Node sibling, String uri, String nodeName, int number) { |
|
while (sibling != null) { |
|
if (sibling.getNamespaceURI() != null && sibling.getNamespaceURI().equals(uri) |
|
&& sibling.getLocalName().equals(nodeName)) { |
|
if (number == 0) { |
|
return (Element)sibling; |
|
} |
|
number--; |
|
} |
|
sibling = sibling.getNextSibling(); |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element[] selectDsNodes(Node sibling, String nodeName) { |
|
return selectNodes(sibling, Constants.SignatureSpecNS, nodeName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element[] selectDs11Nodes(Node sibling, String nodeName) { |
|
return selectNodes(sibling, Constants.SignatureSpec11NS, nodeName); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Element[] selectNodes(Node sibling, String uri, String nodeName) { |
|
List<Element> list = new ArrayList<>(); |
|
while (sibling != null) { |
|
if (sibling.getNamespaceURI() != null && sibling.getNamespaceURI().equals(uri) |
|
&& sibling.getLocalName().equals(nodeName)) { |
|
list.add((Element)sibling); |
|
} |
|
sibling = sibling.getNextSibling(); |
|
} |
|
return list.toArray(new Element[list.size()]); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static Set<Node> excludeNodeFromSet(Node signatureElement, Set<Node> inputSet) { |
|
return inputSet.stream().filter((inputNode) -> |
|
!XMLUtils.isDescendantOrSelf(signatureElement, inputNode)).collect(Collectors.toSet()); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static String getStrFromNode(Node xpathnode) { |
|
if (xpathnode.getNodeType() == Node.TEXT_NODE) { |
|
// we iterate over all siblings of the context node because eventually, |
|
|
|
StringBuilder sb = new StringBuilder(); |
|
|
|
for (Node currentSibling = xpathnode.getParentNode().getFirstChild(); |
|
currentSibling != null; |
|
currentSibling = currentSibling.getNextSibling()) { |
|
if (currentSibling.getNodeType() == Node.TEXT_NODE) { |
|
sb.append(((Text) currentSibling).getData()); |
|
} |
|
} |
|
|
|
return sb.toString(); |
|
} else if (xpathnode.getNodeType() == Node.ATTRIBUTE_NODE) { |
|
return xpathnode.getNodeValue(); |
|
} else if (xpathnode.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) { |
|
return xpathnode.getNodeValue(); |
|
} |
|
|
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean isDescendantOrSelf(Node ctx, Node descendantOrSelf) { |
|
if (ctx == descendantOrSelf) { |
|
return true; |
|
} |
|
|
|
Node parent = descendantOrSelf; |
|
|
|
while (true) { |
|
if (parent == null) { |
|
return false; |
|
} |
|
|
|
if (parent == ctx) { |
|
return true; |
|
} |
|
|
|
if (parent.getNodeType() == Node.ATTRIBUTE_NODE) { |
|
parent = ((Attr) parent).getOwnerElement(); |
|
} else { |
|
parent = parent.getParentNode(); |
|
} |
|
} |
|
} |
|
|
|
public static boolean ignoreLineBreaks() { |
|
return ignoreLineBreaks; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean protectAgainstWrappingAttack(Node startNode, String value) { |
|
String id = value.trim(); |
|
if (!id.isEmpty() && id.charAt(0) == '#') { |
|
id = id.substring(1); |
|
} |
|
|
|
Node startParent = null; |
|
Node processedNode = null; |
|
Element foundElement = null; |
|
if (startNode != null) { |
|
startParent = startNode.getParentNode(); |
|
} |
|
|
|
while (startNode != null) { |
|
if (startNode.getNodeType() == Node.ELEMENT_NODE) { |
|
Element se = (Element) startNode; |
|
|
|
NamedNodeMap attributes = se.getAttributes(); |
|
if (attributes != null) { |
|
int length = attributes.getLength(); |
|
for (int i = 0; i < length; i++) { |
|
Attr attr = (Attr)attributes.item(i); |
|
if (attr.isId() && id.equals(attr.getValue())) { |
|
if (foundElement == null) { |
|
|
|
foundElement = attr.getOwnerElement(); |
|
} else { |
|
LOG.debug("Multiple elements with the same 'Id' attribute value!"); |
|
return false; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
processedNode = startNode; |
|
startNode = startNode.getFirstChild(); |
|
|
|
|
|
if (startNode == null) { |
|
|
|
startNode = processedNode.getNextSibling(); |
|
} |
|
|
|
// no more siblings, get parent, all children |
|
|
|
while (startNode == null) { |
|
processedNode = processedNode.getParentNode(); |
|
if (processedNode == startParent) { |
|
return true; |
|
} |
|
|
|
startNode = processedNode.getNextSibling(); |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static boolean protectAgainstWrappingAttack( |
|
Node startNode, Element knownElement, String value |
|
) { |
|
String id = value.trim(); |
|
if (!id.isEmpty() && id.charAt(0) == '#') { |
|
id = id.substring(1); |
|
} |
|
|
|
Node startParent = null; |
|
Node processedNode = null; |
|
if (startNode != null) { |
|
startParent = startNode.getParentNode(); |
|
} |
|
|
|
while (startNode != null) { |
|
if (startNode.getNodeType() == Node.ELEMENT_NODE) { |
|
Element se = (Element) startNode; |
|
|
|
NamedNodeMap attributes = se.getAttributes(); |
|
if (attributes != null) { |
|
int length = attributes.getLength(); |
|
for (int i = 0; i < length; i++) { |
|
Attr attr = (Attr)attributes.item(i); |
|
if (attr.isId() && id.equals(attr.getValue()) && se != knownElement) { |
|
LOG.debug("Multiple elements with the same 'Id' attribute value!"); |
|
return false; |
|
} |
|
} |
|
} |
|
} |
|
|
|
processedNode = startNode; |
|
startNode = startNode.getFirstChild(); |
|
|
|
|
|
if (startNode == null) { |
|
|
|
startNode = processedNode.getNextSibling(); |
|
} |
|
|
|
// no more siblings, get parent, all children |
|
|
|
while (startNode == null) { |
|
processedNode = processedNode.getParentNode(); |
|
if (processedNode == startParent) { |
|
return true; |
|
} |
|
|
|
startNode = processedNode.getNextSibling(); |
|
} |
|
} |
|
return true; |
|
} |
|
|
|
public static Document read(InputStream inputStream, boolean disallowDocTypeDeclarations) throws XMLParserException { |
|
|
|
return xmlParserImpl.parse(inputStream, disallowDocTypeDeclarations); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public static byte[] getBytes(BigInteger big, int bitlen) { |
|
|
|
|
|
bitlen = ((bitlen + 7) >> 3) << 3; |
|
|
|
if (bitlen < big.bitLength()) { |
|
throw new IllegalArgumentException(I18n.translate("utils.Base64.IllegalBitlength")); |
|
} |
|
|
|
byte[] bigBytes = big.toByteArray(); |
|
|
|
if (big.bitLength() % 8 != 0 |
|
&& big.bitLength() / 8 + 1 == bitlen / 8) { |
|
return bigBytes; |
|
} |
|
|
|
// some copying needed |
|
int startSrc = 0; |
|
int bigLen = bigBytes.length; |
|
|
|
if (big.bitLength() % 8 == 0) { // correct values |
|
startSrc = 1; |
|
|
|
bigLen--; |
|
} |
|
|
|
int startDst = bitlen / 8 - bigLen; |
|
byte[] resizedBytes = new byte[bitlen / 8]; |
|
|
|
System.arraycopy(bigBytes, startSrc, resizedBytes, startDst, bigLen); |
|
|
|
return resizedBytes; |
|
} |
|
|
|
|
|
|
|
} |