jdk/src/share/classes/java/util/zip/ZipOutputStream.java
changeset 17910 82d10099a8a6
parent 16713 7824dded9821
child 19374 6773349693eb
equal deleted inserted replaced
17729:90a2bf654c4f 17910:82d10099a8a6
    30 import java.nio.charset.Charset;
    30 import java.nio.charset.Charset;
    31 import java.nio.charset.StandardCharsets;
    31 import java.nio.charset.StandardCharsets;
    32 import java.util.Vector;
    32 import java.util.Vector;
    33 import java.util.HashSet;
    33 import java.util.HashSet;
    34 import static java.util.zip.ZipConstants64.*;
    34 import static java.util.zip.ZipConstants64.*;
       
    35 import static java.util.zip.ZipUtils.*;
    35 
    36 
    36 /**
    37 /**
    37  * This class implements an output stream filter for writing files in the
    38  * This class implements an output stream filter for writing files in the
    38  * ZIP file format. Includes support for both compressed and uncompressed
    39  * ZIP file format. Includes support for both compressed and uncompressed
    39  * entries.
    40  * entries.
   188     public void putNextEntry(ZipEntry e) throws IOException {
   189     public void putNextEntry(ZipEntry e) throws IOException {
   189         ensureOpen();
   190         ensureOpen();
   190         if (current != null) {
   191         if (current != null) {
   191             closeEntry();       // close previous entry
   192             closeEntry();       // close previous entry
   192         }
   193         }
   193         if (e.time == -1) {
   194         if (e.mtime == -1) {
   194             e.setTime(System.currentTimeMillis());
   195             e.setTime(System.currentTimeMillis());
   195         }
   196         }
   196         if (e.method == -1) {
   197         if (e.method == -1) {
   197             e.method = method;  // use default method
   198             e.method = method;  // use default method
   198         }
   199         }
   380      * Writes local file (LOC) header for specified entry.
   381      * Writes local file (LOC) header for specified entry.
   381      */
   382      */
   382     private void writeLOC(XEntry xentry) throws IOException {
   383     private void writeLOC(XEntry xentry) throws IOException {
   383         ZipEntry e = xentry.entry;
   384         ZipEntry e = xentry.entry;
   384         int flag = e.flag;
   385         int flag = e.flag;
       
   386         boolean hasZip64 = false;
   385         int elen = (e.extra != null) ? e.extra.length : 0;
   387         int elen = (e.extra != null) ? e.extra.length : 0;
   386         boolean hasZip64 = false;
   388         int eoff = 0;
   387 
   389         boolean foundEXTT = false;      // if EXTT already present
       
   390                                         // do nothing.
       
   391         while (eoff + 4 < elen) {
       
   392             int tag = get16(e.extra, eoff);
       
   393             int sz = get16(e.extra, eoff + 2);
       
   394             if (tag == EXTID_EXTT) {
       
   395                 foundEXTT = true;
       
   396             }
       
   397             eoff += (4 + sz);
       
   398         }
   388         writeInt(LOCSIG);               // LOC header signature
   399         writeInt(LOCSIG);               // LOC header signature
   389 
       
   390         if ((flag & 8) == 8) {
   400         if ((flag & 8) == 8) {
   391             writeShort(version(e));     // version needed to extract
   401             writeShort(version(e));     // version needed to extract
   392             writeShort(flag);           // general purpose bit flag
   402             writeShort(flag);           // general purpose bit flag
   393             writeShort(e.method);       // compression method
   403             writeShort(e.method);       // compression method
   394             writeInt(e.time);           // last modification time
   404             writeInt(javaToDosTime(e.mtime)); // last modification time
   395 
   405 
   396             // store size, uncompressed size, and crc-32 in data descriptor
   406             // store size, uncompressed size, and crc-32 in data descriptor
   397             // immediately following compressed entry data
   407             // immediately following compressed entry data
   398             writeInt(0);
   408             writeInt(0);
   399             writeInt(0);
   409             writeInt(0);
   405             } else {
   415             } else {
   406                 writeShort(version(e)); // version needed to extract
   416                 writeShort(version(e)); // version needed to extract
   407             }
   417             }
   408             writeShort(flag);           // general purpose bit flag
   418             writeShort(flag);           // general purpose bit flag
   409             writeShort(e.method);       // compression method
   419             writeShort(e.method);       // compression method
   410             writeInt(e.time);           // last modification time
   420             writeInt(javaToDosTime(e.mtime)); // last modification time
   411             writeInt(e.crc);            // crc-32
   421             writeInt(e.crc);            // crc-32
   412             if (hasZip64) {
   422             if (hasZip64) {
   413                 writeInt(ZIP64_MAGICVAL);
   423                 writeInt(ZIP64_MAGICVAL);
   414                 writeInt(ZIP64_MAGICVAL);
   424                 writeInt(ZIP64_MAGICVAL);
   415                 elen += 20;        //headid(2) + size(2) + size(8) + csize(8)
   425                 elen += 20;        //headid(2) + size(2) + size(8) + csize(8)
   418                 writeInt(e.size);   // uncompressed size
   428                 writeInt(e.size);   // uncompressed size
   419             }
   429             }
   420         }
   430         }
   421         byte[] nameBytes = zc.getBytes(e.name);
   431         byte[] nameBytes = zc.getBytes(e.name);
   422         writeShort(nameBytes.length);
   432         writeShort(nameBytes.length);
       
   433         if (!foundEXTT)
       
   434             elen += 9;              // use Info-ZIP's ext time in extra
   423         writeShort(elen);
   435         writeShort(elen);
   424         writeBytes(nameBytes, 0, nameBytes.length);
   436         writeBytes(nameBytes, 0, nameBytes.length);
   425         if (hasZip64) {
   437         if (hasZip64) {
   426             writeShort(ZIP64_EXTID);
   438             writeShort(ZIP64_EXTID);
   427             writeShort(16);
   439             writeShort(16);
   428             writeLong(e.size);
   440             writeLong(e.size);
   429             writeLong(e.csize);
   441             writeLong(e.csize);
       
   442         }
       
   443         if (!foundEXTT) {
       
   444             writeShort(EXTID_EXTT);
       
   445             writeShort(5);          // size for the folowing data block
       
   446             writeByte(0x1);         // flags byte, mtime only
       
   447             writeInt(javaToUnixTime(e.mtime));
   430         }
   448         }
   431         if (e.extra != null) {
   449         if (e.extra != null) {
   432             writeBytes(e.extra, 0, e.extra.length);
   450             writeBytes(e.extra, 0, e.extra.length);
   433         }
   451         }
   434         locoff = written;
   452         locoff = written;
   455      */
   473      */
   456     private void writeCEN(XEntry xentry) throws IOException {
   474     private void writeCEN(XEntry xentry) throws IOException {
   457         ZipEntry e  = xentry.entry;
   475         ZipEntry e  = xentry.entry;
   458         int flag = e.flag;
   476         int flag = e.flag;
   459         int version = version(e);
   477         int version = version(e);
   460 
       
   461         long csize = e.csize;
   478         long csize = e.csize;
   462         long size = e.size;
   479         long size = e.size;
   463         long offset = xentry.offset;
   480         long offset = xentry.offset;
   464         int e64len = 0;
   481         int elenZIP64 = 0;
   465         boolean hasZip64 = false;
   482         boolean hasZip64 = false;
       
   483 
   466         if (e.csize >= ZIP64_MAGICVAL) {
   484         if (e.csize >= ZIP64_MAGICVAL) {
   467             csize = ZIP64_MAGICVAL;
   485             csize = ZIP64_MAGICVAL;
   468             e64len += 8;              // csize(8)
   486             elenZIP64 += 8;              // csize(8)
   469             hasZip64 = true;
   487             hasZip64 = true;
   470         }
   488         }
   471         if (e.size >= ZIP64_MAGICVAL) {
   489         if (e.size >= ZIP64_MAGICVAL) {
   472             size = ZIP64_MAGICVAL;    // size(8)
   490             size = ZIP64_MAGICVAL;    // size(8)
   473             e64len += 8;
   491             elenZIP64 += 8;
   474             hasZip64 = true;
   492             hasZip64 = true;
   475         }
   493         }
   476         if (xentry.offset >= ZIP64_MAGICVAL) {
   494         if (xentry.offset >= ZIP64_MAGICVAL) {
   477             offset = ZIP64_MAGICVAL;
   495             offset = ZIP64_MAGICVAL;
   478             e64len += 8;              // offset(8)
   496             elenZIP64 += 8;              // offset(8)
   479             hasZip64 = true;
   497             hasZip64 = true;
   480         }
   498         }
   481         writeInt(CENSIG);           // CEN header signature
   499         writeInt(CENSIG);           // CEN header signature
   482         if (hasZip64) {
   500         if (hasZip64) {
   483             writeShort(45);         // ver 4.5 for zip64
   501             writeShort(45);         // ver 4.5 for zip64
   486             writeShort(version);    // version made by
   504             writeShort(version);    // version made by
   487             writeShort(version);    // version needed to extract
   505             writeShort(version);    // version needed to extract
   488         }
   506         }
   489         writeShort(flag);           // general purpose bit flag
   507         writeShort(flag);           // general purpose bit flag
   490         writeShort(e.method);       // compression method
   508         writeShort(e.method);       // compression method
   491         writeInt(e.time);           // last modification time
   509         writeInt(javaToDosTime(e.mtime)); // last modification time
   492         writeInt(e.crc);            // crc-32
   510         writeInt(e.crc);            // crc-32
   493         writeInt(csize);            // compressed size
   511         writeInt(csize);            // compressed size
   494         writeInt(size);             // uncompressed size
   512         writeInt(size);             // uncompressed size
   495         byte[] nameBytes = zc.getBytes(e.name);
   513         byte[] nameBytes = zc.getBytes(e.name);
   496         writeShort(nameBytes.length);
   514         writeShort(nameBytes.length);
       
   515 
       
   516         int elen = (e.extra != null) ? e.extra.length : 0;
       
   517         int eoff = 0;
       
   518         boolean foundEXTT = false;  // if EXTT already present
       
   519                                     // do nothing.
       
   520         while (eoff + 4 < elen) {
       
   521             int tag = get16(e.extra, eoff);
       
   522             int sz = get16(e.extra, eoff + 2);
       
   523             if (tag == EXTID_EXTT) {
       
   524                 foundEXTT = true;
       
   525             }
       
   526             eoff += (4 + sz);
       
   527         }
   497         if (hasZip64) {
   528         if (hasZip64) {
   498             // + headid(2) + datasize(2)
   529             // + headid(2) + datasize(2)
   499             writeShort(e64len + 4 + (e.extra != null ? e.extra.length : 0));
   530             elen += (elenZIP64 + 4);
   500         } else {
   531         }
   501             writeShort(e.extra != null ? e.extra.length : 0);
   532         if (!foundEXTT)
   502         }
   533             elen += 9;              // Info-ZIP's Extended Timestamp
       
   534         writeShort(elen);
   503         byte[] commentBytes;
   535         byte[] commentBytes;
   504         if (e.comment != null) {
   536         if (e.comment != null) {
   505             commentBytes = zc.getBytes(e.comment);
   537             commentBytes = zc.getBytes(e.comment);
   506             writeShort(Math.min(commentBytes.length, 0xffff));
   538             writeShort(Math.min(commentBytes.length, 0xffff));
   507         } else {
   539         } else {
   513         writeInt(0);                // external file attributes (unused)
   545         writeInt(0);                // external file attributes (unused)
   514         writeInt(offset);           // relative offset of local header
   546         writeInt(offset);           // relative offset of local header
   515         writeBytes(nameBytes, 0, nameBytes.length);
   547         writeBytes(nameBytes, 0, nameBytes.length);
   516         if (hasZip64) {
   548         if (hasZip64) {
   517             writeShort(ZIP64_EXTID);// Zip64 extra
   549             writeShort(ZIP64_EXTID);// Zip64 extra
   518             writeShort(e64len);
   550             writeShort(elenZIP64);
   519             if (size == ZIP64_MAGICVAL)
   551             if (size == ZIP64_MAGICVAL)
   520                 writeLong(e.size);
   552                 writeLong(e.size);
   521             if (csize == ZIP64_MAGICVAL)
   553             if (csize == ZIP64_MAGICVAL)
   522                 writeLong(e.csize);
   554                 writeLong(e.csize);
   523             if (offset == ZIP64_MAGICVAL)
   555             if (offset == ZIP64_MAGICVAL)
   524                 writeLong(xentry.offset);
   556                 writeLong(xentry.offset);
       
   557         }
       
   558         if (!foundEXTT) {
       
   559             writeShort(EXTID_EXTT);
       
   560             writeShort(5);
       
   561             writeByte(0x1);            // flags byte
       
   562             writeInt(javaToUnixTime(e.mtime));
   525         }
   563         }
   526         if (e.extra != null) {
   564         if (e.extra != null) {
   527             writeBytes(e.extra, 0, e.extra.length);
   565             writeBytes(e.extra, 0, e.extra.length);
   528         }
   566         }
   529         if (commentBytes != null) {
   567         if (commentBytes != null) {
   587             writeShort(0);
   625             writeShort(0);
   588         }
   626         }
   589     }
   627     }
   590 
   628 
   591     /*
   629     /*
       
   630      * Writes a 8-bit byte to the output stream.
       
   631      */
       
   632     private void writeByte(int v) throws IOException {
       
   633         OutputStream out = this.out;
       
   634         out.write(v & 0xff);
       
   635         written += 1;
       
   636     }
       
   637 
       
   638     /*
   592      * Writes a 16-bit short to the output stream in little-endian byte order.
   639      * Writes a 16-bit short to the output stream in little-endian byte order.
   593      */
   640      */
   594     private void writeShort(int v) throws IOException {
   641     private void writeShort(int v) throws IOException {
   595         OutputStream out = this.out;
   642         OutputStream out = this.out;
   596         out.write((v >>> 0) & 0xff);
   643         out.write((v >>> 0) & 0xff);