This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/7.0.x by this push:
     new 0c756e4  Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63829
0c756e4 is described below

commit 0c756e4252cd1d3669fdb693990bc8da9820a615
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Oct 23 11:30:54 2019 +0200

    Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63829
    
    Improve the check of the Content-Encoding header when looking to see if
    Tomcat is serving pre-compressed content. Ensure that only a full token
    is matched and that the match is case insensitive.
---
 .../coyote/http11/AbstractHttp11Processor.java     | 35 +++++++++++-----------
 .../apache/coyote/http11/LocalStrings.properties   |  1 +
 .../apache/tomcat/util/http/parser/TokenList.java  | 24 ++++++++++++++-
 webapps/docs/changelog.xml                         |  6 ++++
 4 files changed, 47 insertions(+), 19 deletions(-)

diff --git a/java/org/apache/coyote/http11/AbstractHttp11Processor.java 
b/java/org/apache/coyote/http11/AbstractHttp11Processor.java
index 37ecc9a..2064f93 100644
--- a/java/org/apache/coyote/http11/AbstractHttp11Processor.java
+++ b/java/org/apache/coyote/http11/AbstractHttp11Processor.java
@@ -19,7 +19,6 @@ package org.apache.coyote.http11;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.io.StringReader;
-import java.util.Collection;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.List;
@@ -611,10 +610,21 @@ public abstract class AbstractHttp11Processor<S> extends 
AbstractProcessor<S> {
         // Check if content is not already compressed
         MessageBytes contentEncodingMB = 
response.getMimeHeaders().getValue("Content-Encoding");
 
-        if ((contentEncodingMB != null) &&
-                (contentEncodingMB.indexOf("gzip") != -1 ||
-                        contentEncodingMB.indexOf("br") != -1)) {
-            return false;
+        if (contentEncodingMB != null) {
+            // Content-Encoding values are ordered but order is not important
+            // for this check so use a Set rather than a List
+            Set<String> tokens = new HashSet<String>();
+            try {
+                
TokenList.parseTokenList(response.getMimeHeaders().values("Content-Encoding"), 
tokens);
+            } catch (IOException e) {
+                // Because we are using StringReader, any exception here is a
+                // Tomcat bug.
+                
getLog().warn(sm.getString("http11Processor.contentEncodingParseFail"), e);
+                return false;
+            }
+            if (tokens.contains("gzip") || tokens.contains("br")) {
+                return false;
+            }
         }
 
         // If force mode, always compress (test purposes only)
@@ -1342,7 +1352,7 @@ public abstract class AbstractHttp11Processor<S> extends 
AbstractProcessor<S> {
         MessageBytes connectionValueMB = 
headers.getValue(Constants.CONNECTION);
         if (connectionValueMB != null && !connectionValueMB.isNull()) {
             Set<String> tokens = new HashSet<String>();
-            parseConnectionTokens(headers, tokens);
+            TokenList.parseTokenList(headers.values(Constants.CONNECTION), 
tokens);
             if (tokens.contains(Constants.CLOSE)) {
                 keepAlive = false;
             } else if (tokens.contains(Constants.KEEPALIVE)) {
@@ -1758,22 +1768,11 @@ public abstract class AbstractHttp11Processor<S> 
extends AbstractProcessor<S> {
         }
 
         Set<String> tokens = new HashSet<String>();
-        parseConnectionTokens(headers, tokens);
+        TokenList.parseTokenList(headers.values(Constants.CONNECTION), tokens);
         return tokens.contains(token);
     }
 
 
-    private static void parseConnectionTokens(MimeHeaders headers, 
Collection<String> tokens) throws IOException {
-        Enumeration<String> values = headers.values(Constants.CONNECTION);
-        while (values.hasMoreElements()) {
-            String nextHeaderValue = values.nextElement();
-            if (nextHeaderValue != null) {
-                TokenList.parseTokenList(new StringReader(nextHeaderValue), 
tokens);
-            }
-        }
-    }
-
-
     protected abstract boolean prepareSendfile(OutputFilter[] outputFilters);
 
 
diff --git a/java/org/apache/coyote/http11/LocalStrings.properties 
b/java/org/apache/coyote/http11/LocalStrings.properties
index 7f3eb7e..ad41849 100644
--- a/java/org/apache/coyote/http11/LocalStrings.properties
+++ b/java/org/apache/coyote/http11/LocalStrings.properties
@@ -16,6 +16,7 @@
 http11Processor.upgrade=An internal error has occurred as upgraded connections 
should only be processed by the dedicated upgrade processor implementations
 
 http11processor.comet.notsupported=The Comet protocol is not supported by this 
connector
+http11Processor.contentEncodingParseFail=Failed to parse Content-Encoding 
header when chekcing to see if compression was already in use
 http11processor.fallToDebug=\n\
 \ Note: further occurrences of HTTP request parsing errors will be logged at 
DEBUG level.
 http11processor.filter.error=Error intializing filter [{0}]
diff --git a/java/org/apache/tomcat/util/http/parser/TokenList.java 
b/java/org/apache/tomcat/util/http/parser/TokenList.java
index 3837b51..7ba886c 100644
--- a/java/org/apache/tomcat/util/http/parser/TokenList.java
+++ b/java/org/apache/tomcat/util/http/parser/TokenList.java
@@ -18,7 +18,9 @@ package org.apache.tomcat.util.http.parser;
 
 import java.io.IOException;
 import java.io.Reader;
+import java.io.StringReader;
 import java.util.Collection;
+import java.util.Enumeration;
 import java.util.Locale;
 
 import org.apache.tomcat.util.http.parser.HttpParser.SkipResult;
@@ -31,12 +33,32 @@ public class TokenList {
 
 
     /**
+     * Parses an enumeration of header values of the form 1#token, forcing all
+     * parsed values to lower case.
+     *
+     * @param inputs The headers to parse
+     * @param result The Collection (usually a list of a set) to which the
+     *                   parsed tokens should be added
+     *
+     * @throws IOException If an I/O error occurs reading the header
+     */
+    public static void parseTokenList(Enumeration<String> inputs, 
Collection<String> result) throws IOException {
+        while (inputs.hasMoreElements()) {
+            String nextHeaderValue = inputs.nextElement();
+            if (nextHeaderValue != null) {
+                TokenList.parseTokenList(new StringReader(nextHeaderValue), 
result);
+            }
+        }
+    }
+
+
+    /**
      * Parses a header of the form 1#token, forcing all parsed values to lower
      * case. This is typically used when header values are case-insensitive.
      *
      * @param input  The header to parse
      * @param result The Collection (usually a list of a set) to which the
-     *                   parsed token should be added
+     *                   parsed tokens should be added
      *
      * @throws IOException If an I/O error occurs reading the header
      */
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index a6a0734..16c7cb4 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -92,6 +92,12 @@
         <code>Connection</code> HTTP headers looking for a specific token, be
         stricter in ensuring that the exact token is present. (markt)
       </fix>
+      <fix>
+        <bug>63829</bug>: Improve the check of the 
<code>Content-Encoding</code>
+        header when looking to see if Tomcat is serving pre-compressed content.
+        Ensure that only a full token is matched and that the match is case
+        insensitive. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Other">


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org
For additional commands, e-mail: dev-h...@tomcat.apache.org

Reply via email to