You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2007/12/31 19:54:18 UTC

svn commit: r607764 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry/internal/ main/java/org/apache/tapestry/internal/services/ test/app1/ test/java/org/apache/tapestry/integration/ test/java/org/apache/tapestry/integrati...

Author: hlship
Date: Mon Dec 31 10:54:15 2007
New Revision: 607764

URL: http://svn.apache.org/viewvc?rev=607764&view=rev
Log:
TAPESTRY-1988: Page activation paremeter with escaped ( %2f ) slash ( " / " ) character not passed correctly

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInvocationImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PageLinkContext.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Kicker.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PageLinkContext.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Target.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/TapestryInternalUtils.java Mon Dec 31 10:54:15 2007
@@ -14,7 +14,6 @@
 
 package org.apache.tapestry.internal;
 
-import org.apache.commons.codec.DecoderException;
 import org.apache.commons.codec.EncoderException;
 import org.apache.commons.codec.net.URLCodec;
 import org.apache.tapestry.OptionModel;
@@ -36,6 +35,7 @@
 import java.io.Closeable;
 import java.io.IOException;
 import java.lang.reflect.Method;
+import java.util.BitSet;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -45,7 +45,23 @@
  */
 public class TapestryInternalUtils
 {
-    private static final URLCodec CODEC = new URLCodec();
+    private static final URLCodec CODEC = new URLCodec()
+    {
+
+        private BitSet contextSafe = (BitSet) WWW_FORM_URL.clone();
+
+        {
+            // Servlet container does not decode '+' in path to ' ',
+            // so we encode ' ' to %20, not to '+'.
+            contextSafe.clear(' ');
+        }
+
+        @Override
+        public byte[] encode(byte[] bytes)
+        {
+            return encodeUrl(contextSafe, bytes);
+        }
+    };
 
     private TapestryInternalUtils()
     {
@@ -472,11 +488,11 @@
         return getLabelForEnum(messages, prefix, value);
     }
 
-    public static String urlEncode(String input)
+    public static String encodeContext(String input)
     {
         try
         {
-            return CODEC.encode(input);
+            return CODEC.encode(escapePercentAndSlash(input));
         }
         catch (EncoderException ex)
         {
@@ -484,16 +500,14 @@
         }
     }
 
-    public static String urlDecode(String input)
+    public static String escapePercentAndSlash(String input)
     {
-        try
-        {
-            return CODEC.decode(input);
-        }
-        catch (DecoderException ex)
-        {
-            throw new RuntimeException(ex);
-        }
+        return input.replaceAll("%", "%25").replaceAll("/", "%2F");
+    }
+
+    public static String unescapePercentAndSlash(String input)
+    {
+        return input.replaceAll("%2[Ff]", "/").replaceAll("%25", "%");
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentActionDispatcher.java Mon Dec 31 10:54:15 2007
@@ -136,7 +136,7 @@
 
         for (int i = 0; i < result.length; i++)
         {
-            result[i] = TapestryInternalUtils.urlDecode(result[i]);
+            result[i] = TapestryInternalUtils.unescapePercentAndSlash(result[i]);
         }
 
         return result;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInvocationImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInvocationImpl.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInvocationImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ComponentInvocationImpl.java Mon Dec 31 10:54:15 2007
@@ -98,7 +98,7 @@
         {
             builder.append("/");
 
-            builder.append(TapestryInternalUtils.urlEncode(id));
+            builder.append(TapestryInternalUtils.encodeContext(id));
         }
 
         return builder.toString();

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/LinkFactoryImpl.java Mon Dec 31 10:54:15 2007
@@ -146,7 +146,7 @@
         {
             if (i > 0) builder.append("/");
 
-            builder.append(TapestryInternalUtils.urlEncode(activationContext[i]));
+            builder.append(TapestryInternalUtils.encodeContext(activationContext[i]));
         }
 
         link.addParameter(InternalConstants.PAGE_CONTEXT_NAME, builder.toString());

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/PageRenderDispatcher.java Mon Dec 31 10:54:15 2007
@@ -92,7 +92,7 @@
 
         for (int i = 0; i < context.length; i++)
         {
-            context[i] = TapestryInternalUtils.urlDecode(context[i]);
+            context[i] = TapestryInternalUtils.unescapePercentAndSlash(context[i]);
         }
 
         return context;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PageLinkContext.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PageLinkContext.tml?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PageLinkContext.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/PageLinkContext.tml Mon Dec 31 10:54:15 2007
@@ -1,9 +1,10 @@
 <html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-    
+
     <h1>PageLink Context Demo</h1>
-    
+
     <p>
-        Demonstrates how to supply explicit context is a page link.  This is often used in pages with a master/detail relationship,
+        Demonstrates how to supply explicit context is a page link. This is often used in pages with a master/detail
+        relationship,
         with the master page providing links to the detail page, configured via the explicit context.
     </p>
 
@@ -12,6 +13,10 @@
     <a t:type="pagelink" page="target" context="literal:literal context">literal context</a>
     <br/>
     <a t:type="pagelink" page="target" context="computedContext">computed context</a>
+    <br/>
+    <a t:type="pagelink" page="target" context="unsafeCharacters">unsafe characters</a>
+    <br/>
+    <a t:type="pagelink" page="target" context="japaneseKanji">japanese kanji</a>
+
 
-    
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Mon Dec 31 10:54:15 2007
@@ -718,13 +718,13 @@
 
         clickAndWait("actionlink");
 
-        assertTextSeries("//li[%d]", 1, "betty", "wilma");
+        assertTextSeries("//li[%d]", 1, "betty", "wilma", "betty/wilma", "\u82B1\u5B50");
         assertTextPresent("No component context.");
 
         clickAndWait("link=go");
 
-        assertTextSeries("//li[%d]", 1, "betty", "wilma");
-        assertTextSeries("//ul[2]/li[%d]", 1, "fred", "barney", "clark kent");
+        assertTextSeries("//li[%d]", 1, "betty", "wilma", "betty/wilma", "\u82B1\u5B50");
+        assertTextSeries("//ul[2]/li[%d]", 1, "fred", "barney", "clark kent", "fred/barney", "\u592A\u90CE");
     }
 
     @Test
@@ -734,7 +734,7 @@
 
         clickAndWait("actionlink");
 
-        assertTextSeries("//li[%d]", 1, "betty", "wilma");
+        assertTextSeries("//li[%d]", 1, "betty", "wilma", "betty/wilma", "\u82B1\u5B50");
 
         clickAndWait("nocontext");
 
@@ -759,6 +759,18 @@
         clickAndWait("link=computed context");
 
         assertTextSeries("//li[%d]", 1, "fred", "7", "true");
+
+        clickAndWait("link=PageLink Context Demo");
+
+        clickAndWait("link=unsafe characters");
+
+        assertText("//li[1]", "unsafe characters: !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~");
+
+        clickAndWait("link=PageLink Context Demo");
+
+        clickAndWait("link=japanese kanji");
+
+        assertText("//li[1]", "japanese kanji: \u65E5\u672C\u8A9E");
     }
 
     @Test

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Kicker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Kicker.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Kicker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Kicker.java Mon Dec 31 10:54:15 2007
@@ -23,8 +23,7 @@
 
     Object onAction()
     {
-        _target.setActivationContext(new String[]
-                {"betty", "wilma"});
+        _target.setActivationContext(new String[]{"betty", "wilma", "betty/wilma", "\u82B1\u5B50"});
 
         return _target;
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PageLinkContext.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PageLinkContext.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PageLinkContext.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/PageLinkContext.java Mon Dec 31 10:54:15 2007
@@ -18,7 +18,16 @@
 {
     public Object[] getComputedContext()
     {
-        return new Object[]
-                {"fred", 7, true};
+        return new Object[]{"fred", 7, true};
+    }
+
+    public String getUnsafeCharacters()
+    {
+        return "unsafe characters: !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
+    }
+
+    public String getJapaneseKanji()
+    {
+        return "japanese kanji: \u65E5\u672C\u8A9E";
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Target.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Target.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Target.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/app1/pages/Target.java Mon Dec 31 10:54:15 2007
@@ -50,8 +50,7 @@
 
     public Object[] getContextToEncode()
     {
-        return new Object[]
-                {"fred", "barney", "clark kent"};
+        return new Object[]{"fred", "barney", "clark kent", "fred/barney", "\u592A\u90CE"};
     }
 
     public Object getObject()

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java?rev=607764&r1=607763&r2=607764&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/TapestryInternalUtilsTest.java Mon Dec 31 10:54:15 2007
@@ -98,22 +98,14 @@
     @DataProvider(name = "to_user_presentable")
     public Object[][] to_user_presentable_data()
     {
-        return new Object[][]
-                {
-                        {"hello", "Hello"},
-                        {"userId", "User Id"},
-                        {"useHTML", "Use HTML"},
-                        {"underscored_name", "Underscored Name"},};
+        return new Object[][]{{"hello", "Hello"}, {"userId", "User Id"}, {"useHTML", "Use HTML"},
+                              {"underscored_name", "Underscored Name"},};
     }
 
     @Test
     public void map_from_keys_and_values()
     {
-        Map<String, String> map = TapestryInternalUtils.mapFromKeysAndValues(
-                "fred",
-                "flintstone",
-                "barney",
-                "rubble");
+        Map<String, String> map = TapestryInternalUtils.mapFromKeysAndValues("fred", "flintstone", "barney", "rubble");
 
         assertEquals(map.size(), 2);
         assertEquals(map.get("fred"), "flintstone");
@@ -302,15 +294,11 @@
     @Test
     public void extract_id_from_property_expression()
     {
-        assertEquals(
-                TapestryInternalUtils.extractIdFromPropertyExpression("simpleName"),
-                "simpleName");
-        assertEquals(
-                TapestryInternalUtils.extractIdFromPropertyExpression("complex.name().withStuff"),
-                "complexnamewithStuff");
-        assertEquals(
-                TapestryInternalUtils.extractIdFromPropertyExpression("number99.withABullet"),
-                "number99withABullet");
+        assertEquals(TapestryInternalUtils.extractIdFromPropertyExpression("simpleName"), "simpleName");
+        assertEquals(TapestryInternalUtils.extractIdFromPropertyExpression("complex.name().withStuff"),
+                     "complexnamewithStuff");
+        assertEquals(TapestryInternalUtils.extractIdFromPropertyExpression("number99.withABullet"),
+                     "number99withABullet");
     }
 
     @Test
@@ -322,9 +310,7 @@
 
         replay();
 
-        assertEquals(
-                TapestryInternalUtils.defaultLabel("myid", messages, "myid-name-not-used"),
-                "My Id");
+        assertEquals(TapestryInternalUtils.defaultLabel("myid", messages, "myid-name-not-used"), "My Id");
 
         verify();
     }
@@ -338,10 +324,7 @@
 
         replay();
 
-        assertEquals(TapestryInternalUtils.defaultLabel(
-                "foobarbazbiff",
-                messages,
-                "foo.bar().baz.biff()"), "Biff");
+        assertEquals(TapestryInternalUtils.defaultLabel("foobarbazbiff", messages, "foo.bar().baz.biff()"), "Biff");
 
         verify();
     }
@@ -373,14 +356,7 @@
 
         // Subclass properties listed after superclass properties, as desired.
 
-        assertEquals(sorted, Arrays.asList(
-                "firstName",
-                "lastName",
-                "age",
-                "street",
-                "city",
-                "state",
-                "zip"));
+        assertEquals(sorted, Arrays.asList("firstName", "lastName", "age", "street", "city", "state", "zip"));
     }
 
     @Test
@@ -457,5 +433,41 @@
 
         verify();
 
+    }
+
+    @Test
+    public void escape_percent_and_slash()
+    {
+        assertEquals(TapestryInternalUtils.escapePercentAndSlash("foo%bar/baz"), "foo%25bar%2Fbaz");
+    }
+
+    @Test
+    public void unescape_percent_and_slash()
+    {
+        assertEquals(TapestryInternalUtils.unescapePercentAndSlash("foo%25bar%2Fbaz"), "foo%bar/baz");
+    }
+
+    @Test
+    public void encode_alphanum_context()
+    {
+        String input = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+        String expected = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+        assertEquals(TapestryInternalUtils.encodeContext(input), expected);
+    }
+
+    @Test
+    public void encode_unsafe_context()
+    {
+        String input = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
+        String expected = "%20%21%22%23%24%2525%26%27%28%29*%2B%2C-.%252F%3A%3B%3C%3D%3E%3F%40%5B%5C%5D%5E_%60%7B%7C%7D%7E";
+        assertEquals(TapestryInternalUtils.encodeContext(input), expected);
+    }
+
+    @Test
+    public void encode_utf8_japanese_context()
+    {
+        String input = "\u65E5\u672C\u8A9E";
+        String expected = "%E6%97%A5%E6%9C%AC%E8%AA%9E";
+        assertEquals(TapestryInternalUtils.encodeContext(input), expected);
     }
 }