Releases: nlink-jp/zip-porter
Release list
v0.11.0
Opening several archives at once is now one job, and a Finder-launched run
stops hanging around after it has finished.
Changed
- Several archives opened together are reported once, not N times
(ADR-016). Selecting three ZIPs in Finder produced three completion
banners about a second apart — and macOS replaces one banner with the
next from the same app, so only the last was readable while the rest
piled up in Notification Center. It also meant three Finder reveals, an
OK per archive on the dialog setting, a destination panel per archive on
ask every time, and a password prompt per archive for a set that
shares one password. A request now gets one progress bar weighted across
the whole selection ("2 of 3 — foo.zip"), one destination question, a
password carried to the next archive, one summary and one Finder reveal. - A failed archive no longer stops the rest. The remaining archives are
extracted and the result reads "2 of 3 archives extracted", naming what
failed. - Clicking a completion notification reveals the result in Finder.
Fixed
- The app no longer lingers after a Finder-launched run. It used to
post its banner, drop out of the Dock and stay alive ~4.5 s, because a
notification presented by the app is withdrawn when the app exits — and
that invisible-but-alive gap is what truncated an extraction mid-write in
v0.10.3. Notifications are now scheduled with a trigger, so the system
owns the presentation and the banner outlives the process: measured
process lifetime 6.3 s → 0.35 s, with the banner appearing and lasting
exactly as before. The deferred quit and the Dock demotion are gone
rather than guarded, and the ~1.2 s stall between archives went with them.
Requires macOS 14+ on Apple Silicon. Notarized and stapled.
v0.10.3
Fixed
- Opening a second archive right after the first no longer kills the work
in progress. After a Finder-launched run finishes, the app leaves the
Dock but stays alive for a few seconds so its completion banner is not cut
short. The quit scheduled for the end of that wait was unconditional, so
anything that arrived during it was destroyed on a timer belonging to the
previous job: an extraction in progress was terminated mid-write, leaving a
truncated file and no error (a 700 MB archive reproducibly left 543 MB
on disk); an encrypted archive's password prompt vanished about three
seconds into typing; and clicking the Dock icon to keep the app open got
the window taken away again. The quit is now cancelled by anything that
gives the process new purpose, and re-evaluated when it fires rather than
acting on a decision made seconds earlier. - A second archive opened while one is still running is now queued instead
of dropped. It answered with a beep and did nothing — inaudible from a
Finder launch, where there is no window on screen, so the second archive
simply never extracted.
Full Changelog: v0.10.2...v0.10.3
v0.10.2
Fixed
- ⌘V (and ⌘X / ⌘C / ⌘A / ⌘Z) now work in the password fields, and ⌘W
closes the droplet window. Both were missing for the same reason: the
app had no Edit menu and no Close item, and macOS routes those
shortcuts to the focused control through main-menu key equivalents —
with no matching item, the keystroke never reaches the text field.
The menu bar also draws the top-level menu item's own title, so the
new File and Edit menus carry titles rather than relying on their
submenu's (an untitled item is an invisible menu).
Full Changelog: v0.10.1...v0.10.2
v0.10.1
起動時クラッシュの修正。
ビルドした本人のマシン以外では、v0.10.0 以前は起動直後に必ずクラッシュしていました(EXC_BREAKPOINT)。SwiftPM が生成する Bundle.module はローカライズバンドルを .app のルート直下でしか探さず(実際のインストール先は Contents/Resources)、見つからないとコンパイル時に焼き込まれた .build の絶対パスにフォールバックするため、ビルド機だけで解決していたのが原因です。grid-edit v0.2.4 と同じ修正です。
リソースバンドルの探索を .app のレイアウトに合わせ、見つからない場合も英語文字列で動作を継続するようにしました。
v0.10.0
A security review of the extractor, and the five defects it found. Two of
them were crashes on malformed input; two were holes in guarantees the app
already claimed (Gatekeeper propagation, "never overwrite"); one let an
archive decide the permissions of the files it dropped on you.
Changed
- Hardening pass over the unchecked arithmetic and boundaries the two
crashes came from (#6): the little-endian readers are bounds-checked
and throwing, so a read added to the parser later cannot forget the
guard; entry ranges, the writer's 16/32-bit header conversions and the
extraction budget all reject values that would trap; archives and
extracted files are created withO_EXCL, so "never overwrite" no
longer rests on the gap between the check and the write; AES key
material is wiped once it stops being needed
Fixed
-
A malformed ZIP64 header crashed the process instead of being
rejected (#1). Two bounds checks in the central-directory parser did
their own arithmetic on attacker-supplied 64-bit values: the ZIP64
locator address (eocd - 20, underflowing on a 22-byte file whose EOCD
claims ZIP64) and the directory bounds (cdOffset + cdSize, overflowing
while checking themselves). Both trapped, taking the GUI down on a
double-clicked.zip. The checks now subtract from the file size instead
of adding to the offsets, and two hostile fixtures cover the shapes -
The pre-extraction free-space budget could be switched off from inside
the archive (#2). The declared total was summed with wrapping
arithmetic, so two ZIP64 entries declaring 2^63 apiece summed to exactly
zero and the budget check approved anything. Since per-entry fail-fast
only bounds an entry by its own declared size, that left a decompression
bomb free to fill the volume. The sum now saturates atUInt64.max, and
the check subtracts the margin from the free space instead of adding it
to the requirement -
Quarantine did not reach directories the extractor created
implicitly (#3), so an archive with no directory entries — 7-Zip writes
them that way routinely — produced a.appwhose files each carried
com.apple.quarantinebut whose bundle root, the thing Gatekeeper
actually evaluates, did not.dittomarks the bundle root; now so do we.
This was the ADR-012 §4 gap re-opening through a different door -
Extraction applied the archive's permission bits verbatim (#4), so an
archive asking for0777produced world-writable — and executable —
files in the user's folder. On a shared Mac another local account could
rewrite them. The requested mode is now masked with the process umask,
the ruleunzipanddittofollow (0777→0755,0666→0644
under the default umask); setuid/setgid never survived and still do not -
A failure to mark an extracted item as quarantined was silent (#5),
and the result claimed propagation had happened as long as the archive
carried the attribute. Failures are now collected per item and reported
the way every other security-relevant outcome is: a warning line in the
CLI, and the result dialog (never the quiet notification) in the GUI
v0.9.3
Fixes zip-porter --version printing "dev" when run through the cask's symlink. Launched that way, Bundle.main is not the .app, so the version was never found; it now falls back to the Info.plist beside the resolved executable.
Together with v0.9.2 this makes the documented CLI usable as written:
brew install --cask nlink-jp/tap/zip-porter
zip-porter --version
zip-porter pack ~/Documents/報告書v0.9.2
The CLI is now actually reachable. The README described zip-porter pack … while the executable sat inside the app bundle with nothing on PATH — the documented commands could not be run as written.
The cask now symlinks it, so installing gives you both the app and the command:
brew install --cask nlink-jp/tap/zip-porter
zip-porter --versionIf you install the .app by hand, link it yourself:
ln -s "/Applications/ZipPorter.app/Contents/MacOS/ZipPorter" /usr/local/bin/zip-porterBoth READMEs now say this up front. The shared org cask template gained an optional binary stanza, so other GUI apps with an embedded CLI can do the same.
v0.9.1
Excluded macOS metadata is now reported in the completion message instead of forcing the result dialog.
Dropping .DS_Store and friends is what this app is for — routine, not a warning — so packing any folder Finder had ever opened used to end in a dialog. That count now rides along in whichever completion style you chose (notification, dialog, or nothing).
Skipped symlinks, skipped unsafe paths and renamed duplicates are real deviations and still show the dialog.
Install: brew install --cask nlink-jp/tap/zip-porter
v0.9.0
How a successful finish is announced is now up to you. Settings › General › "When finished successfully":
- Notification — a banner, no click needed (the default; unchanged behavior)
- Dialog — the result summary with a Close button
- Nothing — the operation just completes
Runs that have something to report — skipped unsafe paths, renamed duplicates, excluded macOS metadata — still show the dialog whatever this is set to, and errors still alert. The setting cannot silence anything security-relevant.
Install: brew install --cask nlink-jp/tap/zip-porter
v0.8.3
Small correctness fix to the quit timing introduced in v0.8.2.
A Finder-launched run held the process for the banner's display time even when no banner had been shown — after a result dialog the user had already dismissed, or when notifications are switched off. It now waits only while a banner is actually on screen, and quits immediately otherwise.
Install: brew install --cask nlink-jp/tap/zip-porter