jakarta.servlet.jsp.jstl.tlv.ScriptFreeTLV Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jakarta.servlet.jsp.jstl-api Show documentation
Show all versions of jakarta.servlet.jsp.jstl-api Show documentation
Jakarta Standard Tag Library API
/*
* Copyright (c) 1997-2020 Oracle and/or its affiliates. All rights reserved.
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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 jakarta.servlet.jsp.jstl.tlv;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import jakarta.servlet.jsp.tagext.PageData;
import jakarta.servlet.jsp.tagext.TagLibraryValidator;
import jakarta.servlet.jsp.tagext.ValidationMessage;
/**
*
* A TagLibraryValidator for enforcing restrictions against the use of JSP scripting elements.
*
*
* This TLV supports four initialization parameters, for controlling which of the four types of scripting elements are
* allowed or prohibited:
*
*
* - allowDeclarations: if true, indicates that declaration elements are not prohibited.
*
- allowScriptlets: if true, indicates that scriptlets are not prohibited
*
- allowExpressions: if true, indicates that top-level expression elements (i.e., expressions not associated
* with request-time attribute values) are not prohibited.
*
- allowRTExpressions: if true, indicates that expression elements associated with request-time attribute
* values are not prohibited.
*
*
* The default value for all for initialization parameters is false, indicating all forms of scripting elements are to
* be prohibited.
*
*
* @author Mark A. Kolb
* @author Shawn Bayern (minor changes)
*/
public class ScriptFreeTLV extends TagLibraryValidator {
private boolean allowDeclarations = false;
private boolean allowScriptlets = false;
private boolean allowExpressions = false;
private boolean allowRTExpressions = false;
private SAXParserFactory factory;
/**
* Constructs a new validator instance. Initializes the parser factory to create non-validating, namespace-aware SAX
* parsers.
*/
public ScriptFreeTLV() {
factory = SAXParserFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(true);
}
/**
* Sets the values of the initialization parameters, as supplied in the TLD.
*
* @param initParms a mapping from the names of the initialization parameters to their values, as specified in the TLD.
*/
public void setInitParameters(Map initParms) {
super.setInitParameters(initParms);
String declarationsParm = (String) initParms.get("allowDeclarations");
String scriptletsParm = (String) initParms.get("allowScriptlets");
String expressionsParm = (String) initParms.get("allowExpressions");
String rtExpressionsParm = (String) initParms.get("allowRTExpressions");
allowDeclarations = "true".equalsIgnoreCase(declarationsParm);
allowScriptlets = "true".equalsIgnoreCase(scriptletsParm);
allowExpressions = "true".equalsIgnoreCase(expressionsParm);
allowRTExpressions = "true".equalsIgnoreCase(rtExpressionsParm);
}
/**
* Validates a single JSP page.
*
* @param prefix the namespace prefix specified by the page for the custom tag library being validated.
* @param uri the URI specified by the page for the TLD of the custom tag library being validated.
* @param page a wrapper around the XML representation of the page being validated.
* @return null, if the page is valid; otherwise, a ValidationMessage[] containing one or more messages indicating why
* the page is not valid.
*/
public ValidationMessage[] validate(String prefix, String uri, PageData page) {
InputStream in = null;
SAXParser parser;
MyContentHandler handler = new MyContentHandler();
try {
synchronized (factory) {
parser = factory.newSAXParser();
}
in = page.getInputStream();
parser.parse(in, handler);
} catch (ParserConfigurationException e) {
return vmFromString(e.toString());
} catch (SAXException e) {
return vmFromString(e.toString());
} catch (IOException e) {
return vmFromString(e.toString());
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
return handler.reportResults();
}
/**
* Handler for SAX events. Four counters are provided as instance variables, for counting occurrences of prohibited
* scripting elements.
*/
private class MyContentHandler extends DefaultHandler {
private int declarationCount = 0;
private int scriptletCount = 0;
private int expressionCount = 0;
private int rtExpressionCount = 0;
/**
* This event is received whenever a new element is encountered. The qualified name of each such element is compared
* against the names of any prohibited scripting elements. When found, the corresponding counter is incremented. If
* expressions representing request-time attribute values are prohibited, it is also necessary to check the values of
* all attributes specified by the element. (Trying to figure out which attributes actually support request-time
* attribute values and checking only those is far more trouble than it's worth.)
*/
public void startElement(String namespaceUri, String localName, String qualifiedName, Attributes atts) {
if (!allowDeclarations && qualifiedName.equals("jsp:declaration")) {
++declarationCount;
} else if (!allowScriptlets && qualifiedName.equals("jsp:scriptlet")) {
++scriptletCount;
} else if (!allowExpressions && qualifiedName.equals("jsp:expression")) {
++expressionCount;
}
if (!allowRTExpressions) {
countRTExpressions(atts);
}
}
/**
* Auxiliary method for checking attribute values to see if are specified via request-time attribute values. Expressions
* representing request-time attribute values are recognized by their "%=" and "%" delimiters. When found, the
* corresponding counter is incremented.
*/
private void countRTExpressions(Attributes atts) {
int stop = atts.getLength();
for (int i = 0; i < stop; ++i) {
String attval = atts.getValue(i);
if (attval.startsWith("%=") && attval.endsWith("%")) {
++rtExpressionCount;
}
}
}
/**
* Constructs a String reporting the number(s) of prohibited scripting elements that were detected, if any. Returns null
* if no violations were found, making the result of this method suitable for the return value of the
* TagLibraryValidator.validate() method.
*
* TODO: The update from 7/13/2001 merely makes this validator compliant with the new TLV API, but does not fully take
* advantage of this API. In the future, we should do so... but because of the possibility that anti-script checking
* will be incorporated into the base TLV, I've held off for now and just changed this class to use the new API. -- SB.
*/
public ValidationMessage[] reportResults() {
if (declarationCount + scriptletCount + expressionCount + rtExpressionCount > 0) {
StringBuffer results = new StringBuffer("JSP page contains ");
boolean first = true;
if (declarationCount > 0) {
results.append(Integer.toString(declarationCount));
results.append(" declaration");
if (declarationCount > 1) {
results.append('s');
}
first = false;
}
if (scriptletCount > 0) {
if (!first) {
results.append(", ");
}
results.append(Integer.toString(scriptletCount));
results.append(" scriptlet");
if (scriptletCount > 1) {
results.append('s');
}
first = false;
}
if (expressionCount > 0) {
if (!first) {
results.append(", ");
}
results.append(Integer.toString(expressionCount));
results.append(" expression");
if (expressionCount > 1) {
results.append('s');
}
first = false;
}
if (rtExpressionCount > 0) {
if (!first) {
results.append(", ");
}
results.append(Integer.toString(rtExpressionCount));
results.append(" request-time attribute value");
if (rtExpressionCount > 1) {
results.append('s');
}
first = false;
}
results.append(".");
return vmFromString(results.toString());
} else {
return null;
}
}
}
// constructs a ValidationMessage[] from a single String and no ID
private static ValidationMessage[] vmFromString(String message) {
return new ValidationMessage[] { new ValidationMessage(null, message) };
}
}