wpd-codec 3.2.2 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -3
- package/dist/bytes/base64.cjs +21 -0
- package/dist/bytes/base64.d.cts +4 -0
- package/dist/bytes/base64.d.ts +4 -0
- package/dist/bytes/base64.js +20 -0
- package/dist/container/container.cjs +6 -3
- package/dist/container/container.d.cts +2 -2
- package/dist/container/container.d.ts +2 -2
- package/dist/container/container.js +6 -3
- package/dist/container/encryption.cjs +59 -0
- package/dist/container/encryption.d.cts +9 -0
- package/dist/container/encryption.d.ts +9 -0
- package/dist/container/encryption.js +54 -0
- package/dist/container/header.cjs +5 -3
- package/dist/container/header.d.cts +6 -2
- package/dist/container/header.d.ts +6 -2
- package/dist/container/header.js +5 -3
- package/dist/{diagnostics-Dtb2uPw4.d.cts → diagnostics-DhO7mgqJ.d.cts} +1 -0
- package/dist/{diagnostics-Dtb2uPw4.d.ts → diagnostics-DhO7mgqJ.d.ts} +1 -0
- package/dist/diagnostics.cjs +1 -0
- package/dist/diagnostics.d.cts +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.js +1 -0
- package/dist/errors.cjs +11 -0
- package/dist/errors.d.cts +6 -1
- package/dist/errors.d.ts +6 -1
- package/dist/errors.js +11 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/read.cjs +177 -7
- package/dist/read.d.cts +9 -3
- package/dist/read.d.ts +9 -3
- package/dist/read.js +177 -7
- package/dist/stream/furniture.cjs +33 -0
- package/dist/stream/furniture.d.cts +15 -0
- package/dist/stream/furniture.d.ts +15 -0
- package/dist/stream/furniture.js +25 -0
- package/dist/stream/image.cjs +72 -0
- package/dist/stream/image.d.cts +8 -0
- package/dist/stream/image.d.ts +8 -0
- package/dist/stream/image.js +71 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -71,7 +71,7 @@ readWpdContent(bytes, {
|
|
|
71
71
|
});
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
-
Structural nonconformance is not a diagnostic — it throws. `WpdNotAWordPerfectFileError`, `WpdEncryptedDocumentError`, `WpdUnsupportedVersionError`, and the general `WpdFormatError` are all exported, and all extend the last.
|
|
74
|
+
Structural nonconformance is not a diagnostic — it throws. `WpdNotAWordPerfectFileError`, `WpdEncryptedDocumentError`, `WpdWrongPasswordError`, `WpdUnsupportedVersionError`, and the general `WpdFormatError` are all exported, and all extend the last.
|
|
75
75
|
|
|
76
76
|
## What it provides
|
|
77
77
|
|
|
@@ -174,12 +174,17 @@ This is a bet against libwpd's _code_, not against citing its _data_: the charac
|
|
|
174
174
|
|
|
175
175
|
Everything below is recognised by the tokeniser and skipped by the fold, so a document containing it still reads — losing that construct's own structure, never the surrounding text. Each is reported through the diagnostic sink rather than passed over in silence.
|
|
176
176
|
|
|
177
|
-
- **
|
|
177
|
+
- **A box whose content is a presentation, video, macro, sound, or external payload**, and a box relying on its own template's inherited geometry rather than an explicit function-level position/size override. Reported through `wpd/box-content-unresolved` and `wpd/box-frame-unresolved` respectively. An image box IS lifted when its content packet carries a whole PNG or JPEG payload: the packet's raw bytes are scanned by signature and structural walk (`src/stream/image.ts` — the chunk chain to IEND for PNG, the marker segments to EOI for JPEG), never by guessing at a container header, and the span lifts as a `ContentImageBlock` sized by the box's own frame, with an absolute-from-page-edge position carried as the image's `floatPosition`. What stays unresolved: a WPG vector graphic (a distinct binary graphics format `ContentImageBlock`'s `png`/`jpeg`/`svg`/`gif` set cannot hold as recovered, and which this package does not decode — a project on the scale of this package's own WordPerfect reader, not a wiring job) and a native OLE object (see the next bullet). A box with no function-level content override at all — relying entirely on its template's own rendering defaults — is reported through `wpd/box-dropped`, unchanged from before.
|
|
178
|
+
- **Watermarks** (the 0xD6 group's two watermark subfunctions). Reported through `wpd/header-footer-dropped`: a watermark is neither a header nor a footer and owns no parity, so the shared page-furniture vocabulary has no slot for one.
|
|
179
|
+
- **A second header or footer claiming a slot a first already filled.** WordPerfect's own A/B two-slot-per-kind mechanism is a shape the shared one-flow-per-slot vocabulary does not carry; the first function to claim a slot is the one lifted, and the collision is reported through `wpd/header-footer-dropped`.
|
|
180
|
+
|
|
181
|
+
Headers and footers themselves are LIFTED (ExaDev/documents.js#1128): a D6 function's occurrence bits narrow onto the shared furniture vocabulary's slots (`ContentSection.headers`/`footers`, `default`/`even` — odd-only and both-parities are the default slot, even-only the even slot), its body folded from the General WP Text packet its first prefix ID names. Footnotes and endnotes are anchored in the flat form (a footnote/endnote anchor construct around the reference site, `definition` naming `note-1`, `note-2`, ... in document order) and their bodies are carried by `readWpd` as definitions-table entries in the tree form — the flat `readWpdContent` reports each still-borne body through `wpd/note-dropped`, since the flat `ContentDocument` genuinely has no home for one (`rtf-codec` documents the same split for its own equivalent constructs).
|
|
182
|
+
|
|
178
183
|
- **A box whose content is an image, presentation, video, macro, sound, or external payload**, and a box relying on its own template's inherited geometry rather than an explicit function-level position/size override. Reported through `wpd/box-content-unresolved` and `wpd/box-frame-unresolved` respectively. An image box's own content resolves to a Graphics Filename prefix packet (type 0x40) whose children carry either WPG vector graphics (a distinct binary graphics format `ContentImageBlock`'s `png`/`jpeg`/`svg`/`gif` set cannot hold as recovered, and which this package does not decode — a project on the scale of this package's own WordPerfect reader, not a wiring job) or a native OLE object (see the next bullet). A box with no function-level content override at all — relying entirely on its template's own rendering defaults — is reported through `wpd/box-dropped`, unchanged from before.
|
|
179
184
|
- **Embedded OLE objects**, stored under the compound file's `PerfectOffice_OBJECTS` storage and named by an image box's Graphics Filename packet's own `0x70`/`0x71` (OLE Object Descriptor / OLE Object Data) children. `archive-codec`'s compound-file reader already reaches that storage, which is how `ooxml.js` recovers a ZIP-payload embedded object — but a WordPerfect OLE object's payload is a native OLE server's own stream rather than a nested document package (`ooxml.js`'s own equivalent case, a classic OLE1 `.bin` payload with no `Package` stream, stays opaque by the identical scope boundary), so recovering one generically is a project in its own right, not a wiring job.
|
|
180
185
|
- **The counter groups** (0xD8, 0xD9, 0xDB, 0xDC): setting, numbering-method, increment and decrement carry no text and change no structure this reader models, so only the Display Number group's own paragraph-number pair is read.
|
|
181
186
|
- **Every merge subfunction other than FIELD** (ASSIGN, CALL, IF, FOR, CASE, and the rest of WordPerfect's own merge scripting language) and **cross-references** (0xD5). A cross-reference's displayed text survives as ordinary text; its target binding does not. Reported through `wpd/merge-code-dropped` and `wpd/cross-reference-flattened`. Unlike FIELD, these can legitimately wrap whole paragraphs of body text as control flow, which the run-scoped field construct's own one-paragraph extent cannot express regardless — a schema gap for a scripting language's control flow, not a parsing gap.
|
|
182
|
-
- **
|
|
187
|
+
- **WordPerfect 9-and-later "enhanced encryption"**, which throws: a different, unpublished cipher whose header word is not the standard mode's password checksum, so a `password` read option either verifies against that checksum and decrypts the standard ("original") mode or throws `WpdWrongPasswordError` naming both possible readings of the mismatch. The standard mode itself is decrypted for real (see `src/container/encryption.ts` for the cipher's two independent sources, and for the honest limit that no open-source reference implementation of the 6.x wiring exists to cross-check against a WordPerfect-produced encrypted file).
|
|
183
188
|
|
|
184
189
|
## Evidence
|
|
185
190
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_bytes_view = require("./view.cjs");
|
|
3
|
+
//#region src/bytes/base64.ts
|
|
4
|
+
const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
5
|
+
function bytesToBase64(bytes) {
|
|
6
|
+
let out = "";
|
|
7
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
8
|
+
const b0 = require_bytes_view.byteAt(bytes, i);
|
|
9
|
+
const b1 = bytes[i + 1];
|
|
10
|
+
const b2 = bytes[i + 2];
|
|
11
|
+
out += ALPHABET.charAt(b0 >>> 2);
|
|
12
|
+
out += ALPHABET.charAt((b0 & 3) << 4 | (b1 ?? 0) >>> 4);
|
|
13
|
+
if (b1 === void 0) return out + "==";
|
|
14
|
+
out += ALPHABET.charAt((b1 & 15) << 2 | (b2 ?? 0) >>> 6);
|
|
15
|
+
if (b2 === void 0) return out + "=";
|
|
16
|
+
out += ALPHABET.charAt(b2 & 63);
|
|
17
|
+
}
|
|
18
|
+
return out;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
exports.bytesToBase64 = bytesToBase64;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { byteAt } from "./view.js";
|
|
2
|
+
//#region src/bytes/base64.ts
|
|
3
|
+
const ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
4
|
+
function bytesToBase64(bytes) {
|
|
5
|
+
let out = "";
|
|
6
|
+
for (let i = 0; i < bytes.length; i += 3) {
|
|
7
|
+
const b0 = byteAt(bytes, i);
|
|
8
|
+
const b1 = bytes[i + 1];
|
|
9
|
+
const b2 = bytes[i + 2];
|
|
10
|
+
out += ALPHABET.charAt(b0 >>> 2);
|
|
11
|
+
out += ALPHABET.charAt((b0 & 3) << 4 | (b1 ?? 0) >>> 4);
|
|
12
|
+
if (b1 === void 0) return out + "==";
|
|
13
|
+
out += ALPHABET.charAt((b1 & 15) << 2 | (b2 ?? 0) >>> 6);
|
|
14
|
+
if (b2 === void 0) return out + "=";
|
|
15
|
+
out += ALPHABET.charAt(b2 & 63);
|
|
16
|
+
}
|
|
17
|
+
return out;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
export { bytesToBase64 };
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_errors = require("../errors.cjs");
|
|
3
3
|
const require_container_header = require("./header.cjs");
|
|
4
|
+
const require_container_encryption = require("./encryption.cjs");
|
|
4
5
|
const require_container_prefix = require("./prefix.cjs");
|
|
5
6
|
let archive_codec = require("archive-codec");
|
|
6
7
|
//#region src/container/container.ts
|
|
@@ -35,9 +36,11 @@ function documentAreaEnd(bytes, header) {
|
|
|
35
36
|
if (fileSize > documentAreaOffset && fileSize <= bytes.length) return fileSize;
|
|
36
37
|
return bytes.length;
|
|
37
38
|
}
|
|
38
|
-
function openWpdDocument(input) {
|
|
39
|
-
const { bytes, compound } = unwrapContainer(toArrayBufferBacked(input));
|
|
40
|
-
const header = require_container_header.readFileHeader(
|
|
39
|
+
function openWpdDocument(input, options = {}) {
|
|
40
|
+
const { bytes: wrapped, compound } = unwrapContainer(toArrayBufferBacked(input));
|
|
41
|
+
const header = require_container_header.readFileHeader(wrapped, options);
|
|
42
|
+
const suppliedPassword = options.password === "" ? void 0 : options.password;
|
|
43
|
+
const bytes = header.encryption !== 0 && suppliedPassword !== void 0 ? require_container_encryption.decryptWpdDocument(wrapped, header, suppliedPassword) : wrapped;
|
|
41
44
|
return {
|
|
42
45
|
header,
|
|
43
46
|
packets: require_container_prefix.readPrefixPackets(bytes, header),
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WpdFileHeader } from "./header.cjs";
|
|
1
|
+
import { ReadWpdHeaderOptions, WpdFileHeader } from "./header.cjs";
|
|
2
2
|
import { WpdPrefixPacket } from "./prefix.cjs";
|
|
3
3
|
//#region src/container/container.d.ts
|
|
4
4
|
declare const PERFECT_OFFICE_MAIN_STREAM = "PerfectOffice_MAIN";
|
|
@@ -11,6 +11,6 @@ interface WpdDocumentContainer {
|
|
|
11
11
|
readonly documentAreaEnd: number;
|
|
12
12
|
readonly compound: boolean;
|
|
13
13
|
}
|
|
14
|
-
declare function openWpdDocument(input: Uint8Array): WpdDocumentContainer;
|
|
14
|
+
declare function openWpdDocument(input: Uint8Array, options?: ReadWpdHeaderOptions): WpdDocumentContainer;
|
|
15
15
|
//#endregion
|
|
16
16
|
export { PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, WpdDocumentContainer, openWpdDocument };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WpdFileHeader } from "./header.js";
|
|
1
|
+
import { ReadWpdHeaderOptions, WpdFileHeader } from "./header.js";
|
|
2
2
|
import { WpdPrefixPacket } from "./prefix.js";
|
|
3
3
|
//#region src/container/container.d.ts
|
|
4
4
|
declare const PERFECT_OFFICE_MAIN_STREAM = "PerfectOffice_MAIN";
|
|
@@ -11,6 +11,6 @@ interface WpdDocumentContainer {
|
|
|
11
11
|
readonly documentAreaEnd: number;
|
|
12
12
|
readonly compound: boolean;
|
|
13
13
|
}
|
|
14
|
-
declare function openWpdDocument(input: Uint8Array): WpdDocumentContainer;
|
|
14
|
+
declare function openWpdDocument(input: Uint8Array, options?: ReadWpdHeaderOptions): WpdDocumentContainer;
|
|
15
15
|
//#endregion
|
|
16
16
|
export { PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, WpdDocumentContainer, openWpdDocument };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { WpdNotAWordPerfectFileError } from "../errors.js";
|
|
2
2
|
import { hasWordPerfectFileId, readFileHeader } from "./header.js";
|
|
3
|
+
import { decryptWpdDocument } from "./encryption.js";
|
|
3
4
|
import { readPrefixPackets } from "./prefix.js";
|
|
4
5
|
import { isCompoundFile, readCompoundFile } from "archive-codec";
|
|
5
6
|
//#region src/container/container.ts
|
|
@@ -34,9 +35,11 @@ function documentAreaEnd(bytes, header) {
|
|
|
34
35
|
if (fileSize > documentAreaOffset && fileSize <= bytes.length) return fileSize;
|
|
35
36
|
return bytes.length;
|
|
36
37
|
}
|
|
37
|
-
function openWpdDocument(input) {
|
|
38
|
-
const { bytes, compound } = unwrapContainer(toArrayBufferBacked(input));
|
|
39
|
-
const header = readFileHeader(
|
|
38
|
+
function openWpdDocument(input, options = {}) {
|
|
39
|
+
const { bytes: wrapped, compound } = unwrapContainer(toArrayBufferBacked(input));
|
|
40
|
+
const header = readFileHeader(wrapped, options);
|
|
41
|
+
const suppliedPassword = options.password === "" ? void 0 : options.password;
|
|
42
|
+
const bytes = header.encryption !== 0 && suppliedPassword !== void 0 ? decryptWpdDocument(wrapped, header, suppliedPassword) : wrapped;
|
|
40
43
|
return {
|
|
41
44
|
header,
|
|
42
45
|
packets: readPrefixPackets(bytes, header),
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_errors = require("../errors.cjs");
|
|
3
|
+
const require_bytes_view = require("../bytes/view.cjs");
|
|
4
|
+
require("./header.cjs");
|
|
5
|
+
//#region src/container/encryption.ts
|
|
6
|
+
function normaliseWpdPassword(password) {
|
|
7
|
+
const normalised = [];
|
|
8
|
+
for (let i = 0; i < password.length; i++) {
|
|
9
|
+
const unit = password.charCodeAt(i);
|
|
10
|
+
if (unit > 255) throw new require_errors.WpdFormatError(`A password with characters outside Latin-1 cannot be encoded into the byte-keyed WordPerfect cipher (code unit U+${unit.toString(16).toUpperCase().padStart(4, "0")} at position ${i}).`);
|
|
11
|
+
normalised.push(unit >= 97 && unit <= 122 ? unit - 97 + 65 : unit);
|
|
12
|
+
}
|
|
13
|
+
return normalised;
|
|
14
|
+
}
|
|
15
|
+
function wpdPasswordChecksum16(normalised) {
|
|
16
|
+
let checksum = 0;
|
|
17
|
+
for (const unit of normalised) {
|
|
18
|
+
checksum = (checksum >>> 1 | checksum << 15) ^ unit << 8;
|
|
19
|
+
checksum &= 65535;
|
|
20
|
+
}
|
|
21
|
+
return checksum;
|
|
22
|
+
}
|
|
23
|
+
function applyWpdStandardEncryption(bytes, normalised, startOffset) {
|
|
24
|
+
if (normalised.length === 0) throw new require_errors.WpdFormatError("The WordPerfect cipher is keyed by the password's own bytes, so an empty password decrypts nothing.");
|
|
25
|
+
const maskBase = normalised.length + 1 & 255;
|
|
26
|
+
const output = new Uint8Array(bytes.length);
|
|
27
|
+
output.set(bytes.subarray(0, startOffset));
|
|
28
|
+
for (let pos = startOffset; pos < bytes.length; pos++) {
|
|
29
|
+
const relative = pos - startOffset;
|
|
30
|
+
const passwordByte = normalised[relative % normalised.length];
|
|
31
|
+
if (passwordByte === void 0) throw new require_errors.WpdFormatError("The password normalised to no bytes, which the cipher cannot key with.");
|
|
32
|
+
const mask = maskBase + relative & 255;
|
|
33
|
+
output[pos] = require_bytes_view.byteAt(bytes, pos) ^ passwordByte ^ mask;
|
|
34
|
+
}
|
|
35
|
+
return output;
|
|
36
|
+
}
|
|
37
|
+
function decryptWpdDocument(bytes, header, password) {
|
|
38
|
+
const normalised = normaliseWpdPassword(password);
|
|
39
|
+
if (normalised.length === 0) throw new require_errors.WpdWrongPasswordError(header.encryption, 0);
|
|
40
|
+
const checksum = wpdPasswordChecksum16(normalised);
|
|
41
|
+
if (checksum !== header.encryption) throw new require_errors.WpdWrongPasswordError(header.encryption, checksum);
|
|
42
|
+
return applyWpdStandardEncryption(bytes, normalised, 512);
|
|
43
|
+
}
|
|
44
|
+
function encryptWpdDocumentForTests(bytes, password) {
|
|
45
|
+
const normalised = normaliseWpdPassword(password);
|
|
46
|
+
const checksum = wpdPasswordChecksum16(normalised);
|
|
47
|
+
const encrypted = applyWpdStandardEncryption(bytes, normalised, 512);
|
|
48
|
+
const output = new Uint8Array(encrypted.length);
|
|
49
|
+
output.set(encrypted);
|
|
50
|
+
output[12] = checksum & 255;
|
|
51
|
+
output[13] = checksum >>> 8 & 255;
|
|
52
|
+
return output;
|
|
53
|
+
}
|
|
54
|
+
//#endregion
|
|
55
|
+
exports.applyWpdStandardEncryption = applyWpdStandardEncryption;
|
|
56
|
+
exports.decryptWpdDocument = decryptWpdDocument;
|
|
57
|
+
exports.encryptWpdDocumentForTests = encryptWpdDocumentForTests;
|
|
58
|
+
exports.normaliseWpdPassword = normaliseWpdPassword;
|
|
59
|
+
exports.wpdPasswordChecksum16 = wpdPasswordChecksum16;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WpdFileHeader } from "./header.cjs";
|
|
2
|
+
//#region src/container/encryption.d.ts
|
|
3
|
+
declare function normaliseWpdPassword(password: string): number[];
|
|
4
|
+
declare function wpdPasswordChecksum16(normalised: readonly number[]): number;
|
|
5
|
+
declare function applyWpdStandardEncryption(bytes: Uint8Array, normalised: readonly number[], startOffset: number): Uint8Array<ArrayBuffer>;
|
|
6
|
+
declare function decryptWpdDocument(bytes: Uint8Array<ArrayBuffer>, header: WpdFileHeader, password: string): Uint8Array<ArrayBuffer>;
|
|
7
|
+
declare function encryptWpdDocumentForTests(bytes: Uint8Array, password: string): Uint8Array<ArrayBuffer>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { applyWpdStandardEncryption, decryptWpdDocument, encryptWpdDocumentForTests, normaliseWpdPassword, wpdPasswordChecksum16 };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WpdFileHeader } from "./header.js";
|
|
2
|
+
//#region src/container/encryption.d.ts
|
|
3
|
+
declare function normaliseWpdPassword(password: string): number[];
|
|
4
|
+
declare function wpdPasswordChecksum16(normalised: readonly number[]): number;
|
|
5
|
+
declare function applyWpdStandardEncryption(bytes: Uint8Array, normalised: readonly number[], startOffset: number): Uint8Array<ArrayBuffer>;
|
|
6
|
+
declare function decryptWpdDocument(bytes: Uint8Array<ArrayBuffer>, header: WpdFileHeader, password: string): Uint8Array<ArrayBuffer>;
|
|
7
|
+
declare function encryptWpdDocumentForTests(bytes: Uint8Array, password: string): Uint8Array<ArrayBuffer>;
|
|
8
|
+
//#endregion
|
|
9
|
+
export { applyWpdStandardEncryption, decryptWpdDocument, encryptWpdDocumentForTests, normaliseWpdPassword, wpdPasswordChecksum16 };
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { WpdFormatError, WpdWrongPasswordError } from "../errors.js";
|
|
2
|
+
import { byteAt } from "../bytes/view.js";
|
|
3
|
+
import "./header.js";
|
|
4
|
+
//#region src/container/encryption.ts
|
|
5
|
+
function normaliseWpdPassword(password) {
|
|
6
|
+
const normalised = [];
|
|
7
|
+
for (let i = 0; i < password.length; i++) {
|
|
8
|
+
const unit = password.charCodeAt(i);
|
|
9
|
+
if (unit > 255) throw new WpdFormatError(`A password with characters outside Latin-1 cannot be encoded into the byte-keyed WordPerfect cipher (code unit U+${unit.toString(16).toUpperCase().padStart(4, "0")} at position ${i}).`);
|
|
10
|
+
normalised.push(unit >= 97 && unit <= 122 ? unit - 97 + 65 : unit);
|
|
11
|
+
}
|
|
12
|
+
return normalised;
|
|
13
|
+
}
|
|
14
|
+
function wpdPasswordChecksum16(normalised) {
|
|
15
|
+
let checksum = 0;
|
|
16
|
+
for (const unit of normalised) {
|
|
17
|
+
checksum = (checksum >>> 1 | checksum << 15) ^ unit << 8;
|
|
18
|
+
checksum &= 65535;
|
|
19
|
+
}
|
|
20
|
+
return checksum;
|
|
21
|
+
}
|
|
22
|
+
function applyWpdStandardEncryption(bytes, normalised, startOffset) {
|
|
23
|
+
if (normalised.length === 0) throw new WpdFormatError("The WordPerfect cipher is keyed by the password's own bytes, so an empty password decrypts nothing.");
|
|
24
|
+
const maskBase = normalised.length + 1 & 255;
|
|
25
|
+
const output = new Uint8Array(bytes.length);
|
|
26
|
+
output.set(bytes.subarray(0, startOffset));
|
|
27
|
+
for (let pos = startOffset; pos < bytes.length; pos++) {
|
|
28
|
+
const relative = pos - startOffset;
|
|
29
|
+
const passwordByte = normalised[relative % normalised.length];
|
|
30
|
+
if (passwordByte === void 0) throw new WpdFormatError("The password normalised to no bytes, which the cipher cannot key with.");
|
|
31
|
+
const mask = maskBase + relative & 255;
|
|
32
|
+
output[pos] = byteAt(bytes, pos) ^ passwordByte ^ mask;
|
|
33
|
+
}
|
|
34
|
+
return output;
|
|
35
|
+
}
|
|
36
|
+
function decryptWpdDocument(bytes, header, password) {
|
|
37
|
+
const normalised = normaliseWpdPassword(password);
|
|
38
|
+
if (normalised.length === 0) throw new WpdWrongPasswordError(header.encryption, 0);
|
|
39
|
+
const checksum = wpdPasswordChecksum16(normalised);
|
|
40
|
+
if (checksum !== header.encryption) throw new WpdWrongPasswordError(header.encryption, checksum);
|
|
41
|
+
return applyWpdStandardEncryption(bytes, normalised, 512);
|
|
42
|
+
}
|
|
43
|
+
function encryptWpdDocumentForTests(bytes, password) {
|
|
44
|
+
const normalised = normaliseWpdPassword(password);
|
|
45
|
+
const checksum = wpdPasswordChecksum16(normalised);
|
|
46
|
+
const encrypted = applyWpdStandardEncryption(bytes, normalised, 512);
|
|
47
|
+
const output = new Uint8Array(encrypted.length);
|
|
48
|
+
output.set(encrypted);
|
|
49
|
+
output[12] = checksum & 255;
|
|
50
|
+
output[13] = checksum >>> 8 & 255;
|
|
51
|
+
return output;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { applyWpdStandardEncryption, decryptWpdDocument, encryptWpdDocumentForTests, normaliseWpdPassword, wpdPasswordChecksum16 };
|
|
@@ -16,7 +16,7 @@ function hasWordPerfectFileId(bytes) {
|
|
|
16
16
|
if (bytes.length < WPD_FILE_ID.length) return false;
|
|
17
17
|
return WPD_FILE_ID.every((expected, index) => bytes[index] === expected);
|
|
18
18
|
}
|
|
19
|
-
function readFileHeader(bytes) {
|
|
19
|
+
function readFileHeader(bytes, options = {}) {
|
|
20
20
|
if (!hasWordPerfectFileId(bytes)) {
|
|
21
21
|
const actual = Array.from(require_bytes_view.sliceAt(bytes, 0, Math.min(4, bytes.length))).map((byte) => byte.toString(16).padStart(2, "0")).join(" ");
|
|
22
22
|
throw new require_errors.WpdNotAWordPerfectFileError(`Expected the WordPerfect file ID FF 57 50 43 (-1,"WPC") at offset 0, found ${actual}.`);
|
|
@@ -28,7 +28,8 @@ function readFileHeader(bytes) {
|
|
|
28
28
|
const minorVersion = require_bytes_view.byteAt(bytes, 11);
|
|
29
29
|
const encryption = require_bytes_view.uint16At(bytes, 12);
|
|
30
30
|
const indexAreaOffset = require_bytes_view.uint16At(bytes, 14);
|
|
31
|
-
|
|
31
|
+
const suppliedPassword = options.password === "" ? void 0 : options.password;
|
|
32
|
+
if (encryption !== 0 && suppliedPassword === void 0) throw new require_errors.WpdEncryptedDocumentError(`This document is encrypted (encryption word ${encryption}); nothing beyond the file header is intelligible without the password. Pass { password } to read it -- the standard ("original") encryption mode is supported, and a non-matching password throws WpdWrongPasswordError.`);
|
|
32
33
|
if (productType !== PRODUCT_TYPE_WORDPERFECT) throw new require_errors.WpdUnsupportedVersionError(`Product type ${productType} is not WordPerfect (${PRODUCT_TYPE_WORDPERFECT}); this file was produced by a different Corel product.`);
|
|
33
34
|
if (!DOCUMENT_FILE_TYPES.includes(fileType)) throw new require_errors.WpdUnsupportedVersionError(`File type ${fileType} is not a WordPerfect document (expected ${DOCUMENT_FILE_TYPES.join(" or ")}).`);
|
|
34
35
|
if (majorVersion !== MAJOR_VERSION_WP6_THROUGH_X6) throw new require_errors.WpdUnsupportedVersionError(`Major version ${majorVersion} is outside the WordPerfect 6.x-X6 lineage (major version ${MAJOR_VERSION_WP6_THROUGH_X6}), the one generation this reader covers.`);
|
|
@@ -39,7 +40,8 @@ function readFileHeader(bytes) {
|
|
|
39
40
|
majorVersion,
|
|
40
41
|
minorVersion,
|
|
41
42
|
indexAreaOffset,
|
|
42
|
-
fileSize: require_bytes_view.uint32At(bytes, 20)
|
|
43
|
+
fileSize: require_bytes_view.uint32At(bytes, 20),
|
|
44
|
+
encryption
|
|
43
45
|
};
|
|
44
46
|
}
|
|
45
47
|
//#endregion
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
//#region src/container/header.d.ts
|
|
2
2
|
declare const WPD_FILE_ID: readonly number[];
|
|
3
3
|
declare const WPD_PREFIX_HEADER_SIZE = 512;
|
|
4
|
+
interface ReadWpdHeaderOptions {
|
|
5
|
+
readonly password?: string;
|
|
6
|
+
}
|
|
4
7
|
interface WpdFileHeader {
|
|
5
8
|
readonly documentAreaOffset: number;
|
|
6
9
|
readonly productType: number;
|
|
@@ -9,8 +12,9 @@ interface WpdFileHeader {
|
|
|
9
12
|
readonly minorVersion: number;
|
|
10
13
|
readonly indexAreaOffset: number;
|
|
11
14
|
readonly fileSize: number;
|
|
15
|
+
readonly encryption: number;
|
|
12
16
|
}
|
|
13
17
|
declare function hasWordPerfectFileId(bytes: Uint8Array): boolean;
|
|
14
|
-
declare function readFileHeader(bytes: Uint8Array): WpdFileHeader;
|
|
18
|
+
declare function readFileHeader(bytes: Uint8Array, options?: ReadWpdHeaderOptions): WpdFileHeader;
|
|
15
19
|
//#endregion
|
|
16
|
-
export { WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader };
|
|
20
|
+
export { ReadWpdHeaderOptions, WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader };
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
//#region src/container/header.d.ts
|
|
2
2
|
declare const WPD_FILE_ID: readonly number[];
|
|
3
3
|
declare const WPD_PREFIX_HEADER_SIZE = 512;
|
|
4
|
+
interface ReadWpdHeaderOptions {
|
|
5
|
+
readonly password?: string;
|
|
6
|
+
}
|
|
4
7
|
interface WpdFileHeader {
|
|
5
8
|
readonly documentAreaOffset: number;
|
|
6
9
|
readonly productType: number;
|
|
@@ -9,8 +12,9 @@ interface WpdFileHeader {
|
|
|
9
12
|
readonly minorVersion: number;
|
|
10
13
|
readonly indexAreaOffset: number;
|
|
11
14
|
readonly fileSize: number;
|
|
15
|
+
readonly encryption: number;
|
|
12
16
|
}
|
|
13
17
|
declare function hasWordPerfectFileId(bytes: Uint8Array): boolean;
|
|
14
|
-
declare function readFileHeader(bytes: Uint8Array): WpdFileHeader;
|
|
18
|
+
declare function readFileHeader(bytes: Uint8Array, options?: ReadWpdHeaderOptions): WpdFileHeader;
|
|
15
19
|
//#endregion
|
|
16
|
-
export { WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader };
|
|
20
|
+
export { ReadWpdHeaderOptions, WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader };
|
package/dist/container/header.js
CHANGED
|
@@ -15,7 +15,7 @@ function hasWordPerfectFileId(bytes) {
|
|
|
15
15
|
if (bytes.length < WPD_FILE_ID.length) return false;
|
|
16
16
|
return WPD_FILE_ID.every((expected, index) => bytes[index] === expected);
|
|
17
17
|
}
|
|
18
|
-
function readFileHeader(bytes) {
|
|
18
|
+
function readFileHeader(bytes, options = {}) {
|
|
19
19
|
if (!hasWordPerfectFileId(bytes)) {
|
|
20
20
|
const actual = Array.from(sliceAt(bytes, 0, Math.min(4, bytes.length))).map((byte) => byte.toString(16).padStart(2, "0")).join(" ");
|
|
21
21
|
throw new WpdNotAWordPerfectFileError(`Expected the WordPerfect file ID FF 57 50 43 (-1,"WPC") at offset 0, found ${actual}.`);
|
|
@@ -27,7 +27,8 @@ function readFileHeader(bytes) {
|
|
|
27
27
|
const minorVersion = byteAt(bytes, 11);
|
|
28
28
|
const encryption = uint16At(bytes, 12);
|
|
29
29
|
const indexAreaOffset = uint16At(bytes, 14);
|
|
30
|
-
|
|
30
|
+
const suppliedPassword = options.password === "" ? void 0 : options.password;
|
|
31
|
+
if (encryption !== 0 && suppliedPassword === void 0) throw new WpdEncryptedDocumentError(`This document is encrypted (encryption word ${encryption}); nothing beyond the file header is intelligible without the password. Pass { password } to read it -- the standard ("original") encryption mode is supported, and a non-matching password throws WpdWrongPasswordError.`);
|
|
31
32
|
if (productType !== PRODUCT_TYPE_WORDPERFECT) throw new WpdUnsupportedVersionError(`Product type ${productType} is not WordPerfect (${PRODUCT_TYPE_WORDPERFECT}); this file was produced by a different Corel product.`);
|
|
32
33
|
if (!DOCUMENT_FILE_TYPES.includes(fileType)) throw new WpdUnsupportedVersionError(`File type ${fileType} is not a WordPerfect document (expected ${DOCUMENT_FILE_TYPES.join(" or ")}).`);
|
|
33
34
|
if (majorVersion !== MAJOR_VERSION_WP6_THROUGH_X6) throw new WpdUnsupportedVersionError(`Major version ${majorVersion} is outside the WordPerfect 6.x-X6 lineage (major version ${MAJOR_VERSION_WP6_THROUGH_X6}), the one generation this reader covers.`);
|
|
@@ -38,7 +39,8 @@ function readFileHeader(bytes) {
|
|
|
38
39
|
majorVersion,
|
|
39
40
|
minorVersion,
|
|
40
41
|
indexAreaOffset,
|
|
41
|
-
fileSize: uint32At(bytes, 20)
|
|
42
|
+
fileSize: uint32At(bytes, 20),
|
|
43
|
+
encryption
|
|
42
44
|
};
|
|
43
45
|
}
|
|
44
46
|
//#endregion
|
|
@@ -16,6 +16,7 @@ declare const WpdDiagnosticCodes: {
|
|
|
16
16
|
readonly OutlineNumberRegenerated: "wpd/outline-number-regenerated";
|
|
17
17
|
readonly BoxDropped: "wpd/box-dropped";
|
|
18
18
|
readonly NoteDropped: "wpd/note-dropped";
|
|
19
|
+
readonly NoteSpansParagraphs: "wpd/note-spans-paragraphs";
|
|
19
20
|
readonly HeaderFooterDropped: "wpd/header-footer-dropped";
|
|
20
21
|
readonly CrossReferenceFlattened: "wpd/cross-reference-flattened";
|
|
21
22
|
readonly MergeCodeDropped: "wpd/merge-code-dropped";
|
|
@@ -16,6 +16,7 @@ declare const WpdDiagnosticCodes: {
|
|
|
16
16
|
readonly OutlineNumberRegenerated: "wpd/outline-number-regenerated";
|
|
17
17
|
readonly BoxDropped: "wpd/box-dropped";
|
|
18
18
|
readonly NoteDropped: "wpd/note-dropped";
|
|
19
|
+
readonly NoteSpansParagraphs: "wpd/note-spans-paragraphs";
|
|
19
20
|
readonly HeaderFooterDropped: "wpd/header-footer-dropped";
|
|
20
21
|
readonly CrossReferenceFlattened: "wpd/cross-reference-flattened";
|
|
21
22
|
readonly MergeCodeDropped: "wpd/merge-code-dropped";
|
package/dist/diagnostics.cjs
CHANGED
|
@@ -12,6 +12,7 @@ const WpdDiagnosticCodes = {
|
|
|
12
12
|
OutlineNumberRegenerated: "wpd/outline-number-regenerated",
|
|
13
13
|
BoxDropped: "wpd/box-dropped",
|
|
14
14
|
NoteDropped: "wpd/note-dropped",
|
|
15
|
+
NoteSpansParagraphs: "wpd/note-spans-paragraphs",
|
|
15
16
|
HeaderFooterDropped: "wpd/header-footer-dropped",
|
|
16
17
|
CrossReferenceFlattened: "wpd/cross-reference-flattened",
|
|
17
18
|
MergeCodeDropped: "wpd/merge-code-dropped",
|
package/dist/diagnostics.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-
|
|
1
|
+
import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-DhO7mgqJ.cjs";
|
|
2
2
|
export { NOOP_WPD_DIAGNOSTIC_SINK, WpdDiagnostic, WpdDiagnosticCodes, WpdDiagnosticSink };
|
package/dist/diagnostics.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-
|
|
1
|
+
import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-DhO7mgqJ.js";
|
|
2
2
|
export { NOOP_WPD_DIAGNOSTIC_SINK, WpdDiagnostic, WpdDiagnosticCodes, WpdDiagnosticSink };
|
package/dist/diagnostics.js
CHANGED
|
@@ -11,6 +11,7 @@ const WpdDiagnosticCodes = {
|
|
|
11
11
|
OutlineNumberRegenerated: "wpd/outline-number-regenerated",
|
|
12
12
|
BoxDropped: "wpd/box-dropped",
|
|
13
13
|
NoteDropped: "wpd/note-dropped",
|
|
14
|
+
NoteSpansParagraphs: "wpd/note-spans-paragraphs",
|
|
14
15
|
HeaderFooterDropped: "wpd/header-footer-dropped",
|
|
15
16
|
CrossReferenceFlattened: "wpd/cross-reference-flattened",
|
|
16
17
|
MergeCodeDropped: "wpd/merge-code-dropped",
|
package/dist/errors.cjs
CHANGED
|
@@ -18,6 +18,16 @@ var WpdEncryptedDocumentError = class extends WpdFormatError {
|
|
|
18
18
|
this.name = "WpdEncryptedDocumentError";
|
|
19
19
|
}
|
|
20
20
|
};
|
|
21
|
+
var WpdWrongPasswordError = class extends WpdFormatError {
|
|
22
|
+
headerEncryptionWord;
|
|
23
|
+
passwordChecksum;
|
|
24
|
+
constructor(headerEncryptionWord, passwordChecksum) {
|
|
25
|
+
super(`The header's encryption word (0x${headerEncryptionWord.toString(16)}) does not match this password's checksum (0x${passwordChecksum.toString(16)}): either the password is wrong, or the file uses the enhanced encryption mode (WordPerfect 9 and later), which this reader does not support.`);
|
|
26
|
+
this.headerEncryptionWord = headerEncryptionWord;
|
|
27
|
+
this.passwordChecksum = passwordChecksum;
|
|
28
|
+
this.name = "WpdWrongPasswordError";
|
|
29
|
+
}
|
|
30
|
+
};
|
|
21
31
|
var WpdUnsupportedVersionError = class extends WpdFormatError {
|
|
22
32
|
constructor(message) {
|
|
23
33
|
super(message);
|
|
@@ -29,3 +39,4 @@ exports.WpdEncryptedDocumentError = WpdEncryptedDocumentError;
|
|
|
29
39
|
exports.WpdFormatError = WpdFormatError;
|
|
30
40
|
exports.WpdNotAWordPerfectFileError = WpdNotAWordPerfectFileError;
|
|
31
41
|
exports.WpdUnsupportedVersionError = WpdUnsupportedVersionError;
|
|
42
|
+
exports.WpdWrongPasswordError = WpdWrongPasswordError;
|
package/dist/errors.d.cts
CHANGED
|
@@ -8,8 +8,13 @@ declare class WpdNotAWordPerfectFileError extends WpdFormatError {
|
|
|
8
8
|
declare class WpdEncryptedDocumentError extends WpdFormatError {
|
|
9
9
|
constructor(message: string);
|
|
10
10
|
}
|
|
11
|
+
declare class WpdWrongPasswordError extends WpdFormatError {
|
|
12
|
+
readonly headerEncryptionWord: number;
|
|
13
|
+
readonly passwordChecksum: number;
|
|
14
|
+
constructor(headerEncryptionWord: number, passwordChecksum: number);
|
|
15
|
+
}
|
|
11
16
|
declare class WpdUnsupportedVersionError extends WpdFormatError {
|
|
12
17
|
constructor(message: string);
|
|
13
18
|
}
|
|
14
19
|
//#endregion
|
|
15
|
-
export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError };
|
|
20
|
+
export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError, WpdWrongPasswordError };
|
package/dist/errors.d.ts
CHANGED
|
@@ -8,8 +8,13 @@ declare class WpdNotAWordPerfectFileError extends WpdFormatError {
|
|
|
8
8
|
declare class WpdEncryptedDocumentError extends WpdFormatError {
|
|
9
9
|
constructor(message: string);
|
|
10
10
|
}
|
|
11
|
+
declare class WpdWrongPasswordError extends WpdFormatError {
|
|
12
|
+
readonly headerEncryptionWord: number;
|
|
13
|
+
readonly passwordChecksum: number;
|
|
14
|
+
constructor(headerEncryptionWord: number, passwordChecksum: number);
|
|
15
|
+
}
|
|
11
16
|
declare class WpdUnsupportedVersionError extends WpdFormatError {
|
|
12
17
|
constructor(message: string);
|
|
13
18
|
}
|
|
14
19
|
//#endregion
|
|
15
|
-
export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError };
|
|
20
|
+
export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError, WpdWrongPasswordError };
|
package/dist/errors.js
CHANGED
|
@@ -17,6 +17,16 @@ var WpdEncryptedDocumentError = class extends WpdFormatError {
|
|
|
17
17
|
this.name = "WpdEncryptedDocumentError";
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
|
+
var WpdWrongPasswordError = class extends WpdFormatError {
|
|
21
|
+
headerEncryptionWord;
|
|
22
|
+
passwordChecksum;
|
|
23
|
+
constructor(headerEncryptionWord, passwordChecksum) {
|
|
24
|
+
super(`The header's encryption word (0x${headerEncryptionWord.toString(16)}) does not match this password's checksum (0x${passwordChecksum.toString(16)}): either the password is wrong, or the file uses the enhanced encryption mode (WordPerfect 9 and later), which this reader does not support.`);
|
|
25
|
+
this.headerEncryptionWord = headerEncryptionWord;
|
|
26
|
+
this.passwordChecksum = passwordChecksum;
|
|
27
|
+
this.name = "WpdWrongPasswordError";
|
|
28
|
+
}
|
|
29
|
+
};
|
|
20
30
|
var WpdUnsupportedVersionError = class extends WpdFormatError {
|
|
21
31
|
constructor(message) {
|
|
22
32
|
super(message);
|
|
@@ -24,4 +34,4 @@ var WpdUnsupportedVersionError = class extends WpdFormatError {
|
|
|
24
34
|
}
|
|
25
35
|
};
|
|
26
36
|
//#endregion
|
|
27
|
-
export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError };
|
|
37
|
+
export { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError, WpdWrongPasswordError };
|
package/dist/index.cjs
CHANGED
|
@@ -67,6 +67,7 @@ exports.WpdEncryptedDocumentError = require_errors.WpdEncryptedDocumentError;
|
|
|
67
67
|
exports.WpdFormatError = require_errors.WpdFormatError;
|
|
68
68
|
exports.WpdNotAWordPerfectFileError = require_errors.WpdNotAWordPerfectFileError;
|
|
69
69
|
exports.WpdUnsupportedVersionError = require_errors.WpdUnsupportedVersionError;
|
|
70
|
+
exports.WpdWrongPasswordError = require_errors.WpdWrongPasswordError;
|
|
70
71
|
exports.decodeAttributeByte = require_stream_attributes.decodeAttributeByte;
|
|
71
72
|
exports.decodeSingleByteCharacter = require_stream_characters.decodeSingleByteCharacter;
|
|
72
73
|
exports.decodeWordString = require_stream_characters.decodeWordString;
|
package/dist/index.d.cts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-
|
|
1
|
+
import { i as WpdDiagnosticSink, n as WpdDiagnostic, r as WpdDiagnosticCodes, t as NOOP_WPD_DIAGNOSTIC_SINK } from "./diagnostics-DhO7mgqJ.cjs";
|
|
2
2
|
import { ReadWpdOptions, readWpd, readWpdContent } from "./read.cjs";
|
|
3
3
|
import { WpdBytesSchema, wpdContentCodec } from "./codec.cjs";
|
|
4
4
|
import { WPD_FILE_ID, WPD_PREFIX_HEADER_SIZE, WpdFileHeader, hasWordPerfectFileId, readFileHeader } from "./container/header.cjs";
|
|
5
5
|
import { PACKET_TYPE_DESIRED_FONT_DESCRIPTOR, WPD_INDEX_RECORD_SIZE, WpdPrefixPacket, packetByPrefixId, readPrefixPackets, readTypefaceName } from "./container/prefix.cjs";
|
|
6
6
|
import { PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, WpdDocumentContainer, openWpdDocument } from "./container/container.cjs";
|
|
7
7
|
import { PACKET_TYPE_EXTENDED_DOCUMENT_SUMMARY, readDocumentSummary } from "./container/summary.cjs";
|
|
8
|
-
import { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError } from "./errors.cjs";
|
|
8
|
+
import { WpdEncryptedDocumentError, WpdFormatError, WpdNotAWordPerfectFileError, WpdUnsupportedVersionError, WpdWrongPasswordError } from "./errors.cjs";
|
|
9
9
|
import { WPD_FILE_EXTENSION, WPD_MEDIA_TYPE } from "./format.cjs";
|
|
10
10
|
import { FIRST_FIXED_FUNCTION, FIRST_SINGLE_BYTE_FUNCTION, FIRST_VARIABLE_FUNCTION, WpdCharacterToken, WpdFixedFunctionToken, WpdSingleByteFunctionToken, WpdToken, WpdVariableFunctionToken, tokeniseDocumentArea } from "./stream/tokenise.cjs";
|
|
11
11
|
import { EOL_GROUP, FIRST_SINGLE_BYTE_EOL, LAST_SINGLE_BYTE_EOL, WpdEolMapping, eolMappingForSubfunction, isSingleByteEol, subfunctionForSingleByteEol } from "./stream/eol.cjs";
|
|
@@ -16,4 +16,4 @@ import { COLUMN_GROUP, COLUMN_LEFT_MARGIN_SET, COLUMN_RIGHT_MARGIN_SET, DEFAULT_
|
|
|
16
16
|
import { TAB_GROUP, WpdTabEffect, tabEffectFor } from "./stream/tab.cjs";
|
|
17
17
|
import { DISPLAY_NUMBER_GROUP, STYLE_GROUP, WpdStyleSemantics, isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isStyleScopeCloser, isStyleScopeOpener, readDisplayNumberLevel, readSystemStyleNumber, styleSemanticsFor } from "./stream/style.cjs";
|
|
18
18
|
import { CELL_FILL_COLORS_SUBFUNCTION, CELL_INFORMATION_SUBFUNCTION, CELL_SPANNING_SUBFUNCTION, CHARACTER_DEFINE_TABLE_END, CHARACTER_TABLE_COLUMN, CHARACTER_TABLE_DEFINITION, ROW_INFORMATION_SUBFUNCTION, WpdCellFill, WpdCellInformation, WpdCellSpanning, WpdEmbeddedSubfunction, WpdEmbeddedSubfunctions, WpdRowInformation, findEmbeddedSubfunction, readCellFill, readCellInformation, readCellSpanning, readEmbeddedSubfunctions, readRowInformation, readTableColumnWidthPt } from "./stream/table.cjs";
|
|
19
|
-
export { ATTRIBUTE_OFF, ATTRIBUTE_ON, CELL_FILL_COLORS_SUBFUNCTION, CELL_INFORMATION_SUBFUNCTION, CELL_SPANNING_SUBFUNCTION, CHARACTER_DEFINE_TABLE_END, CHARACTER_TABLE_COLUMN, CHARACTER_TABLE_DEFINITION, COLUMN_GROUP, COLUMN_LEFT_MARGIN_SET, COLUMN_RIGHT_MARGIN_SET, DEFAULT_MARGIN_PT, DEFAULT_PAGE_HEIGHT_PT, DEFAULT_PAGE_WIDTH_PT, DISPLAY_NUMBER_GROUP, EOL_GROUP, FIRST_ASCII_CHARACTER, FIRST_FIXED_FUNCTION, FIRST_SINGLE_BYTE_EOL, FIRST_SINGLE_BYTE_FUNCTION, FIRST_VARIABLE_FUNCTION, LAST_CHARACTER, LAST_SINGLE_BYTE_EOL, NOOP_WPD_DIAGNOSTIC_SINK, PACKET_TYPE_DESIRED_FONT_DESCRIPTOR, PACKET_TYPE_EXTENDED_DOCUMENT_SUMMARY, PAGE_BOTTOM_MARGIN_SET, PAGE_FORM, PAGE_GROUP, PAGE_TOP_MARGIN_SET, PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, POINTS_PER_INCH, ROW_INFORMATION_SUBFUNCTION, type ReadWpdOptions, STYLE_GROUP, TAB_GROUP, UNMAPPED_CHARACTER, WPD_FILE_EXTENSION, WPD_FILE_ID, WPD_INDEX_RECORD_SIZE, WPD_MEDIA_TYPE, WPD_PREFIX_HEADER_SIZE, WPU_PER_INCH, WpdAttribute, type WpdAttributeCode, WpdBytesSchema, type WpdCellFill, type WpdCellInformation, type WpdCellSpanning, type WpdCharacterToken, type WpdDiagnostic, WpdDiagnosticCodes, type WpdDiagnosticSink, type WpdDocumentContainer, type WpdEmbeddedSubfunction, type WpdEmbeddedSubfunctions, WpdEncryptedDocumentError, type WpdEolMapping, type WpdFileHeader, type WpdFixedFunctionToken, WpdFormatError, WpdNotAWordPerfectFileError, type WpdPageForm, type WpdPrefixPacket, type WpdRowInformation, type WpdRunAttributes, type WpdSingleByteFunctionToken, type WpdStyleSemantics, type WpdTabEffect, type WpdToken, WpdUnsupportedVersionError, type WpdVariableFunctionToken, decodeAttributeByte, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter, eolMappingForSubfunction, findEmbeddedSubfunction, hasWordPerfectFileId, isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isSingleByteEol, isStyleScopeCloser, isStyleScopeOpener, openWpdDocument, packetByPrefixId, pointsFromWpu, readCellFill, readCellInformation, readCellSpanning, readDisplayNumberLevel, readDocumentSummary, readEmbeddedSubfunctions, readFileHeader, readMarginPt, readPageForm, readPrefixPackets, readRowInformation, readSystemStyleNumber, readTableColumnWidthPt, readTypefaceName, readWpd, readWpdContent, runAttributesFrom, styleSemanticsFor, subfunctionForSingleByteEol, tabEffectFor, tokeniseDocumentArea, wpdContentCodec };
|
|
19
|
+
export { ATTRIBUTE_OFF, ATTRIBUTE_ON, CELL_FILL_COLORS_SUBFUNCTION, CELL_INFORMATION_SUBFUNCTION, CELL_SPANNING_SUBFUNCTION, CHARACTER_DEFINE_TABLE_END, CHARACTER_TABLE_COLUMN, CHARACTER_TABLE_DEFINITION, COLUMN_GROUP, COLUMN_LEFT_MARGIN_SET, COLUMN_RIGHT_MARGIN_SET, DEFAULT_MARGIN_PT, DEFAULT_PAGE_HEIGHT_PT, DEFAULT_PAGE_WIDTH_PT, DISPLAY_NUMBER_GROUP, EOL_GROUP, FIRST_ASCII_CHARACTER, FIRST_FIXED_FUNCTION, FIRST_SINGLE_BYTE_EOL, FIRST_SINGLE_BYTE_FUNCTION, FIRST_VARIABLE_FUNCTION, LAST_CHARACTER, LAST_SINGLE_BYTE_EOL, NOOP_WPD_DIAGNOSTIC_SINK, PACKET_TYPE_DESIRED_FONT_DESCRIPTOR, PACKET_TYPE_EXTENDED_DOCUMENT_SUMMARY, PAGE_BOTTOM_MARGIN_SET, PAGE_FORM, PAGE_GROUP, PAGE_TOP_MARGIN_SET, PERFECT_OFFICE_MAIN_STREAM, PERFECT_OFFICE_OBJECTS_STORAGE, POINTS_PER_INCH, ROW_INFORMATION_SUBFUNCTION, type ReadWpdOptions, STYLE_GROUP, TAB_GROUP, UNMAPPED_CHARACTER, WPD_FILE_EXTENSION, WPD_FILE_ID, WPD_INDEX_RECORD_SIZE, WPD_MEDIA_TYPE, WPD_PREFIX_HEADER_SIZE, WPU_PER_INCH, WpdAttribute, type WpdAttributeCode, WpdBytesSchema, type WpdCellFill, type WpdCellInformation, type WpdCellSpanning, type WpdCharacterToken, type WpdDiagnostic, WpdDiagnosticCodes, type WpdDiagnosticSink, type WpdDocumentContainer, type WpdEmbeddedSubfunction, type WpdEmbeddedSubfunctions, WpdEncryptedDocumentError, type WpdEolMapping, type WpdFileHeader, type WpdFixedFunctionToken, WpdFormatError, WpdNotAWordPerfectFileError, type WpdPageForm, type WpdPrefixPacket, type WpdRowInformation, type WpdRunAttributes, type WpdSingleByteFunctionToken, type WpdStyleSemantics, type WpdTabEffect, type WpdToken, WpdUnsupportedVersionError, type WpdVariableFunctionToken, WpdWrongPasswordError, decodeAttributeByte, decodeSingleByteCharacter, decodeWordString, decodeWpCharacter, eolMappingForSubfunction, findEmbeddedSubfunction, hasWordPerfectFileId, isParagraphNumberDisplayOff, isParagraphNumberDisplayOn, isSingleByteEol, isStyleScopeCloser, isStyleScopeOpener, openWpdDocument, packetByPrefixId, pointsFromWpu, readCellFill, readCellInformation, readCellSpanning, readDisplayNumberLevel, readDocumentSummary, readEmbeddedSubfunctions, readFileHeader, readMarginPt, readPageForm, readPrefixPackets, readRowInformation, readSystemStyleNumber, readTableColumnWidthPt, readTypefaceName, readWpd, readWpdContent, runAttributesFrom, styleSemanticsFor, subfunctionForSingleByteEol, tabEffectFor, tokeniseDocumentArea, wpdContentCodec };
|