You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by bu...@apache.org on 2003/05/02 10:50:56 UTC
DO NOT REPLY [Bug 19545] New: -
CGIServlet accidentaly changes content-length
DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://nagoya.apache.org/bugzilla/show_bug.cgi?id=19545>.
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