1.1 --- a/emul/mini/src/main/java/java/util/zip/ZipInputStream.java Thu Feb 14 12:06:16 2013 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,467 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -
1.29 -package java.util.zip;
1.30 -
1.31 -import java.io.InputStream;
1.32 -import java.io.IOException;
1.33 -import java.io.EOFException;
1.34 -import java.io.PushbackInputStream;
1.35 -import static java.util.zip.ZipConstants64.*;
1.36 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
1.37 -
1.38 -/**
1.39 - * This class implements an input stream filter for reading files in the
1.40 - * ZIP file format. Includes support for both compressed and uncompressed
1.41 - * entries.
1.42 - *
1.43 - * @author David Connelly
1.44 - */
1.45 -public
1.46 -class ZipInputStream extends InflaterInputStream implements ZipConstants {
1.47 - private ZipEntry entry;
1.48 - private int flag;
1.49 - private CRC32 crc = new CRC32();
1.50 - private long remaining;
1.51 - private byte[] tmpbuf = new byte[512];
1.52 -
1.53 - private static final int STORED = ZipEntry.STORED;
1.54 - private static final int DEFLATED = ZipEntry.DEFLATED;
1.55 -
1.56 - private boolean closed = false;
1.57 - // this flag is set to true after EOF has reached for
1.58 - // one entry
1.59 - private boolean entryEOF = false;
1.60 -
1.61 - /**
1.62 - * Check to make sure that this stream has not been closed
1.63 - */
1.64 - private void ensureOpen() throws IOException {
1.65 - if (closed) {
1.66 - throw new IOException("Stream closed");
1.67 - }
1.68 - }
1.69 -
1.70 - /**
1.71 - * Creates a new ZIP input stream.
1.72 - *
1.73 - * <p>The UTF-8 {@link java.nio.charset.Charset charset} is used to
1.74 - * decode the entry names.
1.75 - *
1.76 - * @param in the actual input stream
1.77 - */
1.78 - public ZipInputStream(InputStream in) {
1.79 -// this(in, "UTF-8");
1.80 - super(new PushbackInputStream(in, 512), new Inflater(true), 512);
1.81 - usesDefaultInflater = true;
1.82 - if(in == null) {
1.83 - throw new NullPointerException("in is null");
1.84 - }
1.85 - }
1.86 -
1.87 - /**
1.88 - * Creates a new ZIP input stream.
1.89 - *
1.90 - * @param in the actual input stream
1.91 - *
1.92 - * @param charset
1.93 - * The {@linkplain java.nio.charset.Charset charset} to be
1.94 - * used to decode the ZIP entry name (ignored if the
1.95 - * <a href="package-summary.html#lang_encoding"> language
1.96 - * encoding bit</a> of the ZIP entry's general purpose bit
1.97 - * flag is set).
1.98 - *
1.99 - * @since 1.7
1.100 - *
1.101 - public ZipInputStream(InputStream in, Charset charset) {
1.102 - super(new PushbackInputStream(in, 512), new Inflater(true), 512);
1.103 - usesDefaultInflater = true;
1.104 - if(in == null) {
1.105 - throw new NullPointerException("in is null");
1.106 - }
1.107 - if (charset == null)
1.108 - throw new NullPointerException("charset is null");
1.109 - this.zc = ZipCoder.get(charset);
1.110 - }
1.111 - */
1.112 -
1.113 - /**
1.114 - * Reads the next ZIP file entry and positions the stream at the
1.115 - * beginning of the entry data.
1.116 - * @return the next ZIP file entry, or null if there are no more entries
1.117 - * @exception ZipException if a ZIP file error has occurred
1.118 - * @exception IOException if an I/O error has occurred
1.119 - */
1.120 - public ZipEntry getNextEntry() throws IOException {
1.121 - ensureOpen();
1.122 - if (entry != null) {
1.123 - closeEntry();
1.124 - }
1.125 - crc.reset();
1.126 - inf.reset();
1.127 - if ((entry = readLOC()) == null) {
1.128 - return null;
1.129 - }
1.130 - if (entry.method == STORED) {
1.131 - remaining = entry.size;
1.132 - }
1.133 - entryEOF = false;
1.134 - return entry;
1.135 - }
1.136 -
1.137 - /**
1.138 - * Closes the current ZIP entry and positions the stream for reading the
1.139 - * next entry.
1.140 - * @exception ZipException if a ZIP file error has occurred
1.141 - * @exception IOException if an I/O error has occurred
1.142 - */
1.143 - public void closeEntry() throws IOException {
1.144 - ensureOpen();
1.145 - while (read(tmpbuf, 0, tmpbuf.length) != -1) ;
1.146 - entryEOF = true;
1.147 - }
1.148 -
1.149 - /**
1.150 - * Returns 0 after EOF has reached for the current entry data,
1.151 - * otherwise always return 1.
1.152 - * <p>
1.153 - * Programs should not count on this method to return the actual number
1.154 - * of bytes that could be read without blocking.
1.155 - *
1.156 - * @return 1 before EOF and 0 after EOF has reached for current entry.
1.157 - * @exception IOException if an I/O error occurs.
1.158 - *
1.159 - */
1.160 - public int available() throws IOException {
1.161 - ensureOpen();
1.162 - if (entryEOF) {
1.163 - return 0;
1.164 - } else {
1.165 - return 1;
1.166 - }
1.167 - }
1.168 -
1.169 - /**
1.170 - * Reads from the current ZIP entry into an array of bytes.
1.171 - * If <code>len</code> is not zero, the method
1.172 - * blocks until some input is available; otherwise, no
1.173 - * bytes are read and <code>0</code> is returned.
1.174 - * @param b the buffer into which the data is read
1.175 - * @param off the start offset in the destination array <code>b</code>
1.176 - * @param len the maximum number of bytes read
1.177 - * @return the actual number of bytes read, or -1 if the end of the
1.178 - * entry is reached
1.179 - * @exception NullPointerException if <code>b</code> is <code>null</code>.
1.180 - * @exception IndexOutOfBoundsException if <code>off</code> is negative,
1.181 - * <code>len</code> is negative, or <code>len</code> is greater than
1.182 - * <code>b.length - off</code>
1.183 - * @exception ZipException if a ZIP file error has occurred
1.184 - * @exception IOException if an I/O error has occurred
1.185 - */
1.186 - public int read(byte[] b, int off, int len) throws IOException {
1.187 - ensureOpen();
1.188 - if (off < 0 || len < 0 || off > b.length - len) {
1.189 - throw new IndexOutOfBoundsException();
1.190 - } else if (len == 0) {
1.191 - return 0;
1.192 - }
1.193 -
1.194 - if (entry == null) {
1.195 - return -1;
1.196 - }
1.197 - switch (entry.method) {
1.198 - case DEFLATED:
1.199 - len = super.read(b, off, len);
1.200 - if (len == -1) {
1.201 - readEnd(entry);
1.202 - entryEOF = true;
1.203 - entry = null;
1.204 - } else {
1.205 - crc.update(b, off, len);
1.206 - }
1.207 - return len;
1.208 - case STORED:
1.209 - if (remaining <= 0) {
1.210 - entryEOF = true;
1.211 - entry = null;
1.212 - return -1;
1.213 - }
1.214 - if (len > remaining) {
1.215 - len = (int)remaining;
1.216 - }
1.217 - len = in.read(b, off, len);
1.218 - if (len == -1) {
1.219 - throw new ZipException("unexpected EOF");
1.220 - }
1.221 - crc.update(b, off, len);
1.222 - remaining -= len;
1.223 - if (remaining == 0 && entry.crc != crc.getValue()) {
1.224 - throw new ZipException(
1.225 - "invalid entry CRC (expected 0x" + Long.toHexString(entry.crc) +
1.226 - " but got 0x" + Long.toHexString(crc.getValue()) + ")");
1.227 - }
1.228 - return len;
1.229 - default:
1.230 - throw new ZipException("invalid compression method");
1.231 - }
1.232 - }
1.233 -
1.234 - /**
1.235 - * Skips specified number of bytes in the current ZIP entry.
1.236 - * @param n the number of bytes to skip
1.237 - * @return the actual number of bytes skipped
1.238 - * @exception ZipException if a ZIP file error has occurred
1.239 - * @exception IOException if an I/O error has occurred
1.240 - * @exception IllegalArgumentException if n < 0
1.241 - */
1.242 - public long skip(long n) throws IOException {
1.243 - if (n < 0) {
1.244 - throw new IllegalArgumentException("negative skip length");
1.245 - }
1.246 - ensureOpen();
1.247 - int max = (int)Math.min(n, Integer.MAX_VALUE);
1.248 - int total = 0;
1.249 - while (total < max) {
1.250 - int len = max - total;
1.251 - if (len > tmpbuf.length) {
1.252 - len = tmpbuf.length;
1.253 - }
1.254 - len = read(tmpbuf, 0, len);
1.255 - if (len == -1) {
1.256 - entryEOF = true;
1.257 - break;
1.258 - }
1.259 - total += len;
1.260 - }
1.261 - return total;
1.262 - }
1.263 -
1.264 - /**
1.265 - * Closes this input stream and releases any system resources associated
1.266 - * with the stream.
1.267 - * @exception IOException if an I/O error has occurred
1.268 - */
1.269 - public void close() throws IOException {
1.270 - if (!closed) {
1.271 - super.close();
1.272 - closed = true;
1.273 - }
1.274 - }
1.275 -
1.276 - private byte[] b = new byte[256];
1.277 -
1.278 - /*
1.279 - * Reads local file (LOC) header for next entry.
1.280 - */
1.281 - private ZipEntry readLOC() throws IOException {
1.282 - try {
1.283 - readFully(tmpbuf, 0, LOCHDR);
1.284 - } catch (EOFException e) {
1.285 - return null;
1.286 - }
1.287 - if (get32(tmpbuf, 0) != LOCSIG) {
1.288 - return null;
1.289 - }
1.290 - // get flag first, we need check EFS.
1.291 - flag = get16(tmpbuf, LOCFLG);
1.292 - // get the entry name and create the ZipEntry first
1.293 - int len = get16(tmpbuf, LOCNAM);
1.294 - int blen = b.length;
1.295 - if (len > blen) {
1.296 - do
1.297 - blen = blen * 2;
1.298 - while (len > blen);
1.299 - b = new byte[blen];
1.300 - }
1.301 - readFully(b, 0, len);
1.302 - // Force to use UTF-8 if the EFS bit is ON, even the cs is NOT UTF-8
1.303 - ZipEntry e = createZipEntry(((flag & EFS) != 0)
1.304 - ? toStringUTF8(b, len)
1.305 - : toString(b, len));
1.306 - // now get the remaining fields for the entry
1.307 - if ((flag & 1) == 1) {
1.308 - throw new ZipException("encrypted ZIP entry not supported");
1.309 - }
1.310 - e.method = get16(tmpbuf, LOCHOW);
1.311 - e.time = get32(tmpbuf, LOCTIM);
1.312 - if ((flag & 8) == 8) {
1.313 - /* "Data Descriptor" present */
1.314 - if (e.method != DEFLATED) {
1.315 - throw new ZipException(
1.316 - "only DEFLATED entries can have EXT descriptor");
1.317 - }
1.318 - } else {
1.319 - e.crc = get32(tmpbuf, LOCCRC);
1.320 - e.csize = get32(tmpbuf, LOCSIZ);
1.321 - e.size = get32(tmpbuf, LOCLEN);
1.322 - }
1.323 - len = get16(tmpbuf, LOCEXT);
1.324 - if (len > 0) {
1.325 - byte[] bb = new byte[len];
1.326 - readFully(bb, 0, len);
1.327 - e.setExtra(bb);
1.328 - // extra fields are in "HeaderID(2)DataSize(2)Data... format
1.329 - if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
1.330 - int off = 0;
1.331 - while (off + 4 < len) {
1.332 - int sz = get16(bb, off + 2);
1.333 - if (get16(bb, off) == ZIP64_EXTID) {
1.334 - off += 4;
1.335 - // LOC extra zip64 entry MUST include BOTH original and
1.336 - // compressed file size fields
1.337 - if (sz < 16 || (off + sz) > len ) {
1.338 - // Invalid zip64 extra fields, simply skip. Even it's
1.339 - // rare, it's possible the entry size happens to be
1.340 - // the magic value and it "accidnetly" has some bytes
1.341 - // in extra match the id.
1.342 - return e;
1.343 - }
1.344 - e.size = get64(bb, off);
1.345 - e.csize = get64(bb, off + 8);
1.346 - break;
1.347 - }
1.348 - off += (sz + 4);
1.349 - }
1.350 - }
1.351 - }
1.352 - return e;
1.353 - }
1.354 -
1.355 - /**
1.356 - * Creates a new <code>ZipEntry</code> object for the specified
1.357 - * entry name.
1.358 - *
1.359 - * @param name the ZIP file entry name
1.360 - * @return the ZipEntry just created
1.361 - */
1.362 - protected ZipEntry createZipEntry(String name) {
1.363 - return new ZipEntry(name);
1.364 - }
1.365 -
1.366 - /*
1.367 - * Reads end of deflated entry as well as EXT descriptor if present.
1.368 - */
1.369 - private void readEnd(ZipEntry e) throws IOException {
1.370 - int n = inf.getRemaining();
1.371 - if (n > 0) {
1.372 - ((PushbackInputStream)in).unread(buf, len - n, n);
1.373 - }
1.374 - if ((flag & 8) == 8) {
1.375 - /* "Data Descriptor" present */
1.376 - if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
1.377 - inf.getBytesRead() > ZIP64_MAGICVAL) {
1.378 - // ZIP64 format
1.379 - readFully(tmpbuf, 0, ZIP64_EXTHDR);
1.380 - long sig = get32(tmpbuf, 0);
1.381 - if (sig != EXTSIG) { // no EXTSIG present
1.382 - e.crc = sig;
1.383 - e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
1.384 - e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
1.385 - ((PushbackInputStream)in).unread(
1.386 - tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
1.387 - } else {
1.388 - e.crc = get32(tmpbuf, ZIP64_EXTCRC);
1.389 - e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
1.390 - e.size = get64(tmpbuf, ZIP64_EXTLEN);
1.391 - }
1.392 - } else {
1.393 - readFully(tmpbuf, 0, EXTHDR);
1.394 - long sig = get32(tmpbuf, 0);
1.395 - if (sig != EXTSIG) { // no EXTSIG present
1.396 - e.crc = sig;
1.397 - e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
1.398 - e.size = get32(tmpbuf, EXTLEN - EXTCRC);
1.399 - ((PushbackInputStream)in).unread(
1.400 - tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
1.401 - } else {
1.402 - e.crc = get32(tmpbuf, EXTCRC);
1.403 - e.csize = get32(tmpbuf, EXTSIZ);
1.404 - e.size = get32(tmpbuf, EXTLEN);
1.405 - }
1.406 - }
1.407 - }
1.408 - if (e.size != inf.getBytesWritten()) {
1.409 - throw new ZipException(
1.410 - "invalid entry size (expected " + e.size +
1.411 - " but got " + inf.getBytesWritten() + " bytes)");
1.412 - }
1.413 - if (e.csize != inf.getBytesRead()) {
1.414 - throw new ZipException(
1.415 - "invalid entry compressed size (expected " + e.csize +
1.416 - " but got " + inf.getBytesRead() + " bytes)");
1.417 - }
1.418 - if (e.crc != crc.getValue()) {
1.419 - throw new ZipException(
1.420 - "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
1.421 - " but got 0x" + Long.toHexString(crc.getValue()) + ")");
1.422 - }
1.423 - }
1.424 -
1.425 - /*
1.426 - * Reads bytes, blocking until all bytes are read.
1.427 - */
1.428 - private void readFully(byte[] b, int off, int len) throws IOException {
1.429 - while (len > 0) {
1.430 - int n = in.read(b, off, len);
1.431 - if (n == -1) {
1.432 - throw new EOFException();
1.433 - }
1.434 - off += n;
1.435 - len -= n;
1.436 - }
1.437 - }
1.438 -
1.439 - /*
1.440 - * Fetches unsigned 16-bit value from byte array at specified offset.
1.441 - * The bytes are assumed to be in Intel (little-endian) byte order.
1.442 - */
1.443 - private static final int get16(byte b[], int off) {
1.444 - return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
1.445 - }
1.446 -
1.447 - /*
1.448 - * Fetches unsigned 32-bit value from byte array at specified offset.
1.449 - * The bytes are assumed to be in Intel (little-endian) byte order.
1.450 - */
1.451 - private static final long get32(byte b[], int off) {
1.452 - return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
1.453 - }
1.454 -
1.455 - /*
1.456 - * Fetches signed 64-bit value from byte array at specified offset.
1.457 - * The bytes are assumed to be in Intel (little-endian) byte order.
1.458 - */
1.459 - private static final long get64(byte b[], int off) {
1.460 - return get32(b, off) | (get32(b, off+4) << 32);
1.461 - }
1.462 -
1.463 - private static String toStringUTF8(byte[] arr, int len) {
1.464 - return new String(arr, 0, len);
1.465 - }
1.466 -
1.467 - private static String toString(byte[] b, int len) {
1.468 - return new String(b, 0, len);
1.469 - }
1.470 -}