Hi Daniel,

thank you for your answer. 

The real usage is a little bit different but with the same result. We're using 
Spring in our software and added a macro to simplify and unify the usage of the 
spring.messageText and spring.messageArgs macros. And since our messageKeys 
could include HTML we set the outputformat to plaintext (default is HTML).

<#outputformat "plainText">
  <#macro message key args=[]>
    <#compress>
      <#if key?has_content>
        <#if args?has_content>
          <#local messageText><@spring.messageArgs key args/></#local>
        <#else>
          <#local messageText><@spring.message key/></#local>
        </#if>
        ${messageText}
      </#if>
    </#compress>
  </#macro>
</#outputformat>

But we also need this as a return value for other usecases, so we added a small 
wrapper as function:

<#outputformat "plainText">
<#function getMessage key args=[]>
  <#local result><@message key=key args=args /></#local>
  <#return result />
</#function>
</#outputformat>

And this causes the problem with the escaping, since it wasn't clear to us that 
the output format is fixed.

--Michael

-----Ursprüngliche Nachricht-----
Von: Daniel Dekany [mailto:ddek...@apache.org] 
Gesendet: Montag, 9. April 2018 16:14
An: Riehemann, Michael <dev@freemarker.apache.org>
Betreff: Re: Autoescaping

Output formats works the same with both #function and #macro. What causes the 
difference in your case is that you *call* another macro from that function. 
You could call it from a macro as well with similar conclusion, but you have 
printed the output directly there.
The output format of the body of the called macro is fixed on parse time. 
Imagine it as if the parser (where parsing happens when the template is first 
loaded, earlier than template execution), it modifies ${foo} to 
${foo?esc('HTML')} for you (it doesn't, but it's something similar). It's not 
dynamic. It saves you typing and prevents human errors exploitable for XSS 
attack. See also this from the page your have linked:

  Basically, each position in a template has an associated output
  format, and as you saw above, it might not be the same everywhere in
  the template. This association sticks to the positions and won't
  change as the template executes. So if, for example, you call a
  macro from inside an outputformat block and the called macro is
  defined outside that block, it won't get the output format of it.
  Or, if you have a macro that's defined in a template with HTML
  output format, no mater from where you call it, that macro will
  always execute with HTML output format. This is like if you were
  coloring each characters of the template files by output format in
  the text editor, and then later when the templates are executed, it
  only considers the color of the statement being executed. This gives
  you firm control over the output format and hence escaping; you
  don't have to consider the possible execution paths that can lead to
  a point.

Also, I'm curious what use case do you have for dynamic escaping. I mean, I see 
your example, why, in the real world do you need something like that?


Monday, April 9, 2018, 2:44:36 PM, Riehemann, Michael wrote:

> Hi Freemarker Devs,
>
> I have a question about the Autoescaping and the outputformat, 
> https://freemarker.apache.org/docs/dgui_misc_autoescaping.html
>
> Examplecode:
>
> <#ftl output_format="HTML">
>
> <#outputformat "plainText">
> <#function testFunction>
> <#local result><@testMacro /></#local> <#return result /> </#function> 
> </#outputformat>
>
> <#outputformat "plainText">
> <#macro testMacro>
> &
> </#macro>
> </#outputformat>
>
> Test Function: ${testFunction()}
> Test Macro: <@testMacro/>
>
> Output:
>
> Test Function: &amp;
> Test Macro: &
>
> It looks like outputformat is not working surrounding a function.
> The simplest fix is to add ?no_esc to the call:
> ${testFunction()?no_esc}
>
> But we have a lot of calls of this function and don't want to change all 
> templates.
>
> So I tried this code (without outputformat):
>
> <#ftl output_format="HTML">
>
> <#function testFunction>
> <#local result><@testMacro /></#local> <#return result /> </#function>
>
> <#outputformat "plainText">
> <#macro testMacro>
> &
> </#macro>
> </#outputformat>
>
> Test Function: ${testFunction()}
> Test Macro: <@testMacro/>
>
> Output:
>
> Test Function: &
> Test Macro: &
>
> Why does it work without the ouputformat surrounding the function?
> Or maybe, why does the outputformat do the opposite to the function?
>
> Thank you,
> Michael Riehemann

--
Thanks,
 Daniel Dekany

Reply via email to