diff --git a/CHANGELOG.md b/CHANGELOG.md index a90cf0a..e354cd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## 0.2.0 - 2026-07-22 + +- Open unfragmented FSSHTTPB package-store `.one` sections through the same + bounded page/content model as desktop revision stores. +- Interpret desktop and FSSHTTPB `.onetoc2` stores into authored section-group, + section, page, and subpage trees, with identity fallback and deterministic + handling of missing, duplicate, cyclic, and unlisted entries. +- Add complete-set CAB extraction for multi-cabinet packages, including split + CFDATA blocks, spanning files, codec continuity, link validation, aggregate + limits, and browser selection of one `.onepkg` plus its `.cab` companions. +- Add native MSZIP and Quantum decoding alongside uncompressed and LZX CAB + support. +- Parse and render structured outlines, rich-text formatting and safe links, + tables, signature/header-validated PNG/JPEG images, decoded ink, layout hints, + and declared embedded attachments. +- Add local structured JSON, text, Markdown, inert HTML, and deterministic + static notebook ZIP exports with diagnostics, unsupported-content summaries, + normalized resource names, and bounded output. +- Add independent parser, image-preview, display, TOC, cabinet-set, and export + resource budgets. Oversized images remain explicitly downloadable but are + not copied or decoded for automatic preview. +- Verify the implementation against the redistributable OneNote golden corpus, + a licensed five-part libmspack fixture, adversarial malformed inputs, and two + private `.onepkg` files without committing their bytes. + +Known unsupported areas remain fragmented FSSHTTPB data-element reconstruction, +equations, audio/video, pixel-perfect page placement, and untested OneNote +producer variants. + ## 0.1.0 - 2026-07-22 - Add a standalone React/Vite reader integrated with Toolbox SDK 0.1.1, @@ -8,21 +37,17 @@ - Add a worker-hosted native TypeScript parser for a desktop OneNote revision-store subset: bounded file-node and object-space traversal, property sets, page metadata, titles, timestamps, levels, and plain text. -- Add bounded FSSHTTPB packaging, storage-index/cell/revision/object-group - parsing and open unfragmented package-store `.one` sections through the same - content model. -- Add in-memory CAB enumeration and extraction for uncompressed, MSZIP, - Quantum, and LZX folders, including checksums, strict paths, explicit - resource limits, and cooperative cancellation between data blocks. +- Add in-memory CAB enumeration and extraction for uncompressed and LZX + folders, including checksums, strict paths, explicit resource limits, and + cooperative cancellation between data blocks. - Open contained `.one` sections independently and expose package entries, section/page navigation, partial failures, and structured diagnostics. - Verify a Joplin `.one` golden with three pages and a Joplin LZX `0x1203` `.onepkg` golden with seven entries, five sections, and seven pages. Also - verify rust-cab uncompressed, MSZIP, and LZX `0x1303` fixtures plus a - generated two-block MSZIP dictionary-chain fixture and pinned Quantum - single-/multi-frame payloads. + verify rust-cab uncompressed and LZX `0x1303` fixtures. - Add deterministic static release packaging, SHA-256 sidecars, pinned-source provenance, fixture licensing, and security/support documentation. -Known unsupported areas include fragmented FSSHTTPB data-element -reconstruction and untested OneNote producer variants. +Known unsupported areas are FSSHTTP-packaged `.one`, MSZIP and Quantum CAB +extraction, multi-cabinet archives, `.onetoc2` hierarchy/order interpretation, +visual content, attachments, layout/format fidelity, links, and exports. diff --git a/LICENSE b/LICENSE index bbe986b..2cf1508 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,8 @@ -SPDX-License-Identifier: MPL-2.0 +SPDX-License-Identifier: MPL-2.0 AND LGPL-2.1-only -OneNote Tools is licensed under the Mozilla Public License, version 2.0. -The complete, unmodified licence text is provided in LICENSES/MPL-2.0.txt. +OneNote Tools is primarily licensed under the Mozilla Public License, version +2.0. The adapted multi-cabinet implementation in +src/onenote/onepkg/cabinet-set.ts is LGPL-2.1-only. Complete, unmodified licence +texts are provided in LICENSES/MPL-2.0.txt and +LICENSES/libmspack-LGPL-2.1.txt. Other adapted and third-party material remains +under the terms recorded in THIRD_PARTY_NOTICES.md. diff --git a/README.md b/README.md index 5eadfe6..eeab0ab 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,61 @@ # OneNote Tools -OneNote Tools is a standalone, local-first browser reader for a tested subset -of Microsoft OneNote `.one` sections and CAB-based `.onepkg` packages. The -parser is native TypeScript, runs in a dedicated module worker, and never -uploads or persists the selected notebook. +OneNote Tools is a standalone, local-first browser reader and exporter for a +tested subset of Microsoft OneNote `.one` sections and CAB-based `.onepkg` +packages. Its native TypeScript parser runs in a dedicated module worker; the +selected notebook is neither uploaded nor persisted. -It is also an independent application in the add·ideas Toolbox contract: the +It is also an independent application in the add·ideas Toolbox contract. The source uses the Toolbox SDK shell and manifest, builds with Vite `base: './'`, -and is delivered to Toolbox Portal as an already-built, checksummed static ZIP. +and is delivered to Toolbox Portal as a checksummed static ZIP. -## What version 0.1.0 can open +## What version 0.2.0 supports -- Desktop revision-store `.one` sections from the tested OneNote family. The - reader exposes section/page names, stable page IDs, created and updated - timestamps when present, page level, and readable plain text. -- Unfragmented FSSHTTPB-packaged `.one` sections matching the tested Joplin - family. Package cells, revision chains, object groups, and resolved object - and page-space references feed the same bounded content reader. -- Single-cabinet `.onepkg` files whose CAB folders are uncompressed, MSZIP, - Quantum, or LZX compressed. Each contained supported `.one` section is - parsed independently, so one unsupported section does not hide sections that - did parse. -- Package entries, safe normalized paths, uncompressed sizes, compression - metadata, section/page navigation, and structured diagnostics. +- Desktop revision-store and unfragmented FSSHTTPB package-store `.one` + sections from the tested producer families. +- Complete single- or multi-cabinet `.onepkg` sets using uncompressed, MSZIP, + Quantum, or LZX CAB folders. Split packages can be selected as one `.onepkg` + file together with all of its `.cab` companions, in any selection order. +- Desktop and FSSHTTPB `.onetoc2` stores inside packages. Section groups, + authored section order, recycle-bin filtering, pages, and subpages are + presented as a notebook tree; unresolved entries retain a deterministic + fallback rather than hiding readable sections. +- Structured page content: outlines and layout hints, rich-text runs, safe + links, tables, PNG/JPEG images, decoded ink strokes, and declared embedded + attachments. Resource bytes remain lazy until previewed, explicitly + downloaded, or included in an explicit export. +- Local exports as structured JSON, plain text, Markdown, inert semantic HTML, + or a deterministic static notebook ZIP. Exports retain parser diagnostics + and unsupported-content summaries; they do not create or modify OneNote + files. -The golden tests parse a real Joplin desktop `.one` file with three pages, an -unfragmented 17,197-byte Joplin FSSHTTPB `.one` file with one page, and a real -Joplin `.onepkg` with seven entries, five sections, and seven pages. LZX -`0x1203` and `0x1303`, uncompressed CAB, one- and two-block MSZIP data, and -single- and multi-frame Quantum data are covered by fixtures. The MSZIP and -Quantum fixtures are CAB-level evidence, not a claim about a particular -OneNote `.onepkg` producer. +The redistributable golden corpus covers desktop and unfragmented FSSHTTPB +sections, a real LZX `.onepkg`, all four CAB compression modes, a five-part +spanning CAB set, TOC hierarchy behavior, rich content, resources, and every +export format. The generic MSZIP, Quantum, and multi-cabinet fixtures establish +CAB behavior; they are not claims about every OneNote producer. -This is a structural reader, not a full-fidelity OneNote renderer. Images, -tables, ink, embedded files, layout, formatting, links, and exports are not -rendered. Fragmented FSSHTTPB data elements and some producer variants remain -unsupported. See -[format support](docs/FORMAT_SUPPORT.md) for the precise matrix. +This remains a deliberately bounded compatibility subset. Fragmented FSSHTTPB +data-element reconstruction, equations, audio/video, and untested producer +variants are not supported. Visual placement is approximate rather than a +pixel-perfect OneNote layout. See [format support](docs/FORMAT_SUPPORT.md) for +the precise matrix. -There is no Rust/Wasm runtime, server, proxy, upload, telemetry, or notebook -storage. All parsing and CAB/LZX/MSZIP/Quantum decompression is ordinary -browser JavaScript produced from the TypeScript source. +There is no Rust/Wasm runtime, notebook-processing application backend, upload +proxy, telemetry, or notebook storage. All parsing and CAB decompression is +ordinary browser JavaScript produced from the TypeScript source. ## Use -Run the static build or open it through Toolbox Portal, then drop or choose one -local `.one` or `.onepkg` file. Use **Clear file** to terminate the current -worker and release application references. Browser garbage collection does not -provide a secure-erasure guarantee. +Run the static build or open it through Toolbox Portal, then: + +- choose one local `.one` file; or +- choose one `.onepkg` file and, for a split package, all linked `.cab` parts + in the same file-picker action. + +Use **Clear file** to terminate the current worker and release application +references. Browser garbage collection does not provide a secure-erasure +guarantee. ## Development @@ -72,7 +80,7 @@ supplied through the SDK's `?toolbox=` context mechanism. The app uses the SDK ```sh npm run release:artifact -(cd release && sha256sum -c onenote-tools-0.1.0.sha256) +(cd release && sha256sum -c onenote-tools-0.2.0.sha256) ``` The ZIP root contains the built static app and manifest plus the changelog, @@ -95,7 +103,7 @@ into the portal React tree. ## Licence -OneNote Tools is licensed under MPL-2.0. The complete licence is in -[`LICENSES/MPL-2.0.txt`](LICENSES/MPL-2.0.txt). Adapted and third-party material -remains under the terms recorded in +OneNote Tools is primarily MPL-2.0; the adapted multi-cabinet module is +LGPL-2.1-only. The complete licence texts are in [`LICENSES/`](LICENSES/), and +adapted/third-party material remains under the terms recorded in [`THIRD_PARTY_NOTICES.md`](THIRD_PARTY_NOTICES.md). diff --git a/SOURCE.md b/SOURCE.md index 3f7e7a4..5080ddf 100644 --- a/SOURCE.md +++ b/SOURCE.md @@ -1,8 +1,8 @@ # Corresponding source -The corresponding source for OneNote Tools 0.1.0 is the `v0.1.0` tag: +The corresponding source for OneNote Tools 0.2.0 is the `v0.2.0` tag: -https://git.add-ideas.de/zemion/onenote-tools/src/tag/v0.1.0 +https://git.add-ideas.de/zemion/onenote-tools/src/tag/v0.2.0 Build the release from that tag with Node.js 22 or newer: diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 413b3d7..655f429 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -28,6 +28,17 @@ modules, pinned at `04a6db2aa7bd487a89c559631d79d1b384139f50`. Its adapted modules carry provenance headers and its licence is in `LICENSES/compcol-MIT.txt`. +Multi-cabinet chain construction, split CFDATA handling, and spanning-file +semantics adapt libmspack's LGPL-2.1-only CAB decompressor, pinned at +`55d501976171397ccd5d5a7a1ca7da065b1d9a06`. The adapted module carries its +copyright/provenance header and the complete licence is in +`LICENSES/libmspack-LGPL-2.1.txt`. + +`one2html` (MIT), pinned at +`59930ad309004030f812790c6749efe4265bb6bd`, was inspected as a behavioral +reference for rich-content rendering. No one2html source, template, stylesheet, +binary, or runtime dependency is shipped in this application. + MSZIP raw DEFLATE decoding uses fflate 0.8.3 (MIT). Its complete installed licence text is included in the generated runtime licence bundle. @@ -49,5 +60,6 @@ The encoded fixture bytes are excluded from `dist` and the release ZIP. The release retains the fixture provenance document and AGPL text so these notices remain complete. -The remaining npm packages are build and test tooling and are not shipped as -runtime modules in the static application. +Vite and the remaining npm packages are build/test tooling rather than runtime +modules. Vite's optional modulepreload runtime polyfill is explicitly disabled +for this baseline-browser build. diff --git a/docs/FORMAT_SUPPORT.md b/docs/FORMAT_SUPPORT.md index 4182658..b7520d6 100644 --- a/docs/FORMAT_SUPPORT.md +++ b/docs/FORMAT_SUPPORT.md @@ -1,20 +1,27 @@ # Format support -## Version 0.1.0 support matrix +## Version 0.2.0 support matrix -| Input or feature | Status | Tested evidence and boundary | -| ---------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------- | -| Desktop revision-store `.one` | Supported subset | Real 34,904-byte Joplin golden; three pages | -| FSSHTTPB-packaged `.one` | Supported subset | Licensed 17,197-byte Joplin golden; one page; unfragmented data elements | -| Unknown/legacy `.one` variants | Unsupported | File type and format GUIDs are validated before traversal | -| `.onepkg`, single CAB, LZX | Supported subset | Real Joplin package: LZX `0x1203`, three CFDATA blocks, seven entries, five sections, seven pages | -| CAB LZX `0x1303` | Supported extraction | Byte-for-byte rust-cab MIT unit fixture, two text entries | -| CAB without compression | Supported extraction | Byte-for-byte rust-cab MIT unit fixture | -| CAB MSZIP | Supported extraction | rust-cab single-block fixture plus a generated two-block dictionary-chain fixture | -| CAB Quantum | Supported extraction | Pinned compcol qtm.txt payload, generated one-folder CAB, and two-frame state/sentinel tests | -| Multi-cabinet CAB / spanning files | Unsupported | Header flags and spanning folder indexes are rejected | -| `.onetoc2` package entries | Listed only | Files are identified, but notebook hierarchy and section order are not interpreted | -| Standalone `.onetoc2` | Unsupported in the app | The picker accepts only `.one` and `.onepkg` | +| Input or feature | Status | Tested evidence and boundary | +| -------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------- | +| Desktop revision-store `.one` | Supported subset | Real 34,904-byte Joplin golden; three pages and rich content | +| FSSHTTPB package-store `.one` | Supported subset | Licensed 17,197-byte Joplin golden; one page; unfragmented data elements | +| Unknown/legacy `.one` variants | Unsupported | File type and format GUIDs are validated before traversal | +| `.onepkg`, one CAB | Supported subset | Real Joplin LZX package; generated/pinned none, MSZIP, Quantum, and LZX codec fixtures | +| `.onepkg`, complete CAB set | Supported extraction | Licensed five-part libmspack set plus split-block, spanning-file, ordering, and malformed-set tests | +| Missing/inconsistent CAB parts | Rejected | Set ID, indexes, previous/next names, compression, split blocks, and spanning records must agree | +| CAB without compression | Supported extraction | Byte-for-byte rust-cab fixture | +| CAB MSZIP | Supported extraction | rust-cab single block plus generated two-block dictionary-chain fixture | +| CAB Quantum | Supported extraction | Pinned compcol payloads and generated CAB integration fixture | +| CAB LZX | Supported extraction | Real OneNote `0x1203` package and rust-cab `0x1303` fixture | +| `.onetoc2` inside a package | Supported subset | Desktop golden/hierarchy tests; FSSHTTPB dispatch uses a mocked shared-store seam, not a real golden | +| Standalone `.onetoc2` in the app | Not selectable | The picker accepts `.one`, or `.onepkg` together with `.cab` companions | +| Rich text and layout hints | Supported subset | Run formatting, paragraph properties, safe links, and bounded layout metadata | +| Tables | Supported subset | Rows, cells, nested blocks, column widths, locks, borders, and cell backgrounds | +| Images | Supported subset | Lazy, signature/header-validated PNG and JPEG resources; unsafe images stay downloadable only | +| Ink | Supported subset | Bounded delta decoding, strokes, colors, width/height, transparency, and SVG display/export | +| Embedded attachments | Supported subset | `ATTACHMENT_DECLARATION`/file-data resources remain inert until explicit download | +| Export | Supported subset | JSON, text, Markdown, inert HTML, and deterministic static notebook ZIP | “Supported subset” is intentionally narrower than “all files with this extension.” A successful open requires the tested desktop or FSSHTTPB OneStore @@ -22,6 +29,8 @@ structures and content graph nodes. Malformed offsets, counts, references, CAB checksums, paths, compressed data, and unsupported variants produce bounded diagnostics or a controlled failure. +## OneStore and package boundaries + FSSHTTPB support covers the OneStore packaging envelope, Storage Index and Storage Manifest, header/data-root cells, bounded revision chains, Object Group partitions, resolved object/page-space references, and available Object Data @@ -31,49 +40,68 @@ the store adapter rejects packages containing fragment records with a controlled `UNSUPPORTED_FORMAT` error. Excluded object data cannot be reconstructed from a standalone file and is likewise unsupported. +For a split package, the browser must receive the `.onepkg` and every linked +`.cab` companion in one selection. The extractor validates a complete, +uniquely indexed cabinet chain before decoding. It reassembles split CFDATA +blocks, preserves codec state across cabinets, and reconciles the CAB +`continued from previous`, `continued to next`, and `continued both` file +records. Partial sets are not opened heuristically. + The default LZX limit accepts CAB window sizes through 8 MiB, but compatibility claims are fixture-backed only for window bits 18 (`0x1203`) and 19 (`0x1303`). MSZIP validates the `CK` prefix, limits each compressed block to 32 KiB + 12, decodes into a fixed-size output buffer, requires the declared output length, -and carries at most 32 KiB of history between blocks in one folder. The MSZIP -tests establish CAB extraction behavior; no redistributable MSZIP-compressed -OneNote export is currently present, so they do not establish producer-specific -`.onepkg` compatibility. +and carries at most 32 KiB of history between blocks in one logical folder. Quantum validates level/window metadata, bounds its window to 2 MiB by default, requires full 32 KiB intermediate frames, preserves its arithmetic models and -LZ window across frames, and injects exactly one `0xFF` CAB block sentinel. -Trailer padding is limited to the documented 0..4 zero bytes; match, frame, -output, operation, and cancellation bounds are enforced. Its tests likewise -establish CAB extraction behavior only: no redistributable Quantum-compressed -OneNote export is currently present. +LZ window across frames/cabinets, and injects exactly one `0xFF` CAB block +sentinel. Trailer, match, frame, output, operation, and cancellation bounds are +enforced. Trailing CAB data is ignored with a warning. Reserved CAB areas are bounded and skipped. CAB names are decoded as strict UTF-8; unmarked valid UTF-8 receives a warning, while invalid non-ASCII legacy-code-page names are rejected rather than guessed. -## Extracted OneNote data +## Notebook and page model -The supported section paths currently return: +Supported `.onetoc2` stores provide authored section order, nested section +groups, display names, identities, and colors. Exact normalized paths take +precedence; same-directory file identity is a guarded fallback. Recycle-bin +entries are omitted, duplicate/cyclic references are diagnosed, and readable +sections not reachable from a TOC are appended deterministically. Page levels +are interpreted as a page/subpage tree. -- section display name; -- page ID, title, created/updated timestamp when available, and page level; -- visible Unicode/extended-ASCII rich text as plain text and a text preview; -- diagnostics tied to an offset, structure, or page where available. +The supported section path returns: -It does not preserve visual position, rich-text formatting, list formatting, -tables, images, ink, equations, embedded files, audio/video, active links, -page versions/conflicts, or exports. Unsupported content objects remain visible -as diagnostics instead of being silently presented as parsed. +- section/page identities, names, timestamps, page levels, and diagnostics; +- outlines and recursively nested content blocks; +- rich-text runs with bold, italic, underline, strikeout, super/subscript, + font, size, foreground/highlight color, paragraph alignment/spacing, and + allow-listed `http`, `https`, and `mailto` links; +- tables, lazy PNG/JPEG images, embedded-file declarations, and decoded ink; +- bounded layout hints such as offsets, maximum dimensions, and alignment. -Within a supported `.onepkg`, each `.one` entry is parsed independently. -Malformed or unsupported sections are marked failed/unsupported while other -sections remain available. Package navigation is temporary normalized-path -order until `.onetoc2` interpretation is implemented. +This is not a pixel-perfect OneNote renderer. Equations, audio/video, page +versions/conflicts, and producer-specific structures outside the golden corpus +are not represented. Encountered unsupported object kinds remain visible as +diagnostics. Active notebook HTML/SVG is never injected. + +## Export + +All exports are created inside the existing local parser worker. They include a +versioned parser/support manifest, the readable page hierarchy, diagnostics, +and unsupported-content summaries. The static ZIP contains inert semantic HTML +plus JSON, text, Markdown, warnings, and bounded resources. Resource names are +normalized, potentially active attachment suffixes are neutralized, and only +validated image types may be embedded for automatic display. + +Export is a representation of the parser-supported subset, not a round trip: +it neither emits `.one`/`.onepkg` nor promises full OneNote visual fidelity. ## Test fixtures -The exact hashes, source revisions, licences, expected page names, and CAB +The exact hashes, source revisions, licences, expected content, and CAB structures are recorded in [`tests/fixtures/README.md`](../tests/fixtures/README.md). Tests use no private notebooks and do not treat a synthetic archive as proof of Microsoft OneNote diff --git a/docs/PORTING.md b/docs/PORTING.md index 52f4ec5..3cd29b8 100644 --- a/docs/PORTING.md +++ b/docs/PORTING.md @@ -3,32 +3,42 @@ The desktop `.one` reader adapts selected structures from the pinned `onenote.rs` implementation. It is not a line-for-line or complete port. -| TypeScript module | Upstream path(s) | Revision | Port scope and deviations | -| ---------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `src/onenote/onestore/file-node.ts` | `onestore/desktop/file_structure/file_node_list_fragment.rs`, `file_node/*`, chunk references | `onenote.rs@5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected; immutable byte input, strict range checks, fragment/child cycle detection, and depth/count limits | -| `src/onenote/onestore/property-set.ts` | `onestore/shared/{object_prop_set,prop_set,property,object_stream_header}.rs` | same | Substantial; bounded vectors/counts/nesting and serializable discriminated unions | -| `src/onenote/onestore/desktop-store.ts` | `onestore/desktop/{file_node,file_structure,objects}/*` | same | Selected desktop section path; explicit missing-reference errors; file-data/attachment payloads skipped with diagnostics | -| `src/onenote/fsshttpb/*` | `fsshttpb/{data,data_element,packaging}.rs` | same | Native bounded package/header/data-element records, checked compact integers, zero-copy BLOB ranges; fragment records parsed but not assembled | -| `src/onenote/onestore/fsshttp-store.ts` | `onestore/fsshttpb/{header,mapping_table,object,object_space,revision,revision_role}.rs` | same | Unfragmented package-store adapter; bounded/cycle-checked revision chains, newest-revision precedence, resolved positional reference arrays | -| `src/onenote/one/{constants,section}.ts` | `one/property*`, `one/property_set/*`, `onenote/{section,page,page_series,outline,rich_text}.rs` | same | Page metadata, titles, and plain text only; bounded graph traversal; visual/embedded content diagnosed | +| TypeScript module | Upstream path(s) | Revision | Port scope and deviations | +| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| `src/onenote/onestore/file-node.ts` | `onestore/desktop/file_structure/file_node_list_fragment.rs`, `file_node/*`, chunk references | `onenote.rs@5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected; immutable byte input, strict range checks, fragment/child cycle detection, and depth/count limits | +| `src/onenote/onestore/property-set.ts` | `onestore/shared/{object_prop_set,prop_set,property,object_stream_header}.rs` | same | Substantial; bounded vectors/counts/nesting and serializable discriminated unions | +| `src/onenote/onestore/desktop-store.ts` | `onestore/desktop/{file_node,file_structure,objects}/*` | same | Selected desktop section/TOC paths; explicit missing-reference errors; bounded file-data references | +| `src/onenote/onestore/file-data.ts` | `onestore/desktop/{file_node/shared,objects/file_data_store}.rs` | same | Bounded zero-copy file-data payload ranges, checked declarations, and explicit external/invalid availability | +| `src/onenote/onestore/types.ts` | `onestore/desktop/common/*`, `onestore/shared/*`, and desktop object modules | same | Serializable structural records used across desktop and FSSHTTPB adapters | +| `src/onenote/fsshttpb/*` | `fsshttpb/{data,data_element,packaging}.rs` | same | Native bounded package/header/data-element records, checked compact integers, zero-copy BLOB ranges; fragment records parsed but not assembled | +| `src/onenote/onestore/fsshttp-store.ts` | `onestore/fsshttpb/{header,mapping_table,object,object_space,revision,revision_role}.rs` | same | Unfragmented package-store adapter; bounded/cycle-checked revision chains, newest-revision precedence, resolved positional reference arrays | +| `src/onenote/one/{constants,section,content}.ts` | `one/property*`, `one/property_set/*`, `onenote/{section,page,page_series,outline,rich_text,table,image,embedded_file,ink}.rs` | same | Page metadata plus bounded recursive rich text, tables, resources, layout hints, and decoded ink in an inert browser DTO | +| `src/onenote/one/property-access.ts` | `one/property/{simple,object_reference}.rs` | same | Typed property access and resolved/compact reference validation without coercion | +| `src/onenote/one/section-content.ts` | `onenote/{section,page_series,page}.rs` | same | Worker-retained page/content/resource model with bounded diagnostics and timestamps | +| `src/onenote/parser/parse-toc.ts` | `one/property_set/toc_container.rs` and desktop/FSSHTTP OneStore readers | same | Desktop/FSSHTTP TOC content, names, identities, ordering, colors, nesting, and bounded diagnostics | -The browser-native package path has separate MIT provenance: +The browser-native package path has separate upstream provenance: | TypeScript module | Upstream path(s) | Revision and selected licence | Port scope and deviations | | ------------------------------------------------------------------------ | ------------------------------------------------------ | --------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `src/onenote/onepkg/{cabinet,checksum}.ts` | rust-cab `src/{cabinet,folder,file,ctype,checksum}.rs` | `c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2`, MIT | CAB reading/checksum adapted for immutable browser bytes, strict normalized paths, checked ranges/checksums, whole-folder extraction, explicit limits, and cancellation/yield hooks; writers are not ported | +| `src/onenote/onepkg/cabinet-set.ts` | libmspack `mspack/cabd.c` | `55d501976171397ccd5d5a7a1ca7da065b1d9a06`, LGPL-2.1-only | Complete named-set validation, split CFDATA reassembly, codec continuity, spanning-file reconciliation, aggregate limits, and immutable browser inputs | | `src/onenote/onepkg/mszip/decoder.ts` | rust-cab `src/mszip.rs`; fflate raw DEFLATE | rust-cab revision above; fflate 0.8.3, MIT | `CK` framing and persistent 32 KiB folder history follow rust-cab; raw DEFLATE uses fflate with a caller-owned bounded buffer and strict declared-size checks | | `src/onenote/onepkg/quantum/{bit-reader,budget,decoder,model,tables}.ts` | compcol `src/quantum/{bits,decoder,model,tables}.rs` | `04a6db2aa7bd487a89c559631d79d1b384139f50`, MIT | Native TypeScript arithmetic/model/LZ decoder; fixed CAB output, 2 MiB maximum window, strict match/frame/trailer checks, two-block lookahead, operation budget, and cancellation checkpoints | | `src/onenote/onepkg/lzx/{bit-reader,huffman,decoder}.ts` | lzxd 0.2.5 `src/{bitstream,tree,block,window,lib}.rs` | `4748e43594e3e30cff2ace3a6ad7a376c9816fdd`, MIT option of MIT OR Apache-2.0 | Directly translated core with typed arrays, CAB CFDATA boundaries, persistent folder state, strict malformed-stream errors, and operation/window/cancellation limits; delta reference data is omitted | The bounded binary readers, format detection, parser limits/error model, path -policy, worker protocol/DTOs, package-to-section boundary, and application UI -are original TypeScript implementations guided by the normative specifications -and project requirements. +policy, package TOC-to-section hierarchy, worker protocol/DTOs, safe image +inspection, export serializers/ZIP writer, and React application UI are original +TypeScript implementations guided by the normative specifications and project +requirements. The pinned `one2html` renderer informed expected visual semantics +for rich text, tables, images, attachments, and ink; its Rust/templates/CSS were +not copied or shipped. Files adapted from `onenote.rs` carry an MPL-2.0 notice, SPDX identifier, upstream path/revision, and deviations. Files adapted from rust-cab, compcol, -or lzxd carry their MIT provenance, copyright notice, exact revision, and deviations. +or lzxd carry their MIT provenance, copyright notice, exact revision, and +deviations. The multi-cabinet module carries libmspack's LGPL-2.1-only notice. Licence texts are reproduced in `LICENSES/` and included in the release ZIP. Focused tests cover successful pinned fixtures plus malformed bounds, diff --git a/docs/REFERENCE_IMPLEMENTATIONS.md b/docs/REFERENCE_IMPLEMENTATIONS.md index d649428..f9f3804 100644 --- a/docs/REFERENCE_IMPLEMENTATIONS.md +++ b/docs/REFERENCE_IMPLEMENTATIONS.md @@ -1,18 +1,20 @@ # Specifications and pinned references -Version 0.1.0 records these immutable implementation revisions: +Version 0.2.0 records these immutable implementation revisions: -| Repository | Exact revision | Use | -| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------- | -| [`toolbox-sdk`](https://git.add-ideas.de/zemion/toolbox-sdk/src/commit/5e206baf42dfae5a00f2743fb2cc501bb12d9b7a) | `5e206baf42dfae5a00f2743fb2cc501bb12d9b7a` | App contract, React shell, manifest schema/testkit, and nested-path behavior | -| [`toolbox-portal`](https://git.add-ideas.de/zemion/toolbox-portal/src/commit/5d2e466ad61e36a0e2be2a2d8459b1a127f53f11) | `5d2e466ad61e36a0e2be2a2d8459b1a127f53f11` | Reviewed ZIP shape, exact checksum lock, and independent-app assembly model | -| [`onenote.rs`](https://github.com/msiemens/onenote.rs/tree/5138a39a3f4e72b840932f9872fecde52fa9da60) | `5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected desktop/FSSHTTPB OneStore and MS-ONE structures adapted into TypeScript | -| [`rust-cab`](https://github.com/mdsteele/rust-cab/tree/c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2) | `c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2` | CAB structures, checksum, enumeration/extraction, MSZIP history, and unit fixtures | -| [`compcol`](https://github.com/KarpelesLab/compcol/tree/04a6db2aa7bd487a89c559631d79d1b384139f50) | `04a6db2aa7bd487a89c559631d79d1b384139f50` | Quantum bit reader, arithmetic models, LZ window, CAB sentinel behavior, and tests | -| [`lzxd` 0.2.5](https://github.com/Lonami/lzxd/tree/4748e43594e3e30cff2ace3a6ad7a376c9816fdd) | `4748e43594e3e30cff2ace3a6ad7a376c9816fdd` | LZX bitstream, Huffman, block/window, match, and E8 logic adapted into TypeScript | +| Repository | Exact revision | Use | +| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------- | +| [`toolbox-sdk`](https://git.add-ideas.de/zemion/toolbox-sdk/src/commit/5e206baf42dfae5a00f2743fb2cc501bb12d9b7a) | `5e206baf42dfae5a00f2743fb2cc501bb12d9b7a` | App contract, React shell, manifest schema/testkit, and nested-path behavior | +| [`toolbox-portal`](https://git.add-ideas.de/zemion/toolbox-portal/src/commit/d46f1b61fb85a18299b6b8af2148dcd991ef6b05) | `d46f1b61fb85a18299b6b8af2148dcd991ef6b05` | Reviewed ZIP shape, exact checksum lock, independent-app assembly, and nginx deployment model | +| [`onenote.rs`](https://github.com/msiemens/onenote.rs/tree/5138a39a3f4e72b840932f9872fecde52fa9da60) | `5138a39a3f4e72b840932f9872fecde52fa9da60` | Selected desktop/FSSHTTPB OneStore and MS-ONE structures adapted into TypeScript | +| [`rust-cab`](https://github.com/mdsteele/rust-cab/tree/c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2) | `c5839f5fdfa4c4e7cc9b22f570c79c96af0560e2` | CAB structures, checksum, enumeration/extraction, MSZIP history, and unit fixtures | +| [`compcol`](https://github.com/KarpelesLab/compcol/tree/04a6db2aa7bd487a89c559631d79d1b384139f50) | `04a6db2aa7bd487a89c559631d79d1b384139f50` | Quantum bit reader, arithmetic models, LZ window, CAB sentinel behavior, and tests | +| [`lzxd` 0.2.5](https://github.com/Lonami/lzxd/tree/4748e43594e3e30cff2ace3a6ad7a376c9816fdd) | `4748e43594e3e30cff2ace3a6ad7a376c9816fdd` | LZX bitstream, Huffman, block/window, match, and E8 logic adapted into TypeScript | +| [`libmspack`](https://github.com/kyz/libmspack/tree/55d501976171397ccd5d5a7a1ca7da065b1d9a06) | `55d501976171397ccd5d5a7a1ca7da065b1d9a06` | Multi-cabinet chain, split CFDATA, spanning-file semantics, and licensed fixtures | +| [`one2html`](https://github.com/msiemens/one2html/tree/59930ad309004030f812790c6749efe4265bb6bd) | `59930ad309004030f812790c6749efe4265bb6bd` | Behavioral reference for rich text, tables, images, attachments, ink, and HTML rendering | -The SDK and Portal revisions were inspected from the local repositories. The -four parser references were cloned and reviewed at the hashes above; a branch +The SDK and Portal revisions were inspected from the local repositories. Every +parser/renderer reference was cloned and reviewed at the hash above; a branch name or package version alone is not used as provenance. Source-level mappings and behavioural deviations are in [PORTING.md](PORTING.md). @@ -50,5 +52,6 @@ The Microsoft documents are linked rather than copied. Their published pages can change independently; the source references and golden bytes remain pinned for reproducibility. -`one2html` is deliberately not pinned or inspected because visual HTML -rendering is outside this release. +The `one2html` renderer is a behavioral reference only: no Rust, Askama +template, stylesheet, or generated HTML is shipped or executed by this +application. diff --git a/docs/SECURITY.md b/docs/SECURITY.md index 407dcc4..9e9abb1 100644 --- a/docs/SECURITY.md +++ b/docs/SECURITY.md @@ -2,119 +2,172 @@ ## Trust boundary and local processing -Selected `.one` and `.onepkg` files are untrusted. The main thread checks the -source size, reads one file into an `ArrayBuffer`, transfers it to a dedicated -module worker, and receives serializable data-transfer objects. CAB entries are -extracted only into memory; archive paths are never written to the filesystem. +Selected `.one`, `.onepkg`, and companion `.cab` files are untrusted. The main +thread validates the selection and combined size, reads the files into +`ArrayBuffer`s, and transfers them to a dedicated module worker. CAB entries +are extracted only into memory; archive paths are never written to the +filesystem. The worker is a fault-containment and responsiveness boundary, not a security -sandbox. A successful open keeps its worker session alive for page requests. -Clearing the file, choosing another file, or unmounting the app terminates that -worker; a failed open also terminates it. JavaScript garbage collection does -not promise immediate release or secure erasure. +sandbox. A successful open keeps its session alive for page/resource/export +requests. Clearing the file, choosing another file, or unmounting the app +terminates that worker; a failed open also terminates it. JavaScript garbage +collection does not promise immediate release or secure erasure. The application does not: - upload or transmit notebook bytes; -- use a backend, proxy, telemetry, analytics, remote fonts, or external content - fetching; +- use a notebook-processing application backend, upload proxy, telemetry, + analytics, remote fonts, or notebook-referenced external content fetching; + the optional same-origin Toolbox catalogue/manifest is application chrome + and receives no notebook data; - persist source or derived content in LocalStorage, IndexedDB, Cache Storage, cookies, or a service worker; - execute notebook content or inject notebook HTML/SVG; - use WebAssembly, a Rust runtime, or a native helper. -## Active default limits +## Active parser defaults -The main thread rejects a source larger than 512 MiB before reading it. The -OneStore section parsers then apply these independent defaults: +The main thread accepts one `.one`, or one `.onepkg` plus its `.cab` +companions. It permits at most 256 selected parts, 512 MiB per file, and 512 MiB +combined before reading. -| Resource | Default limit | -| ------------------------------------- | -------------------: | -| Section bytes | 512 MiB | -| File-node list fragments / nesting | 16,384 / 64 | -| File nodes | 1,000,000 | -| Objects | 500,000 | -| Properties per set / property nesting | 16,384 / 64 | -| Stream IDs | 1,000,000 | -| FSSHTTPB revision-chain entries | 16,384 | -| One property vector | 64 MiB | -| Object references | 1,000,000 | -| Content-graph depth | 256 | -| Pages per section | 100,000 | -| Diagnostics per section | 10,000 | -| Extracted text per section | 2,000,000 characters | +The OneStore parser applies these independent defaults per section/store: -The CAB/package path applies these defaults: +| Resource | Default limit | +| ------------------------------------------------ | -------------------------: | +| Section bytes | 512 MiB | +| Transaction fragments / entries | 16,384 / 1,000,000 | +| File-node list fragments / nesting | 16,384 / 64 | +| File nodes | 1,000,000 | +| Objects | 500,000 | +| Properties per set / property nesting | 16,384 / 64 | +| Stream IDs | 1,000,000 | +| FSSHTTPB revision-chain entries | 16,384 | +| One property vector | 64 MiB | +| Desktop object-reference vector | 1,000,000 per vector | +| FSSHTTPB ExGUID/CellID references | 1,000,000 aggregate | +| Nested PropertySets per ObjectPropSet | 1,000,000 aggregate | +| File-data objects / one payload / total payloads | 10,000 / 256 MiB / 512 MiB | +| Content-graph depth | 256 | +| Content blocks / text runs / table cells | 100,000 each | +| Decoded ink points | 100,000 | +| Pages | 10,000 | +| Diagnostics | 10,000 | +| Retained rich/extracted text | 2,000,000 UTF-16 units | -| Resource | Default limit | -| ------------------------------- | -------------: | -| Cabinet input | 512 MiB | -| Folders / files | 1,024 / 10,000 | -| CFDATA blocks | 131,072 | -| CAB name bytes | 255 | -| Path characters / path segments | 4,096 / 64 | -| One extracted file | 256 MiB | -| One folder output | 512 MiB | -| Total folder output | 512 MiB | -| Total extracted entry bytes | 512 MiB | -| Folder compression ratio | 200:1 | -| One MSZIP compressed block | 32 KiB + 12 B | -| Quantum window | 2 MiB | -| LZX window | 8 MiB | -| LZX/Quantum decode operations | 1,000,000,000 | +Images are automatically previewable only when a bounded PNG IHDR or JPEG +marker/SOF inspection succeeds. The compressed payload must be at most 32 MiB, +each dimension at most 16,384 pixels, and the image at most 67,108,864 pixels. +JPEG inspection reads at most 1 MiB of markers and 4,096 marker records. Images +outside those limits stay inert and are available only through an explicit +download action. + +The CAB/package path applies these defaults across a complete cabinet set: + +| Resource | Default limit | +| ------------------------------------------- | -----------------: | +| One cabinet / complete set input | 512 MiB / 512 MiB | +| Cabinet parts | 256 | +| Folder segments / files | 1,024 / 10,000 | +| CFDATA fragments | 131,072 | +| CAB name bytes | 255 | +| Path characters / path segments | 4,096 / 64 | +| TOC construction operations / diagnostics | 1,000,000 / 10,000 | +| One extracted file | 256 MiB | +| One logical folder output | 512 MiB | +| Total folder output / extracted entry bytes | 512 MiB / 512 MiB | +| Logical-folder compression ratio | 200:1 | +| One MSZIP compressed block | 32 KiB + 12 B | +| Quantum window | 2 MiB | +| LZX window | 8 MiB | +| LZX/Quantum decode operations | 1,000,000,000 | A CFDATA block may declare at most 32 KiB of output. Counts and offsets use checked arithmetic and bounded readers. The CAB parser verifies supplied block -checksums, rejects overlapping/out-of-range data, rejects absolute/traversal, -empty, control-character, and case-insensitive duplicate paths, and refuses -multi-cabinet/spanning entries. +checksums; rejects overlapping/out-of-range data, traversal/absolute/control or +case-insensitive duplicate paths; and validates a complete cabinet set before +decoding. Set IDs, indexes, links, compression, split blocks, and spanning-file +records must agree. Reserve areas are private to each cabinet/folder and are +validated locally rather than compared across parts. -MSZIP checks its `CK` framing and raw DEFLATE data, writes into a fixed caller -buffer with one overflow-detection byte, requires the exact declared output -size, and retains no more than 32 KiB of history. LZX checks its window, Huffman -trees, block sizes, match ranges, output size, and operation budget. CAB -Quantum limits its window, model scans, arithmetic renormalisation, matches, -frame/output boundaries, operation count, and trailer padding. It queues at -most the current and next compressed block so a synthetic `0xFF` sentinel can -be consumed without buffering a complete folder. CAB extraction checks -cancellation during Quantum work and yields between data blocks so the worker -can process termination. Desktop OneStore traversal checks fragment/reference -cycles, nesting, object/property/reference counts, and byte ranges. FSSHTTPB -parsing bounds every declared stream body and compact integer, rejects invalid -end markers and non-zero package tails, checks mapping/reference counts and -revision cycles, and retains BLOB payloads as bounded source ranges. Fragment -records are range-checked, but packages containing them are rejected because +MSZIP checks `CK` framing and raw DEFLATE data, writes into a fixed caller +buffer with overflow detection, requires the declared output size, and keeps at +most 32 KiB of logical-folder history. LZX and Quantum validate their windows, +trees/models, blocks/frames, matches, output, trailer, and operation budgets. +Codec state is preserved across continued cabinet segments. Extraction checks +cancellation between data blocks and periodically yields to the worker loop. + +Desktop OneStore traversal checks fragment/reference cycles, nesting, +object/property/reference counts, and byte ranges. FSSHTTPB parsing bounds every +declared stream body and compact integer, rejects invalid end markers and +non-zero package tails, checks aggregate reference/mapping counts and revision +cycles, and retains BLOB payloads as bounded source ranges. Fragment records +are range-checked, but packages containing them are rejected because fragmented-element reconstruction is not implemented. -## Rendering and links +## Display and export budgets -DTO strings are rendered as React text nodes. Notebook HTML, active SVG, -scripts, attachment payloads, and automatic external navigation are not -rendered. Link activation is not implemented. If links are added, they require -explicit user action, scheme validation, and safe navigation attributes. +Parser DTOs are projected through a smaller page-display budget before React +creates nodes: 5,000 blocks, depth 64, 10,000 text runs, 500,000 displayed text +units, 2,000 table rows, 5,000 table cells, 256 columns, 10,000 ink strokes, +50,000 ink points, and 4,096 characters per metadata label. Exceeding a display +budget produces an explicit truncation notice. Newlines remain inside text +nodes instead of multiplying DOM elements. -## Known gaps and roadmap +Navigation and inspectors separately expose at most 250 page links, 500 +notebook nodes at depth 16, 200 package entries per page, and 100 diagnostics +per page. Titles, previews, package paths, diagnostic fields, and panel labels +are length-bounded; pagination/truncation remains explicit in the UI. -- There is no wall-clock deadline. Synchronous OneStore `.one` parsing cannot - observe cooperative cancellation until control returns; terminating the - worker is the current hard stop. -- The package flow holds the source, decompressed folder buffers, extracted - entry slices, and parsed DTOs in memory at overlapping times. The byte/count - limits bound these individually but do not guarantee a low peak heap. -- Section text/page/diagnostic limits apply per contained section rather than - once to the complete package. +Export planning independently permits at most 10,000 sections, 100,000 pages, +1,000,000 blocks, depth 256, 100,000 diagnostics, 8,000,000 text units, and +500,000 ink points. One resource and all resources are capped at 64 MiB; one +standalone output or all uncompressed static-ZIP members are capped at 128 MiB. +Planning accounts for metadata and projected UTF-8 output before serialization, +then verifies actual encoded/member sizes. Resource views remain zero-copy until +the bounded serializer needs bytes. + +## Rendering, links, and downloads + +DTO strings are rendered as React text nodes. Notebook HTML, scripts, active +SVG, and attachment payloads are never injected. Only parsed ink coordinates +generate application-owned SVG path attributes. Hyperlinks require an explicit +click, are limited to `http`, `https`, or `mailto`, and use +`rel="noopener noreferrer"`. + +Automatic image requests carry a distinct preview intent. The worker rejects a +non-image, unapproved media type, unsafe dimensions, or oversized payload before +allocating/copying its bytes to the main thread. Approved image bytes may cross +for automatic preview; attachment bytes and rejected image bytes cross only +after the user presses a download button. + +Static export HTML is inert, contains no script or external fetch, escapes all +text/attributes, embeds only images that pass the same inspector, and +neutralizes potentially active attachment suffixes. Exports represent the +supported reader model; they do not write OneNote files. + +## Known gaps + +- There is no wall-clock deadline. Synchronous OneStore graph parsing cannot + observe cancellation until control returns; terminating the worker is the + current hard stop. +- Package opening can hold source cabinets, decompressed logical folders, + extracted entry views, and parsed DTOs at overlapping times. Byte/count limits + bound them, but do not guarantee a low peak heap. +- Section content limits apply per contained section rather than once to the + complete `.onepkg`; cabinet/TOC limits are aggregate for the package set. - CAB checksums detect accidental corruption but do not authenticate a package. -- Format coverage is narrow and has only the documented golden files. New - producer/version claims require licensed regression fixtures and malformed +- Format coverage is limited to the documented golden files and structures. + New producer/version claims require licensed regression fixtures and malformed variants. - The worker boundary reduces UI impact but is not a substitute for browser and operating-system isolation. Open especially sensitive files in a dedicated browser profile if that risk matters. -Planned hardening includes an elapsed-time budget, cancellation checkpoints in -desktop OneStore graph traversal, aggregate package DTO/text budgets, lower -peak-memory extraction, expanded malformed-input/fuzz corpora, and additional -licensed OneNote export fixtures. +Planned hardening includes elapsed-time budgets, more cancellation checkpoints, +lower-peak-memory extraction, expanded malformed-input/fuzz corpora, fragmented +FSSHTTP reconstruction, and additional licensed OneNote producer fixtures. ## Fixtures and vulnerability reporting diff --git a/package-lock.json b/package-lock.json index 229286e..621ed5c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { "name": "onenote-tools", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "onenote-tools", - "version": "0.1.0", - "license": "MPL-2.0", + "version": "0.2.0", + "license": "MPL-2.0 AND LGPL-2.1-only", "dependencies": { "@add-ideas/toolbox-contract": "0.1.1", "@add-ideas/toolbox-shell-react": "0.1.1", diff --git a/package.json b/package.json index 66cc28a..e7c86bd 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "onenote-tools", - "version": "0.1.0", - "description": "A local-first browser workspace for native OneNote parsing.", - "license": "MPL-2.0", + "version": "0.2.0", + "description": "A local-first browser reader and exporter for OneNote files.", + "license": "MPL-2.0 AND LGPL-2.1-only", "private": true, "type": "module", "engines": { diff --git a/public/toolbox-app.json b/public/toolbox-app.json index b839de2..1271899 100644 --- a/public/toolbox-app.json +++ b/public/toolbox-app.json @@ -3,11 +3,22 @@ "schemaVersion": 1, "id": "de.add-ideas.onenote-tools", "name": "OneNote Tools", - "description": "Local-first reader for tested desktop revision-store .one sections and LZX .onepkg packages; other OneNote formats are not implemented.", + "description": "Local-first reader and exporter for tested .one and .onepkg variants, with notebook trees, rich content, and split CAB package support.", "entry": "./", "icon": "./favicon.svg", "categories": ["documents", "onenote"], - "tags": ["local", "read-only", "one", "onepkg", "cab", "lzx"], + "tags": [ + "local", + "read-only", + "one", + "onepkg", + "cab", + "lzx", + "mszip", + "quantum", + "fsshttp", + "export" + ], "integration": { "contextVersion": 1, "launchModes": ["navigate", "new-tab"], @@ -27,7 +38,7 @@ }, "source": { "repository": "https://git.add-ideas.de/zemion/onenote-tools", - "license": "MPL-2.0" + "license": "MPL-2.0 AND LGPL-2.1-only" }, - "version": "0.1.0" + "version": "0.2.0" } diff --git a/src/components/HelpDialog.tsx b/src/components/HelpDialog.tsx index 6ba5c65..016394b 100644 --- a/src/components/HelpDialog.tsx +++ b/src/components/HelpDialog.tsx @@ -13,20 +13,27 @@ export function HelpDialog({ onClose }: HelpDialogProps) { >

About OneNote Tools

- Read the tested desktop revision-store .one subset and single-cabinet - LZX or uncompressed .onepkg packages with a native TypeScript parser. - Unsupported content remains visible as diagnostics instead of being - silently discarded. + Open tested desktop and unfragmented FSSHTTPB OneNote sections or + complete single- and multi-cabinet .onepkg sets with a native + TypeScript parser. For a split package, select its .onepkg and all + linked .cab files together.

- FSSHTTP sections, MSZIP and Quantum packages, multi-cabinet archives, - notebook TOC ordering, visual fidelity, attachments, and export are - not supported in this release. + Notebook trees, rich text, safe links, tables, PNG/JPEG images, ink, + attachments, and local JSON, text, Markdown, HTML, or static ZIP + exports are supported within documented safety and format limits. + Encountered unsupported object kinds remain visible as diagnostics.

- Nothing is uploaded, persisted, or sent to telemetry. Closing or - clearing releases application references and terminates the worker; - this is not a secure-erasure guarantee. + Fragmented FSSHTTPB data, equations, audio/video, exact OneNote page + placement, and untested producer variants remain unsupported. Exports + preserve readable content but do not create OneNote files. +

+

+ Nothing is uploaded or sent to telemetry, and the app stores no + notebook data unless you explicitly download a resource or create an + export. Closing or clearing releases application references and + terminates the worker; this is not a secure-erasure guarantee.