--- java/org/apache/catalina/Context.java.orig 2014-07-21 17:24:05.516400000 -0400
+++ java/org/apache/catalina/Context.java 2014-07-21 17:46:59.386109000 -0400
@@ -40,6 +40,7 @@
import org.apache.catalina.deploy.NamingResources;
import org.apache.catalina.deploy.SecurityConstraint;
import org.apache.catalina.util.CharsetMapper;
+import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.http.mapper.Mapper;
@@ -61,7 +62,7 @@
* <p>
*
* @author Craig R. McClanahan
- * @version $Id: Context.java 1492415 2013-06-12 20:41:33Z markt $
+ * @version $Id: Context.java 1552258 2013-12-19 09:25:18Z markt $
*/
public interface Context extends Container {
@@ -616,70 +617,99 @@
/**
- * Get the server.xml <context> attribute's xmlNamespaceAware.
- * @return true if namespace awareness is enabled.
+ * Will the parsing of web.xml and web-fragment.xml files for this Context
+ * be performed by a namespace aware parser?
*
+ * @return true if namespace awareness is enabled.
*/
public boolean getXmlNamespaceAware();
+
+ /**
+ * Controls whether the parsing of web.xml and web-fragment.xml files for
+ * this Context will be performed by a namespace aware parser.
+ *
+ * @param xmlNamespaceAware true to enable namespace awareness
+ */
+ public void setXmlNamespaceAware(boolean xmlNamespaceAware);
+
/**
- * Get the server.xml <context> attribute's xmlValidation.
- * @return true if validation is enabled.
+ * Will the parsing of web.xml and web-fragment.xml files for this Context
+ * be performed by a validating parser?
*
+ * @return true if validation is enabled.
*/
public boolean getXmlValidation();
/**
- * Set the validation feature of the XML parser used when
- * parsing xml instances.
- * @param xmlValidation true to enable xml instance validation
+ * Controls whether the parsing of web.xml and web-fragment.xml files
+ * for this Context will be performed by a validating parser.
+ *
+ * @param xmlValidation true to enable xml validation
*/
public void setXmlValidation(boolean xmlValidation);
- /**
- * Set the namespace aware feature of the XML parser used when
- * parsing xml instances.
- * @param xmlNamespaceAware true to enable namespace awareness
+ /**
+ * *.tld files are always parsed using a namespace aware parser.
+ *
+ * @return Always <code>true</code>
+ *
+ * @deprecated This option will be removed in 8.0.x.
*/
- public void setXmlNamespaceAware(boolean xmlNamespaceAware);
+ @Deprecated
+ public boolean getTldNamespaceAware();
+
+
/**
- * Get the server.xml <context> attribute's xmlValidation.
- * @return true if validation is enabled.
+ * *.tld files are always parsed using a namespace aware parser.
+ *
+ * @param tldNamespaceAware ignored
+ *
+ * @deprecated This option will be removed in 8.0.x.
*/
+ @Deprecated
+ public void setTldNamespaceAware(boolean tldNamespaceAware);
/**
- * Set the validation feature of the XML parser used when
- * parsing tlds files.
- * @param tldValidation true to enable xml instance validation
+ * Will the parsing of web.xml, web-fragment.xml, *.tld, *.jspx, *.tagx and
+ * tagplugin.xml files for this Context block the use of external entities?
+ *
+ * @return true if access to external entities is blocked
*/
- public void setTldValidation(boolean tldValidation);
+ public boolean getXmlBlockExternal();
/**
- * Get the server.xml <context> attribute's webXmlValidation.
- * @return true if validation is enabled.
+ * Controls whether the parsing of web.xml, web-fragment.xml, *.tld, *.jspx,
+ * *.tagx and tagplugin.xml files for this Context will block the use of
+ * external entities.
*
+ * @param xmlBlockExternal true to block external entities
*/
- public boolean getTldValidation();
+ public void setXmlBlockExternal(boolean xmlBlockExternal);
/**
- * Get the server.xml <host> attribute's xmlNamespaceAware.
- * @return true if namespace awareness is enabled.
+ * Will the parsing of *.tld files for this Context be performed by a
+ * validating parser?
+ *
+ * @return true if validation is enabled.
*/
- public boolean getTldNamespaceAware();
+ public boolean getTldValidation();
/**
- * Set the namespace aware feature of the XML parser used when
- * parsing xml instances.
- * @param tldNamespaceAware true to enable namespace awareness
+ * Controls whether the parsing of *.tld files for this Context will be
+ * performed by a validating parser.
+ *
+ * @param tldValidation true to enable xml validation
*/
- public void setTldNamespaceAware(boolean tldNamespaceAware);
+ public void setTldValidation(boolean tldValidation);
+
/**
* Get the Jar Scanner to be used to scan for JAR resources for this
@@ -712,6 +742,16 @@
*/
public boolean getLogEffectiveWebXml();
+ /**
+ * Get the instance manager associated with this context.
+ */
+ public InstanceManager getInstanceManager();
+
+ /**
+ * Set the instance manager associated with this context.
+ */
+ public void setInstanceManager(InstanceManager instanceManager);
+
// --------------------------------------------------------- Public Methods
--- java/org/apache/catalina/Globals.java.orig 2014-07-21 17:24:05.521402000 -0400
+++ java/org/apache/catalina/Globals.java 2014-07-21 17:46:59.394034000 -0400
@@ -14,18 +14,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-
package org.apache.catalina;
-
/**
* Global constants that are applicable to multiple packages within Catalina.
*
* @author Craig R. McClanahan
- * @version $Id: Globals.java 1301255 2012-03-15 22:47:40Z markt $
+ * @version $Id: Globals.java 1549529 2013-12-09 10:05:56Z markt $
*/
-
public final class Globals {
/**
@@ -310,4 +306,25 @@
* the tomcat instance installation path
*/
public static final String CATALINA_BASE_PROP = "catalina.base";
+
+
+ /**
+ * Name of the ServletContext init-param that determines if the JSP engine
+ * should validate *.tld files when parsing them.
+ * <p>
+ * This must be kept in sync with org.apache.jasper.Constants
+ */
+ public static final String JASPER_XML_VALIDATION_TLD_INIT_PARAM =
+ "org.apache.jasper.XML_VALIDATE_TLD";
+
+
+ /**
+ * Name of the ServletContext init-param that determines if the JSP engine
+ * will block external entities from being used in *.tld, *.jspx, *.tagx and
+ * tagplugin.xml files.
+ * <p>
+ * This must be kept in sync with org.apache.jasper.Constants
+ */
+ public static final String JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM =
+ "org.apache.jasper.XML_BLOCK_EXTERNAL";
}
--- java/org/apache/catalina/ant/ValidatorTask.java.orig 2014-07-21 17:24:05.537406000 -0400
+++ java/org/apache/catalina/ant/ValidatorTask.java 2014-07-21 17:46:59.401034000 -0400
@@ -14,18 +14,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-
package org.apache.catalina.ant;
-
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
+import org.apache.catalina.Globals;
import org.apache.catalina.startup.Constants;
-import org.apache.catalina.startup.DigesterFactory;
+import org.apache.tomcat.util.descriptor.DigesterFactory;
import org.apache.tomcat.util.digester.Digester;
import org.apache.tools.ant.BuildException;
import org.xml.sax.InputSource;
@@ -36,7 +34,7 @@
* schema validation.
*
* @author Remy Maucherat
- * @version $Id: ValidatorTask.java 1001899 2010-09-27 20:24:18Z markt $
+ * @version $Id: ValidatorTask.java 1549529 2013-12-09 10:05:56Z markt $
* @since 5.0
*/
@@ -90,7 +88,10 @@
Thread.currentThread().setContextClassLoader
(ValidatorTask.class.getClassLoader());
- Digester digester = DigesterFactory.newDigester(true, true, null);
+ // Called through trusted manager interface. If running under a
+ // SecurityManager assume that untrusted applications may be deployed.
+ Digester digester = DigesterFactory.newDigester(
+ true, true, null, Globals.IS_SECURITY_ENABLED);
try {
file = file.getCanonicalFile();
InputStream stream =
--- java/org/apache/catalina/core/ApplicationContext.java.orig 2014-07-21 17:24:05.543399000 -0400
+++ java/org/apache/catalina/core/ApplicationContext.java 2014-07-22 16:07:21.579832000 -0400
@@ -5,9 +5,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -84,7 +84,7 @@
*
* @author Craig R. McClanahan
* @author Remy Maucherat
- * @version $Id: ApplicationContext.java 1493015 2013-06-14 10:00:57Z markt $
+ * @version $Id: ApplicationContext.java 1549529 2013-12-09 10:05:56Z markt $
*/
public class ApplicationContext
@@ -97,7 +97,7 @@
static {
STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
-
+
String requireSlash = System.getProperty(
"org.apache.catalina.core.ApplicationContext.GET_RESOURCE_REQUIRE_SLASH");
if (requireSlash == null) {
@@ -302,7 +302,7 @@
}
}
-
+
/**
* Return the main path associated with this context.
*/
@@ -310,7 +310,7 @@
public String getContextPath() {
return context.getPath();
}
-
+
/**
* Return the value of the specified initialization parameter, or
@@ -320,6 +320,20 @@
*/
@Override
public String getInitParameter(final String name) {
+ // Special handling for XML settings as the context setting must
+ // always override anything that might have been set by an application.
+ if (Globals.JASPER_XML_VALIDATION_TLD_INIT_PARAM.equals(name) &&
+ context.getTldValidation()) {
+ return "true";
+ }
+ if (Globals.JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM.equals(name)) {
+ if (context.getXmlBlockExternal()) {
+ return "true";
+ } else if (Globals.IS_SECURITY_ENABLED) {
+ // System admin has explicitly changed the default
+ return "false";
+ }
+ }
return parameters.get(name);
}
@@ -330,7 +344,17 @@
*/
@Override
public Enumeration<String> getInitParameterNames() {
- return Collections.enumeration(parameters.keySet());
+ Set<String> names = new HashSet<String>();
+ names.addAll(parameters.keySet());
+ // Special handling for XML settings as these attributes will always be
+ // available if they have been set on the context
+ if (context.getTldValidation()) {
+ names.add(Globals.JASPER_XML_VALIDATION_TLD_INIT_PARAM);
+ }
+ if (context.getXmlBlockExternal() || Globals.IS_SECURITY_ENABLED) {
+ names.add(Globals.JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM);
+ }
+ return Collections.enumeration(names);
}
@@ -395,7 +419,7 @@
Wrapper wrapper = (Wrapper) context.findChild(name);
if (wrapper == null)
return (null);
-
+
return new ApplicationDispatcher(wrapper, null, null, null, null, name);
}
@@ -444,7 +468,7 @@
if (normalizedPath == null)
return (null);
- pos = normalizedPath.length();
+ pos = normalizedPath.length();
// Use the thread local URI and mapping data
DispatchData dd = dispatchData.get();
@@ -495,10 +519,10 @@
String pathInfo = mappingData.pathInfo.toString();
mappingData.recycle();
-
+
// Construct a RequestDispatcher to process this request
return new ApplicationDispatcher
- (wrapper, uriCC.toString(), wrapperPath, pathInfo,
+ (wrapper, uriCC.toString(), wrapperPath, pathInfo,
queryString, null);
}
@@ -523,7 +547,7 @@
!path.startsWith("/") && GET_RESOURCE_REQUIRE_SLASH)
throw new MalformedURLException(sm.getString(
"applicationContext.requestDispatcher.iae", path));
-
+
String normPath = RequestUtil.normalize(path);
if (normPath == null)
return (null);
@@ -724,7 +748,7 @@
@Override
@Deprecated
public void log(Exception exception, String message) {
-
+
context.getLogger().error(message, exception);
}
@@ -738,7 +762,7 @@
*/
@Override
public void log(String message, Throwable throwable) {
-
+
context.getLogger().error(message, throwable);
}
@@ -893,11 +917,11 @@
@Override
public FilterRegistration.Dynamic addFilter(String filterName,
String filterClass) throws IllegalStateException {
-
+
return addFilter(filterName, filterClass, null);
}
-
+
/**
* Add filter to context.
* @param filterName Name of filter to add
@@ -915,11 +939,11 @@
@Override
public FilterRegistration.Dynamic addFilter(String filterName,
Filter filter) throws IllegalStateException {
-
+
return addFilter(filterName, null, filter);
}
-
+
/**
* Add filter to context.
* @param filterName Name of filter to add
@@ -937,13 +961,13 @@
@Override
public FilterRegistration.Dynamic addFilter(String filterName,
Class<? extends Filter> filterClass) throws IllegalStateException {
-
+
return addFilter(filterName, filterClass.getName(), null);
}
private FilterRegistration.Dynamic addFilter(String filterName,
String filterClass, Filter filter) throws IllegalStateException {
-
+
if (filterName == null || filterName.equals("")) {
throw new IllegalArgumentException(sm.getString(
"applicationContext.invalidFilterName", filterName));
@@ -957,7 +981,7 @@
}
FilterDef filterDef = context.findFilterDef(filterName);
-
+
// Assume a 'complete' FilterRegistration is one that has a class and
// a name
if (filterDef == null) {
@@ -977,14 +1001,15 @@
filterDef.setFilterClass(filter.getClass().getName());
filterDef.setFilter(filter);
}
-
+
return new ApplicationFilterRegistration(filterDef, context);
- }
-
+ }
+
@Override
public <T extends Filter> T createFilter(Class<T> c)
throws ServletException {
try {
+ @SuppressWarnings("unchecked")
T filter = (T) context.getInstanceManager().newInstance(c.getName());
return filter;
} catch (IllegalAccessException e) {
@@ -1011,7 +1036,7 @@
return new ApplicationFilterRegistration(filterDef, context);
}
-
+
/**
* Add servlet to context.
* @param servletName Name of servlet to add
@@ -1029,7 +1054,7 @@
@Override
public ServletRegistration.Dynamic addServlet(String servletName,
String servletClass) throws IllegalStateException {
-
+
return addServlet(servletName, servletClass, null);
}
@@ -1055,7 +1080,7 @@
return addServlet(servletName, null, servlet);
}
-
+
/**
* Add servlet to context.
* @param servletName Name of servlet to add
@@ -1080,7 +1105,7 @@
private ServletRegistration.Dynamic addServlet(String servletName,
String servletClass, Servlet servlet) throws IllegalStateException {
-
+
if (servletName == null || servletName.equals("")) {
throw new IllegalArgumentException(sm.getString(
"applicationContext.invalidServletName", servletName));
@@ -1092,9 +1117,9 @@
sm.getString("applicationContext.addServlet.ise",
getContextPath()));
}
-
+
Wrapper wrapper = (Wrapper) context.findChild(servletName);
-
+
// Assume a 'complete' ServletRegistration is one that has a class and
// a name
if (wrapper == null) {
@@ -1127,6 +1152,7 @@
public <T extends Servlet> T createServlet(Class<T> c)
throws ServletException {
try {
+ @SuppressWarnings("unchecked")
T servlet = (T) context.getInstanceManager().newInstance(c.getName());
context.dynamicServletCreated(servlet);
return servlet;
@@ -1151,10 +1177,10 @@
if (wrapper == null) {
return null;
}
-
+
return new ApplicationServletRegistration(wrapper, context);
}
-
+
/**
* By default {@link SessionTrackingMode#URL} is always supported, {@link
@@ -1171,15 +1197,15 @@
private void populateSessionTrackingModes() {
// URL re-writing is always enabled by default
- defaultSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
+ defaultSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
supportedSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
-
+
if (context.getCookies()) {
defaultSessionTrackingModes.add(SessionTrackingMode.COOKIE);
supportedSessionTrackingModes.add(SessionTrackingMode.COOKIE);
}
- // SSL not enabled by default as it can only used on its own
+ // SSL not enabled by default as it can only used on its own
// Context > Host > Engine > Service
Service s = ((Engine) context.getParent().getParent()).getService();
Connector[] connectors = s.findConnectors();
@@ -1189,7 +1215,7 @@
supportedSessionTrackingModes.add(SessionTrackingMode.SSL);
break;
}
- }
+ }
}
/**
@@ -1226,7 +1252,7 @@
sm.getString("applicationContext.setSessionTracking.ise",
getContextPath()));
}
-
+
// Check that only supported tracking modes have been requested
for (SessionTrackingMode sessionTrackingMode : sessionTrackingModes) {
if (!supportedSessionTrackingModes.contains(sessionTrackingMode)) {
@@ -1244,7 +1270,7 @@
getContextPath()));
}
}
-
+
this.sessionTrackingModes = sessionTrackingModes;
}
@@ -1253,8 +1279,8 @@
public boolean setInitParameter(String name, String value) {
return parameters.putIfAbsent(name, value) == null;
}
-
-
+
+
@Override
public void addListener(Class<? extends EventListener> listenerClass) {
EventListener listener;
@@ -1271,7 +1297,7 @@
@Override
public void addListener(String className) {
-
+
try {
Object obj = context.getInstanceManager().newInstance(className);
@@ -1305,7 +1331,7 @@
"applicationContext.addListener.iae.cnfe", className),
e);
}
-
+
}
@@ -1325,7 +1351,7 @@
context.addApplicationEventListener(t);
match = true;
}
-
+
if (t instanceof HttpSessionListener
|| (t instanceof ServletContextListener &&
newServletContextListenerAllowed)) {
@@ -1334,9 +1360,9 @@
context.addApplicationLifecycleListener(t);
match = true;
}
-
+
if (match) return;
-
+
if (t instanceof ServletContextListener) {
throw new IllegalArgumentException(sm.getString(
"applicationContext.addListener.iae.sclNotAllowed",
@@ -1353,8 +1379,9 @@
public <T extends EventListener> T createListener(Class<T> c)
throws ServletException {
try {
+ @SuppressWarnings("unchecked")
T listener =
- (T) context.getInstanceManager().newInstance(c.getName());
+ (T) context.getInstanceManager().newInstance(c);
if (listener instanceof ServletContextListener ||
listener instanceof ServletContextAttributeListener ||
listener instanceof ServletRequestListener ||
@@ -1375,27 +1402,26 @@
throw new ServletException(e);
} catch (InstantiationException e) {
throw new ServletException(e);
- } catch (ClassNotFoundException e) {
- throw new ServletException(e);
- } }
+ }
+ }
@Override
public void declareRoles(String... roleNames) {
-
+
if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
//TODO Spec breaking enhancement to ignore this restriction
throw new IllegalStateException(
sm.getString("applicationContext.addRole.ise",
getContextPath()));
}
-
+
if (roleNames == null) {
throw new IllegalArgumentException(
sm.getString("applicationContext.roles.iae",
getContextPath()));
}
-
+
for (String role : roleNames) {
if (role == null || "".equals(role)) {
throw new IllegalArgumentException(
@@ -1424,7 +1450,7 @@
new RuntimePermission("getClassLoader"));
}
}
-
+
return result;
}
@@ -1445,7 +1471,7 @@
public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
Map<String, ApplicationFilterRegistration> result =
new HashMap<String, ApplicationFilterRegistration>();
-
+
FilterDef[] filterDefs = context.findFilterDefs();
for (FilterDef filterDef : filterDefs) {
result.put(filterDef.getFilterName(),
@@ -1473,7 +1499,7 @@
public Map<String, ? extends ServletRegistration> getServletRegistrations() {
Map<String, ApplicationServletRegistration> result =
new HashMap<String, ApplicationServletRegistration>();
-
+
Container[] wrappers = context.findChildren();
for (Container wrapper : wrappers) {
result.put(((Wrapper) wrapper).getName(),
@@ -1484,12 +1510,12 @@
return result;
}
-
+
// -------------------------------------------------------- Package Methods
protected StandardContext getContext() {
return this.context;
}
-
+
@Deprecated
protected Map<String,String> getReadonlyAttributes() {
return this.readOnlyAttributes;
@@ -1513,10 +1539,10 @@
String key = keys.next();
removeAttribute(key);
}
-
+
}
-
-
+
+
/**
* Return the facade associated with this ApplicationContext.
*/
@@ -1541,7 +1567,7 @@
protected void setNewServletContextListenerAllowed(boolean allowed) {
this.newServletContextListenerAllowed = allowed;
}
-
+
/**
* List resource paths (recursively), and store all of them in the given
* Set.
@@ -1572,13 +1598,13 @@
*/
private static String getJNDIUri(String hostName, String path) {
String result;
-
+
if (path.startsWith("/")) {
result = "/" + hostName + path;
} else {
result = "/" + hostName + "/" + path;
}
-
+
return result;
}
--- java/org/apache/catalina/core/StandardContext.java.orig 2014-07-21 17:24:05.568403000 -0400
+++ java/org/apache/catalina/core/StandardContext.java 2014-07-22 16:08:44.199113000 -0400
@@ -126,6 +126,7 @@
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.descriptor.XmlIdentifiers;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.scan.StandardJarScanner;
@@ -136,7 +137,7 @@
*
* @author Craig R. McClanahan
* @author Remy Maucherat
- * @version $Id: StandardContext.java 1493073 2013-06-14 13:51:13Z markt $
+ * @version $Id: StandardContext.java 1549529 2013-12-09 10:05:56Z markt $
*/
public class StandardContext extends ContainerBase
@@ -524,6 +525,12 @@
/**
+ * Context level override for default {@link StandardHost#isCopyXML()}.
+ */
+ private boolean copyXML = false;
+
+
+ /**
* The default context override flag for this web application.
*/
private boolean override = false;
@@ -691,6 +698,13 @@
protected int cacheMaxSize = 10240; // 10 MB
+
+ /**
+ * Attribute used to turn on/off the use of external entities.
+ */
+ private boolean xmlBlockExternal = Globals.IS_SECURITY_ENABLED;
+
+
/**
* Cache object max size in KB.
*/
@@ -726,7 +740,8 @@
/**
- * Attribute value used to turn on/off XML validation
+ * Attribute value used to turn on/off XML validation for web.xml and
+ * web-fragment.xml files.
*/
private boolean webXmlValidation = Globals.STRICT_SERVLET_COMPLIANCE;
@@ -748,12 +763,6 @@
/**
- * Attribute value used to turn on/off TLD XML namespace validation
- */
- private boolean tldNamespaceAware = Globals.STRICT_SERVLET_COMPLIANCE;
-
-
- /**
* Should we save the configuration.
*/
private boolean saveConfig = true;
@@ -1055,11 +1064,13 @@
}
+ @Override
public InstanceManager getInstanceManager() {
return instanceManager;
}
+ @Override
public void setInstanceManager(InstanceManager instanceManager) {
this.instanceManager = instanceManager;
}
@@ -2463,6 +2474,17 @@
}
+
+ public boolean getCopyXML() {
+ return copyXML;
+ }
+
+
+ public void setCopyXML(boolean copyXML) {
+ this.copyXML = copyXML;
+ }
+
+
/**
* Return the Java class name of the Wrapper implementation used
* for servlets registered in this Context.
@@ -4861,7 +4883,7 @@
ExceptionUtils.handleThrowable(t);
getLogger().error
(sm.getString("standardContext.applicationListener",
- listeners[i]), t);
+ listeners[i].getClassName()), t);
ok = false;
}
}
@@ -5233,8 +5255,7 @@
}
if (ok) {
if (!resourcesStart()) {
- log.error( "Error in resourceStart()");
- ok = false;
+ throw new LifecycleException("Error in resourceStart()");
}
}
@@ -5822,17 +5843,10 @@
*/
@Override
public boolean isServlet22() {
-
- if (this.publicId == null)
- return (false);
- if (this.publicId.equals
- (org.apache.catalina.startup.Constants.WebDtdPublicId_22))
- return (true);
- else
- return (false);
-
+ return XmlIdentifiers.WEB_22_PUBLIC.equals(publicId);
}
+
@Override
public Set<String> addServletSecurity(
ApplicationServletRegistration registration,
@@ -5928,7 +5942,7 @@
if (getResources() == null)
return oldContextClassLoader;
- if (getLoader().getClassLoader() != null) {
+ if (getLoader() != null && getLoader().getClassLoader() != null) {
Thread.currentThread().setContextClassLoader
(getLoader().getClassLoader());
}
@@ -6580,72 +6594,67 @@
}
- /**
- * Set the validation feature of the XML parser used when
- * parsing xml instances.
- * @param webXmlValidation true to enable xml instance validation
- */
+
+ @Override
+ public boolean getXmlNamespaceAware(){
+ return webXmlNamespaceAware;
+ }
+
+
+ @Override
+ public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
+ this.webXmlNamespaceAware = webXmlNamespaceAware;
+ }
+
+
@Override
public void setXmlValidation(boolean webXmlValidation){
-
this.webXmlValidation = webXmlValidation;
-
}
- /**
- * Get the server.xml <context> attribute's xmlValidation.
- * @return true if validation is enabled.
- *
- */
+
@Override
public boolean getXmlValidation(){
return webXmlValidation;
}
- /**
- * Get the server.xml <context> attribute's xmlNamespaceAware.
- * @return true if namespace awarenes is enabled.
- */
@Override
- public boolean getXmlNamespaceAware(){
- return webXmlNamespaceAware;
+ public boolean getTldNamespaceAware(){
+ return true;
}
- /**
- * Set the namespace aware feature of the XML parser used when
- * parsing xml instances.
- * @param webXmlNamespaceAware true to enable namespace awareness
- */
@Override
- public void setXmlNamespaceAware(boolean webXmlNamespaceAware){
- this.webXmlNamespaceAware= webXmlNamespaceAware;
+ public void setTldNamespaceAware(boolean tldNamespaceAware){
+ // NO-OP;
}
- /**
- * Set the validation feature of the XML parser used when
- * parsing tlds files.
- * @param tldValidation true to enable xml instance validation
- */
+ @Override
+ public void setXmlBlockExternal(boolean xmlBlockExternal) {
+ this.xmlBlockExternal = xmlBlockExternal;
+ }
+
+
+ @Override
+ public boolean getXmlBlockExternal() {
+ return xmlBlockExternal;
+ }
+
+
@Override
public void setTldValidation(boolean tldValidation){
-
this.tldValidation = tldValidation;
-
}
- /**
- * Get the server.xml <context> attribute's webXmlValidation.
- * @return true if validation is enabled.
- *
- */
+
@Override
public boolean getTldValidation(){
return tldValidation;
}
+
/**
* Sets the process TLDs attribute.
*
@@ -6655,6 +6664,7 @@
processTlds = newProcessTlds;
}
+
/**
* Returns the processTlds attribute value.
*/
@@ -6662,26 +6672,6 @@
return processTlds;
}
- /**
- * Get the server.xml <host> attribute's xmlNamespaceAware.
- * @return true if namespace awarenes is enabled.
- */
- @Override
- public boolean getTldNamespaceAware(){
- return tldNamespaceAware;
- }
-
-
- /**
- * Set the namespace aware feature of the XML parser used when
- * parsing xml instances.
- * @param tldNamespaceAware true to enable namespace awareness
- */
- @Override
- public void setTldNamespaceAware(boolean tldNamespaceAware){
- this.tldNamespaceAware= tldNamespaceAware;
- }
-
/**
* Support for "stateManageable" JSR77
--- java/org/apache/catalina/startup/ContextConfig.java.orig 2014-07-21 17:24:05.574403000 -0400
+++ java/org/apache/catalina/startup/ContextConfig.java 2014-07-21 17:46:59.422037000 -0400
@@ -95,6 +95,8 @@
import org.apache.tomcat.util.bcel.classfile.ElementValue;
import org.apache.tomcat.util.bcel.classfile.ElementValuePair;
import org.apache.tomcat.util.bcel.classfile.JavaClass;
+import org.apache.tomcat.util.descriptor.DigesterFactory;
+import org.apache.tomcat.util.descriptor.XmlErrorHandler;
import org.apache.tomcat.util.digester.Digester;
import org.apache.tomcat.util.digester.RuleSet;
import org.apache.tomcat.util.res.StringManager;
@@ -109,7 +111,7 @@
*
* @author Craig R. McClanahan
* @author Jean-Francois Arcand
- * @version $Id: ContextConfig.java 1488152 2013-05-31 11:07:18Z kkolinko $
+ * @version $Id: ContextConfig.java 1549529 2013-12-09 10:05:56Z markt $
*/
public class ContextConfig implements LifecycleListener {
@@ -514,14 +516,16 @@
public void createWebXmlDigester(boolean namespaceAware,
boolean validation) {
+ boolean blockExternal = context.getXmlBlockExternal();
+
webRuleSet = new WebRuleSet(false);
webDigester = DigesterFactory.newDigester(validation,
- namespaceAware, webRuleSet);
+ namespaceAware, webRuleSet, blockExternal);
webDigester.getParser();
webFragmentRuleSet = new WebRuleSet(true);
webFragmentDigester = DigesterFactory.newDigester(validation,
- namespaceAware, webFragmentRuleSet);
+ namespaceAware, webFragmentRuleSet, blockExternal);
webFragmentDigester.getParser();
}
@@ -710,11 +714,11 @@
String pathName = cn.getBaseName();
boolean unpackWARs = true;
- if (host instanceof StandardHost &&
- context instanceof StandardContext) {
- unpackWARs = ((StandardHost) host).isUnpackWARs() &&
- ((StandardContext) context).getUnpackWAR() &&
- (docBase.startsWith(canonicalAppBase.getPath()));
+ if (host instanceof StandardHost) {
+ unpackWARs = ((StandardHost) host).isUnpackWARs();
+ if (unpackWARs && context instanceof StandardContext) {
+ unpackWARs = ((StandardContext) context).getUnpackWAR();
+ }
}
if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") && !file.isDirectory() && unpackWARs) {
@@ -838,14 +842,6 @@
createWebXmlDigester(context.getXmlNamespaceAware(),
context.getXmlValidation());
-
- try {
- fixDocBase();
- } catch (IOException e) {
- log.error(sm.getString(
- "contextConfig.fixDocBase", context.getName()), e);
- }
-
}
@@ -854,8 +850,14 @@
*/
protected synchronized void beforeStart() {
- antiLocking();
+ try {
+ fixDocBase();
+ } catch (IOException e) {
+ log.error(sm.getString(
+ "contextConfig.fixDocBase", context.getName()), e);
+ }
+ antiLocking();
}
@@ -1131,7 +1133,7 @@
for (int j = 0; j < roles.length; j++) {
if (!"*".equals(roles[j]) &&
!context.findSecurityRole(roles[j])) {
- log.info(sm.getString("contextConfig.role.auth", roles[j]));
+ log.warn(sm.getString("contextConfig.role.auth", roles[j]));
context.addSecurityRole(roles[j]);
}
}
@@ -1143,14 +1145,14 @@
Wrapper wrapper = (Wrapper) wrappers[i];
String runAs = wrapper.getRunAs();
if ((runAs != null) && !context.findSecurityRole(runAs)) {
- log.info(sm.getString("contextConfig.role.runas", runAs));
+ log.warn(sm.getString("contextConfig.role.runas", runAs));
context.addSecurityRole(runAs);
}
String names[] = wrapper.findSecurityReferences();
for (int j = 0; j < names.length; j++) {
String link = wrapper.findSecurityReference(names[j]);
if ((link != null) && !context.findSecurityRole(link)) {
- log.info(sm.getString("contextConfig.role.link", link));
+ log.warn(sm.getString("contextConfig.role.link", link));
context.addSecurityRole(link);
}
}
@@ -1258,7 +1260,7 @@
// Step 1. Identify all the JARs packaged with the application
// If the JARs have a web-fragment.xml it will be parsed at this
// point.
- Map<String,WebXml> fragments = processJarsForWebFragments();
+ Map<String,WebXml> fragments = processJarsForWebFragments(webXml);
// Step 2. Order the fragments.
Set<WebXml> orderedFragments = null;
@@ -1546,7 +1548,7 @@
URL url = fragment.getURL();
Jar jar = null;
InputStream is = null;
- ServletContainerInitializer sci = null;
+ List<ServletContainerInitializer> detectedScis = null;
try {
if ("jar".equals(url.getProtocol())) {
jar = JarFactory.newInstance(url);
@@ -1559,7 +1561,7 @@
}
}
if (is != null) {
- sci = getServletContainerInitializer(is);
+ detectedScis = getServletContainerInitializers(is);
}
} catch (IOException ioe) {
log.error(sm.getString(
@@ -1580,42 +1582,44 @@
}
}
- if (sci == null) {
+ if (detectedScis == null) {
continue;
}
- initializerClassMap.put(sci, new HashSet<Class<?>>());
+ for (ServletContainerInitializer sci : detectedScis) {
+ initializerClassMap.put(sci, new HashSet<Class<?>>());
- HandlesTypes ht = null;
- try {
- ht = sci.getClass().getAnnotation(HandlesTypes.class);
- } catch (Exception e) {
- if (log.isDebugEnabled()) {
- log.info(sm.getString("contextConfig.sci.debug", url), e);
- } else {
- log.info(sm.getString("contextConfig.sci.info", url));
+ HandlesTypes ht = null;
+ try {
+ ht = sci.getClass().getAnnotation(HandlesTypes.class);
+ } catch (Exception e) {
+ if (log.isDebugEnabled()) {
+ log.info(sm.getString("contextConfig.sci.debug", url),
+ e);
+ } else {
+ log.info(sm.getString("contextConfig.sci.info", url));
+ }
}
- }
- if (ht != null) {
- Class<?>[] types = ht.value();
- if (types != null) {
- for (Class<?> type : types) {
- if (type.isAnnotation()) {
- handlesTypesAnnotations = true;
- } else {
- handlesTypesNonAnnotations = true;
- }
- Set<ServletContainerInitializer> scis =
- typeInitializerMap.get(type);
- if (scis == null) {
- scis = new HashSet<ServletContainerInitializer>();
- typeInitializerMap.put(type, scis);
+ if (ht != null) {
+ Class<?>[] types = ht.value();
+ if (types != null) {
+ for (Class<?> type : types) {
+ if (type.isAnnotation()) {
+ handlesTypesAnnotations = true;
+ } else {
+ handlesTypesNonAnnotations = true;
+ }
+ Set<ServletContainerInitializer> scis = typeInitializerMap
+ .get(type);
+ if (scis == null) {
+ scis = new HashSet<ServletContainerInitializer>();
+ typeInitializerMap.put(type, scis);
+ }
+ scis.add(sci);
}
- scis.add(sci);
}
}
}
-
}
}
@@ -1627,19 +1631,28 @@
* @return The class name
* @throws IOException
*/
- protected ServletContainerInitializer getServletContainerInitializer(
+ protected List<ServletContainerInitializer> getServletContainerInitializers(
InputStream is) throws IOException {
- String className = null;
+ List<ServletContainerInitializer> initializers = new ArrayList<ServletContainerInitializer>();
if (is != null) {
String line = null;
try {
- BufferedReader br =
- new BufferedReader(new InputStreamReader(is, "UTF-8"));
- line = br.readLine();
- if (line != null && line.trim().length() > 0) {
- className = line.trim();
+ BufferedReader br = new BufferedReader(new InputStreamReader(
+ is, "UTF-8"));
+ while ((line = br.readLine()) != null) {
+ line = line.trim();
+ if (line.length() > 0) {
+ int i = line.indexOf('#');
+ if (i > -1) {
+ if (i == 0) {
+ continue;
+ }
+ line = line.substring(0, i).trim();
+ }
+ initializers.add(getServletContainerInitializer(line));
+ }
}
} catch (UnsupportedEncodingException e) {
// Should never happen with UTF-8
@@ -1647,11 +1660,16 @@
}
}
+ return initializers;
+ }
+
+ protected ServletContainerInitializer getServletContainerInitializer(
+ String className) throws IOException {
ServletContainerInitializer sci = null;
try {
- Class<?> clazz = Class.forName(className,true,
- context.getLoader().getClassLoader());
- sci = (ServletContainerInitializer) clazz.newInstance();
+ Class<?> clazz = Class.forName(className, true, context.getLoader()
+ .getClassLoader());
+ sci = (ServletContainerInitializer) clazz.newInstance();
} catch (ClassNotFoundException e) {
log.error(sm.getString("contextConfig.invalidSci", className), e);
throw new IOException(e);
@@ -1923,10 +1941,21 @@
*
* @return A map of JAR name to processed web fragment (if any)
*/
- protected Map<String,WebXml> processJarsForWebFragments() {
+ protected Map<String,WebXml> processJarsForWebFragments(WebXml application) {
JarScanner jarScanner = context.getJarScanner();
- FragmentJarScannerCallback callback = new FragmentJarScannerCallback();
+
+ boolean parseRequired = true;
+ Set<String> absoluteOrder = application.getAbsoluteOrdering();
+ if (absoluteOrder != null && absoluteOrder.isEmpty() &&
+ !context.getXmlValidation()) {
+ // Skip parsing when there is an empty absolute ordering and
+ // validation is not enabled
+ parseRequired = false;
+ }
+
+ FragmentJarScannerCallback callback =
+ new FragmentJarScannerCallback(parseRequired);
jarScanner.scan(context.getServletContext(),
context.getLoader().getClassLoader(), callback,
@@ -2282,6 +2311,12 @@
} catch (IOException e) {
log.debug(sm.getString("contextConfig.invalidSciHandlesTypes",
className), e);
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // ignore
+ }
}
}
}
@@ -2650,7 +2685,12 @@
private static final String FRAGMENT_LOCATION =
"META-INF/web-fragment.xml";
private Map<String,WebXml> fragments = new HashMap<String,WebXml>();
+ private final boolean parseRequired;
+ public FragmentJarScannerCallback(boolean parseRequired) {
+ this.parseRequired = parseRequired;
+ }
+
@Override
public void scan(JarURLConnection jarConn) throws IOException {
@@ -2662,15 +2702,18 @@
try {
jar = JarFactory.newInstance(url);
- is = jar.getInputStream(FRAGMENT_LOCATION);
+ if (parseRequired || context.getXmlValidation()) {
+ is = jar.getInputStream(FRAGMENT_LOCATION);
+ }
if (is == null) {
- // If there is no web.xml, normal JAR no impact on
- // distributable
+ // If there is no web-fragment.xml to process there is no
+ // impact on distributable
fragment.setDistributable(true);
} else {
InputSource source = new InputSource(
- resourceURL.toString() + "!/" + FRAGMENT_LOCATION);
+ "jar:" + resourceURL.toString() + "!/" +
+ FRAGMENT_LOCATION);
source.setByteStream(is);
parseWebXml(source, fragment, true);
}
--- java/org/apache/catalina/startup/FailedContext.java.orig 2014-07-21 17:24:05.579400000 -0400
+++ java/org/apache/catalina/startup/FailedContext.java 2014-07-21 17:46:59.429034000 -0400
@@ -59,6 +59,7 @@
import org.apache.catalina.util.CharsetMapper;
import org.apache.catalina.util.LifecycleMBeanBase;
import org.apache.juli.logging.Log;
+import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.util.http.mapper.Mapper;
import org.apache.tomcat.util.res.StringManager;
@@ -427,10 +428,15 @@
@Override
public void setTldValidation(boolean tldValidation) { /* NO-OP */ }
@Override
+ public boolean getXmlBlockExternal() { return true; }
+ @Override
+ public void setXmlBlockExternal(boolean xmlBlockExternal) { /* NO-OP */ }
+
+ @Override
public boolean getTldValidation() { return false; }
@Override
- public boolean getTldNamespaceAware() { return false; }
+ public boolean getTldNamespaceAware() { return true; }
@Override
public void setTldNamespaceAware(boolean tldNamespaceAware) { /* NO-OP */ }
@@ -685,4 +691,10 @@
@Override
public Map<String, String> findPreDestroyMethods() { return null; }
+
+ @Override
+ public InstanceManager getInstanceManager() { return null; }
+
+ @Override
+ public void setInstanceManager(InstanceManager instanceManager) { /* NO-OP */ }
}
\ No newline at end of file
--- java/org/apache/catalina/startup/TldConfig.java.orig 2014-07-21 17:24:05.583404000 -0400
+++ java/org/apache/catalina/startup/TldConfig.java 2014-07-24 12:20:22.130289000 -0400
@@ -40,6 +40,8 @@
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.JarScannerCallback;
import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.descriptor.DigesterFactory;
+import org.apache.tomcat.util.descriptor.XmlErrorHandler;
import org.apache.tomcat.util.digester.Digester;
import org.apache.tomcat.util.res.StringManager;
import org.apache.tomcat.util.scan.Jar;
@@ -83,38 +85,23 @@
* Create (if necessary) and return a Digester configured to process the
* tld.
*/
- private static Digester createTldDigester(boolean namespaceAware,
- boolean validation) {
-
- Digester digester = null;
- if (!namespaceAware && !validation) {
- if (tldDigesters[0] == null) {
- tldDigesters[0] = DigesterFactory.newDigester(validation,
- namespaceAware, new TldRuleSet());
- tldDigesters[0].getParser();
- }
- digester = tldDigesters[0];
- } else if (!namespaceAware && validation) {
- if (tldDigesters[1] == null) {
- tldDigesters[1] = DigesterFactory.newDigester(validation,
- namespaceAware, new TldRuleSet());
- tldDigesters[1].getParser();
- }
- digester = tldDigesters[1];
- } else if (namespaceAware && !validation) {
- if (tldDigesters[2] == null) {
- tldDigesters[2] = DigesterFactory.newDigester(validation,
- namespaceAware, new TldRuleSet());
- tldDigesters[2].getParser();
- }
- digester = tldDigesters[2];
- } else {
- if (tldDigesters[3] == null) {
- tldDigesters[3] = DigesterFactory.newDigester(validation,
- namespaceAware, new TldRuleSet());
- tldDigesters[3].getParser();
- }
- digester = tldDigesters[3];
+ private static synchronized Digester createTldDigester(boolean validation,
+ boolean blockExternal) {
+
+ Digester digester;
+ int cacheIndex = 0;
+ if (validation) {
+ cacheIndex += 1;
+ }
+ if (blockExternal) {
+ cacheIndex += 2;
+ }
+ digester = tldDigesters[cacheIndex];
+ if (digester == null) {
+ digester = DigesterFactory.newDigester(validation,
+ true, new TldRuleSet(), blockExternal);
+ digester.getParser();
+ tldDigesters[cacheIndex] = digester;
}
return digester;
}
@@ -155,7 +142,10 @@
}
StringTokenizer tokenizer = new StringTokenizer(jarNames, ",");
while (tokenizer.hasMoreElements()) {
- noTldJars.add(tokenizer.nextToken());
+ String token = tokenizer.nextToken().trim();
+ if (token.length() > 0) {
+ noTldJars.add(token);
+ }
}
}
}
@@ -354,10 +344,15 @@
try {
stream = context.getServletContext().getResourceAsStream(
resourcePath);
- XmlErrorHandler handler = tldScanStream(stream);
- handler.logFindings(log, resourcePath);
- taglibUris.add(descriptor.getTaglibURI());
- webxmlTaglibUris.add(descriptor.getTaglibURI());
+ if (stream != null) {
+ XmlErrorHandler handler = tldScanStream(stream);
+ handler.logFindings(log, resourcePath);
+ taglibUris.add(descriptor.getTaglibURI());
+ webxmlTaglibUris.add(descriptor.getTaglibURI());
+ } else {
+ log.warn(sm.getString("tldConfig.webxmlFailPathDoesNotExist", resourcePath,
+ descriptor.getTaglibURI()));
+ }
} catch (IOException ioe) {
log.warn(sm.getString("tldConfig.webxmlFail", resourcePath,
descriptor.getTaglibURI()), ioe);
@@ -580,8 +575,8 @@
private void init() {
if (tldDigester == null){
- tldDigester = createTldDigester(context.getTldNamespaceAware(),
- context.getTldValidation());
+ tldDigester = createTldDigester(context.getTldValidation(),
+ context.getXmlBlockExternal());
}
}
--- java/org/apache/jasper/Constants.java.orig 2014-07-21 17:24:05.588400000 -0400
+++ java/org/apache/jasper/Constants.java 2014-07-21 17:46:59.443034000 -0400
@@ -14,14 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.jasper;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-
/**
* Some constants and other global data that are used by the compiler and the runtime.
*
@@ -233,4 +231,23 @@
*/
public static final String TLD_JAR_SKIP_PROP=
"org.apache.catalina.startup.TldConfig.jarsToSkip";
+
+
+ /**
+ * Name of the ServletContext init-param that determines if the XML parsers
+ * used for *.tld files will be validating or not.
+ * <p>
+ * This must be kept in sync with org.apache.catalina.Globals
+ */
+ public static final String XML_VALIDATION_TLD_INIT_PARAM =
+ "org.apache.jasper.XML_VALIDATE_TLD";
+
+ /**
+ * Name of the ServletContext init-param that determines if the XML parsers
+ * will block the resolution of external entities.
+ * <p>
+ * This must be kept in sync with org.apache.catalina.Globals
+ */
+ public static final String XML_BLOCK_EXTERNAL_INIT_PARAM =
+ "org.apache.jasper.XML_BLOCK_EXTERNAL";
}
--- java/org/apache/jasper/JspC.java.orig 2014-07-21 17:24:05.593406000 -0400
+++ java/org/apache/jasper/JspC.java 2014-07-21 17:46:59.450034000 -0400
@@ -126,6 +126,8 @@
protected static final String SWITCH_ENCODING = "-javaEncoding";
protected static final String SWITCH_SMAP = "-smap";
protected static final String SWITCH_DUMP_SMAP = "-dumpsmap";
+ protected static final String SWITCH_VALIDATE_TLD = "-validateTld";
+ protected static final String SWITCH_BLOCK_EXTERNAL = "-blockExternal";
protected static final String SHOW_SUCCESS ="-s";
protected static final String LIST_ERRORS = "-l";
protected static final int INC_WEBXML = 10;
@@ -156,6 +158,8 @@
protected URLClassLoader loader = null;
protected boolean trimSpaces = false;
protected boolean genStringAsCharArray = false;
+ protected boolean validateTld;
+ protected boolean blockExternal;
protected boolean xpoweredBy;
protected boolean mappedFile = false;
protected boolean poolingEnabled = true;
@@ -363,6 +367,10 @@
smapSuppressed = false;
} else if (tok.equals(SWITCH_DUMP_SMAP)) {
smapDumped = true;
+ } else if (tok.equals(SWITCH_VALIDATE_TLD)) {
+ setValidateTld(true);
+ } else if (tok.equals(SWITCH_BLOCK_EXTERNAL)) {
+ setBlockExternal(true);
} else {
if (tok.startsWith("-")) {
throw new JasperException("Unrecognized option: " + tok +
@@ -842,8 +850,20 @@
}
}
- public void setValidateXml( boolean b ) {
- org.apache.jasper.xmlparser.ParserUtils.validating=b;
+ public void setValidateTld( boolean b ) {
+ this.validateTld = b;
+ }
+
+ public boolean isValidateTld() {
+ return validateTld;
+ }
+
+ public void setBlockExternal( boolean b ) {
+ this.blockExternal = b;
+ }
+
+ public boolean isBlockExternal() {
+ return blockExternal;
}
public void setListErrors( boolean b ) {
@@ -1257,8 +1277,6 @@
/**
* Executes the compilation.
- *
- * @throws JasperException If an error occurs
*/
@Override
public void execute() {
@@ -1426,6 +1444,13 @@
} catch (MalformedURLException me) {
System.out.println("**" + me);
}
+ if (isValidateTld()) {
+ context.setInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM, "true");
+ }
+ if (isBlockExternal()) {
+ context.setInitParameter(Constants.XML_BLOCK_EXTERNAL_INIT_PARAM, "true");
+ }
+
rctxt = new JspRuntimeContext(context, this);
jspConfig = new JspConfig(context);
tagPluginManager = new TagPluginManager(context);
--- java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java.orig 2014-07-21 17:24:05.597404000 -0400
+++ java/org/apache/jasper/compiler/ImplicitTagLibraryInfo.java 2014-07-21 17:46:59.457040000 -0400
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.jasper.compiler;
import java.io.InputStream;
@@ -24,11 +23,13 @@
import java.util.Set;
import java.util.Vector;
+import javax.servlet.ServletContext;
import javax.servlet.jsp.tagext.FunctionInfo;
import javax.servlet.jsp.tagext.TagFileInfo;
import javax.servlet.jsp.tagext.TagInfo;
import javax.servlet.jsp.tagext.TagLibraryInfo;
+import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
import org.apache.jasper.util.ExceptionUtils;
@@ -124,7 +125,21 @@
pi.addDependant(path, ctxt.getLastModified(path));
}
- ParserUtils pu = new ParserUtils();
+ ServletContext servletContext = ctxt.getServletContext();
+ boolean validate = Boolean.parseBoolean(
+ servletContext.getInitParameter(
+ Constants.XML_VALIDATION_TLD_INIT_PARAM));
+ String blockExternalString =
+ servletContext.getInitParameter(
+ Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
+ boolean blockExternal;
+ if (blockExternalString == null) {
+ blockExternal = Constants.IS_SECURITY_ENABLED;
+ } else {
+ blockExternal = Boolean.parseBoolean(blockExternalString);
+ }
+
+ ParserUtils pu = new ParserUtils(validate, blockExternal);
TreeNode tld = pu.parseXMLDocument(uri, in);
if (tld.findAttribute("version") != null) {
--- java/org/apache/jasper/compiler/JspConfig.java.orig 2014-07-21 17:24:05.605401000 -0400
+++ java/org/apache/jasper/compiler/JspConfig.java 2014-07-21 17:46:59.469055000 -0400
@@ -22,6 +22,7 @@
import javax.servlet.ServletContext;
+import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.xmlparser.ParserUtils;
import org.apache.jasper.xmlparser.TreeNode;
@@ -77,9 +78,20 @@
try {
webXml = new WebXml(ctxt);
+ boolean validate = Boolean.parseBoolean(
+ ctxt.getInitParameter(Constants.XML_VALIDATION_TLD_INIT_PARAM));
+ String blockExternalString =
+ ctxt.getInitParameter(Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
+ boolean blockExternal;
+ if (blockExternalString == null) {
+ blockExternal = Constants.IS_SECURITY_ENABLED;
+ } else {
+ blockExternal = Boolean.parseBoolean(blockExternalString);
+ }
+
TreeNode webApp = null;
if (webXml.getInputSource() != null) {
- ParserUtils pu = new ParserUtils();
+ ParserUtils pu = new ParserUtils(validate, blockExternal);
webApp = pu.parseXMLDocument(webXml.getSystemId(),
webXml.getInputSource());
}
--- java/org/apache/jasper/compiler/JspDocumentParser.java.orig 2014-07-21 17:24:05.610399000 -0400
+++ java/org/apache/jasper/compiler/JspDocumentParser.java 2014-07-21 17:46:59.476041000 -0400
@@ -5,9 +5,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -30,17 +30,20 @@
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
+import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
+import org.apache.tomcat.util.descriptor.DigesterFactory;
+import org.apache.tomcat.util.descriptor.LocalResolver;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.XMLReader;
-import org.xml.sax.ext.LexicalHandler;
+import org.xml.sax.ext.DefaultHandler2;
+import org.xml.sax.ext.EntityResolver2;
import org.xml.sax.helpers.AttributesImpl;
-import org.xml.sax.helpers.DefaultHandler;
/**
* Class implementing a parser for a JSP document, that is, a JSP page in XML
@@ -51,8 +54,8 @@
*/
class JspDocumentParser
- extends DefaultHandler
- implements LexicalHandler, TagConstants {
+ extends DefaultHandler2
+ implements TagConstants {
private static final String LEXICAL_HANDLER_PROPERTY =
"http://xml.org/sax/properties/lexical-handler";
@@ -71,7 +74,7 @@
* Outermost (in the nesting hierarchy) node whose body is declared to be
* scriptless. If a node's body is declared to be scriptless, all its
* nested nodes must be scriptless, too.
- */
+ */
private Node scriptlessBodyNode;
private Locator locator;
@@ -92,6 +95,7 @@
private boolean inDTD;
private boolean isValidating;
+ private final EntityResolver2 entityResolver;
private ErrorDispatcher err;
private boolean isTagFile;
@@ -120,6 +124,20 @@
this.isTagFile = isTagFile;
this.directivesOnly = directivesOnly;
this.isTop = true;
+
+ String blockExternalString = ctxt.getServletContext().getInitParameter(
+ Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
+ boolean blockExternal;
+ if (blockExternalString == null) {
+ blockExternal = Constants.IS_SECURITY_ENABLED;
+ } else {
+ blockExternal = Boolean.parseBoolean(blockExternalString);
+ }
+
+ this.entityResolver = new LocalResolver(
+ DigesterFactory.SERVLET_API_PUBLIC_IDS,
+ DigesterFactory.SERVLET_API_SYSTEM_IDS,
+ blockExternal);
}
/*
@@ -162,6 +180,8 @@
jspDocParser.isTop = false;
}
+ jspDocParser.isValidating = false;
+
// Parse the input
SAXParser saxParser = getSAXParser(false, jspDocParser);
InputStream inStream = null;
@@ -238,11 +258,34 @@
}
}
+
+ @Override
+ public InputSource getExternalSubset(String name, String baseURI)
+ throws SAXException, IOException {
+ return entityResolver.getExternalSubset(name, baseURI);
+ }
+
+
+
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId)
+ throws SAXException, IOException {
+ return entityResolver.resolveEntity(publicId, systemId);
+ }
+
+
+ @Override
+ public InputSource resolveEntity(String name, String publicId, String baseURI, String systemId)
+ throws SAXException, IOException {
+ return entityResolver.resolveEntity(name, publicId, baseURI, systemId);
+ }
+
+
/*
* Receives notification of the start of an element.
*
* This method assigns the given tag attributes to one of 3 buckets:
- *
+ *
* - "xmlns" attributes that represent (standard or custom) tag libraries.
* - "xmlns" attributes that do not represent tag libraries.
* - all remaining attributes.
@@ -272,11 +315,8 @@
return;
}
- String currentPrefix = getPrefix(current.getQName());
-
// jsp:text must not have any subelements
- if (JSP_URI.equals(uri) && TEXT_ACTION.equals(current.getLocalName())
- && "jsp".equals(currentPrefix)) {
+ if (current instanceof Node.JspText) {
throw new SAXParseException(
Localizer.getMessage("jsp.error.text.has_subelement"),
locator);
@@ -288,7 +328,7 @@
if (attrs != null) {
/*
* Notice that due to a bug in the underlying SAX parser, the
- * attributes must be enumerated in descending order.
+ * attributes must be enumerated in descending order.
*/
boolean isTaglib = false;
for (int i = attrs.getLength() - 1; i >= 0; i--) {
@@ -437,7 +477,7 @@
* invoke this method with chunks of it. This is a problem when we try
* to determine if the text contains only whitespaces, or when we are
* looking for an EL expression string. Therefore it is necessary to
- * buffer and concatenate the chunks and process the concatenated text
+ * buffer and concatenate the chunks and process the concatenated text
* later (at beginTag and endTag)
*
* @param buf The characters
@@ -670,7 +710,7 @@
if (!(child instanceof Node.NamedAttribute)) {
throw new SAXParseException(Localizer.getMessage(
"jasper.error.emptybodycontent.nonempty",
- current.qName), locator);
+ current.qName), locator);
}
}
}
@@ -785,7 +825,7 @@
}
/*
- * Receives notification of the start of a Namespace mapping.
+ * Receives notification of the start of a Namespace mapping.
*/
@Override
public void startPrefixMapping(String prefix, String uri)
@@ -795,7 +835,7 @@
if (directivesOnly && !(JSP_URI.equals(uri))) {
return;
}
-
+
try {
taglibInfo = getTaglibInfo(prefix, uri);
} catch (JasperException je) {
@@ -816,7 +856,7 @@
}
/*
- * Receives notification of the end of a Namespace mapping.
+ * Receives notification of the end of a Namespace mapping.
*/
@Override
public void endPrefixMapping(String prefix) throws SAXException {
@@ -1425,17 +1465,25 @@
throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
- factory.setNamespaceAware(true);
+ factory.setNamespaceAware(true);
// Preserve xmlns attributes
factory.setFeature(
"http://xml.org/sax/features/namespace-prefixes",
true);
+
factory.setValidating(validating);
- //factory.setFeature(
- // "http://xml.org/sax/features/validation",
- // validating);
-
+ if (validating) {
+ // Enable DTD validation
+ factory.setFeature(
+ "http://xml.org/sax/features/validation",
+ true);
+ // Enable schema validation
+ factory.setFeature(
+ "http://apache.org/xml/features/validation/schema",
+ true);
+ }
+
// Configure the parser
SAXParser saxParser = factory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
--- java/org/apache/jasper/compiler/TagLibraryInfoImpl.java.orig 2014-07-21 17:24:05.614400000 -0400
+++ java/org/apache/jasper/compiler/TagLibraryInfoImpl.java 2014-07-21 17:46:59.483050000 -0400
@@ -31,6 +31,7 @@
import java.util.Map;
import java.util.Vector;
+import javax.servlet.ServletContext;
import javax.servlet.jsp.tagext.FunctionInfo;
import javax.servlet.jsp.tagext.PageData;
import javax.servlet.jsp.tagext.TagAttributeInfo;
@@ -43,6 +44,7 @@
import javax.servlet.jsp.tagext.ValidationMessage;
import javax.servlet.jsp.tagext.VariableInfo;
+import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.JspCompilationContext;
import org.apache.jasper.util.ExceptionUtils;
@@ -212,8 +214,20 @@
Vector<TagFileInfo> tagFileVector = new Vector<TagFileInfo>();
Hashtable<String, FunctionInfo> functionTable = new Hashtable<String, FunctionInfo>();
+ ServletContext servletContext = ctxt.getServletContext();
+ boolean validate = Boolean.parseBoolean(servletContext.getInitParameter(
+ Constants.XML_VALIDATION_TLD_INIT_PARAM));
+ String blockExternalString = servletContext.getInitParameter(
+ Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
+ boolean blockExternal;
+ if (blockExternalString == null) {
+ blockExternal = Constants.IS_SECURITY_ENABLED;
+ } else {
+ blockExternal = Boolean.parseBoolean(blockExternalString);
+ }
+
// Create an iterator over the child elements of our <taglib> element
- ParserUtils pu = new ParserUtils();
+ ParserUtils pu = new ParserUtils(validate, blockExternal);
TreeNode tld = pu.parseXMLDocument(uri, in);
// Check to see if the <taglib> root element contains a 'version'
--- java/org/apache/jasper/compiler/TagPluginManager.java.orig 2014-07-21 17:24:05.619399000 -0400
+++ java/org/apache/jasper/compiler/TagPluginManager.java 2014-07-21 17:46:59.492036000 -0400
@@ -5,9 +5,9 @@
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -25,6 +25,7 @@
import javax.servlet.ServletContext;
+import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.tagplugin.TagPlugin;
import org.apache.jasper.compiler.tagplugin.TagPluginContext;
@@ -45,7 +46,6 @@
private boolean initialized = false;
private HashMap<String, TagPlugin> tagPlugins = null;
private ServletContext ctxt;
- private PageInfo pageInfo;
public TagPluginManager(ServletContext ctxt) {
this.ctxt = ctxt;
@@ -59,19 +59,9 @@
return;
}
- this.pageInfo = pageInfo;
-
- page.visit(new Node.Visitor() {
- @Override
- public void visit(Node.CustomTag n)
- throws JasperException {
- invokePlugin(n);
- visitBody(n);
- }
- });
-
+ page.visit(new NodeVisitor(this, pageInfo));
}
-
+
private void init(ErrorDispatcher err) throws JasperException {
if (initialized)
return;
@@ -130,8 +120,18 @@
private void loadTagPlugins(ErrorDispatcher err, InputStream is)
throws JasperException {
- TreeNode root =
- (new ParserUtils()).parseXMLDocument(TAG_PLUGINS_XML, is);
+ String blockExternalString = ctxt.getInitParameter(
+ Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
+ boolean blockExternal;
+ if (blockExternalString == null) {
+ blockExternal = Constants.IS_SECURITY_ENABLED;
+ } else {
+ blockExternal = Boolean.parseBoolean(blockExternalString);
+ }
+
+ ParserUtils pu = new ParserUtils(false, blockExternal);
+
+ TreeNode root = pu.parseXMLDocument(TAG_PLUGINS_XML, is);
if (root == null) {
return;
}
@@ -175,12 +175,12 @@
}
/**
- * Invoke tag plugin for the given custom tag, if a plugin exists for
+ * Invoke tag plugin for the given custom tag, if a plugin exists for
* the custom tag's tag handler.
*
* The given custom tag node will be manipulated by the plugin.
*/
- private void invokePlugin(Node.CustomTag n) {
+ private void invokePlugin(Node.CustomTag n, PageInfo pageInfo) {
TagPlugin tagPlugin = tagPlugins.get(n.getTagHandlerClass().getName());
if (tagPlugin == null) {
return;
@@ -191,8 +191,24 @@
tagPlugin.doTag(tagPluginContext);
}
- static class TagPluginContextImpl implements TagPluginContext {
- private Node.CustomTag node;
+ private static class NodeVisitor extends Node.Visitor {
+ private final TagPluginManager manager;
+ private final PageInfo pageInfo;
+
+ public NodeVisitor(TagPluginManager manager, PageInfo pageInfo) {
+ this.manager = manager;
+ this.pageInfo = pageInfo;
+ }
+
+ @Override
+ public void visit(Node.CustomTag n) throws JasperException {
+ manager.invokePlugin(n, pageInfo);
+ visitBody(n);
+ }
+ }
+
+ private static class TagPluginContextImpl implements TagPluginContext {
+ private final Node.CustomTag node;
private Node.Nodes curNodes;
private PageInfo pageInfo;
private HashMap<String, Object> pluginAttributes;
@@ -291,7 +307,7 @@
@Override
public void generateBody() {
- // Since we'll generate the body anyway, this is really a nop,
+ // Since we'll generate the body anyway, this is really a nop,
// except for the fact that it lets us put the Java sources the
// plugins produce in the correct order (w.r.t the body).
curNodes = node.getAtETag();
--- java/org/apache/jasper/compiler/TldLocationsCache.java.orig 2014-07-21 17:24:05.623404000 -0400
+++ java/org/apache/jasper/compiler/TldLocationsCache.java 2014-07-21 17:46:59.500034000 -0400
@@ -286,9 +286,23 @@
return;
}
+ boolean validate = Boolean.parseBoolean(
+ ctxt.getInitParameter(
+ Constants.XML_VALIDATION_TLD_INIT_PARAM));
+ String blockExternalString = ctxt.getInitParameter(
+ Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
+ boolean blockExternal;
+ if (blockExternalString == null) {
+ blockExternal = Constants.IS_SECURITY_ENABLED;
+ } else {
+ blockExternal = Boolean.parseBoolean(blockExternalString);
+ }
+
// Parse the web application deployment descriptor
+ ParserUtils pu = new ParserUtils(validate, blockExternal);
+
TreeNode webtld = null;
- webtld = new ParserUtils().parseXMLDocument(webXml.getSystemId(),
+ webtld = pu.parseXMLDocument(webXml.getSystemId(),
webXml.getInputSource());
// Allow taglib to be an element of the root or jsp-config (JSP2.0)
@@ -491,8 +505,20 @@
// Parse the tag library descriptor at the specified resource path
String uri = null;
- TreeNode tld =
- new ParserUtils().parseXMLDocument(resourcePath, stream);
+ boolean validate = Boolean.parseBoolean(
+ ctxt.getInitParameter(
+ Constants.XML_VALIDATION_TLD_INIT_PARAM));
+ String blockExternalString = ctxt.getInitParameter(
+ Constants.XML_BLOCK_EXTERNAL_INIT_PARAM);
+ boolean blockExternal;
+ if (blockExternalString == null) {
+ blockExternal = Constants.IS_SECURITY_ENABLED;
+ } else {
+ blockExternal = Boolean.parseBoolean(blockExternalString);
+ }
+
+ ParserUtils pu = new ParserUtils(validate, blockExternal);
+ TreeNode tld = pu.parseXMLDocument(resourcePath, stream);
TreeNode uriNode = tld.findChild("uri");
if (uriNode != null) {
String body = uriNode.getBody();
--- java/org/apache/jasper/xmlparser/ParserUtils.java.orig 2014-07-21 17:24:05.628407000 -0400
+++ java/org/apache/jasper/xmlparser/ParserUtils.java 2014-07-21 17:46:59.508034000 -0400
@@ -14,7 +14,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.apache.jasper.xmlparser;
import java.io.IOException;
@@ -27,8 +26,9 @@
import org.apache.jasper.Constants;
import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.Localizer;
-import org.apache.juli.logging.Log;
-import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.descriptor.DigesterFactory;
+import org.apache.tomcat.util.descriptor.LocalResolver;
+import org.apache.tomcat.util.descriptor.XmlErrorHandler;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
@@ -48,24 +48,38 @@
* use a separate class loader for the parser to be used.
*
* @author Craig R. McClanahan
- * @version $Id: ParserUtils.java 1301227 2012-03-15 21:59:06Z markt $
+ * @version $Id: ParserUtils.java 1549529 2013-12-09 10:05:56Z markt $
*/
-
public class ParserUtils {
/**
* An error handler for use when parsing XML documents.
*/
- static ErrorHandler errorHandler = new MyErrorHandler();
+ static ErrorHandler errorHandler = new XmlErrorHandler();
/**
* An entity resolver for use when parsing XML documents.
*/
- static EntityResolver entityResolver = new MyEntityResolver();
-
- // Turn off for JSP 2.0 until switch over to using xschema.
- public static boolean validating = false;
-
+ static EntityResolver entityResolver;
+
+ private final EntityResolver entityResolverInstance;
+
+ private final boolean validating;
+
+ public ParserUtils(boolean validating) {
+ this(validating, Constants.IS_SECURITY_ENABLED);
+ }
+
+ public ParserUtils(boolean validating, boolean blockExternal) {
+ this.validating = validating;
+ if (entityResolver == null) {
+ this.entityResolverInstance = new LocalResolver(
+ DigesterFactory.SERVLET_API_PUBLIC_IDS,
+ DigesterFactory.SERVLET_API_SYSTEM_IDS, blockExternal);
+ } else {
+ this.entityResolverInstance = entityResolver;
+ }
+ }
// --------------------------------------------------------- Public Methods
@@ -91,7 +105,7 @@
factory.setNamespaceAware(true);
factory.setValidating(validating);
DocumentBuilder builder = factory.newDocumentBuilder();
- builder.setEntityResolver(entityResolver);
+ builder.setEntityResolver(entityResolverInstance);
builder.setErrorHandler(errorHandler);
document = builder.parse(is);
} catch (ParserConfigurationException ex) {
@@ -196,56 +210,3 @@
return (treeNode);
}
}
-
-
-// ------------------------------------------------------------ Private Classes
-
-class MyEntityResolver implements EntityResolver {
-
- @Override
- public InputSource resolveEntity(String publicId, String systemId)
- throws SAXException {
- for (int i = 0; i < Constants.CACHED_DTD_PUBLIC_IDS.size(); i++) {
- String cachedDtdPublicId = Constants.CACHED_DTD_PUBLIC_IDS.get(i);
- if (cachedDtdPublicId.equals(publicId)) {
- String resourcePath =
- Constants.CACHED_DTD_RESOURCE_PATHS.get(i);
- InputStream input = this.getClass().getResourceAsStream(
- resourcePath);
- if (input == null) {
- throw new SAXException(Localizer.getMessage(
- "jsp.error.internal.filenotfound", resourcePath));
- }
- InputSource isrc = new InputSource(input);
- return isrc;
- }
- }
- Log log = LogFactory.getLog(MyEntityResolver.class);
- if (log.isDebugEnabled())
- log.debug("Resolve entity failed" + publicId + " " + systemId);
- log.error(Localizer.getMessage("jsp.error.parse.xml.invalidPublicId",
- publicId));
- return null;
- }
-}
-
-class MyErrorHandler implements ErrorHandler {
-
- @Override
- public void warning(SAXParseException ex) throws SAXException {
- Log log = LogFactory.getLog(MyErrorHandler.class);
- if (log.isDebugEnabled())
- log.debug("ParserUtils: warning ", ex);
- // We ignore warnings
- }
-
- @Override
- public void error(SAXParseException ex) throws SAXException {
- throw ex;
- }
-
- @Override
- public void fatalError(SAXParseException ex) throws SAXException {
- throw ex;
- }
-}
--- webapps/docs/changelog.xml.orig 2014-07-22 17:42:18.576034000 -0400
+++ webapps/docs/changelog.xml 2014-07-22 18:48:34.775453000 -0400
@@ -58,6 +58,12 @@
<section name="Tomcat 7.0.42 (markt)">
<subsection name="Catalina">
<changelog>
+ <add>
+ Add an option to the Context to control the blocking of XML external
+ entities when parsing XML configuration files and enable this blocking
+ by default when a security manager is used. The block is implemented via
+ a custom resolver to enable the logging of any blocked entities. (markt)
+ </add>
<fix>
CVE-2014-0099, Fix overflow when parsing long values from
byte array. (markt) Patch applied by Red Hat Jun 16 2014
--- webapps/docs/config/context.xml.orig 2014-07-21 17:24:05.643402000 -0400
+++ webapps/docs/config/context.xml 2014-07-21 17:46:59.530037000 -0400
@@ -448,6 +448,14 @@
useful for portlet specification implementations) set this attribute to
<code>/</code> in the global <code>CATALINA_BASE/conf/context.xml</code>
file.</p>
+ <p>Note: Once one web application using
+ <code>sessionCookiePath="/"</code> obtains a session, all
+ subsequent sessions for any other web application in the same host also
+ configured with <code>sessionCookiePath="/"</code> will always
+ use the same session ID. This holds even if the session is invalidated
+ and a new one created. This makes session fixation protection more
+ difficult and requires custom, Tomcat specific code to change the
+ session ID shared by the multiple applications.</p>
</attribute>
<attribute name="sessionCookiePathUsesTrailingSlash" required="false">
@@ -493,18 +501,6 @@
of the flag is <code>false</code>.</p>
</attribute>
- <attribute name="tldNamespaceAware" required="false">
- <p>If the value of this flag is <code>true</code>, the TLD files
- XML validation will be namespace-aware. If you turn this flag on,
- you should probably also turn <code>tldValidation</code> on. If the
- <code>org.apache.catalina.STRICT_SERVLET_COMPLIANCE</code>
- <a href="systemprops.html">system property</a> is set to
- <code>true</code>, the default value of this attribute will be
- <code>true</code>, else the default value will be <code>false</code>.
- Setting this attribute to <code>true</code> will incur a performance
- penalty.</p>
- </attribute>
-
<attribute name="tldValidation" required="false">
<p>If the value of this flag is <code>true</code>, the TLD files
will be XML validated on context startup. If the
@@ -528,11 +524,26 @@
Context. If not specified, a standard default value will be used.</p>
</attribute>
+ <attribute name="xmlBlockExternal" required="false">
+ <p>If the value of this flag is <code>true</code>, the parsing of
+ <code>web.xml</code>, <code>web-fragment.xml</code>, <code>*.tld</code>,
+ <code>*.jspx</code>, <code>*.tagx</code> and <code>tagPlugins.xml</code>
+ files for this web application will not permit external entities to be
+ loaded. If a <code>SecurityManager</code> is configured then the default
+ value of this attribute will be <code>true</code>, else the default
+ value will be <code>false</code>.</p>
+ </attribute>
+
<attribute name="xmlNamespaceAware" required="false">
- <p>If the value of this flag is <code>true</code>, the validation of
- XML files will be namespace-aware. If you turn this flag on,
- you should probably also turn <code>xmlValidation</code> on. If
- the <code>org.apache.catalina.STRICT_SERVLET_COMPLIANCE</code>
+ <p>If the value of this flag is <code>true</code>, the parsing of
+ <code>web.xml</code> and <code>web-fragment.xml</code> files for this
+ web application will be namespace-aware. Note that <code>*.tld</code>,
+ <code>*.jspx</code> and <code>*.tagx</code> files are always parsed
+ using a namespace-aware parser and that the <code>tagPlugins.xml</code>
+ file (if any) is never parsed using a namespace-aware parser. Note also
+ that if you turn this flag on, you should probably also turn
+ <code>xmlValidation</code> on. If the
+ <code>org.apache.catalina.STRICT_SERVLET_COMPLIANCE</code>
<a href="systemprops.html">system property</a> is set to
<code>true</code>, the default value of this attribute will be
<code>true</code>, else the default value will be <code>false</code>.
@@ -541,8 +552,9 @@
</attribute>
<attribute name="xmlValidation" required="false">
- <p>If the value of this flag is <code>true</code>, the XML files
- will be validated on context startup. If the
+ <p>If the value of this flag is <code>true</code>, the parsing of
+ <code>web.xml</code> and <code>web-fragment.xml</code> files for this
+ web application will use a validating parser. If the
<code>org.apache.catalina.STRICT_SERVLET_COMPLIANCE</code>
<a href="systemprops.html">system property</a> is set to
<code>true</code>, the default value of this attribute will be
@@ -706,7 +718,10 @@
is likely to result in instability. As such, enabling this should be
viewed as an option of last resort in a development environment and is
not recommended in a production environment. If not specified, the
- default value of <code>false</code> will be used.</p>
+ default value of <code>false</code> will be used. If this feature is
+ enabled, web applications may take up to two seconds longer to stop as
+ executor threads are given up to two seconds to stop gracefully before
+ <code>Thread.stop()</code> is called on any remaining threads.</p>
</attribute>
<attribute name="clearReferencesStopTimerThreads" required = "false">
@@ -717,6 +732,22 @@
not specified, the default value of <code>false</code> will be used.</p>
</attribute>
+ <attribute name="copyXML" required="false">
+ <p>Set to <code>true</code> if you want a context XML descriptor
+ embedded inside the application (located at
+ <code>/META-INF/context.xml</code>) to be copied to the owning
+ <a href="host.html">Host</a>'s <code>xmlBase</code> when the application
+ is deployed. On subsequent starts, the copied context XML descriptor
+ will be used in preference to any context XML descriptor embedded inside
+ the application even if the descriptor embedded inside the application
+ is more recent. The flag's value defaults to <code>false</code>. Note if
+ the <strong>deployXML</strong> attribute of the owning
+ <a href="host.html">Host</a> is <code>false</code> or if the
+ <strong>copyXML</strong> attribute of the owning
+ <a href="host.html">Host</a> is <code>true</code>, this attribute will
+ have no effect.</p>
+ </attribute>
+
<attribute name="jndiExceptionOnFailedWrite" required="false">
<p>If <code>true</code>, any attempt by an application to modify the
provided JNDI context with a call to bind(), unbind(),
--- webapps/docs/security-howto.xml.orig 2014-07-21 17:24:05.649404000 -0400
+++ webapps/docs/security-howto.xml 2014-07-21 17:46:59.538035000 -0400
@@ -72,10 +72,74 @@
</section>
<section name="Default web applications">
- <p>Tomcat ships with a number of web applications by default.
- Vulnerabilities have been discovered in these applications in the past.
- Applications that are not required should be removed so the system will not
- be at risk if another vulnerability is discovered.</p>
+
+ <subsection name="General">
+ <p>Tomcat ships with a number of web applications that are enabled by
+ default. Vulnerabilities have been discovered in these applications in the
+ past. Applications that are not required should be removed so the system
+ will not be at risk if another vulnerability is discovered.</p>
+ </subsection>
+
+ <subsection name="ROOT">
+ <p>The ROOT web application presents a very low security risk but it does
+ include the version of Tomcat that is being used. The ROOT web application
+ should normally be removed from a publicly accessible Tomcat instance, not
+ for security reasons, but so that a more appropriate default page is shown
+ to users.</p>
+ </subsection>
+
+ <subsection name="Documentation">
+ <p>The documentation web application presents a very low security risk but
+ it does identify the version of Tomcat that is being used. It should
+ normally be removed from a publicly accessible Tomcat instance.</p>
+ </subsection>
+
+ <subsection name="Examples">
+ <p>The examples web application should always be removed from any security
+ sensitive installation. While the examples web application does not
+ contain any known vulnerabilities, it is known to contain features
+ (particularly the cookie examples that display the contents of all
+ received and allow new cookies to be set) that may be used by an attacker
+ in conjunction with a vulnerability in another application deployed on the
+ Tomcat instance to obtain additional information that would otherwise be
+ unavailable.</p>
+ </subsection>
+
+ <subsection name="Manager">
+ <p>The Manager application allows the remote deployment of web
+ applications and is frequently targeted by attackers due to the widespread
+ use of weak passwords and publicly accessible Tomcat instances with the
+ Manager application enabled. The Manager application is not accessible by
+ default as no users are configured with the necessary access. If the
+ Manager application is enabled then guidance in the section
+ <strong>Securing Management Applications</strong> section should be
+ followed.</p>
+ </subsection>
+
+ <subsection name="Host Manager">
+ <p>The Host Manager application allows the creation and management of
+ virtual hosts - including the enabling of the Manager application for a
+ virtual host. The Host Manager application is not accessible by default
+ as no users are configured with the necessary access. If the Host Manager
+ application is enabled then guidance in the section <strong>Securing
+ Management Applications</strong> section should be followed.</p>
+ </subsection>
+
+ <subsection name="Securing Management Applications">
+ <p>When deploying a web application that provides management functions for
+ the Tomcat instance, the following guidelines should be followed:</p>
+ <ul>
+ <ol>Ensure that any users permitted to access the management application
+ have strong passwords.</ol>
+ <ol>Do not remove the use of the <a
+ href="config/realm.html#LockOut_Realm_-_org.apache.catalina.realm.LockOutRealm">LockOutRealm</a>
+ which prevents brute force attacks against user passwords.</ol>
+ <ol>Uncomment the <a href="config/valve.html#Remote_Address_Filter">RemoteAddrValve</a>
+ in <code>/META-INF/context.xml</code> which limits access to
+ localhost. If remote access is required, limit it to specific IP
+ addresses using this valve.</ol>
+ </ul>
+ </subsection>
</section>
<section name="Security manager">
@@ -109,6 +173,16 @@
manager should be introduced at the start of the development cycle as it can
be time-consuming to track down and fix issues caused by enabling a security
manager for a mature application.</p>
+
+ <p>Enabling the security manager changes the defaults for the following
+ settings:</p>
+ <ul>
+ <li>The default value for the <strong>deployXML</strong> attribute of the
+ <strong>Host</strong> element is changed to <code>false</code>.</li>
+ <li>The default value for the <strong>xmlBlockExternal</strong> attribute
+ of the <strong>Context</strong> element is changed to <code>true</code>.
+ </li>
+ </ul>
</section>
<section name="server.xml">
@@ -229,9 +303,11 @@
</p>
<p>In a hosted environment where web applications may not be trusted, set
- the <strong>deployXML</strong> attribute to <code>false</code> to ignore any
- context.xml packaged with the web application that may try to assign
- increased privileges to the web application. </p>
+ the <strong>deployXML</strong> attribute to <code>false</code> to ignore
+ any context.xml packaged with the web application that may try to assign
+ increased privileges to the web application. Note that if the security
+ manager is enabled that the <strong>deployXML</strong> attribute will
+ default to <code>false</code>.</p>
</subsection>
<subsection name="Context">
--- java/org/apache/catalina/core/DefaultInstanceManager.java.orig 2014-07-22 16:56:51.460868000 -0400
+++ java/org/apache/catalina/core/DefaultInstanceManager.java 2014-07-22 16:59:03.496296000 -0400
@@ -55,7 +55,7 @@
import org.apache.tomcat.util.res.StringManager;
/**
- * @version $Id: DefaultInstanceManager.java 1437338 2013-01-23 11:02:35Z markt $
+ * @version $Id: DefaultInstanceManager.java 1514663 2013-08-16 11:51:28Z markt $
*/
public class DefaultInstanceManager implements InstanceManager {
@@ -133,6 +133,11 @@
}
@Override
+ public Object newInstance(Class<?> clazz) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException {
+ return newInstance(clazz.newInstance(), clazz);
+ }
+
+ @Override
public Object newInstance(String className) throws IllegalAccessException, InvocationTargetException, NamingException, InstantiationException, ClassNotFoundException {
Class<?> clazz = loadClassMaybePrivileged(className, classLoader);
return newInstance(clazz.newInstance(), clazz);
--- java/org/apache/tomcat/InstanceManager.java.orig 2014-07-22 16:57:21.347937000 -0400
+++ java/org/apache/tomcat/InstanceManager.java 2014-07-22 17:00:47.400650000 -0400
@@ -21,10 +21,14 @@
import javax.naming.NamingException;
/**
- * @version $Id: InstanceManager.java 1200164 2011-11-10 05:46:02Z kkolinko $
+ * @version $Id: InstanceManager.java 1514663 2013-08-16 11:51:28Z markt $
*/
public interface InstanceManager {
+ public Object newInstance(Class<?> clazz)
+ throws IllegalAccessException, InvocationTargetException, NamingException,
+ InstantiationException;
+
public Object newInstance(String className)
throws IllegalAccessException, InvocationTargetException, NamingException,
InstantiationException, ClassNotFoundException;
--- java/org/apache/jasper/EmbeddedServletOptions.java.orig 2014-07-22 17:08:09.862127000 -0400
+++ java/org/apache/jasper/EmbeddedServletOptions.java 2014-07-22 17:08:43.749244000 -0400
@@ -30,7 +30,6 @@
import org.apache.jasper.compiler.Localizer;
import org.apache.jasper.compiler.TagPluginManager;
import org.apache.jasper.compiler.TldLocationsCache;
-import org.apache.jasper.xmlparser.ParserUtils;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
@@ -456,11 +455,7 @@
String v=config.getInitParameter( k );
setProperty( k, v);
}
-
- // quick hack
- String validating=config.getInitParameter( "validating");
- if( "false".equals( validating )) ParserUtils.validating=false;
-
+
String keepgen = config.getInitParameter("keepgenerated");
if (keepgen != null) {
if (keepgen.equalsIgnoreCase("true")) {
--- java/org/apache/tomcat/util/descriptor/DigesterFactory.java.orig 2014-07-21 17:24:05.654400000 -0400
+++ java/org/apache/tomcat/util/descriptor/DigesterFactory.java 2014-07-21 17:46:59.547034000 -0400
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.descriptor;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+
+import org.apache.tomcat.util.digester.Digester;
+import org.apache.tomcat.util.digester.RuleSet;
+import org.xml.sax.ext.EntityResolver2;
+
+/**
+ * Wrapper class around the Digester that hide Digester's initialization
+ * details.
+ */
+public class DigesterFactory {
+
+ /**
+ * Mapping of well-known public IDs used by the Servlet API to the matching
+ * local resource.
+ */
+ public static final Map<String,String> SERVLET_API_PUBLIC_IDS;
+
+ /**
+ * Mapping of well-known system IDs used by the Servlet API to the matching
+ * local resource.
+ */
+ public static final Map<String,String> SERVLET_API_SYSTEM_IDS;
+
+ static {
+ Map<String, String> publicIds = new HashMap<String, String>();
+ Map<String, String> systemIds = new HashMap<String, String>();
+
+ // W3C
+ publicIds.put(XmlIdentifiers.XSD_10_PUBLIC, idFor("XMLSchema.dtd"));
+ publicIds.put(XmlIdentifiers.DATATYPES_PUBLIC, idFor("datatypes.dtd"));
+ systemIds.put(XmlIdentifiers.XML_2001_XSD, idFor("xml.xsd"));
+
+ // from J2EE 1.2
+ publicIds.put(XmlIdentifiers.WEB_22_PUBLIC, idFor("web-app_2_2.dtd"));
+ publicIds.put(XmlIdentifiers.TLD_11_PUBLIC, idFor("web-jsptaglibrary_1_1.dtd"));
+
+ // from J2EE 1.3
+ publicIds.put(XmlIdentifiers.WEB_23_PUBLIC, idFor("web-app_2_3.dtd"));
+ publicIds.put(XmlIdentifiers.TLD_12_PUBLIC, idFor("web-jsptaglibrary_1_2.dtd"));
+
+ // from J2EE 1.4
+ systemIds.put("http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd",
+ idFor("j2ee_web_services_1_1.xsd"));
+ systemIds.put("http://www.ibm.com/webservices/xsd/j2ee_web_services_client_1_1.xsd",
+ idFor("j2ee_web_services_client_1_1.xsd"));
+ systemIds.put(XmlIdentifiers.WEB_24_XSD, idFor("web-app_2_4.xsd"));
+ systemIds.put(XmlIdentifiers.TLD_20_XSD, idFor("web-jsptaglibrary_2_0.xsd"));
+ addSelf(systemIds, "j2ee_1_4.xsd");
+ addSelf(systemIds, "jsp_2_0.xsd");
+
+ // from JavaEE 5
+ systemIds.put(XmlIdentifiers.WEB_25_XSD, idFor("web-app_2_5.xsd"));
+ systemIds.put(XmlIdentifiers.TLD_21_XSD, idFor("web-jsptaglibrary_2_1.xsd"));
+ addSelf(systemIds, "javaee_5.xsd");
+ addSelf(systemIds, "jsp_2_1.xsd");
+ addSelf(systemIds, "javaee_web_services_1_2.xsd");
+ addSelf(systemIds, "javaee_web_services_client_1_2.xsd");
+
+ // from JavaEE 6
+ systemIds.put(XmlIdentifiers.WEB_30_XSD, idFor("web-app_3_0.xsd"));
+ systemIds.put(XmlIdentifiers.WEB_FRAGMENT_30_XSD, idFor("web-fragment_3_0.xsd"));
+ addSelf(systemIds, "web-common_3_0.xsd");
+ addSelf(systemIds, "javaee_6.xsd");
+ addSelf(systemIds, "jsp_2_2.xsd");
+ addSelf(systemIds, "javaee_web_services_1_3.xsd");
+ addSelf(systemIds, "javaee_web_services_client_1_3.xsd");
+
+ SERVLET_API_PUBLIC_IDS = Collections.unmodifiableMap(publicIds);
+ SERVLET_API_SYSTEM_IDS = Collections.unmodifiableMap(systemIds);
+ }
+
+ private static void addSelf(Map<String, String> ids, String id) {
+ String systemId = idFor(id);
+ ids.put(systemId, systemId);
+ ids.put(id, systemId);
+ }
+
+ private static String idFor(String url) {
+ URL id = ServletContext.class.getResource("resources/" + url);
+ if (id == null) {
+ id = ServletContext.class.getResource("jsp/resources/" + url);
+ }
+ return id.toExternalForm();
+ }
+
+
+ /**
+ * Create a <code>Digester</code> parser.
+ * @param xmlValidation turn on/off xml validation
+ * @param xmlNamespaceAware turn on/off namespace validation
+ * @param rule an instance of <code>RuleSet</code> used for parsing the xml.
+ * @param blockExternal turn on/off the blocking of external resources
+ */
+ public static Digester newDigester(boolean xmlValidation,
+ boolean xmlNamespaceAware,
+ RuleSet rule,
+ boolean blockExternal) {
+ Digester digester = new Digester();
+ digester.setNamespaceAware(xmlNamespaceAware);
+ digester.setValidating(xmlValidation);
+ digester.setUseContextClassLoader(true);
+ EntityResolver2 resolver = new LocalResolver(SERVLET_API_PUBLIC_IDS,
+ SERVLET_API_SYSTEM_IDS, blockExternal);
+ digester.setEntityResolver(resolver);
+ if (rule != null) {
+ digester.addRuleSet(rule);
+ }
+
+ return digester;
+ }
+}
--- java/org/apache/tomcat/util/descriptor/LocalResolver.java.orig 2014-07-21 17:24:05.658412000 -0400
+++ java/org/apache/tomcat/util/descriptor/LocalResolver.java 2014-07-21 17:46:59.555034000 -0400
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.descriptor;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Map;
+
+import org.apache.tomcat.util.res.StringManager;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.ext.EntityResolver2;
+
+/**
+ * A resolver for locally cached XML resources.
+ */
+public class LocalResolver implements EntityResolver2 {
+
+ private static final StringManager sm =
+ StringManager.getManager(Constants.PACKAGE_NAME);
+
+ private final Map<String,String> publicIds;
+ private final Map<String,String> systemIds;
+ private final boolean blockExternal;
+
+ /**
+ * Constructor providing mappings of public and system identifiers to local
+ * resources. Each map contains a mapping from a well-known identifier to a
+ * URL for a local resource path.
+ *
+ * @param publicIds mapping of well-known public identifiers to local
+ * resources
+ * @param systemIds mapping of well-known system identifiers to local
+ * resources
+ * @param blockExternal are external resources blocked that are not
+ * well-known
+ */
+ public LocalResolver(Map<String,String> publicIds,
+ Map<String,String> systemIds, boolean blockExternal) {
+ this.publicIds = publicIds;
+ this.systemIds = systemIds;
+ this.blockExternal = blockExternal;
+ }
+
+
+ @Override
+ public InputSource resolveEntity(String publicId, String systemId)
+ throws SAXException, IOException {
+ return resolveEntity(null, publicId, null, systemId);
+ }
+
+
+ @Override
+ public InputSource resolveEntity(String name, String publicId,
+ String base, String systemId) throws SAXException, IOException {
+
+ // First try resolving using the publicId
+ String resolved = publicIds.get(publicId);
+ if (resolved != null) {
+ InputSource is = new InputSource(resolved);
+ is.setPublicId(publicId);
+ return is;
+ }
+
+ // If there is no systemId, can't try anything else
+ if (systemId == null) {
+ throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity",
+ name, publicId, systemId, base));
+ }
+
+ // Try resolving with the supplied systemId
+ resolved = systemIds.get(systemId);
+ if (resolved != null) {
+ InputSource is = new InputSource(resolved);
+ is.setPublicId(publicId);
+ return is;
+ }
+
+ // Resolve the supplied systemId against the base
+ URI systemUri;
+ try {
+ if (base == null) {
+ systemUri = new URI(systemId);
+ } else {
+ // Can't use URI.resolve() because "jar:..." URLs are not valid
+ // hierarchical URIs so resolve() does not work. new URL()
+ // delegates to the jar: stream handler and it manages to figure
+ // it out.
+ URI baseUri = new URI(base);
+ systemUri = new URL(baseUri.toURL(), systemId).toURI();
+ }
+ systemUri = systemUri.normalize();
+ } catch (URISyntaxException e) {
+ // May be caused by a | being used instead of a : in an absolute
+ // file URI on Windows.
+ if (blockExternal) {
+ // Absolute paths aren't allowed so block it
+ throw new MalformedURLException(e.getMessage());
+ } else {
+ // See if the URLHandler can resolve it
+ return new InputSource(systemId);
+ }
+ }
+ if (systemUri.isAbsolute()) {
+ // Try the resolved systemId
+ resolved = systemIds.get(systemUri.toString());
+ if (resolved != null) {
+ InputSource is = new InputSource(resolved);
+ is.setPublicId(publicId);
+ return is;
+ }
+ if (!blockExternal) {
+ InputSource is = new InputSource(systemUri.toString());
+ is.setPublicId(publicId);
+ return is;
+ }
+ }
+ throw new FileNotFoundException(sm.getString("localResolver.unresolvedEntity",
+ name, publicId, systemId, base));
+ }
+
+
+ @Override
+ public InputSource getExternalSubset(String name, String baseURI)
+ throws SAXException, IOException {
+ return null;
+ }
+}
--- java/org/apache/tomcat/util/descriptor/LocalStrings.properties.orig 2014-07-21 17:24:05.663406000 -0400
+++ java/org/apache/tomcat/util/descriptor/LocalStrings.properties 2014-07-21 17:46:59.562036000 -0400
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+localResolver.unresolvedEntity=Could not resolve XML resource [{0}] with public ID [{1}], system ID [{2}] and base URI [{3}] to a known, local entity.
+
+xmlErrorHandler.error=Non-fatal error [{0}] reported processing [{1}].
+xmlErrorHandler.warning=Warning [{0}] reported processing [{1}].
--- java/org/apache/tomcat/util/descriptor/Constants.java.orig 2014-07-21 17:24:05.668398000 -0400
+++ java/org/apache/tomcat/util/descriptor/Constants.java 2014-07-21 17:46:59.569034000 -0400
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.descriptor;
+
+public class Constants {
+
+ public static final String PACKAGE_NAME =
+ Constants.class.getPackage().getName();
+
+}
--- java/org/apache/tomcat/util/descriptor/LocalStrings_es.properties.orig 2014-07-21 17:24:05.672404000 -0400
+++ java/org/apache/tomcat/util/descriptor/LocalStrings_es.properties 2014-07-21 17:46:59.574035000 -0400
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+xmlErrorHandler.error = Error no fatal [{0}] reportado por el proceso [{1}].
+xmlErrorHandler.warning = Aviso [{0}] reportado por el proceso [{1}].
--- java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java.orig 2014-07-21 17:24:05.677400000 -0400
+++ java/org/apache/tomcat/util/descriptor/XmlIdentifiers.java 2014-07-21 17:46:59.580036000 -0400
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.descriptor;
+
+/**
+ * Defines constants for well-known Public and System identifiers documented by
+ * the Servlet and JSP specifications.
+ */
+public final class XmlIdentifiers {
+
+ // from W3C
+ public static final String XML_2001_XSD = "http://www.w3.org/2001/xml.xsd";
+ public static final String DATATYPES_PUBLIC = "datatypes";
+ public static final String XSD_10_PUBLIC =
+ "-//W3C//DTD XMLSCHEMA 200102//EN";
+
+ // from J2EE 1.2
+ public static final String WEB_22_PUBLIC =
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN";
+ public static final String WEB_22_SYSTEM =
+ "http://java.sun.com/dtd/web-app_2_2.dtd";
+ public static final String TLD_11_PUBLIC =
+ "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN";
+ public static final String TLD_11_SYSTEM =
+ "http://java.sun.com/dtd/web-jsptaglibrary_1_1.dtd";
+
+ // from J2EE 1.3
+ public static final String WEB_23_PUBLIC =
+ "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN";
+ public static final String WEB_23_SYSTEM =
+ "http://java.sun.com/dtd/web-app_2_3.dtd";
+ public static final String TLD_12_PUBLIC =
+ "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN";
+ public static final String TLD_12_SYSTEM =
+ "http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd";
+
+ // from J2EE 1.4
+ public static final String WEB_24_XSD =
+ "http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd";
+ public static final String TLD_20_XSD =
+ "http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd";
+ public static final String WEBSERVICES_11_XSD =
+ "http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd";
+
+ // from JavaEE 5
+ public static final String WEB_25_XSD =
+ "http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd";
+ public static final String TLD_21_XSD =
+ "http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd";
+ public static final String WEBSERVICES_12_XSD =
+ "http://java.sun.com/xml/ns/javaee/javaee_web_services_1_2.xsd";
+
+ // from JavaEE 6
+ public static final String WEB_30_XSD =
+ "http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd";
+ public static final String WEB_FRAGMENT_30_XSD =
+ "http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd";
+ public static final String WEBSERVICES_13_XSD =
+ "http://java.sun.com/xml/ns/javaee/javaee_web_services_1_3.xsd";
+
+ private XmlIdentifiers() {
+ }
+}
\ No newline at end of file
--- java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java.orig 2014-07-21 17:24:05.683398000 -0400
+++ java/org/apache/tomcat/util/descriptor/XmlErrorHandler.java 2014-07-21 17:46:59.586038000 -0400
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.descriptor;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.juli.logging.Log;
+import org.apache.tomcat.util.res.StringManager;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+public class XmlErrorHandler implements ErrorHandler {
+
+ private static final StringManager sm =
+ StringManager.getManager(Constants.PACKAGE_NAME);
+
+ private final Set<SAXParseException> errors = new HashSet<SAXParseException>();
+
+ private final Set<SAXParseException> warnings = new HashSet<SAXParseException>();
+
+ @Override
+ public void error(SAXParseException exception) throws SAXException {
+ // Collect non-fatal errors
+ errors.add(exception);
+ }
+
+ @Override
+ public void fatalError(SAXParseException exception) throws SAXException {
+ // Re-throw fatal errors
+ throw exception;
+ }
+
+ @Override
+ public void warning(SAXParseException exception) throws SAXException {
+ // Collect warnings
+ warnings.add(exception);
+ }
+
+ public Set<SAXParseException> getErrors() {
+ // Internal use only - don't worry about immutability
+ return errors;
+ }
+
+ public Set<SAXParseException> getWarnings() {
+ // Internal use only - don't worry about immutability
+ return warnings;
+ }
+
+ public void logFindings(Log log, String source) {
+ for (SAXParseException e : getWarnings()) {
+ log.warn(sm.getString(
+ "xmlErrorHandler.warning", e.getMessage(), source));
+ }
+ for (SAXParseException e : getErrors()) {
+ log.warn(sm.getString(
+ "xmlErrorHandler.error", e.getMessage(), source));
+ }
+ }
+}