StrutsLinkTool breaks paths containing a query string
-----------------------------------------------------

                 Key: VELTOOLS-138
                 URL: https://issues.apache.org/jira/browse/VELTOOLS-138
             Project: Velocity Tools
          Issue Type: Bug
          Components: GenericTools
    Affects Versions: 2.0
            Reporter: Gabriel Lavoie
             Fix For: 2.0.x


When using StrutsLinkTool with a Struts global-forward containing a query 
string in its path, the question mark separating the path from the query string 
gets encoded into %3F and the generated link is broken. I traced problem down 
to the "public LinkTool absolute(Object obj)" method from the "LinkTool" class 
that doesn't manage well "non-absolute" links (not starting with the "http" 
prefix). Those links are managed as if they were only a path and the query 
string isn't extracted. The Java URI class is able to manage such link to 
extract correctly the information. 

Here's a patch that solves the problem (including a unit test that will fail if 
LinkTool.java isn't patched):

--- src/main/java/org/apache/velocity/tools/generic/LinkTool.java       Wed Mar 
16 13:35:18 2011
+++ src/main/java/org/apache/velocity/tools/generic/LinkTool.java       Wed Mar 
16 13:42:28 2011
@@ -1349,40 +1349,44 @@
         else
         {
             pth = String.valueOf(obj);
+
+            // looks absolute already
+            URI uri = toURI(pth);
+            if (uri == null)
+            {
+                return null;
+            }
+            
             if (pth.startsWith(DEFAULT_SCHEME))
             {
-                // looks absolute already
-                URI uri = toURI(pth);
-                if (uri == null)
-                {
-                    return null;
-                }
                 copy.setScheme(uri.getScheme());
                 copy.setUserInfo(uri.getUserInfo());
                 copy.setHost(uri.getHost());
                 copy.setPort(uri.getPort());
-                // handle path, query and fragment with care
-                pth = uri.getPath();
-                if (pth.equals("/") || pth.length() == 0)
-                {
-                    pth = null;
-                }
-                copy.setPath(pth);
-                if (uri.getQuery() != null)
-                {
-                    copy.setQuery(uri.getQuery());
-                }
-                if (uri.getFragment() != null)
-                {
-                    copy.setFragment(uri.getFragment());
-                }
-                return copy;
             }
-            else if (!pth.startsWith("/"))
+            
+            // handle path, query and fragment with care
+            pth = uri.getPath();
+
+            if (pth.equals("/") || pth.length() == 0)
+            {
+                pth = null;
+            }
+            
+            if (pth != null && !pth.startsWith("/"))
             {
                 // paths that don't start with '/'
                 // are considered relative to the current directory
                 pth = combinePath(getDirectory(), pth);
+            }
+            
+            if (uri.getQuery() != null)
+            {
+                copy.setQuery(uri.getQuery());
+            }
+            if (uri.getFragment() != null)
+            {
+                copy.setFragment(uri.getFragment());
             }
         }
         copy.setPath(pth);
--- src/test/java/org/apache/velocity/tools/generic/LinkToolTests.java  Wed Mar 
16 13:35:42 2011
+++ src/test/java/org/apache/velocity/tools/generic/LinkToolTests.java  Wed Mar 
16 13:43:35 2011
@@ -463,6 +463,16 @@
         assertEquals("http://apache.org/test/bar.vm";, result.toString());
         result = result.absolute("/woogie.vm");
         assertEquals("http://apache.org/woogie.vm";, result.toString());
+        
+        result = link.absolute("http://apache.org/a/path?param1=value1";);
+        assertEquals("apache.org", result.getHost());
+        assertEquals("value1", result.getParams().get("param1"));
+        assertEquals("/a/path", result.getPath());
+        
+        result = link.absolute("/a/path?param1=value1");
+        assertNull(result.getHost());
+        assertEquals("value1", result.getParams().get("param1"));
+        assertEquals("/a/path", result.getPath());
     }
 
     public @Test void methodGetBaseRef() throws Exception


--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to