Skip to content

Commit

Permalink
Qute - make the set of escaped content-types configurable
Browse files Browse the repository at this point in the history
- introduce the quarkus.qute.escape-content-types configuration property
- resolves quarkusio#21731
  • Loading branch information
mkouba committed Nov 26, 2021
1 parent f6f8077 commit af991ad
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 11 deletions.
2 changes: 2 additions & 0 deletions docs/src/main/asciidoc/qute-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -430,6 +430,8 @@ If you need to render the unescaped value:
<1> `title` that resolves to `Expressions & Escapes` will be rendered as `Expressions &amp;amp; Escapes`
<2> `paragraph` that resolves to `<p>My text!</p>` will be rendered as `<p>My text!</p>`

TIP: By default, a template with one of the following content types is escaped: `text/html`, `text/xml`, `application/xml` and `application/xhtml+xml`. However, it's possible to extend this list via the `quarkus.qute.escape-content-types` configuration property.

[[virtual_methods]]
==== Virtual Methods

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ public class EscapingTest {
.addAsResource(new StringAsset("{text} {other} {text.raw} {text.safe} {item.foo}"),
"templates/foo.html")
.addAsResource(new StringAsset("{item} {item.raw}"),
"templates/item.html")
"templates/item.xhtml")
.addAsResource(new StringAsset("{text} {other} {text.raw} {text.safe} {item.foo}"),
"templates/bar.txt")
.addAsResource(new StringAsset("{@java.lang.String text}{text} {text.raw} {text.safe}"),
"templates/validation.html"));
"templates/validation.html"))
.overrideConfigKey("quarkus.qute.content-types.xhtml", "application/xhtml+xml")
.overrideConfigKey("quarkus.qute.suffixes", "qute.html,qute.txt,html,txt,xhtml");

@Inject
Template foo;
Expand Down Expand Up @@ -67,6 +69,13 @@ public void testEngineParse() {
assertEquals("&lt;div&gt; <div>",
engine.parse("{text} {text.raw}",
new Variant(Locale.ENGLISH, "text/html", "UTF-8")).data("text", "<div>").render());
assertEquals("&lt;div&gt; <div>",
engine.parse("{text} {text.raw}",
new Variant(Locale.ENGLISH, "application/xml", "UTF-8")).data("text", "<div>").render());
assertEquals("&lt;div&gt; <div>",
engine.parse("{text} {text.raw}",
new Variant(Locale.ENGLISH, "application/xhtml+xml;charset=UTF-8", "UTF-8")).data("text", "<div>")
.render());
}

@TemplateData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,8 @@ public EngineProducer(QuteContext context, QuteConfig config, QuteRuntimeConfig
}
}

// Escape some characters for HTML templates
builder.addResultMapper(new HtmlEscaper());
// Escape some characters for HTML/XML templates
builder.addResultMapper(new HtmlEscaper(List.copyOf(config.escapeContentTypes)));

// Fallback reflection resolver
builder.addValueResolver(new ReflectionValueResolver());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,11 @@ public class QuteConfig {
@ConfigItem(defaultValue = "<alias_>")
public String iterationMetadataPrefix;

/**
* The list of content types for which the {@code '}, {@code "}, {@code <}, {@code >} and {@code &} characters are escaped
* if a template variant is set.
*/
@ConfigItem(defaultValue = "text/html,text/xml,application/xml,application/xhtml+xml")
public List<String> escapeContentTypes;

}
Original file line number Diff line number Diff line change
Expand Up @@ -516,7 +516,7 @@ private Engine buildEngine(List<DevTemplatePathBuildItem> devTemplatePaths,
EngineBuilder builder = Engine.builder().addDefaults();

// Escape some characters for HTML templates
builder.addResultMapper(new HtmlEscaper());
builder.addResultMapper(new HtmlEscaper(List.of(Variant.TEXT_HTML)));

builder.strictRendering(true)
.addValueResolver(new ReflectionValueResolver())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package io.quarkus.qute;

import io.quarkus.qute.TemplateNode.Origin;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

public class HtmlEscaper implements ResultMapper {

private final List<String> escapedContentTypes;

public HtmlEscaper(List<String> escapedContentTypes) {
this.escapedContentTypes = escapedContentTypes;
}

@Override
public boolean appliesTo(Origin origin, Object result) {
if (result instanceof RawString) {
Expand Down Expand Up @@ -37,10 +44,17 @@ String escape(CharSequence value) {
return value.toString();
}

static boolean requiresDefaultEscaping(Variant variant) {
return variant.getContentType() != null
? (Variant.TEXT_HTML.equals(variant.getContentType()) || Variant.TEXT_XML.equals(variant.getContentType()))
: false;
private boolean requiresDefaultEscaping(Variant variant) {
String contentType = variant.getContentType();
if (contentType == null) {
return false;
}
for (String escaped : escapedContentTypes) {
if (contentType.startsWith(escaped)) {
return true;
}
}
return false;
}

private String doEscape(CharSequence value, int index, StringBuilder builder) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import io.quarkus.qute.TemplateNode.Origin;
import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import org.junit.jupiter.api.Test;
Expand All @@ -14,7 +15,7 @@ public class HtmlEscaperTest {

@Test
public void testAppliesTo() {
HtmlEscaper html = new HtmlEscaper();
HtmlEscaper html = new HtmlEscaper(List.of(Variant.TEXT_HTML));
Origin htmlOrigin = new Origin() {

@Override
Expand Down Expand Up @@ -53,7 +54,7 @@ public int getLine() {

@Test
public void testEscaping() throws IOException {
HtmlEscaper html = new HtmlEscaper();
HtmlEscaper html = new HtmlEscaper(List.of(Variant.TEXT_HTML));
assertEquals("Čolek", html.escape("Čolek"));
assertEquals("&lt;strong&gt;Čolek&lt;/strong&gt;", html.escape("<strong>Čolek</strong>"));
assertEquals("&lt;a&gt;&amp;link&quot;&#39;&lt;/a&gt;", html.escape("<a>&link\"'</a>"));
Expand Down

0 comments on commit af991ad

Please sign in to comment.