Index: 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 --- org/apache/commons/httpclient/HttpMethodBase.java 13 Nov 2003 22:24:46 -0000 1.190 +++ org/apache/commons/httpclient/HttpMethodBase.java 19 Nov 2003 13:53:53 -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 $ */ @@ -880,7 +881,6 @@ * @return boolean true if we should close the connection. */ protected boolean shouldCloseConnection(HttpConnection conn) { - // Connection must be closed due to an abnormal circumstance if (isConnectionCloseForced()) { LOG.debug("Should force-close connection."); @@ -1838,24 +1838,29 @@ throws IOException, HttpRecoverableException, HttpException { LOG.trace("enter HttpMethodBase.readStatusLine(HttpState, HttpConnection)"); + final int maxGarbageLines = getParams(). + getIntParameter(HttpMethodParams.STATUS_LINE_GARBAGE_LIMIT, Integer.MAX_VALUE); + //read out the HTTP status string - String s = conn.readLine(); - while ((s != null) && !StatusLine.startsWithHTTP(s)) { + int count = 0; + String s; + do { + s = conn.readLine(); if (Wire.enabled()) { Wire.input(s + "\r\n"); } - s = conn.readLine(); - } - if (s == null) { - // A null statusString means the connection was lost before we got a - // response. Try again. - throw new HttpRecoverableException("Error in parsing the status " - + " line from the response: unable to find line starting with" - + " \"HTTP\""); - } - if (Wire.enabled()) { - Wire.input(s + "\r\n"); - } + if (s != null && StatusLine.startsWithHTTP(s)) { + // Got one + break; + } else if (s == null || count >= maxGarbageLines) { + // Giving up + throw new HttpRecoverableException("Error in parsing the status " + + " line from the response: unable to find line starting with" + + " \"HTTP\""); + } + count++; + } while(true); + //create the status line from the status string statusLine = new StatusLine(s); @@ -2250,6 +2255,25 @@ if (responseConnection != null) { responseConnection.setLastResponseInputStream(null); + // At this point, no response data should be available. + // If there is data available, regard the connection as being + // unreliable and close it. + + try { + if(responseConnection.isResponseAvailable()) { + boolean logExtraInput = + getParams().isParameterTrue(HttpMethodParams.WARN_EXTRA_INPUT); + + if(logExtraInput) { + LOG.warn("Extra response data detected - closing connection"); + } + 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: 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 --- org/apache/commons/httpclient/params/HttpMethodParams.java 22 Oct 2003 19:31:00 -0000 1.5 +++ org/apache/commons/httpclient/params/HttpMethodParams.java 19 Nov 2003 13:53:53 -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,45 @@ * 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. + *
+ *
+ * If this parameter is set to true, any detection of extra
+ * input data will generate a warning in the log.
+ *
+ * This parameter expects a value of type {@link Boolean}. + *
+ */ + public static final String WARN_EXTRA_INPUT = "http.protocol.warn-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/empty lines before the status line.
+ * To specify no limit, use {@link Integer.MAX_VALUE} (default in lenient mode).
+ *