@awacloud/pdf 0.0.0-stage → 1.0.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/CHANGELOG.md +609 -0
- package/LICENSE +661 -0
- package/NOTICE +77 -0
- package/README.md +363 -2
- package/dist/build/index.js +21 -0
- package/dist/build/pdf-full-rw.js +10972 -0
- package/dist/build/pdf-full-rw.meta.json +105 -0
- package/dist/build/pdf-full-rw.min.js +53 -0
- package/dist/build/pdf-full.js +6078 -0
- package/dist/build/pdf-full.meta.json +90 -0
- package/dist/build/pdf-full.min.js +32 -0
- package/dist/build/pdf-large-rw.js +10367 -0
- package/dist/build/pdf-large-rw.meta.json +99 -0
- package/dist/build/pdf-large-rw.min.js +53 -0
- package/dist/build/pdf-large.js +5473 -0
- package/dist/build/pdf-large.meta.json +84 -0
- package/dist/build/pdf-large.min.js +32 -0
- package/dist/build/pdf-legacy-rw.js +12402 -0
- package/dist/build/pdf-legacy-rw.meta.json +110 -0
- package/dist/build/pdf-legacy-rw.min.js +53 -0
- package/dist/build/pdf-legacy.js +7508 -0
- package/dist/build/pdf-legacy.meta.json +95 -0
- package/dist/build/pdf-legacy.min.js +32 -0
- package/dist/build/pdf-rw.js +7578 -0
- package/dist/build/pdf-rw.meta.json +77 -0
- package/dist/build/pdf-rw.min.js +53 -0
- package/dist/build/pdf.js +2684 -0
- package/dist/build/pdf.meta.json +62 -0
- package/dist/build/pdf.min.js +32 -0
- package/dist/standalone/pdf-full-rw.js +16798 -0
- package/dist/standalone/pdf-full-rw.meta.json +78 -0
- package/dist/standalone/pdf-full-rw.min.js +56 -0
- package/dist/standalone/pdf-full.js +11904 -0
- package/dist/standalone/pdf-full.meta.json +63 -0
- package/dist/standalone/pdf-full.min.js +35 -0
- package/dist/standalone/pdf-large-rw.js +16193 -0
- package/dist/standalone/pdf-large-rw.meta.json +72 -0
- package/dist/standalone/pdf-large-rw.min.js +56 -0
- package/dist/standalone/pdf-large.js +11299 -0
- package/dist/standalone/pdf-large.meta.json +57 -0
- package/dist/standalone/pdf-large.min.js +35 -0
- package/dist/standalone/pdf-legacy-rw.js +18228 -0
- package/dist/standalone/pdf-legacy-rw.meta.json +83 -0
- package/dist/standalone/pdf-legacy-rw.min.js +56 -0
- package/dist/standalone/pdf-legacy.js +13334 -0
- package/dist/standalone/pdf-legacy.meta.json +68 -0
- package/dist/standalone/pdf-legacy.min.js +35 -0
- package/dist/standalone/pdf-rw.js +13404 -0
- package/dist/standalone/pdf-rw.meta.json +50 -0
- package/dist/standalone/pdf-rw.min.js +56 -0
- package/dist/standalone/pdf.js +8510 -0
- package/dist/standalone/pdf.meta.json +35 -0
- package/dist/standalone/pdf.min.js +35 -0
- package/docs/README.md +53 -0
- package/docs/api/README.md +38 -0
- package/docs/api/_shared/README.md +91 -0
- package/docs/api/action/README.md +29 -0
- package/docs/api/action/action.md +81 -0
- package/docs/api/action/goTo.md +66 -0
- package/docs/api/action/launch.md +58 -0
- package/docs/api/action/named.md +55 -0
- package/docs/api/action/uri.md +54 -0
- package/docs/api/annot/README.md +53 -0
- package/docs/api/annot/annot.md +114 -0
- package/docs/api/annot/fileAttach.md +53 -0
- package/docs/api/annot/freeText.md +68 -0
- package/docs/api/annot/ink.md +69 -0
- package/docs/api/annot/link.md +74 -0
- package/docs/api/annot/markup.md +83 -0
- package/docs/api/annot/popup.md +52 -0
- package/docs/api/annot/projection.md +56 -0
- package/docs/api/annot/redact.md +67 -0
- package/docs/api/annot/square.md +87 -0
- package/docs/api/annot/stamp.md +54 -0
- package/docs/api/annot/text.md +69 -0
- package/docs/api/annot/widget.md +69 -0
- package/docs/api/associatedFiles/README.md +9 -0
- package/docs/api/associatedFiles/associatedFiles.md +78 -0
- package/docs/api/bundles/README.md +68 -0
- package/docs/api/bundles/dist-matrix.md +165 -0
- package/docs/api/bundles/pdf-full.md +148 -0
- package/docs/api/bundles/pdf-large.md +144 -0
- package/docs/api/bundles/pdf-legacy.md +169 -0
- package/docs/api/content/README.md +29 -0
- package/docs/api/content/color.md +99 -0
- package/docs/api/content/graphics.md +114 -0
- package/docs/api/content/images.md +124 -0
- package/docs/api/content/ops.md +100 -0
- package/docs/api/content/stream.md +107 -0
- package/docs/api/content/text.md +98 -0
- package/docs/api/crypto/README.md +29 -0
- package/docs/api/crypto/aesGcm.md +72 -0
- package/docs/api/crypto/permissions.md +79 -0
- package/docs/api/crypto/security.md +98 -0
- package/docs/api/crypto/standardV4.md +104 -0
- package/docs/api/crypto/standardV5.md +84 -0
- package/docs/api/crypto/standardV6.md +93 -0
- package/docs/api/destination/README.md +9 -0
- package/docs/api/destination/destination.md +79 -0
- package/docs/api/document/README.md +29 -0
- package/docs/api/document/builder.md +281 -0
- package/docs/api/document/catalog.md +98 -0
- package/docs/api/document/document.md +187 -0
- package/docs/api/document/encryptedWriter.md +149 -0
- package/docs/api/document/incrementalWriter.md +148 -0
- package/docs/api/document/page.md +99 -0
- package/docs/api/document/pages.md +82 -0
- package/docs/api/document/resources.md +102 -0
- package/docs/api/document/writer.md +157 -0
- package/docs/api/document/xrefStreamWriter.md +122 -0
- package/docs/api/embedded/README.md +13 -0
- package/docs/api/embedded/collection.md +80 -0
- package/docs/api/embedded/embeddedFile.md +86 -0
- package/docs/api/embedded/fileSpec.md +87 -0
- package/docs/api/errors.md +110 -0
- package/docs/api/extra/3d-richmedia.md +76 -0
- package/docs/api/extra/README.md +99 -0
- package/docs/api/extra/annot-extended.md +71 -0
- package/docs/api/extra/associated-files.md +70 -0
- package/docs/api/extra/ccitt-fax-decoder.md +74 -0
- package/docs/api/extra/color-spaces-extended.md +72 -0
- package/docs/api/extra/content-ops-extended.md +82 -0
- package/docs/api/extra/document-parts.md +69 -0
- package/docs/api/extra/embedded-files-portfolio.md +87 -0
- package/docs/api/extra/font-cid-typed.md +77 -0
- package/docs/api/extra/font-color-tagging.md +76 -0
- package/docs/api/extra/form-actions-extended.md +75 -0
- package/docs/api/extra/info-dict-deprecated.md +72 -0
- package/docs/api/extra/jbig2-read.md +80 -0
- package/docs/api/extra/legacy-deprecated-annots.md +89 -0
- package/docs/api/extra/legacy-deprecated-filters.md +78 -0
- package/docs/api/extra/legacy-rc4-read.md +74 -0
- package/docs/api/extra/legacy-xfa-read.md +65 -0
- package/docs/api/extra/linearization-write.md +71 -0
- package/docs/api/extra/misc.md +93 -0
- package/docs/api/extra/optional-content-extended.md +83 -0
- package/docs/api/extra/pdf-a-output-intent.md +65 -0
- package/docs/api/extra/pdf-sandbox.md +76 -0
- package/docs/api/extra/pdf-ua-tagged.md +63 -0
- package/docs/api/extra/pdf-x-prepress.md +65 -0
- package/docs/api/extra/redaction-iso32005.md +65 -0
- package/docs/api/extra/shading-typed.md +73 -0
- package/docs/api/extra/sig-aes-gcm.md +69 -0
- package/docs/api/extra/sig-pades.md +103 -0
- package/docs/api/extra/tagged-pdf-typed.md +78 -0
- package/docs/api/extra/transparency-typed.md +74 -0
- package/docs/api/extra/well-tagged-pdf.md +61 -0
- package/docs/api/extra/xmp-extended.md +65 -0
- package/docs/api/font/README.md +25 -0
- package/docs/api/font/embed.md +157 -0
- package/docs/api/font/encoding.md +95 -0
- package/docs/api/font/font.md +97 -0
- package/docs/api/font/type3.md +89 -0
- package/docs/api/form/README.md +35 -0
- package/docs/api/form/acroform.md +88 -0
- package/docs/api/form/appearance.md +87 -0
- package/docs/api/form/button.md +97 -0
- package/docs/api/form/choice.md +96 -0
- package/docs/api/form/fieldTree.md +93 -0
- package/docs/api/form/signature.md +90 -0
- package/docs/api/form/text.md +88 -0
- package/docs/api/linearization/README.md +11 -0
- package/docs/api/linearization/linearization.md +81 -0
- package/docs/api/main.md +116 -0
- package/docs/api/metadata/README.md +10 -0
- package/docs/api/metadata/info.md +70 -0
- package/docs/api/metadata/xmp.md +62 -0
- package/docs/api/ocg/README.md +23 -0
- package/docs/api/ocg/config.md +95 -0
- package/docs/api/ocg/ocg.md +77 -0
- package/docs/api/outline/README.md +11 -0
- package/docs/api/outline/outline.md +107 -0
- package/docs/api/pdf.md +152 -0
- package/docs/api/prepress/README.md +10 -0
- package/docs/api/prepress/outputIntent.md +79 -0
- package/docs/api/prepress/pageBoundary.md +75 -0
- package/docs/api/sig/README.md +32 -0
- package/docs/api/sig/byteRange.md +120 -0
- package/docs/api/sig/certChain.md +84 -0
- package/docs/api/sig/dss.md +111 -0
- package/docs/api/sig/oids.md +76 -0
- package/docs/api/sig/sha1.md +72 -0
- package/docs/api/sig/sign.md +317 -0
- package/docs/api/sig/signature.md +178 -0
- package/docs/api/sig/timestamp.md +84 -0
- package/docs/api/syntax/README.md +29 -0
- package/docs/api/syntax/crossRefStream.md +115 -0
- package/docs/api/syntax/filters/README.md +50 -0
- package/docs/api/syntax/filters/ascii85.md +76 -0
- package/docs/api/syntax/filters/asciiHex.md +73 -0
- package/docs/api/syntax/filters/dispatch.md +125 -0
- package/docs/api/syntax/filters/flate.md +134 -0
- package/docs/api/syntax/filters/runLength.md +78 -0
- package/docs/api/syntax/objStream.md +88 -0
- package/docs/api/syntax/parser-obj.md +97 -0
- package/docs/api/syntax/parser.md +151 -0
- package/docs/api/syntax/serializer.md +109 -0
- package/docs/api/syntax/tokenizer.md +104 -0
- package/docs/api/syntax/trailer.md +85 -0
- package/docs/api/syntax/xref.md +139 -0
- package/docs/api/tagged/README.md +25 -0
- package/docs/api/tagged/classMap.md +67 -0
- package/docs/api/tagged/markedContent.md +62 -0
- package/docs/api/tagged/parentTree.md +67 -0
- package/docs/api/tagged/roleMap.md +67 -0
- package/docs/api/tagged/structElement.md +76 -0
- package/docs/api/tagged/structTree.md +75 -0
- package/docs/guide/coverage.md +113 -0
- package/docs/guide/crypto.md +121 -0
- package/docs/guide/extending.md +76 -0
- package/docs/guide/getting-started.md +75 -0
- package/docs/guide/legacy-1.7.md +42 -0
- package/docs/guide/pades-integration.md +579 -0
- package/docs/guide/read-pdf.md +89 -0
- package/package.json +97 -4
- package/src/_shared/index.js +179 -0
- package/src/action/action.js +119 -0
- package/src/action/goTo.js +89 -0
- package/src/action/launch.js +61 -0
- package/src/action/named.js +54 -0
- package/src/action/uri.js +51 -0
- package/src/annot/annot.js +212 -0
- package/src/annot/fileAttach.js +55 -0
- package/src/annot/freeText.js +82 -0
- package/src/annot/ink.js +77 -0
- package/src/annot/link.js +77 -0
- package/src/annot/markup.js +91 -0
- package/src/annot/popup.js +53 -0
- package/src/annot/projection.js +52 -0
- package/src/annot/redact.js +87 -0
- package/src/annot/square.js +132 -0
- package/src/annot/stamp.js +48 -0
- package/src/annot/text.js +54 -0
- package/src/annot/widget.js +61 -0
- package/src/associatedFiles/associatedFiles.js +86 -0
- package/src/bundles/pdf-full.js +91 -0
- package/src/bundles/pdf-large.js +81 -0
- package/src/bundles/pdf-legacy.js +107 -0
- package/src/content/color.js +114 -0
- package/src/content/graphics.js +192 -0
- package/src/content/images.js +160 -0
- package/src/content/ops.js +137 -0
- package/src/content/stream.js +154 -0
- package/src/content/text.js +125 -0
- package/src/crypto/aesGcm.js +123 -0
- package/src/crypto/permissions.js +112 -0
- package/src/crypto/security.js +327 -0
- package/src/crypto/standardV4.js +443 -0
- package/src/crypto/standardV5.js +306 -0
- package/src/crypto/standardV6.js +334 -0
- package/src/destination/destination.js +183 -0
- package/src/document/builder.js +618 -0
- package/src/document/catalog.js +100 -0
- package/src/document/document.js +472 -0
- package/src/document/encryptedWriter.js +554 -0
- package/src/document/incrementalWriter.js +514 -0
- package/src/document/page.js +131 -0
- package/src/document/pages.js +103 -0
- package/src/document/resources.js +146 -0
- package/src/document/writer.js +211 -0
- package/src/document/xrefStreamWriter.js +353 -0
- package/src/embedded/collection.js +102 -0
- package/src/embedded/embeddedFile.js +99 -0
- package/src/embedded/fileSpec.js +137 -0
- package/src/errors.js +78 -0
- package/src/extra/3d-richmedia.js +171 -0
- package/src/extra/annot-extended.js +200 -0
- package/src/extra/associated-files.js +131 -0
- package/src/extra/ccitt-fax-decoder.js +776 -0
- package/src/extra/color-spaces-extended.js +196 -0
- package/src/extra/content-ops-extended.js +153 -0
- package/src/extra/document-parts.js +149 -0
- package/src/extra/embedded-files-portfolio.js +234 -0
- package/src/extra/font-cid-typed.js +185 -0
- package/src/extra/font-color-tagging.js +144 -0
- package/src/extra/form-actions-extended.js +196 -0
- package/src/extra/info-dict-deprecated.js +137 -0
- package/src/extra/jbig2-read.js +169 -0
- package/src/extra/legacy-deprecated-annots.js +198 -0
- package/src/extra/legacy-deprecated-filters.js +167 -0
- package/src/extra/legacy-rc4-read.js +235 -0
- package/src/extra/legacy-xfa-read.js +104 -0
- package/src/extra/linearization-write.js +97 -0
- package/src/extra/misc.js +217 -0
- package/src/extra/optional-content-extended.js +142 -0
- package/src/extra/pdf-a-output-intent.js +112 -0
- package/src/extra/pdf-sandbox.js +88 -0
- package/src/extra/pdf-ua-tagged.js +116 -0
- package/src/extra/pdf-x-prepress.js +114 -0
- package/src/extra/redaction-iso32005.js +136 -0
- package/src/extra/shading-typed.js +222 -0
- package/src/extra/sig-aes-gcm.js +135 -0
- package/src/extra/sig-pades.js +242 -0
- package/src/extra/tagged-pdf-typed.js +203 -0
- package/src/extra/transparency-typed.js +135 -0
- package/src/extra/well-tagged-pdf.js +138 -0
- package/src/extra/xmp-extended.js +190 -0
- package/src/font/embed.js +480 -0
- package/src/font/encoding.js +92 -0
- package/src/font/font.js +101 -0
- package/src/font/type3.js +75 -0
- package/src/form/acroform.js +94 -0
- package/src/form/appearance.js +90 -0
- package/src/form/button.js +105 -0
- package/src/form/choice.js +152 -0
- package/src/form/fieldTree.js +120 -0
- package/src/form/signature.js +100 -0
- package/src/form/text.js +101 -0
- package/src/linearization/linearization.js +107 -0
- package/src/main.js +411 -0
- package/src/metadata/info.js +87 -0
- package/src/metadata/xmp.js +62 -0
- package/src/ocg/config.js +156 -0
- package/src/ocg/ocg.js +124 -0
- package/src/outline/outline.js +157 -0
- package/src/pdf.js +133 -0
- package/src/prepress/outputIntent.js +118 -0
- package/src/prepress/pageBoundary.js +108 -0
- package/src/sig/byteRange.js +306 -0
- package/src/sig/certChain.js +247 -0
- package/src/sig/dss.js +317 -0
- package/src/sig/oids.js +157 -0
- package/src/sig/sha1.js +142 -0
- package/src/sig/sign.js +1899 -0
- package/src/sig/signature.js +1441 -0
- package/src/sig/timestamp.js +236 -0
- package/src/syntax/crossRefStream.js +133 -0
- package/src/syntax/filters/ascii85.js +122 -0
- package/src/syntax/filters/asciiHex.js +83 -0
- package/src/syntax/filters/dispatch.js +176 -0
- package/src/syntax/filters/flate.js +316 -0
- package/src/syntax/filters/runLength.js +96 -0
- package/src/syntax/objStream.js +99 -0
- package/src/syntax/parser-obj.js +52 -0
- package/src/syntax/parser.js +321 -0
- package/src/syntax/serializer.js +221 -0
- package/src/syntax/tokenizer.js +290 -0
- package/src/syntax/trailer.js +76 -0
- package/src/syntax/xref.js +341 -0
- package/src/tagged/classMap.js +81 -0
- package/src/tagged/markedContent.js +123 -0
- package/src/tagged/parentTree.js +126 -0
- package/src/tagged/roleMap.js +107 -0
- package/src/tagged/structElement.js +138 -0
- package/src/tagged/structTree.js +94 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfContentOps
|
|
3
|
+
category: pdf/content
|
|
4
|
+
dependencies: []
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfContentOps
|
|
11
|
+
|
|
12
|
+
> Exhaustive catalogue of content-stream operators — ISO 32000-2 §8.2 Table 60 + §9.4.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfContentOps` | **Source** `packages/front/office/pdf/src/content/ops.js` | **Deps** none | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Single source of truth for the PDF operator mnemonics, their **category**
|
|
17
|
+
(`gstate`, `path`, `paint`, `clip`, `color`, `shading`, `image`, `xobject`,
|
|
18
|
+
`marked`, `text`) and their expected **arity**. Consumed by `pdfContentStream`
|
|
19
|
+
for categorisation, and by any linter wanting to validate a stream's coherence.
|
|
20
|
+
71 operators are registered.
|
|
21
|
+
|
|
22
|
+
## Resolve
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
const opsMod = runtime.resolve('pdfContentOps');
|
|
26
|
+
// Returns: { OPS, OP_NAMES, lookupOp, isOp }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## API
|
|
30
|
+
|
|
31
|
+
| Member | Signature | Returns |
|
|
32
|
+
|--------|-----------|---------|
|
|
33
|
+
| `OPS` | `Object<string, OpRecord>` (frozen) | Full table, keyed by mnemonic. |
|
|
34
|
+
| `OP_NAMES` | `string[]` (frozen) | Alphabetically sorted list (71 entries). |
|
|
35
|
+
| `lookupOp` | `(mnemonic: string) => OpRecord \| undefined` | Direct lookup. |
|
|
36
|
+
| `isOp` | `(mnemonic: string) => boolean` | Membership test. |
|
|
37
|
+
|
|
38
|
+
### `OpRecord` shape
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
{ op: string, category: string, arity: number | 'var', desc: string }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`arity` is `'var'` for exactly four operators — `SC`, `sc`, `SCN`, `scn` —
|
|
45
|
+
whose operand count depends on the current colour space. `TJ` has arity `1`
|
|
46
|
+
(the single positioning array).
|
|
47
|
+
|
|
48
|
+
### Categories covered
|
|
49
|
+
|
|
50
|
+
| Category | §ISO | Count | Operators |
|
|
51
|
+
|----------|------|-------|-----------|
|
|
52
|
+
| `gstate` | §8.4 | 13 | `q`, `Q`, `cm`, `w`, `J`, `j`, `M`, `d`, `ri`, `i`, `gs`, `d0`, `d1` |
|
|
53
|
+
| `path` | §8.5.2 | 7 | `m`, `l`, `c`, `v`, `y`, `h`, `re` |
|
|
54
|
+
| `paint` | §8.5.3 | 10 | `S`, `s`, `f`, `F`, `f*`, `B`, `B*`, `b`, `b*`, `n` |
|
|
55
|
+
| `clip` | §8.5.4 | 2 | `W`, `W*` |
|
|
56
|
+
| `color` | §8.6 | 12 | `CS`, `cs`, `SC`, `sc`, `SCN`, `scn`, `G`, `g`, `RG`, `rg`, `K`, `k` |
|
|
57
|
+
| `shading` | §8.7 | 1 | `sh` |
|
|
58
|
+
| `image` | §8.9.7 | 3 | `BI`, `ID`, `EI` |
|
|
59
|
+
| `xobject` | §8.10 | 1 | `Do` |
|
|
60
|
+
| `marked` | §14.6 | 5 | `MP`, `DP`, `BMC`, `BDC`, `EMC` |
|
|
61
|
+
| `text` | §9.3 / §9.4 | 17 | `BT`, `ET`, `Tc`, `Tw`, `Tz`, `TL`, `Tf`, `Tr`, `Ts`, `Td`, `TD`, `Tm`, `T*`, `Tj`, `'`, `"`, `TJ` |
|
|
62
|
+
|
|
63
|
+
## Examples
|
|
64
|
+
|
|
65
|
+
### Lookup
|
|
66
|
+
|
|
67
|
+
```js
|
|
68
|
+
const { lookupOp, isOp } = runtime.resolve('pdfContentOps');
|
|
69
|
+
lookupOp('Tj'); // { op: 'Tj', category: 'text', arity: 1, desc: 'show text' }
|
|
70
|
+
isOp('xyz'); // false
|
|
71
|
+
isOp('cm'); // true
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Iterating by category
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
const { OPS } = runtime.resolve('pdfContentOps');
|
|
78
|
+
const textOps = Object.values(OPS).filter(o => o.category === 'text');
|
|
79
|
+
textOps.length; // 17
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Validating an operator's arity
|
|
83
|
+
|
|
84
|
+
```js
|
|
85
|
+
const rec = lookupOp(op.op);
|
|
86
|
+
if (rec.arity !== 'var' && op.args.length !== rec.arity) {
|
|
87
|
+
throw new Error(`${op.op}: expected ${rec.arity} args, got ${op.args.length}`);
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Errors
|
|
92
|
+
|
|
93
|
+
A table module with no I/O — it emits no `PdfError`. Consumers
|
|
94
|
+
(`pdfContentStream`, linters) surface their own errors.
|
|
95
|
+
|
|
96
|
+
## See also
|
|
97
|
+
|
|
98
|
+
- [`pdfContentStream`](./stream.md) — consumes `isOp` to recognise operators.
|
|
99
|
+
- [`pdfGraphics`](./graphics.md), [`pdfText`](./text.md), [`pdfColor`](./color.md) — dispatch by category.
|
|
100
|
+
- [`pdfImages`](./images.md) — types the XObjects invoked by `Do`.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfContentStream
|
|
3
|
+
category: pdf/content
|
|
4
|
+
dependencies: [pdfErrors, pdfParser, pdfContentOps]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfContentStream
|
|
11
|
+
|
|
12
|
+
> Content-stream parser — decoded `Uint8Array` → ordered list of typed operations. ISO 32000-2 §7.8 + §8.2 + Table 60.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfContentStream` | **Source** `packages/front/office/pdf/src/content/stream.js` | **Deps** `pdfErrors`, `pdfParser`, `pdfContentOps` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Reads the bytes of an **already decoded** content stream (the `/Filter` chain
|
|
17
|
+
must have been applied by `pdfFilterDispatch` upstream) and produces
|
|
18
|
+
`[{ op, args, data? }]`. Operands stay **typed** (`{ type, value, … }`) — a `Tj`
|
|
19
|
+
carries its typed `string`, ready for ToUnicode resolution; a `gs` carries its
|
|
20
|
+
`name`, usable directly against `/Resources /ExtGState`. Inline images
|
|
21
|
+
`BI … ID … EI` (§8.9.7) are captured as a single synthetic op with
|
|
22
|
+
`data: Uint8Array`.
|
|
23
|
+
|
|
24
|
+
## Resolve
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
const csMod = runtime.resolve('pdfContentStream');
|
|
28
|
+
// Returns: { parseContentStream }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
| Method | Signature | Returns |
|
|
34
|
+
|--------|-----------|---------|
|
|
35
|
+
| `parseContentStream` | `(bytes: Uint8Array) => Op[]` | Ordered list of operations. |
|
|
36
|
+
|
|
37
|
+
### `Op` shape
|
|
38
|
+
|
|
39
|
+
```js
|
|
40
|
+
{
|
|
41
|
+
op: string, // mnemonic (e.g. 'Tj', 'cm', 'BI', '__trailing__')
|
|
42
|
+
args: PdfObject[], // typed operands, in stack order
|
|
43
|
+
data?: Uint8Array // present only for 'BI' (raw image data)
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
A synthetic `{ op: '__trailing__', args }` is appended when the stream ends on
|
|
48
|
+
unconsumed operands — this preserves rewrite fidelity.
|
|
49
|
+
|
|
50
|
+
### Inline images
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
{
|
|
54
|
+
op: 'BI',
|
|
55
|
+
args: [{ type: 'dict', entries: { Width, Height, ColorSpace, Filter, … } }],
|
|
56
|
+
data: Uint8Array // raw bytes between `ID\n` and the space before `EI`
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Examples
|
|
61
|
+
|
|
62
|
+
### Parse a minimal stream
|
|
63
|
+
|
|
64
|
+
```js
|
|
65
|
+
const cs = runtime.resolve('pdfContentStream');
|
|
66
|
+
const bytes = new TextEncoder().encode('BT /F1 12 Tf (Hello) Tj ET');
|
|
67
|
+
const ops = cs.parseContentStream(bytes);
|
|
68
|
+
// → [{op:'BT',args:[]}, {op:'Tf',args:[name,int]}, {op:'Tj',args:[string]}, {op:'ET',args:[]}]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Extract the font names in use
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
const fonts = new Set();
|
|
75
|
+
for (const op of ops) {
|
|
76
|
+
if (op.op === 'Tf') fonts.add(op.args[0].value); // args[0] = name
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Inline image
|
|
81
|
+
|
|
82
|
+
```js
|
|
83
|
+
const ops = cs.parseContentStream(streamBytes);
|
|
84
|
+
const img = ops.find(o => o.op === 'BI');
|
|
85
|
+
img.args[0].entries.W; // typed int
|
|
86
|
+
img.data; // Uint8Array — feed to pdfFilterDispatch when /F is set
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Errors
|
|
90
|
+
|
|
91
|
+
| Code | Class | When |
|
|
92
|
+
|------|-------|------|
|
|
93
|
+
| `pdf/content/bad-input` | `ParseError` | Argument is not a `Uint8Array`. |
|
|
94
|
+
| `pdf/content/unknown-op` | `ParseError` | Unknown mnemonic (absent from `pdfContentOps`). |
|
|
95
|
+
| `pdf/content/inline-image/no-ID` | `ParseError` | `BI` without a matching `ID`. |
|
|
96
|
+
| `pdf/content/inline-image/bad-key` | `ParseError` | Non-`name` key in the inline dictionary. |
|
|
97
|
+
| `pdf/content/inline-image/no-EI` | `ParseError` | `ID` without a matching `EI`. |
|
|
98
|
+
|
|
99
|
+
It also propagates the `pdf/parser/*` codes while parsing operands.
|
|
100
|
+
|
|
101
|
+
## See also
|
|
102
|
+
|
|
103
|
+
- [`pdfContentOps`](./ops.md) — operator table.
|
|
104
|
+
- [`pdfGraphics`](./graphics.md) — applies the `gstate` ops.
|
|
105
|
+
- [`pdfText`](./text.md) — decodes the `text` ops.
|
|
106
|
+
- [`pdfColor`](./color.md) — applies the `color` ops.
|
|
107
|
+
- [`pdfImages`](./images.md) — types the XObjects (`Do`).
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfText
|
|
3
|
+
category: pdf/content
|
|
4
|
+
dependencies: [pdfErrors]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfText
|
|
11
|
+
|
|
12
|
+
> Text state + Tm/Tlm matrices + Unicode extraction — ISO 32000-2 §9.3 / §9.4.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfText` | **Source** `packages/front/office/pdf/src/content/text.js` | **Deps** `pdfErrors` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Applies the operators that mutate `gstate.text` (`Tf`, `BT`, `Td`, `TD`, `Tm`,
|
|
17
|
+
`T*`) and exposes `extractText`, which decodes a `Tj`/`TJ`/`'`/`"` operand into
|
|
18
|
+
Unicode through a caller-supplied `cidToUnicode` function (typically built from
|
|
19
|
+
`@awacloud/fonts`' `cmapToUnicode` module, `@awacloud/fonts/cmap-to-unicode`). ToUnicode
|
|
20
|
+
resolution is deliberately **not** done here, so the module stays worker-safe
|
|
21
|
+
with no font dependency.
|
|
22
|
+
|
|
23
|
+
## Resolve
|
|
24
|
+
|
|
25
|
+
```js
|
|
26
|
+
const t = runtime.resolve('pdfText');
|
|
27
|
+
// Returns: { setFont, beginTextObject, td, tdSetLeading,
|
|
28
|
+
// setTextMatrix, nextLine, rawStringBytes, extractText }
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## API
|
|
32
|
+
|
|
33
|
+
| Method | Signature | Returns |
|
|
34
|
+
|--------|-----------|---------|
|
|
35
|
+
| `setFont` | `(gstate, fontResource: string, size: number) => void` | Applies `Tf`. |
|
|
36
|
+
| `beginTextObject` | `() => { Tm, Tlm }` | Initialises `BT` — both matrices identity. |
|
|
37
|
+
| `td` | `(state, tx, ty) => void` | Operator `Td`. |
|
|
38
|
+
| `tdSetLeading` | `(gstate, state, tx, ty) => void` | Operator `TD` — also sets `gstate.text.leading = -ty`. |
|
|
39
|
+
| `setTextMatrix` | `(state, m: number[6]) => void` | Operator `Tm`. |
|
|
40
|
+
| `nextLine` | `(gstate, state) => void` | Operator `T*`. |
|
|
41
|
+
| `rawStringBytes` | `(stringObj) => Uint8Array` | Raw bytes of a typed `string` operand. |
|
|
42
|
+
| `extractText` | `(op, font, cidToUnicode) => string` | Decodes `Tj`/`TJ`/`'`/`"`. |
|
|
43
|
+
|
|
44
|
+
`state` is the `{ Tm, Tlm }` record returned by `beginTextObject`; `gstate` is a
|
|
45
|
+
graphics state from [`pdfGraphics`](./graphics.md), whose `text` sub-object is
|
|
46
|
+
mutated in place.
|
|
47
|
+
|
|
48
|
+
### `extractText`
|
|
49
|
+
|
|
50
|
+
- Single-byte fonts (`font.subtype !== 'Type0'`): each byte is a CID.
|
|
51
|
+
- CID fonts (`font.subtype === 'Type0'`): big-endian byte pairs.
|
|
52
|
+
- Numbers inside a `TJ` array (positioning adjustments) contribute no text.
|
|
53
|
+
- The `"` operator reads its string from `args[2]`; `Tj` and `'` from `args[0]`.
|
|
54
|
+
- A glyph with no ToUnicode mapping yields the replacement character `'�'`.
|
|
55
|
+
|
|
56
|
+
## Examples
|
|
57
|
+
|
|
58
|
+
### Minimal extraction pipeline
|
|
59
|
+
|
|
60
|
+
```js
|
|
61
|
+
const t = runtime.resolve('pdfText');
|
|
62
|
+
const state = t.beginTextObject();
|
|
63
|
+
let acc = '';
|
|
64
|
+
for (const op of ops) {
|
|
65
|
+
if (op.op === 'Tf') t.setFont(gstate, op.args[0].value, op.args[1].value);
|
|
66
|
+
else if (op.op === 'Td') t.td(state, op.args[0].value, op.args[1].value);
|
|
67
|
+
else if (op.op === 'Tj' || op.op === 'TJ') {
|
|
68
|
+
acc += t.extractText(op, currentFont, cidToUnicode);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Set the text matrix
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
t.setTextMatrix(state, [1, 0, 0, 1, 72, 720]); // (72, 720) in user space
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Raw bytes for an external ToUnicode
|
|
80
|
+
|
|
81
|
+
```js
|
|
82
|
+
const raw = t.rawStringBytes(op.args[0]); // Uint8Array
|
|
83
|
+
const text = customCmap.decode(raw);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Errors
|
|
87
|
+
|
|
88
|
+
| Code | Class | When |
|
|
89
|
+
|------|-------|------|
|
|
90
|
+
| `pdf/text/bad-matrix` | `ContractError` | `Tm` matrix is not 6 elements. |
|
|
91
|
+
| `pdf/text/bad-string` | `ContractError` | `rawStringBytes` given something other than a `{type:'string'}`. |
|
|
92
|
+
|
|
93
|
+
## See also
|
|
94
|
+
|
|
95
|
+
- [`pdfContentStream`](./stream.md) — produces the `Tj`/`TJ` ops.
|
|
96
|
+
- [`pdfGraphics`](./graphics.md) — hosts `gstate.text`.
|
|
97
|
+
- [`pdfFont`](../font/font.md) — supplies `subtype` to `extractText`.
|
|
98
|
+
- [`pdfFontEncoding`](../font/encoding.md) — `/Encoding` resolution.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Crypto — ISO 32000-2 §7.6 + ISO TS 32003
|
|
2
|
+
|
|
3
|
+
Encryption handlers and permissions. All modules are `fwModules`; the handlers' fw-crypto deps resolve from `@awacloud/fw/crypto`.
|
|
4
|
+
|
|
5
|
+
| Module | Returns | Deps | Description |
|
|
6
|
+
|--------|----------|------|-------------|
|
|
7
|
+
| [`pdfSecurity`](./security.md) | `{ typeEncryptDict, selectHandler, isEmbeddedFileStream, dispatchDecryptStream }` | `pdfErrors` | Dispatch, §7.6.2. |
|
|
8
|
+
| [`pdfStandardV4`](./standardV4.md) | `{ tryPassword, decryptString, decryptStream, decryptEmbeddedFile, encryptEmbeddedFile, encryptString, encryptStream, buildOU, buildPerms, computeFileKey, computeU, computeO, objectKey, rc4, md5, padPassword, PASSWORD_PADDING }` | `pdfErrors`, `aes`, `cbc`, `bitArray` | PDF 1.6 legacy — RC4-128 / AES-128-CBC. |
|
|
9
|
+
| [`pdfStandardV5`](./standardV5.md) | `{ tryPassword, decryptString, decryptStream, encryptString, encryptStream, buildUUE, buildOOE, buildPerms }` | `pdfErrors`, fw crypto, `pdfAesGcm`? | Historical R=5 AES-256. |
|
|
10
|
+
| [`pdfStandardV6`](./standardV6.md) | `{ tryPassword, decryptString, decryptStream, encryptString, encryptStream, buildUUE, buildOOE, buildPerms }` | `pdfErrors`, fw crypto, `pdfAesGcm`? | R=6 hardening, §7.6.4. |
|
|
11
|
+
| [`pdfPermissions`](./permissions.md) | `{ decodePermissions, verifyPermsField }` | `pdfErrors`, fw `aes` | `/P` + `/Perms` MAC. |
|
|
12
|
+
| [`pdfAesGcm`](./aesGcm.md) | `{ encryptObjectGcm, decryptObjectGcm }` | `pdfErrors`, fw `aes`, `gcm`, `bitArray` | AES-GCM (ISO TS 32003). |
|
|
13
|
+
|
|
14
|
+
## Decryption pattern
|
|
15
|
+
|
|
16
|
+
```js
|
|
17
|
+
const sec = runtime.resolve('pdfSecurity');
|
|
18
|
+
const enc = sec.typeEncryptDict(trailer.encrypt);
|
|
19
|
+
const selection = sec.selectHandler(enc, {
|
|
20
|
+
v5: runtime.resolve('pdfStandardV5'),
|
|
21
|
+
v6: runtime.resolve('pdfStandardV6')
|
|
22
|
+
});
|
|
23
|
+
const { fileEncryptionKey } = selection.handler.tryPassword(enc, password, false);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## See also
|
|
27
|
+
|
|
28
|
+
- [`pdfTrailer`](../syntax/trailer.md) — carrier of the `/Encrypt` dict.
|
|
29
|
+
- [Signature](../sig/README.md) — orthogonal to the encryption handlers.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfAesGcm
|
|
3
|
+
category: pdf/crypto
|
|
4
|
+
dependencies: [pdfErrors, aes, gcm, bitArray]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfAesGcm
|
|
11
|
+
|
|
12
|
+
> AES-GCM cipher for PDF objects — ISO TS 32003.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfAesGcm` | **Source** `packages/front/office/pdf/src/crypto/aesGcm.js` | **Deps** `pdfErrors`, `aes`, `gcm`, `bitArray` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Implements the `AESV4` cipher introduced by ISO TS 32003: AES-256 in GCM mode with a 12-byte IV and a 16-byte authentication tag. Both functions operate on the PDF wire format directly — a single `Uint8Array` framed as `IV (12) ‖ ciphertext (n) ‖ tag (16)` — rather than a `{ iv, ciphertext, tag }` object. Decryption rejects truncated ciphertext or a mismatched tag.
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const gcm = runtime.resolve('pdfAesGcm');
|
|
22
|
+
// Returns: { encryptObjectGcm, decryptObjectGcm }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `encryptObjectGcm` | `(fek: Uint8Array, plaintext: Uint8Array, ivProvider: () => Uint8Array) => Uint8Array` | Framed `iv ‖ ciphertext ‖ tag`. `ivProvider` is called with no arguments and must return exactly 12 bytes. |
|
|
30
|
+
| `decryptObjectGcm` | `(fek: Uint8Array, framed: Uint8Array) => Uint8Array` | Splits `framed` into `iv`/`ciphertext`/`tag`, verifies the tag, and returns the plaintext. Throws on tag mismatch. |
|
|
31
|
+
|
|
32
|
+
`fek` (File Encryption Key) must be exactly 32 bytes (AES-256).
|
|
33
|
+
|
|
34
|
+
## Examples
|
|
35
|
+
|
|
36
|
+
### Deterministic encrypt (tests)
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
const gcm = runtime.resolve('pdfAesGcm');
|
|
40
|
+
const framed = gcm.encryptObjectGcm(
|
|
41
|
+
fek,
|
|
42
|
+
new TextEncoder().encode('hello'),
|
|
43
|
+
() => new Uint8Array(12) // ZERO IV — test only
|
|
44
|
+
);
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Decrypt the wire format
|
|
48
|
+
|
|
49
|
+
```js
|
|
50
|
+
const gcm = runtime.resolve('pdfAesGcm');
|
|
51
|
+
const plain = gcm.decryptObjectGcm(fek, framed);
|
|
52
|
+
// framed === iv(12) ‖ ciphertext ‖ tag(16), exactly as read from the PDF object.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Errors
|
|
56
|
+
|
|
57
|
+
| Code | Class | When |
|
|
58
|
+
|------|--------|------|
|
|
59
|
+
| `pdf/crypto/gcm/missing-fw` | `EncryptionError` | fw bundle incomplete (thrown at module construction). |
|
|
60
|
+
| `pdf/crypto/gcm/bad-fek` | `EncryptionError` | FEK ≠ 32 bytes. |
|
|
61
|
+
| `pdf/crypto/gcm/aes-schedule-failed` | `EncryptionError` | AES-256 key schedule failed. |
|
|
62
|
+
| `pdf/crypto/gcm/bad-input` | `EncryptionError` | `framed` is not a Uint8Array of at least 28 bytes. |
|
|
63
|
+
| `pdf/crypto/gcm/tag-mismatch` | `EncryptionError` | Authentication tag invalid — data tampered or wrong key. |
|
|
64
|
+
| `pdf/crypto/gcm/bad-plaintext` | `EncryptionError` | Plaintext is not a Uint8Array. |
|
|
65
|
+
| `pdf/crypto/gcm/bad-iv-provider` | `EncryptionError` | `ivProvider` is not a function. |
|
|
66
|
+
| `pdf/crypto/gcm/bad-iv` | `EncryptionError` | `ivProvider()` did not return exactly 12 bytes. |
|
|
67
|
+
| `pdf/crypto/gcm/encrypt-failed` | `EncryptionError` | The GCM provider failed. |
|
|
68
|
+
|
|
69
|
+
## See also
|
|
70
|
+
|
|
71
|
+
- [`pdfStandardV6`](./standardV6.md) — handler carrying the CFM.
|
|
72
|
+
- [`pdfSecurity`](./security.md)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfPermissions
|
|
3
|
+
category: pdf/crypto
|
|
4
|
+
dependencies: [pdfErrors, aes]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfPermissions
|
|
11
|
+
|
|
12
|
+
> `/P` decoding + `/Perms` verification — ISO 32000-2 §7.6.3.2 Table 22.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfPermissions` | **Source** `packages/front/office/pdf/src/crypto/permissions.js` | **Deps** `pdfErrors`, `aes` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
The `/P` field is a signed 32-bit integer whose bits encode permissions (bit 3 = print, 4 = modify, 5 = copy/extract, 6 = annotate, 9 = fill forms, 10 = accessibility extraction, 11 = assemble, 12 = high-quality print). `verifyPermsField` decrypts the 16-byte `/Perms` string (AES-256-ECB with the FEK) and checks that it encodes the same `/P` — a de facto MAC protecting against post-encryption tampering.
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const perms = runtime.resolve('pdfPermissions');
|
|
22
|
+
// Returns: { decodePermissions, verifyPermsField }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `decodePermissions` | `(p: number) => PermFlags` | Decomposes `/P` into readable booleans. |
|
|
30
|
+
| `verifyPermsField` | `(typedEncrypt: { Perms }, fek: Uint8Array) => { ok, p, encryptMetadata }` | Verifies the `/Perms` MAC. |
|
|
31
|
+
|
|
32
|
+
### Shape `PermFlags`
|
|
33
|
+
|
|
34
|
+
```js
|
|
35
|
+
{
|
|
36
|
+
raw: number,
|
|
37
|
+
print: boolean, // bit 3
|
|
38
|
+
modify: boolean, // bit 4
|
|
39
|
+
copy: boolean, // bit 5
|
|
40
|
+
annot: boolean, // bit 6
|
|
41
|
+
formFill: boolean, // bit 9
|
|
42
|
+
accessible: boolean, // bit 10 — accessibility extraction
|
|
43
|
+
assemble: boolean, // bit 11
|
|
44
|
+
printHighQuality: boolean // bit 12
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Examples
|
|
49
|
+
|
|
50
|
+
### Decoding the flags
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
const p = runtime.resolve('pdfPermissions').decodePermissions(enc.P);
|
|
54
|
+
if (!p.copy) viewer.disableTextSelection();
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### MAC verification
|
|
58
|
+
|
|
59
|
+
```js
|
|
60
|
+
const v = perms.verifyPermsField(enc, fek);
|
|
61
|
+
if (!v.ok) throw new Error('permissions tampered');
|
|
62
|
+
v.encryptMetadata === enc.EncryptMetadata;
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Errors
|
|
66
|
+
|
|
67
|
+
| Code | Class | When |
|
|
68
|
+
|------|--------|------|
|
|
69
|
+
| `pdf/crypto/permissions/bad-input` | `EncryptionError` | `p` argument is not an integer. |
|
|
70
|
+
| `pdf/crypto/permissions/missing-fw` | `EncryptionError` | fw bundle incomplete (thrown at module construction). |
|
|
71
|
+
| `pdf/crypto/permissions/missing-perms` | `EncryptionError` | `/Perms` absent. |
|
|
72
|
+
| `pdf/crypto/permissions/bad-perms-length` | `EncryptionError` | `/Perms` ≠ 16 bytes. |
|
|
73
|
+
| `pdf/crypto/permissions/bad-fek` | `EncryptionError` | FEK ≠ 32 bytes. |
|
|
74
|
+
| `pdf/crypto/permissions/aes-schedule-failed` | `EncryptionError` | Key schedule failed. |
|
|
75
|
+
| `pdf/crypto/permissions/aes-decrypt-failed` | `EncryptionError` | Block decryption failed. |
|
|
76
|
+
|
|
77
|
+
## See also
|
|
78
|
+
|
|
79
|
+
- [`pdfSecurity`](./security.md) · [`pdfStandardV5`](./standardV5.md) · [`pdfStandardV6`](./standardV6.md)
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
---
|
|
2
|
+
module: pdfSecurity
|
|
3
|
+
category: pdf/crypto
|
|
4
|
+
dependencies: [pdfErrors]
|
|
5
|
+
returns: object
|
|
6
|
+
worker-safe: true
|
|
7
|
+
status: complete
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# pdfSecurity
|
|
11
|
+
|
|
12
|
+
> `/Encrypt` dict typing and handler selection — ISO 32000-2 §7.6.
|
|
13
|
+
|
|
14
|
+
**Module** `pdfSecurity` | **Source** `packages/front/office/pdf/src/crypto/security.js` | **Deps** `pdfErrors` | **Worker-safe** yes
|
|
15
|
+
|
|
16
|
+
Neutral layer that interprets the trailer's `/Encrypt` dict (§7.6.2 Table 21) and selects the appropriate handler (`v4` = RC4/AES-128 legacy, `v5` = historical AES-256 ISO 32000-1 R5, `v6` = AES-256 ISO 32000-2 R6, transparently including ISO/TS 32003 AES-GCM when `/CFM = AESV4`). Performs no key derivation itself — delegates to the specialized handlers, and additionally routes stream decryption between the regular stream path and the embedded-file path (`/EFF`, ISO 32000-1 §7.6.5).
|
|
17
|
+
|
|
18
|
+
## Resolve
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
const sec = runtime.resolve('pdfSecurity');
|
|
22
|
+
// Returns: { typeEncryptDict, selectHandler, isEmbeddedFileStream, dispatchDecryptStream }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## API
|
|
26
|
+
|
|
27
|
+
| Method | Signature | Returns |
|
|
28
|
+
|--------|-----------|---------|
|
|
29
|
+
| `typeEncryptDict` | `(dict \| Map) => Encrypt` | Strict typing of the `/Encrypt` entries. |
|
|
30
|
+
| `selectHandler` | `(typedEncrypt: Encrypt, handlers: { v4?, v5?, v6? }) => { handler, revision, method, strMethod, effMethod }` | Dispatches `V=4` → `handlers.v4`, `V=5,R=5` → `handlers.v5`, `V=5,R=6` → `handlers.v6`; also resolves the `/CF`/`/StmF`/`/StrF`/`/EFF` crypt-filter method (`'AESV2'`/`'V2'`/`'Identity'` for V=4, `'AESV3'`/`'AESV4'`/`'Identity'` for V=5) into `method` (streams), `strMethod` (strings) and `effMethod` (embedded files). |
|
|
31
|
+
| `isEmbeddedFileStream` | `(stream) => boolean` | `true` when the stream dict has `/Type /EmbeddedFile`. |
|
|
32
|
+
| `dispatchDecryptStream` | `(selection, stream, fek, objNum, gen, ciphertext) => Uint8Array` | Routes to `selection.handler.decryptEmbeddedFile` (with `effMethod`) when `stream` is an embedded file, else to `handler.decryptStream` (with `method`). Returns `ciphertext` unchanged, without calling the handler, when that method is `'Identity'`. |
|
|
33
|
+
|
|
34
|
+
### Identity crypt filter
|
|
35
|
+
|
|
36
|
+
A class whose crypt filter is `Identity` — named explicitly, or absent, which is the ISO 32000-2 §7.6.6 Table 20 default for `/StmF` and `/StrF` — is not encrypted. `selectHandler` resolves each class on its own: `/StmF` gives `method`, `/StrF` gives `strMethod`, and `/EFF` gives `effMethod`, where an absent `/EFF` follows `/StmF`. A V=5 file with `/StmF /StdCF` and `/StrF /Identity` therefore has encrypted streams and clear strings. `dispatchDecryptStream` returns the bytes of an `Identity` class unchanged on every revision (V=4, V=5 R=5, V=5 R=6), and signing such a file writes its new strings in the clear. On V=4, a `/StmF /Identity` paired with a named `/StrF` keeps its existing behaviour: streams use the `/StrF` filter.
|
|
37
|
+
|
|
38
|
+
### Shape `Encrypt`
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
{
|
|
42
|
+
V, R, Filter, SubFilter, Length, CF, StmF, StrF, EFF,
|
|
43
|
+
O, U, OE, UE, Perms, // Uint8Array
|
|
44
|
+
EncryptMetadata: boolean,
|
|
45
|
+
P: number, // permissions bitmask, §7.6.3.2 Table 22
|
|
46
|
+
raw
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Examples
|
|
51
|
+
|
|
52
|
+
### Dispatcher
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
const sec = runtime.resolve('pdfSecurity');
|
|
56
|
+
const enc = sec.typeEncryptDict(trailer.encrypt);
|
|
57
|
+
const selection = sec.selectHandler(enc, {
|
|
58
|
+
v5: runtime.resolve('pdfStandardV5'),
|
|
59
|
+
v6: runtime.resolve('pdfStandardV6')
|
|
60
|
+
});
|
|
61
|
+
const fek = selection.handler.tryPassword(enc, password, false).fileEncryptionKey;
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Stream decryption routing (regular vs embedded file)
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
const plain = sec.dispatchDecryptStream(selection, streamObj, fek, num, gen, ciphertext);
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Inspecting permissions
|
|
71
|
+
|
|
72
|
+
```js
|
|
73
|
+
const perms = runtime.resolve('pdfPermissions').decodePermissions(enc.P);
|
|
74
|
+
perms.print;
|
|
75
|
+
perms.copy;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Errors
|
|
79
|
+
|
|
80
|
+
| Code | Class | When |
|
|
81
|
+
|------|--------|------|
|
|
82
|
+
| `pdf/crypto/encrypt-dict/bad-input` | `EncryptionError` | Argument is not an object. |
|
|
83
|
+
| `pdf/crypto/encrypt-dict/missing-V-R` | `EncryptionError` | `/V` or `/R` missing. |
|
|
84
|
+
| `pdf/crypto/encrypt-dict/bad-V-R-type` | `EncryptionError` | `/V` or `/R` not an integer. |
|
|
85
|
+
| `pdf/crypto/v4/missing-cf-entry` | `EncryptionError` | `V=4` requires a `/CF /<name>` entry that is absent. |
|
|
86
|
+
| `pdf/crypto/v4/bad-cfm` | `EncryptionError` | `V=4` CFM is neither `AESV2` nor `V2`. |
|
|
87
|
+
| `pdf/crypto/v5/bad-cfm` | `EncryptionError` | `V=5` CFM is neither `AESV3` nor `AESV4`. |
|
|
88
|
+
| `pdf/crypto/security/bad-typed` | `EncryptionError` | `selectHandler` receives a non-typed encrypt dict. |
|
|
89
|
+
| `pdf/crypto/unsupported-version` | `EncryptionError` | `V`/`R` combination outside `4`/`5`+`5`/`5`+`6`. |
|
|
90
|
+
| `pdf/crypto/missing-handler` | `EncryptionError` | Required `v4`/`v5`/`v6` handler not supplied. |
|
|
91
|
+
| `pdf/crypto/security/bad-selection` | `EncryptionError` | `dispatchDecryptStream` receives a selection without a `handler`. |
|
|
92
|
+
| `pdf/crypto/security/no-eff` | `EncryptionError` | Embedded-file stream but the handler exposes neither `decryptEmbeddedFile` nor `decryptStream`. |
|
|
93
|
+
| `pdf/crypto/security/no-stream` | `EncryptionError` | Regular stream but the handler lacks `decryptStream`. |
|
|
94
|
+
|
|
95
|
+
## See also
|
|
96
|
+
|
|
97
|
+
- [`pdfStandardV5`](./standardV5.md) · [`pdfStandardV6`](./standardV6.md) · [`pdfAesGcm`](./aesGcm.md)
|
|
98
|
+
- [`pdfPermissions`](./permissions.md)
|