Repository: netty/netty
Issue: HttpContentEncoder/Decoder accepts the encoding whose qvalue is 0
Labels: defect

The following accept-encoding headers have 0 qvalue which means 'do not accept', but Netty does not handle qvalues at all.  We at least handle the case where qvalue is 0 or invalid so that we don't accept the wrong encodings.

```
[deflate;q=0, gzip, x-gzip, compress, x-compress]=> [gzip, x-gzip, compress, x-compress]
[identity, *; q=0]=> [identity]
```


Issue comments:

Pull request review comments:

Patch that resolved the issue:
diff --git a/src/main/java/org/jboss/netty/handler/codec/http/HttpContentCompressor.java b/src/main/java/org/jboss/netty/handler/codec/http/HttpContentCompressor.java
index 803c2c53b56..8f455234f2f 100644
--- a/src/main/java/org/jboss/netty/handler/codec/http/HttpContentCompressor.java
+++ b/src/main/java/org/jboss/netty/handler/codec/http/HttpContentCompressor.java
@@ -83,12 +83,42 @@ protected String getTargetContentEncoding(String acceptEncoding) throws Exceptio
     }
 
     private ZlibWrapper determineWrapper(String acceptEncoding) {
-        // FIXME: Use the Q value.
-        if (acceptEncoding.indexOf("gzip") >= 0) {
-            return ZlibWrapper.GZIP;
+        float starQ = -1.0f;
+        float gzipQ = -1.0f;
+        float deflateQ = -1.0f;
+        for (String encoding : acceptEncoding.split(",")) {
+            float q = 1.0f;
+            int equalsPos = encoding.indexOf('=');
+            if (equalsPos != -1) {
+                try {
+                    q = Float.valueOf(encoding.substring(equalsPos + 1));
+                } catch (NumberFormatException e) {
+                    // Ignore encoding
+                    q = 0.0f;
+                }
+            }
+            if (encoding.indexOf("*") >= 0) {
+                starQ = q;
+            } else if (encoding.indexOf("gzip") >= 0 && q > gzipQ) {
+                gzipQ = q;
+            } else if (encoding.indexOf("deflate") >= 0 && q > deflateQ) {
+                deflateQ = q;
+            }
         }
-        if (acceptEncoding.indexOf("deflate") >= 0) {
-            return ZlibWrapper.ZLIB;
+        if (gzipQ > 0.0f || deflateQ > 0.0f) {
+            if (gzipQ >= deflateQ) {
+                return ZlibWrapper.GZIP;
+            } else {
+                return ZlibWrapper.ZLIB;
+            }
+        }
+        if (starQ > 0.0f) {
+            if (gzipQ == -1.0f) {
+                return ZlibWrapper.GZIP;
+            }
+            if (deflateQ == -1.0f) {
+                return ZlibWrapper.ZLIB;
+            }
         }
         return null;
     }


Test patch:
diff --git a/src/test/java/org/jboss/netty/handler/codec/http/HttpContentCompressorTest.java b/src/test/java/org/jboss/netty/handler/codec/http/HttpContentCompressorTest.java
new file mode 100644
index 00000000000..3fb962ccabd
--- /dev/null
+++ b/src/test/java/org/jboss/netty/handler/codec/http/HttpContentCompressorTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package org.jboss.netty.handler.codec.http;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class HttpContentCompressorTest {
+
+    private HttpContentCompressor httpContentCompressor =
+        new HttpContentCompressor();
+
+    @Test
+    public void testGetTargetContentEncoding() throws Exception {
+        HttpContentCompressor compressor = new HttpContentCompressor();
+
+        String[] tests = {
+            // Accept-Encoding      ->     Content-Encoding
+            "",                            null,
+            "*",                           "gzip",
+            "*;q=0.0",                     null,
+            "gzip",                        "gzip",
+            "compress, gzip;q=0.5",        "gzip",
+            "gzip; q=0.5, identity",       "gzip",
+            "gzip ; q=0.1",                "gzip",
+            "gzip; q=0, deflate",          "deflate",
+            " defalte ; q=0 , *;q=0.5",    "gzip",
+        };
+        for (int i = 0; i < tests.length; i += 2) {
+            String acceptEncoding = tests[i];
+            String contentEncoding = tests[i + 1];
+            String targetEncoding = compressor.getTargetContentEncoding(acceptEncoding);
+            Assert.assertEquals(contentEncoding, targetEncoding);
+        }
+    }
+}