Skip to content

Commit

Permalink
Merge pull request #373 from JCgH4164838Gh792C124B5/local_26x_TagBody…
Browse files Browse the repository at this point in the history
…EscapeCtrl

Proposed fix for WW-5022 (escape html tag body control flag)
  • Loading branch information
lukaszlenart committed Oct 19, 2019
2 parents be262bc + 9592355 commit 2d23357
Show file tree
Hide file tree
Showing 21 changed files with 245 additions and 16 deletions.
4 changes: 2 additions & 2 deletions apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@

<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><s:a value="%{home}"><i class="glyphicon glyphicon-home"></i> Home</s:a></li>
<li><s:a value="%{home}" escapeHtmlBody="false"><i class="glyphicon glyphicon-home"></i> Home</s:a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="glyphicon glyphicon-cog"></i> Configuration
Expand Down Expand Up @@ -233,7 +233,7 @@
</li>
<li><s:a value="/person/index.html">Person Manager</s:a></li>
<li><s:a value="/skill/index.html">CRUD</s:a></li>
<li><s:a value="/wait/index.html">Execute &amp; Wait</s:a></li>
<li><s:a value="/wait/index.html" escapeHtmlBody="false">Execute &amp; Wait</s:a></li>
<li><s:a value="/token/index.html">Token</s:a></li>
<li><s:url var="url" namespace="/modelDriven" action="modelDriven"/><s:a
href="%{url}">Model Driven</s:a></li>
Expand Down
4 changes: 2 additions & 2 deletions apps/showcase/src/main/webapp/WEB-INF/filedownload/index.jsp
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@
</div>

<s:url var="url" action="download"/>
<s:a href="%{url}" cssClass="btn btn-large btn-info"><i class="icon-picture"></i> Download image file.</s:a>
<s:a href="%{url}" cssClass="btn btn-large btn-info" escapeHtmlBody="false"><i class="icon-picture"></i> Download image file.</s:a>
</div>
<div class="col-md-6" style="text-align: center;">
<div class="alert alert-info">
The browser should prompt for a location to save the ZIP file.
</div>

<s:url var="url" action="download2"/>
<s:a href="%{url}" cssClass="btn btn-large btn-info"><i class="icon-download-alt"></i> Download ZIP file.</s:a>
<s:a href="%{url}" cssClass="btn btn-large btn-info" escapeHtmlBody="false"><i class="icon-download-alt"></i> Download ZIP file.</s:a>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
</s:iterator>

<s:url var="url" action="showAppendTagDemo" namespace="/tags/non-ui/appendIteratorTag" />
<s:a href="%{#url}" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
<s:a href="%{#url}" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@


<s:url var="url" action="showGeneratorTagDemo" namespace="/tags/non-ui/iteratorGeneratorTag" />
<s:a href="%{#url}" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
<s:a href="%{#url}" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
</s:iterator>

<s:url var="url" action="showMergeTagDemo" namespace="/tags/non-ui/mergeIteratorTag" />
<s:a href="%{#url}" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
<s:a href="%{#url}" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
</s:subset>

<s:url var="url" action="showSubsetTagDemo" namespace="/tags/non-ui/subsetIteratorTag" />
<s:a href="%{#url}" cssClass="btn btn-info"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
<s:a href="%{#url}" cssClass="btn btn-info" escapeHtmlBody="false"><i class="icon icon-arrow-left"></i> Back To Input</s:a>
</div>
</div>
</div>
Expand Down
18 changes: 18 additions & 0 deletions core/src/main/java/org/apache/struts2/components/Anchor.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ public class Anchor extends ClosingUIBean {
protected UrlProvider urlProvider;
protected UrlRenderer urlRenderer;
protected boolean processingTagBody = false;
protected boolean escapeHtmlBody = true;

//these params are passed by the Param tag
protected Map urlParameters = new LinkedHashMap();
Expand All @@ -95,6 +96,18 @@ public boolean usesBody() {
return true;
}

/**
* Override to set if body content should be HTML-escaped.
*
* @return true if body should be HTML-escaped, false otherwise.
*
* @since 2.6
*/
@Override
public boolean escapeHtmlBody() {
return escapeHtmlBody;
}

@Override
protected void evaluateExtraParams() {
super.evaluateExtraParams();
Expand Down Expand Up @@ -262,4 +275,9 @@ public void setEscapeAmp(boolean escapeAmp) {
public void setForceAddSchemeHostAndPort(boolean forceAddSchemeHostAndPort) {
urlProvider.setForceAddSchemeHostAndPort(forceAddSchemeHostAndPort);
}

@StrutsTagAttribute(required = false, description = "Specifies whether to HTML-escape the tag body or not", type = "Boolean", defaultValue = "true")
public void setEscapeHtmlBody(boolean escapeHtmlBody) {
this.escapeHtmlBody = escapeHtmlBody;
}
}
11 changes: 11 additions & 0 deletions core/src/main/java/org/apache/struts2/components/Component.java
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,17 @@ public boolean usesBody() {
return false;
}

/**
* Override to set if body content should be HTML-escaped.
*
* @return always true (default) for this component.
*
* @since 2.6
*/
public boolean escapeHtmlBody() {
return true;
}

/**
* Checks if provided name is a valid tag's attribute
*
Expand Down
17 changes: 17 additions & 0 deletions core/src/main/java/org/apache/struts2/components/Submit.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class Submit extends FormButton {
final public static String OPEN_TEMPLATE = "submit";
final public static String TEMPLATE = "submit-close";
protected String src;
protected boolean escapeHtmlBody = true;

public Submit(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
super(stack, request, response);
Expand Down Expand Up @@ -100,12 +101,28 @@ public void setSrc(String src) {
this.src = src;
}

@StrutsTagAttribute(required = false, description = "Specifies whether to HTML-escape the tag body or not", type = "Boolean", defaultValue = "true")
public void setEscapeHtmlBody(boolean escapeHtmlBody) {
this.escapeHtmlBody = escapeHtmlBody;
}

@Override
public boolean usesBody() {
return true;
}

/**
* Override to set if body content should be HTML-escaped.
*
* @return true if body should be HTML-escaped, false otherwise.
*
* @since 2.6
*/
@Override
public boolean escapeHtmlBody() {
return escapeHtmlBody;
}

/**
* Overrides to be able to render body in a template rather than always before the template
*/
Expand Down
19 changes: 16 additions & 3 deletions core/src/main/java/org/apache/struts2/views/jsp/ui/AnchorTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ public class AnchorTag extends AbstractClosingTag {
protected String portletUrlType;
protected String anchor;
protected String forceAddSchemeHostAndPort;

protected boolean escapeHtmlBody = true; // Default - escape HTML body

public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
return new Anchor(stack, req, res);
}
Expand Down Expand Up @@ -77,11 +78,12 @@ protected void populateParams() {
if (escapeAmp != null) {
tag.setEscapeAmp(BooleanUtils.toBoolean(escapeAmp));
}
if (forceAddSchemeHostAndPort != null) {
if (forceAddSchemeHostAndPort != null) {
tag.setForceAddSchemeHostAndPort(BooleanUtils.toBoolean(forceAddSchemeHostAndPort));
}
tag.setEscapeHtmlBody(escapeHtmlBody);
}

public void setHref(String href) {
this.href = href;
}
Expand Down Expand Up @@ -141,6 +143,17 @@ public void setAnchor(String anchor) {
public void setForceAddSchemeHostAndPort(String forceAddSchemeHostAndPort) {
this.forceAddSchemeHostAndPort = forceAddSchemeHostAndPort;
}

/**
* Set via parameter to control if body content should be HTML-escaped.
*
* @param escapeHtmlBody
*
* @since 2.6
*/
public void setEscapeHtmlBody(boolean escapeHtmlBody) {
this.escapeHtmlBody = escapeHtmlBody;
}
}


13 changes: 13 additions & 0 deletions core/src/main/java/org/apache/struts2/views/jsp/ui/SubmitTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class SubmitTag extends AbstractClosingTag {
protected String method;
protected String type;
protected String src;
protected boolean escapeHtmlBody = true; // Default - escape HTML body

public Component getBean(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
return new Submit(stack, req, res);
Expand All @@ -50,6 +51,7 @@ protected void populateParams() {
submit.setMethod(method);
submit.setType(type);
submit.setSrc(src);
submit.setEscapeHtmlBody(escapeHtmlBody);
}

public void setAction(String action) {
Expand All @@ -71,4 +73,15 @@ public void setType(String type) {
public void setSrc(String src) {
this.src = src;
}

/**
* Set via parameter to control if body content should be HTML-escaped.
*
* @param escapeHtmlBody
*
* @since 2.6
*/
public void setEscapeHtmlBody(boolean escapeHtmlBody) {
this.escapeHtmlBody = escapeHtmlBody;
}
}
2 changes: 1 addition & 1 deletion core/src/main/resources/template/simple/a-close.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,4 @@
<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
>${parameters.body}</a>
>${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}</a>
6 changes: 3 additions & 3 deletions core/src/main/resources/template/simple/submit-close.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
*/
-->
<#if parameters.type?? && parameters.type=="button">
<#if parameters.body?length gt 0>${parameters.body}<#elseif parameters.label??><@s.property value="parameters.label"/><#rt/></#if>
<#if parameters.body?length gt 0>${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}<#elseif parameters.label??><@s.property value="parameters.label"/><#rt/></#if>
</button>
<#else>
${parameters.body}<#rt/>
</#if>
${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}<#rt/>
</#if>
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,6 @@ public void testURLComponentDisposeItselfFromComponentStack() throws Exception {
}
}


// updownselect
public void testUpDownSelectDisposeItselfFromComponentStack() throws Exception {
TextFieldTag t = new TextFieldTag();
Expand All @@ -505,4 +504,42 @@ public void testUpDownSelectDisposeItselfFromComponentStack() throws Exception {
fail(e.toString());
}
}

/**
* Test the expected default behaviour for component body state methods.
*/
public void testComponentDefaultBodyStates() {
Component component = new Component(stack);
// Test expected default results for: usesBody(), escapeHtmlBody().
assertFalse("Component default usesBody not false ?", component.usesBody());
assertTrue("Component default htmlEscapeBody not true ?", component.escapeHtmlBody());
}

/**
* Test the behaviour for Anchor body state methods.
*/
public void testAnchorBodyStates() {
Anchor anchor = new Anchor(stack, request, response);
// Test expected default results for: usesBody(), escapeHtmlBody().
assertTrue("Anchor default usesBody not true ?", anchor.usesBody());
assertTrue("Anchor default htmlEscapeBody not true ?", anchor.escapeHtmlBody());
anchor.setEscapeHtmlBody(false);
assertFalse("Anchor htmlEscapeBody not false after set false ?", anchor.escapeHtmlBody());
anchor.setEscapeHtmlBody(true);
assertTrue("Anchor htmlEscapeBody not true after set true ?", anchor.escapeHtmlBody());
}

/**
* Test the behaviour for Submit body state methods.
*/
public void testAnchortBodyStates() {
Submit submit = new Submit(stack, request, response);
// Test expected default results for: usesBody(), escapeHtmlBody().
assertTrue("Submit default usesBody not true ?", submit.usesBody());
assertTrue("Submit default htmlEscapeBody not true ?", submit.escapeHtmlBody());
submit.setEscapeHtmlBody(false);
assertFalse("Submit htmlEscapeBody not false after set false ?", submit.escapeHtmlBody());
submit.setEscapeHtmlBody(true);
assertTrue("Submit htmlEscapeBody not true after set true ?", submit.escapeHtmlBody());
}
}
63 changes: 63 additions & 0 deletions core/src/test/java/org/apache/struts2/views/jsp/ui/AnchorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,67 @@ private AnchorTag createTag() throws JspException {
return tag;
}

/**
* Test anchor tag body supported
*
* @throws Exception
*/
public void testSimpleWithBody() throws Exception {
createAction();

AnchorTag tag = createTag();
tag.setHref("a");

StrutsBodyContent body = new StrutsBodyContent(null);
body.print("normal body text with nothing to escape");
tag.setBodyContent(body);

tag.doStartTag();
tag.doEndTag();

verifyResource("href-3.txt");
}

/**
* Test that by default anchor tag body is HTML-escaped.
*
* @throws Exception
*/
public void testSimpleWithBodyHTMLEscaped() throws Exception {
createAction();

AnchorTag tag = createTag();
tag.setHref("a");

StrutsBodyContent body = new StrutsBodyContent(null);
body.print("should HTML escape: < & >");
tag.setBodyContent(body);

tag.doStartTag();
tag.doEndTag();

verifyResource("href-4.txt");
}

/**
* Test that with htmlEscapeBody false anchor tag body is not HTML-escaped.
*
* @throws Exception
*/
public void testSimpleWithBodyNotHTMLEscaped() throws Exception {
createAction();

AnchorTag tag = createTag();
tag.setHref("a");
tag.setEscapeHtmlBody(false);

StrutsBodyContent body = new StrutsBodyContent(null);
body.print("should not HTML escape: < & >");
tag.setBodyContent(body);

tag.doStartTag();
tag.doEndTag();

verifyResource("href-5.txt");
}
}
Loading

0 comments on commit 2d23357

Please sign in to comment.