/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.util;
import com.liferay.portal.kernel.util.CharPool;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.junit.Assert;
import org.junit.Test;
/**
* @author Olaf Kock
* @author Neil Zhao Jin
*/
public class HtmlImplTest {
@Test
public void testBuildData() {
Assert.assertEquals(StringPool.BLANK, _htmlImpl.buildData(null));
Map<String, Object> data = new LinkedHashMap<>();
Assert.assertEquals(StringPool.BLANK, _htmlImpl.buildData(data));
data.put("key1", "value1");
Assert.assertEquals("data-key1=\"value1\" ", _htmlImpl.buildData(data));
data.put("key2", "value2");
Assert.assertEquals(
"data-key1=\"value1\" data-key2=\"value2\" ",
_htmlImpl.buildData(data));
}
@Test
public void testEscapeBlank() {
assertUnchangedEscape("");
}
@Test
public void testEscapeCaseSensitive() {
assertUnchangedEscape("CAPITAL lowercase Text");
}
@Test
public void testEscapeCSS() {
Assert.assertEquals("1", _htmlImpl.escapeCSS("1"));
Assert.assertEquals("\\27", _htmlImpl.escapeCSS("'"));
Assert.assertEquals("\\27 1", _htmlImpl.escapeCSS("'1"));
Assert.assertEquals("\\27a", _htmlImpl.escapeCSS("'a"));
}
@Test
public void testEscapeExtendedASCIICharacters() {
StringBuilder sb = new StringBuilder(256);
for (int i = 0; i < 256; i++) {
if (Character.isLetterOrDigit(i)) {
sb.append((char)i);
}
}
String value = sb.toString();
Assert.assertEquals(value, _htmlImpl.escape(value));
Assert.assertEquals(
value, _htmlImpl.escape(value, HtmlImpl.ESCAPE_MODE_ATTRIBUTE));
}
@Test
public void testEscapeHREF() {
Assert.assertNull(_htmlImpl.escapeHREF(null));
Assert.assertEquals(
StringPool.BLANK, _htmlImpl.escapeHREF(StringPool.BLANK));
Assert.assertEquals(
"javascript%3aalert('hello');",
_htmlImpl.escapeHREF("javascript:alert('hello');"));
Assert.assertEquals(
"data%3atext/html;base64,PHNjcmlwdD5hbGVydCgn" +
"dGVzdDMnKTwvc2NyaXB0Pg",
_htmlImpl.escapeHREF(
"data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaX" +
"B0Pg"));
assertUnchangedEscape("http://localhost:8080");
}
@Test
public void testEscapeHtmlAttributeMultiline() {
String original = "\tThis is\na multi-line\ntitle\r";
String escaped = _htmlImpl.escapeAttribute(original);
String extracted = _htmlImpl.extractText(escaped);
Assert.assertEquals(original, extracted);
}
@Test
public void testEscapeHtmlEncodingAmpersand() {
Assert.assertEquals("&", _htmlImpl.escape("&"));
}
@Test
public void testEscapeHtmlEncodingAmpersandInBetween() {
Assert.assertEquals("You & Me", _htmlImpl.escape("You & Me"));
}
@Test
public void testEscapeHtmlEncodingDoubleQuotes() {
Assert.assertEquals(
"<span class="test">Test</span>",
_htmlImpl.escape("<span class=\"test\">Test</span>"));
}
@Test
public void testEscapeHtmlEncodingGreaterThan() {
Assert.assertEquals(">", _htmlImpl.escape(">"));
}
@Test
public void testEscapeHtmlEncodingLessThan() {
Assert.assertEquals("<", _htmlImpl.escape("<"));
}
@Test
public void testEscapeHtmlEncodingQuotes() {
Assert.assertEquals(
"I'm quoting: "this is a quote"",
_htmlImpl.escape("I'm quoting: \"this is a quote\""));
}
@Test
public void testEscapeHtmlEncodingScriptTag() {
Assert.assertEquals("<script>", _htmlImpl.escape("<script>"));
}
@Test
public void testEscapeJS() throws ScriptException {
ScriptEngineManager scriptEngineManager = new ScriptEngineManager();
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(
"JavaScript");
String[] stringLiterals =
{"'", "\"", "\\", "\n", "\r", "\u2028", "\u2029"};
for (String stringLiteral : stringLiterals) {
String escaped = _htmlImpl.escapeJS(stringLiteral);
scriptEngine.eval(String.format("var result = '%1$s';", escaped));
Assert.assertEquals(stringLiteral, scriptEngine.get("result"));
}
}
@Test
public void testEscapeJSLink() {
Assert.assertEquals(
"javascript%3aalert('hello');",
_htmlImpl.escapeJSLink("javascript:alert('hello');"));
Assert.assertEquals(
"http://localhost:8080",
_htmlImpl.escapeJSLink("http://localhost:8080"));
}
@Test
public void testEscapeNoTrimmingPerformed() {
assertUnchangedEscape(" no trimming performed ");
}
@Test
public void testEscapeNull() {
Assert.assertNull(_htmlImpl.escape(null));
}
@Test
public void testEscapeNullChar() {
Assert.assertEquals(
StringPool.SPACE, _htmlImpl.escape(StringPool.NULL_CHAR));
}
@Test
public void testEscapeSemiColon() {
assertUnchangedEscape(";");
}
@Test
public void testEscapeText() {
assertUnchangedEscape("text");
}
@Test
public void testEscapeUTF8SupplementaryCharacter() {
assertUnchangedEscape("\uD83D\uDC31");
}
@Test
public void testEscapeWhitespace() {
assertUnchangedEscape(" ");
}
@Test
public void testExtraction() {
Assert.assertEquals(
"whitespace removal",
_htmlImpl.extractText(" whitespace \n <br/> removal "));
Assert.assertEquals(
"script removal",
_htmlImpl.extractText(
"script <script> test </script> removal"));
Assert.assertEquals(
"HTML attribute removal",
_htmlImpl.extractText(
"<h1>HTML</h1> <i>attribute</i> <strong>removal</strong>"));
Assert.assertEquals(
"onclick removal",
_htmlImpl.extractText(
"<div onclick=\"honk()\">onclick removal</div>"));
}
@Test
public void testGetAUICompatibleId() {
Assert.assertNull(_htmlImpl.getAUICompatibleId(null));
Assert.assertEquals(
StringPool.BLANK, _htmlImpl.getAUICompatibleId(StringPool.BLANK));
Assert.assertEquals(
"hello_20_world", _htmlImpl.getAUICompatibleId("hello world"));
Assert.assertEquals(
"hello__world", _htmlImpl.getAUICompatibleId("hello_world"));
StringBundler actualSB = new StringBundler(53);
for (int i = 0; i <= 47; i++) {
actualSB.append(StringPool.ASCII_TABLE[i]);
}
actualSB.append(":;<=>?@[\\]^_`{|}~");
actualSB.append(CharPool.DELETE);
actualSB.append(CharPool.NO_BREAK_SPACE);
actualSB.append(CharPool.FIGURE_SPACE);
actualSB.append(CharPool.NARROW_NO_BREAK_SPACE);
StringBundler expectedSB = new StringBundler(6);
expectedSB.append("_0__1__2__3__4__5__6__7__8__9__a__b__c__d__e__f_");
expectedSB.append("_10__11__12__13__14__15__16__17__18__19__1a__1b_");
expectedSB.append("_1c__1d__1e__1f__20__21__22__23__24__25__26__27_");
expectedSB.append("_28__29__2a__2b__2c__2d__2e__2f__3a__3b__3c__3d_");
expectedSB.append("_3e__3f__40__5b__5c__5d__5e____60__7b__7c__7d__7e_");
expectedSB.append("_7f__a0__2007__202f_");
Assert.assertEquals(
expectedSB.toString(),
_htmlImpl.getAUICompatibleId(actualSB.toString()));
}
@Test
public void testNewLineConversion() {
Assert.assertEquals(
"one<br />two<br />three<br /><br />five",
_htmlImpl.replaceNewLine("one\ntwo\r\nthree\n\nfive"));
}
@Test
public void testStripBetween() {
Assert.assertEquals(
"test-test-test", _htmlImpl.stripBetween("test-test-test", "test"));
}
@Test
public void testStripBetweenHtmlElement() {
Assert.assertEquals(
"test--test",
_htmlImpl.stripBetween(
"test-<honk>thiswillbestripped</honk>-test", "honk"));
}
@Test
public void testStripBetweenHtmlElementAcrossLines() {
Assert.assertEquals(
"works across lines",
_htmlImpl.stripBetween(
"works across <honk>\r\n a number of </honk> lines", "honk"));
}
@Test
public void testStripBetweenHtmlElementWithAttribute() {
Assert.assertEquals(
"test--test",
_htmlImpl.stripBetween(
"test-<honk attribute=\"value\">thiswillbestripped</honk>-test",
"honk"));
}
@Test
public void testStripBetweenMultipleOcurrencesOfHtmlElement() {
Assert.assertEquals(
"multiple occurrences, multiple indeed",
_htmlImpl.stripBetween(
"multiple <a>many</a>occurrences, multiple <a>HONK</a>indeed",
"a"));
}
@Test
public void testStripBetweenNull() {
Assert.assertNull(_htmlImpl.stripBetween(null, "test"));
}
@Test
public void testStripBetweenSelfClosedHtmlElement() {
Assert.assertEquals(
"self-closing <test/> is unhandled",
_htmlImpl.stripBetween(
"self-closing <test/> is unhandled", "test"));
}
@Test
public void testStripBetweenSelfClosedHtmlElementWithWhitespaceEnding() {
Assert.assertEquals(
"self-closing <test /> is unhandled",
_htmlImpl.stripBetween(
"self-closing <test /> is unhandled", "test"));
}
@Test
public void testStripComments() {
Assert.assertEquals("", _htmlImpl.stripComments("<!-- bla -->"));
}
@Test
public void testStripCommentsAccrossLines() {
Assert.assertEquals("test", _htmlImpl.stripComments("te<!-- \n -->st"));
}
@Test
public void testStripCommentsAfter() {
Assert.assertEquals(
"test", _htmlImpl.stripComments("test<!-- bla -->"));
}
@Test
public void testStripCommentsBefore() {
Assert.assertEquals(
"test", _htmlImpl.stripComments("<!-- bla -->test"));
}
@Test
public void testStripEmptyComments() {
Assert.assertEquals("", _htmlImpl.stripComments("<!---->"));
}
@Test
public void testStripHtml() {
Assert.assertEquals(
"Hello World!",
_htmlImpl.stripHtml(
"<html><body><h1>Hello World!</h1></body></html>"));
}
@Test
public void testStripHtmlWithScripTag() {
Assert.assertEquals(
"Hello World!",
_htmlImpl.stripHtml(
"<body>Hello<script>alert('xss');</script> World!</body>"));
}
@Test
public void testStripHtmlWithStyleTag() {
Assert.assertEquals(
"Hello World!",
_htmlImpl.stripHtml(
"<body>Hello<style>p{color:#000000}</style> World!</body>"));
}
@Test
public void testStripMultipleComments() {
Assert.assertEquals(
"test",
_htmlImpl.stripComments("te<!-- bla -->s<!-- bla bla -->t"));
}
@Test
public void testStripMultipleEmptyComments() {
Assert.assertEquals(
"test", _htmlImpl.stripComments("te<!-- --><!-- -->st"));
}
@Test
public void testStripNullComments() {
Assert.assertNull(_htmlImpl.stripComments(null));
}
@Test
public void testStripTag() {
char[] tag = {'t', 'a', 'g'};
Assert.assertEquals(
17, _htmlImpl.stripTag(tag, "<tag>Hello World!</tag>", 0));
Assert.assertEquals(
0, _htmlImpl.stripTag(tag, "<gat>Hello World!</gat>", 0));
}
@Test
public void testUnescapeDoubleHtmlEncoding() {
Assert.assertEquals(
""", _htmlImpl.unescape(_htmlImpl.escape(""")));
}
@Test
public void testUnescapeHtmlEncodingAmpersand() {
Assert.assertEquals("&", _htmlImpl.unescape("&"));
}
@Test
public void testUnescapeHtmlEncodingAmpersandInBetween() {
Assert.assertEquals("You & Me", _htmlImpl.unescape("You & Me"));
}
@Test
public void testUnescapeHtmlEncodingRightSingleQuote() {
Assert.assertEquals("\u2019", _htmlImpl.unescape("’"));
}
protected void assertUnchangedEscape(String input) {
Assert.assertEquals(input, _htmlImpl.escape(input));
}
private final HtmlImpl _htmlImpl = new HtmlImpl();
}