Author: johnh
Date: Fri Jan 28 00:47:50 2011
New Revision: 1064391
URL: http://svn.apache.org/viewvc?rev=1064391&view=rev
Log:
Stuff like <<!-- -->evil> is interpreted by the parser as a text node
containing "<" (unescaped) followed by a comment node, followed by
another text node containing "evil>". When the tree is serialized again,
as the HTMLSerializer expects to receive escaped content from the
parser, it is reconstituted as <evil>, and boom.
With this patch, if the document is in a string, first we do a trivial
pass to remove the comments, serialize it, and then do the sanitization.
If it's a DOM document, nothing extra is done...
Patch provided by Jacobo Tarrio.
Added:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriter.java
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriterTest.java
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java
Added:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriter.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriter.java?rev=1064391&view=auto
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriter.java
(added)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriter.java
Fri Jan 28 00:47:50 2011
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shindig.gadgets.render;
+
+import org.apache.shindig.gadgets.Gadget;
+import org.apache.shindig.gadgets.rewrite.DomWalker;
+import org.apache.shindig.gadgets.rewrite.MutableContent;
+import org.apache.shindig.gadgets.rewrite.RewritingException;
+import org.w3c.dom.Node;
+
+import java.util.List;
+
+/**
+ * Removes all HTML comments from the document source when sanitize=1.
+ */
+public class DropCommentsGadgetRewriter extends DomWalker.Rewriter {
+
+ public DropCommentsGadgetRewriter() {
+ super(new CommentFilter());
+ }
+
+ @Override
+ public void rewrite(Gadget gadget, MutableContent content) throws
RewritingException {
+ if (gadget.sanitizeOutput()) {
+ MutableContent rewritten =
+ new MutableContent(content.getContentParser(), content.getContent());
+ super.rewrite(gadget, rewritten);
+ content.setContent(rewritten.getContent());
+ }
+ }
+
+ private static class CommentFilter implements DomWalker.Visitor {
+
+ public VisitStatus visit(Gadget gadget, Node node) {
+ if (node.getNodeType() == Node.COMMENT_NODE) {
+ return VisitStatus.RESERVE_TREE;
+ }
+ return VisitStatus.BYPASS;
+ }
+
+ public boolean revisit(Gadget gadget, List<Node> nodes) {
+ for (Node node : nodes) {
+ node.getParentNode().removeChild(node);
+ }
+ return true;
+ }
+ }
+}
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java?rev=1064391&r1=1064390&r2=1064391&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java
(original)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/MutableContent.java
Fri Jan 28 00:47:50 2011
@@ -250,6 +250,10 @@ public class MutableContent {
}
return document;
}
+
+ public GadgetHtmlParser getContentParser() {
+ return contentParser;
+ }
public int getNumChanges() {
return numChanges;
Modified:
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java?rev=1064391&r1=1064390&r2=1064391&view=diff
==============================================================================
---
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java
(original)
+++
shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/RewriteModule.java
Fri Jan 28 00:47:50 2011
@@ -33,6 +33,7 @@ import com.google.inject.name.Names;
import org.apache.shindig.config.ContainerConfig;
import org.apache.shindig.gadgets.parse.GadgetHtmlParser;
import org.apache.shindig.gadgets.render.CajaResponseRewriter;
+import org.apache.shindig.gadgets.render.DropCommentsGadgetRewriter;
import org.apache.shindig.gadgets.render.OpenSocialI18NGadgetRewriter;
import org.apache.shindig.gadgets.render.RenderingGadgetRewriter;
import org.apache.shindig.gadgets.render.SanitizingGadgetRewriter;
@@ -135,6 +136,7 @@ public class RewriteModule extends Abstr
private void configureRewriters() {
Multibinder<GadgetRewriter> multibinder =
Multibinder.newSetBinder(binder(),
GadgetRewriter.class, Names.named("shindig.rewriters.gadget.set"));
+ multibinder.addBinding().to(DropCommentsGadgetRewriter.class);
multibinder.addBinding().to(PipelineDataGadgetRewriter.class);
multibinder.addBinding().to(TemplateRewriter.class);
multibinder.addBinding().to(AbsolutePathReferenceRewriter.class);
Added:
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriterTest.java
URL:
http://svn.apache.org/viewvc/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriterTest.java?rev=1064391&view=auto
==============================================================================
---
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriterTest.java
(added)
+++
shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/DropCommentsGadgetRewriterTest.java
Fri Jan 28 00:47:50 2011
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.shindig.gadgets.render;
+
+import static org.junit.Assert.*;
+
+import org.apache.shindig.common.uri.Uri;
+import org.apache.shindig.gadgets.Gadget;
+import org.apache.shindig.gadgets.GadgetContext;
+import org.apache.shindig.gadgets.parse.GadgetHtmlParser;
+import org.apache.shindig.gadgets.parse.caja.CajaHtmlParser;
+import org.apache.shindig.gadgets.rewrite.MutableContent;
+import org.apache.shindig.gadgets.rewrite.RewriterTestBase;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.uri.UriCommon.Param;
+import org.junit.Test;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * Tests for {@link DropCommentsGadgetRewriter}.
+ */
+public class DropCommentsGadgetRewriterTest extends RewriterTestBase {
+
+ private static final Pattern BODY_REGEX =
Pattern.compile(".*<body>(.+)</body>.*");
+
+ @Override
+ protected Class<? extends GadgetHtmlParser> getParserClass() {
+ return CajaHtmlParser.class;
+ }
+
+ private String rewrite(final boolean sanitize, String markup) throws
Exception {
+ DropCommentsGadgetRewriter rewriter = new DropCommentsGadgetRewriter();
+ GadgetContext context = new GadgetContext() {
+ @Override
+ public String getParameter(String name) {
+ return Param.SANITIZE.getKey().equals(name) && sanitize ? "1" : null;
+ }
+
+ @Override
+ public String getContainer() {
+ return "mockContainer";
+ }
+ };
+ Gadget gadget =
+ new Gadget().setContext(context).setSpec(
+ new GadgetSpec(Uri.parse("http://www.example.org/gadget.xml"),
+ "<Module><ModulePrefs title=''/><Content
type='x-html-sanitized'/></Module>"));
+
+ MutableContent content = new MutableContent(parser, markup);
+ rewriter.rewrite(gadget, content);
+
+ Matcher matcher = BODY_REGEX.matcher(content.getContent());
+ if (matcher.matches()) {
+ return matcher.group(1);
+ }
+ return content.getContent();
+ }
+
+ @Test
+ public void testCommentsUntouchedWithoutSanitize() throws Exception {
+ String markup = "<b>Good<!-- bad --></b>";
+ assertEquals(markup, rewrite(false, markup));
+ }
+
+ @Test
+ public void testCommentsDroppedWithSanitize() throws Exception {
+ String markup = "<b>Good<!-- bad --></b>";
+ assertEquals("<b>Good</b>", rewrite(true, markup));
+ }
+
+ @Test
+ public void testCommentsInMidTagDroppedWithSanitize() throws Exception {
+ String markup = "<<!-- -->b>Good<<!-- -->/b>";
+ assertEquals("<b>Good</b>", rewrite(true, markup));
+ }
+
+ @Test
+ public void testSlightlyExoticCommentsAlsoDropped() throws Exception {
+ String markup = "<b>Good<!-- bad -- \n ></b>";
+ assertEquals("<b>Good</b>", rewrite(true, markup));
+ }
+}