Skip to content

feat(archives): read CBR and CB7 through libarchive - #30

Closed
devaryakjha wants to merge 3 commits into
claude/project-thread-eheuhr-a11yfrom
claude/project-thread-eheuhr-archives
Closed

devaryakjha wants to merge 3 commits into
claude/project-thread-eheuhr-a11yfrom
claude/project-thread-eheuhr-archives

Conversation

@devaryakjha

Copy link
Copy Markdown
Contributor

Requested by Arya · project thread

Before

ChekReaderArchives was a placeholder: it claimed CBR and CB7 and threw notYetImplemented for both. The format sniffer already recognised RAR and 7-Zip signatures, so those comics failed to open with a clear error and nothing more.

After

ArchivesModule opens CBR (RAR 4 and RAR 5) and CB7 from a file, memory, a URL or a resource provider. Pages, natural ordering, folders as chapters and ComicInfo.xml work exactly as for CBZ, because the archive feeds the same comic parser. Entries are checked against ReaderLimits (count, total size, size per resource) before anything is read. Password-protected archives fail with ReaderError.drmProtected(scheme: "password"), and damaged ones with malformed carrying libarchive's message.

The add-on stays out of the umbrella product, as decided. Apps register it alongside the defaults:

ReaderFormats.registerDefaults()
ReaderFormats.register(ArchivesModule.self)

How

  • libarchive. Apple platforms link Lakr233/libarchive.xcframework 1.0.1 (exact pin), a static XCFramework of libarchive 3.8.10 with xz, zstd and lz4 built in, for every Apple platform. Its packaging is MIT and the upstreams are BSD-2, 0BSD and BSD-3; the README's new Dependencies section lists them. Linux can't use an XCFramework, so there Package.swift declares a CLibArchive system library (pkg-config libarchive) and the CI job installs libarchive-dev. The Swift code imports whichever is present.
  • LibArchiveContainer holds the archive in memory, lists entries once at open, and reads a resource by opening the archive again and skipping to its entry, since libarchive reads front to back. Solid RAR archives decompress everything before the entry on each read, so pages in order are cheap and jumps are not; that's noted on the type.
  • Strict memory safety. Every call into libarchive is marked unsafe, with the one real invariant (the bytes stay in place for the whole read because Data holds them) explained in a comment.
  • ComicParser becomes package so the add-on can reuse it.
  • Tests (ChekReaderArchivesTests): a CBR built by hand as a stored RAR 4 archive with correct header and data CRCs, since no free tool writes RAR; a CB7 written by libarchive; pages, order, ComicInfo.xml, limits, a corrupted header and a truncated entry.

Built and tested on Linux here against libarchive 3.7.2 (all 177 tests pass). The Apple build resolves the XCFramework package and is the first build of that path; the Apple CI job covers it and I'll fix anything it turns up. The demo app's Xcode project doesn't link the add-on, so it reads CBZ and CBT but not CBR yet.


Generated by Claude Code

ArchivesModule opens RAR and 7-Zip comic archives with libarchive: a
prebuilt static XCFramework from Lakr233/libarchive.xcframework on Apple
platforms, pinned to one release, and the system library on Linux, where
CI installs libarchive-dev. The archive is read whole, its entries are
checked against ReaderLimits, and pages and ComicInfo.xml then go through
the same comic parser as CBZ. Password-protected archives fail with
drmProtected.

Tests build a stored RAR 4 archive by hand, since no free tool writes
RAR, and a 7-Zip archive with libarchive's writer.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfwUCp8GqHWUdTK7EhZCT5
@devaryakjha devaryakjha self-assigned this Oct 21, 2026
libarchive 3.7 lists the entries of the truncated fixture and fails
when the cut page is read; the version in the xcframework reports the
truncation while listing. The test only cares that the damage is
reported as a ReaderError, so it allows either.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfwUCp8GqHWUdTK7EhZCT5
…y' into claude/project-thread-eheuhr-archives

# Conflicts:
#	Package.swift
@devaryakjha
devaryakjha changed the base branch from main to claude/project-thread-eheuhr-a11y October 21, 2026 04:51
devaryakjha added a commit that referenced this pull request Oct 21, 2026
Lands four pull requests in one:

- #28 feat(core): search a publication's text. Publication.search
  finds a query in reflowable formats and PDFs, returning Locators
  that go(to:) opens at the match, with the text around it.
- #29 feat(ui): standard controls, accessibility and a String Catalog.
  ReaderView draws a title bar, table of contents, search and
  appearance sheets and a position slider; every control is labelled
  for VoiceOver, and user-facing strings are localizable.
- #30 feat(archives): read CBR and CB7 through libarchive, in the
  optional ChekReaderArchives product.
- #27 Point the README at the 0.1.0 release instead of main.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfwUCp8GqHWUdTK7EhZCT5

Copy link
Copy Markdown
Contributor Author

Landed on main in 1f74f28 through #27, which carried this branch. Closing.


Generated by Claude Code

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