You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by ge...@apache.org on 2002/09/04 17:07:56 UTC
cvs commit: xml-security/src/org/apache/xml/security/c14n/implementations Canonicalizer20010315.java Canonicalizer20010315Excl.java
geuerp 2002/09/04 08:07:56
Modified: src/org/apache/xml/security/c14n/implementations
Canonicalizer20010315.java
Canonicalizer20010315Excl.java
Log:
Bug fixes in Canonical XML and Exclusive XML Canoncalization
Revision Changes Path
1.26 +18 -11 xml-security/src/org/apache/xml/security/c14n/implementations/Canonicalizer20010315.java
Index: Canonicalizer20010315.java
===================================================================
RCS file: /home/cvs/xml-security/src/org/apache/xml/security/c14n/implementations/Canonicalizer20010315.java,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -r1.25 -r1.26
--- Canonicalizer20010315.java 30 Aug 2002 21:02:16 -0000 1.25
+++ Canonicalizer20010315.java 4 Sep 2002 15:07:55 -0000 1.26
@@ -74,9 +74,10 @@
/**
- * Class Canonicalizer20010315
+ * Implements <A HREF="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">Canonical
+ * XML Version 1.0</A>, a W3C Recommendation from 15 March 2001.
*
- * @author $Author$
+ * @author Christian Geuer-Pollmann <ge...@apache.org>
* @version $Revision$
*/
public abstract class Canonicalizer20010315 extends CanonicalizerSpi {
@@ -224,7 +225,7 @@
// we output all Attrs which are available
for (int i = 0; i < attrs.length; i++) {
this.outputAttrToWriter(((Attr) attrs[i]).getNodeName(),
- ((Attr) attrs[i]).getNodeValue());
+ ((Attr) attrs[i]).getNodeValue());
}
this._writer.write(">");
@@ -533,6 +534,7 @@
ByteArrayOutputStream baos = new ByteArrayOutputStream();
this._writer = new OutputStreamWriter(baos, Canonicalizer.ENCODING);
+
this.canonicalizeXPathNodeSet(this._rootNodeOfC14n);
this._writer.close();
@@ -689,6 +691,7 @@
*/
Object[] handleAttributes(Element E) throws CanonicalizationException {
+ // System.out.println("During the traversal, I encountered " + XMLUtils.getXPath(E));
// result will contain the attrs which have to be outputted
List result = new Vector();
NamedNodeMap attrs = E.getAttributes();
@@ -711,13 +714,12 @@
* a space followed by xmlns="" if and only if the following conditions
* are met:
*/
- boolean firstNodeIsNotDefaultNamespaceNode =
- xmlns.getNodeValue().equals("");
+ boolean firstNodeIsDefaultNamespaceNode =
+ !xmlns.getNodeValue().equals("") && this._xpathNodeSet.contains(xmlns);
/* the element E that owns the axis is in the node-set
*/
- if (firstNodeIsNotDefaultNamespaceNode
- && this._xpathNodeSet.contains(E)) {
+ if (this._xpathNodeSet.contains(E) &&!firstNodeIsDefaultNamespaceNode) {
/* The nearest ancestor element of E in the node-set has a default
* namespace node in the node-set (default namespace nodes always
@@ -728,17 +730,22 @@
&& (ancestor.getNodeType() == Node.ELEMENT_NODE);
ancestor = ancestor.getParentNode()) {
if (this._xpathNodeSet.contains(ancestor)) {
- Attr xmlnsAncestor = ((Element) ancestor).getAttributeNodeNS(
+ Attr xmlnsA = ((Element) ancestor).getAttributeNodeNS(
Constants.NamespaceSpecNS, "xmlns");
- if (xmlnsAncestor == null) {
+ if (xmlnsA == null) {
throw new CanonicalizationException(
"c14n.XMLUtils.circumventBug2650forgotten");
}
- if (!xmlnsAncestor.getNodeValue().equals("")) {
+ if (!xmlnsA.getNodeValue().equals("")
+ && this._xpathNodeSet.contains(xmlnsA)) {
// OK, we must output xmlns=""
+ xmlns = this._doc.createAttributeNS(Constants.NamespaceSpecNS,
+ "xmlns");
+
+ xmlns.setValue("");
result.add(xmlns);
}
1.7 +594 -215 xml-security/src/org/apache/xml/security/c14n/implementations/Canonicalizer20010315Excl.java
Index: Canonicalizer20010315Excl.java
===================================================================
RCS file: /home/cvs/xml-security/src/org/apache/xml/security/c14n/implementations/Canonicalizer20010315Excl.java,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- Canonicalizer20010315Excl.java 28 Aug 2002 12:08:24 -0000 1.6
+++ Canonicalizer20010315Excl.java 4 Sep 2002 15:07:55 -0000 1.7
@@ -1,3 +1,4 @@
+
/*
* The Apache Software License, Version 1.1
*
@@ -77,31 +78,35 @@
/**
- * Implements <A HREF="http://www.w3.org/Signature/Drafts/xml-exc-c14n">"Exclusive
- * XML Canonicalization, Version 1.0"</A>, Rev 1.58.
+ * Implements "<A HREF="http://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718/">Exclusive XML Canonicalization, Version 1.0</A>"
* <BR />
* Credits: During restructuring of the Canonicalizer framework, Ren� Kollmorgen from
* Software AG submitted an implementation of ExclC14n which fitted into the old
* architecture and which based heavily on my old (and slow) implementation of
* "Canonical XML". A big "thank you" to Ren� for this.
* <BR />
- * THIS implementation is a complete rewrite of the algorithm.
+ * <i>THIS</i> implementation is a complete rewrite of the algorithm.
*
- * @author $Author$
+ * @author Christian Geuer-Pollmann <ge...@apache.org>
* @version $Revision$
- * @see <A HREF="http://www.w3.org/Signature/Drafts/xml-exc-c14n">"Exclusive XML Canonicalization, Version 1.0"</A>, Rev 1.58.
+ * @see <A HREF="http://www.w3.org/TR/2002/REC-xml-exc-c14n-20020718/">"Exclusive XML Canonicalization, Version 1.0"</A>
*/
public abstract class Canonicalizer20010315Excl extends CanonicalizerSpi {
//J-
boolean _includeComments = false;
Set _xpathNodeSet = null;
+
+ /**
+ * This Set contains the names (Strings like "xmlns" or "xmlns:foo") of
+ * the inclusive namespaces.
+ */
Set _inclusiveNSSet = null;
Document _doc = null;
Element _documentElement = null;
Node _rootNodeOfC14n = null;
-
+ HashMap _renderedPrefixesForElement = null;
Writer _writer = null;
//J+
@@ -134,9 +139,8 @@
*
* @throws CanonicalizationException
*/
- public byte[] engineCanonicalizeSubTree(
- Node rootNode, String inclusiveNamespaces)
- throws CanonicalizationException {
+ public byte[] engineCanonicalizeSubTree(Node rootNode, String inclusiveNamespaces)
+ throws CanonicalizationException {
this._rootNodeOfC14n = rootNode;
this._doc = XMLUtils.getOwnerDocument(this._rootNodeOfC14n);
@@ -180,9 +184,8 @@
* @throws CanonicalizationException
* @throws IOException
*/
- void canonicalizeSubTree(
- Node currentNode, Map inscopeNamespaces, Map alreadyVisible)
- throws CanonicalizationException, IOException {
+ void canonicalizeSubTree(Node currentNode, Map inscopeNamespaces, Map alreadyVisible)
+ throws CanonicalizationException, IOException {
int currentNodeType = currentNode.getNodeType();
@@ -251,7 +254,6 @@
updateInscopeNamespacesAndReturnVisibleAttrs(currentElement,
inscopeNamespaces, alreadyVisible);
-
// we output all Attrs which are available
for (int i = 0; i < attrs.size(); i++) {
outputAttrToWriter(((Attr) attrs.get(i)).getNodeName(),
@@ -296,13 +298,11 @@
* @return the Attr[]s to be outputted
* @throws CanonicalizationException
*/
- List updateInscopeNamespacesAndReturnVisibleAttrs(
- Element currentElement, Map inscopeNamespaces, Map alreadyVisible)
- throws CanonicalizationException {
+ List updateInscopeNamespacesAndReturnVisibleAttrs(Element currentElement, Map inscopeNamespaces, Map alreadyVisible)
+ throws CanonicalizationException {
Vector ns = new Vector();
Vector at = new Vector();
-
NamedNodeMap attributes = currentElement.getAttributes();
int attributesLength = attributes.getLength();
@@ -370,8 +370,8 @@
} else if (this.utilizedOrIncluded(currentElement, name)
&& (!alreadyVisible.containsKey(name)
|| (alreadyVisible.containsKey(name)
- &&!alreadyVisible.get(name)
- .equals(inscopeValue)))) {
+ &&!alreadyVisible.get(name).equals(
+ inscopeValue)))) {
if (C14nHelper.namespaceIsRelative(inscopeValue)) {
Object exArgs[] = { currentElement.getTagName(), name,
inscopeValue };
@@ -390,9 +390,10 @@
}
}
- Collections.sort(ns, new org.apache.xml.security.c14n.helper.NSAttrCompare());
- Collections.sort(at, new org.apache.xml.security.c14n.helper.NonNSAttrCompare());
-
+ Collections.sort(ns,
+ new org.apache.xml.security.c14n.helper.NSAttrCompare());
+ Collections.sort(
+ at, new org.apache.xml.security.c14n.helper.NonNSAttrCompare());
ns.addAll(at);
return ns;
@@ -508,9 +509,8 @@
*
* @throws CanonicalizationException
*/
- public byte[] engineCanonicalizeXPathNodeSet(
- Set xpathNodeSet, String inclusiveNamespaces)
- throws CanonicalizationException {
+ public byte[] engineCanonicalizeXPathNodeSet(Set xpathNodeSet, String inclusiveNamespaces)
+ throws CanonicalizationException {
this._xpathNodeSet = xpathNodeSet;
@@ -533,9 +533,9 @@
this._writer = new OutputStreamWriter(baos, Canonicalizer.ENCODING);
this._inclusiveNSSet =
InclusiveNamespaces.prefixStr2Set(inclusiveNamespaces);
+ this._renderedPrefixesForElement = new HashMap();
- this.canonicalizeXPathNodeSet(this._doc, true, new EC14nCtx());
-
+ this.canonicalizeXPathNodeSet(this._doc);
this._writer.close();
return baos.toByteArray();
@@ -549,6 +549,7 @@
this._rootNodeOfC14n = null;
this._doc = null;
this._documentElement = null;
+ this._renderedPrefixesForElement = null;
this._writer = null;
}
}
@@ -557,14 +558,11 @@
* Method canonicalizeXPathNodeSet
*
* @param currentNode
- * @param parentIsVisible
- * @param ctx
* @throws CanonicalizationException
* @throws IOException
*/
- void canonicalizeXPathNodeSet(
- Node currentNode, boolean parentIsVisible, EC14nCtx ctx)
- throws CanonicalizationException, IOException {
+ void canonicalizeXPathNodeSet(Node currentNode)
+ throws CanonicalizationException, IOException {
int currentNodeType = currentNode.getNodeType();
boolean currentNodeIsVisible = this._xpathNodeSet.contains(currentNode);
@@ -584,7 +582,7 @@
for (Node currentChild = currentNode.getFirstChild();
currentChild != null;
currentChild = currentChild.getNextSibling()) {
- canonicalizeXPathNodeSet(currentChild, true, ctx);
+ this.canonicalizeXPathNodeSet(currentChild);
}
break;
@@ -597,7 +595,7 @@
this._writer.write("\n");
}
- outputCommentToWriter((Comment) currentNode);
+ this.outputCommentToWriter((Comment) currentNode);
if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
this._writer.write("\n");
@@ -613,7 +611,7 @@
this._writer.write("\n");
}
- outputPItoWriter((ProcessingInstruction) currentNode);
+ this.outputPItoWriter((ProcessingInstruction) currentNode);
if (position == NODE_BEFORE_DOCUMENT_ELEMENT) {
this._writer.write("\n");
@@ -626,13 +624,12 @@
if (this._xpathNodeSet.contains(currentNode)) {
outputTextToWriter(currentNode.getNodeValue());
- for (Node nextSibling =
- currentNode
- .getNextSibling(); (nextSibling != null) && ((nextSibling
- .getNodeType() == Node.TEXT_NODE) || (nextSibling
- .getNodeType() == Node
- .CDATA_SECTION_NODE)); nextSibling =
- nextSibling.getNextSibling()) {
+ for (Node nextSibling = currentNode.getNextSibling();
+ (nextSibling != null)
+ && ((nextSibling.getNodeType() == Node.TEXT_NODE)
+ || (nextSibling.getNodeType()
+ == Node.CDATA_SECTION_NODE));
+ nextSibling = nextSibling.getNextSibling()) {
/* The XPath data model allows to select only the first of a
* sequence of mixed text and CDATA nodes. But we must output
@@ -640,7 +637,7 @@
*
* @see http://nagoya.apache.org/bugzilla/show_bug.cgi?id=6329
*/
- outputTextToWriter(nextSibling.getNodeValue());
+ this.outputTextToWriter(nextSibling.getNodeValue());
}
}
break;
@@ -648,19 +645,20 @@
case Node.ELEMENT_NODE :
Element currentElement = (Element) currentNode;
+ this._renderedPrefixesForElement.put(currentElement, new HashSet());
+
if (currentNodeIsVisible) {
this._writer.write("<");
this._writer.write(currentElement.getTagName());
}
// we output all Attrs which are available
- List attrs = this.getAttrs(currentElement, parentIsVisible, ctx);
- int attrsLength = attrs.size();
+ Object attrs[] = this.handleAttributes(currentElement);
- for (int i = 0; i < attrsLength; i++) {
- Attr a = (Attr) attrs.get(i);
+ for (int i = 0; i < attrs.length; i++) {
+ Attr a = (Attr) attrs[i];
- outputAttrToWriter(a.getNodeName(), a.getNodeValue());
+ this.outputAttrToWriter(a.getNodeName(), a.getNodeValue());
}
if (currentNodeIsVisible) {
@@ -671,18 +669,7 @@
for (Node currentChild = currentNode.getFirstChild();
currentChild != null;
currentChild = currentChild.getNextSibling()) {
- if (currentChild.getNodeType() == Node.ELEMENT_NODE) {
-
- /*
- * We must 'clone' the inscopeXMLAttrs to allow the descendants
- * to mess around in their own map
- */
- canonicalizeXPathNodeSet(currentChild, currentNodeIsVisible,
- ctx.copy());
- } else {
- canonicalizeXPathNodeSet(currentChild, currentNodeIsVisible,
- ctx);
- }
+ this.canonicalizeXPathNodeSet(currentChild);
}
if (currentNodeIsVisible) {
@@ -690,99 +677,10 @@
this._writer.write(currentElement.getTagName());
this._writer.write(">");
}
- break;
- }
- }
-
- /**
- * Method getAttrs
- *
- * @param currentElement
- * @param parentIsVisible
- * @param ctx
- *
- * @throws CanonicalizationException
- */
- List getAttrs(Element currentElement, boolean parentIsVisible, EC14nCtx ctx)
- throws CanonicalizationException {
-
- Set visiblyUtilized = new HashSet();
- boolean currentElementIsInNodeset = this._xpathNodeSet.contains(currentElement);
- if (currentElementIsInNodeset) {
- if (currentElement.getNamespaceURI() != null) {
- String prefix = currentElement.getPrefix();
-
- if (prefix == null) {
- visiblyUtilized.add("xmlns");
- } else {
- visiblyUtilized.add("xmlns:" + prefix);
- }
- }
- }
-
- Vector namespacesInSubset = new Vector();
- Vector attributesInSubset = new Vector();
- NamedNodeMap attributes = currentElement.getAttributes();
- int attributesLength = attributes.getLength();
- for (int i = 0; i < attributesLength; i++) {
- Attr currentAttr = (Attr) attributes.item(i);
- if (this._xpathNodeSet.contains(currentAttr)) {
- String URI = currentAttr.getNamespaceURI();
- if (URI != null && Constants.NamespaceSpecNS.equals(URI)) {
- String value = currentAttr.getValue();
- if (C14nHelper.namespaceIsRelative(value)) {
- Object exArgs[] = { currentElement.getTagName(), currentAttr.getNodeName(), value };
-
- throw new CanonicalizationException("c14n.Canonicalizer.RelativeNamespace", exArgs);
- }
- namespacesInSubset.add(currentAttr);
- } else {
- attributesInSubset.add(currentAttr);
-
- String prefix = currentAttr.getPrefix();
- if (prefix != null) {
- visiblyUtilized.add("xmlns:" + prefix);
- }
- }
- }
- }
- Collections.sort(namespacesInSubset,
- new org.apache.xml.security.c14n.helper.NSAttrCompare());
- Collections.sort(attributesInSubset,
- new org.apache.xml.security.c14n.helper.NonNSAttrCompare());
-
- Vector nsResult = new Vector();
- for (int i = 0; i < namespacesInSubset.size(); i++) {
- Attr currentAttr = (Attr) namespacesInSubset.get(i);
- String name = currentAttr.getNodeName();
- String value = currentAttr.getValue();
-
- if (name.equals("xmlns") && value.equals("")) {
- // undeclare default namespace
- boolean nameAlreadyVisible = ctx.n.containsKey(name);
-
- if (nameAlreadyVisible) {
- ctx.n.remove(name);
- nsResult.add(currentAttr);
- }
- } else {
- //J-
- // boolean utilizedOrIncluded = this.utilizedOrIncluded(currentElement, name);
- boolean utilizedOrIncluded = visiblyUtilized.contains(name) || this._inclusiveNSSet.contains(name);
- boolean nameAlreadyVisible = ctx.n.containsKey(name);
- boolean visibleButNotEqual = nameAlreadyVisible && !ctx.n.get(name).equals(value);
- //J+
- if (currentElementIsInNodeset && utilizedOrIncluded && (!nameAlreadyVisible || visibleButNotEqual)) {
- // ns_rendered_new.put(name, value);
- ctx.n.put(name, value);
- nsResult.add(currentAttr);
- }
- }
+ this._renderedPrefixesForElement.remove(currentElement);
+ break;
}
- nsResult.addAll(attributesInSubset);
-
- return nsResult;
}
/**
@@ -856,8 +754,9 @@
* @throws IOException
*/
void outputPItoWriter(ProcessingInstruction currentPI) throws IOException {
+
if (currentPI == null) {
- return;
+ return;
}
this._writer.write("<?");
@@ -913,8 +812,9 @@
* @throws IOException
*/
void outputCommentToWriter(Comment currentComment) throws IOException {
+
if (currentComment == null) {
- return;
+ return;
}
this._writer.write("<!--");
@@ -947,8 +847,9 @@
* @throws IOException
*/
void outputTextToWriter(String text) throws IOException {
+
if (text == null) {
- return;
+ return;
}
int length = text.length();
@@ -1006,7 +907,7 @@
* Method visiblyUtilized
*
* @param element
- *
+ * @return a Set of namespace names.
*/
public Set visiblyUtilized(Element element) {
@@ -1016,12 +917,12 @@
// we are in the canonicalizeSubtree part
if (element.getNamespaceURI() != null) {
- String elementPrefix = element.getPrefix();
+ String prefix = element.getPrefix();
- if (elementPrefix == null) {
+ if (prefix == null) {
result.add("xmlns");
} else {
- result.add("xmlns:" + elementPrefix);
+ result.add("xmlns:" + prefix);
}
}
@@ -1032,45 +933,44 @@
// a:..., add xmlns:a to the list
for (int i = 0; i < attributesLength; i++) {
Attr currentAttr = (Attr) attributes.item(i);
+ String prefix = currentAttr.getPrefix();
- if (currentAttr.getNamespaceURI() != null) {
- String attrPrefix = currentAttr.getPrefix();
-
- if ((attrPrefix != null) &&!attrPrefix.equals("xml")
- &&!attrPrefix.equals("xmlns")) {
- result.add("xmlns:" + attrPrefix);
+ if (prefix != null) {
+ if (!prefix.equals("xml") &&!prefix.equals("xmlns")) {
+ result.add("xmlns:" + prefix);
}
}
}
- } else if ((this._xpathNodeSet != null)
- && this._xpathNodeSet.contains(element)) {
+ } else {
+ if (this._xpathNodeSet.contains(element)) {
- // we are in the canonicalizeXPathNodeSet part
- if (element.getNamespaceURI() != null) {
- String elementPrefix = element.getPrefix();
-
- if ((elementPrefix == null) || (elementPrefix.length() == 0)) {
- result.add("xmlns");
- } else {
- result.add("xmlns:" + elementPrefix);
+ // we are in the canonicalizeXPathNodeSet part
+ if (element.getNamespaceURI() != null) {
+ String prefix = element.getPrefix();
+
+ if ((prefix == null) || (prefix.length() == 0)) {
+ result.add("xmlns");
+ } else {
+ result.add("xmlns:" + prefix);
+ }
}
- }
- NamedNodeMap attributes = element.getAttributes();
- int attributesLength = attributes.getLength();
+ NamedNodeMap attributes = element.getAttributes();
+ int attributesLength = attributes.getLength();
- // if the attribute is not xmlns:... and not xml:... but
- // a:..., add xmlns:a to the list
- for (int i = 0; i < attributesLength; i++) {
- Attr currentAttr = (Attr) attributes.item(i);
-
- if (this._xpathNodeSet.contains(currentAttr)
- && (currentAttr.getNamespaceURI() != null)) {
- String attrPrefix = currentAttr.getPrefix();
-
- if ((attrPrefix != null) &&!attrPrefix.equals("xml")
- &&!attrPrefix.equals("xmlns")) {
- result.add("xmlns:" + attrPrefix);
+ // if the attribute is not xmlns:... and not xml:... but
+ // a:..., add xmlns:a to the list
+ for (int i = 0; i < attributesLength; i++) {
+ Attr currentAttr = (Attr) attributes.item(i);
+
+ if (this._xpathNodeSet.contains(currentAttr)) {
+ String prefix = currentAttr.getPrefix();
+
+ if (prefix != null) {
+ if (!prefix.equals("xml") &&!prefix.equals("xmlns")) {
+ result.add("xmlns:" + prefix);
+ }
+ }
}
}
}
@@ -1080,45 +980,524 @@
}
/**
- * Class EC14nCtx
*
- * @author $Author$
- * @version $Revision$
+ * @param E
+ * @throws CanonicalizationException
*/
- class EC14nCtx {
+ Object[] handleAttributes(Element E) throws CanonicalizationException {
- /** Field n */
- Map n;
+ // System.out.println("During the traversal, I encountered " + XMLUtils.getXPath(E));
+ // result will contain the attrs which have to be outputted
+ List result = new Vector();
+ HashSet namespacePrefixesOutputForCurrentElement =
+ (HashSet) this._renderedPrefixesForElement.get(E);
+ NamedNodeMap attrs = E.getAttributes();
+ int attrsLength = attrs.getLength();
+
+ if (this._inclusiveNSSet.contains("xmlns")) {
+
+ // handle the default namespace if the #default token is in the prefix list
+
+ /* ***********************************************************************
+ * Handle xmlns=""
+ * ***********************************************************************/
+
+ // first check whether we have to output xmlns=""
+ Attr xmlns = E.getAttributeNodeNS(Constants.NamespaceSpecNS, "xmlns");
+
+ if (xmlns == null) {
+ throw new CanonicalizationException(
+ "c14n.XMLUtils.circumventBug2650forgotten");
+ }
+
+ /* To begin processing L, if the first node is not the default namespace
+ * node (a node with no namespace URI and no local name), then generate
+ * a space followed by xmlns="" if and only if the following conditions
+ * are met:
+ */
+ boolean firstNodeIsDefaultNamespaceNode =
+ !xmlns.getNodeValue().equals("")
+ && this._xpathNodeSet.contains(xmlns);
+
+ /* the element E that owns the axis is in the node-set
+ */
+ if (!firstNodeIsDefaultNamespaceNode
+ && this._xpathNodeSet.contains(E)) {
+
+ /* The nearest output ancestor element of E has a default
+ * namespace node in the node-set
+ */
+ for (Node ancestor = E.getParentNode();
+ (ancestor != null)
+ && (ancestor.getNodeType() == Node.ELEMENT_NODE);
+ ancestor = ancestor.getParentNode()) {
+ if (this._xpathNodeSet.contains(ancestor)) {
+
+ // we're on an output ancestor
+ Attr xmlnsA = ((Element) ancestor).getAttributeNodeNS(
+ Constants.NamespaceSpecNS, "xmlns");
+
+ if (xmlnsA == null) {
+ throw new CanonicalizationException(
+ "c14n.XMLUtils.circumventBug2650forgotten");
+ }
+
+ if (!xmlnsA.getNodeValue().equals("")
+ && this._xpathNodeSet.contains(xmlnsA)) {
+
+ // OK, we must output xmlns=""
+ xmlns =
+ this._doc.createAttributeNS(Constants.NamespaceSpecNS,
+ "xmlns");
+
+ xmlns.setValue("");
+ result.add(xmlns);
+ }
- /**
- * Constructor EC14nCtx
- *
- */
- public EC14nCtx() {
- this.n = new HashMap();
+ break;
+ }
+ }
+ }
}
- /**
- * Constructor EC14nCtx
+ /*
+ * [xmlns not present in the prefix list]
+ * If the token representing the default namespace is not present in
+ * InclusiveNamespaces PrefixList, then the rules for rendering xmlns=""
+ * are changed as follows. When canonicalizing the namespace axis of an
+ * element E that is in the node-set, output xmlns="" if and only if all
+ * of the conditions are met:
*
- * @param n
+ * (1) E is in the node set, and
+ * (2) E visibly utilizes the default namespace (i.e., it has no namespace prefix), and
+ * (3) E has no default namespace node in the node-set, and
+ * (4) the nearest output ancestor of E that visibly utilizes the
+ * default namespace has a default namespace node in the node-set.
*/
- public EC14nCtx(Map n) {
- this.n = n;
+ if (!this._inclusiveNSSet.contains("xmlns")) {
+
+ // #default is not present in InclusiveNamespaces PrefixList
+ if (this._xpathNodeSet.contains(E)) {
+
+ // E is in the node set
+ if (E.getPrefix() == null) {
+
+ // it has no namespace prefix, i.e. E visibly utilizes the default namespace
+ Attr xmlns = E.getAttributeNodeNS(Constants.NamespaceSpecNS,
+ "xmlns");
+
+ if (xmlns == null) {
+ throw new CanonicalizationException(
+ "c14n.XMLUtils.circumventBug2650forgotten");
+ }
+
+ if (xmlns.getValue().equals("")) {
+
+ // it has no default namespace in the node set
+ searchForNearestOutputAncestorWhichUtilizesDefault: for (
+ Node ancestor = E.getParentNode();
+ (ancestor != null)
+ && (ancestor.getNodeType()
+ == Node.ELEMENT_NODE);
+ ancestor = ancestor
+ .getParentNode()) {
+ if (!this._xpathNodeSet.contains(ancestor)) {
+ continue searchForNearestOutputAncestorWhichUtilizesDefault;
+ }
+
+ Element ancestorElement = (Element) ancestor;
+
+ // now we are on an output ancestor
+ if (ancestorElement.getPrefix() == null) {
+
+ // it utilizes the default, so our search found an end, so we must break
+ Attr xmlnsA = ancestorElement.getAttributeNodeNS(
+ Constants.NamespaceSpecNS, "xmlns");
+
+ if (xmlnsA == null) {
+ throw new CanonicalizationException(
+ "c14n.XMLUtils.circumventBug2650forgotten");
+ }
+
+ if (!xmlnsA.getValue().equals("")) {
+
+ // has a default namespace
+ if (this._xpathNodeSet.contains(xmlnsA)) {
+
+ // in the node set
+ result.add(xmlns);
+ }
+ }
+
+ break searchForNearestOutputAncestorWhichUtilizesDefault;
+ }
+ }
+ } else {
+
+ // !xmlns.getValue().equals("")
+ //
+ // the inclusivePrefixList does not contain the #default token,
+ // but E *HAS* a non-empty default namespace in the node set.
+ // now we must see what to do
+ boolean foundAnOutputAncestor = false;
+
+ searchForNearestOutputAncestorWhichUtilizesDefault: for (
+ Node ancestor = E.getParentNode();
+ (ancestor != null)
+ && (ancestor.getNodeType()
+ == Node.ELEMENT_NODE);
+ ancestor = ancestor
+ .getParentNode()) {
+ if (!this._xpathNodeSet.contains(ancestor)) {
+ continue searchForNearestOutputAncestorWhichUtilizesDefault;
+ }
+
+ Element ancestorElement = (Element) ancestor;
+ Attr xmlnsA = ancestorElement.getAttributeNodeNS(
+ Constants.NamespaceSpecNS, "xmlns");
+
+ if (xmlnsA == null) {
+ throw new CanonicalizationException(
+ "c14n.XMLUtils.circumventBug2650forgotten");
+ }
+
+ // now we are on an output ancestor
+ if (ancestorElement.getPrefix() == null) {
+
+ // it utilizes the default, so our search found an end, so we must break
+ foundAnOutputAncestor = true;
+
+ boolean valueEquals =
+ xmlnsA.getValue().equals(xmlns.getValue());
+ boolean inNodeset = this._xpathNodeSet.contains(xmlnsA);
+
+ // boolean alreadyOutputted = ((Set)this._renderedPrefixesForElement.get(ancestorElement)).contains(xmlns.getName());
+ if (valueEquals) {
+ if (inNodeset) {
+ ; // do nothing
+ } else {
+ ;
+ }
+ } else {
+ if (inNodeset) {
+
+ // has a different namespace value in the node set
+ result.add(xmlns);
+
+ if (xmlns.getPrefix() != null) {
+ namespacePrefixesOutputForCurrentElement.add(
+ xmlns.getName());
+ }
+ } else {
+ ;
+ }
+ }
+
+ break searchForNearestOutputAncestorWhichUtilizesDefault;
+ }
+ }
+
+ if (!foundAnOutputAncestor) {
+
+ // we did not find an output ancestor of E which utilizes
+ // the default namespace, so we must output the non-empty
+ // default namespace
+ result.add(xmlns);
+
+ if (xmlns.getPrefix() != null) {
+ namespacePrefixesOutputForCurrentElement.add(
+ xmlns.getName());
+ }
+ }
+ }
+ }
+ }
}
- /**
- * Method copy
- *
- *
+ /* ***********************************************************************
+ * Handle namespace axis
+ * ***********************************************************************/
+ handleNamespacesWhichAreIncludedInInclusiveNamespaces: for (int i = 0;
+ i < attrsLength;
+ i++) {
+ Attr N = (Attr) attrs.item(i);
+
+ if (!Constants.NamespaceSpecNS.equals(N.getNamespaceURI())) {
+
+ // only handle namespaces here
+ continue handleNamespacesWhichAreIncludedInInclusiveNamespaces;
+ }
+
+ if (C14nHelper.namespaceIsRelative(N)) {
+ Object exArgs[] = { E.getTagName(), N.getName(), N.getNodeValue() };
+
+ throw new CanonicalizationException(
+ "c14n.Canonicalizer.RelativeNamespace", exArgs);
+ }
+
+ if ("xml".equals(N.getLocalName())
+ && Constants.XML_LANG_SPACE_SpecNS.equals(N.getNodeValue())) {
+
+ /* except omit namespace node with local name xml, which defines
+ * the xml prefix, if its string value is http://www.w3.org/XML/1998/namespace.
+ */
+ continue handleNamespacesWhichAreIncludedInInclusiveNamespaces;
+ }
+
+ if (N.getName().equals("xmlns") && N.getNodeValue().equals("")) {
+
+ // xmlns="" already handled
+ continue handleNamespacesWhichAreIncludedInInclusiveNamespaces;
+ }
+
+ if (!this._inclusiveNSSet.contains(N.getName())) {
+
+ /*
+ * The Exclusive XML Canonicalization method may receive an
+ * additional, possibly null, parameter InclusiveNamespaces PrefixList
+ * containing a list of namespace prefixes and/or a token indicating
+ * the presence of the default namespace.
+ * All namespace nodes appearing on this list are handled as provided in Canonical XML.
+ */
+ continue handleNamespacesWhichAreIncludedInInclusiveNamespaces;
+ }
+
+ if (!this._xpathNodeSet.contains(N)) {
+
+ // Consider a list L containing only namespace nodes in the axis and in the node-set
+ //
+ // only if N in the node set
+ continue handleNamespacesWhichAreIncludedInInclusiveNamespaces;
+ }
+
+ /* OK, now we have a 'real' namespace in N, no attrs, no xmlns=""
+ * and no xmlns:xml="http://www.w3.org/XML/1998/namespace"
+ */
+
+ /* A namespace node N is ignored if the nearest ancestor element of E
+ * that is in the node-set has a namespace node in the node-set with
+ * the same local name and value as N.
+ *
+ * Otherwise, process the namespace node N in the same way as an
+ * attribute node, except assign the local name xmlns to the default
+ * namespace node if it exists (in XPath, the default namespace node
+ * has an empty URI and local name).
+ */
+ boolean ignoreN = false;
+
+ lookForAncestorsInNodeset: for (Node ancestor = E.getParentNode();
+ (ancestor != null)
+ && (ancestor.getNodeType()
+ == Node.ELEMENT_NODE);
+ ancestor =
+ ancestor.getParentNode()) {
+ if (this._xpathNodeSet.contains(ancestor)) {
+ Attr NA = ((Element) ancestor).getAttributeNodeNS(
+ Constants.NamespaceSpecNS, N.getLocalName());
+
+ if ((NA != null) && NA.getNodeValue().equals(N.getNodeValue())
+ && this._xpathNodeSet.contains(NA)) {
+ ignoreN = true;
+ }
+
+ break lookForAncestorsInNodeset;
+ }
+ }
+
+ if (!ignoreN) {
+ result.add(N);
+
+ if (N.getPrefix() != null) {
+ namespacePrefixesOutputForCurrentElement.add(N.getName());
+ }
+ }
+ }
+
+ /* **********************************************************************
+ * [xmlns:* not present in the prefix list] *
+ * **********************************************************************/
+ Set visiblyUtilized = this.visiblyUtilized(E);
+
+ handleNamespacesWhichAreNotIncludedInInclusiveNamespaces: for (int i = 0;
+ i < attrsLength;
+ i++) {
+ Attr N = (Attr) attrs.item(i);
+
+ if (!Constants.NamespaceSpecNS.equals(N.getNamespaceURI())) {
+
+ // only handle namespaces here
+ continue handleNamespacesWhichAreNotIncludedInInclusiveNamespaces;
+ }
+
+ if (C14nHelper.namespaceIsRelative(N)) {
+ Object exArgs[] = { E.getTagName(), N.getName(), N.getNodeValue() };
+
+ throw new CanonicalizationException(
+ "c14n.Canonicalizer.RelativeNamespace", exArgs);
+ }
+
+ if (N.getName().equals("xmlns")) {
+
+ // xmlns already handled
+ continue handleNamespacesWhichAreNotIncludedInInclusiveNamespaces;
+ }
+
+ if ("xml".equals(N.getLocalName())
+ && Constants.XML_LANG_SPACE_SpecNS.equals(N.getNodeValue())) {
+
+ /* except omit namespace node with local name xml, which defines
+ * the xml prefix, if its string value is http://www.w3.org/XML/1998/namespace.
+ */
+ continue handleNamespacesWhichAreNotIncludedInInclusiveNamespaces;
+ }
+
+ if (this._inclusiveNSSet.contains(N.getName())) {
+
+ // A namespace node N with a prefix that does not appear
+ continue handleNamespacesWhichAreNotIncludedInInclusiveNamespaces;
+ }
+
+ if (!this._xpathNodeSet.contains(N)) {
+
+ // c14n: Consider a list L containing only namespace nodes in the axis and *IN THE NODE-SET*
+ continue handleNamespacesWhichAreNotIncludedInInclusiveNamespaces;
+ }
+
+ /*
+ * [xmlns:* not present in the prefix list]
+ * A namespace node N with a prefix that does not appear in the
+ * InclusiveNamespaces PrefixList is rendered if all of the conditions
+ * are met:
+ *
+ * (1) Its parent element E is in the node-set, and
+ * (2) N is visibly utilized by its parent element E, and
+ * (3a) the prefix has not yet been rendered by any output ancestor, or
+ * (3b) the nearest output ancestor of E that visibly utilizes the
+ * namespace prefix does not have a namespace node in the node-set
+ * with the same namespace prefix and value as N.
+ */
+ if (this._xpathNodeSet.contains(E)) {
+
+ // (1) Its parent element E is in the node-set, and
+ if (visiblyUtilized.contains(N.getName())) {
+
+ // (2) N is visibly utilized by its parent element E
+ boolean renderedByAnOutputAncestor = false;
+
+ if (E != this._documentElement) {
+
+ // this ensure that we have ancestors where we have to look
+ // whether the prefix has been rendered
+ for (Node ancestor = E.getParentNode(); ancestor != this._doc;
+ ancestor = ancestor.getParentNode()) {
+ if (this._xpathNodeSet.contains(ancestor)) {
+
+ // which prefixes have been rendered by ancestor
+ HashSet prefixesRenderedInAncestor =
+ (HashSet) this._renderedPrefixesForElement.get(
+ ancestor);
+
+ if (prefixesRenderedInAncestor.contains(N.getName())) {
+
+ // the prefix HAS been rendered by an output ancestor
+ renderedByAnOutputAncestor = true;
+
+ break;
+ }
+ }
+ }
+ }
+
+ if (!renderedByAnOutputAncestor) {
+ result.add(N);
+
+ if (N.getPrefix() != null) {
+ namespacePrefixesOutputForCurrentElement.add(N.getName());
+ }
+
+ continue handleNamespacesWhichAreNotIncludedInInclusiveNamespaces;
+ }
+
+ // now handle (3b)
+ searchForNearestOutputAncestorWhichUtilizesPrefix: for (
+ Node ancestor = E.getParentNode();
+ (ancestor != null)
+ && (ancestor.getNodeType()
+ == Node.ELEMENT_NODE);
+ ancestor = ancestor
+ .getParentNode()) {
+ if (!this._xpathNodeSet.contains(ancestor)) {
+ continue searchForNearestOutputAncestorWhichUtilizesPrefix;
+ }
+
+ Element ancestorElement = (Element) ancestor;
+
+ // now we are on an output ancestor
+ Set utilizedByAncestor =
+ this.visiblyUtilized(ancestorElement);
+
+ if (utilizedByAncestor.contains(N.getName())) {
+
+ // it utilizes the prefix, so our search found an end, so we must break
+ Attr xmlnsA = ancestorElement.getAttributeNodeNS(
+ Constants.NamespaceSpecNS, N.getLocalName());
+
+ if (xmlnsA == null) {
+
+ // the nearest output ancestor does not have a namespace node
+ result.add(N);
+
+ if (N.getPrefix() != null) {
+ namespacePrefixesOutputForCurrentElement.add(
+ N.getName());
+ }
+
+ continue handleNamespacesWhichAreNotIncludedInInclusiveNamespaces;
+ }
+
+ boolean inNodeSet = this._xpathNodeSet.contains(xmlnsA);
+ final boolean prefixEquals = true;
+ boolean valueEquals =
+ N.getValue().equals(xmlnsA.getValue());
+
+ if (!inNodeSet && prefixEquals && valueEquals) {
+ result.add(N);
+
+ if (N.getPrefix() != null) {
+ namespacePrefixesOutputForCurrentElement.add(
+ N.getName());
+ }
+
+ continue handleNamespacesWhichAreNotIncludedInInclusiveNamespaces;
+ }
+
+ break searchForNearestOutputAncestorWhichUtilizesPrefix;
+ }
+ } // searchForNearestOutputAncestorWhichUtilizesPrefix
+ }
+ }
+ }
+
+ /*
+ * Handle the regular attributes
*/
- public EC14nCtx copy() {
+ for (int i = 0; i < attrsLength; i++) {
+ Attr attr = (Attr) attrs.item(i);
- EC14nCtx c = new EC14nCtx();
+ if (!Constants.NamespaceSpecNS.equals(attr.getNamespaceURI())) {
- c.n = new HashMap(this.n);
+ // we have an attribute, not a namespace
+ if (this._xpathNodeSet.contains(attr)) {
- return c;
+ // output attributes which are in the node set
+ result.add(attr);
+ }
+ }
}
+
+ Object resultAsArray[] = result.toArray();
+ Object sortedResultAsArray[] = C14nHelper.sortAttributes(resultAsArray);
+
+ return sortedResultAsArray;
}
}