Search code examples
struts2escapingfreemarkerstruts-tags

Why escape in Struts tags doesn't work after upgrade to Struts 6.3.0.2


If I have a Struts 2 tag as below

<s:optiontransferselect
   leftTitle="<strong>All system groups</strong>">
</s:optiontransferselect> 

The resulted outcome should be All system groups, but it appears with strong tags with escapeHTML, I tried setting struts.ui.escapeHtmlBody to false but doesn't work.


Solution

  • The struts.ui.escapeHtmlBody setting allows only switch escape option in the body of the tag. Such as if you use nested tags and allows to escape all the tags used in the body of the tag. It doesn't allow to turn of escaping values of the Struts tags attributes.

    The content of the Struts tags is generated using Freemarker. The latest version of Struts use its feature for auto-escape html output which is enabled by default in Freemarker.

    Disabling auto escaping

    For a single interpolation you can disable auto-escaping with ?no_esc:

    TEMPLATE
    <#-- Let's assume we have "HTML" output format by default. -->
    ${'<b>test</b>'}  <#-- prints: &lt;b&gt;test&lt;/b&gt; -->
    ${'<b>test</b>'?no_esc}  <#-- prints: <b>test</b> -->
    

    You can also disable auto escaping for a whole section with the noautoesc directive:

    TEMPLATE
    ${'&'}  <#-- prints: &amp; -->
    <#noautoesc>
      ${'&'}  <#-- prints: & -->
      ...
      ${'&'}  <#-- prints: & -->
    </#noautoesc>
    ${'&'}  <#-- prints: &amp; -->
    

    Just like outputformat, this only applies to the part that's literally inside the block ("coloring" logic).

    Auto-escaping can also be disabled for the whole template in the ftl header. It can then be re-enabled for a section with the autoesc directive:

    TEMPLATE
    <#ftl autoesc=false>
    ${'&'}  <#-- prints: & -->
    <#autoesc>
      ${'&'}  <#-- prints: &amp; -->
      ...
      ${'&'}  <#-- prints: &amp; -->
    </#autoesc>
    ${'&'}  <#-- prints: & -->
    

    You can also force escaping for an individual interpolation when escaping is disabled, with ?esc:

    TEMPLATE
    <#ftl autoesc=false>
    ${'&'}  <#-- prints: & -->
    ${'&'?esc}  <#-- prints: &amp; -->
    

    Naturally, both autoesc and ?esc works inside noautoesc blocks too.


    Now you can trick a Freemarker to disable auto-escape for the single value

    <s:optiontransferselect
      leftTitle="%{"'<strong>All system groups</strong>'?no_esc"}" /> 
     
    

    Another option is to use custom template to customize the html output using a custom Freemarker template where you can turn off auto-escape. More information about it you can find in Themes and templates.