--- old/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11.java 2013-06-28 11:33:05.931288971 -0400
+++ new/src/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/Canonicalizer11.java 2013-06-28 11:33:05.751294572 -0400
@@ -2,21 +2,23 @@
* reserved comment block
* DO NOT REMOVE OR ALTER!
*/
-/*
- * Copyright 2008 The Apache Software Foundation.
- *
- * Licensed 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
+/**
+ * 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
*
- * 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.
+ * 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 com.sun.org.apache.xml.internal.security.c14n.implementations;
@@ -25,7 +27,6 @@
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -34,7 +35,6 @@
import java.util.SortedSet;
import java.util.TreeSet;
import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPath;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -42,8 +42,6 @@
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
-import java.util.logging.Logger;
-import java.util.logging.Logger;
import com.sun.org.apache.xml.internal.security.c14n.CanonicalizationException;
import com.sun.org.apache.xml.internal.security.c14n.helper.C14nHelper;
import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput;
@@ -52,45 +50,51 @@
/**
* Implements
- * Canonical XML Version 1.1, a W3C Proposed Recommendation from 29
+ * Canonical XML Version 1.1, a W3C Proposed Recommendation from 29
* January 2008.
*
* @author Sean Mullan
* @author Raul Benito
- * @version $Revision: 1.2 $
*/
public abstract class Canonicalizer11 extends CanonicalizerBase {
- boolean firstCall = true;
- final SortedSet result = new TreeSet(COMPARE);
- static final String XMLNS_URI = Constants.NamespaceSpecNS;
- static final String XML_LANG_URI = Constants.XML_LANG_SPACE_SpecNS;
-
- static Logger log = Logger.getLogger(Canonicalizer11.class.getName());
+
+ private static final String XMLNS_URI = Constants.NamespaceSpecNS;
+ private static final String XML_LANG_URI = Constants.XML_LANG_SPACE_SpecNS;
+ private static java.util.logging.Logger log =
+ java.util.logging.Logger.getLogger(Canonicalizer11.class.getName());
+ private final SortedSet result = new TreeSet(COMPARE);
+
+ private boolean firstCall = true;
- static class XmlAttrStack {
- int currentLevel = 0;
- int lastlevel = 0;
- XmlsStackElement cur;
+ private static class XmlAttrStack {
static class XmlsStackElement {
int level;
boolean rendered = false;
List nodes = new ArrayList();
};
- List levels = new ArrayList();
+
+ int currentLevel = 0;
+ int lastlevel = 0;
+ XmlsStackElement cur;
+ List levels = new ArrayList();
+
void push(int level) {
currentLevel = level;
- if (currentLevel == -1)
+ if (currentLevel == -1) {
return;
+ }
cur = null;
while (lastlevel >= currentLevel) {
levels.remove(levels.size() - 1);
- if (levels.size() == 0) {
+ int newSize = levels.size();
+ if (newSize == 0) {
lastlevel = 0;
- return;
+ return;
}
- lastlevel=(levels.get(levels.size()-1)).level;
+ lastlevel = (levels.get(newSize - 1)).level;
}
}
+
void addXmlnsAttr(Attr n) {
if (cur == null) {
cur = new XmlsStackElement();
@@ -100,22 +104,24 @@
}
cur.nodes.add(n);
}
+
void getXmlnsAttr(Collection col) {
+ int size = levels.size() - 1;
if (cur == null) {
cur = new XmlsStackElement();
cur.level = currentLevel;
lastlevel = currentLevel;
levels.add(cur);
}
- int size = levels.size() - 2;
boolean parentRendered = false;
XmlsStackElement e = null;
if (size == -1) {
parentRendered = true;
} else {
e = levels.get(size);
- if (e.rendered && e.level+1 == currentLevel)
+ if (e.rendered && e.level + 1 == currentLevel) {
parentRendered = true;
+ }
}
if (parentRendered) {
col.addAll(cur.nodes);
@@ -123,10 +129,10 @@
return;
}
- Map loa = new HashMap();
+ Map loa = new HashMap();
List baseAttrs = new ArrayList();
boolean successiveOmitted = true;
- for (;size>=0;size--) {
+ for (; size >= 0; size--) {
e = levels.get(size);
if (e.rendered) {
successiveOmitted = false;
@@ -134,16 +140,15 @@
Iterator it = e.nodes.iterator();
while (it.hasNext() && successiveOmitted) {
Attr n = it.next();
- if (n.getLocalName().equals("base")) {
- if (!e.rendered) {
- baseAttrs.add(n);
- }
- } else if (!loa.containsKey(n.getName()))
+ if (n.getLocalName().equals("base") && !e.rendered) {
+ baseAttrs.add(n);
+ } else if (!loa.containsKey(n.getName())) {
loa.put(n.getName(), n);
+ }
}
}
if (!baseAttrs.isEmpty()) {
- Iterator it = cur.nodes.iterator();
+ Iterator it = col.iterator();
String base = null;
Attr baseAttr = null;
while (it.hasNext()) {
@@ -164,7 +169,9 @@
try {
base = joinURI(n.getValue(), base);
} catch (URISyntaxException ue) {
- ue.printStackTrace();
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, ue.getMessage(), ue);
+ }
}
}
}
@@ -178,8 +185,9 @@
col.addAll(loa.values());
}
};
- XmlAttrStack xmlattrStack = new XmlAttrStack();
-
+
+ private XmlAttrStack xmlattrStack = new XmlAttrStack();
+
/**
* Constructor Canonicalizer11
*
@@ -190,186 +198,197 @@
}
/**
- * Returns the Attr[]s to be outputted for the given element.
+ * Always throws a CanonicalizationException because this is inclusive c14n.
+ *
+ * @param xpathNodeSet
+ * @param inclusiveNamespaces
+ * @return none it always fails
+ * @throws CanonicalizationException always
+ */
+ public byte[] engineCanonicalizeXPathNodeSet(
+ Set xpathNodeSet, String inclusiveNamespaces
+ ) throws CanonicalizationException {
+ throw new CanonicalizationException("c14n.Canonicalizer.UnsupportedOperation");
+ }
+
+ /**
+ * Always throws a CanonicalizationException because this is inclusive c14n.
+ *
+ * @param rootNode
+ * @param inclusiveNamespaces
+ * @return none it always fails
+ * @throws CanonicalizationException
+ */
+ public byte[] engineCanonicalizeSubTree(
+ Node rootNode, String inclusiveNamespaces
+ ) throws CanonicalizationException {
+ throw new CanonicalizationException("c14n.Canonicalizer.UnsupportedOperation");
+ }
+
+ /**
+ * Returns the Attr[]s to be output for the given element.
*
* The code of this method is a copy of {@link #handleAttributes(Element,
* NameSpaceSymbTable)},
- * whereas it takes into account that subtree-c14n is -- well --
+ * whereas it takes into account that subtree-c14n is -- well --
* subtree-based.
* So if the element in question isRoot of c14n, it's parent is not in the
* node set, as well as all other ancestors.
*
- * @param E
+ * @param element
* @param ns
- * @return the Attr[]s to be outputted
+ * @return the Attr[]s to be output
* @throws CanonicalizationException
*/
- Iterator handleAttributesSubtree(Element E, NameSpaceSymbTable ns)
+ @Override
+ protected Iterator handleAttributesSubtree(Element element, NameSpaceSymbTable ns)
throws CanonicalizationException {
- if (!E.hasAttributes() && !firstCall) {
- return null;
+ if (!element.hasAttributes() && !firstCall) {
+ return null;
}
- // result will contain the attrs which have to be outputted
- final SortedSet result = this.result;
+ // result will contain the attrs which have to be output
+ final SortedSet result = this.result;
result.clear();
- NamedNodeMap attrs = E.getAttributes();
- int attrsLength = attrs.getLength();
-
- for (int i = 0; i < attrsLength; i++) {
- Attr N = (Attr) attrs.item(i);
- String NUri = N.getNamespaceURI();
-
- if (XMLNS_URI != NUri) {
- // It's not a namespace attr node. Add to the result and
- // continue.
- result.add(N);
- continue;
- }
-
- String NName = N.getLocalName();
- String NValue = N.getValue();
- if (XML.equals(NName)
- && XML_LANG_URI.equals(NValue)) {
- // The default mapping for xml must not be output.
- continue;
- }
-
- Node n = ns.addMappingAndRender(NName, NValue, N);
- if (n != null) {
- // Render the ns definition
- result.add((Attr)n);
- if (C14nHelper.namespaceIsRelative(N)) {
- Object exArgs[] = {E.getTagName(), NName, N.getNodeValue()};
- throw new CanonicalizationException(
- "c14n.Canonicalizer.RelativeNamespace", exArgs);
+ if (element.hasAttributes()) {
+ NamedNodeMap attrs = element.getAttributes();
+ int attrsLength = attrs.getLength();
+
+ for (int i = 0; i < attrsLength; i++) {
+ Attr attribute = (Attr) attrs.item(i);
+ String NUri = attribute.getNamespaceURI();
+ String NName = attribute.getLocalName();
+ String NValue = attribute.getValue();
+
+ if (!XMLNS_URI.equals(NUri)) {
+ // It's not a namespace attr node. Add to the result and continue.
+ result.add(attribute);
+ } else if (!(XML.equals(NName) && XML_LANG_URI.equals(NValue))) {
+ // The default mapping for xml must not be output.
+ Node n = ns.addMappingAndRender(NName, NValue, attribute);
+
+ if (n != null) {
+ // Render the ns definition
+ result.add((Attr)n);
+ if (C14nHelper.namespaceIsRelative(attribute)) {
+ Object exArgs[] = {element.getTagName(), NName, attribute.getNodeValue()};
+ throw new CanonicalizationException(
+ "c14n.Canonicalizer.RelativeNamespace", exArgs
+ );
+ }
+ }
}
}
}
if (firstCall) {
// It is the first node of the subtree
- // Obtain all the namespaces defined in the parents, and added
- // to the output.
- ns.getUnrenderedNodes(result);
+ // Obtain all the namespaces defined in the parents, and added to the output.
+ ns.getUnrenderedNodes(result);
// output the attributes in the xml namespace.
- xmlattrStack.getXmlnsAttr(getSortedSetAsCollection(result));
+ xmlattrStack.getXmlnsAttr(result);
firstCall = false;
- }
+ }
return result.iterator();
}
-
-
/**
- * Returns the Attr[]s to be outputted for the given element.
+ * Returns the Attr[]s to be output for the given element.
*
- * IMPORTANT: This method expects to work on a modified DOM tree, i.e. a
- * DOM which has been prepared using
+ * IMPORTANT: This method expects to work on a modified DOM tree, i.e. a
+ * DOM which has been prepared using
* {@link com.sun.org.apache.xml.internal.security.utils.XMLUtils#circumventBug2650(
* org.w3c.dom.Document)}.
- *
- * @param E
+ *
+ * @param element
* @param ns
- * @return the Attr[]s to be outputted
+ * @return the Attr[]s to be output
* @throws CanonicalizationException
*/
- Iterator handleAttributes(Element E, NameSpaceSymbTable ns)
- throws CanonicalizationException {
+ @Override
+ protected Iterator handleAttributes(Element element, NameSpaceSymbTable ns)
+ throws CanonicalizationException {
// result will contain the attrs which have to be output
xmlattrStack.push(ns.getLevel());
- boolean isRealVisible = isVisibleDO(E, ns.getLevel()) == 1;
- NamedNodeMap attrs = null;
- int attrsLength = 0;
- if (E.hasAttributes()) {
- attrs = E.getAttributes();
- attrsLength = attrs.getLength();
- }
-
- SortedSet result = this.result;
+ boolean isRealVisible = isVisibleDO(element, ns.getLevel()) == 1;
+ final SortedSet result = this.result;
result.clear();
-
- for (int i = 0; i < attrsLength; i++) {
- Attr N = (Attr)attrs.item(i);
- String NUri = N.getNamespaceURI();
-
- if (XMLNS_URI != NUri) {
- // A non namespace definition node.
- if (XML_LANG_URI == NUri) {
- if (N.getLocalName().equals("id")) {
- if (isRealVisible) {
- // treat xml:id like any other attribute
- // (emit it, but don't inherit it)
- result.add(N);
+
+ if (element.hasAttributes()) {
+ NamedNodeMap attrs = element.getAttributes();
+ int attrsLength = attrs.getLength();
+
+ for (int i = 0; i < attrsLength; i++) {
+ Attr attribute = (Attr) attrs.item(i);
+ String NUri = attribute.getNamespaceURI();
+ String NName = attribute.getLocalName();
+ String NValue = attribute.getValue();
+
+ if (!XMLNS_URI.equals(NUri)) {
+ //A non namespace definition node.
+ if (XML_LANG_URI.equals(NUri)) {
+ if (NName.equals("id")) {
+ if (isRealVisible) {
+ // treat xml:id like any other attribute
+ // (emit it, but don't inherit it)
+ result.add(attribute);
+ }
+ } else {
+ xmlattrStack.addXmlnsAttr(attribute);
+ }
+ } else if (isRealVisible) {
+ //The node is visible add the attribute to the list of output attributes.
+ result.add(attribute);
+ }
+ } else if (!XML.equals(NName) || !XML_LANG_URI.equals(NValue)) {
+ /* 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.
+ */
+ // add the prefix binding to the ns symb table.
+ if (isVisible(attribute)) {
+ if (isRealVisible || !ns.removeMappingIfRender(NName)) {
+ // The xpath select this node output it if needed.
+ Node n = ns.addMappingAndRender(NName, NValue, attribute);
+ if (n != null) {
+ result.add((Attr)n);
+ if (C14nHelper.namespaceIsRelative(attribute)) {
+ Object exArgs[] = { element.getTagName(), NName, attribute.getNodeValue() };
+ throw new CanonicalizationException(
+ "c14n.Canonicalizer.RelativeNamespace", exArgs
+ );
+ }
+ }
}
} else {
- xmlattrStack.addXmlnsAttr(N);
- }
- } else if (isRealVisible) {
- // The node is visible add the attribute to the list of
- // output attributes.
- result.add(N);
- }
- // keep working
- continue;
- }
-
- String NName = N.getLocalName();
- String NValue = N.getValue();
- if ("xml".equals(NName)
- && XML_LANG_URI.equals(NValue)) {
- /* 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;
- }
- // add the prefix binding to the ns symb table.
- // ns.addInclusiveMapping(NName,NValue,N,isRealVisible);
- if (isVisible(N)) {
- if (!isRealVisible && ns.removeMappingIfRender(NName)) {
- continue;
- }
- // The xpath select this node output it if needed.
- // Node n = ns.addMappingAndRenderXNodeSet
- // (NName, NValue, N, isRealVisible);
- Node n = ns.addMappingAndRender(NName, NValue, N);
- if (n != null) {
- result.add((Attr)n);
- if (C14nHelper.namespaceIsRelative(N)) {
- Object exArgs[] =
- { E.getTagName(), NName, N.getNodeValue() };
- throw new CanonicalizationException(
- "c14n.Canonicalizer.RelativeNamespace", exArgs);
+ if (isRealVisible && !XMLNS.equals(NName)) {
+ ns.removeMapping(NName);
+ } else {
+ ns.addMapping(NName, NValue, attribute);
+ }
}
}
- } else {
- if (isRealVisible && NName != XMLNS) {
- ns.removeMapping(NName);
- } else {
- ns.addMapping(NName, NValue, N);
- }
}
}
- if (isRealVisible) {
- // The element is visible, handle the xmlns definition
- Attr xmlns = E.getAttributeNodeNS(XMLNS_URI, XMLNS);
+
+ if (isRealVisible) {
+ //The element is visible, handle the xmlns definition
+ Attr xmlns = element.getAttributeNodeNS(XMLNS_URI, XMLNS);
Node n = null;
if (xmlns == null) {
- // No xmlns def just get the already defined.
- n = ns.getMapping(XMLNS);
+ //No xmlns def just get the already defined.
+ n = ns.getMapping(XMLNS);
} else if (!isVisible(xmlns)) {
- // There is a defn but the xmlns is not selected by the xpath.
- // then xmlns=""
- n = ns.addMappingAndRender(XMLNS, "", nullNode);
+ //There is a definition but the xmlns is not selected by the xpath.
+ //then xmlns=""
+ n = ns.addMappingAndRender(XMLNS, "", nullNode);
}
- // output the xmlns def if needed.
+ //output the xmlns def if needed.
if (n != null) {
result.add((Attr)n);
}
- // Float all xml:* attributes of the unselected parent elements to
- // this one. addXmlAttributes(E,result);
+ //Float all xml:* attributes of the unselected parent elements to this one.
xmlattrStack.getXmlnsAttr(result);
ns.getUnrenderedNodes(result);
}
@@ -377,39 +396,12 @@
return result.iterator();
}
- /**
- * Always throws a CanonicalizationException because this is inclusive c14n.
- *
- * @param xpathNodeSet
- * @param inclusiveNamespaces
- * @return none it always fails
- * @throws CanonicalizationException always
- */
- public byte[] engineCanonicalizeXPathNodeSet(Set xpathNodeSet,
- String inclusiveNamespaces) throws CanonicalizationException {
- throw new CanonicalizationException(
- "c14n.Canonicalizer.UnsupportedOperation");
- }
-
- /**
- * Always throws a CanonicalizationException because this is inclusive c14n.
- *
- * @param rootNode
- * @param inclusiveNamespaces
- * @return none it always fails
- * @throws CanonicalizationException
- */
- public byte[] engineCanonicalizeSubTree(Node rootNode,
- String inclusiveNamespaces) throws CanonicalizationException {
- throw new CanonicalizationException(
- "c14n.Canonicalizer.UnsupportedOperation");
- }
-
- void circumventBugIfNeeded(XMLSignatureInput input)
- throws CanonicalizationException, ParserConfigurationException,
+ protected void circumventBugIfNeeded(XMLSignatureInput input)
+ throws CanonicalizationException, ParserConfigurationException,
IOException, SAXException {
- if (!input.isNeedsToBeExpanded())
+ if (!input.isNeedsToBeExpanded()) {
return;
+ }
Document doc = null;
if (input.getSubNode() != null) {
doc = XMLUtils.getOwnerDocument(input.getSubNode());
@@ -419,40 +411,47 @@
XMLUtils.circumventBug2650(doc);
}
- void handleParent(Element e, NameSpaceSymbTable ns) {
- if (!e.hasAttributes()) {
+ protected void handleParent(Element e, NameSpaceSymbTable ns) {
+ if (!e.hasAttributes() && e.getNamespaceURI() == null) {
return;
}
xmlattrStack.push(-1);
NamedNodeMap attrs = e.getAttributes();
int attrsLength = attrs.getLength();
for (int i = 0; i < attrsLength; i++) {
- Attr N = (Attr) attrs.item(i);
- if (Constants.NamespaceSpecNS != N.getNamespaceURI()) {
- // Not a namespace definition, ignore.
- if (XML_LANG_URI == N.getNamespaceURI()) {
- xmlattrStack.addXmlnsAttr(N);
- }
- continue;
- }
-
- String NName = N.getLocalName();
- String NValue = N.getNodeValue();
- if (XML.equals(NName)
- && Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) {
- continue;
+ Attr attribute = (Attr) attrs.item(i);
+ String NName = attribute.getLocalName();
+ String NValue = attribute.getNodeValue();
+
+ if (Constants.NamespaceSpecNS.equals(attribute.getNamespaceURI())) {
+ if (!XML.equals(NName) || !Constants.XML_LANG_SPACE_SpecNS.equals(NValue)) {
+ ns.addMapping(NName, NValue, attribute);
+ }
+ } else if (!"id".equals(NName) && XML_LANG_URI.equals(attribute.getNamespaceURI())) {
+ xmlattrStack.addXmlnsAttr(attribute);
+ }
+ }
+ if (e.getNamespaceURI() != null) {
+ String NName = e.getPrefix();
+ String NValue = e.getNamespaceURI();
+ String Name;
+ if (NName == null || NName.equals("")) {
+ NName = "xmlns";
+ Name = "xmlns";
+ } else {
+ Name = "xmlns:" + NName;
}
- ns.addMapping(NName,NValue,N);
+ Attr n = e.getOwnerDocument().createAttributeNS("http://www.w3.org/2000/xmlns/", Name);
+ n.setValue(NValue);
+ ns.addMapping(NName, NValue, n);
}
}
- private static String joinURI(String baseURI, String relativeURI)
- throws URISyntaxException {
+ private static String joinURI(String baseURI, String relativeURI) throws URISyntaxException {
String bscheme = null;
String bauthority = null;
String bpath = "";
String bquery = null;
- String bfragment = null; // Is this correct?
// pre-parse the baseURI
if (baseURI != null) {
@@ -464,7 +463,6 @@
bauthority = base.getAuthority();
bpath = base.getPath();
bquery = base.getQuery();
- bfragment = base.getFragment();
}
URI r = new URI(relativeURI);
@@ -472,9 +470,8 @@
String rauthority = r.getAuthority();
String rpath = r.getPath();
String rquery = r.getQuery();
- String rfragment = null;
- String tscheme, tauthority, tpath, tquery, tfragment;
+ String tscheme, tauthority, tpath, tquery;
if (rscheme != null && rscheme.equals(bscheme)) {
rscheme = null;
}
@@ -502,7 +499,7 @@
} else {
if (bauthority != null && bpath.length() == 0) {
tpath = "/" + rpath;
- } else {
+ } else {
int last = bpath.lastIndexOf('/');
if (last == -1) {
tpath = rpath;
@@ -518,13 +515,13 @@
}
tscheme = bscheme;
}
- tfragment = rfragment;
- return new URI(tscheme, tauthority, tpath, tquery, tfragment).toString();
+ return new URI(tscheme, tauthority, tpath, tquery, null).toString();
}
private static String removeDotSegments(String path) {
-
- log.log(java.util.logging.Level.FINE, "STEP OUTPUT BUFFER\t\tINPUT BUFFER");
+ if (log.isLoggable(java.util.logging.Level.FINE)) {
+ log.log(java.util.logging.Level.FINE, "STEP OUTPUT BUFFER\t\tINPUT BUFFER");
+ }
// 1. The input buffer is initialized with the now-appended path
// components then replace occurrences of "//" in the input buffer
@@ -535,7 +532,7 @@
}
// Initialize the output buffer with the empty string.
- StringBuffer output = new StringBuffer();
+ StringBuilder output = new StringBuilder();
// If the input buffer starts with a root slash "/" then move this
// character to the output buffer.
@@ -563,9 +560,9 @@
output.append("../");
}
printStep("2A", output.toString(), input);
- // 2B. if the input buffer begins with a prefix of "/./" or "/.",
- // where "." is a complete path segment, then replace that prefix
- // with "/" in the input buffer; otherwise,
+ // 2B. if the input buffer begins with a prefix of "/./" or "/.",
+ // where "." is a complete path segment, then replace that prefix
+ // with "/" in the input buffer; otherwise,
} else if (input.startsWith("/./")) {
input = input.substring(2);
printStep("2B", output.toString(), input);
@@ -573,16 +570,16 @@
// FIXME: what is complete path segment?
input = input.replaceFirst("/.", "/");
printStep("2B", output.toString(), input);
- // 2C. if the input buffer begins with a prefix of "/../" or "/..",
- // where ".." is a complete path segment, then replace that prefix
- // with "/" in the input buffer and if also the output buffer is
- // empty, last segment in the output buffer equals "../" or "..",
- // where ".." is a complete path segment, then append ".." or "/.."
- // for the latter case respectively to the output buffer else
- // remove the last segment and its preceding "/" (if any) from the
- // output buffer and if hereby the first character in the output
- // buffer was removed and it was not the root slash then delete a
- // leading slash from the input buffer; otherwise,
+ // 2C. if the input buffer begins with a prefix of "/../" or "/..",
+ // where ".." is a complete path segment, then replace that prefix
+ // with "/" in the input buffer and if also the output buffer is
+ // empty, last segment in the output buffer equals "../" or "..",
+ // where ".." is a complete path segment, then append ".." or "/.."
+ // for the latter case respectively to the output buffer else
+ // remove the last segment and its preceding "/" (if any) from the
+ // output buffer and if hereby the first character in the output
+ // buffer was removed and it was not the root slash then delete a
+ // leading slash from the input buffer; otherwise,
} else if (input.startsWith("/../")) {
input = input.substring(3);
if (output.length() == 0) {
@@ -594,7 +591,7 @@
} else {
int index = output.lastIndexOf("/");
if (index == -1) {
- output = new StringBuffer();
+ output = new StringBuilder();
if (input.charAt(0) == '/') {
input = input.substring(1);
}
@@ -615,7 +612,7 @@
} else {
int index = output.lastIndexOf("/");
if (index == -1) {
- output = new StringBuffer();
+ output = new StringBuilder();
if (input.charAt(0) == '/') {
input = input.substring(1);
}
@@ -624,23 +621,24 @@
}
}
printStep("2C", output.toString(), input);
- // 2D. if the input buffer consists only of ".", then remove
- // that from the input buffer else if the input buffer consists
- // only of ".." and if the output buffer does not contain only
- // the root slash "/", then move the ".." to the output buffer
- // else delte it.; otherwise,
+ // 2D. if the input buffer consists only of ".", then remove
+ // that from the input buffer else if the input buffer consists
+ // only of ".." and if the output buffer does not contain only
+ // the root slash "/", then move the ".." to the output buffer
+ // else delte it.; otherwise,
} else if (input.equals(".")) {
input = "";
printStep("2D", output.toString(), input);
} else if (input.equals("..")) {
- if (!output.toString().equals("/"))
+ if (!output.toString().equals("/")) {
output.append("..");
+ }
input = "";
printStep("2D", output.toString(), input);
- // 2E. move the first path segment (if any) in the input buffer
- // to the end of the output buffer, including the initial "/"
- // character (if any) and any subsequent characters up to, but not
- // including, the next "/" character or the end of the input buffer.
+ // 2E. move the first path segment (if any) in the input buffer
+ // to the end of the output buffer, including the initial "/"
+ // character (if any) and any subsequent characters up to, but not
+ // including, the next "/" character or the end of the input buffer.
} else {
int end = -1;
int begin = input.indexOf('/');