A Zig library and CLI for reading Mobipocket (.mobi, .prc, .azw) e-books.

Add MOBI reading library

Parses Palm database, PalmDOC, MOBI and EXTH headers, and reads book content out of them. Text: uncompressed, PalmDOC LZ77, and HUFF/CDIC decompression, with the trailing data entries described by extra_record_data_flags stripped from each text record. CP-1252 text is transcoded to UTF-8. Encryption: both Mobipocket schemes, built on the PC1 stream cipher. Legacy files carry their key in record zero; DRM files carry it in a voucher that opens with either the internal reader key or a key derived from a device serial number. Amazon's newer KFX/Topaz protection is a different container and is not handled. Also extracts embedded images and reports the KF8 boundary in dual-format files. The book the tests read is downloaded during `zig build test` and checked against a SHA-256 pinned in build.zig, rather than committed as several hundred kilobytes of binary that never changes with the code. A plain `zig build` never reaches that step, so it stays offline. The download uses ianic/tls.zig wrapped in a small HTTP/1.1 client in tools/fetch.zig: Zig's package manager cannot do the job, since it only accepts archives rather than a bare file, and its HTTP client fails to handshake with gutenberg.org even though the host negotiates TLS 1.3 fine under OpenSSL. The test module is built separately from the published one so the fetched book reaches @embedFile without dragging the download into every dependent's build. Gutenberg regenerates these files periodically, so the book tests assert invariants -- the decompressed length matching text_length, the text containing known phrases -- rather than exact record counts, and should survive a new build of the book. The PC1 and PID vectors in the tests were generated from libmobi's reference C routines so the implementation is pinned against a known good one rather than against itself. Two paths have no real sample to test against: HUFF/CDIC, whose tables the tests build by hand, and legacy key placement, whose version-dependent offsets follow libmobi but are unverified. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BM6SkLZRb2GJwXBKdkziju


Author jcollie.dev
Co-author Claude Opus 5 (1M context) Date Commit