Skip to content

feat: listContents + selective extract via unzip entries (#365) - #369

Merged
plrthink merged 8 commits into
masterfrom
cursor/list-contents-selective-extract-b7ed
Aug 15, 2026
Merged

feat: listContents + selective extract via unzip entries (#365)#369
plrthink merged 8 commits into
masterfrom
cursor/list-contents-selective-extract-b7ed

Conversation

@plrthink

@plrthink plrthink commented Jul 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements #365 (P0): inspect ZIP archives and extract only selected entries on both platforms.

APIs

  • listContents(source, charset?)ZipEntry[] (path, size, compressedSize, isDirectory, isEncrypted)
  • Optional entries on existing unzip APIs (no separate unzipFiles* methods):
    • unzip(source, target, charset?, entries?) — also accepts unzip(src, dest, ['a.txt'])
    • unzipWithPassword(source, target, password, entries?)

E2E

  • Maestro _list-contents-test.yaml wired into ci-master.yaml
  • Covers list contents, selective unzip, and password selective unzip
  • Playground demos assert Listed Entries / Selective Extract / Password Selective Extract (including skipped hello.txt)

Implementation notes

  • Android: zip4j file headers + existing Zip Slip checks
  • iOS: minizip central-directory listing + selective extract with path-traversal guard
  • TurboModule spec, TypeScript types, Jest mocks/tests, Android entry-matching unit tests

Test plan

  • npm test
  • Maestro flow added to CI master suite
  • Confirm CI E2E (expo + rn, Android + iOS) green
  • Confirm Zip Slip rejected for ../ selected entries

Stack

Merge first: this PR → #370#371#372

Open in Web Open in Cursor 

Expose listContents, unzipFiles, and unzipFilesWithPassword on iOS and
Android so apps can inspect archives and extract only selected entries
without switching to another library.

Co-authored-by: Perry <plrthink@gmail.com>
cursoragent and others added 4 commits July 25, 2026 01:58
Co-authored-by: Perry <plrthink@gmail.com>
Co-authored-by: Perry <plrthink@gmail.com>
Co-authored-by: Perry <plrthink@gmail.com>
Remove unzipFiles/unzipFilesWithPassword and add an optional entries
argument to unzip and unzipWithPassword instead, matching the existing
zip overload style.

Co-authored-by: Perry <plrthink@gmail.com>
@cursor cursor Bot changed the title feat: listContents + selective extract APIs (#365) feat: listContents + selective extract via unzip entries (#365) Jul 27, 2026
cursoragent and others added 3 commits July 27, 2026 01:33
Add Maestro coverage for listing archive entries, selective unzip via
entries, and password selective unzip. Playground demos now surface
assertable Listed Entries / Selective Extract / Password Selective
Extract results including files that were intentionally skipped.

Co-authored-by: Perry <plrthink@gmail.com>
Remove an extra closing brace left from the selective-extract cherry-pick
that broke Android compilation on stacked PRs. Make the list/selective
Maestro flow assert stable accessibility labels and summary markers.

Co-authored-by: Perry <plrthink@gmail.com>
zip4j cannot extract ZIP_STANDARD_VARIANT_STRONG, which caused
password selective extract E2E to fail with "encryption method is
not supported". Map explicit STANDARD to ZIP_STANDARD like the
default path.

Co-authored-by: Perry <plrthink@gmail.com>
@plrthink
plrthink marked this pull request as ready for review August 15, 2026 12:57
@cursor

cursor Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@plrthink
plrthink merged commit 74de841 into master Aug 15, 2026
8 of 9 checks passed

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 potential issues.

View 1 additional finding in Devin Review.

Open in Devin Review

Comment thread ios/RNZipArchive.mm
Comment thread android/src/main/java/com/rnziparchive/RNZipArchiveModule.java
Comment thread ios/RNZipArchive.mm
cursor Bot pushed a commit that referenced this pull request Aug 15, 2026
Rebased onto master after #369 was squash-merged so this PR no longer
conflicts with the rewritten listContents history.

Co-authored-by: Perry <plrthink@gmail.com>
cursor Bot pushed a commit that referenced this pull request Aug 15, 2026
Rebased onto #370 after #369 was squash-merged.

Co-authored-by: Perry <plrthink@gmail.com>
cursor Bot pushed a commit that referenced this pull request Aug 15, 2026
Rebased onto #371 after #369 was squash-merged.

Co-authored-by: Perry <plrthink@gmail.com>
cursor Bot pushed a commit that referenced this pull request Aug 15, 2026
Rebased onto #370 after #369 was squash-merged.

Co-authored-by: Perry <plrthink@gmail.com>
cursor Bot pushed a commit that referenced this pull request Aug 15, 2026
Rebased onto #371 after #369 was squash-merged.

Co-authored-by: Perry <plrthink@gmail.com>
cursor Bot pushed a commit that referenced this pull request Aug 15, 2026
Rebased onto #370 after #369 was squash-merged.

Co-authored-by: Perry <plrthink@gmail.com>
cursor Bot pushed a commit that referenced this pull request Aug 15, 2026
Rebased onto #371 after #369 was squash-merged.

Co-authored-by: Perry <plrthink@gmail.com>
plrthink added a commit that referenced this pull request Aug 15, 2026
* feat: cancel() + stable error codes (#366)

Rebased onto master after #369 was squash-merged so this PR no longer
conflicts with the rewritten listContents history.

Co-authored-by: Perry <plrthink@gmail.com>

* fix: address review comments on cancel, extract CRC, and sizes

Make iOS cancel() interrupt in-flight work by running zip/unzip on a
background queue instead of the serial method queue. Reset Android's
cancel flag when enqueueing work so a cancel right after start is not
discarded. Selective extract now checks fwrite and CRC, maps password
failures to ERR_WRONG_PASSWORD, and listContents uses 64-bit zip info.
Document Android STANDARD encryption as ZipCrypto.

Co-authored-by: Perry <plrthink@gmail.com>

* fix: align selective-extract progress and password charset

On iOS, emit 0% progress when selective extract fails instead of
forcing 100% before reject, matching Android. On Android, do not
force UTF-8 when unzipWithPassword extracts selected entries so
entry names match the full unzipWithPassword path.

Co-authored-by: Perry <plrthink@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
plrthink added a commit that referenced this pull request Aug 15, 2026
* fix(ios): zip interoperability for server-side unzippers (#367)

Rebased onto #370 after #369 was squash-merged.

Co-authored-by: Perry <plrthink@gmail.com>

* docs: file-array zipWithPassword honors encryptionType on iOS

The interoperability change writes ZipCrypto vs AES based on
encryptionType for file arrays; drop the outdated README callout.

Co-authored-by: Perry <plrthink@gmail.com>

* docs: note iOS file-array zipWithPassword default is now ZipCrypto

Omitting encryptionType used to always write WinZip-AES for iOS file
arrays. Callers who need AES must pass AES-128 or AES-256.

Co-authored-by: Perry <plrthink@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
plrthink added a commit that referenced this pull request Aug 15, 2026
Rebased onto #371 after #369 was squash-merged.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
plrthink added a commit that referenced this pull request Aug 16, 2026
* fix(ios): zip interoperability for server-side unzippers (#367) (#371)

* fix(ios): zip interoperability for server-side unzippers (#367)

Rebased onto #370 after #369 was squash-merged.

Co-authored-by: Perry <plrthink@gmail.com>

* docs: file-array zipWithPassword honors encryptionType on iOS

The interoperability change writes ZipCrypto vs AES based on
encryptionType for file arrays; drop the outdated README callout.

Co-authored-by: Perry <plrthink@gmail.com>

* docs: note iOS file-array zipWithPassword default is now ZipCrypto

Omitting encryptionType used to always write WinZip-AES for iOS file
arrays. Callers who need AES must pass AES-128 or AES-256.

Co-authored-by: Perry <plrthink@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

* feat: close iOS/Android platform parity gaps (#368) (#372)

Rebased onto #371 after #369 was squash-merged.

Co-authored-by: Cursor Agent <cursoragent@cursor.com>

* fix: restore Maestro install retries and align unzip failure progress

Keep the hardened E2E Maestro install from master (retry + version
check). Emit 0% progress when iOS unzip/unzipAssets fails, matching
Android. Document the iOS file-array ZipCrypto default in MIGRATION.md.

Co-authored-by: Perry <plrthink@gmail.com>

* docs: point README migrating section at v9.2–v9.4 notes

Co-authored-by: Perry <plrthink@gmail.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants