Author: markt Date: Thu Nov 5 19:55:00 2015 New Revision: 1712859 URL: http://svn.apache.org/viewvc?rev=1712859&view=rev Log: Further work on https://bz.apache.org/bugzilla/show_bug.cgi?id=57136 Add a configuration option that allows EL expressions in attribute values to use JSP attribute quoting or not. The default (and specification compliant behaviour) is not to.
Added: tomcat/trunk/test/webapp/el-misc-no-quote-attribute-el.jsp - copied unchanged from r1712812, tomcat/trunk/test/webapp/el-misc.jsp tomcat/trunk/test/webapp/el-misc-with-quote-attribute-el.jsp (with props) Removed: tomcat/trunk/test/webapp/el-misc.jsp Modified: tomcat/trunk/java/org/apache/jasper/EmbeddedServletOptions.java tomcat/trunk/java/org/apache/jasper/JspC.java tomcat/trunk/java/org/apache/jasper/Options.java tomcat/trunk/java/org/apache/jasper/compiler/AttributeParser.java tomcat/trunk/java/org/apache/jasper/compiler/Parser.java tomcat/trunk/test/org/apache/el/TestELInJsp.java tomcat/trunk/test/org/apache/jasper/compiler/TestAttributeParser.java Modified: tomcat/trunk/java/org/apache/jasper/EmbeddedServletOptions.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/EmbeddedServletOptions.java?rev=1712859&r1=1712858&r2=1712859&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/EmbeddedServletOptions.java (original) +++ tomcat/trunk/java/org/apache/jasper/EmbeddedServletOptions.java Thu Nov 5 19:55:00 2015 @@ -205,6 +205,8 @@ public final class EmbeddedServletOption */ private boolean strictQuoteEscaping = true; + private boolean quoteAttributeEL = false; + public String getProperty(String name ) { return settings.getProperty( name ); } @@ -215,6 +217,15 @@ public final class EmbeddedServletOption } } + public void setQuoteAttributeEL(boolean b) { + this.quoteAttributeEL = b; + } + + @Override + public boolean getQuoteAttributeEL() { + return quoteAttributeEL; + } + /** * Are we keeping generated code around? */ @@ -765,6 +776,18 @@ public final class EmbeddedServletOption } } + String quoteAttributeEL = config.getInitParameter("quoteAttributeEL"); + if (quoteAttributeEL != null) { + if (quoteAttributeEL.equalsIgnoreCase("true")) { + this.quoteAttributeEL = true; + } else if (quoteAttributeEL.equalsIgnoreCase("false")) { + this.quoteAttributeEL = false; + } else { + if (log.isWarnEnabled()) { + log.warn(Localizer.getMessage("jsp.warning.quoteAttributeEL")); + } + } + } // Setup the global Tag Libraries location cache for this // web-application. Modified: tomcat/trunk/java/org/apache/jasper/JspC.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/JspC.java?rev=1712859&r1=1712858&r2=1712859&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/JspC.java (original) +++ tomcat/trunk/java/org/apache/jasper/JspC.java Thu Nov 5 19:55:00 2015 @@ -137,6 +137,7 @@ public class JspC extends Task implement protected static final String SWITCH_VALIDATE_XML = "-validateXml"; protected static final String SWITCH_NO_BLOCK_EXTERNAL = "-no-blockExternal"; protected static final String SWITCH_NO_STRICT_QUOTE_ESCAPING = "-no-strictQuoteEscaping"; + protected static final String SWITCH_QUOTE_ATTRIBUTE_EL = "-quoteAttributeEL"; protected static final String SHOW_SUCCESS ="-s"; protected static final String LIST_ERRORS = "-l"; protected static final int INC_WEBXML = 10; @@ -171,6 +172,7 @@ public class JspC extends Task implement protected boolean validateXml; protected boolean blockExternal = true; protected boolean strictQuoteEscaping = true; + protected boolean quoteAttributeEL = false; protected boolean xpoweredBy; protected boolean mappedFile = false; protected boolean poolingEnabled = true; @@ -387,6 +389,8 @@ public class JspC extends Task implement setBlockExternal(false); } else if (tok.equals(SWITCH_NO_STRICT_QUOTE_ESCAPING)) { setStrictQuoteEscaping(false); + } else if (tok.equals(SWITCH_QUOTE_ATTRIBUTE_EL)) { + setQuoteAttributeEL(true); } else { if (tok.startsWith("-")) { throw new JasperException("Unrecognized option: " + tok + @@ -903,6 +907,15 @@ public class JspC extends Task implement return strictQuoteEscaping; } + public void setQuoteAttributeEL(boolean b) { + quoteAttributeEL = b; + } + + @Override + public boolean getQuoteAttributeEL() { + return quoteAttributeEL; + } + public void setListErrors( boolean b ) { listErrors = b; } Modified: tomcat/trunk/java/org/apache/jasper/Options.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/Options.java?rev=1712859&r1=1712858&r2=1712859&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/Options.java (original) +++ tomcat/trunk/java/org/apache/jasper/Options.java Thu Nov 5 19:55:00 2015 @@ -237,4 +237,10 @@ public interface Options { * the JSP specification should be applied to scriplet expression. */ public boolean getStrictQuoteEscaping(); + + /** + * @return {@code true} if EL expressions used within attributes should have + * the quoting rules in JSP.1.6 applied to the expression. + */ + public boolean getQuoteAttributeEL(); } Modified: tomcat/trunk/java/org/apache/jasper/compiler/AttributeParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/AttributeParser.java?rev=1712859&r1=1712858&r2=1712859&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/AttributeParser.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/AttributeParser.java Thu Nov 5 19:55:00 2015 @@ -41,15 +41,16 @@ public class AttributeParser { * Are deferred expressions treated as literals? * @param strict Should the rules of JSP.1.6 for escpaing quotes be * strictly applied? + * @param quoteAttributeEL * @return An unquoted JSP attribute that, if it contains * expression language can be safely passed to the EL * processor without fear of ambiguity. */ public static String getUnquoted(String input, char quote, boolean isELIgnored, boolean isDeferredSyntaxAllowedAsLiteral, - boolean strict) { + boolean strict, boolean quoteAttributeEL) { return (new AttributeParser(input, quote, isELIgnored, - isDeferredSyntaxAllowedAsLiteral, strict)).getUnquoted(); + isDeferredSyntaxAllowedAsLiteral, strict, quoteAttributeEL)).getUnquoted(); } /* The quoted input string. */ @@ -70,6 +71,8 @@ public class AttributeParser { */ private final boolean strict; + private final boolean quoteAttributeEL; + /* The type ($ or #) of expression. Literals have a type of null. */ private final char type; @@ -94,13 +97,14 @@ public class AttributeParser { */ private AttributeParser(String input, char quote, boolean isELIgnored, boolean isDeferredSyntaxAllowedAsLiteral, - boolean strict) { + boolean strict, boolean quoteAttributeEL) { this.input = input; this.quote = quote; this.isELIgnored = isELIgnored; this.isDeferredSyntaxAllowedAsLiteral = isDeferredSyntaxAllowedAsLiteral; this.strict = strict; + this.quoteAttributeEL = quoteAttributeEL; this.type = getType(input); this.size = input.length(); result = new StringBuilder(size); @@ -189,7 +193,12 @@ public class AttributeParser { boolean insideLiteral = false; char literalQuote = 0; while (i < size && !endEL) { - char ch = input.charAt(i++); + char ch; + if (quoteAttributeEL) { + ch = nextChar(); + } else { + ch = input.charAt(i++); + } if (ch == '\'' || ch == '\"') { if (insideLiteral) { if (literalQuote == ch) { @@ -203,7 +212,11 @@ public class AttributeParser { } else if (ch == '\\') { result.append(ch); if (insideLiteral && size < i) { - ch = input.charAt(i++); + if (quoteAttributeEL) { + ch = nextChar(); + } else { + ch = input.charAt(i++); + } result.append(ch); } } else if (ch == '}') { Modified: tomcat/trunk/java/org/apache/jasper/compiler/Parser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/jasper/compiler/Parser.java?rev=1712859&r1=1712858&r2=1712859&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/jasper/compiler/Parser.java (original) +++ tomcat/trunk/java/org/apache/jasper/compiler/Parser.java Thu Nov 5 19:55:00 2015 @@ -264,8 +264,11 @@ class Parser implements TagConstants { * ('%>"' | TRANSLATION_ERROR) */ private String parseAttributeValue(String qName, String watch, boolean ignoreEL) throws JasperException { + boolean quoteAttributeEL = ctxt.getOptions().getQuoteAttributeEL(); Mark start = reader.mark(); - Mark stop = reader.skipUntilIgnoreEsc(watch, ignoreEL); + // In terms of finding the end of the value, quoting EL is equivalent to + // ignoring it. + Mark stop = reader.skipUntilIgnoreEsc(watch, ignoreEL || quoteAttributeEL); if (stop == null) { err.jspError(start, "jsp.error.attribute.unterminated", qName); } @@ -282,7 +285,8 @@ class Parser implements TagConstants { ret = AttributeParser.getUnquoted(reader.getText(start, stop), quote, isElIgnored, pageInfo.isDeferredSyntaxAllowedAsLiteral(), - ctxt.getOptions().getStrictQuoteEscaping()); + ctxt.getOptions().getStrictQuoteEscaping(), + quoteAttributeEL); } catch (IllegalArgumentException iae) { err.jspError(start, iae.getMessage()); } Modified: tomcat/trunk/test/org/apache/el/TestELInJsp.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/el/TestELInJsp.java?rev=1712859&r1=1712858&r2=1712859&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/el/TestELInJsp.java (original) +++ tomcat/trunk/test/org/apache/el/TestELInJsp.java Thu Nov 5 19:55:00 2015 @@ -16,6 +16,7 @@ */ package org.apache.el; +import java.io.File; import java.math.BigDecimal; import java.util.Collections; @@ -24,7 +25,11 @@ import javax.servlet.DispatcherType; import org.junit.Assert; import org.junit.Test; +import org.apache.catalina.Wrapper; +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.startup.Tomcat; import org.apache.catalina.startup.TomcatBaseTest; +import org.apache.jasper.servlet.JasperInitializer; import org.apache.tomcat.util.buf.ByteChunk; /** @@ -289,10 +294,43 @@ public class TestELInJsp extends TomcatB } @Test - public void testELMisc() throws Exception { - getTomcatInstanceTestWebapp(false, true); + public void testELMiscNoQuoteAttributeEL() throws Exception { + doTestELMisc(false); + } + + @Test + public void testELMiscWithQuoteAttributeEL() throws Exception { + doTestELMisc(true); + } + + private void doTestELMisc(boolean quoteAttributeEL) throws Exception { + Tomcat tomcat = getTomcatInstance(); + + // Create the context (don't use addWebapp as we want to modify the + // JSP Servlet settings). + File appDir = new File("test/webapp"); + StandardContext ctxt = (StandardContext) tomcat.addContext( + null, "/test", appDir.getAbsolutePath()); + + ctxt.addServletContainerInitializer(new JasperInitializer(), null); + + // Configure the defaults and then tweak the JSP servlet settings + // Note: Min value for maxLoadedJsps is 2 + Tomcat.initWebappDefaults(ctxt); + Wrapper w = (Wrapper) ctxt.findChild("jsp"); + + String jspName; + if (quoteAttributeEL) { + jspName = "/test/el-misc-with-quote-attribute-el.jsp"; + w.addInitParameter("quoteAttributeEL", "true"); + } else { + jspName = "/test/el-misc-no-quote-attribute-el.jsp"; + w.addInitParameter("quoteAttributeEL", "false"); + } + + tomcat.start(); - ByteChunk res = getUrl("http://localhost:" + getPort() + "/test/el-misc.jsp"); + ByteChunk res = getUrl("http://localhost:" + getPort() + jspName); String result = res.toString(); assertEcho(result, "00-\\\\\\\"${'hello world'}"); Modified: tomcat/trunk/test/org/apache/jasper/compiler/TestAttributeParser.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/jasper/compiler/TestAttributeParser.java?rev=1712859&r1=1712858&r2=1712859&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/jasper/compiler/TestAttributeParser.java (original) +++ tomcat/trunk/test/org/apache/jasper/compiler/TestAttributeParser.java Thu Nov 5 19:55:00 2015 @@ -171,14 +171,14 @@ public class TestAttributeParser { ctx.setFunctionMapper(new FMapper()); ValueExpression ve = exprFactory.createValueExpression(ctx, AttributeParser.getUnquoted(expression, quote, false, false, - false), + false, false), String.class); return (String) ve.getValue(ctx); } private String parseScriptExpression(String expression, char quote) { return AttributeParser.getUnquoted(expression, quote, false, false, - false); + false, false); } public static class FMapper extends FunctionMapper { Added: tomcat/trunk/test/webapp/el-misc-with-quote-attribute-el.jsp URL: http://svn.apache.org/viewvc/tomcat/trunk/test/webapp/el-misc-with-quote-attribute-el.jsp?rev=1712859&view=auto ============================================================================== --- tomcat/trunk/test/webapp/el-misc-with-quote-attribute-el.jsp (added) +++ tomcat/trunk/test/webapp/el-misc-with-quote-attribute-el.jsp Thu Nov 5 19:55:00 2015 @@ -0,0 +1,44 @@ +<%-- + 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. +--%> +<%@ taglib prefix="tags" tagdir="/WEB-INF/tags" %> +<html> + <head><title>Misc EL test cases</title></head> + <body> + <p>00-\\\"\${'hello world'}</p> + <p>01-\\\"\\${'hello world'}</p> + <tags:echo echo="02-\\\"\${'hello world'}" /> + <tags:echo echo="03-\\\"\\${'hello world'}" /> + <tags:echo echo="${'2'}az-04" /> + <tags:echo echo="05-a${'2'}z" /> + <tags:echo echo="06-az${'2'}" /> + <tags:echo echo="${\"2\"}az-07" /> + <tags:echo echo="08-a${\"2\"}z" /> + <tags:echo echo="09-az${\"2\"}" /> + <tags:echo echo="10-\${'foo'}${'bar'}" /> + <tags:echo echo="11-${\"\\\\\"}\"}" /> + <tags:echo echo="12-${'foo'}\\${'bar'}\\${'baz'}" /> + <tags:echo echo="13-${'foo'}\\${\"bar\"}\\${'baz'}" /> + <tags:echo echo="14-${\"foo\"}\\${'bar'}\\${\"baz\"}" /> + <tags:echo echo='15-${\'foo\'}\\${"bar"}\\${\'baz\'}' /> + <tags:echo echo='16-${"foo"}\\${\'bar\'}\\${"baz"}' /> + <tags:echo echo='17-${"foo"}\\${"&"}${"apos;bar"}${"&"}${"apos;"}\\${"&"}${"quot;baz"}${"&"}${"quot;"}' /> + <tags:echo echo='18-${((x,y)->x+y)(1,2)}' /> + <tags:echo echo='19-${{1,2,3,4}.stream().max().orElse(-1)}' /> + <p>20-${{1,2,3,4}.stream().max().orElse(-1)}</p> + <tags:echo echo='21-${{1,2,3,4}.stream().sorted().map(u->{"value":u+10}).toList()}' /> + <p>22-${{1,2,3,4}.stream().sorted().map(u->{"value":u+10}).toList()}</p> </body> +</html> \ No newline at end of file Propchange: tomcat/trunk/test/webapp/el-misc-with-quote-attribute-el.jsp ------------------------------------------------------------------------------ svn:eol-style = native --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org