Skip to content

Releases: nlink-jp/zip-porter

v0.11.0

Choose a tag to compare

@magifd2 magifd2 released this 03 Aug 10:16

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

Choose a tag to compare

@magifd2 magifd2 released this 03 Aug 02:17

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

Choose a tag to compare

@magifd2 magifd2 released this 03 Aug 01:49

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

Choose a tag to compare

@magifd2 magifd2 released this 02 Aug 23:38

起動時クラッシュの修正。

ビルドした本人のマシン以外では、v0.10.0 以前は起動直後に必ずクラッシュしていました(EXC_BREAKPOINT)。SwiftPM が生成する Bundle.module はローカライズバンドルを .app のルート直下でしか探さず(実際のインストール先は Contents/Resources)、見つからないとコンパイル時に焼き込まれた .build の絶対パスにフォールバックするため、ビルド機だけで解決していたのが原因です。grid-edit v0.2.4 と同じ修正です。

リソースバンドルの探索を .app のレイアウトに合わせ、見つからない場合も英語文字列で動作を継続するようにしました。

v0.10.0

Choose a tag to compare

@magifd2 magifd2 released this 02 Aug 03:46

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 with O_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 at UInt64.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 .app whose files each carried
    com.apple.quarantine but whose bundle root, the thing Gatekeeper
    actually evaluates, did not. ditto marks 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 for 0777 produced 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 rule unzip and ditto follow (07770755, 06660644
    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

Choose a tag to compare

@magifd2 magifd2 released this 02 Aug 00:30

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

Choose a tag to compare

@magifd2 magifd2 released this 02 Aug 00:27

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 --version

If you install the .app by hand, link it yourself:

ln -s "/Applications/ZipPorter.app/Contents/MacOS/ZipPorter" /usr/local/bin/zip-porter

Both 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

Choose a tag to compare

@magifd2 magifd2 released this 02 Aug 00:07

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

Choose a tag to compare

@magifd2 magifd2 released this 01 Aug 14:21

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

Choose a tag to compare

@magifd2 magifd2 released this 01 Aug 14:14

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