This page contains information about advanced HTML encoding for Confluence plugins.
In some cases a method may return a collection of values, each of which contain HTML markup to be treated literally in a Velocity template. If a collection returning method is marked as HtmlSafe
, then all of its members will be treated as HtmlSafe
as well should they be written to a Velocity template.
More precisely, a value retrieved from a HtmlSafe
collection will be treated as HtmlSafe
in the following situations:
java.util.List#get(index)
java.util.Map#get(key)
java.util.Collection#iterator()
(as is the case when a collection is used with the Velocity #foreach
statement.)HtmlFragment
One of the things that has become painfully obvious in the implementation of this system is the inadequacy of the String
class for returning markup. The need for a HtmlSafe
annotation is only necessary because a String
return type does not convey any information about the data returned other than it is a sequence of characters. The com.atlassian.confluence.velocity.htmlsafe.HtmlFragment
class is a type that can be used to indicate that the toString()
method of a particular object returns markup to be interpreted as literal HTML during rendering.
1 2HtmlFragment aHtmlFragment = new HtmlFragment("<span>This string contains literal HTML</span">); HtmlFragment anotherHtmlFragment = new HtmlFragment(new MyHtmlClass());
The HtmlFragment
class' toString()
method delegates to the wrapped object's toString()
method and will be treated as being safe for use in HTML templates. This is useful for adding your own HtmlSafe
values directly to a Velocity context or as a return type for methods returning HTML markup.
VelocityUtils
HTML detection heuristicThe com.atlassian.confluence.utils.VelocityUtils
class defines methods of the form getRenderedTemplate
for
convenient rendering of a template to a String
. Unfortunately the only information available to this mechanism
is the template name and Velocity context, neither of which indicate directly whether the template is to be used
for HTML output. It is using HTML encoding by default, unless you explicitly opt-out using the #disableAntiXss()
directive. Opting out is recommended only for troubleshooting purposes.
PossibleIncorrectHtmlEncodingEventHandler
To help track down any Velocity reference that might be encoded incorrectly, Confluence attaches a logging event listener to the Velocity context. This event listener will print the reference name and the template that contains the reference if the reference value contains HTML like markup (either element markup or encoded entities) but the reference hasn't been marked as HTML safe. Naturally some values may contain HTML markup that are not meant to be interpreted as literal HTML, as is the case in HTML injection attacks.
This event listener will only be active if the log4j logger category com.atlassian.confluence.velocity.htmlsafe.PossibleIncorrectHtmlEncodingEventHandler
has been set to log at INFO
.
Confluence employs a specialisation of Velocity's pluggable, federated introspection strategy known as an Uberspect
. The Velocity runtime delegates all method calls, property accesses and iterator strategy retrieval via the configured uberspect. The default Velocity uberspect implementation provides all of the facilities to call methods and access properties of objects in the Velocity context by making heavy use of the Java reflection API. It also provides the mechanism for case insensitive property access, Velocity's map getter syntactic sugar and uses an internal introspection cache to optimise performance.
To enable the tracking of values retrieved from HtmlSafe
sources, Confluence is configured to use a specialised uberspect that boxes any ReturnValueAnnotation
annotations with the method return value. Return values from method calls that do not have any such annotations are treated exactly as before. Of course any of these uberspect boxed values may be subsequently used as arguments or targets of other method calls, so the annotation boxing uberspect is also responsible for unboxing these values before a method is executed, providing a mostly transparent operation.
For those developers who are more interested in the exact implementation details, you will want to examine the source of the classes in the new com.atlassian.confluence.velocity.introspection
package, with the AnnotationBoxingUberspect
being the best place to start.
Rate this page: