Index: java/org/apache/commons/httpclient/HttpMethodBase.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v retrieving revision 1.190 diff -u -r1.190 HttpMethodBase.java --- java/org/apache/commons/httpclient/HttpMethodBase.java 13 Nov 2003 22:24:46 -0000 1.190 +++ java/org/apache/commons/httpclient/HttpMethodBase.java 13 Nov 2003 22:31:16 -0000 @@ -1,5 +1,5 @@ /* - * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v 1.190 2003/11/13 22:24:46 olegk Exp $ + * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpMethodBase.java,v 1.190 2003/11/13 22:24:46 olegk Exp $ * $Revision: 1.190 $ * $Date: 2003/11/13 22:24:46 $ * @@ -122,6 +122,7 @@ * @author Oleg Kalnichevski * @author Mike Bowler * @author Gary Gregory + * @author Christian Kohlschuetter * * @version $Revision: 1.190 $ $Date: 2003/11/13 22:24:46 $ */ @@ -886,7 +887,6 @@ LOG.debug("Should force-close connection."); return true; } - Header connectionHeader = null; // In case being connected via a proxy server if (!conn.isTransparent()) { @@ -1838,13 +1838,37 @@ throws IOException, HttpRecoverableException, HttpException { LOG.trace("enter HttpMethodBase.readStatusLine(HttpState, HttpConnection)"); - //read out the HTTP status string - String s = conn.readLine(); - while ((s != null) && !StatusLine.startsWithHTTP(s)) { + final int maxGarbageLines = getParams(). + getIntParameter(HttpMethodParams.STATUS_LINE_GARBAGE_LIMIT, -1); + + // Skip all blank lines first + String s = null; + while ((s = conn.readLine()) != null) { if (Wire.enabled()) { Wire.input(s + "\r\n"); } + if (s.trim().length() > 0) { + break; + } + } + + //read out the HTTP status string + int count = 0; + while (s != null) { + if (StatusLine.startsWithHTTP(s)) { + // Got one + break; + } + if ((maxGarbageLines >= 0) && (count >= maxGarbageLines)) { + // Giving up + s = null; + break; + } s = conn.readLine(); + if (Wire.enabled()) { + Wire.input(s + "\r\n"); + } + count++; } if (s == null) { // A null statusString means the connection was lost before we got a @@ -1853,9 +1877,7 @@ + " line from the response: unable to find line starting with" + " \"HTTP\""); } - if (Wire.enabled()) { - Wire.input(s + "\r\n"); - } + //create the status line from the status string statusLine = new StatusLine(s); @@ -2250,6 +2272,23 @@ if (responseConnection != null) { responseConnection.setLastResponseInputStream(null); + // At this point, no response data should be available. + // If there is data available, assume a protocol violation and + // close the connection + boolean testExtraInput = getParams(). + isParameterTrue(HttpMethodParams.TEST_EXTRA_INPUT); + if (testExtraInput) { + try { + if (responseConnection.isResponseAvailable()) { + LOG.warn("Extra response data detected"); + setConnectionCloseForced(true); + } + } + catch (IOException e) { + LOG.error("Unexpected I/O error when testing for extra response data", e); + setConnectionCloseForced(true); + } + } if (shouldCloseConnection(responseConnection)) { responseConnection.close(); } Index: java/org/apache/commons/httpclient/params/HttpMethodParams.java =================================================================== RCS file: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/params/HttpMethodParams.java,v retrieving revision 1.5 diff -u -r1.5 HttpMethodParams.java --- java/org/apache/commons/httpclient/params/HttpMethodParams.java 22 Oct 2003 19:31:00 -0000 1.5 +++ java/org/apache/commons/httpclient/params/HttpMethodParams.java 13 Nov 2003 22:31:19 -0000 @@ -1,5 +1,5 @@ /* - * $Header: /home/cvspublic/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/params/HttpMethodParams.java,v 1.5 2003/10/22 19:31:00 olegk Exp $ + * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/params/HttpMethodParams.java,v 1.5 2003/10/22 19:31:00 olegk Exp $ * $Revision: 1.5 $ * $Date: 2003/10/22 19:31:00 $ * @@ -76,6 +76,7 @@ * its value will be drawn from the parent collection of parameters. * * @author Oleg Kalnichevski + * @author Christian Kohlschuetter * * @version $Revision: 1.5 $ */ @@ -184,7 +185,41 @@ * This parameter expects a value of type {@link String}. *
*/ - public static final String COOKIE_POLICY = "http.protocol.cookie-policy"; + public static final String COOKIE_POLICY = "http.protocol.cookie-policy"; + + /** + * Defines HttpClient's behavior when a response provides more bytes than + * expected (specified with Content-Length, for example). + *+ * Such surplus data makes the HTTP connection unreliable for keep-alive + * requests, as malicious response data (faked headers etc.) can lead to undesired + * results on the next request using that connection. + *
+ *+ * This parameter expects a value of type {@link Boolean}. + *
+ */ + public static final String TEST_EXTRA_INPUT = "http.protocol.test-extra-input"; + + /** + * Defines the maximum number of ignorable lines before we expect + * a HTTP response's status code. + *
+ * With HTTP/1.1 persistent connections, the problem arises that
+ * broken scripts could return a wrong Content-Length
+ * (there are more bytes sent than specified).
+ * Unfortunately, in some cases, this is not possible after the bad response,
+ * but only before the next one.
+ * So, HttpClient must be able to skip those surplus lines this way.
+ *
+ * Set this to 0 to disallow any garbage lines before the status line.
+ * To specify no limit, use {@link Integer.MAX_VALUE}.
+ *