So I am using Spring 5.3.xx right now with a simple ftl file (i have simplified it for now)
<#import "/spring.ftl" as spring/>
<@spring.formInput path="${textInputName}" attributes='maxlength="1024" '/>
with some simple free-marker settings from context.xml
<property name="freemarkerSettings">
<props>
<prop key="datetime_format">yyyy-MM-dd</prop>
<prop key="url_escaping_charset">UTF-8</prop>
</props>
</property>
And i have enable escaping in web.xml
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
I am facing an issue with double escaping. A simple value like "abc"
in input
will be render as "abc"
in input
value on a page reload.
ftl
since the spring.ftl
uses #ftl output_format="HTML"
and that causes autoEscape
below to be set to true
Are we suppose to turn off escaping from spring from web.xml
(which don't seem safe to me) or is it something else that I missed ?
ref: https://github.com/spring-projects/spring-framework/issues/19306
TLDR; just leave the defaultHtmlEscape
context parameter unset, and don't use some ancient Spring/JSTL version, then both JSP and FreeMarker will escape HTML form values exactly once. Especially if you don't use JSP, you have no much to fear, as spring.formInput
is hard-wired to do HTML escaping in spring.ftl
.
Longer version...
My experience is that, at least with Spring 5.2.3 (comes with JSTL 1.2.7), the JSP form:input
tag escapes by default, if you don't set the defaultHtmlEscape
context parameter at all. Also, the FreeMarker spring.formInput
only escapes via ${...}
FreeMarker auto-escaping then, not with the JSTL binding escaping mechanism. So by default both JSP and FreeMarker escapes exactly once.
OTOH if you set defaultHtmlEscape
to anything (true
or false
), one of the two (JSP or FreeMarker form support) will be broken.
But, if there's some company policy that requires you to have defaultHtmlEscape=true
, then you can do this workaround:
<#import "/spring.ftl" as spring/>
<#assign htmlEscape = false in spring>
...
<@spring.formInput "user.name" />
There, <#assign htmlEscape = false in spring>
disables the JSTL binding escaping for this response generation only, but spring.formInput
will still do its own escaping.
Update: There's a caveat with <#assign htmlEscape = false in spring>
. <@spring.message ... />
is not affected by it, but it's affected by defaultHtmlEscape
. If defaultHtmlEscape
is not set, or it's set to false
the message is not escaped. If defaultHtmlEscape
is set to true
, the message is escaped, and you can't avoid that (as far as you are using that macro). But there's no double escaping.