Index: src/cf.data.pre
===================================================================
RCS file: /squid/squid/src/cf.data.pre,v
retrieving revision 1.471
diff -u -r1.471 cf.data.pre
--- src/cf.data.pre	27 Apr 2008 20:55:42 -0000	1.471
+++ src/cf.data.pre	9 May 2008 00:51:59 -0000
@@ -3234,17 +3234,24 @@
 DOC_END
 
 NAME: request_body_max_size
-COMMENT: (KB)
-TYPE: b_size_t
-DEFAULT: 0 KB
-LOC: Config.maxRequestBodySize
+COMMENT: bytes allow|deny acl acl...
+TYPE: body_size_t
+DEFAULT: none
+DEFAULT_IF_NONE: 0 allow all
+LOC: Config.RequestBodySize
 DOC_START
-	This specifies the maximum size for an HTTP request body.
-	In other words, the maximum size of a PUT/POST request.
-	A user who attempts to send a request with a body larger
-	than this limit receives an "Invalid Request" error message.
-	If you set this parameter to a zero (the default), there will
-	be no limit imposed.
+	This option specifies the maximum size of a request body in bytes.
+	It can be used to prevent users from uploading very large files. When
+	the request headers are received, the request_body_max_size lines are
+	processed, and the first line with a result of "allow" is used as the
+	maximum body size for this request.  This size is checked against the
+	content-length value in the request headers.  If the content length
+	value is larger than the allowed size, the request is denied and the
+	user receives an error message that says "the request or reply is too
+	large."
+
+	If you set this parameter to zero (the default), there will be
+	no limit imposed.
 DOC_END
 
 NAME: broken_posts
Index: src/client_side.c
===================================================================
RCS file: /squid/squid/src/client_side.c,v
retrieving revision 1.768
diff -u -r1.768 client_side.c
--- src/client_side.c	2 May 2008 20:09:59 -0000	1.768
+++ src/client_side.c	9 May 2008 00:52:00 -0000
@@ -151,7 +151,7 @@
 static DEFER httpAcceptDefer;
 static log_type clientProcessRequest2(clientHttpRequest * http);
 static int clientReplyBodyTooLarge(clientHttpRequest *, squid_off_t clen);
-static int clientRequestBodyTooLarge(squid_off_t clen);
+static int clientRequestBodyTooLarge(clientHttpRequest *, request_t *);
 static void clientProcessBody(ConnStateData * conn);
 static void clientEatRequestBody(clientHttpRequest *);
 static void clientAccessCheck(void *data);
@@ -2715,15 +2715,47 @@
 }
 #endif
 
+/*
+ * Calculates the maximum size allowed for an HTTP request body
+ */
+static void
+clientMaxRequestBodySize(request_t * request, clientHttpRequest * http)
+{
+    body_size *bs;
+    aclCheck_t *checklist;
+    if (http->log_type == LOG_TCP_DENIED)
+	    return;
+    bs = (body_size *) Config.RequestBodySize.head;
+    http->maxRequestBodySize = 0;
+    while (bs) {
+	    checklist = clientAclChecklistCreate(bs->access_list, http);
+	    if (aclCheckFast(bs->access_list, checklist) != 1) {
+	        /* deny - skip this entry */
+	        bs = (body_size *) bs->node.next;
+	    } else {
+	        /* Allow - use this entry */
+	        http->maxRequestBodySize = bs->maxsize;
+	        bs = NULL;
+	        debug(58, 3) ("clientMaxRequestBodySize: Setting maxRequestBodySize to %ld\n", (long int) http->maxRequestBodySize);
+	    }
+	    aclChecklistFree(checklist);
+    }
+}
+
 static int
-clientRequestBodyTooLarge(squid_off_t clen)
+clientRequestBodyTooLarge(clientHttpRequest * http, request_t * request)
 {
-    if (0 == Config.maxRequestBodySize)
-	return 0;		/* disabled */
-    if (clen < 0)
-	return 0;		/* unknown, bug? */
-    if (clen > Config.maxRequestBodySize)
-	return 1;		/* too large */
+    
+    if (http->maxRequestBodySize == -1) {
+        clientMaxRequestBodySize(request, http);
+    }
+
+    if (0 == http->maxRequestBodySize)
+	    return 0;		/* disabled */
+    if (request->content_length < 0)
+	    return 0;		/* unknown, bug? */
+    if (request->content_length > http->maxRequestBodySize)
+	    return 1;		/* too large */
     return 0;
 }
 
@@ -3767,6 +3799,7 @@
     http->start = current_time;
     http->req_sz = prefix_sz;
     http->range_iter.boundary = StringNull;
+    http->maxRequestBodySize = -1;
     dlinkAdd(http, &http->active, &ClientActiveRequests);
 
     debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n", hmsg->buf + hmsg->req_end);
@@ -4083,7 +4116,7 @@
 	    request->body_reader_data = conn;
 	    cbdataLock(conn);
 	    /* Is it too large? */
-	    if (clientRequestBodyTooLarge(request->content_length)) {
+	    if (clientRequestBodyTooLarge(http, request)) {
 		err = errorCon(ERR_TOO_BIG, HTTP_REQUEST_ENTITY_TOO_LARGE, request);
 		http->log_type = LOG_TCP_DENIED;
 		http->entry = clientCreateStoreEntry(http,
Index: src/structs.h
===================================================================
RCS file: /squid/squid/src/structs.h,v
retrieving revision 1.554
diff -u -r1.554 structs.h
--- src/structs.h	21 Apr 2008 02:28:14 -0000	1.554
+++ src/structs.h	9 May 2008 00:52:01 -0000
@@ -486,8 +486,8 @@
 #endif
     } Timeout;
     squid_off_t maxRequestHeaderSize;
-    squid_off_t maxRequestBodySize;
     squid_off_t maxReplyHeaderSize;
+    dlink_list RequestBodySize;
     dlink_list ReplyBodySize;
     dlink_list DelayBodySize;
     struct {
@@ -1280,6 +1280,7 @@
 	char *location;
     } redirect;
     dlink_node active;
+    squid_off_t maxRequestBodySize;
     squid_off_t maxBodySize;
     squid_off_t delayMaxBodySize;
     ushort delayAssignedPool;

