1 /*
2 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.util.zip;
27
28 import java.io.InputStream;
29 import java.io.IOException;
30 import java.io.EOFException;
31 import java.io.PushbackInputStream;
32
33 /**
34 * This class implements an input stream filter for reading files in the
35 * ZIP file format. Includes support for both compressed and uncompressed
36 * entries.
37 *
38 * @author David Connelly
39 */
40 public
41 class ZipInputStream extends InflaterInputStream implements ZipConstants {
42 private ZipEntry entry;
43 private int flag;
44 private CRC32 crc = new CRC32();
45 private long remaining;
46 private byte[] tmpbuf = new byte[512];
47
48 private static final int STORED = ZipEntry.STORED;
49 private static final int DEFLATED = ZipEntry.DEFLATED;
50
51 private boolean closed = false;
268 throw new ZipException("encrypted ZIP entry not supported");
269 }
270 e.method = get16(tmpbuf, LOCHOW);
271 e.time = get32(tmpbuf, LOCTIM);
272 if ((flag & 8) == 8) {
273 /* "Data Descriptor" present */
274 if (e.method != DEFLATED) {
275 throw new ZipException(
276 "only DEFLATED entries can have EXT descriptor");
277 }
278 } else {
279 e.crc = get32(tmpbuf, LOCCRC);
280 e.csize = get32(tmpbuf, LOCSIZ);
281 e.size = get32(tmpbuf, LOCLEN);
282 }
283 len = get16(tmpbuf, LOCEXT);
284 if (len > 0) {
285 byte[] bb = new byte[len];
286 readFully(bb, 0, len);
287 e.setExtra(bb);
288 }
289 return e;
290 }
291
292 /*
293 * Fetches a UTF8-encoded String from the specified byte array.
294 */
295 private static String getUTF8String(byte[] b, int off, int len) {
296 // First, count the number of characters in the sequence
297 int count = 0;
298 int max = off + len;
299 int i = off;
300 while (i < max) {
301 int c = b[i++] & 0xff;
302 switch (c >> 4) {
303 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
304 // 0xxxxxxx
305 count++;
306 break;
307 case 12: case 13:
308 // 110xxxxx 10xxxxxx
358 * Creates a new <code>ZipEntry</code> object for the specified
359 * entry name.
360 *
361 * @param name the ZIP file entry name
362 * @return the ZipEntry just created
363 */
364 protected ZipEntry createZipEntry(String name) {
365 return new ZipEntry(name);
366 }
367
368 /*
369 * Reads end of deflated entry as well as EXT descriptor if present.
370 */
371 private void readEnd(ZipEntry e) throws IOException {
372 int n = inf.getRemaining();
373 if (n > 0) {
374 ((PushbackInputStream)in).unread(buf, len - n, n);
375 }
376 if ((flag & 8) == 8) {
377 /* "Data Descriptor" present */
378 readFully(tmpbuf, 0, EXTHDR);
379 long sig = get32(tmpbuf, 0);
380 if (sig != EXTSIG) { // no EXTSIG present
381 e.crc = sig;
382 e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
383 e.size = get32(tmpbuf, EXTLEN - EXTCRC);
384 ((PushbackInputStream)in).unread(
385 tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
386 } else {
387 e.crc = get32(tmpbuf, EXTCRC);
388 e.csize = get32(tmpbuf, EXTSIZ);
389 e.size = get32(tmpbuf, EXTLEN);
390 }
391 }
392 if (e.size != inf.getBytesWritten()) {
393 throw new ZipException(
394 "invalid entry size (expected " + e.size +
395 " but got " + inf.getBytesWritten() + " bytes)");
396 }
397 if (e.csize != inf.getBytesRead()) {
398 throw new ZipException(
399 "invalid entry compressed size (expected " + e.csize +
400 " but got " + inf.getBytesRead() + " bytes)");
401 }
402 if (e.crc != crc.getValue()) {
403 throw new ZipException(
404 "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
405 " but got 0x" + Long.toHexString(crc.getValue()) + ")");
406 }
407 }
408
409 /*
410 * Reads bytes, blocking until all bytes are read.
411 */
416 throw new EOFException();
417 }
418 off += n;
419 len -= n;
420 }
421 }
422
423 /*
424 * Fetches unsigned 16-bit value from byte array at specified offset.
425 * The bytes are assumed to be in Intel (little-endian) byte order.
426 */
427 private static final int get16(byte b[], int off) {
428 return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
429 }
430
431 /*
432 * Fetches unsigned 32-bit value from byte array at specified offset.
433 * The bytes are assumed to be in Intel (little-endian) byte order.
434 */
435 private static final long get32(byte b[], int off) {
436 return get16(b, off) | ((long)get16(b, off+2) << 16);
437 }
438 }
|
1 /*
2 * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package java.util.zip;
27
28 import java.io.InputStream;
29 import java.io.IOException;
30 import java.io.EOFException;
31 import java.io.PushbackInputStream;
32 import static java.util.zip.ZipConstants64.*;
33
34 /**
35 * This class implements an input stream filter for reading files in the
36 * ZIP file format. Includes support for both compressed and uncompressed
37 * entries.
38 *
39 * @author David Connelly
40 */
41 public
42 class ZipInputStream extends InflaterInputStream implements ZipConstants {
43 private ZipEntry entry;
44 private int flag;
45 private CRC32 crc = new CRC32();
46 private long remaining;
47 private byte[] tmpbuf = new byte[512];
48
49 private static final int STORED = ZipEntry.STORED;
50 private static final int DEFLATED = ZipEntry.DEFLATED;
51
52 private boolean closed = false;
269 throw new ZipException("encrypted ZIP entry not supported");
270 }
271 e.method = get16(tmpbuf, LOCHOW);
272 e.time = get32(tmpbuf, LOCTIM);
273 if ((flag & 8) == 8) {
274 /* "Data Descriptor" present */
275 if (e.method != DEFLATED) {
276 throw new ZipException(
277 "only DEFLATED entries can have EXT descriptor");
278 }
279 } else {
280 e.crc = get32(tmpbuf, LOCCRC);
281 e.csize = get32(tmpbuf, LOCSIZ);
282 e.size = get32(tmpbuf, LOCLEN);
283 }
284 len = get16(tmpbuf, LOCEXT);
285 if (len > 0) {
286 byte[] bb = new byte[len];
287 readFully(bb, 0, len);
288 e.setExtra(bb);
289 // extra fields are in "HeaderID(2)DataSize(2)Data... format
290 if (e.csize == ZIP64_MAGICVAL || e.size == ZIP64_MAGICVAL) {
291 int off = 0;
292 while (off + 4 < len) {
293 int sz = get16(bb, off + 2);
294 if (get16(bb, off) == ZIP64_EXTID) {
295 off += 4;
296 // LOC extra zip64 entry MUST include BOTH original and
297 // compressed file size fields
298 if (sz < 16 || (off + sz) > len ) {
299 // invalid zip64 extra fields, simply skip.
300 // throw new ZipException("invalid Zip64 extra fields in LOC");
301 return e;
302 }
303 e.size = get64(bb, off);
304 e.csize = get64(bb, off + 8);
305 break;
306 }
307 off += (sz + 4);
308 }
309 }
310 }
311 return e;
312 }
313
314 /*
315 * Fetches a UTF8-encoded String from the specified byte array.
316 */
317 private static String getUTF8String(byte[] b, int off, int len) {
318 // First, count the number of characters in the sequence
319 int count = 0;
320 int max = off + len;
321 int i = off;
322 while (i < max) {
323 int c = b[i++] & 0xff;
324 switch (c >> 4) {
325 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
326 // 0xxxxxxx
327 count++;
328 break;
329 case 12: case 13:
330 // 110xxxxx 10xxxxxx
380 * Creates a new <code>ZipEntry</code> object for the specified
381 * entry name.
382 *
383 * @param name the ZIP file entry name
384 * @return the ZipEntry just created
385 */
386 protected ZipEntry createZipEntry(String name) {
387 return new ZipEntry(name);
388 }
389
390 /*
391 * Reads end of deflated entry as well as EXT descriptor if present.
392 */
393 private void readEnd(ZipEntry e) throws IOException {
394 int n = inf.getRemaining();
395 if (n > 0) {
396 ((PushbackInputStream)in).unread(buf, len - n, n);
397 }
398 if ((flag & 8) == 8) {
399 /* "Data Descriptor" present */
400 if (inf.getBytesWritten() > ZIP64_MAGICVAL ||
401 inf.getBytesRead() > ZIP64_MAGICVAL) {
402 // ZIP64 format
403 readFully(tmpbuf, 0, ZIP64_EXTHDR);
404 long sig = get32(tmpbuf, 0);
405 if (sig != EXTSIG) { // no EXTSIG present
406 e.crc = sig;
407 e.csize = get64(tmpbuf, ZIP64_EXTSIZ - ZIP64_EXTCRC);
408 e.size = get64(tmpbuf, ZIP64_EXTLEN - ZIP64_EXTCRC);
409 ((PushbackInputStream)in).unread(
410 tmpbuf, ZIP64_EXTHDR - ZIP64_EXTCRC - 1, ZIP64_EXTCRC);
411 } else {
412 e.crc = get32(tmpbuf, ZIP64_EXTCRC);
413 e.csize = get64(tmpbuf, ZIP64_EXTSIZ);
414 e.size = get64(tmpbuf, ZIP64_EXTLEN);
415 }
416 } else {
417 readFully(tmpbuf, 0, EXTHDR);
418 long sig = get32(tmpbuf, 0);
419 if (sig != EXTSIG) { // no EXTSIG present
420 e.crc = sig;
421 e.csize = get32(tmpbuf, EXTSIZ - EXTCRC);
422 e.size = get32(tmpbuf, EXTLEN - EXTCRC);
423 ((PushbackInputStream)in).unread(
424 tmpbuf, EXTHDR - EXTCRC - 1, EXTCRC);
425 } else {
426 e.crc = get32(tmpbuf, EXTCRC);
427 e.csize = get32(tmpbuf, EXTSIZ);
428 e.size = get32(tmpbuf, EXTLEN);
429 }
430 }
431 }
432 if (e.size != inf.getBytesWritten()) {
433 throw new ZipException(
434 "invalid entry size (expected " + e.size +
435 " but got " + inf.getBytesWritten() + " bytes)");
436 }
437 if (e.csize != inf.getBytesRead()) {
438 throw new ZipException(
439 "invalid entry compressed size (expected " + e.csize +
440 " but got " + inf.getBytesRead() + " bytes)");
441 }
442 if (e.crc != crc.getValue()) {
443 throw new ZipException(
444 "invalid entry CRC (expected 0x" + Long.toHexString(e.crc) +
445 " but got 0x" + Long.toHexString(crc.getValue()) + ")");
446 }
447 }
448
449 /*
450 * Reads bytes, blocking until all bytes are read.
451 */
456 throw new EOFException();
457 }
458 off += n;
459 len -= n;
460 }
461 }
462
463 /*
464 * Fetches unsigned 16-bit value from byte array at specified offset.
465 * The bytes are assumed to be in Intel (little-endian) byte order.
466 */
467 private static final int get16(byte b[], int off) {
468 return (b[off] & 0xff) | ((b[off+1] & 0xff) << 8);
469 }
470
471 /*
472 * Fetches unsigned 32-bit value from byte array at specified offset.
473 * The bytes are assumed to be in Intel (little-endian) byte order.
474 */
475 private static final long get32(byte b[], int off) {
476 return (get16(b, off) | ((long)get16(b, off+2) << 16)) & 0xffffffffL;
477 }
478
479 /*
480 * Fetches signed 64-bit value from byte array at specified offset.
481 * The bytes are assumed to be in Intel (little-endian) byte order.
482 */
483 private static final long get64(byte b[], int off) {
484 return get32(b, off) | (get32(b, off+4) << 32);
485 }
486 }
|