Skip to content

v2.8.58

Choose a tag to compare

@gildas-lormeau gildas-lormeau released this 24 Aug 14:07
· 19 commits to master since this release

What's Changed in v2.8.58

New features

  • New ZipWriter#appendZip method. It copies the entries of an existing zip file into the current zip. Unlike prependZip, it can be called at any position: after entries have been added, between add() calls, and repeatedly to merge several zip files. The central directory of the copied file is rebuilt and its entries are relocated to the positions they get in the output. prependZip is kept as a deprecated alias
  • New rawLastModDate option of ZipWriter#add. It sets the raw MS-DOS date and time of the entry directly, which passThrough copies of ZipCrypto entries need (see below)
  • New localDirectory.dataOffset property. It is the byte offset of the entry data, i.e. the entry offset plus the size of the local file header, of the filename and of the extra field. It can be used with Reader#createReadable to serve ranged requests into an entry stored without compression
  • New ERR_ZIP_CRYPTO_LAST_MOD_DATE error constant

Behavior changes

  • Errors of add() and appendZip() calls left un-awaited are not lost anymore. close() waits for the pending calls and throws the first unreported error, with all of them available in its entryErrors property. Throwing counts as reporting: catching the error and calling close() again finalizes the zip file without the failed entries. ZipWriterStream now aborts its writable when an entry fails, so the readable errors instead of hanging
  • An interrupted appendZip() copy now sets hasCorruptedEntries on the writer and keeps the offsets of the entries written after it consistent
  • The "version needed to extract" field is now 10 for entries stored without compression or encryption, instead of 20
  • Last modification dates before 1980 are now clamped to the MS-DOS epoch instead of underflowing the date field
  • The directory property of read entries is now derived from the trailing slash of the filename alone. A name ending with "/" is a folder even when the entry declares an uncompressed size
  • Unicode Path and Unicode Comment extra fields are now applied only when their version is 1, as required by section 4.6.8 of the zip specification
  • Reading an archive with a multiple of 65,536 entries and no zip64 record now returns all the entries. The 16-bit count of the end of central directory record wraps around; the reader detects the wrap by walking the central directory records past the declared count. The recovery is skipped when the strictness checks reject ambiguous archives
  • The unsafe* optimizations of the minifier were removed from the builds. Two of them shipped real miscompilations in the past, one of which stayed undetected for four years, and the size they saved was about 50 bytes per compressed bundle

Bug fixes

  • ZipCrypto entries copied with passThrough can now be read back with their password. The password verification byte of ZipCrypto depends on the raw date of the entry when a data descriptor is used, so a copy that regenerated the date or forced the descriptor failed with ERR_INVALID_PASSWORD. The dataDescriptor option is not forced anymore for pass-through ZipCrypto data, the new rawLastModDate option preserves the raw date, and the filesystem API forwards both when exporting, throwing the new ERR_ZIP_CRYPTO_LAST_MOD_DATE error if the date is overridden
  • The end of central directory records of split zip files now declare the number of central directory entries stored on the last disk, as required by section 4.4.21 of the zip specification, instead of the total. The count is 0 when the record starts on a fresh disk, which is how Info-ZIP fills the field. The check deciding whether the disk number of the record requires zip64 also accounts for the actual record and comment length when predicting a disk rollover near 65,535 disks
  • The spanning signature of split zip files is now written while holding the writer lock. A first entry written with bufferedWrite, or interleaved un-awaited add() calls, could fail on the locked stream or misplace the signature
  • Duplicate filenames are now detected before the entry waits for a worker slot. Two add() calls with the same filename made while the worker pool was saturated could both be accepted

Documentation

  • The usdz option states that its constraints apply to the entries written with add() only. The entries copied with appendZip keep the layout of the source zip file and are not checked
  • The ZipReader constructor states that a stream input is buffered entirely in memory, because reading a zip file requires random access, and points at custom Reader implementations for large seekable resources
  • WritableWriter#size states that a value set before the first write is used as the starting offset
  • useUnicodeFileNames states that disabling it only clears the language encoding flag and does not re-encode the filenames
  • passThrough documents the coupling between ZipCrypto and the last modification date
  • msDosCompatible documents how PKUNZIP handles folder entries

Tests and continuous integration

  • New PKZIP 1.10 and PKZIP 2.04g fixtures (attributes, comments, spanned archives) with tests reading the archives produced by the original tools
  • New regression tests lock the fixes above: the spanning signature position with concurrent and buffered writes, the per-disk entry counts of spanning central directories, including in the golden output, the ZipCrypto pass-through copies, the queued duplicate names, and the retryable close()
  • The Safari suite retries up to four times, the ZipCrypto tests are immune to date and wrong-password flakes, and the test fixtures are resolved independently of the working directory
  • The dead extra field handling of the appendZip entry rebuild was removed, making it explicit that copied entries carry their extra fields verbatim