You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2008/05/09 23:59:02 UTC

svn commit: r654952 - in /httpd/httpd/trunk: CHANGES modules/filters/mod_request.c modules/filters/mod_request.h server/request.c

Author: minfrin
Date: Fri May  9 14:59:02 2008
New Revision: 654952

URL: http://svn.apache.org/viewvc?rev=654952&view=rev
Log:
mod_request: Insert the KEPT_BODY filter via the insert_filter
hook instead of during fixups. Add a safety check to ensure the
filters cannot be inserted more than once. [Graham Leggett,
Ruediger Pluem]

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/modules/filters/mod_request.c
    httpd/httpd/trunk/modules/filters/mod_request.h
    httpd/httpd/trunk/server/request.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=654952&r1=654951&r2=654952&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Fri May  9 14:59:02 2008
@@ -2,6 +2,11 @@
 Changes with Apache 2.3.0
 [ When backported to 2.2.x, remove entry from this file ]
 
+  *) mod_request: Insert the KEPT_BODY filter via the insert_filter
+     hook instead of during fixups. Add a safety check to ensure the
+     filters cannot be inserted more than once. [Graham Leggett,
+     Rüdiger Pluem]
+
   *) core: Do not allow Options ALL if not all options are allowed to be
      overwritten. PR 44262 [Michał Grzędzicki <lazy iq.pl>]
 

Modified: httpd/httpd/trunk/modules/filters/mod_request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/filters/mod_request.c?rev=654952&r1=654951&r2=654952&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/filters/mod_request.c (original)
+++ httpd/httpd/trunk/modules/filters/mod_request.c Fri May  9 14:59:02 2008
@@ -185,7 +185,7 @@
     if (kept_body) {
         apr_table_unset(r->headers_in, "Transfer-Encoding");
         apr_brigade_length(kept_body, 1, &length);
-        apr_table_set(r->headers_in, "Content-Length", apr_off_t_toa(r->pool, length));
+        apr_table_setn(r->headers_in, "Content-Length", apr_off_t_toa(r->pool, length));
     }
 
     return OK;
@@ -307,13 +307,11 @@
  * NOTE: File upload is not yet supported, but can be without change
  * to the function call.
  */
-AP_DECLARE(int) ap_parse_request_form(request_rec * r, apr_array_header_t ** ptr,
+AP_DECLARE(int) ap_parse_request_form(request_rec * r, ap_filter_t * f, 
+                                      apr_array_header_t ** ptr,
                                       apr_size_t num, apr_size_t size)
 {
-    request_dir_conf *dconf;
-    apr_off_t left = 0;
-    apr_bucket_brigade *bb = NULL, *kept_body = NULL;
-    apr_bucket *e;
+    apr_bucket_brigade *bb = NULL;
     int seen_eos = 0;
     char buffer[HUGE_STRING_LEN + 1];
     const char *ct;
@@ -333,18 +331,15 @@
         return ap_discard_request_body(r);
     }
 
-    dconf = ap_get_module_config(r->per_dir_config,
-                                     &request_module);
-    if (dconf->keep_body > 0) {
-        left = dconf->keep_body;
-        kept_body = apr_brigade_create(r->pool, r->connection->bucket_alloc);
+    if (!f) {
+        f = r->input_filters;
     }
 
     bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
     do {
         apr_bucket *bucket = NULL, *last = NULL;
 
-        int rv = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
+        int rv = ap_get_brigade(f, bb, AP_MODE_READBYTES,
                                 APR_BLOCK_READ, HUGE_STRING_LEN);
         if (rv != APR_SUCCESS) {
             apr_brigade_destroy(bb);
@@ -460,24 +455,6 @@
                 }
             }
 
-            /* If we have been asked to, keep the data up until the
-             * configured limit. If the limit is exceeded, we return an
-             * HTTP_REQUEST_ENTITY_TOO_LARGE response so the caller is
-             * clear the server couldn't handle their request.
-             */
-            if (kept_body) {
-                if (len <= left) {
-                    apr_bucket_copy(bucket, &e);
-                    APR_BRIGADE_INSERT_TAIL(kept_body, e);
-                    left -= len;
-                }
-                else {
-                    apr_brigade_destroy(bb);
-                    apr_brigade_destroy(kept_body);
-                    return HTTP_REQUEST_ENTITY_TOO_LARGE;
-                }
-            }
-
         }
 
         apr_brigade_cleanup(bb);
@@ -492,34 +469,69 @@
         APR_BRIGADE_INSERT_TAIL(pair->value, b);
     }
 
-    if (kept_body) {
-        r->kept_body = kept_body;
-    }
-
     return OK;
 
 }
 
 /**
- * Fixups hook.
+ * Check whether this filter is not already present.
+ */
+static int request_is_filter_present(request_rec * r, ap_filter_rec_t *fn)
+{
+    ap_filter_t * f = r->input_filters;
+    while (f) {
+        if (f->frec == fn) {
+            return 1;
+        }
+        f = f->next;
+    }
+    return 0;
+}
+
+/**
+ * Insert filter hook.
  * 
  * Add the KEEP_BODY filter to the request, if the admin wants to keep
  * the body using the KeptBodySize directive.
  * 
+ * As a precaution, any pre-existing instances of either the kept_body or
+ * keep_body filters will be removed before the filter is added.
+ * 
  * @param r The request
  */
-static int request_fixups(request_rec * r)
+AP_DECLARE(void) ap_request_insert_filter(request_rec * r)
 {
     request_dir_conf *conf = ap_get_module_config(r->per_dir_config,
                                                   &request_module);
 
-    if (conf->keep_body) {
-        ap_add_input_filter_handle(ap_keep_body_input_filter_handle,
-                                   NULL, r, r->connection);
+    if (r->kept_body) {
+        if (!request_is_filter_present(r, ap_kept_body_input_filter_handle)) {
+            ap_add_input_filter_handle(ap_kept_body_input_filter_handle,
+                                       NULL, r, r->connection);
+        }
+    }
+    else if (conf->keep_body) {
+        if (!request_is_filter_present(r, ap_kept_body_input_filter_handle)) {
+            ap_add_input_filter_handle(ap_keep_body_input_filter_handle,
+                                       NULL, r, r->connection);
+        }
     }
 
-    return OK;
+}
 
+/**
+ * Remove the kept_body and keep body filters from this specific request.
+ */
+AP_DECLARE(void) ap_request_remove_filter(request_rec * r)
+{
+    ap_filter_t * f = r->input_filters;
+    while (f) {
+        if (f->frec->filter_func.in_func == ap_kept_body_filter ||
+                f->frec->filter_func.in_func == ap_keep_body_filter) {
+            ap_remove_input_filter(f);
+        }
+        f = f->next;
+    }
 }
 
 static void *create_request_dir_config(apr_pool_t *p, char *dummy)
@@ -573,8 +585,10 @@
     ap_kept_body_input_filter_handle =
         ap_register_input_filter(KEPT_BODY_FILTER, ap_kept_body_filter,
                                  kept_body_filter_init, AP_FTYPE_RESOURCE);
-    ap_hook_fixups(request_fixups, NULL, NULL, APR_HOOK_MIDDLE);
+    ap_hook_insert_filter(ap_request_insert_filter, NULL, NULL, APR_HOOK_LAST);
     APR_REGISTER_OPTIONAL_FN(ap_parse_request_form);
+    APR_REGISTER_OPTIONAL_FN(ap_request_insert_filter);
+    APR_REGISTER_OPTIONAL_FN(ap_request_remove_filter);
 }
 
 module AP_MODULE_DECLARE_DATA request_module = {

Modified: httpd/httpd/trunk/modules/filters/mod_request.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/filters/mod_request.h?rev=654952&r1=654951&r2=654952&view=diff
==============================================================================
--- httpd/httpd/trunk/modules/filters/mod_request.h (original)
+++ httpd/httpd/trunk/modules/filters/mod_request.h Fri May  9 14:59:02 2008
@@ -66,6 +66,12 @@
                                              ap_input_mode_t mode, apr_read_type_e block,
                                              apr_off_t readbytes);
 
+/* Optional function to add either the keep body filter or kept body filter as appropriate */
+AP_DECLARE(void) ap_request_insert_filter(request_rec * r);
+
+/* Optional function to remove either the keep body filter or kept body filter as appropriate */
+AP_DECLARE(void) ap_request_remove_filter(request_rec * r);
+
 /**
  * Structure to store the contents of an HTTP form of the type
  * application/x-www-form-urlencoded.
@@ -111,15 +117,21 @@
  * NOTE: File upload is not yet supported, but can be without change
  * to the function call.
  */
-AP_DECLARE(int) ap_parse_request_form(request_rec * r, apr_array_header_t ** ptr,
+AP_DECLARE(int) ap_parse_request_form(request_rec * r, ap_filter_t * f, 
+                                      apr_array_header_t ** ptr,
                                       apr_size_t num, apr_size_t size);
 
-APR_DECLARE_OPTIONAL_FN(int, ap_parse_request_form, (request_rec * r, apr_array_header_t ** ptr,
+APR_DECLARE_OPTIONAL_FN(int, ap_parse_request_form, (request_rec * r, ap_filter_t * f, 
+                                                     apr_array_header_t ** ptr,
                                                      apr_size_t num, apr_size_t size));
 
+APR_DECLARE_OPTIONAL_FN(void, ap_request_insert_filter, (request_rec * r));
+
+APR_DECLARE_OPTIONAL_FN(void, ap_request_remove_filter, (request_rec * r));
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif	/* !MOD_REQUEST_H */
+#endif /* !MOD_REQUEST_H */
 /** @} */

Modified: httpd/httpd/trunk/server/request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/request.c?rev=654952&r1=654951&r2=654952&view=diff
==============================================================================
--- httpd/httpd/trunk/server/request.c (original)
+++ httpd/httpd/trunk/server/request.c Fri May  9 14:59:02 2008
@@ -1645,13 +1645,6 @@
     /* Pass on the kept body (if any) into the new request. */
     rnew->kept_body = r->kept_body;
 
-    /*
-     * Add the KEPT_BODY filter, which will insert any body marked to be
-     * kept for the use of a subrequest, into the subrequest.
-     */
-    ap_add_input_filter(KEPT_BODY_FILTER,
-                        NULL, rnew, rnew->connection);
-
     return rnew;
 }