Details
-
Improvement
-
Status: Resolved
-
Major
-
Resolution: Fixed
-
1.21
Description
When writing to a Zip file through ZipArchiveOutputStream, setting creation and access times in a ZipArchiveEntry does not cause these to be reflected as X5455 or X000A extra fields in the resulting zip file. This also happens for modification times that do not fit into an MS-DOS time.
As a consequence, the date range is reduced, as well as the granularity (form 100ns intervals to seconds).
ZipEntry and standard java.util.zip facilities do that automatically, but that's missing here.
My proposal is to use the same logic the java.util.zip do and add those extra fields automatically, if situation requires them.
See my existing logic for this here: https://github.com/andrebrait/DATROMTool/blob/86a4f4978bab250ca54d047c58b4f91e7dbbcc7f/core/src/main/java/io/github/datromtool/io/FileCopier.java#L1425
It's (almost) the same logic from java.util.zip, but adapted to be used with ZipArchiveEntry.
If you're ok with it, I can send a PR.
Actual logic will be more like java.util.zip.ZipOutputStream#writeLOC(XEntry), represented below:
int elenEXTT = 0; // info-zip extended timestamp int flagEXTT = 0; long umtime = -1; long uatime = -1; long uctime = -1; if (e.mtime != null) { elenEXTT += 4; flagEXTT |= EXTT_FLAG_LMT; umtime = fileTimeToUnixTime(e.mtime); } if (e.atime != null) { elenEXTT += 4; flagEXTT |= EXTT_FLAG_LAT; uatime = fileTimeToUnixTime(e.atime); } if (e.ctime != null) { elenEXTT += 4; flagEXTT |= EXTT_FLAT_CT; uctime = fileTimeToUnixTime(e.ctime); } if (flagEXTT != 0) { // to use ntfs time if any m/a/ctime is beyond unixtime upper bound if (umtime > UPPER_UNIXTIME_BOUND || uatime > UPPER_UNIXTIME_BOUND || uctime > UPPER_UNIXTIME_BOUND) { elen += 36; // NTFS time, total 36 bytes } else { elen += (elenEXTT + 5); // headid(2) + size(2) + flag(1) + data } } writeShort(elen); writeBytes(nameBytes, 0, nameBytes.length); if (hasZip64) { writeShort(ZIP64_EXTID); writeShort(16); writeLong(e.size); writeLong(e.csize); } if (flagEXTT != 0) { if (umtime > UPPER_UNIXTIME_BOUND || uatime > UPPER_UNIXTIME_BOUND || uctime > UPPER_UNIXTIME_BOUND) { writeShort(EXTID_NTFS); // id writeShort(32); // data size writeInt(0); // reserved writeShort(0x0001); // NTFS attr tag writeShort(24); writeLong(e.mtime == null ? WINDOWS_TIME_NOT_AVAILABLE : fileTimeToWinTime(e.mtime)); writeLong(e.atime == null ? WINDOWS_TIME_NOT_AVAILABLE : fileTimeToWinTime(e.atime)); writeLong(e.ctime == null ? WINDOWS_TIME_NOT_AVAILABLE : fileTimeToWinTime(e.ctime)); } else { writeShort(EXTID_EXTT); writeShort(elenEXTT + 1); // flag + data writeByte(flagEXTT); if (e.mtime != null) writeInt(umtime); if (e.atime != null) writeInt(uatime); if (e.ctime != null) writeInt(uctime); } } writeExtra(e.extra); locoff = written;