// Copyright (c) 2011, Mike Samuel // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions // are met: // // Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // Neither the name of the OWASP nor the names of its contributors may // be used to endorse or promote products derived from this software // without specific prior written permission. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE // COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. package org.owasp.html; import java.util.List; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import junit.framework.TestCase; public class HtmlStreamRendererTest extends TestCase { private final List errors = Lists.newArrayList(); private final StringBuilder rendered = new StringBuilder(); private final HtmlStreamRenderer renderer = HtmlStreamRenderer.create( rendered, new Handler() { public void handle(String errorMessage) { errors.add(errorMessage); } }); @Override protected void setUp() throws Exception { super.setUp(); errors.clear(); rendered.setLength(0); } @Override protected void tearDown() throws Exception { super.tearDown(); assertTrue(errors.isEmpty()); // Catch any tests that don't check errors. } public final void testEmptyDocument() throws Exception { assertNormalized("", ""); } public final void testElementNamesNormalized() throws Exception { assertNormalized("
", "
"); assertNormalized("
", "
"); assertNormalized("
", "
"); assertNormalized("
", ""); } public final void testAttributeNamesNormalized() throws Exception { assertNormalized("", ""); assertNormalized("", ""); assertNormalized("", ""); assertNormalized("", ""); assertNormalized("", ""); } public final void testAttributeValuesEscaped() throws Exception { assertNormalized("
", "
"); } public final void testRcdataEscaped() throws Exception { assertNormalized( "I <3 PONIES, OMG!!!", "I <3 PONIES, OMG!!!"); } public final void testCdataNotEscaped() throws Exception { assertNormalized( "", ""); } public final void testIllegalElementName() throws Exception { renderer.openDocument(); renderer.openTag(":svg", ImmutableList.of()); renderer.openTag("svg:", ImmutableList.of()); renderer.openTag("-1", ImmutableList.of()); renderer.openTag("svg::svg", ImmutableList.of()); renderer.openTag("a@b", ImmutableList.of()); renderer.closeDocument(); String output = rendered.toString(); assertFalse(output, output.contains("<")); assertEquals( Joiner.on('\n').join( "Invalid element name : :svg", "Invalid element name : svg:", "Invalid element name : -1", "Invalid element name : svg::svg", "Invalid element name : a@b"), Joiner.on('\n').join(errors)); errors.clear(); } public final void testIllegalAttributeName() throws Exception { renderer.openDocument(); renderer.openTag("div", ImmutableList.of(":svg", "x")); renderer.openTag("div", ImmutableList.of("svg:", "x")); renderer.openTag("div", ImmutableList.of("-1", "x")); renderer.openTag("div", ImmutableList.of("svg::svg", "x")); renderer.openTag("div", ImmutableList.of("a@b", "x")); renderer.closeDocument(); String output = rendered.toString(); assertFalse(output, output.contains("=")); assertEquals( Joiner.on('\n').join( "Invalid attr name : :svg", "Invalid attr name : svg:", "Invalid attr name : -1", "Invalid attr name : svg::svg", "Invalid attr name : a@b"), Joiner.on('\n').join(errors)); errors.clear(); } public final void testCdataContainsEndTag1() throws Exception { renderer.openDocument(); renderer.openTag("script", ImmutableList.of("type", "text/javascript")); renderer.text("document.write('')"); renderer.closeTag("script"); renderer.closeDocument(); assertEquals( "", rendered.toString()); assertEquals( "Invalid CDATA text content : '", Joiner.on('\n').join(errors)); errors.clear(); } public final void testCdataContainsEndTag2() throws Exception { renderer.openDocument(); renderer.openTag("style", ImmutableList.of("type", "text/css")); renderer.text("/* */"); renderer.closeTag("style"); renderer.closeDocument(); assertEquals( "", rendered.toString()); assertEquals( "Invalid CDATA text content : *", Joiner.on('\n').join(errors)); errors.clear(); } public final void testRcdataContainsEndTag() throws Exception { renderer.openDocument(); renderer.openTag("textarea", ImmutableList.of()); renderer.text(""); renderer.closeTag("textarea"); renderer.closeDocument(); assertEquals( "", rendered.toString()); } public final void testCdataContainsEndTagInEscapingSpan() throws Exception { assertNormalized( "", ""); } public final void testTagInCdata() throws Exception { renderer.openDocument(); renderer.openTag("script", ImmutableList.of()); renderer.text("alert('"); renderer.openTag("b", ImmutableList.of()); renderer.text("foo"); renderer.closeTag("b"); renderer.text("')"); renderer.closeTag("script"); renderer.closeDocument(); assertEquals( "", rendered.toString()); assertEquals( Joiner.on('\n').join( "Tag content cannot appear inside CDATA element : b", "Tag content cannot appear inside CDATA element : b"), Joiner.on('\n').join(errors)); errors.clear(); } public final void testUnclosedEscapingTextSpan() throws Exception { renderer.openDocument(); renderer.openTag("script", ImmutableList.of()); renderer.text("