1.1 --- a/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Wed Jan 30 14:03:49 2013 +0100
1.2 +++ b/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Thu Feb 07 12:58:12 2013 +0100
1.3 @@ -27,10 +27,6 @@
1.4
1.5 import java.io.InputStream;
1.6 import java.io.IOException;
1.7 -import java.io.EOFException;
1.8 -import java.io.PushbackInputStream;
1.9 -import static java.util.zip.ZipConstants64.*;
1.10 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.11
1.12 /**
1.13 * This class implements an input stream filter for reading files in the
1.14 @@ -41,28 +37,7 @@
1.15 */
1.16 public
1.17 class ZipInputStream extends InflaterInputStream implements ZipConstants {
1.18 - private ZipEntry entry;
1.19 - private int flag;
1.20 - private CRC32 crc = new CRC32();
1.21 - private long remaining;
1.22 - private byte[] tmpbuf = new byte[512];
1.23 -
1.24 - private static final int STORED = ZipEntry.STORED;
1.25 - private static final int DEFLATED = ZipEntry.DEFLATED;
1.26 -
1.27 - private boolean closed = false;
1.28 - // this flag is set to true after EOF has reached for
1.29 - // one entry
1.30 - private boolean entryEOF = false;
1.31 -
1.32 - /**
1.33 - * Check to make sure that this stream has not been closed
1.34 - */
1.35 - private void ensureOpen() throws IOException {
1.36 - if (closed) {
1.37 - throw new IOException("Stream closed");
1.38 - }
1.39 - }
1.40 + private final org.apidesign.bck2brwsr.emul.zip.ZipInputStream impl;
1.41
1.42 /**
1.43 * Creates a new ZIP input stream.
1.44 @@ -73,12 +48,8 @@
1.45 * @param in the actual input stream
1.46 */
1.47 public ZipInputStream(InputStream in) {
1.48 -// this(in, "UTF-8");
1.49 - super(new PushbackInputStream(in, 512), new Inflater(true), 512);
1.50 - usesDefaultInflater = true;
1.51 - if(in == null) {
1.52 - throw new NullPointerException("in is null");
1.53 - }
1.54 + super(null);
1.55 + impl = new org.apidesign.bck2brwsr.emul.zip.ZipInputStream(in);
1.56 }
1.57
1.58 /**
1.59 @@ -115,20 +86,7 @@
1.60 * @exception IOException if an I/O error has occurred
1.61 */
1.62 public ZipEntry getNextEntry() throws IOException {
1.63 - ensureOpen();
1.64 - if (entry != null) {
1.65 - closeEntry();
1.66 - }
1.67 - crc.reset();
1.68 - inf.reset();
1.69 - if ((entry = readLOC()) == null) {
1.70 - return null;
1.71 - }
1.72 - if (entry.method == STORED) {
1.73 - remaining = entry.size;
1.74 - }
1.75 - entryEOF = false;
1.76 - return entry;
1.77 + return impl.getNextEntry();
1.78 }
1.79
1.80 /**
1.81 @@ -138,9 +96,7 @@
1.82 * @exception IOException if an I/O error has occurred
1.83 */
1.84 public void closeEntry() throws IOException {
1.85 - ensureOpen();
1.86 - while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
1.87 - entryEOF = true;
1.88 + impl.closeEntry();
1.89 }
1.90
1.91 /**
1.92 @@ -155,12 +111,7 @@
1.93 *
1.94 */
1.95 public int available() throws IOException {
1.96 - ensureOpen();
1.97 - if (entryEOF) {
1.98 - return 0;
1.99 - } else {
1.100 - return 1;
1.101 - }
1.102 + return impl.available();
1.103 }
1.104
1.105 /**
1.106 @@ -181,51 +132,7 @@
1.107 * @exception IOException if an I/O error has occurred
1.108 */
1.109 public int read(byte[] b, int off, int len) throws IOException {
1.110 - ensureOpen();
1.111 - if (off < 0 || len < 0 || off > b.length - len) {
1.112 - throw new IndexOutOfBoundsException();
1.113 - } else if (len == 0) {
1.114 - return 0;
1.115 - }
1.116 -
1.117 - if (entry == null) {
1.118 - return -1;
1.119 - }
1.120 - switch (entry.method) {
1.121 - case DEFLATED:
1.122 - len = super.read(b, off, len);
1.123 - if (len == -1) {
1.124 - readEnd(entry);
1.125 - entryEOF = true;
1.126 - entry = null;
1.127 - } else {
1.128 - crc.update(b, off, len);
1.129 - }
1.130 - return len;
1.131 - case STORED:
1.132 - if (remaining <= 0) {
1.133 - entryEOF = true;
1.134 - entry = null;
1.135 - return -1;
1.136 - }
1.137 - if (len > remaining) {
1.138 - len = (int)remaining;
1.139 - }
1.140 - len = in.read(b, off, len);
1.141 - if (len == -1) {
1.142 - throw new ZipException("unexpected EOF");
1.143 - }
1.144 - crc.update(b, off, len);
1.145 - remaining -= len;
1.146 - if (remaining == 0 && entry.crc != crc.getValue()) {
1.147 - throw new ZipException(
1.148 - "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
1.149 - " but got 0x" + Long.toHexString(crc.getValue()) + ")");
1.150 - }
1.151 - return len;
1.152 - default:
1.153 - throw new ZipException("invalid compression method");
1.154 - }
1.155 + return impl.read(b, off, len);
1.156 }
1.157
1.158 /**
1.159 @@ -237,25 +144,7 @@
1.160 * @exception IllegalArgumentException if n < 0
1.161 */
1.162 public long skip(long n) throws IOException {
1.163 - if (n < 0) {
1.164 - throw new IllegalArgumentException("negative skip length");
1.165 - }
1.166 - ensureOpen();
1.167 - int max = (int)Math.min(n, Integer.MAX_VALUE);
1.168 - int total = 0;
1.169 - while (total < max) {
1.170 - int len = max - total;
1.171 - if (len > tmpbuf.length) {
1.172 - len = tmpbuf.length;
1.173 - }
1.174 - len = read(tmpbuf, 0, len);
1.175 - if (len == -1) {
1.176 - entryEOF = true;
1.177 - break;
1.178 - }
1.179 - total += len;
1.180 - }
1.181 - return total;
1.182 + return impl.skip(n);
1.183 }
1.184
1.185 /**
1.186 @@ -264,89 +153,7 @@
1.187 * @exception IOException if an I/O error has occurred
1.188 */
1.189 public void close() throws IOException {
1.190 - if (!closed) {
1.191 - super.close();
1.192 - closed = true;
1.193 - }
1.194 - }
1.195 -
1.196 - private byte[] b = new byte[256];
1.197 -
1.198 - /*
1.199 - * Reads local file (LOC) header for next entry.
1.200 - */
1.201 - private ZipEntry readLOC() throws IOException {
1.202 - try {
1.203 - readFully(tmpbuf, 0, LOCHDR);
1.204 - } catch (EOFException e) {
1.205 - return null;
1.206 - }
1.207 - if (get32(tmpbuf, 0) != LOCSIG) {
1.208 - return null;
1.209 - }
1.210 - // get flag first, we need check EFS.
1.211 - flag = get16(tmpbuf, LOCFLG);
1.212 - // get the entry name and create the ZipEntry first
1.213 - int len = get16(tmpbuf, LOCNAM);
1.214 - int blen = b.length;
1.215 - if (len > blen) {
1.216 - do
1.217 - blen = blen * 2;
1.218 - while (len > blen);
1.219 - b = new byte[blen];
1.220 - }
1.221 - readFully(b, 0, len);
1.222 - // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
1.223 - ZipEntry e = createZipEntry(((flag & EFS) != 0)
1.224 - ? toStringUTF8(b, len)
1.225 - : toString(b, len));
1.226 - // now get the remaining fields for the entry
1.227 - if ((flag & 1) == 1) {
1.228 - throw new ZipException("encrypted ZIP entry not supported");
1.229 - }
1.230 - e.method = get16(tmpbuf, LOCHOW);
1.231 - e.time = get32(tmpbuf, LOCTIM);
1.232 - if ((flag & 8) == 8) {
1.233 - /* "Data Descriptor" present */
1.234 - if (e.method != DEFLATED) {
1.235 - throw new ZipException(
1.236 - "only DEFLATED entries can have EXT descriptor");
1.237 - }
1.238 - } else {
1.239 - e.crc = get32(tmpbuf, LOCCRC);
1.240 - e.csize = get32(tmpbuf, LOCSIZ);
1.241 - e.size = get32(tmpbuf, LOCLEN);
1.242 - }
1.243 - len = get16(tmpbuf, LOCEXT);
1.244 - if (len > 0) {
1.245 - byte[] bb = new byte[len];
1.246 - readFully(bb, 0, len);
1.247 - e.setExtra(bb);
1.248 - // extra fields are in "HeaderID(2)DataSize(2)Data... format
1.249 - if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
1.250 - int off = 0;
1.251 - while (off + 4 < len) {
1.252 - int sz = get16(bb, off + 2);
1.253 - if (get16(bb, off) == ZIP64_EXTID) {
1.254 - off += 4;
1.255 - // LOC extra zip64 entry MUST include BOTH original and
1.256 - // compressed file size fields
1.257 - if (sz < 16 || (off + sz) > len ) {
1.258 - // Invalid zip64 extra fields, simply skip. Even it's
1.259 - // rare, it's possible the entry size happens to be
1.260 - // the magic value and it "accidnetly" has some bytes
1.261 - // in extra match the id.
1.262 - return e;
1.263 - }
1.264 - e.size = get64(bb, off);
1.265 - e.csize = get64(bb, off + 8);
1.266 - break;
1.267 - }
1.268 - off += (sz + 4);
1.269 - }
1.270 - }
1.271 - }
1.272 - return e;
1.273 + impl.close();
1.274 }
1.275
1.276 /**
1.277 @@ -360,108 +167,28 @@
1.278 return new ZipEntry(name);
1.279 }
1.280
1.281 - /*
1.282 - * Reads end of deflated entry as well as EXT descriptor if present.
1.283 - */
1.284 - private void readEnd(ZipEntry e) throws IOException {
1.285 - int n = inf.getRemaining();
1.286 - if (n > 0) {
1.287 - ((PushbackInputStream)in).unread(buf, len - n, n);
1.288 - }
1.289 - if ((flag & 8) == 8) {
1.290 - /* "Data Descriptor" present */
1.291 - if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
1.292 - inf.getBytesRead() > ZIP64_MAGICVAL) {
1.293 - // ZIP64 format
1.294 - readFully(tmpbuf, 0, ZIP64_EXTHDR);
1.295 - long sig = get32(tmpbuf, 0);
1.296 - if (sig != EXTSIG) { // no EXTSIG present
1.297 - e.crc = sig;
1.298 - e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
1.299 - e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
1.300 - ((PushbackInputStream)in).unread(
1.301 - tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
1.302 - } else {
1.303 - e.crc = get32(tmpbuf, ZIP64_EXTCRC);
1.304 - e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
1.305 - e.size = get64(tmpbuf, ZIP64_EXTLEN);
1.306 - }
1.307 - } else {
1.308 - readFully(tmpbuf, 0, EXTHDR);
1.309 - long sig = get32(tmpbuf, 0);
1.310 - if (sig != EXTSIG) { // no EXTSIG present
1.311 - e.crc = sig;
1.312 - e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
1.313 - e.size = get32(tmpbuf, EXTLEN - EXTCRC);
1.314 - ((PushbackInputStream)in).unread(
1.315 - tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
1.316 - } else {
1.317 - e.crc = get32(tmpbuf, EXTCRC);
1.318 - e.csize = get32(tmpbuf, EXTSIZ);
1.319 - e.size = get32(tmpbuf, EXTLEN);
1.320 - }
1.321 - }
1.322 - }
1.323 - if (e.size != inf.getBytesWritten()) {
1.324 - throw new ZipException(
1.325 - "invalid entry size (expected " + e.size +
1.326 - " but got " + inf.getBytesWritten() + " bytes)");
1.327 - }
1.328 - if (e.csize != inf.getBytesRead()) {
1.329 - throw new ZipException(
1.330 - "invalid entry compressed size (expected " + e.csize +
1.331 - " but got " + inf.getBytesRead() + " bytes)");
1.332 - }
1.333 - if (e.crc != crc.getValue()) {
1.334 - throw new ZipException(
1.335 - "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
1.336 - " but got 0x" + Long.toHexString(crc.getValue()) + ")");
1.337 - }
1.338 + @Override
1.339 + public int read() throws IOException {
1.340 + return impl.read();
1.341 }
1.342
1.343 - /*
1.344 - * Reads bytes, blocking until all bytes are read.
1.345 - */
1.346 - private void readFully(byte[] b, int off, int len) throws IOException {
1.347 - while (len > 0) {
1.348 - int n = in.read(b, off, len);
1.349 - if (n == -1) {
1.350 - throw new EOFException();
1.351 - }
1.352 - off += n;
1.353 - len -= n;
1.354 - }
1.355 + @Override
1.356 + public boolean markSupported() {
1.357 + return impl.markSupported();
1.358 }
1.359
1.360 - /*
1.361 - * Fetches unsigned 16-bit value from byte array at specified offset.
1.362 - * The bytes are assumed to be in Intel (little-endian) byte order.
1.363 - */
1.364 - private static final int get16(byte b[], int off) {
1.365 - return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
1.366 + @Override
1.367 + public void mark(int readlimit) {
1.368 + impl.mark(readlimit);
1.369 }
1.370
1.371 - /*
1.372 - * Fetches unsigned 32-bit value from byte array at specified offset.
1.373 - * The bytes are assumed to be in Intel (little-endian) byte order.
1.374 - */
1.375 - private static final long get32(byte b[], int off) {
1.376 - return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
1.377 + @Override
1.378 + public void reset() throws IOException {
1.379 + impl.reset();
1.380 }
1.381
1.382 - /*
1.383 - * Fetches signed 64-bit value from byte array at specified offset.
1.384 - * The bytes are assumed to be in Intel (little-endian) byte order.
1.385 - */
1.386 - private static final long get64(byte b[], int off) {
1.387 - return get32(b, off) | (get32(b, off+4) << 32);
1.388 - }
1.389 -
1.390 - private static String toStringUTF8(byte[] arr, int len) {
1.391 - return new String(arr, 0, len);
1.392 - }
1.393 -
1.394 - private static String toString(byte[] b, int len) {
1.395 - return new String(b, 0, len);
1.396 + @Override
1.397 + public int read(byte[] b) throws IOException {
1.398 + return impl.read(b);
1.399 }
1.400 }