Return-Path: Delivered-To: apmail-jakarta-tomcat-dev-archive@apache.org Received: (qmail 43843 invoked from network); 2 May 2003 08:49:14 -0000 Received: from exchange.sun.com (192.18.33.10) by daedalus.apache.org with SMTP; 2 May 2003 08:49:14 -0000 Received: (qmail 24698 invoked by uid 97); 2 May 2003 08:51:28 -0000 Delivered-To: qmlist-jakarta-archive-tomcat-dev@nagoya.betaversion.org Received: (qmail 24691 invoked from network); 2 May 2003 08:51:27 -0000 Received: from daedalus.apache.org (HELO apache.org) (208.185.179.12) by nagoya.betaversion.org with SMTP; 2 May 2003 08:51:27 -0000 Received: (qmail 42135 invoked by uid 500); 2 May 2003 08:48:42 -0000 Mailing-List: contact tomcat-dev-help@jakarta.apache.org; run by ezmlm Precedence: bulk List-Unsubscribe: List-Subscribe: List-Help: List-Post: List-Id: "Tomcat Developers List" Reply-To: "Tomcat Developers List" Delivered-To: mailing list tomcat-dev@jakarta.apache.org Received: (qmail 42118 invoked from network); 2 May 2003 08:48:42 -0000 Received: from exchange.sun.com (192.18.33.10) by daedalus.apache.org with SMTP; 2 May 2003 08:48:42 -0000 Received: (qmail 24681 invoked by uid 50); 2 May 2003 08:50:56 -0000 Date: 2 May 2003 08:50:56 -0000 Message-ID: <20030502085056.24680.qmail@nagoya.betaversion.org> From: bugzilla@apache.org To: tomcat-dev@jakarta.apache.org Cc: Subject: DO NOT REPLY [Bug 19545] New: - CGIServlet accidentaly changes content-length X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT . ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND INSERTED IN THE BUG DATABASE. http://nagoya.apache.org/bugzilla/show_bug.cgi?id=19545 CGIServlet accidentaly changes content-length Summary: CGIServlet accidentaly changes content-length Product: Tomcat 4 Version: 4.1.24 Platform: All OS/Version: All Status: NEW Severity: Normal Priority: Other Component: Servlets:CGI AssignedTo: tomcat-dev@jakarta.apache.org ReportedBy: artonx@yahoo.co.jp There are 3 problems on CGIServlet. 1st: need CONTENT_LENGTH variable justification the situation: The client's input multibyte character may or may not be encoded as a pair of bytes. for example the shift_jis code 0x83-0x65 was encoded into "%83e" by the user-agent(this was produced by IE6). But re-encoded data from Catalina to CGIServlet was encoded into "%83%65". I think it's not a problem but behaviour. The problme is, after changing entire size of the content (because "%83e" - length=4, but "%83%65" - length = 6), the "CONTENT_LENGTH" variable isn't adjusted. So the CGI program can't read entire message body, because the program read within CONTENT_LENGTH bytes as the matter of CGI specification. say "it must not attempt to read more than CONTENT_LENGTH bytes" by http://cgi- spec.golux.com/cgi-120-00a.html#7.0. 2nd: It's too late to adjust CONTETN_LENGTH CGIServlet modifies CONTETN_LENGTH after the CGI program was executed. I faced the problem that the CGI program start to read CONTENT_LENGTH bytes before CGIServlet set modified CONTETN_LENGTH. -- This modification by CGIServlet is from CGIRunner#getPostInput. 3rd: CGIRunner#getPostInput put the content twice. I think it's bad behaviour because the CGI program read the data twice, and I didn't figure out why the CGIServlet does this. Here is patch: diff -u CGIServlet.java.org CGIServlet.java --- CGIServlet.java.org Fri May 02 02:57:25 2003 +++ CGIServlet.java Fri May 02 17:14:05 2003 @@ -73,6 +73,7 @@ import java.io.OutputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; +import java.io.ByteArrayOutputStream; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.IOException; @@ -1584,9 +1585,44 @@ cmdAndArgs = perlCommand; } + String sContentLength = (String) env.get("CONTENT_LENGTH"); + ByteArrayOutputStream contentStream = null; + if(!"".equals(sContentLength)) { + byte[] content = new byte[Integer.parseInt(sContentLength)]; + int lenRead = stdin.read(content); + contentStream = new ByteArrayOutputStream(Integer.parseInt (sContentLength)); + if ("POST".equals(env.get("REQUEST_METHOD"))) { + String paramStr = getPostInput(params); + if (paramStr != null) { + byte[] paramBytes = paramStr.getBytes(); + contentStream.write(paramBytes); + + int contentLength = paramBytes.length; + if (lenRead > 0) { + String lineSep = System.getProperty("line.separator"); + contentStream.write(lineSep.getBytes()); + contentLength = lineSep.length() + lenRead; + } + env.put("CONTENT_LENGTH", new Integer(contentLength)); + } + } + + if (lenRead > 0) { + contentStream.write(content, 0, lenRead); + } + contentStream.close(); + } + rt = Runtime.getRuntime(); proc = rt.exec(cmdAndArgs.toString(), hashToStringArray(env), wd); + + if(contentStream != null) { + commandsStdIn = new BufferedOutputStream(proc.getOutputStream()); + proc.getOutputStream().write(contentStream.toByteArray()); + commandsStdIn.flush(); + commandsStdIn.close(); + } /* * provide input to cgi * First -- parameters @@ -1649,40 +1685,6 @@ } commandsStdIn.flush(); commandsStdIn.close();*/ - String sContentLength = (String) env.get("CONTENT_LENGTH"); - if(!"".equals(sContentLength)) { - commandsStdIn = new BufferedOutputStream(proc.getOutputStream()); - byte[] content = new byte[Integer.parseInt(sContentLength)]; - - int lenRead = stdin.read(content); - - if ("POST".equals(env.get("REQUEST_METHOD"))) { - String paramStr = getPostInput(params); - if (paramStr != null) { - byte[] paramBytes = paramStr.getBytes(); - commandsStdIn.write(paramBytes); - - int contentLength = paramBytes.length; - if (lenRead > 0) { - String lineSep = System.getProperty("line.separator"); - - commandsStdIn.write(lineSep.getBytes()); - - contentLength = lineSep.length() + lenRead; - } - - env.put("CONTENT_LENGTH", new Integer(contentLength)); - } - } - - if (lenRead > 0) { - commandsStdIn.write(content, 0, lenRead); - } - - - commandsStdIn.flush(); - commandsStdIn.close(); - } /* we want to wait for the process to exit, Process.waitFor() * is useless in our situation; see @@ -1803,26 +1805,23 @@ protected String getPostInput(Hashtable params) { String lineSeparator = System.getProperty("line.separator"); Enumeration paramNames = params.keys(); - StringBuffer postInput = new StringBuffer(""); StringBuffer qs = new StringBuffer(""); if (paramNames != null && paramNames.hasMoreElements()) { while (paramNames.hasMoreElements()) { String k = (String) paramNames.nextElement(); String v = params.get(k).toString(); if ((k.indexOf("=") < 0) && (v.indexOf("=") < 0)) { - postInput.append(k); qs.append(k); - postInput.append("="); qs.append("="); - postInput.append(v); qs.append(v); - postInput.append(lineSeparator); qs.append("&"); } } } - qs.append(lineSeparator); - return qs.append(postInput.toString()).toString(); + if (qs.charAt(qs.length() - 1) == '&') { + qs.setLength(qs.length() - 1); + } + return qs.toString(); } --------------------------------------------------------------------- To unsubscribe, e-mail: tomcat-dev-unsubscribe@jakarta.apache.org For additional commands, e-mail: tomcat-dev-help@jakarta.apache.org