Author: remy.maucherat(a)jboss.com
Date: 2013-11-06 04:38:04 -0500 (Wed, 06 Nov 2013)
New Revision: 2301
Modified:
branches/7.4.x/src/main/java/org/apache/jasper/compiler/ELParser.java
branches/7.4.x/src/main/java/org/apache/jasper/compiler/Validator.java
branches/7.4.x/src/main/java/org/apache/jasper/runtime/PageContextImpl.java
Log:
Port fix for some EL processing
https://issues.apache.org/bugzilla/show_bug.cgi?id=55735
Modified: branches/7.4.x/src/main/java/org/apache/jasper/compiler/ELParser.java
===================================================================
--- branches/7.4.x/src/main/java/org/apache/jasper/compiler/ELParser.java 2013-11-05
16:23:32 UTC (rev 2300)
+++ branches/7.4.x/src/main/java/org/apache/jasper/compiler/ELParser.java 2013-11-06
09:38:04 UTC (rev 2301)
@@ -17,6 +17,12 @@
package org.apache.jasper.compiler;
+import org.apache.jasper.JasperException;
+import org.apache.jasper.compiler.ELNode.ELText;
+import org.apache.jasper.compiler.ELNode.Function;
+import org.apache.jasper.compiler.ELNode.Root;
+import org.apache.jasper.compiler.ELNode.Text;
+
/**
* This class implements a parser for EL expressions.
*
@@ -106,6 +112,7 @@
// Output whatever is in buffer
if (buf.length() > 0) {
ELexpr.add(new ELNode.ELText(buf.toString()));
+ buf = new StringBuilder();
}
if (!parseFunction()) {
ELexpr.add(new ELNode.ELText(curToken.toString()));
@@ -131,8 +138,8 @@
}
String s1 = null; // Function prefix
String s2 = curToken.toString(); // Function name
- int mark = getIndex();
if (hasNext()) {
+ int mark = getIndex();
curToken = nextToken();
if (curToken.toChar() == ':') {
if (hasNext()) {
@@ -150,8 +157,9 @@
ELexpr.add(new ELNode.Function(s1, s2));
return true;
}
+ curToken = prevToken;
+ setIndex(mark);
}
- setIndex(mark);
return false;
}
@@ -389,4 +397,41 @@
public char getType() {
return type;
}
+
+ protected static class TextBuilder extends ELNode.Visitor {
+
+ protected StringBuilder output = new StringBuilder();
+
+ public String getText() {
+ return output.toString();
+ }
+
+ @Override
+ public void visit(Root n) throws JasperException {
+ output.append(n.getType());
+ output.append('{');
+ n.getExpression().visit(this);
+ output.append('}');
+ }
+
+ @Override
+ public void visit(Function n) throws JasperException {
+ if (n.getPrefix() != null) {
+ output.append(n.getPrefix());
+ output.append(':');
+ }
+ output.append(n.getName());
+ output.append('(');
+ }
+
+ @Override
+ public void visit(Text n) throws JasperException {
+ output.append(n.getText());
+ }
+
+ @Override
+ public void visit(ELText n) throws JasperException {
+ output.append(n.getText());
+ }
+ }
}
Modified: branches/7.4.x/src/main/java/org/apache/jasper/compiler/Validator.java
===================================================================
--- branches/7.4.x/src/main/java/org/apache/jasper/compiler/Validator.java 2013-11-05
16:23:32 UTC (rev 2300)
+++ branches/7.4.x/src/main/java/org/apache/jasper/compiler/Validator.java 2013-11-06
09:38:04 UTC (rev 2301)
@@ -41,6 +41,7 @@
import javax.servlet.jsp.tagext.ValidationMessage;
import org.apache.jasper.JasperException;
+import org.apache.jasper.compiler.ELNode.Text;
import org.apache.jasper.el.ELContextImpl;
import org.xml.sax.Attributes;
@@ -1352,8 +1353,16 @@
validateFunctions(el, n);
- result = new Node.JspAttribute(tai, qName, uri,
- localName, value, false, el, dynamic);
+ if (n.getRoot().isXmlSyntax()) {
+ // The non-EL elements need to be XML escaped
+ XmlEscapeNonELVisitor v = new XmlEscapeNonELVisitor();
+ el.visit(v);
+ result = new Node.JspAttribute(tai, qName, uri,
+ localName, v.getText(), false, el, dynamic);
+ } else {
+ result = new Node.JspAttribute(tai, qName, uri,
+ localName, value, false, el, dynamic);
+ }
ELContextImpl ctx = new ELContextImpl();
ctx.setFunctionMapper(getFunctionMapper(el));
@@ -1387,6 +1396,14 @@
return result;
}
+ private static class XmlEscapeNonELVisitor extends ELParser.TextBuilder {
+
+ @Override
+ public void visit(Text n) throws JasperException {
+ output.append(xmlEscape(n.getText()));
+ }
+ }
+
/*
* Return an empty StringBuilder [not thread-safe]
*/
@@ -1810,4 +1827,67 @@
errDisp.jspError(errMsg.toString());
}
}
+
+ protected static String xmlEscape(String s) {
+ if (s == null) {
+ return null;
+ }
+ int len = s.length();
+
+ /*
+ * Look for any "bad" characters, Escape "bad" character was
found
+ */
+ // ASCII " 34 & 38 ' 39 < 60 > 62
+ for (int i = 0; i < len; i++) {
+ char c = s.charAt(i);
+ if (c >= '\"' && c <= '>' &&
+ (c == '<' || c == '>' || c == '\''
|| c == '&' || c == '"')) {
+ // need to escape them and then quote the whole string
+ StringBuilder sb = new StringBuilder((int) (len * 1.2));
+ sb.append(s, 0, i);
+ int pos = i + 1;
+ for (int j = i; j < len; j++) {
+ c = s.charAt(j);
+ if (c >= '\"' && c <= '>') {
+ if (c == '<') {
+ if (j > pos) {
+ sb.append(s, pos, j);
+ }
+ sb.append("<");
+ pos = j + 1;
+ } else if (c == '>') {
+ if (j > pos) {
+ sb.append(s, pos, j);
+ }
+ sb.append(">");
+ pos = j + 1;
+ } else if (c == '\'') {
+ if (j > pos) {
+ sb.append(s, pos, j);
+ }
+ sb.append("'"); // '
+ pos = j + 1;
+ } else if (c == '&') {
+ if (j > pos) {
+ sb.append(s, pos, j);
+ }
+ sb.append("&");
+ pos = j + 1;
+ } else if (c == '"') {
+ if (j > pos) {
+ sb.append(s, pos, j);
+ }
+ sb.append("""); // "
+ pos = j + 1;
+ }
+ }
+ }
+ if (pos < len) {
+ sb.append(s, pos, len);
+ }
+ return sb.toString();
+ }
+ }
+ return s;
+ }
}
Modified: branches/7.4.x/src/main/java/org/apache/jasper/runtime/PageContextImpl.java
===================================================================
--- branches/7.4.x/src/main/java/org/apache/jasper/runtime/PageContextImpl.java 2013-11-05
16:23:32 UTC (rev 2300)
+++ branches/7.4.x/src/main/java/org/apache/jasper/runtime/PageContextImpl.java 2013-11-06
09:38:04 UTC (rev 2301)
@@ -846,69 +846,6 @@
}
}
- protected static String XmlEscape(String s) {
- if (s == null) {
- return null;
- }
- int len = s.length();
-
- /*
- * Look for any "bad" characters, Escape "bad" character was
found
- */
- // ASCII " 34 & 38 ' 39 < 60 > 62
- for (int i = 0; i < len; i++) {
- char c = s.charAt(i);
- if (c >= '\"' && c <= '>' &&
- (c == '<' || c == '>' || c == '\''
|| c == '&' || c == '"')) {
- // need to escape them and then quote the whole string
- StringBuilder sb = new StringBuilder((int) (len * 1.2));
- sb.append(s, 0, i);
- int pos = i + 1;
- for (int j = i; j < len; j++) {
- c = s.charAt(j);
- if (c >= '\"' && c <= '>') {
- if (c == '<') {
- if (j > pos) {
- sb.append(s, pos, j);
- }
- sb.append("<");
- pos = j + 1;
- } else if (c == '>') {
- if (j > pos) {
- sb.append(s, pos, j);
- }
- sb.append(">");
- pos = j + 1;
- } else if (c == '\'') {
- if (j > pos) {
- sb.append(s, pos, j);
- }
- sb.append("'"); // '
- pos = j + 1;
- } else if (c == '&') {
- if (j > pos) {
- sb.append(s, pos, j);
- }
- sb.append("&");
- pos = j + 1;
- } else if (c == '"') {
- if (j > pos) {
- sb.append(s, pos, j);
- }
- sb.append("""); // "
- pos = j + 1;
- }
- }
- }
- if (pos < len) {
- sb.append(s, pos, len);
- }
- return sb.toString();
- }
- }
- return s;
- }
-
/**
* Proprietary method to evaluate EL expressions. XXX - This method should
* go away once the EL interpreter moves out of JSTL and into its own
@@ -957,10 +894,6 @@
ValueExpression ve = exprFactory.createValueExpression(ctx, expression,
expectedType);
retValue = ve.getValue(ctx);
}
- if (escape && retValue != null) {
- retValue = XmlEscape(retValue.toString());
- }
-
return retValue;
}