You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by nb...@apache.org on 2009/05/11 22:31:31 UTC

svn commit: r773678 - in /velocity/tools/trunk/src: main/java/org/apache/velocity/tools/generic/LinkTool.java test/java/org/apache/velocity/tools/LinkToolTests.java

Author: nbubna
Date: Mon May 11 20:31:31 2009
New Revision: 773678

URL: http://svn.apache.org/viewvc?rev=773678&view=rev
Log:
fix double escaping of query strings

Modified:
    velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LinkTool.java
    velocity/tools/trunk/src/test/java/org/apache/velocity/tools/LinkToolTests.java

Modified: velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LinkTool.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LinkTool.java?rev=773678&r1=773677&r2=773678&view=diff
==============================================================================
--- velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LinkTool.java (original)
+++ velocity/tools/trunk/src/main/java/org/apache/velocity/tools/generic/LinkTool.java Mon May 11 20:31:31 2009
@@ -1618,7 +1618,80 @@
         {
             return null;
         }
-        return uri.toString();
+        return decodeQueryPercents(uri.toString());
+    }
+
+    /**
+     * This is an ugly (but fast) hack that's needed because URI encodes
+     * things that we don't need encoded while not encoding things
+     * that we do need encoded.  So, we have to encode query data
+     * before creating the URI to ensure they are properly encoded,
+     * but then URI encodes all the % from that encoding.  Here,
+     * we isolate the query data and manually decode the encoded
+     * %25 in that section back to %, without decoding anything else.
+     */
+    protected String decodeQueryPercents(String url)
+    {
+        StringBuilder out = new StringBuilder(url.length());
+        boolean inQuery = false, havePercent = false, haveTwo = false;
+        for (int i=0; i<url.length(); i++)
+        {
+            char c = url.charAt(i);
+            if (inQuery)
+            {
+                if (havePercent)
+                {
+                    if (haveTwo)
+                    {
+                        out.append('%');
+                        if (c != '5')
+                        {
+                            out.append('2').append(c);
+                        }
+                        havePercent = haveTwo = false;
+                    }
+                    else if (c == '2')
+                    {
+                        haveTwo = true;
+                    }
+                    else
+                    {
+                        out.append('%').append(c);
+                        havePercent = false;
+                    }
+                }
+                else if (c == '%')
+                {
+                    havePercent = true;
+                }
+                else
+                {
+                    out.append(c);
+                }
+                if (c == '#')
+                {
+                    inQuery = false;
+                }
+            }
+            else
+            {
+                out.append(c);
+                if (c == '?')
+                {
+                    inQuery = true;
+                }
+            }
+        }
+        // if things ended part way
+        if (havePercent)
+        {
+            out.append('%');
+            if (haveTwo)
+            {
+                out.append('2');
+            }
+        }
+        return out.toString();
     }
 
     /**

Modified: velocity/tools/trunk/src/test/java/org/apache/velocity/tools/LinkToolTests.java
URL: http://svn.apache.org/viewvc/velocity/tools/trunk/src/test/java/org/apache/velocity/tools/LinkToolTests.java?rev=773678&r1=773677&r2=773678&view=diff
==============================================================================
--- velocity/tools/trunk/src/test/java/org/apache/velocity/tools/LinkToolTests.java (original)
+++ velocity/tools/trunk/src/test/java/org/apache/velocity/tools/LinkToolTests.java Mon May 11 20:31:31 2009
@@ -633,6 +633,8 @@
         assertEquals("x=1", link.toQuery('x', 1));
         assertEquals("true=false", link.toQuery(true, false));
         assertEquals("path=%2Ffoo+bar%2Fnew", link.toQuery("path", "/foo bar/new"));
+        // try all URI reserved chars
+        assertEquals("x=%2C%3B%3A%24%26%2B%3D%3F%2F%5B%5D%40", link.toQuery('x', ",;:$&+=?/[]@"));
     }
 
     public @Test void methodSetParam_ObjectObjectboolean() throws Exception
@@ -830,5 +832,17 @@
         assertEquals("#42", link.anchor(42).toString());
     }
 
+    public @Test void methodNoDoubleEncode() throws Exception
+    {
+        LinkTool link = newInstance().relative("/foo");
+        assertEquals("/foo", link.toString());
+        link = link.param("q","a:b c");
+        assertEquals("/foo?q=a%3Ab+c", link.toString());
+        link = link.anchor("a(b, c)");
+        assertEquals("/foo?q=a%3Ab+c#a(b,%20c)", link.toString());
+        link = link.param("evil","%25%24%").anchor(null);
+        assertEquals("/foo?q=a%3Ab+c&amp;evil=%2525%2524%25", link.toString());
+    }
+
 }
         
\ No newline at end of file