release: prepare OneNote Tools 0.2.0
This commit is contained in:
47
CHANGELOG.md
47
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.
|
||||
|
||||
10
LICENSE
10
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.
|
||||
|
||||
92
README.md
92
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).
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 |
|
||||
| -------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------- |
|
||||
| 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`, 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` |
|
||||
| `.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
|
||||
|
||||
@@ -4,31 +4,41 @@ 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/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}.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 |
|
||||
| `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,
|
||||
|
||||
@@ -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 |
|
||||
| [`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.
|
||||
|
||||
183
docs/SECURITY.md
183
docs/SECURITY.md
@@ -2,35 +2,42 @@
|
||||
|
||||
## 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.
|
||||
|
||||
The OneStore parser applies these independent defaults per section/store:
|
||||
|
||||
| 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 |
|
||||
@@ -38,26 +45,39 @@ OneStore section parsers then apply these independent defaults:
|
||||
| Stream IDs | 1,000,000 |
|
||||
| FSSHTTPB revision-chain entries | 16,384 |
|
||||
| One property vector | 64 MiB |
|
||||
| Object references | 1,000,000 |
|
||||
| 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 |
|
||||
| Pages per section | 100,000 |
|
||||
| Diagnostics per section | 10,000 |
|
||||
| Extracted text per section | 2,000,000 characters |
|
||||
| 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 |
|
||||
|
||||
The CAB/package path applies these defaults:
|
||||
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 |
|
||||
| ------------------------------- | -------------: |
|
||||
| Cabinet input | 512 MiB |
|
||||
| Folders / files | 1,024 / 10,000 |
|
||||
| CFDATA blocks | 131,072 |
|
||||
| ------------------------------------------- | -----------------: |
|
||||
| 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 folder output | 512 MiB |
|
||||
| Total folder output | 512 MiB |
|
||||
| Total extracted entry bytes | 512 MiB |
|
||||
| Folder compression ratio | 200:1 |
|
||||
| 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 |
|
||||
@@ -65,56 +85,89 @@ The CAB/package path applies these defaults:
|
||||
|
||||
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
|
||||
|
||||
|
||||
6
package-lock.json
generated
6
package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -13,20 +13,27 @@ export function HelpDialog({ onClose }: HelpDialogProps) {
|
||||
>
|
||||
<h2 id="help-title">About OneNote Tools</h2>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
<button type="button" onClick={onClose}>
|
||||
Close
|
||||
|
||||
@@ -529,6 +529,15 @@ p {
|
||||
background: #f5eff8;
|
||||
}
|
||||
|
||||
.render-limit-notice {
|
||||
margin: 1rem 0 0;
|
||||
border-left: 0.2rem solid #b18124;
|
||||
padding: 0.7rem 0.85rem;
|
||||
color: #66552f;
|
||||
background: #fbf4e6;
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
.package-inspector,
|
||||
.diagnostics {
|
||||
padding: 1.25rem;
|
||||
|
||||
@@ -1,11 +1,22 @@
|
||||
{
|
||||
"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"],
|
||||
@@ -25,6 +36,6 @@
|
||||
},
|
||||
"source": {
|
||||
"repository": "https://git.add-ideas.de/zemion/onenote-tools",
|
||||
"license": "MPL-2.0"
|
||||
"license": "MPL-2.0 AND LGPL-2.1-only"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,8 @@ describe('toolbox manifest', () => {
|
||||
});
|
||||
|
||||
it('does not advertise unimplemented format support', () => {
|
||||
expect(toolboxApp.description).toContain('not implemented');
|
||||
expect(toolboxApp.description).toContain('tested');
|
||||
expect(toolboxApp.description).not.toContain('all OneNote');
|
||||
expect(toolboxApp.privacy).toEqual(
|
||||
expect.objectContaining({
|
||||
processing: 'local',
|
||||
|
||||
@@ -1 +1 @@
|
||||
export const APP_VERSION = '0.1.0';
|
||||
export const APP_VERSION = '0.2.0';
|
||||
|
||||
6
tests/fixtures/README.md
vendored
6
tests/fixtures/README.md
vendored
@@ -17,7 +17,8 @@ and does not change the underlying file's licence.
|
||||
`7c43e85e2169b4bc3236db73a24c8f20d5c284b74563c07baf1406887d20eb5e`.
|
||||
- Golden expectation: desktop OneStore section with three pages — `Test`,
|
||||
`Another page`, and `Page 3` — plus readable text/timestamps and diagnostics
|
||||
for image, table, and ink content.
|
||||
plus structured rich text, a PNG resource, a table, and 1,316 decoded ink
|
||||
points across 11 ink blocks.
|
||||
|
||||
## `joplin-test.onepkg.base64`
|
||||
|
||||
@@ -33,7 +34,8 @@ and does not change the underlying file's licence.
|
||||
and nested paths, five `.one` sections, and two `.onetoc2` entries.
|
||||
- Parser expectation: all five sections parse, producing seven pages in total:
|
||||
`Page 1`, `Page 2`, `Test`, `Test page`, `Testing…`, `A test`, and
|
||||
`Tuesday, January 13, 2026`.
|
||||
`Tuesday, January 13, 2026`; the contained TOCs provide interpreted notebook
|
||||
ordering rather than normalized-path-only navigation.
|
||||
|
||||
Tests verify the package hash, all seven paths, the native `.one` magic for
|
||||
every section, section parse statuses, and representative title/text output.
|
||||
|
||||
@@ -5,6 +5,11 @@ import { defineConfig } from 'vite';
|
||||
export default defineConfig({
|
||||
base: './',
|
||||
plugins: [react()],
|
||||
build: {
|
||||
// Baseline browsers support modulepreload natively. Avoid shipping Vite's
|
||||
// injected runtime polyfill (and an otherwise unnecessary runtime notice).
|
||||
modulePreload: { polyfill: false },
|
||||
},
|
||||
test: {
|
||||
environment: 'jsdom',
|
||||
setupFiles: './src/test/setup.ts',
|
||||
|
||||
Reference in New Issue
Block a user