mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			230 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Java
		
	
	
	
			
		
		
	
	
			230 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Java
		
	
	
	
/* Copyright (C) 1999, 2000  Free Software Foundation
 | 
						|
 | 
						|
   This file is part of libgcj.
 | 
						|
 | 
						|
This software is copyrighted work licensed under the terms of the
 | 
						|
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
 | 
						|
details.  */
 | 
						|
 | 
						|
package java.util.zip;
 | 
						|
import java.io.*;
 | 
						|
 | 
						|
/**
 | 
						|
 * @author Per Bothner
 | 
						|
 * @date May 1999.
 | 
						|
 */
 | 
						|
 | 
						|
/*
 | 
						|
 * Written using on-line Java Platform 1.2 API Specification, as well
 | 
						|
 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
 | 
						|
 * Status:  Quite incomplete, but can read uncompressed .zip archives.
 | 
						|
 */
 | 
						|
 | 
						|
// JDK1.2 has "protected ZipEntry createZipEntry(String)" but is very
 | 
						|
// vague about what the method does.  FIXME.
 | 
						|
// We do not calculate the CRC and compare it with the specified value;
 | 
						|
// we probably should.  FIXME.
 | 
						|
   
 | 
						|
 | 
						|
public class ZipInputStream extends InflaterInputStream implements ZipConstants
 | 
						|
{
 | 
						|
  public ZipInputStream (InputStream in)
 | 
						|
  {
 | 
						|
    super (in, new Inflater (true));
 | 
						|
  }
 | 
						|
 | 
						|
  public ZipEntry getNextEntry () throws IOException
 | 
						|
  {
 | 
						|
    if (current != null)
 | 
						|
      closeEntry();
 | 
						|
    if (in.read() != 'P'
 | 
						|
	|| in.read() != 'K')
 | 
						|
      return null;
 | 
						|
    int code = in.read();
 | 
						|
    while (code == '\001')
 | 
						|
      {
 | 
						|
	code = in.read();
 | 
						|
	if (code != '\002')
 | 
						|
	  return null;
 | 
						|
	in.skip(16);
 | 
						|
	int size = read4();
 | 
						|
	in.skip(4);
 | 
						|
	int fname_length = readu2();
 | 
						|
	int extra_length = readu2();
 | 
						|
	int fcomment_length = readu2();
 | 
						|
	// `12' is the number of bytes between the comment length
 | 
						|
	// field and the end of the fixed part of the header:
 | 
						|
	// 2 bytes for `disk number start'
 | 
						|
	// 2 bytes for `internal file attributes'
 | 
						|
	// 4 bytes for `external file attributes'
 | 
						|
	// 4 bytes for `relative offset of local header'
 | 
						|
	in.skip(12 + fname_length + extra_length + fcomment_length);
 | 
						|
	if (in.read() != 'P' || in.read() != 'K')
 | 
						|
	  return null;
 | 
						|
	code = in.read();
 | 
						|
      }
 | 
						|
    if (code == '\005')
 | 
						|
      {
 | 
						|
	if (in.read() != '\006')
 | 
						|
	  return null;
 | 
						|
	in.skip(16);
 | 
						|
	int comment_size = readu2();
 | 
						|
	in.skip(comment_size);
 | 
						|
	if (in.read() != 'P' || in.read() != 'K')
 | 
						|
	  return null;
 | 
						|
	code = in.read();
 | 
						|
      }
 | 
						|
    if (code != '\003'
 | 
						|
	|| in.read() != '\004')
 | 
						|
      return null;
 | 
						|
    int ex_version = readu2();
 | 
						|
    current_flags = readu2();
 | 
						|
    int method = readu2();
 | 
						|
    int modtime = readu2();
 | 
						|
    int moddate = readu2();
 | 
						|
    int crc = read4();
 | 
						|
    int compressedSize = read4();
 | 
						|
    int uncompressedSize = read4();
 | 
						|
    int filenameLength = readu2();
 | 
						|
    int extraLength = readu2();
 | 
						|
    byte[] bname = new byte[filenameLength];
 | 
						|
    readFully(bname);
 | 
						|
    ZipEntry entry = new ZipEntry(new String(bname, "8859_1"));
 | 
						|
    if (extraLength > 0)
 | 
						|
      {
 | 
						|
	byte[] bextra = new byte[extraLength];
 | 
						|
	readFully(bextra);
 | 
						|
	entry.extra = bextra;
 | 
						|
      }
 | 
						|
    entry.compressedSize = compressedSize;
 | 
						|
    entry.size = uncompressedSize;
 | 
						|
    entry.crc = (long) crc & 0xffffffffL;
 | 
						|
    entry.method = method;
 | 
						|
    entry.time = ZipEntry.timeFromDOS(moddate, modtime);
 | 
						|
    current = entry;
 | 
						|
    avail = uncompressedSize;
 | 
						|
    compressed_bytes = compressedSize;
 | 
						|
    return entry;
 | 
						|
  }
 | 
						|
 | 
						|
  // We override fill to let us control how much data gets read from
 | 
						|
  // the underlying input stream.  This lets us avoid having to push
 | 
						|
  // back data.
 | 
						|
  protected void fill () throws IOException
 | 
						|
  {
 | 
						|
    int count = buf.length;
 | 
						|
    if (count > compressed_bytes)
 | 
						|
      count = compressed_bytes;
 | 
						|
    len = in.read(buf, 0, count);
 | 
						|
    if (len != -1)
 | 
						|
      {
 | 
						|
	compressed_bytes -= len;
 | 
						|
	inf.setInput(buf, 0, len);
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public int read (byte[] b, int off, int len)  throws IOException
 | 
						|
  {
 | 
						|
    if (len > avail)
 | 
						|
      len = avail;
 | 
						|
    int count;
 | 
						|
    if (current.method == Deflater.DEFLATED)
 | 
						|
      count = super.read(b, off, len);
 | 
						|
    else
 | 
						|
      count = in.read(b, off, len);
 | 
						|
    if (count == -1 || avail == 0)
 | 
						|
      {
 | 
						|
	inf.reset();
 | 
						|
	count = -1;
 | 
						|
      }
 | 
						|
    else
 | 
						|
      avail -= count;
 | 
						|
    return count;
 | 
						|
  }
 | 
						|
 | 
						|
  public long skip (long n)  throws IOException
 | 
						|
  {
 | 
						|
    if (n > avail)
 | 
						|
      n = avail;
 | 
						|
    long count;
 | 
						|
    if (current.method == Deflater.DEFLATED)
 | 
						|
      count = super.skip(n);
 | 
						|
    else
 | 
						|
      count = in.skip(n);
 | 
						|
    avail = avail - (int) count;
 | 
						|
    return count;
 | 
						|
  }
 | 
						|
 | 
						|
  private void readFully (byte[] b)  throws IOException
 | 
						|
  {
 | 
						|
    int off = 0;
 | 
						|
    int len = b.length;
 | 
						|
    while (len > 0)
 | 
						|
      {
 | 
						|
	int count = in.read(b, off, len);
 | 
						|
	if (count <= 0)
 | 
						|
	  throw new EOFException(".zip archive ended prematurely");
 | 
						|
	off += count;
 | 
						|
	len -= count;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  private int readu2 ()  throws IOException
 | 
						|
  {
 | 
						|
    int byte0 = in.read();
 | 
						|
    int byte1 = in.read();
 | 
						|
    if (byte0 < 0 || byte1 < 0)
 | 
						|
      throw new EOFException(".zip archive ended prematurely");
 | 
						|
    return ((byte1 & 0xFF) << 8) | (byte0 & 0xFF);
 | 
						|
  }
 | 
						|
 | 
						|
  private int read4 () throws IOException
 | 
						|
  {
 | 
						|
    int byte0 = in.read();
 | 
						|
    int byte1 = in.read();
 | 
						|
    int byte2 = in.read();
 | 
						|
    int byte3 = in.read();
 | 
						|
    if (byte3 < 0)
 | 
						|
      throw new EOFException(".zip archive ended prematurely");
 | 
						|
    return ((byte3 & 0xFF) << 24) + ((byte2 & 0xFF) << 16)
 | 
						|
      + ((byte1 & 0xFF) << 8) + (byte0 & 0xFF);
 | 
						|
  }
 | 
						|
 | 
						|
  public void closeEntry ()  throws IOException
 | 
						|
  {
 | 
						|
    if (current != null)
 | 
						|
      {
 | 
						|
	if (avail > 0)
 | 
						|
	  skip (avail);
 | 
						|
	if ((current_flags & 8) != 0)
 | 
						|
	  {
 | 
						|
	    int sig = read4();
 | 
						|
	    if (sig != 0x04034b50)
 | 
						|
	      throw new ZipException("bad/missing magic number at end of .zip entry");
 | 
						|
	    int crc = read4();
 | 
						|
	    int compressedSize = read4();
 | 
						|
	    int uncompressedSize = read4();
 | 
						|
	    if (current.compressedSize != compressedSize
 | 
						|
		|| current.size != uncompressedSize
 | 
						|
		|| current.crc != crc)
 | 
						|
	      throw new ZipException("bad data descriptor at end of .zip entry");
 | 
						|
	  }
 | 
						|
	current = null;
 | 
						|
	avail = 0;
 | 
						|
      }
 | 
						|
  }
 | 
						|
 | 
						|
  public void close ()  throws IOException
 | 
						|
  {
 | 
						|
    current = null;
 | 
						|
    super.close();
 | 
						|
  }
 | 
						|
 | 
						|
  private ZipEntry current;
 | 
						|
  private int current_flags;
 | 
						|
  // Number of uncompressed bytes to be read.
 | 
						|
  private int avail;
 | 
						|
  // Number of bytes we can read from underlying stream.
 | 
						|
  private int compressed_bytes;
 | 
						|
}
 |