Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Qute - escape expressions in HTML by default #6194

Merged
merged 1 commit into from Dec 16, 2019

Conversation

mkouba
Copy link
Contributor

@mkouba mkouba commented Dec 16, 2019

What this PR does?

  1. For HTML templates ',",<, > and & are escaped by default
  2. It's possilble to use raw and safe extension methods for String to "unescape" the value; ie. {foo.myString.raw}
  3. RawString is never escaped
  4. Template now has an optional Variant

@mkouba mkouba added the area/qute The template engine label Dec 16, 2019
@mkouba mkouba added this to the 1.2.0 milestone Dec 16, 2019
@mkouba mkouba requested review from FroMage and gsmet December 16, 2019 11:30
@gsmet
Copy link
Member

gsmet commented Dec 16, 2019

I would lean towards including that one into 1.1. I'm not very happy to release a templating engine without default escaping. WDYT?

Any chance you could add some documentation about this behavior?

@mkouba
Copy link
Contributor Author

mkouba commented Dec 16, 2019

I would lean towards including that one into 1.1

I thought that 1.1 is released already ;-). If it's easy to backport (and I believe it should be because we did not change in Qute since 1.1 code freeze) then +1.

Any chance you could add some documentation about this behavior?

+1, I'll mention this in the docs.

@mkouba
Copy link
Contributor Author

mkouba commented Dec 16, 2019

Hm, I've been thinking about the implementation and it's very likely not correct. The ResultMapper that performs escaping is only applied to expression values that resolve to a String. However, the escaping should be performed after the value is converted to String.

I'll need to change the default ResultMapper to convert everything to String first (if needed) and then escape the value. Custom ResultMapper can be still implemented if it's using higher getPriority().

- resolves quarkusio#6155
- API changes:
 - introduce TemplateLocator
 - add Template#getVariant()
Copy link
Member

@FroMage FroMage left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

builder.addValueResolver(ValueResolvers.rawResolver());

// Escape some characters for HTML templates
Escaper htmlEscaper = Escaper.builder().add('"', "&quot;").add('\'', "&#39;")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Override
public boolean appliesTo(Origin origin, Object result) {
return !(result instanceof RawString)
&& origin.getVariant().filter(EngineProducer::requiresDefaultEscaping).isPresent();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing in the future we'll need to turn this into an SPI for custom escaping of other variant content types. But it can wait.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 for proper SPI... in the furure ;-).

// Escape some characters for HTML templates
Escaper htmlEscaper = Escaper.builder().add('"', "&quot;").add('\'', "&#39;")
.add('&', "&amp;").add('<', "&lt;").add('>', "&gt;").build();
builder.addResultMapper(new ResultMapper() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we sure it's the last mapper? I don't think users should be able to register mappers after this one, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mappers with higher priority are tried first. So if a user wants to map some object then the priority should be > io.quarkus.qute.WithPriority.DEFAULT_PRIORITY.

} else if (suffix.equalsIgnoreCase(".json")) {
return "application/json";
return Variant.APPLICATION_JSON;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We support JSON but I didn't see any escaper for JSON.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, actually we don't support JSON ATM ;-). TBD


public final static String TEXT_HTML = "text/html";
public final static String TEXT_PLAIN = "text/plain";
public final static String TEXT_XML = "text/xml";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that XML can be application/xml in many cases, but I don't think it matters here. https://www.ietf.org/rfc/rfc2376.txt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I know. But in our case we guess the content type from a file suffix and set always text/xml for *.xml templates.

}

@Test
public void testRawStringRevolver() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public void testRawStringRevolver() {
public void testRawStringResolver() {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be blind but what's the suggested change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Revolver != resolver 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it's confirmed. I'm blind...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most beautiful typo I've seen so far :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm very good at typos!

@gsmet gsmet merged commit 3f30c8d into quarkusio:master Dec 16, 2019
@gsmet
Copy link
Member

gsmet commented Dec 16, 2019

Let's get moving, we can adjust later but we need at least some escaping in 1.1.

@gsmet gsmet modified the milestones: 1.2.0, 1.1.0.Final Dec 16, 2019
@gsmet gsmet removed the backport? label Dec 16, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/qute The template engine
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Handle escaping in Qute
4 participants