--- /home/cpdev/src/classpath/java/util/zip/GZIPInputStream.java	2005-07-02 21:03:49.000000000 +0000
+++ java/util/zip/GZIPInputStream.java	2005-06-30 05:34:52.000000000 +0000
@@ -35,12 +35,10 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package java.util.zip;
 
-import java.io.EOFException;
-import java.io.IOException;
 import java.io.InputStream;
+import java.io.IOException;
 
 /**
  * This filter stream is used to decompress a "GZIP" format stream. 
@@ -58,32 +56,34 @@
    */
   public static final int GZIP_MAGIC = 0x8b1f;
 
-  /**
-   * The mask for bit 0 of the flag byte.
-   */
-  static final int FTEXT = 0x1;
+  static final int Z_DEFLATED = 8;
 
   /**
    * The mask for bit 1 of the flag byte.
    */
-  static final int FHCRC = 0x2;
+  static final int HEAD_CRC = 0x02;
 
   /**
    * The mask for bit 2 of the flag byte.
    */
-  static final int FEXTRA = 0x4;
+  static final int EXTRA_FIELD = 0x04;
 
   /**
    * The mask for bit 3 of the flag byte.
    */
-  static final int FNAME = 0x8;
+  static final int ORIG_NAME = 0x08;
 
   /**
    * The mask for bit 4 of the flag byte.
    */
-  static final int FCOMMENT = 0x10;
+  static final int COMMENT = 0x10;
 
   /**
+   * The mask for all reserved bits of the flag byte.
+   */
+  static final int RESERVED = 0xe0;
+  
+  /**
    * The CRC-32 checksum value for uncompressed data.
    */
   protected CRC32 crc; 
@@ -94,11 +94,6 @@
   protected boolean eos;
 
   /**
-   * Indicates whether or not the GZIP header has been read in.
-   */
-  private boolean readGZIPHeader;
-
-  /**
    * Creates a GZIPInputStream with the default buffer size.
    *
    * @param in The stream to read compressed data from 
@@ -127,8 +122,60 @@
     throws IOException
   {
     super(in, new Inflater(true), size);
+
+    // NOTE: header reading code taken from zlib's gzio.c.
+
+    // Read the magic number.
+    int magic = eof_read() | (eof_read() << 8);
+    if (magic != GZIP_MAGIC)
+      throw new ZipException("gzip header corrupted");
+
+    int method = eof_read();
+    int flags = eof_read();
+    // Test from zlib.
+    if (method != Z_DEFLATED || (flags & RESERVED) != 0)
+      throw new ZipException("gzip header corrupted");
+
+    // Discard time, xflags, OS code.
+    for (int i = 0; i < 6; ++i)
+      eof_read();
+
+    // Skip the extra field.
+    if ((flags & EXTRA_FIELD) != 0)
+      {
+	int len = eof_read() | (eof_read() << 8);
+	while (len-- != 0)
+	  eof_read();
+      }
+
+    if ((flags & ORIG_NAME) != 0)
+      {
+	while (true)
+	  {
+	    int c = eof_read();
+	    if (c == 0)
+	      break;
+	  }
+      }
+
+    if ((flags & COMMENT) != 0)
+      {
+	while (true)
+	  {
+	    int c = eof_read();
+	    if (c == 0)
+	      break;
+	  }
+      }
+
+    if ((flags & HEAD_CRC) != 0)
+      {
+	// FIXME: consider checking CRC of the header.
+	eof_read();
+	eof_read();
+      }
+
     crc = new CRC32();
-    readHeader();
   }
 
   /**
@@ -143,6 +190,14 @@
     super.close();
   }
 
+  private final int eof_read() throws IOException
+  {
+    int r = in.read();
+    if (r == -1)
+      throw new ZipException("gzip header corrupted");
+    return r & 0xff;
+  }
+
   /**
    * Reads in GZIP-compressed data and stores it in uncompressed form
    * into an array of bytes.  The method will block until either
@@ -157,199 +212,41 @@
    */
   public int read(byte[] buf, int offset, int len) throws IOException
   {
-    // We first have to slurp in the GZIP header, then we feed all the
-    // rest of the data to the superclass.
-    //
-    // As we do that we continually update the CRC32. Once the data is
-    // finished, we check the CRC32.
-    //
-    // This means we don't need our own buffer, as everything is done
-    // in the superclass.
-    if (!readGZIPHeader)
-      readHeader();
-
     if (eos)
       return -1;
-
-    //  System.err.println("GZIPIS.read(byte[], off, len ... " + offset + " and len " + len);
-
-    /* We don't have to read the header,
-     * so we just grab data from the superclass.
-     */
-    int numRead = super.read(buf, offset, len);
-    if (numRead > 0)
-      crc.update(buf, offset, numRead);
-
-    if (inf.finished())
-      readFooter();
-    return numRead;
-  }
-
-
-  /**
-   * Reads in the GZIP header.
-   */
-  private void readHeader() throws IOException
-  {
-    /* 1. Check the two magic bytes */
-    CRC32 headCRC = new CRC32();
-    int magic = in.read();
-    if (magic < 0)
-    {
-      eos = true;
-      return;
-    }
-    int magic2 = in.read();
-    if ((magic + (magic2 << 8)) != GZIP_MAGIC)
-      throw new IOException("Error in GZIP header, bad magic code");
-    headCRC.update(magic);
-    headCRC.update(magic2);
-    
-    /* 2. Check the compression type (must be 8) */
-    int CM = in.read();
-    if (CM != 8)
-      throw new IOException("Error in GZIP header, data not in deflate format");
-    headCRC.update(CM);
-
-    /* 3. Check the flags */
-    int flags = in.read();
-    if (flags < 0)
-      throw new EOFException("Early EOF in GZIP header");
-    headCRC.update(flags);
-    
-    /*    This flag byte is divided into individual bits as follows:
-	  
-	  bit 0   FTEXT
-	  bit 1   FHCRC
-	  bit 2   FEXTRA
-	  bit 3   FNAME
-	  bit 4   FCOMMENT
-	  bit 5   reserved
-	  bit 6   reserved
-	  bit 7   reserved
-    */
-    
-    /* 3.1 Check the reserved bits are zero */    
-    if ((flags & 0xd0) != 0)
-      throw new IOException("Reserved flag bits in GZIP header != 0");
-    
-    /* 4.-6. Skip the modification time, extra flags, and OS type */
-    for (int i=0; i< 6; i++)
-    {
-      int readByte = in.read();
-      if (readByte < 0)
-	throw new EOFException("Early EOF in GZIP header");
-      headCRC.update(readByte);
-    }
-    
-    /* 7. Read extra field */
-    if ((flags & FEXTRA) != 0)
-    {
-      /* Skip subfield id */
-      for (int i=0; i< 2; i++)
+    int r = super.read(buf, offset, len);
+    if (r == -1)
       {
-        int readByte = in.read();
-	if (readByte < 0)
-	  throw new EOFException("Early EOF in GZIP header");
-	headCRC.update(readByte);
-      }
-      if (in.read() < 0 || in.read() < 0)
-	throw new EOFException("Early EOF in GZIP header");
-	
-      int len1, len2, extraLen;
-      len1 = in.read();
-      len2 = in.read();
-      if ((len1 < 0) || (len2 < 0))
-	throw new EOFException("Early EOF in GZIP header");
-      headCRC.update(len1);
-      headCRC.update(len2);
+	eos = true;
 
-      extraLen = (len1 << 8) | len2;
-      for (int i = 0; i < extraLen;i++)
-      {
-	int readByte = in.read();
-	if (readByte < 0)
-	  throw new EOFException("Early EOF in GZIP header");
-	headCRC.update(readByte);
+	byte[] tmp = new byte[8];
+	// First copy remaining bytes from inflater input buffer.
+	int avail = inf.getRemaining();
+	System.arraycopy(this.buf, this.len - avail, tmp, 0, avail);
+
+	// Now read remaining bytes from wrapped input stream.
+	for (int i = avail; i < 8; ++i)
+	  {
+	    tmp[i] = (byte) eof_read();
+	  }
+
+	// Be careful to avoid sign extension here; CRC32.getValue()
+	// returns a long.
+	long header_crc = read4(tmp, 0) & 0xffffffffL;
+	if (crc.getValue() != header_crc)
+	  throw new ZipException("corrupted gzip file - crc mismatch");
+	int isize = read4(tmp, 4);
+	if (inf.getTotalOut() != isize)
+	  throw new ZipException("corrupted gzip file - size mismatch");
+	return -1;
       }
-    }
-    
-    /* 8. Read file name */
-    if ((flags & FNAME) != 0)
-    {
-      int readByte;
-      while ( (readByte = in.read()) > 0)
-	headCRC.update(readByte);
-      if (readByte < 0)
-	throw new EOFException("Early EOF in GZIP file name");
-      headCRC.update(readByte);
-    }
-
-    /* 9. Read comment */
-    if ((flags & FCOMMENT) != 0)
-    {
-      int readByte;
-      while ( (readByte = in.read()) > 0)
-        headCRC.update(readByte);
-
-      if (readByte < 0)
-        throw new EOFException("Early EOF in GZIP comment");
-      headCRC.update(readByte);
-    }
-    
-    /* 10. Read header CRC */
-    if ((flags & FHCRC) != 0)
-    {
-      int tempByte;
-      int crcval = in.read();
-      if (crcval < 0)
-        throw new EOFException("Early EOF in GZIP header");
-	
-      tempByte = in.read();
-      if (tempByte < 0)
-        throw new EOFException("Early EOF in GZIP header");
-	
-      crcval = (crcval << 8) | tempByte;
-      if (crcval != ((int) headCRC.getValue() & 0xffff))
-        throw new IOException("Header CRC value mismatch");
-    }
-    
-    readGZIPHeader = true;
-    //System.err.println("Read GZIP header");
+    crc.update(buf, offset, r);
+    return r;
   }
 
-  private void readFooter() throws IOException
+  private final int read4(byte[] buf, int offset) throws IOException
   {
-    byte[] footer = new byte[8];
-    int avail = inf.getRemaining();
-    if (avail > 8)
-      avail = 8;
-    System.arraycopy(buf, len - inf.getRemaining(), footer, 0, avail);
-    int needed = 8 - avail;
-    while (needed > 0)
-    {
-      int count = in.read(footer, 8-needed, needed);
-      if (count <= 0)
-	throw new EOFException("Early EOF in GZIP footer");
-      needed -= count; //Jewel Jan 16
-    }
-
-    int crcval = (footer[0] & 0xff) | ((footer[1] & 0xff) << 8)
-      | ((footer[2] & 0xff) << 16) | (footer[3] << 24);
-    if (crcval != (int) crc.getValue())
-      throw new IOException("GZIP crc sum mismatch, theirs \""
-			    + Integer.toHexString(crcval)
-			    + "\" and ours \""
-			    + Integer.toHexString( (int) crc.getValue()));
-
-    int total = (footer[4] & 0xff) | ((footer[5] & 0xff) << 8)
-      | ((footer[6] & 0xff) << 16) | (footer[7] << 24);
-    if (total != inf.getTotalOut())
-      throw new IOException("Number of bytes mismatch");
-
-    /* FIXME" XXX Should we support multiple members.
-     * Difficult, since there may be some bytes still in buf
-     */
-    eos = true;
+    return (((buf[offset + 3] & 0xFF) << 24) + ((buf[offset + 2] & 0xFF) << 16)
+	    + ((buf[offset + 1] & 0xFF) << 8) + (buf[offset] & 0xFF));
   }
 }
