[MINOR] stats: add support for several packets in stats admin

Some browsers send POST requests in several packets, which was not supported
by the "stats admin" function.

This patch allows to wait for more data when they are not fully received
(we are still limited to a certain size defined by the buffer size minus its
reserved space).
It also adds support for the "Expect: 100-Continue" header.
diff --git a/doc/configuration.txt b/doc/configuration.txt
index bb25448..c768fc7 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -4856,13 +4856,10 @@
          unless you know what you do : memory is not shared between the
          processes, which can result in random behaviours.
 
-  Currently, there are 2 known limitations :
-
-    - The POST data are limited to one packet, which means that if the list of
-      servers is too long, the request won't be processed. It is recommended
-      to alter few servers at a time.
-
-    - Expect: 100-continue is not supported.
+  Currently, the POST request is limited to the buffer size minus the reserved
+  buffer space, which means that if the list of servers is too long, the
+  request won't be processed. It is recommended to alter few servers at a
+  time.
 
   Example :
     # statistics admin level only for localhost
diff --git a/src/proto_http.c b/src/proto_http.c
index dbd6a2e..3a404e6 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2855,8 +2855,7 @@
 
 /* We reached the stats page through a POST request.
  * Parse the posted data and enable/disable servers if necessary.
- * Returns 0 if request was parsed.
- * Returns 1 if there was a problem parsing the posted data.
+ * Returns 1 if request was parsed or zero if it needs more data.
  */
 int http_process_req_stat_post(struct session *s, struct buffer *req)
 {
@@ -2874,15 +2873,15 @@
 
 	cur_param = next_param = end_params;
 
-	if (end_params >= req->data + req->size) {
+	if (end_params >= req->data + req->size - global.tune.maxrewrite) {
 		/* Prevent buffer overflow */
 		s->data_ctx.stats.st_code = STAT_STATUS_EXCD;
 		return 1;
 	}
 	else if (end_params > req->data + req->l) {
-		/* This condition also rejects a request with Expect: 100-continue */
-		s->data_ctx.stats.st_code = STAT_STATUS_EXCD;
-		return 1;
+		/* we need more data */
+		s->data_ctx.stats.st_code = STAT_STATUS_NONE;
+		return 0;
 	}
 
 	*end_params = '\0';
@@ -2955,7 +2954,7 @@
 			next_param = cur_param;
 		}
 	}
-	return 0;
+	return 1;
 }
 
 /* This stream analyser runs all HTTP request processing which is common to
@@ -3195,7 +3194,28 @@
 		/* Was the status page requested with a POST ? */
 		if (txn->meth == HTTP_METH_POST) {
 			if (s->data_ctx.stats.flags & STAT_ADMIN) {
-				http_process_req_stat_post(s, req);
+				if (msg->msg_state < HTTP_MSG_100_SENT) {
+					/* If we have HTTP/1.1 and Expect: 100-continue, then we must
+					 * send an HTTP/1.1 100 Continue intermediate response.
+					 */
+					if (txn->flags & TX_REQ_VER_11) {
+						struct hdr_ctx ctx;
+						ctx.idx = 0;
+						/* Expect is allowed in 1.1, look for it */
+						if (http_find_header2("Expect", 6, msg->sol, &txn->hdr_idx, &ctx) &&
+						    unlikely(ctx.vlen == 12 && strncasecmp(ctx.line+ctx.val, "100-continue", 12) == 0)) {
+							buffer_write(s->rep, http_100_chunk.str, http_100_chunk.len);
+						}
+					}
+					msg->msg_state = HTTP_MSG_100_SENT;
+					s->logs.tv_request = now;  /* update the request timer to reflect full request */
+				}
+				if (!http_process_req_stat_post(s, req)) {
+					/* we need more data */
+					req->analysers |= an_bit;
+					buffer_dont_connect(req);
+					return 0;
+				}
 			} else {
 				s->data_ctx.stats.st_code = STAT_STATUS_DENY;
 			}