aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/util/zip/ZipInputStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/java/util/zip/ZipInputStream.java')
-rw-r--r--libjava/java/util/zip/ZipInputStream.java223
1 files changed, 223 insertions, 0 deletions
diff --git a/libjava/java/util/zip/ZipInputStream.java b/libjava/java/util/zip/ZipInputStream.java
new file mode 100644
index 00000000000..41b092d8133
--- /dev/null
+++ b/libjava/java/util/zip/ZipInputStream.java
@@ -0,0 +1,223 @@
+/* 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 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();
+ 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;
+ 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;
+}