src/share/classes/java/util/zip/ZipInputStream.java

Print this page


   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 }