/**
  * Creates a new zip entry with fields taken from the specified zip entry.
  *
  * <p>Assumes the entry represents a directory if and only if the name ends with a forward slash
  * "/".
  *
  * @param entry the entry to get fields from
  * @throws ZipException on error
  */
 public ZipArchiveEntry(ZipArchiveEntry entry) throws ZipException {
   this((java.util.zip.ZipEntry) entry);
   setInternalAttributes(entry.getInternalAttributes());
   setExternalAttributes(entry.getExternalAttributes());
   setExtraFields(getAllExtraFieldsNoCopy());
   setPlatform(entry.getPlatform());
   GeneralPurposeBit other = entry.getGeneralPurposeBit();
   setGeneralPurposeBit(other == null ? null : (GeneralPurposeBit) other.clone());
 }
 /* (non-Javadoc)
  * @see java.lang.Object#equals(java.lang.Object)
  */
 @Override
 public boolean equals(Object obj) {
   if (this == obj) {
     return true;
   }
   if (obj == null || getClass() != obj.getClass()) {
     return false;
   }
   ZipArchiveEntry other = (ZipArchiveEntry) obj;
   String myName = getName();
   String otherName = other.getName();
   if (myName == null) {
     if (otherName != null) {
       return false;
     }
   } else if (!myName.equals(otherName)) {
     return false;
   }
   String myComment = getComment();
   String otherComment = other.getComment();
   if (myComment == null) {
     myComment = "";
   }
   if (otherComment == null) {
     otherComment = "";
   }
   return getTime() == other.getTime()
       && myComment.equals(otherComment)
       && getInternalAttributes() == other.getInternalAttributes()
       && getPlatform() == other.getPlatform()
       && getExternalAttributes() == other.getExternalAttributes()
       && getMethod() == other.getMethod()
       && getSize() == other.getSize()
       && getCrc() == other.getCrc()
       && getCompressedSize() == other.getCompressedSize()
       && Arrays.equals(getCentralDirectoryExtra(), other.getCentralDirectoryExtra())
       && Arrays.equals(getLocalFileDataExtra(), other.getLocalFileDataExtra())
       && gpb.equals(other.gpb);
 }
  /**
   * Writes the central file header entry.
   *
   * @param ze the entry to write
   * @throws IOException on error
   * @throws Zip64RequiredException if the archive's size exceeds 4 GByte and {@link Zip64Mode
   *     #setUseZip64} is {@link Zip64Mode#Never}.
   */
  protected void writeCentralFileHeader(ZipArchiveEntry ze) throws IOException {
    writeOut(CFH_SIG);
    written += WORD;

    final long lfhOffset = offsets.get(ze).longValue();
    final boolean needsZip64Extra =
        hasZip64Extra(ze)
            || ze.getCompressedSize() >= ZIP64_MAGIC
            || ze.getSize() >= ZIP64_MAGIC
            || lfhOffset >= ZIP64_MAGIC;

    if (needsZip64Extra && zip64Mode == Zip64Mode.Never) {
      // must be the offset that is too big, otherwise an
      // exception would have been throw in putArchiveEntry or
      // closeArchiveEntry
      throw new Zip64RequiredException(Zip64RequiredException.ARCHIVE_TOO_BIG_MESSAGE);
    }

    handleZip64Extra(ze, lfhOffset, needsZip64Extra);

    // version made by
    // CheckStyle:MagicNumber OFF
    writeOut(
        ZipShort.getBytes(
            (ze.getPlatform() << 8)
                | (!hasUsedZip64 ? DATA_DESCRIPTOR_MIN_VERSION : ZIP64_MIN_VERSION)));
    written += SHORT;

    final int zipMethod = ze.getMethod();
    final boolean encodable = zipEncoding.canEncode(ze.getName());
    writeVersionNeededToExtractAndGeneralPurposeBits(
        zipMethod, !encodable && fallbackToUTF8, needsZip64Extra);
    written += WORD;

    // compression method
    writeOut(ZipShort.getBytes(zipMethod));
    written += SHORT;

    // last mod. time and date
    writeOut(ZipUtil.toDosTime(ze.getTime()));
    written += WORD;

    // CRC
    // compressed length
    // uncompressed length
    writeOut(ZipLong.getBytes(ze.getCrc()));
    if (ze.getCompressedSize() >= ZIP64_MAGIC || ze.getSize() >= ZIP64_MAGIC) {
      writeOut(ZipLong.ZIP64_MAGIC.getBytes());
      writeOut(ZipLong.ZIP64_MAGIC.getBytes());
    } else {
      writeOut(ZipLong.getBytes(ze.getCompressedSize()));
      writeOut(ZipLong.getBytes(ze.getSize()));
    }
    // CheckStyle:MagicNumber OFF
    written += 12;
    // CheckStyle:MagicNumber ON

    ByteBuffer name = getName(ze);

    writeOut(ZipShort.getBytes(name.limit()));
    written += SHORT;

    // extra field length
    byte[] extra = ze.getCentralDirectoryExtra();
    writeOut(ZipShort.getBytes(extra.length));
    written += SHORT;

    // file comment length
    String comm = ze.getComment();
    if (comm == null) {
      comm = "";
    }

    ByteBuffer commentB = getEntryEncoding(ze).encode(comm);

    writeOut(ZipShort.getBytes(commentB.limit()));
    written += SHORT;

    // disk number start
    writeOut(ZERO);
    written += SHORT;

    // internal file attributes
    writeOut(ZipShort.getBytes(ze.getInternalAttributes()));
    written += SHORT;

    // external file attributes
    writeOut(ZipLong.getBytes(ze.getExternalAttributes()));
    written += WORD;

    // relative offset of LFH
    writeOut(ZipLong.getBytes(Math.min(lfhOffset, ZIP64_MAGIC)));
    written += WORD;

    // file name
    writeOut(name.array(), name.arrayOffset(), name.limit() - name.position());
    written += name.limit();

    // extra field
    writeOut(extra);
    written += extra.length;

    // file comment
    writeOut(commentB.array(), commentB.arrayOffset(), commentB.limit() - commentB.position());
    written += commentB.limit();
  }