gcc/libjava/java/util/zip/ZipInputStream.java

191 lines
4.5 KiB
Java
Raw Normal View History

/* Copyright (C) 1999 Cygnus Solutions
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
{
ZipEntry current;
int current_flags;
int avail;
public ZipInputStream (InputStream in)
{
super(in);
}
public ZipEntry getNextEntry () throws IOException
{
if (current != null)
closeZipEntry();
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();
in.skip(12+fname_length+extra_length+fcomment_length+size);
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;
return entry;
}
public int read (byte[] b, int off, int len) throws IOException
{
if (len > avail)
len = avail;
int count = super.read(b, off, len);
if (count > 0)
avail -= count;
return count;
}
public long skip (long n) throws IOException
{
if (n > avail)
n = avail;
long count = super.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 closeZipEntry () throws IOException
{
if (current != null)
{
if (avail > 0)
skip (avail);
if ((current_flags & 8) != 0)
{
int sig = read4();
if (sig != 0x04034b50)
throw new IOException("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 IOException("bad data descriptor at end of .zip entry");
}
current = null;
avail = 0;
}
}
public void close () throws IOException
{
current = null;
super.close();
}
}