Ejemplo n.º 1
0
 private void positionAtCentralDirectory64() throws IOException {
   this.skipBytes(4);
   this.archive.readFully(this.DWORD_BUF);
   this.archive.seek(ZipEightByteInteger.getLongValue(this.DWORD_BUF));
   this.archive.readFully(this.WORD_BUF);
   if (!Arrays.equals(this.WORD_BUF, ZipOutputStream.ZIP64_EOCD_SIG)) {
     throw new ZipException("archive's ZIP64 end of central directory locator is corrupt.");
   }
   this.skipBytes(44);
   this.archive.readFully(this.DWORD_BUF);
   this.archive.seek(ZipEightByteInteger.getLongValue(this.DWORD_BUF));
 }
 /**
  * Writes the data descriptor entry.
  *
  * @param ze the entry to write
  * @throws IOException on error
  */
 protected void writeDataDescriptor(ZipArchiveEntry ze) throws IOException {
   if (ze.getMethod() != DEFLATED || raf != null) {
     return;
   }
   writeOut(DD_SIG);
   writeOut(ZipLong.getBytes(ze.getCrc()));
   int sizeFieldSize = WORD;
   if (!hasZip64Extra(ze)) {
     writeOut(ZipLong.getBytes(ze.getCompressedSize()));
     writeOut(ZipLong.getBytes(ze.getSize()));
   } else {
     sizeFieldSize = DWORD;
     writeOut(ZipEightByteInteger.getBytes(ze.getCompressedSize()));
     writeOut(ZipEightByteInteger.getBytes(ze.getSize()));
   }
   written += 2 * WORD + 2 * sizeFieldSize;
 }
  /**
   * When using random access output, write the local file header and potentiall the ZIP64 extra
   * containing the correct CRC and compressed/uncompressed sizes.
   */
  private void rewriteSizesAndCrc(boolean actuallyNeedsZip64) throws IOException {
    long save = raf.getFilePointer();

    raf.seek(entry.localDataStart);
    writeOut(ZipLong.getBytes(entry.entry.getCrc()));
    if (!hasZip64Extra(entry.entry) || !actuallyNeedsZip64) {
      writeOut(ZipLong.getBytes(entry.entry.getCompressedSize()));
      writeOut(ZipLong.getBytes(entry.entry.getSize()));
    } else {
      writeOut(ZipLong.ZIP64_MAGIC.getBytes());
      writeOut(ZipLong.ZIP64_MAGIC.getBytes());
    }

    if (hasZip64Extra(entry.entry)) {
      // seek to ZIP64 extra, skip header and size information
      raf.seek(
          entry.localDataStart + 3 * WORD + 2 * SHORT + getName(entry.entry).limit() + 2 * SHORT);
      // inside the ZIP64 extra uncompressed size comes
      // first, unlike the LFH, CD or data descriptor
      writeOut(ZipEightByteInteger.getBytes(entry.entry.getSize()));
      writeOut(ZipEightByteInteger.getBytes(entry.entry.getCompressedSize()));

      if (!actuallyNeedsZip64) {
        // do some cleanup:
        // * rewrite version needed to extract
        raf.seek(entry.localDataStart - 5 * SHORT);
        writeOut(ZipShort.getBytes(INITIAL_VERSION));

        // * remove ZIP64 extra so it doesn't get written
        //   to the central directory
        entry.entry.removeExtraField(Zip64ExtendedInformationExtraField.HEADER_ID);
        entry.entry.setExtra();

        // * reset hasUsedZip64 if it has been set because
        //   of this entry
        if (entry.causedUseOfZip64) {
          hasUsedZip64 = false;
        }
      }
    }
    raf.seek(save);
  }
  /**
   * Writes the "ZIP64 End of central dir record" and "ZIP64 End of central dir
   * locator".
   *
   * @throws IOException on error
   * @since 1.3
   */
  protected void writeZip64CentralDirectory() throws IOException {
    if (zip64Mode == Zip64Mode.Never) {
      return;
    }

    if (!hasUsedZip64
        && (cdOffset >= ZIP64_MAGIC
            || cdLength >= ZIP64_MAGIC
            || entries.size() >= ZIP64_MAGIC_SHORT)) {
      // actually "will use"
      hasUsedZip64 = true;
    }

    if (!hasUsedZip64) {
      return;
    }

    long offset = written;

    writeOut(ZIP64_EOCD_SIG);
    // size, we don't have any variable length as we don't support
    // the extensible data sector, yet
    writeOut(
        ZipEightByteInteger.getBytes(
            SHORT /* version made by */
                + SHORT /* version needed to extract */
                + WORD /* disk number */
                + WORD /* disk with central directory */
                + DWORD /* number of entries in CD on this disk */
                + DWORD /* total number of entries */
                + DWORD /* size of CD */
                + DWORD /* offset of CD */));

    // version made by and version needed to extract
    writeOut(ZipShort.getBytes(ZIP64_MIN_VERSION));
    writeOut(ZipShort.getBytes(ZIP64_MIN_VERSION));

    // disk numbers - four bytes this time
    writeOut(LZERO);
    writeOut(LZERO);

    // number of entries
    byte[] num = ZipEightByteInteger.getBytes(entries.size());
    writeOut(num);
    writeOut(num);

    // length and location of CD
    writeOut(ZipEightByteInteger.getBytes(cdLength));
    writeOut(ZipEightByteInteger.getBytes(cdOffset));

    // no "zip64 extensible data sector" for now

    // and now the "ZIP64 end of central directory locator"
    writeOut(ZIP64_EOCD_LOC_SIG);

    // disk number holding the ZIP64 EOCD record
    writeOut(LZERO);
    // relative offset of ZIP64 EOCD record
    writeOut(ZipEightByteInteger.getBytes(offset));
    // total number of disks
    writeOut(ONE);
  }