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));
+  }  
+}


Reply via email to