Port CGI parameter and POST fixes from TC5
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 13 Jul 2006 02:12:34 +0000 (02:12 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 13 Jul 2006 02:12:34 +0000 (02:12 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk@421478 13f79535-47bb-0310-9956-ffa450edef68

java/org/apache/catalina/servlets/CGIServlet.java

index 67e446a..7cccd99 100644 (file)
@@ -19,14 +19,14 @@ package org.apache.catalina.servlets;
 \r
 import java.io.BufferedOutputStream;\r
 import java.io.BufferedReader;\r
-import java.io.ByteArrayOutputStream;\r
 import java.io.File;\r
 import java.io.FileOutputStream;\r
 import java.io.IOException;\r
 import java.io.InputStream;\r
 import java.io.InputStreamReader;\r
 import java.io.OutputStream;\r
-import java.net.URLEncoder;\r
+import java.io.UnsupportedEncodingException;\r
+import java.net.URLDecoder;\r
 import java.util.ArrayList;\r
 import java.util.Date;\r
 import java.util.Enumeration;\r
@@ -234,7 +234,7 @@ import org.apache.catalina.util.IOTools;
  *\r
  * @author Martin T Dengler [root@martindengler.com]\r
  * @author Amy Roh\r
- * @version $Revision: 383693 $, $Date: 2006-03-06 23:16:24 +0100 (lun., 06 mars 2006) $\r
+ * @version $Revision: 421476 $, $Date: 2006-07-12 22:08:28 -0400 (Wed, 12 Jul 2006) $\r
  * @since Tomcat 4.0\r
  *\r
  */\r
@@ -707,7 +707,7 @@ public final class CGIServlet extends HttpServlet {
      * <p>\r
      * </p>\r
      *\r
-     * @version  $Revision: 383693 $, $Date: 2006-03-06 23:16:24 +0100 (lun., 06 mars 2006) $\r
+     * @version  $Revision: 421476 $, $Date: 2006-07-12 22:08:28 -0400 (Wed, 12 Jul 2006) $\r
      * @since    Tomcat 4.0\r
      *\r
      */\r
@@ -741,8 +741,8 @@ public final class CGIServlet extends HttpServlet {
         /** cgi command's desired working directory */\r
         private File workingDirectory = null;\r
 \r
-        /** cgi command's query parameters */\r
-        private ArrayList queryParameters = new ArrayList();\r
+        /** cgi command's command line parameters */\r
+        private ArrayList cmdLineParameters = new ArrayList();\r
 \r
         /** whether or not this object is valid or not */\r
         private boolean valid = false;\r
@@ -763,20 +763,6 @@ public final class CGIServlet extends HttpServlet {
             setupFromContext(context);\r
             setupFromRequest(req);\r
 \r
-            Enumeration paramNames = req.getParameterNames();\r
-            while (paramNames != null && paramNames.hasMoreElements()) {\r
-                String param = paramNames.nextElement().toString();\r
-                if (param != null) {\r
-                    String values[] = req.getParameterValues(param);\r
-                    for (int i=0; i < values.length; i++) {\r
-                        String value = URLEncoder.encode(values[i],\r
-                                                         parameterEncoding);\r
-                        NameValuePair nvp = new NameValuePair(param, value);\r
-                        queryParameters.add(nvp);\r
-                    }\r
-                }\r
-            }\r
-\r
             this.valid = setCGIEnvironment(req);\r
 \r
             if (this.valid) {\r
@@ -807,8 +793,11 @@ public final class CGIServlet extends HttpServlet {
          *\r
          * @param  req   HttpServletRequest for information provided by\r
          *               the Servlet API\r
+         * @throws UnsupportedEncodingException \r
          */\r
-        protected void setupFromRequest(HttpServletRequest req) {\r
+        protected void setupFromRequest(HttpServletRequest req)\r
+                throws UnsupportedEncodingException {\r
+            \r
             this.contextPath = req.getContextPath();\r
             this.servletPath = req.getServletPath();\r
             this.pathInfo = req.getPathInfo();\r
@@ -817,10 +806,34 @@ public final class CGIServlet extends HttpServlet {
             if (this.pathInfo == null) {\r
                 this.pathInfo = this.servletPath;\r
             }\r
+            \r
+            // If request is HEAD or GET and Query String does not contain\r
+            // an unencoded "=" this is an indexed query. Parsed Query String\r
+            // forms command line parameters for cgi command.\r
+            if (!"GET".equals(req.getMethod()) &&\r
+                    !"HEAD".equals(req.getMethod()))\r
+                return;\r
+            \r
+            String qs = req.getQueryString();\r
+            \r
+            if (qs == null || qs.indexOf("=")>0)\r
+                return;\r
+            \r
+            int delimIndex = 0;\r
+            int lastDelimIndex = 0;\r
+            delimIndex = qs.indexOf("+");\r
+            \r
+            while (delimIndex >0) {\r
+                cmdLineParameters.add(URLDecoder.decode(qs.substring(\r
+                        lastDelimIndex,delimIndex),parameterEncoding));\r
+                lastDelimIndex = delimIndex + 1;\r
+                delimIndex = qs.indexOf("+",lastDelimIndex);\r
+            }\r
+            cmdLineParameters.add(URLDecoder.decode(qs.substring(\r
+                    lastDelimIndex),parameterEncoding));\r
         }\r
 \r
 \r
-\r
         /**\r
          * Resolves core information about the cgi script.\r
          *\r
@@ -1270,15 +1283,14 @@ public final class CGIServlet extends HttpServlet {
             }\r
             sb.append("</td></tr>");\r
 \r
-            sb.append("<tr><td colspan=2>Query Params</td></tr>");\r
-            for (int i=0; i < queryParameters.size(); i++) {\r
-                NameValuePair nvp = (NameValuePair) queryParameters.get(i);\r
-                sb.append("<tr><td>");\r
-                sb.append(nvp.getName());\r
-                sb.append("</td><td>");\r
-                sb.append(nvp.getValue());\r
-                sb.append("</td></tr>");\r
+            sb.append("<tr><td>Command Line Params</td><td>");\r
+            for (int i=0; i < cmdLineParameters.size(); i++) {\r
+                String param = (String) cmdLineParameters.get(i);\r
+                sb.append("<p>");\r
+                sb.append(param);\r
+                sb.append("</p>");\r
             }\r
+            sb.append("</td></tr>");\r
 \r
             sb.append("</TABLE><p>end.");\r
 \r
@@ -1330,7 +1342,7 @@ public final class CGIServlet extends HttpServlet {
          *\r
          */\r
         protected ArrayList getParameters() {\r
-            return queryParameters;\r
+            return cmdLineParameters;\r
         }\r
 \r
 \r
@@ -1422,7 +1434,7 @@ public final class CGIServlet extends HttpServlet {
      * and <code>setResponse</code> methods, respectively.\r
      * </p>\r
      *\r
-     * @version   $Revision: 383693 $, $Date: 2006-03-06 23:16:24 +0100 (lun., 06 mars 2006) $\r
+     * @version   $Revision: 421476 $, $Date: 2006-07-12 22:08:28 -0400 (Wed, 12 Jul 2006) $\r
      */\r
 \r
     protected class CGIRunner {\r
@@ -1436,7 +1448,7 @@ public final class CGIServlet extends HttpServlet {
         /** working directory used when invoking the cgi script */\r
         private File wd = null;\r
 \r
-        /** query parameters to be passed to the invoked script */\r
+        /** command line parameters to be passed to the invoked script */\r
         private ArrayList params = null;\r
 \r
         /** stdin to be passed to cgi script */\r
@@ -1462,8 +1474,8 @@ public final class CGIServlet extends HttpServlet {
          * @param  command  string full path to command to be executed\r
          * @param  env      Hashtable with the desired script environment\r
          * @param  wd       File with the script's desired working directory\r
-         * @param  params   ArrayList with the script's query parameters as\r
-         *                  NameValuePairs\r
+         * @param  params   ArrayList with the script's query command line\r
+         *                  paramters as strings\r
          */\r
         protected CGIRunner(String command, Hashtable env, File wd,\r
                             ArrayList params) {\r
@@ -1657,21 +1669,14 @@ public final class CGIServlet extends HttpServlet {
 \r
             for (int i=0; i < params.size(); i++) {\r
                 cmdAndArgs.append(" ");\r
-                NameValuePair nvp = (NameValuePair) params.get(i); \r
-                String k = nvp.getName();\r
-                String v = nvp.getValue();\r
-                if ((k.indexOf("=") < 0) && (v.indexOf("=") < 0)) {\r
-                    StringBuffer arg = new StringBuffer(k);\r
-                    arg.append("=");\r
-                    arg.append(v);\r
-                    if (arg.toString().indexOf(" ") < 0) {\r
-                        cmdAndArgs.append(arg);\r
-                    } else {\r
-                        // Spaces used as delimiter, so need to use quotes\r
-                        cmdAndArgs.append("\"");\r
-                        cmdAndArgs.append(arg);\r
-                        cmdAndArgs.append("\"");\r
-                    }\r
+                String param = (String) params.get(i);\r
+                if (param.indexOf(" ") < 0) {\r
+                    cmdAndArgs.append(param);\r
+                } else {\r
+                    // Spaces used as delimiter, so need to use quotes\r
+                    cmdAndArgs.append("\"");\r
+                    cmdAndArgs.append(param);\r
+                    cmdAndArgs.append("\"");\r
                 }\r
             }\r
 \r
@@ -1680,48 +1685,14 @@ public final class CGIServlet extends HttpServlet {
             command.append(cmdAndArgs.toString());\r
             cmdAndArgs = command;\r
 \r
-            String sContentLength = (String) env.get("CONTENT_LENGTH");\r
-            ByteArrayOutputStream contentStream = null;\r
-            if(!"".equals(sContentLength)) {\r
-                byte[] content = new byte[Integer.parseInt(sContentLength)];\r
-\r
-                // Bugzilla 32023\r
-                int lenRead = 0;\r
-                do {\r
-                    int partRead = stdin.read(content,lenRead,content.length-lenRead);\r
-                    lenRead += partRead;\r
-                } while (lenRead > 0 && lenRead < content.length);\r
-\r
-                contentStream = new ByteArrayOutputStream(\r
-                        Integer.parseInt(sContentLength));\r
-                if ("POST".equals(env.get("REQUEST_METHOD"))) {\r
-                    String paramStr = getPostInput(params);\r
-                    if (paramStr != null) {\r
-                        byte[] paramBytes = paramStr.getBytes();\r
-                        contentStream.write(paramBytes);\r
-\r
-                        int contentLength = paramBytes.length;\r
-                        if (lenRead > 0) {\r
-                            String lineSep = System.getProperty("line.separator");\r
-                            contentStream.write(lineSep.getBytes());\r
-                            contentLength = lineSep.length() + lenRead;\r
-                        }\r
-                        env.put("CONTENT_LENGTH", Integer.toString(contentLength));\r
-                    }\r
-                }\r
-\r
-                if (lenRead > 0) {\r
-                    contentStream.write(content, 0, lenRead);\r
-                }\r
-                contentStream.close();\r
-            }\r
-\r
             rt = Runtime.getRuntime();\r
             proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd);\r
 \r
-            if(contentStream != null) {\r
+            String sContentLength = (String) env.get("CONTENT_LENGTH");\r
+\r
+            if(!"".equals(sContentLength)) {\r
                 commandsStdIn = new BufferedOutputStream(proc.getOutputStream());\r
-                commandsStdIn.write(contentStream.toByteArray());\r
+                IOTools.flow(stdin, commandsStdIn);\r
                 commandsStdIn.flush();\r
                 commandsStdIn.close();\r
             }\r
@@ -1893,64 +1864,9 @@ public final class CGIServlet extends HttpServlet {
                 log("runCGI: " + lineCount + " lines received on stderr") ;\r
             } ;\r
         }\r
-\r
-\r
-        /**\r
-         * Gets a string for input to a POST cgi script\r
-         *\r
-         * @param  params   ArrayList of query parameters to be passed to\r
-         *                  the CGI script\r
-         * @return          for use as input to the CGI script\r
-         */\r
-\r
-        protected String getPostInput(ArrayList params) {\r
-            StringBuffer qs = new StringBuffer("");\r
-            for (int i=0; i < params.size(); i++) {\r
-                NameValuePair nvp = (NameValuePair) this.params.get(i); \r
-                String k = nvp.getName();\r
-                String v = nvp.getValue();\r
-                if ((k.indexOf("=") < 0) && (v.indexOf("=") < 0)) {\r
-                    qs.append(k);\r
-                    qs.append("=");\r
-                    qs.append(v);\r
-                    qs.append("&");\r
-                }\r
-            }\r
-            if (qs.length() > 0) {\r
-                // Remove last "&"\r
-                qs.setLength(qs.length() - 1);\r
-                return qs.toString();\r
-            } else {\r
-                return null;\r
-            }\r
-        }\r
     } //class CGIRunner\r
 \r
     /**\r
-     * This is a simple class for storing name-value pairs.\r
-     * \r
-     * TODO: It might be worth moving this to the utils package there is a\r
-     * wider requirement for this functionality.\r
-     */\r
-    protected class NameValuePair {\r
-        private String name;\r
-        private String value;\r
-        \r
-        NameValuePair(String name, String value) {\r
-            this.name = name;\r
-            this.value = value;\r
-        }\r
-        \r
-        protected String getName() {\r
-            return name;\r
-        }\r
-        \r
-        protected String getValue() {\r
-            return value;\r
-        }\r
-    }\r
-\r
-    /**\r
      * This is an input stream specifically for reading HTTP headers. It reads\r
      * upto and including the two blank lines terminating the headers. It\r
      * allows the content to be read using bytes or characters as appropriate.\r