]> granicus.if.org Git - apache/commitdiff
Fix protocol handling in mod_deflate input filter
authorNick Kew <niq@apache.org>
Sun, 29 Jul 2007 08:35:56 +0000 (08:35 +0000)
committerNick Kew <niq@apache.org>
Sun, 29 Jul 2007 08:35:56 +0000 (08:35 +0000)
PR 23287

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@560689 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
modules/filters/mod_deflate.c

diff --git a/CHANGES b/CHANGES
index 4acc7d213202bee277f106707c3b020a56f0a456..433d46c6f719999eae2d62c09b6dfd7acb5166c4 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@
 Changes with Apache 2.3.0
   [Remove entries to the current 2.0 and 2.2 section below, when backported]
 
+  *) mod_deflate: fix protocol handling in deflate input filter
+     PR 23287 [Nick Kew]
+
   *) mod_ldap, mod_authnzldap: Add support for nested groups (i.e. the ability
      to authorize an authenticated user via a "require ldap-group X" directive
      where the user is not in group X, but is in a subgroup contained in X.
index 2cbb993da7a0f915c09002460208e99f7e68dcb6..0028429b80d9aead98e9443fc5b1d0d375f2fa8d 100644 (file)
@@ -665,22 +665,52 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
             return ap_get_brigade(f->next, bb, mode, block, readbytes);
         }
 
-        /* Let's see what our current Content-Encoding is.
-         * If gzip is present, don't gzip again.  (We could, but let's not.)
+        /* Check whether request body is gzipped.
+         *
+         * If it is, we're transforming the contents, invalidating
+         * some request headers including Content-Encoding.
+         *
+         * If not, we just remove ourself.
          */
         encoding = apr_table_get(r->headers_in, "Content-Encoding");
-        if (encoding) {
+        if (encoding && *encoding) {
             const char *tmp = encoding;
 
-            token = ap_get_token(r->pool, &tmp, 0);
-            while (token && token[0]) {
-                if (!strcasecmp(token, "gzip")) {
-                    found = 1;
-                    break;
-                }
-                /* Otherwise, skip token */
-                tmp++;
+            /* check the usual/simple case first */
+            if (!strcasecmp(encoding, "gzip")) {
+                found = 1;
+                apr_table_unset(r->headers_in, "Content-Encoding");
+            }
+            else {
                 token = ap_get_token(r->pool, &tmp, 0);
+                while (token && token[0]) {
+                    if (!strcasecmp(token, "gzip")) {
+                        char *new_encoding = apr_pstrdup(r->pool, encoding);
+                        char *ptr = ap_strstr(new_encoding, token);
+                        size_t sz = 5*sizeof(char);
+                        if (ptr == new_encoding) {
+                            /* remove "gzip:" at start */
+                            memmove(ptr, ptr+sz, sz);
+                        }
+                        else {
+                            /* remove ":gzip" as found */
+                            memmove(ptr-sizeof(char), ptr+4*sizeof(char), sz);
+                        }
+                        /* Silly edge-case: if there's more than one "gzip"
+                         * token, this is a maybe-bug, as we remove exactly
+                         * one gzip token.  But it's not really our bug:
+                         * two gzips should mean it's double-gzipped,
+                         * shouldn't it?  Insert this filter twice!
+                         */
+                        apr_table_setn(r->headers_in, "Content-Encoding",
+                                       new_encoding);
+                        found = 1;
+                        break;
+                    }
+                    /* Otherwise, skip token */
+                    tmp++;
+                    token = ap_get_token(r->pool, &tmp, 0);
+                }
             }
         }
 
@@ -688,6 +718,9 @@ static apr_status_t deflate_in_filter(ap_filter_t *f,
             ap_remove_input_filter(f);
             return ap_get_brigade(f->next, bb, mode, block, readbytes);
         }
+        apr_table_unset(r->headers_in, "Content-Length");
+        apr_table_unset(r->headers_in, "Content-MD5");
+        apr_table_unset(r->headers_in, "Content-Range");
 
         f->ctx = ctx = apr_pcalloc(f->r->pool, sizeof(*ctx));
         ctx->bb = apr_brigade_create(r->pool, f->c->bucket_alloc);