# HG changeset patch
# User aefimov
# Date 1467951010 -3600
# Node ID f968b06f80c67c03e8df692467d0411affc5a594
# Parent 023fdb2f8ee2e93a1e48bb12fafc91906f17bd38
8149962: Better delineation of XML processing
Reviewed-by: dfuchs, lancea, ahgross
diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xalan/internal/XalanConstants.java
--- a/src/com/sun/org/apache/xalan/internal/XalanConstants.java Fri Jul 08 04:17:27 2016 +0100
+++ b/src/com/sun/org/apache/xalan/internal/XalanConstants.java Fri Jul 08 05:10:10 2016 +0100
@@ -81,6 +81,14 @@
*/
public static final String JDK_GENEAL_ENTITY_SIZE_LIMIT =
ORACLE_JAXP_PROPERTY_PREFIX + "maxGeneralEntitySizeLimit";
+
+ /**
+ * JDK node count limit in entities that limits the total number of nodes
+ * in all of entity references.
+ */
+ public static final String JDK_ENTITY_REPLACEMENT_LIMIT =
+ ORACLE_JAXP_PROPERTY_PREFIX + "entityReplacementLimit";
+
/**
* JDK maximum parameter entity size limit
*/
@@ -137,6 +145,13 @@
* JDK maximum general entity size limit
*/
public static final String SP_GENEAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit";
+
+ /**
+ * JDK node count limit in entities that limits the total number of nodes
+ * in all of entity references.
+ */
+ public static final String SP_ENTITY_REPLACEMENT_LIMIT = "jdk.xml.entityReplacementLimit";
+
/**
* JDK maximum parameter entity size limit
*/
diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java
--- a/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java Fri Jul 08 04:17:27 2016 +0100
+++ b/src/com/sun/org/apache/xalan/internal/utils/XMLSecurityManager.java Fri Jul 08 05:10:10 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -80,7 +80,9 @@
MAX_ELEMENT_DEPTH_LIMIT("MaxElementDepthLimit", XalanConstants.JDK_MAX_ELEMENT_DEPTH,
XalanConstants.SP_MAX_ELEMENT_DEPTH, 0, 0),
MAX_NAME_LIMIT("MaxXMLNameLimit", XalanConstants.JDK_XML_NAME_LIMIT,
- XalanConstants.SP_XML_NAME_LIMIT, 1000, 1000);
+ XalanConstants.SP_XML_NAME_LIMIT, 1000, 1000),
+ ENTITY_REPLACEMENT_LIMIT("EntityReplacementLimit", XalanConstants.JDK_ENTITY_REPLACEMENT_LIMIT,
+ XalanConstants.SP_ENTITY_REPLACEMENT_LIMIT, 0, 3000000);
final String key;
final String apiProperty;
diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/Constants.java
--- a/src/com/sun/org/apache/xerces/internal/impl/Constants.java Fri Jul 08 04:17:27 2016 +0100
+++ b/src/com/sun/org/apache/xerces/internal/impl/Constants.java Fri Jul 08 05:10:10 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -242,6 +242,14 @@
*/
public static final String JDK_GENEAL_ENTITY_SIZE_LIMIT =
ORACLE_JAXP_PROPERTY_PREFIX + "maxGeneralEntitySizeLimit";
+
+ /**
+ * JDK node count limit in entities that limits the total number of nodes
+ * in all of entity references.
+ */
+ public static final String JDK_ENTITY_REPLACEMENT_LIMIT =
+ ORACLE_JAXP_PROPERTY_PREFIX + "entityReplacementLimit";
+
/**
* JDK maximum parameter entity size limit
*/
@@ -295,6 +303,13 @@
* JDK maximum general entity size limit
*/
public static final String SP_GENEAL_ENTITY_SIZE_LIMIT = "jdk.xml.maxGeneralEntitySizeLimit";
+
+ /**
+ * JDK node count limit in entities that limits the total number of nodes
+ * in all of entity references.
+ */
+ public static final String SP_ENTITY_REPLACEMENT_LIMIT = "jdk.xml.entityReplacementLimit";
+
/**
* JDK maximum parameter entity size limit
*/
diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java
--- a/src/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java Fri Jul 08 04:17:27 2016 +0100
+++ b/src/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java Fri Jul 08 05:10:10 2016 +0100
@@ -1,62 +1,21 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2004 The Apache Software Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
+ * 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
*
- * 4. The names "Xerces" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
- * Business Machines, Inc., http://www.apache.org. For more
- * information on the Apache Software Foundation, please see
- *
* Note: The character is consumed.
*
+ * @param nt The type of the name (element or attribute)
+ *
* @throws IOException Thrown if i/o error occurs.
* @throws EOFException Thrown on end of file.
*/
- public int scanChar() throws IOException {
+ protected int scanChar(NameType nt) throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(scanChar: ");
print();
@@ -544,6 +551,7 @@
}
// scan character
+ int offset = fCurrentEntity.position;
int c = fCurrentEntity.ch[fCurrentEntity.position++];
if (c == '\n' ||
(c == '\r' && isExternal)) {
@@ -553,6 +561,7 @@
invokeListeners(1);
fCurrentEntity.ch[0] = (char)c;
load(1, false, false);
+ offset = 0;
}
if (c == '\r' && isExternal) {
if (fCurrentEntity.ch[fCurrentEntity.position++] != '\n') {
@@ -569,6 +578,9 @@
System.out.println(" -> '"+(char)c+"'");
}
fCurrentEntity.columnNumber++;
+ if (!detectingVersion) {
+ checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
+ }
return c;
} // scanChar():int
@@ -588,7 +600,7 @@
* @see com.sun.org.apache.xerces.internal.util.SymbolTable
* @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
*/
- public String scanNmtoken() throws IOException {
+ protected String scanNmtoken() throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(scanNmtoken: ");
print();
@@ -660,6 +672,8 @@
* Note: The string returned must be a symbol. The
* SymbolTable can be used for this purpose.
*
+ * @param nt The type of the name (element or attribute)
+ *
* @throws IOException Thrown if i/o error occurs.
* @throws EOFException Thrown on end of file.
*
@@ -667,7 +681,7 @@
* @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
* @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
*/
- public String scanName() throws IOException {
+ protected String scanName(NameType nt) throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(scanName: ");
print();
@@ -724,6 +738,7 @@
String symbol;
if (length > 0) {
checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length);
+ checkEntityLimit(nt, fCurrentEntity, offset, length);
symbol = fSymbolTable.addSymbol(fCurrentEntity.ch, offset, length);
} else
symbol = null;
@@ -747,6 +762,7 @@
* this purpose.
*
* @param qname The qualified name structure to fill.
+ * @param nt The type of the name (element or attribute)
*
* @return Returns true if a qualified name appeared immediately on
* the input and was scanned, false otherwise.
@@ -758,7 +774,7 @@
* @see com.sun.org.apache.xerces.internal.util.XMLChar#isName
* @see com.sun.org.apache.xerces.internal.util.XMLChar#isNameStart
*/
- public boolean scanQName(QName qname) throws IOException {
+ protected boolean scanQName(QName qname, NameType nt) throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(scanQName, "+qname+": ");
print();
@@ -794,6 +810,7 @@
print();
System.out.println(" -> true");
}
+ checkEntityLimit(nt, fCurrentEntity, 0, 1);
return true;
}
}
@@ -859,6 +876,7 @@
print();
System.out.println(" -> true");
}
+ checkEntityLimit(nt, fCurrentEntity, offset, length);
return true;
}
}
@@ -891,7 +909,7 @@
int nameLength = length;
if (nameOffset != -1) {
nameOffset = nameOffset - offset;
- nameLength = length - nameOffset - 1;
+ nameLength = length - nameOffset;
} else {
nameOffset = offset;
}
@@ -913,22 +931,65 @@
}
/**
+ * If the current entity is an Entity reference, check the accumulated size
+ * against the limit.
+ *
+ * @param nt type of name (element, attribute or entity)
+ * @param entity The current entity
+ * @param offset The index of the first byte
+ * @param length The length of the entity scanned
+ */
+ protected void checkEntityLimit(NameType nt, ScannedEntity entity, int offset, int length) {
+ if (entity == null || !entity.isGE) {
+ return;
+ }
+
+ if (nt != NameType.REFERENCE) {
+ checkLimit(Limit.GENEAL_ENTITY_SIZE_LIMIT, entity, offset, length);
+ }
+ if (nt == NameType.ELEMENTSTART || nt == NameType.ATTRIBUTENAME) {
+ checkNodeCount(entity);
+ }
+ }
+
+ /**
+ * If the current entity is an Entity reference, counts the total nodes in
+ * the entity and checks the accumulated value against the limit.
+ *
+ * @param entity The current entity
+ */
+ protected void checkNodeCount(ScannedEntity entity) {
+ if (entity != null && entity.isGE) {
+ checkLimit(Limit.ENTITY_REPLACEMENT_LIMIT, entity, 0, 1);
+ }
+ }
+
+ /**
* Checks whether the value of the specified Limit exceeds its limit
*
- * @param limit The Limit to be checked.
- * @param entity The current entity.
+ * @param limit The Limit to be checked
+ * @param entity The current entity
* @param offset The index of the first byte
- * @param length The length of the entity scanned.
+ * @param length The length of the entity scanned
*/
protected void checkLimit(Limit limit, ScannedEntity entity, int offset, int length) {
- fLimitAnalyzer.addValue(limit, null, length);
+ fLimitAnalyzer.addValue(limit, entity.name, length);
if (fSecurityManager.isOverLimit(limit, fLimitAnalyzer)) {
fSecurityManager.debugPrint(fLimitAnalyzer);
+ Object[] e = (limit == Limit.ENTITY_REPLACEMENT_LIMIT) ?
+ new Object[]{fLimitAnalyzer.getValue(limit),
+ fSecurityManager.getLimit(limit), fSecurityManager.getStateLiteral(limit)} :
+ new Object[]{entity.name, fLimitAnalyzer.getValue(limit),
+ fSecurityManager.getLimit(limit), fSecurityManager.getStateLiteral(limit)};
fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, limit.key(),
- new Object[]{new String(entity.ch, offset, length),
- fLimitAnalyzer.getTotalValue(limit),
- fSecurityManager.getLimit(limit),
- fSecurityManager.getStateLiteral(limit)},
+ e, XMLErrorReporter.SEVERITY_FATAL_ERROR);
+ }
+ if (fSecurityManager.isOverLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
+ fSecurityManager.debugPrint(fLimitAnalyzer);
+ fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, "TotalEntitySizeLimit",
+ new Object[]{fLimitAnalyzer.getTotalValue(Limit.TOTAL_ENTITY_SIZE_LIMIT),
+ fSecurityManager.getLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT),
+ fSecurityManager.getStateLiteral(Limit.TOTAL_ENTITY_SIZE_LIMIT)},
XMLErrorReporter.SEVERITY_FATAL_ERROR);
}
}
@@ -955,7 +1016,7 @@
* @throws IOException Thrown if i/o error occurs.
* @throws EOFException Thrown on end of file.
*/
- public int scanContent(XMLString content) throws IOException {
+ protected int scanContent(XMLString content) throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(scanContent: ");
print();
@@ -976,6 +1037,7 @@
int offset = fCurrentEntity.position;
int c = fCurrentEntity.ch[offset];
int newlines = 0;
+ boolean counted = false;
if (c == '\n' || (c == '\r' && isExternal)) {
if (DEBUG_BUFFER) {
System.out.print("[newline, "+offset+", "+fCurrentEntity.position+": ");
@@ -989,9 +1051,11 @@
fCurrentEntity.lineNumber++;
fCurrentEntity.columnNumber = 1;
if (fCurrentEntity.position == fCurrentEntity.count) {
+ checkEntityLimit(null, fCurrentEntity, offset, newlines);
offset = 0;
fCurrentEntity.position = newlines;
if (load(newlines, false, true)) {
+ counted = true;
break;
}
}
@@ -1008,9 +1072,11 @@
fCurrentEntity.lineNumber++;
fCurrentEntity.columnNumber = 1;
if (fCurrentEntity.position == fCurrentEntity.count) {
+ checkEntityLimit(null, fCurrentEntity, offset, newlines);
offset = 0;
fCurrentEntity.position = newlines;
if (load(newlines, false, true)) {
+ counted = true;
break;
}
}
@@ -1024,6 +1090,7 @@
}
int length = fCurrentEntity.position - offset;
if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ checkEntityLimit(null, fCurrentEntity, offset, length);
//CHANGED: dont replace the value.. append to the buffer. This gives control to the callee
//on buffering the data..
content.setValues(fCurrentEntity.ch, offset, length);
@@ -1051,8 +1118,8 @@
}
int length = fCurrentEntity.position - offset;
fCurrentEntity.columnNumber += length - newlines;
- if (fCurrentEntity.isGE) {
- checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length);
+ if (!counted) {
+ checkEntityLimit(null, fCurrentEntity, offset, length);
}
//CHANGED: dont replace the value.. append to the buffer. This gives control to the callee
@@ -1108,7 +1175,7 @@
* @throws IOException Thrown if i/o error occurs.
* @throws EOFException Thrown on end of file.
*/
- public int scanLiteral(int quote, XMLString content, boolean isNSURI)
+ protected int scanLiteral(int quote, XMLString content, boolean isNSURI)
throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(scanLiteral, '"+(char)quote+"': ");
@@ -1229,9 +1296,8 @@
}
int length = fCurrentEntity.position - offset;
fCurrentEntity.columnNumber += length - newlines;
- if (fCurrentEntity.isGE) {
- checkLimit(Limit.TOTAL_ENTITY_SIZE_LIMIT, fCurrentEntity, offset, length);
- }
+
+ checkEntityLimit(null, fCurrentEntity, offset, length);
if (isNSURI) {
checkLimit(Limit.MAX_NAME_LIMIT, fCurrentEntity, offset, length);
}
@@ -1282,7 +1348,7 @@
* @throws IOException Thrown if i/o error occurs.
* @throws EOFException Thrown on end of file.
*/
- public boolean scanData(String delimiter, XMLStringBuffer buffer)
+ protected boolean scanData(String delimiter, XMLStringBuffer buffer)
throws IOException {
boolean done = false;
@@ -1320,6 +1386,7 @@
if (fCurrentEntity.position > fCurrentEntity.count - delimLen) {
// something must be wrong with the input: e.g., file ends in an unterminated comment
int length = fCurrentEntity.count - fCurrentEntity.position;
+ checkEntityLimit(NameType.COMMENT, fCurrentEntity, fCurrentEntity.position, length);
buffer.append (fCurrentEntity.ch, fCurrentEntity.position, length);
fCurrentEntity.columnNumber += fCurrentEntity.count;
fCurrentEntity.baseCharOffset += (fCurrentEntity.position - fCurrentEntity.startPosition);
@@ -1382,6 +1449,7 @@
}
int length = fCurrentEntity.position - offset;
if (fCurrentEntity.position == fCurrentEntity.count - 1) {
+ checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
buffer.append(fCurrentEntity.ch, offset, length);
if (DEBUG_BUFFER) {
System.out.print("]newline, "+offset+", "+fCurrentEntity.position+": ");
@@ -1425,12 +1493,14 @@
fCurrentEntity.position--;
int length = fCurrentEntity.position - offset;
fCurrentEntity.columnNumber += length - newlines;
+ checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
buffer.append(fCurrentEntity.ch, offset, length);
return true;
}
}
int length = fCurrentEntity.position - offset;
fCurrentEntity.columnNumber += length - newlines;
+ checkEntityLimit(NameType.COMMENT, fCurrentEntity, offset, length);
if (done) {
length -= delimLen;
}
@@ -1454,13 +1524,14 @@
* the specified character.
*
* @param c The character to skip.
+ * @param nt The type of the name (element or attribute)
*
* @return Returns true if the character was skipped.
*
* @throws IOException Thrown if i/o error occurs.
* @throws EOFException Thrown on end of file.
*/
- public boolean skipChar(int c) throws IOException {
+ protected boolean skipChar(int c, NameType nt) throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(skipChar, '"+(char)c+"': ");
print();
@@ -1473,6 +1544,7 @@
}
// skip character
+ int offset = fCurrentEntity.position;
int cc = fCurrentEntity.ch[fCurrentEntity.position];
if (cc == c) {
fCurrentEntity.position++;
@@ -1487,6 +1559,7 @@
print();
System.out.println(" -> true");
}
+ checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
return true;
} else if (c == '\n' && cc == '\r' && isExternal) {
// handle newlines
@@ -1506,6 +1579,7 @@
print();
System.out.println(" -> true");
}
+ checkEntityLimit(nt, fCurrentEntity, offset, fCurrentEntity.position - offset);
return true;
}
@@ -1535,7 +1609,7 @@
*
* @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
*/
- public boolean skipSpaces() throws IOException {
+ protected boolean skipSpaces() throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(skipSpaces: ");
print();
@@ -1559,6 +1633,7 @@
// skip spaces
int c = fCurrentEntity.ch[fCurrentEntity.position];
+ int offset = fCurrentEntity.position - 1;
if (XMLChar.isSpace(c)) {
do {
boolean entityChanged = false;
@@ -1588,6 +1663,11 @@
} else {
fCurrentEntity.columnNumber++;
}
+
+ //If this is a general entity, spaces within a start element should be counted
+ checkEntityLimit(null, fCurrentEntity, offset, fCurrentEntity.position - offset);
+ offset = fCurrentEntity.position;
+
// load more characters, if needed
if (!entityChanged){
fCurrentEntity.position++;
@@ -1629,7 +1709,7 @@
/**
- * @param legnth This function checks that following number of characters are available.
+ * @param length This function checks that following number of characters are available.
* to the underlying buffer.
* @return This function returns true if capacity asked is available.
*/
@@ -1638,9 +1718,9 @@
}
/**
- * @param legnth This function checks that following number of characters are available.
+ * @param length This function checks that following number of characters are available.
* to the underlying buffer.
- * @param if the underlying function should change the entity
+ * @param changeEntity a flag to indicate that the underlying function should change the entity
* @return This function returns true if capacity asked is available.
*
*/
@@ -1703,7 +1783,7 @@
* @throws IOException Thrown if i/o error occurs.
* @throws EOFException Thrown on end of file.
*/
- public boolean skipString(String s) throws IOException {
+ protected boolean skipString(String s) throws IOException {
final int length = s.length();
@@ -1723,6 +1803,9 @@
if(afterSkip-- == beforeSkip){
fCurrentEntity.position = fCurrentEntity.position + length ;
fCurrentEntity.columnNumber += length;
+ if (!detectingVersion) {
+ checkEntityLimit(null, fCurrentEntity, beforeSkip, length);
+ }
return true;
}
}
@@ -1731,7 +1814,7 @@
return false;
} // skipString(String):boolean
- public boolean skipString(char [] s) throws IOException {
+ protected boolean skipString(char [] s) throws IOException {
final int length = s.length;
//first make sure that required capacity is avaible
@@ -1751,6 +1834,9 @@
}
fCurrentEntity.position = fCurrentEntity.position + length ;
fCurrentEntity.columnNumber += length;
+ if (!detectingVersion) {
+ checkEntityLimit(null, fCurrentEntity, beforeSkip, length);
+ }
return true;
}
@@ -2148,7 +2234,7 @@
*
* @see com.sun.org.apache.xerces.internal.util.XMLChar#isSpace
*/
- public final boolean skipDeclSpaces() throws IOException {
+ protected final boolean skipDeclSpaces() throws IOException {
if (DEBUG_BUFFER) {
System.out.print("(skipDeclSpaces: ");
//XMLEntityManager.print(fCurrentEntity);
diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java
--- a/src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java Fri Jul 08 04:17:27 2016 +0100
+++ b/src/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java Fri Jul 08 05:10:10 2016 +0100
@@ -196,9 +196,9 @@
// There are two variables,fNamespaces and fBindNamespaces
//StAX uses XMLNSDocumentScannerImpl so this distinction needs to be maintained
if (fNamespaces) {
- fEntityScanner.scanQName(fElementQName);
+ fEntityScanner.scanQName(fElementQName, NameType.ELEMENTSTART);
} else {
- String name = fEntityScanner.scanName();
+ String name = fEntityScanner.scanName(NameType.ELEMENTSTART);
fElementQName.setValues(null, name, name, null);
}
@@ -411,11 +411,11 @@
if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()");
// name
- fEntityScanner.scanQName(fAttributeQName);
+ fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTE);
// equals
fEntityScanner.skipSpaces();
- if (!fEntityScanner.skipChar('=')) {
+ if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) {
reportFatalError("EqRequiredInAttribute",
new Object[]{fCurrentElement.rawname,fAttributeQName.rawname});
}
diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java
--- a/src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java Fri Jul 08 04:17:27 2016 +0100
+++ b/src/com/sun/org/apache/xerces/internal/impl/XMLScanner.java Fri Jul 08 05:10:10 2016 +0100
@@ -35,7 +35,6 @@
import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xerces.internal.xni.Augmentations;
-import com.sun.org.apache.xerces.internal.xni.QName;
import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
import com.sun.org.apache.xerces.internal.xni.XMLString;
@@ -117,6 +116,30 @@
/** Debug attribute normalization. */
protected static final boolean DEBUG_ATTR_NORMALIZATION = false;
+ /**
+ * Type of names
+ */
+ public static enum NameType {
+ ATTRIBUTE("attribute"),
+ ATTRIBUTENAME("attribute name"),
+ COMMENT("comment"),
+ DOCTYPE("doctype"),
+ ELEMENTSTART("startelement"),
+ ELEMENTEND("endelement"),
+ ENTITY("entity"),
+ NOTATION("notation"),
+ PI("pi"),
+ REFERENCE("reference");
+
+ final String literal;
+ NameType(String literal) {
+ this.literal = literal;
+ }
+
+ String literal() {
+ return literal;
+ }
+ }
//xxx: setting the default value as false, as we dont need to calculate this value
//we should have a feature when set to true computes this value
@@ -147,7 +170,7 @@
protected boolean fNotifyCharRefs = false;
/** Internal parser-settings feature */
- protected boolean fParserSettings = true;
+ protected boolean fParserSettings = true;
// properties
@@ -176,13 +199,13 @@
/** event type */
protected XMLEvent fEvent ;
- /** Entity scanner, this alwasy works on last entity that was opened. */
+ /** Entity scanner, this always works on last entity that was opened. */
protected XMLEntityScanner fEntityScanner = null;
/** Entity depth. */
protected int fEntityDepth;
- /** Literal value of the last character refence scanned. */
+ /** Literal value of the last character reference scanned. */
protected String fCharRefLiteral = null;
/** Scanning attribute. */
@@ -550,10 +573,10 @@
}
// end
- if (!fEntityScanner.skipChar('?')) {
+ if (!fEntityScanner.skipChar('?', null)) {
reportFatalError("XMLDeclUnterminated", null);
}
- if (!fEntityScanner.skipChar('>')) {
+ if (!fEntityScanner.skipChar('>', null)) {
reportFatalError("XMLDeclUnterminated", null);
}
@@ -580,7 +603,7 @@
* Note: This method uses fStringBuffer2, anything in it
* at the time of calling is lost.
*/
- public String scanPseudoAttribute(boolean scanningTextDecl,
+ protected String scanPseudoAttribute(boolean scanningTextDecl,
XMLString value)
throws IOException, XNIException {
@@ -591,7 +614,7 @@
reportFatalError("PseudoAttrNameExpected", null);
}
fEntityScanner.skipSpaces();
- if (!fEntityScanner.skipChar('=')) {
+ if (!fEntityScanner.skipChar('=', null)) {
reportFatalError(scanningTextDecl ? "EqRequiredInTextDecl"
: "EqRequiredInXMLDecl", new Object[]{name});
}
@@ -601,7 +624,7 @@
reportFatalError(scanningTextDecl ? "QuoteRequiredInTextDecl"
: "QuoteRequiredInXMLDecl" , new Object[]{name});
}
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(NameType.ATTRIBUTE);
int c = fEntityScanner.scanLiteral(quote, value, false);
if (c != quote) {
fStringBuffer2.clear();
@@ -609,7 +632,7 @@
fStringBuffer2.append(value);
if (c != -1) {
if (c == '&' || c == '%' || c == '<' || c == ']') {
- fStringBuffer2.append((char)fEntityScanner.scanChar());
+ fStringBuffer2.append((char)fEntityScanner.scanChar(NameType.ATTRIBUTE));
} else if (XMLChar.isHighSurrogate(c)) {
scanSurrogates(fStringBuffer2);
} else if (isInvalidLiteral(c)) {
@@ -617,7 +640,7 @@
? "InvalidCharInTextDecl" : "InvalidCharInXMLDecl";
reportFatalError(key,
new Object[] {Integer.toString(c, 16)});
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(null);
}
}
c = fEntityScanner.scanLiteral(quote, value, false);
@@ -625,7 +648,7 @@
fStringBuffer2.append(value);
value.setValues(fStringBuffer2);
}
- if (!fEntityScanner.skipChar(quote)) {
+ if (!fEntityScanner.skipChar(quote, null)) {
reportFatalError(scanningTextDecl ? "CloseQuoteMissingInTextDecl"
: "CloseQuoteMissingInXMLDecl",
new Object[]{name});
@@ -683,7 +706,7 @@
// target
fReportEntity = false;
- String target = fEntityScanner.scanName();
+ String target = fEntityScanner.scanName(NameType.PI);
if (target == null) {
reportFatalError("PITargetRequired", null);
}
@@ -748,7 +771,7 @@
} else if (isInvalidLiteral(c)) {
reportFatalError("InvalidCharInPI",
new Object[]{Integer.toHexString(c)});
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(null);
}
}
} while (fEntityScanner.scanData("?>", data));
@@ -789,11 +812,11 @@
if (isInvalidLiteral(c)) {
reportFatalError("InvalidCharInComment",
new Object[] { Integer.toHexString(c) });
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(NameType.COMMENT);
}
}
}
- if (!fEntityScanner.skipChar('>')) {
+ if (!fEntityScanner.skipChar('>', NameType.COMMENT)) {
reportFatalError("DashDashInComment", null);
}
@@ -830,7 +853,7 @@
reportFatalError("OpenQuoteExpected", new Object[]{eleName, atName});
}
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(NameType.ATTRIBUTE);
int entityDepth = fEntityDepth;
int c = fEntityScanner.scanLiteral(quote, value, isNSURI);
@@ -859,11 +882,11 @@
+ stringBuffer.toString() + "\"");
}
if (c == '&') {
- fEntityScanner.skipChar('&');
+ fEntityScanner.skipChar('&', NameType.REFERENCE);
if (entityDepth == fEntityDepth && fNeedNonNormalizedValue ) {
fStringBuffer2.append('&');
}
- if (fEntityScanner.skipChar('#')) {
+ if (fEntityScanner.skipChar('#', NameType.REFERENCE)) {
if (entityDepth == fEntityDepth && fNeedNonNormalizedValue ) {
fStringBuffer2.append('#');
}
@@ -881,53 +904,20 @@
}
}
} else {
- String entityName = fEntityScanner.scanName();
+ String entityName = fEntityScanner.scanName(NameType.ENTITY);
if (entityName == null) {
reportFatalError("NameRequiredInReference", null);
} else if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
fStringBuffer2.append(entityName);
}
- if (!fEntityScanner.skipChar(';')) {
+ if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
reportFatalError("SemicolonRequiredInReference",
new Object []{entityName});
} else if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
fStringBuffer2.append(';');
}
- if (entityName == fAmpSymbol) {
- stringBuffer.append('&');
- if (DEBUG_ATTR_NORMALIZATION) {
- System.out.println("** value5: \""
- + stringBuffer.toString()
- + "\"");
- }
- } else if (entityName == fAposSymbol) {
- stringBuffer.append('\'');
- if (DEBUG_ATTR_NORMALIZATION) {
- System.out.println("** value7: \""
- + stringBuffer.toString()
- + "\"");
- }
- } else if (entityName == fLtSymbol) {
- stringBuffer.append('<');
- if (DEBUG_ATTR_NORMALIZATION) {
- System.out.println("** value9: \""
- + stringBuffer.toString()
- + "\"");
- }
- } else if (entityName == fGtSymbol) {
- stringBuffer.append('>');
- if (DEBUG_ATTR_NORMALIZATION) {
- System.out.println("** valueB: \""
- + stringBuffer.toString()
- + "\"");
- }
- } else if (entityName == fQuotSymbol) {
- stringBuffer.append('"');
- if (DEBUG_ATTR_NORMALIZATION) {
- System.out.println("** valueD: \""
- + stringBuffer.toString()
- + "\"");
- }
+ if (resolveCharacter(entityName, stringBuffer)) {
+ checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
} else {
if (fEntityStore.isExternalEntity(entityName)) {
reportFatalError("ReferenceToExternalEntity",
@@ -954,12 +944,12 @@
} else if (c == '<') {
reportFatalError("LessthanInAttValue",
new Object[] { eleName, atName });
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(null);
if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
fStringBuffer2.append((char)c);
}
} else if (c == '%' || c == ']') {
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(null);
stringBuffer.append((char)c);
if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
fStringBuffer2.append((char)c);
@@ -969,7 +959,7 @@
+ stringBuffer.toString() + "\"");
}
} else if (c == '\n' || c == '\r') {
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(null);
stringBuffer.append(' ');
if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
fStringBuffer2.append('\n');
@@ -990,7 +980,7 @@
} else if (c != -1 && isInvalidLiteral(c)) {
reportFatalError("InvalidCharInAttValue",
new Object[] {eleName, atName, Integer.toString(c, 16)});
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(null);
if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) {
fStringBuffer2.append((char)c);
}
@@ -1016,7 +1006,7 @@
nonNormalizedValue.setValues(fStringBuffer2);
// quote
- int cquote = fEntityScanner.scanChar();
+ int cquote = fEntityScanner.scanChar(NameType.ATTRIBUTE);
if (cquote != quote) {
reportFatalError("CloseQuoteExpected", new Object[]{eleName, atName});
}
@@ -1024,6 +1014,39 @@
/**
+ * Resolves character entity references.
+ * @param entityName the name of the entity
+ * @param stringBuffer the current XMLStringBuffer to append the character to.
+ * @return true if resolved, false otherwise
+ */
+ protected boolean resolveCharacter(String entityName, XMLStringBuffer stringBuffer) {
+ /**
+ * entityNames (symbols) are interned. The equals method would do the same,
+ * but I'm leaving it as comparisons by references are common in the impl
+ * and it made it explicit to others who read this code.
+ */
+ if (entityName == fAmpSymbol) {
+ stringBuffer.append('&');
+ return true;
+ } else if (entityName == fAposSymbol) {
+ stringBuffer.append('\'');
+ return true;
+ } else if (entityName == fLtSymbol) {
+ stringBuffer.append('<');
+ return true;
+ } else if (entityName == fGtSymbol) {
+ checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
+ stringBuffer.append('>');
+ return true;
+ } else if (entityName == fQuotSymbol) {
+ checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
+ stringBuffer.append('"');
+ return true;
+ }
+ return false;
+ }
+
+ /**
* Scans External ID and return the public and system IDs.
*
* @param identifiers An array of size 2 to return the system id,
@@ -1066,7 +1089,7 @@
}
reportFatalError("QuoteRequiredInSystemID", null);
}
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(null);
XMLString ident = fString;
if (fEntityScanner.scanLiteral(quote, ident, false) != quote) {
fStringBuffer.clear();
@@ -1074,7 +1097,7 @@
fStringBuffer.append(ident);
int c = fEntityScanner.peekChar();
if (XMLChar.isMarkup(c) || c == ']') {
- fStringBuffer.append((char)fEntityScanner.scanChar());
+ fStringBuffer.append((char)fEntityScanner.scanChar(null));
} else if (c != -1 && isInvalidLiteral(c)) {
reportFatalError("InvalidCharInSystemID",
new Object[] {Integer.toString(c, 16)});
@@ -1084,7 +1107,7 @@
ident = fStringBuffer;
}
systemId = ident.toString();
- if (!fEntityScanner.skipChar(quote)) {
+ if (!fEntityScanner.skipChar(quote, null)) {
reportFatalError("SystemIDUnterminated", null);
}
}
@@ -1116,7 +1139,7 @@
*/
protected boolean scanPubidLiteral(XMLString literal)
throws IOException, XNIException {
- int quote = fEntityScanner.scanChar();
+ int quote = fEntityScanner.scanChar(null);
if (quote != '\'' && quote != '"') {
reportFatalError("QuoteRequiredInPublicID", null);
return false;
@@ -1127,7 +1150,7 @@
boolean skipSpace = true;
boolean dataok = true;
while (true) {
- int c = fEntityScanner.scanChar();
+ int c = fEntityScanner.scanChar(null);
if (c == ' ' || c == '\n' || c == '\r') {
if (!skipSpace) {
// take the first whitespace as a space and skip the others
@@ -1243,9 +1266,10 @@
*/
protected int scanCharReferenceValue(XMLStringBuffer buf, XMLStringBuffer buf2)
throws IOException, XNIException {
+ int initLen = buf.length;
// scan hexadecimal value
boolean hex = false;
- if (fEntityScanner.skipChar('x')) {
+ if (fEntityScanner.skipChar('x', NameType.REFERENCE)) {
if (buf2 != null) { buf2.append('x'); }
hex = true;
fStringBuffer3.clear();
@@ -1257,7 +1281,7 @@
(c >= 'A' && c <= 'F');
if (digit) {
if (buf2 != null) { buf2.append((char)c); }
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(NameType.REFERENCE);
fStringBuffer3.append((char)c);
do {
@@ -1267,7 +1291,7 @@
(c >= 'A' && c <= 'F');
if (digit) {
if (buf2 != null) { buf2.append((char)c); }
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(NameType.REFERENCE);
fStringBuffer3.append((char)c);
}
} while (digit);
@@ -1285,7 +1309,7 @@
digit = c >= '0' && c <= '9';
if (digit) {
if (buf2 != null) { buf2.append((char)c); }
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(NameType.REFERENCE);
fStringBuffer3.append((char)c);
do {
@@ -1293,7 +1317,7 @@
digit = c >= '0' && c <= '9';
if (digit) {
if (buf2 != null) { buf2.append((char)c); }
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(NameType.REFERENCE);
fStringBuffer3.append((char)c);
}
} while (digit);
@@ -1303,7 +1327,7 @@
}
// end
- if (!fEntityScanner.skipChar(';')) {
+ if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
reportFatalError("SemicolonRequiredInCharRef", null);
}
if (buf2 != null) { buf2.append(';'); }
@@ -1349,6 +1373,9 @@
}
}
+ if (fEntityScanner.fCurrentEntity.isGE) {
+ checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, buf.length - initLen);
+ }
return value;
}
// returns true if the given character is not
@@ -1402,14 +1429,14 @@
protected boolean scanSurrogates(XMLStringBuffer buf)
throws IOException, XNIException {
- int high = fEntityScanner.scanChar();
+ int high = fEntityScanner.scanChar(null);
int low = fEntityScanner.peekChar();
if (!XMLChar.isLowSurrogate(low)) {
reportFatalError("InvalidCharInContent",
new Object[] {Integer.toString(high, 16)});
return false;
}
- fEntityScanner.scanChar();
+ fEntityScanner.scanChar(null);
// convert surrogates to supplemental character
int c = XMLChar.supplemental((char)high, (char)low);
@@ -1472,5 +1499,52 @@
}
}
+ /**
+ * Add the count of the content buffer and check if the accumulated
+ * value exceeds the limit
+ * @param isPEDecl a flag to indicate whether the entity is parameter
+ * @param entityName entity name
+ * @param buffer content buffer
+ */
+ void checkEntityLimit(boolean isPEDecl, String entityName, XMLString buffer) {
+ checkEntityLimit(isPEDecl, entityName, buffer.length);
+ }
+ /**
+ * Add the count and check limit
+ * @param isPEDecl a flag to indicate whether the entity is parameter
+ * @param entityName entity name
+ * @param len length of the buffer
+ */
+ void checkEntityLimit(boolean isPEDecl, String entityName, int len) {
+ if (fLimitAnalyzer == null) {
+ fLimitAnalyzer = fEntityManager.fLimitAnalyzer;
+ }
+ if (isPEDecl) {
+ fLimitAnalyzer.addValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, "%" + entityName, len);
+ if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
+ fSecurityManager.debugPrint(fLimitAnalyzer);
+ reportFatalError("MaxEntitySizeLimit", new Object[]{"%" + entityName,
+ fLimitAnalyzer.getValue(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT),
+ fSecurityManager.getLimit(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT),
+ fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.PARAMETER_ENTITY_SIZE_LIMIT)});
+ }
+ } else {
+ fLimitAnalyzer.addValue(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT, entityName, len);
+ if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
+ fSecurityManager.debugPrint(fLimitAnalyzer);
+ reportFatalError("MaxEntitySizeLimit", new Object[]{entityName,
+ fLimitAnalyzer.getValue(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT),
+ fSecurityManager.getLimit(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT),
+ fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.GENEAL_ENTITY_SIZE_LIMIT)});
+ }
+ }
+ if (fSecurityManager.isOverLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT, fLimitAnalyzer)) {
+ fSecurityManager.debugPrint(fLimitAnalyzer);
+ reportFatalError("TotalEntitySizeLimit",
+ new Object[]{fLimitAnalyzer.getTotalValue(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT),
+ fSecurityManager.getLimit(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT),
+ fSecurityManager.getStateLiteral(XMLSecurityManager.Limit.TOTAL_ENTITY_SIZE_LIMIT)});
+ }
+ }
} // class XMLScanner
diff -r 023fdb2f8ee2 -r f968b06f80c6 src/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java
--- a/src/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java Fri Jul 08 04:17:27 2016 +0100
+++ b/src/com/sun/org/apache/xerces/internal/impl/XMLVersionDetector.java Fri Jul 08 05:10:10 2016 +0100
@@ -1,62 +1,21 @@
/*
- * reserved comment block
- * DO NOT REMOVE OR ALTER!
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
*/
/*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2003 The Apache Software Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
+ * 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
*
- * 4. The names "Xerces" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 2003, International
- * Business Machines, Inc., http://www.apache.org. For more
- * information on the Apache Software Foundation, please see
- *