Commit eb8e2653 authored by Woonsan Ko's avatar Woonsan Ko

HSTTWO-4310: replace message value only with escaping option by default, not the whole.

(cherry picked from commit adc26529)
parent fdb69ac5
......@@ -35,7 +35,6 @@ import org.apache.commons.lang.LocaleUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.taglibs.standard.tag.common.fmt.BundleSupport;
import org.hippoecm.hst.resourcebundle.ResourceBundleUtils;
import org.hippoecm.hst.util.HstRequestUtils;
import org.hippoecm.hst.utils.MessageUtils;
import org.hippoecm.hst.utils.TagUtils;
......@@ -54,7 +53,7 @@ public class MessagesReplaceTag extends BodyTagSupport {
protected String variablePrefix;
protected String variableSuffix;
protected Character escapeChar;
protected Boolean escapeXml = true;
protected boolean escapeMessageXml = true;
@Override
public int doStartTag() throws JspException{
......@@ -97,11 +96,7 @@ public class MessagesReplaceTag extends BodyTagSupport {
if (bundle != null) {
textContent = MessageUtils.replaceMessagesByBundle(bundle, textContent,
variablePrefix, variableSuffix,
escapeChar);
}
if (escapeXml) {
textContent = HstRequestUtils.escapeXml(textContent);
escapeChar, isEscapeMessageXml());
}
if (var == null) {
......@@ -130,7 +125,7 @@ public class MessagesReplaceTag extends BodyTagSupport {
basename = null;
locale = null;
localeString = null;
escapeXml = true;
escapeMessageXml = true;
}
@Override
......@@ -202,12 +197,12 @@ public class MessagesReplaceTag extends BodyTagSupport {
this.escapeChar = escapeChar;
}
public Boolean getEscapeXml() {
return escapeXml;
public boolean isEscapeMessageXml() {
return escapeMessageXml;
}
public void setEscapeXml(Boolean escapeXml) {
this.escapeXml = escapeXml;
public void setEscapeMessageXml(boolean escapeMessageXml) {
this.escapeMessageXml = escapeMessageXml;
}
protected LocalizationContext getLocalizationContext() {
......
/*
* Copyright 2014-2014 Hippo B.V. (http://www.onehippo.com)
* Copyright 2014-2018 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -22,6 +22,7 @@ import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrLookup;
import org.apache.commons.lang.text.StrSubstitutor;
import org.hippoecm.hst.resourcebundle.ResourceBundleUtils;
import org.hippoecm.hst.util.HstRequestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -55,7 +56,7 @@ public class MessageUtils {
* @return replaced string by the values found in the given resource bundle
*/
public static String replaceMessages(String basename, String text) {
return replaceMessages(basename, text, null, null, null);
return replaceMessages(basename, text, null, null, null, false);
}
/**
......@@ -68,7 +69,7 @@ public class MessageUtils {
*/
public static String replaceMessages(String basename, String text, String variablePrefix,
String variableSuffix) {
return replaceMessages(basename, text, variablePrefix, variableSuffix, null);
return replaceMessages(basename, text, variablePrefix, variableSuffix, null, false);
}
/**
......@@ -82,6 +83,21 @@ public class MessageUtils {
*/
public static String replaceMessages(String basename, String text, String variablePrefix,
String variableSuffix, Character escapeChar) {
return replaceMessages(basename, text, variablePrefix, variableSuffix, escapeChar, false);
}
/**
* Replaces the given text by looking up values from the resolved resource bundle by the <code>basename</code>.
* @param basename resource bundle base name
* @param text text to replace
* @param variablePrefix variable reference prefix. "${" by default.
* @param variableSuffix variable reference suffix. "}" by default.
* @param escapeChar escape character which can be put just before a variable reference to ignore the expression.
* @param escapeMessageXml whether or not to escape a message value having &amp;,&gt;,&lt;,", and '.
* @return replaced string by the values found in the given resource bundle
*/
public static String replaceMessages(String basename, String text, String variablePrefix,
String variableSuffix, Character escapeChar, boolean escapeMessageXml) {
ResourceBundle bundle = null;
try {
......@@ -94,7 +110,7 @@ public class MessageUtils {
return text;
}
return replaceMessagesByBundle(bundle, text, variablePrefix, variableSuffix, escapeChar);
return replaceMessagesByBundle(bundle, text, variablePrefix, variableSuffix, escapeChar, escapeMessageXml);
}
/**
......@@ -104,7 +120,7 @@ public class MessageUtils {
* @return replaced string by the values found in the given resource bundle
*/
public static String replaceMessagesByBundle(ResourceBundle bundle, String text) {
return replaceMessagesByBundle(bundle, text, null, null, null);
return replaceMessagesByBundle(bundle, text, null, null, null, false);
}
/**
......@@ -117,7 +133,7 @@ public class MessageUtils {
*/
public static String replaceMessagesByBundle(ResourceBundle bundle, String text, String variablePrefix,
String variableSuffix) {
return replaceMessagesByBundle(bundle, text, variablePrefix, variableSuffix, null);
return replaceMessagesByBundle(bundle, text, variablePrefix, variableSuffix, null, false);
}
/**
......@@ -131,11 +147,26 @@ public class MessageUtils {
*/
public static String replaceMessagesByBundle(ResourceBundle bundle, String text, String variablePrefix,
String variableSuffix, Character escapeChar) {
return replaceMessagesByBundle(bundle, text, variablePrefix, variableSuffix, escapeChar, false);
}
/**
* Replaces the given text by looking up values from the given resource bundle.
* @param bundle resource bundle
* @param text text to replace
* @param variablePrefix variable reference prefix. "${" by default.
* @param variableSuffix variable reference suffix. "}" by default.
* @param escapeChar escape character which can be put just before a variable reference to ignore the expression.
* @param escapeMessageXml whether or not to escape a message value having &amp;,&gt;,&lt;,", and '.
* @return replaced string by the values found in the given resource bundle
*/
public static String replaceMessagesByBundle(ResourceBundle bundle, String text, String variablePrefix,
String variableSuffix, Character escapeChar, boolean escapeMessageXml) {
if (bundle == null) {
throw new IllegalArgumentException("The bundle must not be null.");
}
StrSubstitutor subst = new StrSubstitutor(new ResourceBundleVariableResolver(bundle),
StrSubstitutor subst = new StrSubstitutor(new ResourceBundleVariableResolver(bundle, escapeMessageXml),
StrSubstitutor.DEFAULT_PREFIX,
StrSubstitutor.DEFAULT_SUFFIX,
DEFAULT_ESCAPE);
......@@ -161,16 +192,24 @@ public class MessageUtils {
*/
private static class ResourceBundleVariableResolver extends StrLookup {
private ResourceBundle bundle;
private final ResourceBundle bundle;
private final boolean escapeMessageXml;
ResourceBundleVariableResolver(ResourceBundle bundle) {
ResourceBundleVariableResolver(final ResourceBundle bundle, final boolean escapeMessageXml) {
this.bundle = bundle;
this.escapeMessageXml = escapeMessageXml;
}
@Override
public String lookup(String key) {
try {
return bundle.getString(key);
String value = bundle.getString(key);
if (escapeMessageXml) {
value = HstRequestUtils.escapeXml(value);
}
return value;
} catch (MissingResourceException e) {
return "???" + key + "???";
}
......
......@@ -1099,11 +1099,11 @@
</attribute>
<attribute>
<description>
Whether or not to escape &amp;,&gt;,&lt;,", and '. When escapeXml = true, the
replaced text output can be safely used in a markup result page.
By default escapeXml is set to true.
Whether or not to escape a message value having &amp;,&gt;,&lt;,", and '. When escapeMessageXml = true, the
replaced message text can be safely used as a tag attribute (e.g, href, src, etc.) value.
By default escapeMessageXml is set to true.
</description>
<name>escapeXml</name>
<name>escapeMessageXml</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>java.lang.Boolean</type>
......
/*
* Copyright 2014 Hippo B.V. (http://www.onehippo.com)
* Copyright 2014-2018 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -54,6 +54,7 @@ public class MessagesReplaceTagTest {
final Map<String, String> bundleContent = new HashMap<>();
bundleContent.put("example.title", "<script>alert('hi there')</script>");
bundleContent.put("example.subtitle", "<b>howdy?</b>");
bundleContent.put("example.introduction", "This is an example introduction.");
bundleContent.put("example.body", "<h1>Hello, World!</h1><p>This is the body.</p>");
......@@ -66,12 +67,13 @@ public class MessagesReplaceTagTest {
@Test
public void testMessagesReplaceTagOutputWithoutEscaping() throws Exception {
messagesReplaceTag.setEscapeXml(false);
messagesReplaceTag.setEscapeMessageXml(false);
messagesReplaceTag.doStartTag();
final MockBodyContent bodyContent =
new MockBodyContent(
"<p>${example.introduction}</p>\n"
"<h2>${example.subtitle}</h2>\n"
+ "<p>${example.introduction}</p>\n"
+ "<div>${example.body}</div>",
response);
......@@ -79,8 +81,9 @@ public class MessagesReplaceTagTest {
messagesReplaceTag.doEndTag();
final String[] lines = StringUtils.split(response.getContentAsString(), "\n");
assertEquals("<p>This is an example introduction.</p>", lines[0]);
assertEquals("<div><h1>Hello, World!</h1><p>This is the body.</p></div>", lines[1]);
assertEquals("<h2><b>howdy?</b></h2>", lines[0]);
assertEquals("<p>This is an example introduction.</p>", lines[1]);
assertEquals("<div><h1>Hello, World!</h1><p>This is the body.</p></div>", lines[2]);
}
@Test
......@@ -89,16 +92,16 @@ public class MessagesReplaceTagTest {
final MockBodyContent bodyContent =
new MockBodyContent(
"${example.title}\n"
+ "${example.introduction}",
"<h1>${example.title}</h1>\n"
+ "<div>${example.introduction}</div>",
response);
messagesReplaceTag.setBodyContent(bodyContent);
messagesReplaceTag.doEndTag();
final String[] lines = StringUtils.split(response.getContentAsString(), "\n");
assertEquals(HstRequestUtils.escapeXml("<script>alert('hi there')</script>"), lines[0]);
assertEquals(HstRequestUtils.escapeXml("This is an example introduction."), lines[1]);
assertEquals("<h1>" + HstRequestUtils.escapeXml("<script>alert('hi there')</script>") + "</h1>", lines[0]);
assertEquals("<div>" + HstRequestUtils.escapeXml("This is an example introduction.") + "</div>", lines[1]);
}
}
/*
* Copyright 2014-2014 Hippo B.V. (http://www.onehippo.com)
* Copyright 2014-2018 Hippo B.V. (http://www.onehippo.com)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -15,14 +15,15 @@
*/
package org.hippoecm.hst.utils;
import static org.junit.Assert.assertEquals;
import java.util.ResourceBundle;
import org.hippoecm.hst.resourcebundle.ResourceBundleUtils;
import org.hippoecm.hst.util.HstRequestUtils;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* TestMessageUtils
*/
......@@ -54,6 +55,14 @@ public class TestMessageUtils {
private static final String DOLLAR_SIGN_TEST_EXPECTED_MESSAGE =
"The annual payment is $500.";
private static final String ESCAPABLE_GREETING_VALUE = "<script>alert('hi there!');</script>";
private static final String ESCAPABLE_TEST_MESSAGE_EXPR = "<h1>${escapable.greeting}</h1>";
private static final String EXPECTED_UNESCAPED_TEST_MESSAGE = "<h1>" + ESCAPABLE_GREETING_VALUE + "</h1>";
private static final String EXPECTED_ESCAPED_TEST_MESSAGE = "<h1>" + HstRequestUtils.escapeXml(ESCAPABLE_GREETING_VALUE) + "</h1>";
@Before
public void before() throws Exception {
bundle = ResourceBundleUtils.getBundle(BUNDLE_NAME, null);
......@@ -140,5 +149,16 @@ public class TestMessageUtils {
assertEquals(DOLLAR_SIGN_TEST_EXPECTED_MESSAGE, replacedMessage);
}
@Test
public void testEscaping() throws Exception {
String replacedMessage = MessageUtils.replaceMessages(BUNDLE_NAME, ESCAPABLE_TEST_MESSAGE_EXPR, "${", "}", '\\', true);
assertEquals(EXPECTED_ESCAPED_TEST_MESSAGE, replacedMessage);
replacedMessage = MessageUtils.replaceMessages(BUNDLE_NAME, ESCAPABLE_TEST_MESSAGE_EXPR, "${", "}", '\\', false);
assertEquals(EXPECTED_UNESCAPED_TEST_MESSAGE, replacedMessage);
replacedMessage = MessageUtils.replaceMessages(BUNDLE_NAME, ESCAPABLE_TEST_MESSAGE_EXPR, "${", "}", '\\');
assertEquals(EXPECTED_UNESCAPED_TEST_MESSAGE, replacedMessage);
}
}
#
# Copyright 2014-2014 Hippo B.V. (http://www.onehippo.com)
# Copyright 2014-2018 Hippo B.V. (http://www.onehippo.com)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
......@@ -18,3 +18,4 @@ ns1.target.environment.url=http://web24.ns1.com:9090
header.search.form.action.path.en=/PS/en/Redirect.do
header.search.form.action.path.fr=/PS/fr/Redirect.do
annual.payment=500
escapable.greeting=<script>alert('hi there!');</script>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment