# HG changeset patch
# User Jaroslav Tulach The following code fragment demonstrates a trivial compression
+ * and decompression of a string using Deflater and
+ * Inflater.
+ *
+ *
+ * Note: When using the 'nowrap' option it is also necessary to provide
+ * an extra "dummy" byte as input. This is required by the ZLIB native
+ * library in order to support certain optimizations.
+ *
+ * @param nowrap if true then support GZIP compatible compression
+ */
+ public Inflater(boolean nowrap) {
+ zsRef = new ZStreamRef(init(nowrap));
+ }
+
+ /**
+ * Creates a new decompressor.
+ */
+ public Inflater() {
+ this(false);
+ }
+
+ /**
+ * Sets input data for decompression. Should be called whenever
+ * needsInput() returns true indicating that more input data is
+ * required.
+ * @param b the input data bytes
+ * @param off the start offset of the input data
+ * @param len the length of the input data
+ * @see Inflater#needsInput
+ */
+ public void setInput(byte[] b, int off, int len) {
+ if (b == null) {
+ throw new NullPointerException();
+ }
+ if (off < 0 || len < 0 || off > b.length - len) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ synchronized (zsRef) {
+ this.buf = b;
+ this.off = off;
+ this.len = len;
+ }
+ }
+
+ /**
+ * Sets input data for decompression. Should be called whenever
+ * needsInput() returns true indicating that more input data is
+ * required.
+ * @param b the input data bytes
+ * @see Inflater#needsInput
+ */
+ public void setInput(byte[] b) {
+ setInput(b, 0, b.length);
+ }
+
+ /**
+ * Sets the preset dictionary to the given array of bytes. Should be
+ * called when inflate() returns 0 and needsDictionary() returns true
+ * indicating that a preset dictionary is required. The method getAdler()
+ * can be used to get the Adler-32 value of the dictionary needed.
+ * @param b the dictionary data bytes
+ * @param off the start offset of the data
+ * @param len the length of the data
+ * @see Inflater#needsDictionary
+ * @see Inflater#getAdler
+ */
+ public void setDictionary(byte[] b, int off, int len) {
+ if (b == null) {
+ throw new NullPointerException();
+ }
+ if (off < 0 || len < 0 || off > b.length - len) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ synchronized (zsRef) {
+ ensureOpen();
+ setDictionary(zsRef.address(), b, off, len);
+ needDict = false;
+ }
+ }
+
+ /**
+ * Sets the preset dictionary to the given array of bytes. Should be
+ * called when inflate() returns 0 and needsDictionary() returns true
+ * indicating that a preset dictionary is required. The method getAdler()
+ * can be used to get the Adler-32 value of the dictionary needed.
+ * @param b the dictionary data bytes
+ * @see Inflater#needsDictionary
+ * @see Inflater#getAdler
+ */
+ public void setDictionary(byte[] b) {
+ setDictionary(b, 0, b.length);
+ }
+
+ /**
+ * Returns the total number of bytes remaining in the input buffer.
+ * This can be used to find out what bytes still remain in the input
+ * buffer after decompression has finished.
+ * @return the total number of bytes remaining in the input buffer
+ */
+ public int getRemaining() {
+ synchronized (zsRef) {
+ return len;
+ }
+ }
+
+ /**
+ * Returns true if no data remains in the input buffer. This can
+ * be used to determine if #setInput should be called in order
+ * to provide more input.
+ * @return true if no data remains in the input buffer
+ */
+ public boolean needsInput() {
+ synchronized (zsRef) {
+ return len <= 0;
+ }
+ }
+
+ /**
+ * Returns true if a preset dictionary is needed for decompression.
+ * @return true if a preset dictionary is needed for decompression
+ * @see Inflater#setDictionary
+ */
+ public boolean needsDictionary() {
+ synchronized (zsRef) {
+ return needDict;
+ }
+ }
+
+ /**
+ * Returns true if the end of the compressed data stream has been
+ * reached.
+ * @return true if the end of the compressed data stream has been
+ * reached
+ */
+ public boolean finished() {
+ synchronized (zsRef) {
+ return finished;
+ }
+ }
+
+ /**
+ * Uncompresses bytes into specified buffer. Returns actual number
+ * of bytes uncompressed. A return value of 0 indicates that
+ * needsInput() or needsDictionary() should be called in order to
+ * determine if more input data or a preset dictionary is required.
+ * In the latter case, getAdler() can be used to get the Adler-32
+ * value of the dictionary required.
+ * @param b the buffer for the uncompressed data
+ * @param off the start offset of the data
+ * @param len the maximum number of uncompressed bytes
+ * @return the actual number of uncompressed bytes
+ * @exception DataFormatException if the compressed data format is invalid
+ * @see Inflater#needsInput
+ * @see Inflater#needsDictionary
+ */
+ public int inflate(byte[] b, int off, int len)
+ throws DataFormatException
+ {
+ if (b == null) {
+ throw new NullPointerException();
+ }
+ if (off < 0 || len < 0 || off > b.length - len) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ synchronized (zsRef) {
+ ensureOpen();
+ return inflateBytes(zsRef.address(), b, off, len);
+ }
+ }
+
+ /**
+ * Uncompresses bytes into specified buffer. Returns actual number
+ * of bytes uncompressed. A return value of 0 indicates that
+ * needsInput() or needsDictionary() should be called in order to
+ * determine if more input data or a preset dictionary is required.
+ * In the latter case, getAdler() can be used to get the Adler-32
+ * value of the dictionary required.
+ * @param b the buffer for the uncompressed data
+ * @return the actual number of uncompressed bytes
+ * @exception DataFormatException if the compressed data format is invalid
+ * @see Inflater#needsInput
+ * @see Inflater#needsDictionary
+ */
+ public int inflate(byte[] b) throws DataFormatException {
+ return inflate(b, 0, b.length);
+ }
+
+ /**
+ * Returns the ADLER-32 value of the uncompressed data.
+ * @return the ADLER-32 value of the uncompressed data
+ */
+ public int getAdler() {
+ synchronized (zsRef) {
+ ensureOpen();
+ return getAdler(zsRef.address());
+ }
+ }
+
+ /**
+ * Returns the total number of compressed bytes input so far.
+ *
+ * Since the number of bytes may be greater than
+ * Integer.MAX_VALUE, the {@link #getBytesRead()} method is now
+ * the preferred means of obtaining this information.
+ *
+ * @see Deflater
+ * @author David Connelly
+ *
+ */
+public
+class Inflater {
+
+ private final ZStreamRef zsRef;
+ private byte[] buf = defaultBuf;
+ private int off, len;
+ private boolean finished;
+ private boolean needDict;
+
+ private static final byte[] defaultBuf = new byte[0];
+
+ static {
+ /* Zip library is loaded from System.initializeSystemClass */
+ initIDs();
+ }
+
+ /**
+ * Creates a new decompressor. If the parameter 'nowrap' is true then
+ * the ZLIB header and checksum fields will not be used. This provides
+ * compatibility with the compression format used by both GZIP and PKZIP.
+ *
+ * try {
+ * // Encode a String into bytes
+ * String inputString = "blahblahblah\u20AC\u20AC";
+ * byte[] input = inputString.getBytes("UTF-8");
+ *
+ * // Compress the bytes
+ * byte[] output = new byte[100];
+ * Deflater compresser = new Deflater();
+ * compresser.setInput(input);
+ * compresser.finish();
+ * int compressedDataLength = compresser.deflate(output);
+ *
+ * // Decompress the bytes
+ * Inflater decompresser = new Inflater();
+ * decompresser.setInput(output, 0, compressedDataLength);
+ * byte[] result = new byte[100];
+ * int resultLength = decompresser.inflate(result);
+ * decompresser.end();
+ *
+ * // Decode the bytes into a String
+ * String outputString = new String(result, 0, resultLength, "UTF-8");
+ * } catch(java.io.UnsupportedEncodingException ex) {
+ * // handle
+ * } catch (java.util.zip.DataFormatException ex) {
+ * // handle
+ * }
+ *
Since the number of bytes may be greater than + * Integer.MAX_VALUE, the {@link #getBytesWritten()} method is now + * the preferred means of obtaining this information.
+ * + * @return the total number of uncompressed bytes output so far + */ + public int getTotalOut() { + return (int) getBytesWritten(); + } + + /** + * Returns the total number of uncompressed bytes output so far. + * + * @return the total (non-negative) number of uncompressed bytes output so far + * @since 1.5 + */ + public long getBytesWritten() { + synchronized (zsRef) { + ensureOpen(); + return getBytesWritten(zsRef.address()); + } + } + + /** + * Resets inflater so that a new set of input data can be processed. + */ + public void reset() { + synchronized (zsRef) { + ensureOpen(); + reset(zsRef.address()); + buf = defaultBuf; + finished = false; + needDict = false; + off = len = 0; + } + } + + /** + * Closes the decompressor and discards any unprocessed input. + * This method should be called when the decompressor is no longer + * being used, but will also be called automatically by the finalize() + * method. Once this method is called, the behavior of the Inflater + * object is undefined. + */ + public void end() { + synchronized (zsRef) { + long addr = zsRef.address(); + zsRef.clear(); + if (addr != 0) { + end(addr); + buf = null; + } + } + } + + /** + * Closes the decompressor when garbage is collected. + */ + protected void finalize() { + end(); + } + + private void ensureOpen () { + assert Thread.holdsLock(zsRef); + if (zsRef.address() == 0) + throw new NullPointerException("Inflater has been closed"); + } + + boolean ended() { + synchronized (zsRef) { + return zsRef.address() == 0; + } + } + + private native static void initIDs(); + private native static long init(boolean nowrap); + private native static void setDictionary(long addr, byte[] b, int off, + int len); + private native int inflateBytes(long addr, byte[] b, int off, int len) + throws DataFormatException; + private native static int getAdler(long addr); + private native static long getBytesRead(long addr); + private native static long getBytesWritten(long addr); + private native static void reset(long addr); + private native static void end(long addr); +} diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/InflaterInputStream.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/emul/mini/src/main/java/java/util/zip/InflaterInputStream.java Wed Jan 30 14:00:17 2013 +0100 @@ -0,0 +1,288 @@ +/* + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.util.zip; + +import java.io.FilterInputStream; +import java.io.InputStream; +import java.io.IOException; +import java.io.EOFException; + +/** + * This class implements a stream filter for uncompressing data in the + * "deflate" compression format. It is also used as the basis for other + * decompression filters, such as GZIPInputStream. + * + * @see Inflater + * @author David Connelly + */ +public +class InflaterInputStream extends FilterInputStream { + /** + * Decompressor for this stream. + */ + protected Inflater inf; + + /** + * Input buffer for decompression. + */ + protected byte[] buf; + + /** + * Length of input buffer. + */ + protected int len; + + private boolean closed = false; + // this flag is set to true after EOF has reached + private boolean reachEOF = false; + + /** + * Check to make sure that this stream has not been closed + */ + private void ensureOpen() throws IOException { + if (closed) { + throw new IOException("Stream closed"); + } + } + + + /** + * Creates a new input stream with the specified decompressor and + * buffer size. + * @param in the input stream + * @param inf the decompressor ("inflater") + * @param size the input buffer size + * @exception IllegalArgumentException if size is <= 0 + */ + public InflaterInputStream(InputStream in, Inflater inf, int size) { + super(in); + if (in == null || inf == null) { + throw new NullPointerException(); + } else if (size <= 0) { + throw new IllegalArgumentException("buffer size <= 0"); + } + this.inf = inf; + buf = new byte[size]; + } + + /** + * Creates a new input stream with the specified decompressor and a + * default buffer size. + * @param in the input stream + * @param inf the decompressor ("inflater") + */ + public InflaterInputStream(InputStream in, Inflater inf) { + this(in, inf, 512); + } + + boolean usesDefaultInflater = false; + + /** + * Creates a new input stream with a default decompressor and buffer size. + * @param in the input stream + */ + public InflaterInputStream(InputStream in) { + this(in, new Inflater()); + usesDefaultInflater = true; + } + + private byte[] singleByteBuf = new byte[1]; + + /** + * Reads a byte of uncompressed data. This method will block until + * enough input is available for decompression. + * @return the byte read, or -1 if end of compressed input is reached + * @exception IOException if an I/O error has occurred + */ + public int read() throws IOException { + ensureOpen(); + return read(singleByteBuf, 0, 1) == -1 ? -1 : singleByteBuf[0] & 0xff; + } + + /** + * Reads uncompressed data into an array of bytes. Iflen
is not
+ * zero, the method will block until some input can be decompressed; otherwise,
+ * no bytes are read and 0
is returned.
+ * @param b the buffer into which the data is read
+ * @param off the start offset in the destination array b
+ * @param len the maximum number of bytes read
+ * @return the actual number of bytes read, or -1 if the end of the
+ * compressed input is reached or a preset dictionary is needed
+ * @exception NullPointerException If b
is null
.
+ * @exception IndexOutOfBoundsException If off
is negative,
+ * len
is negative, or len
is greater than
+ * b.length - off
+ * @exception ZipException if a ZIP format error has occurred
+ * @exception IOException if an I/O error has occurred
+ */
+ public int read(byte[] b, int off, int len) throws IOException {
+ ensureOpen();
+ if (b == null) {
+ throw new NullPointerException();
+ } else if (off < 0 || len < 0 || len > b.length - off) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+ try {
+ int n;
+ while ((n = inf.inflate(b, off, len)) == 0) {
+ if (inf.finished() || inf.needsDictionary()) {
+ reachEOF = true;
+ return -1;
+ }
+ if (inf.needsInput()) {
+ fill();
+ }
+ }
+ return n;
+ } catch (DataFormatException e) {
+ String s = e.getMessage();
+ throw new ZipException(s != null ? s : "Invalid ZLIB data format");
+ }
+ }
+
+ /**
+ * Returns 0 after EOF has been reached, otherwise always return 1.
+ *
+ * Programs should not count on this method to return the actual number
+ * of bytes that could be read without blocking.
+ *
+ * @return 1 before EOF and 0 after EOF.
+ * @exception IOException if an I/O error occurs.
+ *
+ */
+ public int available() throws IOException {
+ ensureOpen();
+ if (reachEOF) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ private byte[] b = new byte[512];
+
+ /**
+ * Skips specified number of bytes of uncompressed data.
+ * @param n the number of bytes to skip
+ * @return the actual number of bytes skipped.
+ * @exception IOException if an I/O error has occurred
+ * @exception IllegalArgumentException if n < 0
+ */
+ public long skip(long n) throws IOException {
+ if (n < 0) {
+ throw new IllegalArgumentException("negative skip length");
+ }
+ ensureOpen();
+ int max = (int)Math.min(n, Integer.MAX_VALUE);
+ int total = 0;
+ while (total < max) {
+ int len = max - total;
+ if (len > b.length) {
+ len = b.length;
+ }
+ len = read(b, 0, len);
+ if (len == -1) {
+ reachEOF = true;
+ break;
+ }
+ total += len;
+ }
+ return total;
+ }
+
+ /**
+ * Closes this input stream and releases any system resources associated
+ * with the stream.
+ * @exception IOException if an I/O error has occurred
+ */
+ public void close() throws IOException {
+ if (!closed) {
+ if (usesDefaultInflater)
+ inf.end();
+ in.close();
+ closed = true;
+ }
+ }
+
+ /**
+ * Fills input buffer with more data to decompress.
+ * @exception IOException if an I/O error has occurred
+ */
+ protected void fill() throws IOException {
+ ensureOpen();
+ len = in.read(buf, 0, buf.length);
+ if (len == -1) {
+ throw new EOFException("Unexpected end of ZLIB input stream");
+ }
+ inf.setInput(buf, 0, len);
+ }
+
+ /**
+ * Tests if this input stream supports the mark
and
+ * reset
methods. The markSupported
+ * method of InflaterInputStream
returns
+ * false
.
+ *
+ * @return a boolean
indicating if this stream type supports
+ * the mark
and reset
methods.
+ * @see java.io.InputStream#mark(int)
+ * @see java.io.InputStream#reset()
+ */
+ public boolean markSupported() {
+ return false;
+ }
+
+ /**
+ * Marks the current position in this input stream.
+ *
+ *
The mark
method of InflaterInputStream
+ * does nothing.
+ *
+ * @param readlimit the maximum limit of bytes that can be read before
+ * the mark position becomes invalid.
+ * @see java.io.InputStream#reset()
+ */
+ public synchronized void mark(int readlimit) {
+ }
+
+ /**
+ * Repositions this stream to the position at the time the
+ * mark
method was last called on this input stream.
+ *
+ *
The method reset
for class
+ * InflaterInputStream
does nothing except throw an
+ * IOException
.
+ *
+ * @exception IOException if this method is invoked.
+ * @see java.io.InputStream#mark(int)
+ * @see java.io.IOException
+ */
+ public synchronized void reset() throws IOException {
+ throw new IOException("mark/reset not supported");
+ }
+}
diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZStreamRef.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/mini/src/main/java/java/util/zip/ZStreamRef.java Wed Jan 30 14:00:17 2013 +0100
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.zip;
+
+/**
+ * A reference to the native zlib's z_stream structure.
+ */
+
+class ZStreamRef {
+
+ private long address;
+ ZStreamRef (long address) {
+ this.address = address;
+ }
+
+ long address() {
+ return address;
+ }
+
+ void clear() {
+ address = 0;
+ }
+}
diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipConstants.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/mini/src/main/java/java/util/zip/ZipConstants.java Wed Jan 30 14:00:17 2013 +0100
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.zip;
+
+/*
+ * This interface defines the constants that are used by the classes
+ * which manipulate ZIP files.
+ *
+ * @author David Connelly
+ */
+interface ZipConstants {
+ /*
+ * Header signatures
+ */
+ static long LOCSIG = 0x04034b50L; // "PK\003\004"
+ static long EXTSIG = 0x08074b50L; // "PK\007\008"
+ static long CENSIG = 0x02014b50L; // "PK\001\002"
+ static long ENDSIG = 0x06054b50L; // "PK\005\006"
+
+ /*
+ * Header sizes in bytes (including signatures)
+ */
+ static final int LOCHDR = 30; // LOC header size
+ static final int EXTHDR = 16; // EXT header size
+ static final int CENHDR = 46; // CEN header size
+ static final int ENDHDR = 22; // END header size
+
+ /*
+ * Local file (LOC) header field offsets
+ */
+ static final int LOCVER = 4; // version needed to extract
+ static final int LOCFLG = 6; // general purpose bit flag
+ static final int LOCHOW = 8; // compression method
+ static final int LOCTIM = 10; // modification time
+ static final int LOCCRC = 14; // uncompressed file crc-32 value
+ static final int LOCSIZ = 18; // compressed size
+ static final int LOCLEN = 22; // uncompressed size
+ static final int LOCNAM = 26; // filename length
+ static final int LOCEXT = 28; // extra field length
+
+ /*
+ * Extra local (EXT) header field offsets
+ */
+ static final int EXTCRC = 4; // uncompressed file crc-32 value
+ static final int EXTSIZ = 8; // compressed size
+ static final int EXTLEN = 12; // uncompressed size
+
+ /*
+ * Central directory (CEN) header field offsets
+ */
+ static final int CENVEM = 4; // version made by
+ static final int CENVER = 6; // version needed to extract
+ static final int CENFLG = 8; // encrypt, decrypt flags
+ static final int CENHOW = 10; // compression method
+ static final int CENTIM = 12; // modification time
+ static final int CENCRC = 16; // uncompressed file crc-32 value
+ static final int CENSIZ = 20; // compressed size
+ static final int CENLEN = 24; // uncompressed size
+ static final int CENNAM = 28; // filename length
+ static final int CENEXT = 30; // extra field length
+ static final int CENCOM = 32; // comment length
+ static final int CENDSK = 34; // disk number start
+ static final int CENATT = 36; // internal file attributes
+ static final int CENATX = 38; // external file attributes
+ static final int CENOFF = 42; // LOC header offset
+
+ /*
+ * End of central directory (END) header field offsets
+ */
+ static final int ENDSUB = 8; // number of entries on this disk
+ static final int ENDTOT = 10; // total number of entries
+ static final int ENDSIZ = 12; // central directory size in bytes
+ static final int ENDOFF = 16; // offset of first CEN header
+ static final int ENDCOM = 20; // zip file comment length
+}
diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipConstants64.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/mini/src/main/java/java/util/zip/ZipConstants64.java Wed Jan 30 14:00:17 2013 +0100
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1995, 1996, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.zip;
+
+/*
+ * This class defines the constants that are used by the classes
+ * which manipulate Zip64 files.
+ */
+
+class ZipConstants64 {
+
+ /*
+ * ZIP64 constants
+ */
+ static final long ZIP64_ENDSIG = 0x06064b50L; // "PK\006\006"
+ static final long ZIP64_LOCSIG = 0x07064b50L; // "PK\006\007"
+ static final int ZIP64_ENDHDR = 56; // ZIP64 end header size
+ static final int ZIP64_LOCHDR = 20; // ZIP64 end loc header size
+ static final int ZIP64_EXTHDR = 24; // EXT header size
+ static final int ZIP64_EXTID = 0x0001; // Extra field Zip64 header ID
+
+ static final int ZIP64_MAGICCOUNT = 0xFFFF;
+ static final long ZIP64_MAGICVAL = 0xFFFFFFFFL;
+
+ /*
+ * Zip64 End of central directory (END) header field offsets
+ */
+ static final int ZIP64_ENDLEN = 4; // size of zip64 end of central dir
+ static final int ZIP64_ENDVEM = 12; // version made by
+ static final int ZIP64_ENDVER = 14; // version needed to extract
+ static final int ZIP64_ENDNMD = 16; // number of this disk
+ static final int ZIP64_ENDDSK = 20; // disk number of start
+ static final int ZIP64_ENDTOD = 24; // total number of entries on this disk
+ static final int ZIP64_ENDTOT = 32; // total number of entries
+ static final int ZIP64_ENDSIZ = 40; // central directory size in bytes
+ static final int ZIP64_ENDOFF = 48; // offset of first CEN header
+ static final int ZIP64_ENDEXT = 56; // zip64 extensible data sector
+
+ /*
+ * Zip64 End of central directory locator field offsets
+ */
+ static final int ZIP64_LOCDSK = 4; // disk number start
+ static final int ZIP64_LOCOFF = 8; // offset of zip64 end
+ static final int ZIP64_LOCTOT = 16; // total number of disks
+
+ /*
+ * Zip64 Extra local (EXT) header field offsets
+ */
+ static final int ZIP64_EXTCRC = 4; // uncompressed file crc-32 value
+ static final int ZIP64_EXTSIZ = 8; // compressed size, 8-byte
+ static final int ZIP64_EXTLEN = 16; // uncompressed size, 8-byte
+
+ /*
+ * Language encoding flag EFS
+ */
+ static final int EFS = 0x800; // If this bit is set the filename and
+ // comment fields for this file must be
+ // encoded using UTF-8.
+
+ private ZipConstants64() {}
+}
diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipEntry.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/mini/src/main/java/java/util/zip/ZipEntry.java Wed Jan 30 14:00:17 2013 +0100
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.zip;
+
+import java.util.Date;
+
+/**
+ * This class is used to represent a ZIP file entry.
+ *
+ * @author David Connelly
+ */
+public
+class ZipEntry implements ZipConstants, Cloneable {
+ String name; // entry name
+ long time = -1; // modification time (in DOS time)
+ long crc = -1; // crc-32 of entry data
+ long size = -1; // uncompressed size of entry data
+ long csize = -1; // compressed size of entry data
+ int method = -1; // compression method
+ int flag = 0; // general purpose flag
+ byte[] extra; // optional extra field data for entry
+ String comment; // optional comment string for entry
+
+ /**
+ * Compression method for uncompressed entries.
+ */
+ public static final int STORED = 0;
+
+ /**
+ * Compression method for compressed (deflated) entries.
+ */
+ public static final int DEFLATED = 8;
+
+ /**
+ * Creates a new zip entry with the specified name.
+ *
+ * @param name the entry name
+ * @exception NullPointerException if the entry name is null
+ * @exception IllegalArgumentException if the entry name is longer than
+ * 0xFFFF bytes
+ */
+ public ZipEntry(String name) {
+ if (name == null) {
+ throw new NullPointerException();
+ }
+ if (name.length() > 0xFFFF) {
+ throw new IllegalArgumentException("entry name too long");
+ }
+ this.name = name;
+ }
+
+ /**
+ * Creates a new zip entry with fields taken from the specified
+ * zip entry.
+ * @param e a zip Entry object
+ */
+ public ZipEntry(ZipEntry e) {
+ name = e.name;
+ time = e.time;
+ crc = e.crc;
+ size = e.size;
+ csize = e.csize;
+ method = e.method;
+ flag = e.flag;
+ extra = e.extra;
+ comment = e.comment;
+ }
+
+ /*
+ * Creates a new un-initialized zip entry
+ */
+ ZipEntry() {}
+
+ /**
+ * Returns the name of the entry.
+ * @return the name of the entry
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Sets the modification time of the entry.
+ * @param time the entry modification time in number of milliseconds
+ * since the epoch
+ * @see #getTime()
+ */
+ public void setTime(long time) {
+ this.time = javaToDosTime(time);
+ }
+
+ /**
+ * Returns the modification time of the entry, or -1 if not specified.
+ * @return the modification time of the entry, or -1 if not specified
+ * @see #setTime(long)
+ */
+ public long getTime() {
+ return time != -1 ? dosToJavaTime(time) : -1;
+ }
+
+ /**
+ * Sets the uncompressed size of the entry data.
+ * @param size the uncompressed size in bytes
+ * @exception IllegalArgumentException if the specified size is less
+ * than 0, is greater than 0xFFFFFFFF when
+ * ZIP64 format is not supported,
+ * or is less than 0 when ZIP64 is supported
+ * @see #getSize()
+ */
+ public void setSize(long size) {
+ if (size < 0) {
+ throw new IllegalArgumentException("invalid entry size");
+ }
+ this.size = size;
+ }
+
+ /**
+ * Returns the uncompressed size of the entry data, or -1 if not known.
+ * @return the uncompressed size of the entry data, or -1 if not known
+ * @see #setSize(long)
+ */
+ public long getSize() {
+ return size;
+ }
+
+ /**
+ * Returns the size of the compressed entry data, or -1 if not known.
+ * In the case of a stored entry, the compressed size will be the same
+ * as the uncompressed size of the entry.
+ * @return the size of the compressed entry data, or -1 if not known
+ * @see #setCompressedSize(long)
+ */
+ public long getCompressedSize() {
+ return csize;
+ }
+
+ /**
+ * Sets the size of the compressed entry data.
+ * @param csize the compressed size to set to
+ * @see #getCompressedSize()
+ */
+ public void setCompressedSize(long csize) {
+ this.csize = csize;
+ }
+
+ /**
+ * Sets the CRC-32 checksum of the uncompressed entry data.
+ * @param crc the CRC-32 value
+ * @exception IllegalArgumentException if the specified CRC-32 value is
+ * less than 0 or greater than 0xFFFFFFFF
+ * @see #getCrc()
+ */
+ public void setCrc(long crc) {
+ if (crc < 0 || crc > 0xFFFFFFFFL) {
+ throw new IllegalArgumentException("invalid entry crc-32");
+ }
+ this.crc = crc;
+ }
+
+ /**
+ * Returns the CRC-32 checksum of the uncompressed entry data, or -1 if
+ * not known.
+ * @return the CRC-32 checksum of the uncompressed entry data, or -1 if
+ * not known
+ * @see #setCrc(long)
+ */
+ public long getCrc() {
+ return crc;
+ }
+
+ /**
+ * Sets the compression method for the entry.
+ * @param method the compression method, either STORED or DEFLATED
+ * @exception IllegalArgumentException if the specified compression
+ * method is invalid
+ * @see #getMethod()
+ */
+ public void setMethod(int method) {
+ if (method != STORED && method != DEFLATED) {
+ throw new IllegalArgumentException("invalid compression method");
+ }
+ this.method = method;
+ }
+
+ /**
+ * Returns the compression method of the entry, or -1 if not specified.
+ * @return the compression method of the entry, or -1 if not specified
+ * @see #setMethod(int)
+ */
+ public int getMethod() {
+ return method;
+ }
+
+ /**
+ * Sets the optional extra field data for the entry.
+ * @param extra the extra field data bytes
+ * @exception IllegalArgumentException if the length of the specified
+ * extra field data is greater than 0xFFFF bytes
+ * @see #getExtra()
+ */
+ public void setExtra(byte[] extra) {
+ if (extra != null && extra.length > 0xFFFF) {
+ throw new IllegalArgumentException("invalid extra field length");
+ }
+ this.extra = extra;
+ }
+
+ /**
+ * Returns the extra field data for the entry, or null if none.
+ * @return the extra field data for the entry, or null if none
+ * @see #setExtra(byte[])
+ */
+ public byte[] getExtra() {
+ return extra;
+ }
+
+ /**
+ * Sets the optional comment string for the entry.
+ *
+ *
ZIP entry comments have maximum length of 0xffff. If the length of the
+ * specified comment string is greater than 0xFFFF bytes after encoding, only
+ * the first 0xFFFF bytes are output to the ZIP file entry.
+ *
+ * @param comment the comment string
+ *
+ * @see #getComment()
+ */
+ public void setComment(String comment) {
+ this.comment = comment;
+ }
+
+ /**
+ * Returns the comment string for the entry, or null if none.
+ * @return the comment string for the entry, or null if none
+ * @see #setComment(String)
+ */
+ public String getComment() {
+ return comment;
+ }
+
+ /**
+ * Returns true if this is a directory entry. A directory entry is
+ * defined to be one whose name ends with a '/'.
+ * @return true if this is a directory entry
+ */
+ public boolean isDirectory() {
+ return name.endsWith("/");
+ }
+
+ /**
+ * Returns a string representation of the ZIP entry.
+ */
+ public String toString() {
+ return getName();
+ }
+
+ /*
+ * Converts DOS time to Java time (number of milliseconds since epoch).
+ */
+ private static long dosToJavaTime(long dtime) {
+ Date d = new Date((int)(((dtime >> 25) & 0x7f) + 80),
+ (int)(((dtime >> 21) & 0x0f) - 1),
+ (int)((dtime >> 16) & 0x1f),
+ (int)((dtime >> 11) & 0x1f),
+ (int)((dtime >> 5) & 0x3f),
+ (int)((dtime << 1) & 0x3e));
+ return d.getTime();
+ }
+
+ /*
+ * Converts Java time to DOS time.
+ */
+ private static long javaToDosTime(long time) {
+ Date d = new Date(time);
+ int year = d.getYear() + 1900;
+ if (year < 1980) {
+ return (1 << 21) | (1 << 16);
+ }
+ return (year - 1980) << 25 | (d.getMonth() + 1) << 21 |
+ d.getDate() << 16 | d.getHours() << 11 | d.getMinutes() << 5 |
+ d.getSeconds() >> 1;
+ }
+
+ /**
+ * Returns the hash code value for this entry.
+ */
+ public int hashCode() {
+ return name.hashCode();
+ }
+
+ /**
+ * Returns a copy of this entry.
+ */
+ public Object clone() {
+ try {
+ ZipEntry e = (ZipEntry)super.clone();
+ e.extra = (extra == null) ? null : extra.clone();
+ return e;
+ } catch (CloneNotSupportedException e) {
+ // This should never happen, since we are Cloneable
+ throw new InternalError();
+ }
+ }
+}
diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipException.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/mini/src/main/java/java/util/zip/ZipException.java Wed Jan 30 14:00:17 2013 +0100
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 1995, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.zip;
+
+import java.io.IOException;
+
+/**
+ * Signals that a Zip exception of some sort has occurred.
+ *
+ * @author unascribed
+ * @see java.io.IOException
+ * @since JDK1.0
+ */
+
+public
+class ZipException extends IOException {
+ private static final long serialVersionUID = 8000196834066748623L;
+
+ /**
+ * Constructs a ZipException
with null
+ * as its error detail message.
+ */
+ public ZipException() {
+ super();
+ }
+
+ /**
+ * Constructs a ZipException
with the specified detail
+ * message.
+ *
+ * @param s the detail message.
+ */
+
+ public ZipException(String s) {
+ super(s);
+ }
+}
diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/ZipInputStream.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Wed Jan 30 14:00:17 2013 +0100
@@ -0,0 +1,456 @@
+/*
+ * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.util.zip;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.EOFException;
+import java.io.PushbackInputStream;
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import static java.util.zip.ZipConstants64.*;
+
+/**
+ * This class implements an input stream filter for reading files in the
+ * ZIP file format. Includes support for both compressed and uncompressed
+ * entries.
+ *
+ * @author David Connelly
+ */
+public
+class ZipInputStream extends InflaterInputStream implements ZipConstants {
+ private ZipEntry entry;
+ private int flag;
+ private CRC32 crc = new CRC32();
+ private long remaining;
+ private byte[] tmpbuf = new byte[512];
+
+ private static final int STORED = ZipEntry.STORED;
+ private static final int DEFLATED = ZipEntry.DEFLATED;
+
+ private boolean closed = false;
+ // this flag is set to true after EOF has reached for
+ // one entry
+ private boolean entryEOF = false;
+
+ private ZipCoder zc;
+
+ /**
+ * Check to make sure that this stream has not been closed
+ */
+ private void ensureOpen() throws IOException {
+ if (closed) {
+ throw new IOException("Stream closed");
+ }
+ }
+
+ /**
+ * Creates a new ZIP input stream.
+ *
+ *
The UTF-8 {@link java.nio.charset.Charset charset} is used to + * decode the entry names. + * + * @param in the actual input stream + */ + public ZipInputStream(InputStream in) { + this(in, StandardCharsets.UTF_8); + } + + /** + * Creates a new ZIP input stream. + * + * @param in the actual input stream + * + * @param charset + * The {@linkplain java.nio.charset.Charset charset} to be + * used to decode the ZIP entry name (ignored if the + * language + * encoding bit of the ZIP entry's general purpose bit + * flag is set). + * + * @since 1.7 + */ + public ZipInputStream(InputStream in, Charset charset) { + super(new PushbackInputStream(in, 512), new Inflater(true), 512); + usesDefaultInflater = true; + if(in == null) { + throw new NullPointerException("in is null"); + } + if (charset == null) + throw new NullPointerException("charset is null"); + this.zc = ZipCoder.get(charset); + } + + /** + * Reads the next ZIP file entry and positions the stream at the + * beginning of the entry data. + * @return the next ZIP file entry, or null if there are no more entries + * @exception ZipException if a ZIP file error has occurred + * @exception IOException if an I/O error has occurred + */ + public ZipEntry getNextEntry() throws IOException { + ensureOpen(); + if (entry != null) { + closeEntry(); + } + crc.reset(); + inf.reset(); + if ((entry = readLOC()) == null) { + return null; + } + if (entry.method == STORED) { + remaining = entry.size; + } + entryEOF = false; + return entry; + } + + /** + * Closes the current ZIP entry and positions the stream for reading the + * next entry. + * @exception ZipException if a ZIP file error has occurred + * @exception IOException if an I/O error has occurred + */ + public void closeEntry() throws IOException { + ensureOpen(); + while (read(tmpbuf, 0, tmpbuf.length) != -1) ; + entryEOF = true; + } + + /** + * Returns 0 after EOF has reached for the current entry data, + * otherwise always return 1. + *
+ * Programs should not count on this method to return the actual number
+ * of bytes that could be read without blocking.
+ *
+ * @return 1 before EOF and 0 after EOF has reached for current entry.
+ * @exception IOException if an I/O error occurs.
+ *
+ */
+ public int available() throws IOException {
+ ensureOpen();
+ if (entryEOF) {
+ return 0;
+ } else {
+ return 1;
+ }
+ }
+
+ /**
+ * Reads from the current ZIP entry into an array of bytes.
+ * If len
is not zero, the method
+ * blocks until some input is available; otherwise, no
+ * bytes are read and 0
is returned.
+ * @param b the buffer into which the data is read
+ * @param off the start offset in the destination array b
+ * @param len the maximum number of bytes read
+ * @return the actual number of bytes read, or -1 if the end of the
+ * entry is reached
+ * @exception NullPointerException if b
is null
.
+ * @exception IndexOutOfBoundsException if off
is negative,
+ * len
is negative, or len
is greater than
+ * b.length - off
+ * @exception ZipException if a ZIP file error has occurred
+ * @exception IOException if an I/O error has occurred
+ */
+ public int read(byte[] b, int off, int len) throws IOException {
+ ensureOpen();
+ if (off < 0 || len < 0 || off > b.length - len) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+
+ if (entry == null) {
+ return -1;
+ }
+ switch (entry.method) {
+ case DEFLATED:
+ len = super.read(b, off, len);
+ if (len == -1) {
+ readEnd(entry);
+ entryEOF = true;
+ entry = null;
+ } else {
+ crc.update(b, off, len);
+ }
+ return len;
+ case STORED:
+ if (remaining <= 0) {
+ entryEOF = true;
+ entry = null;
+ return -1;
+ }
+ if (len > remaining) {
+ len = (int)remaining;
+ }
+ len = in.read(b, off, len);
+ if (len == -1) {
+ throw new ZipException("unexpected EOF");
+ }
+ crc.update(b, off, len);
+ remaining -= len;
+ if (remaining == 0 && entry.crc != crc.getValue()) {
+ throw new ZipException(
+ "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
+ " but got 0x" + Long.toHexString(crc.getValue()) + ")");
+ }
+ return len;
+ default:
+ throw new ZipException("invalid compression method");
+ }
+ }
+
+ /**
+ * Skips specified number of bytes in the current ZIP entry.
+ * @param n the number of bytes to skip
+ * @return the actual number of bytes skipped
+ * @exception ZipException if a ZIP file error has occurred
+ * @exception IOException if an I/O error has occurred
+ * @exception IllegalArgumentException if n < 0
+ */
+ public long skip(long n) throws IOException {
+ if (n < 0) {
+ throw new IllegalArgumentException("negative skip length");
+ }
+ ensureOpen();
+ int max = (int)Math.min(n, Integer.MAX_VALUE);
+ int total = 0;
+ while (total < max) {
+ int len = max - total;
+ if (len > tmpbuf.length) {
+ len = tmpbuf.length;
+ }
+ len = read(tmpbuf, 0, len);
+ if (len == -1) {
+ entryEOF = true;
+ break;
+ }
+ total += len;
+ }
+ return total;
+ }
+
+ /**
+ * Closes this input stream and releases any system resources associated
+ * with the stream.
+ * @exception IOException if an I/O error has occurred
+ */
+ public void close() throws IOException {
+ if (!closed) {
+ super.close();
+ closed = true;
+ }
+ }
+
+ private byte[] b = new byte[256];
+
+ /*
+ * Reads local file (LOC) header for next entry.
+ */
+ private ZipEntry readLOC() throws IOException {
+ try {
+ readFully(tmpbuf, 0, LOCHDR);
+ } catch (EOFException e) {
+ return null;
+ }
+ if (get32(tmpbuf, 0) != LOCSIG) {
+ return null;
+ }
+ // get flag first, we need check EFS.
+ flag = get16(tmpbuf, LOCFLG);
+ // get the entry name and create the ZipEntry first
+ int len = get16(tmpbuf, LOCNAM);
+ int blen = b.length;
+ if (len > blen) {
+ do
+ blen = blen * 2;
+ while (len > blen);
+ b = new byte[blen];
+ }
+ readFully(b, 0, len);
+ // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
+ ZipEntry e = createZipEntry(((flag & EFS) != 0)
+ ? zc.toStringUTF8(b, len)
+ : zc.toString(b, len));
+ // now get the remaining fields for the entry
+ if ((flag & 1) == 1) {
+ throw new ZipException("encrypted ZIP entry not supported");
+ }
+ e.method = get16(tmpbuf, LOCHOW);
+ e.time = get32(tmpbuf, LOCTIM);
+ if ((flag & 8) == 8) {
+ /* "Data Descriptor" present */
+ if (e.method != DEFLATED) {
+ throw new ZipException(
+ "only DEFLATED entries can have EXT descriptor");
+ }
+ } else {
+ e.crc = get32(tmpbuf, LOCCRC);
+ e.csize = get32(tmpbuf, LOCSIZ);
+ e.size = get32(tmpbuf, LOCLEN);
+ }
+ len = get16(tmpbuf, LOCEXT);
+ if (len > 0) {
+ byte[] bb = new byte[len];
+ readFully(bb, 0, len);
+ e.setExtra(bb);
+ // extra fields are in "HeaderID(2)DataSize(2)Data... format
+ if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
+ int off = 0;
+ while (off + 4 < len) {
+ int sz = get16(bb, off + 2);
+ if (get16(bb, off) == ZIP64_EXTID) {
+ off += 4;
+ // LOC extra zip64 entry MUST include BOTH original and
+ // compressed file size fields
+ if (sz < 16 || (off + sz) > len ) {
+ // Invalid zip64 extra fields, simply skip. Even it's
+ // rare, it's possible the entry size happens to be
+ // the magic value and it "accidnetly" has some bytes
+ // in extra match the id.
+ return e;
+ }
+ e.size = get64(bb, off);
+ e.csize = get64(bb, off + 8);
+ break;
+ }
+ off += (sz + 4);
+ }
+ }
+ }
+ return e;
+ }
+
+ /**
+ * Creates a new ZipEntry
object for the specified
+ * entry name.
+ *
+ * @param name the ZIP file entry name
+ * @return the ZipEntry just created
+ */
+ protected ZipEntry createZipEntry(String name) {
+ return new ZipEntry(name);
+ }
+
+ /*
+ * Reads end of deflated entry as well as EXT descriptor if present.
+ */
+ private void readEnd(ZipEntry e) throws IOException {
+ int n = inf.getRemaining();
+ if (n > 0) {
+ ((PushbackInputStream)in).unread(buf, len - n, n);
+ }
+ if ((flag & 8) == 8) {
+ /* "Data Descriptor" present */
+ if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
+ inf.getBytesRead() > ZIP64_MAGICVAL) {
+ // ZIP64 format
+ readFully(tmpbuf, 0, ZIP64_EXTHDR);
+ long sig = get32(tmpbuf, 0);
+ if (sig != EXTSIG) { // no EXTSIG present
+ e.crc = sig;
+ e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
+ e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
+ ((PushbackInputStream)in).unread(
+ tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
+ } else {
+ e.crc = get32(tmpbuf, ZIP64_EXTCRC);
+ e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
+ e.size = get64(tmpbuf, ZIP64_EXTLEN);
+ }
+ } else {
+ readFully(tmpbuf, 0, EXTHDR);
+ long sig = get32(tmpbuf, 0);
+ if (sig != EXTSIG) { // no EXTSIG present
+ e.crc = sig;
+ e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
+ e.size = get32(tmpbuf, EXTLEN - EXTCRC);
+ ((PushbackInputStream)in).unread(
+ tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
+ } else {
+ e.crc = get32(tmpbuf, EXTCRC);
+ e.csize = get32(tmpbuf, EXTSIZ);
+ e.size = get32(tmpbuf, EXTLEN);
+ }
+ }
+ }
+ if (e.size != inf.getBytesWritten()) {
+ throw new ZipException(
+ "invalid entry size (expected " + e.size +
+ " but got " + inf.getBytesWritten() + " bytes)");
+ }
+ if (e.csize != inf.getBytesRead()) {
+ throw new ZipException(
+ "invalid entry compressed size (expected " + e.csize +
+ " but got " + inf.getBytesRead() + " bytes)");
+ }
+ if (e.crc != crc.getValue()) {
+ throw new ZipException(
+ "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
+ " but got 0x" + Long.toHexString(crc.getValue()) + ")");
+ }
+ }
+
+ /*
+ * Reads bytes, blocking until all bytes are read.
+ */
+ private void readFully(byte[] b, int off, int len) throws IOException {
+ while (len > 0) {
+ int n = in.read(b, off, len);
+ if (n == -1) {
+ throw new EOFException();
+ }
+ off += n;
+ len -= n;
+ }
+ }
+
+ /*
+ * Fetches unsigned 16-bit value from byte array at specified offset.
+ * The bytes are assumed to be in Intel (little-endian) byte order.
+ */
+ private static final int get16(byte b[], int off) {
+ return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
+ }
+
+ /*
+ * Fetches unsigned 32-bit value from byte array at specified offset.
+ * The bytes are assumed to be in Intel (little-endian) byte order.
+ */
+ private static final long get32(byte b[], int off) {
+ return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
+ }
+
+ /*
+ * Fetches signed 64-bit value from byte array at specified offset.
+ * The bytes are assumed to be in Intel (little-endian) byte order.
+ */
+ private static final long get64(byte b[], int off) {
+ return get32(b, off) | (get32(b, off+4) << 32);
+ }
+}
diff -r 5198affdb915 -r 48ef38e9677e emul/mini/src/main/java/java/util/zip/package.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emul/mini/src/main/java/java/util/zip/package.html Wed Jan 30 14:00:17 2013 +0100
@@ -0,0 +1,98 @@
+
+
+
java.util.zip
classes are based.
+
+
+
+
+
+
+
+
+
+