COMPRESS-316 detect DEFLATE streams with ZLIB header, submitted by Nick Burch

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/compress/trunk@1681356 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 372a7cb..1d19877 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -54,6 +54,11 @@
 This also changes the superclass of ZCompressorInputStream.    
 ">
 
+      <action issue="COMPRESS-316" type="add" date="2015-05-23"
+              due-to=""Nick Burch">
+        CompressorStreamFactory can now auto-detect DEFLATE streams
+        with ZLIB header.
+      </action>
       <action issue="COMPRESS-314" type="fix" date="2015-05-08">
         TarArchiveInputStream can now read entries with group or
         user ids &gt; 0x80000000.
diff --git a/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java b/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java
index adca670..8dc3c52 100644
--- a/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java
+++ b/src/main/java/org/apache/commons/compress/compressors/CompressorStreamFactory.java
@@ -237,6 +237,10 @@
                 return new ZCompressorInputStream(in);
             }
 
+            if (DeflateCompressorInputStream.matches(signature, signatureLength)) {
+                return new DeflateCompressorInputStream(in);
+            }
+
             if (XZUtils.matches(signature, signatureLength) &&
                 XZUtils.isXZCompressionAvailable()) {
                 return new XZCompressorInputStream(in, decompressConcatenated);
diff --git a/src/main/java/org/apache/commons/compress/compressors/deflate/DeflateCompressorInputStream.java b/src/main/java/org/apache/commons/compress/compressors/deflate/DeflateCompressorInputStream.java
index a81a7a0..b8ed198 100644
--- a/src/main/java/org/apache/commons/compress/compressors/deflate/DeflateCompressorInputStream.java
+++ b/src/main/java/org/apache/commons/compress/compressors/deflate/DeflateCompressorInputStream.java
@@ -30,6 +30,12 @@
  * @since 1.9
  */
 public class DeflateCompressorInputStream extends CompressorInputStream {
+    private static final int MAGIC_1 = 0x78;
+    private static final int MAGIC_2a = 0x01;
+    private static final int MAGIC_2b = 0x5e;
+    private static final int MAGIC_2c = 0x9c;
+    private static final int MAGIC_2d = 0xda;
+    
     private final InputStream in;
 
     /**
@@ -88,4 +94,25 @@
     public void close() throws IOException {
         in.close();
     }
+    
+    /**
+     * Checks if the signature matches what is expected for a zlib / deflated file
+     *  with the zlib header.
+     * 
+     * @param signature
+     *            the bytes to check
+     * @param length
+     *            the number of bytes to check
+     * @return true, if this stream is zlib / deflate compressed with a header
+     * stream, false otherwise
+     * 
+     * @since 1.9
+     */
+    public static boolean matches(byte[] signature, int length) {
+        return length > 3 && signature[0] == MAGIC_1 && (
+                signature[1] == (byte) MAGIC_2a ||
+                signature[1] == (byte) MAGIC_2b ||
+                signature[1] == (byte) MAGIC_2c ||
+                signature[1] == (byte) MAGIC_2d);
+    }
 }
diff --git a/src/test/java/org/apache/commons/compress/compressors/DetectCompressorTestCase.java b/src/test/java/org/apache/commons/compress/compressors/DetectCompressorTestCase.java
index 0fc8424..218d913 100644
--- a/src/test/java/org/apache/commons/compress/compressors/DetectCompressorTestCase.java
+++ b/src/test/java/org/apache/commons/compress/compressors/DetectCompressorTestCase.java
@@ -30,6 +30,7 @@
 import org.apache.commons.compress.compressors.CompressorInputStream;
 import org.apache.commons.compress.compressors.CompressorStreamFactory;
 import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
+import org.apache.commons.compress.compressors.deflate.DeflateCompressorInputStream;
 import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
 import org.apache.commons.compress.compressors.pack200.Pack200CompressorInputStream;
 import org.apache.commons.compress.compressors.xz.XZCompressorInputStream;
@@ -104,6 +105,10 @@
         assertNotNull(xz);
         assertTrue(xz instanceof XZCompressorInputStream);
 
+        CompressorInputStream zlib = getStreamFor("bla.tar.deflatez");
+        assertNotNull(zlib);
+        assertTrue(zlib instanceof DeflateCompressorInputStream);
+
         try {
             factory.createCompressorInputStream(new ByteArrayInputStream(new byte[0]));
             fail("No exception thrown for an empty input stream");