@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,135 @@
|
|
|
1
|
+
// Copyright (c) 2026 AwaCloud SAS
|
|
2
|
+
// Author: Matthieu Bouilloux
|
|
3
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
4
|
+
// Dual-licensed; see the NOTICE file for licensing and any additional terms.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview Opt-in: AES-GCM crypt filter wrapper for `/Encrypt`
|
|
8
|
+
* dictionaries — ISO/TS 32003.
|
|
9
|
+
*
|
|
10
|
+
* @module pdf/extra/sig-aes-gcm
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Module factory.
|
|
15
|
+
*/
|
|
16
|
+
import { pdfErrors } from '../errors.js';
|
|
17
|
+
import { pdfParser } from '../syntax/parser.js';
|
|
18
|
+
|
|
19
|
+
export const pdfSigAesGcm = {
|
|
20
|
+
name: 'pdfSigAesGcm',
|
|
21
|
+
dependencies: ['pdfErrors', 'pdfParser'],
|
|
22
|
+
deps: [pdfErrors, pdfParser],
|
|
23
|
+
factory(errors, parser) {
|
|
24
|
+
const { ParseError, EncryptionError } = errors;
|
|
25
|
+
const { isType } = parser;
|
|
26
|
+
|
|
27
|
+
/** Frozen catalog of known Crypt Filter Methods (CFM names). */
|
|
28
|
+
const CFM_CATALOG = Object.freeze({
|
|
29
|
+
None: { cipher: 'none', keyBits: 0, notes: 'identity / stream-as-is' },
|
|
30
|
+
V2: { cipher: 'rc4', keyBits: 40, notes: 'legacy RC4 (deprecated)' },
|
|
31
|
+
AESV2: { cipher: 'aes', keyBits: 128, mode: 'cbc',
|
|
32
|
+
notes: 'AES-128 CBC (R4)' },
|
|
33
|
+
AESV3: { cipher: 'aes', keyBits: 256, mode: 'cbc',
|
|
34
|
+
notes: 'AES-256 CBC (R6, ISO 32000-2)' },
|
|
35
|
+
AESV4: { cipher: 'aes', keyBits: 256, mode: 'gcm',
|
|
36
|
+
notes: 'AES-256 GCM (ISO/TS 32003)' }
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const ENCRYPT_KNOWN = new Set([
|
|
40
|
+
'Filter', 'SubFilter', 'V', 'Length', 'CF', 'StmF', 'StrF', 'EFF',
|
|
41
|
+
'R', 'O', 'U', 'OE', 'UE', 'Perms', 'P', 'EncryptMetadata'
|
|
42
|
+
]);
|
|
43
|
+
const CF_ENTRY_KNOWN = new Set(['Type', 'CFM', 'AuthEvent', 'Length']);
|
|
44
|
+
|
|
45
|
+
function typeEncryptForGcm(dict) {
|
|
46
|
+
if (!isType(dict, 'dict')) {
|
|
47
|
+
throw new ParseError('pdf/extra/sig-aes-gcm/not-dict',
|
|
48
|
+
'/Encrypt must be a dictionary',
|
|
49
|
+
{ context: { type: dict && dict.type } });
|
|
50
|
+
}
|
|
51
|
+
const e = dict.entries;
|
|
52
|
+
const out = {
|
|
53
|
+
v: isType(e.V, 'int') ? e.V.value : null,
|
|
54
|
+
r: isType(e.R, 'int') ? e.R.value : null,
|
|
55
|
+
length: isType(e.Length, 'int') ? e.Length.value : null,
|
|
56
|
+
stmF: isType(e.StmF, 'name') ? e.StmF.value : null,
|
|
57
|
+
strF: isType(e.StrF, 'name') ? e.StrF.value : null,
|
|
58
|
+
eff: isType(e.EFF, 'name') ? e.EFF.value : null,
|
|
59
|
+
cf: {},
|
|
60
|
+
hasAesGcm: false,
|
|
61
|
+
raw: dict,
|
|
62
|
+
_extras: {}
|
|
63
|
+
};
|
|
64
|
+
if (e.CF !== undefined) {
|
|
65
|
+
if (!isType(e.CF, 'dict')) {
|
|
66
|
+
throw new ParseError('pdf/extra/sig-aes-gcm/bad-cf',
|
|
67
|
+
'/CF must be a dictionary',
|
|
68
|
+
{ context: { type: e.CF.type } });
|
|
69
|
+
}
|
|
70
|
+
for (const name of Object.keys(e.CF.entries)) {
|
|
71
|
+
const entry = e.CF.entries[name];
|
|
72
|
+
if (!isType(entry, 'dict')) {
|
|
73
|
+
throw new ParseError('pdf/extra/sig-aes-gcm/bad-cf-entry',
|
|
74
|
+
'/CF entry must be a dictionary',
|
|
75
|
+
{ context: { name } });
|
|
76
|
+
}
|
|
77
|
+
out.cf[name] = typeCfEntry(entry);
|
|
78
|
+
if (out.cf[name].cfm === 'AESV4') out.hasAesGcm = true;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
for (const k of Object.keys(e)) {
|
|
82
|
+
if (!ENCRYPT_KNOWN.has(k)) out._extras[k] = e[k];
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function typeCfEntry(dict) {
|
|
88
|
+
if (!isType(dict, 'dict')) {
|
|
89
|
+
throw new ParseError('pdf/extra/sig-aes-gcm/cf-entry-not-dict',
|
|
90
|
+
'CF entry must be a dictionary',
|
|
91
|
+
{ context: { type: dict && dict.type } });
|
|
92
|
+
}
|
|
93
|
+
const e = dict.entries;
|
|
94
|
+
const cfm = isType(e.CFM, 'name') ? e.CFM.value : null;
|
|
95
|
+
const out = {
|
|
96
|
+
cfm,
|
|
97
|
+
authEvent: isType(e.AuthEvent, 'name') ? e.AuthEvent.value : null,
|
|
98
|
+
length: isType(e.Length, 'int') ? e.Length.value : null,
|
|
99
|
+
catalog: cfm && CFM_CATALOG[cfm] ? CFM_CATALOG[cfm] : null,
|
|
100
|
+
raw: dict,
|
|
101
|
+
_extras: {}
|
|
102
|
+
};
|
|
103
|
+
for (const k of Object.keys(e)) {
|
|
104
|
+
if (!CF_ENTRY_KNOWN.has(k)) out._extras[k] = e[k];
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function validateGcmFraming(framed) {
|
|
110
|
+
if (!(framed instanceof Uint8Array)) {
|
|
111
|
+
throw new EncryptionError('pdf/extra/sig-aes-gcm/bad-input',
|
|
112
|
+
'framed input must be a Uint8Array',
|
|
113
|
+
{ context: { type: typeof framed } });
|
|
114
|
+
}
|
|
115
|
+
if (framed.length < 12 + 16) {
|
|
116
|
+
throw new EncryptionError('pdf/extra/sig-aes-gcm/too-short',
|
|
117
|
+
'AES-GCM framed blob must be at least 28 bytes (IV+tag)',
|
|
118
|
+
{ context: { length: framed.length } });
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
iv: framed.subarray(0, 12),
|
|
122
|
+
ciphertext: framed.subarray(12, framed.length - 16),
|
|
123
|
+
tag: framed.subarray(framed.length - 16)
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
typeEncryptForGcm,
|
|
129
|
+
typeCfEntry,
|
|
130
|
+
validateGcmFraming,
|
|
131
|
+
CFM_CATALOG
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// Copyright (c) 2026 AwaCloud SAS
|
|
2
|
+
// Author: Matthieu Bouilloux
|
|
3
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
4
|
+
// Dual-licensed; see the NOTICE file for licensing and any additional terms.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview Opt-in: PAdES (ETSI EN 319 142-1) profile detection
|
|
8
|
+
* for signature dicts, `/Reference` array typing, and DSS (Document
|
|
9
|
+
* Security Store) dict typing per ISO 32000-2:2020 §12.8.4.3.
|
|
10
|
+
*
|
|
11
|
+
* @module pdf/extra/sig-pades
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Module factory.
|
|
16
|
+
*/
|
|
17
|
+
import { pdfErrors } from '../errors.js';
|
|
18
|
+
import { pdfParser } from '../syntax/parser.js';
|
|
19
|
+
|
|
20
|
+
export const pdfSigPades = {
|
|
21
|
+
name: 'pdfSigPades',
|
|
22
|
+
dependencies: ['pdfErrors', 'pdfParser'],
|
|
23
|
+
deps: [pdfErrors, pdfParser],
|
|
24
|
+
factory(errors, parser) {
|
|
25
|
+
const { ParseError } = errors;
|
|
26
|
+
const { isType } = parser;
|
|
27
|
+
|
|
28
|
+
/** Frozen catalog of recognized signature SubFilter names. */
|
|
29
|
+
const SIG_SUBFILTERS = Object.freeze({
|
|
30
|
+
'adbe.x509.rsa_sha1': { pades: false, kind: 'legacy' },
|
|
31
|
+
'adbe.pkcs7.sha1': { pades: false, kind: 'legacy' },
|
|
32
|
+
'adbe.pkcs7.detached': { pades: false, kind: 'pkcs7-detached' },
|
|
33
|
+
'ETSI.CAdES.detached': { pades: true, kind: 'pades-cades' },
|
|
34
|
+
'ETSI.RFC3161': { pades: true, kind: 'doc-timestamp' }
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
function detectPadesProfile(sigDict, ctx) {
|
|
38
|
+
if (!isType(sigDict, 'dict')) {
|
|
39
|
+
throw new ParseError('pdf/extra/pades/not-dict',
|
|
40
|
+
'signature dict must be a dictionary',
|
|
41
|
+
{ context: { type: sigDict && sigDict.type } });
|
|
42
|
+
}
|
|
43
|
+
const e = sigDict.entries;
|
|
44
|
+
const sf = isType(e.SubFilter, 'name') ? e.SubFilter.value : null;
|
|
45
|
+
const info = sf ? SIG_SUBFILTERS[sf] : null;
|
|
46
|
+
const isPades = !!(info && info.pades);
|
|
47
|
+
const hasTimestamp = !!(
|
|
48
|
+
sf === 'ETSI.RFC3161' ||
|
|
49
|
+
(e.M && isType(e.M, 'string')) ||
|
|
50
|
+
(ctx && ctx.hasSignatureTimestamp)
|
|
51
|
+
);
|
|
52
|
+
let level = null;
|
|
53
|
+
if (isPades) {
|
|
54
|
+
const hasDss = !!(ctx && ctx.dss);
|
|
55
|
+
const ltaTs = !!(ctx && ctx.hasDocTimestampOverDss);
|
|
56
|
+
if (ltaTs) level = 'B-LTA';
|
|
57
|
+
else if (hasDss) level = 'B-LT';
|
|
58
|
+
else if (hasTimestamp) level = 'B-T';
|
|
59
|
+
else level = 'B-B';
|
|
60
|
+
}
|
|
61
|
+
return { subFilter: sf, isPades, level, hasTimestamp };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function typeReferenceArray(arr) {
|
|
65
|
+
if (!isType(arr, 'array')) {
|
|
66
|
+
throw new ParseError('pdf/extra/pades/bad-reference',
|
|
67
|
+
'/Reference must be an array',
|
|
68
|
+
{ context: { type: arr && arr.type } });
|
|
69
|
+
}
|
|
70
|
+
const out = [];
|
|
71
|
+
for (const it of arr.items) {
|
|
72
|
+
if (!isType(it, 'dict')) {
|
|
73
|
+
throw new ParseError('pdf/extra/pades/bad-reference-item',
|
|
74
|
+
'/Reference items must be dicts');
|
|
75
|
+
}
|
|
76
|
+
const e = it.entries;
|
|
77
|
+
if (e.Type && (e.Type.type !== 'name' || e.Type.value !== 'SigRef')) {
|
|
78
|
+
throw new ParseError('pdf/extra/pades/bad-reference-type',
|
|
79
|
+
'/Type of /Reference item must be /SigRef',
|
|
80
|
+
{ context: { actual: e.Type.value } });
|
|
81
|
+
}
|
|
82
|
+
out.push({
|
|
83
|
+
transformMethod: isType(e.TransformMethod, 'name') ? e.TransformMethod.value : null,
|
|
84
|
+
transformParams: isType(e.TransformParams, 'dict') ? e.TransformParams : null,
|
|
85
|
+
data: e.Data || null,
|
|
86
|
+
digestMethod: isType(e.DigestMethod, 'name') ? e.DigestMethod.value : null,
|
|
87
|
+
raw: it
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return out;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function typeDSS(dict) {
|
|
94
|
+
if (!isType(dict, 'dict')) {
|
|
95
|
+
throw new ParseError('pdf/extra/pades/dss-not-dict',
|
|
96
|
+
'DSS must be a dictionary',
|
|
97
|
+
{ context: { type: dict && dict.type } });
|
|
98
|
+
}
|
|
99
|
+
const e = dict.entries;
|
|
100
|
+
if (e.Type && (e.Type.type !== 'name' || e.Type.value !== 'DSS')) {
|
|
101
|
+
throw new ParseError('pdf/extra/pades/dss-bad-type',
|
|
102
|
+
'/Type of DSS dict must be /DSS',
|
|
103
|
+
{ context: { actual: e.Type.value } });
|
|
104
|
+
}
|
|
105
|
+
const out = {
|
|
106
|
+
certs: refsArray(e.Certs, 'DSS /Certs'),
|
|
107
|
+
crls: refsArray(e.CRLs, 'DSS /CRLs'),
|
|
108
|
+
ocsps: refsArray(e.OCSPs, 'DSS /OCSPs'),
|
|
109
|
+
vri: isType(e.VRI, 'dict') ? typeVRI(e.VRI) : null,
|
|
110
|
+
raw: dict,
|
|
111
|
+
_extras: {}
|
|
112
|
+
};
|
|
113
|
+
const known = new Set(['Type', 'Certs', 'CRLs', 'OCSPs', 'VRI']);
|
|
114
|
+
for (const k of Object.keys(e)) if (!known.has(k)) out._extras[k] = e[k];
|
|
115
|
+
return out;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function typeVRI(dict) {
|
|
119
|
+
const out = {};
|
|
120
|
+
for (const k of Object.keys(dict.entries)) {
|
|
121
|
+
const v = dict.entries[k];
|
|
122
|
+
if (!isType(v, 'dict')) continue;
|
|
123
|
+
const ve = v.entries;
|
|
124
|
+
out[k] = {
|
|
125
|
+
cert: refsArray(ve.Cert, 'VRI /Cert'),
|
|
126
|
+
crl: refsArray(ve.CRL, 'VRI /CRL'),
|
|
127
|
+
ocsp: refsArray(ve.OCSP, 'VRI /OCSP'),
|
|
128
|
+
tu: isType(ve.TU, 'string') ? ve.TU.value : null,
|
|
129
|
+
ts: ve.TS || null
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function refsArray(v, ctxLabel) {
|
|
136
|
+
if (!v) return null;
|
|
137
|
+
if (!isType(v, 'array')) {
|
|
138
|
+
throw new ParseError('pdf/extra/pades/dss-bad-array',
|
|
139
|
+
`${ctxLabel} must be an array`,
|
|
140
|
+
{ context: { type: v.type } });
|
|
141
|
+
}
|
|
142
|
+
return v.items;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function validateDocMdp(ref) {
|
|
146
|
+
const issues = [];
|
|
147
|
+
if (!ref || ref.transformMethod !== 'DocMDP') {
|
|
148
|
+
issues.push({
|
|
149
|
+
code: 'pdf/extra/pades/mdp/wrong-transform',
|
|
150
|
+
message: 'reference is not a DocMDP transform',
|
|
151
|
+
context: { transformMethod: ref && ref.transformMethod }
|
|
152
|
+
});
|
|
153
|
+
return { valid: false, level: null, issues };
|
|
154
|
+
}
|
|
155
|
+
if (!ref.transformParams || !isType(ref.transformParams, 'dict')) {
|
|
156
|
+
issues.push({
|
|
157
|
+
code: 'pdf/extra/pades/mdp/missing-params',
|
|
158
|
+
message: 'DocMDP missing /TransformParams dict'
|
|
159
|
+
});
|
|
160
|
+
return { valid: false, level: null, issues };
|
|
161
|
+
}
|
|
162
|
+
const params = ref.transformParams.entries;
|
|
163
|
+
let level = null;
|
|
164
|
+
if (params.P) {
|
|
165
|
+
if (params.P.type !== 'int') {
|
|
166
|
+
issues.push({
|
|
167
|
+
code: 'pdf/extra/pades/mdp/bad-p-type',
|
|
168
|
+
message: '/P must be an integer',
|
|
169
|
+
context: { type: params.P.type }
|
|
170
|
+
});
|
|
171
|
+
} else if (params.P.value < 1 || params.P.value > 3) {
|
|
172
|
+
issues.push({
|
|
173
|
+
code: 'pdf/extra/pades/mdp/bad-p-value',
|
|
174
|
+
message: '/P must be 1, 2 or 3',
|
|
175
|
+
context: { value: params.P.value }
|
|
176
|
+
});
|
|
177
|
+
} else {
|
|
178
|
+
level = params.P.value;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
level = 2;
|
|
182
|
+
}
|
|
183
|
+
if (params.V && params.V.type === 'name'
|
|
184
|
+
&& params.V.value !== '1.2'
|
|
185
|
+
&& params.V.value !== '2.2') {
|
|
186
|
+
issues.push({
|
|
187
|
+
code: 'pdf/extra/pades/mdp/bad-version',
|
|
188
|
+
message: 'unknown DocMDP /V',
|
|
189
|
+
context: { v: params.V.value }
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
if (!ref.digestMethod) {
|
|
193
|
+
issues.push({
|
|
194
|
+
code: 'pdf/extra/pades/mdp/missing-digest',
|
|
195
|
+
message: 'DocMDP reference missing /DigestMethod'
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return { valid: issues.length === 0, level, issues };
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function validateBLtaChain(steps) {
|
|
202
|
+
if (!Array.isArray(steps)) {
|
|
203
|
+
throw new ParseError('pdf/extra/pades/chain/bad-input',
|
|
204
|
+
'validateBLtaChain expects an array of steps',
|
|
205
|
+
{ context: { type: typeof steps } });
|
|
206
|
+
}
|
|
207
|
+
const trace = [];
|
|
208
|
+
let sawDss = false;
|
|
209
|
+
let sawDocTsOverDss = false;
|
|
210
|
+
for (let i = 0; i < steps.length; i++) {
|
|
211
|
+
const step = steps[i];
|
|
212
|
+
if (!step || !step.sigDict) {
|
|
213
|
+
throw new ParseError('pdf/extra/pades/chain/missing-sig',
|
|
214
|
+
'step missing sigDict',
|
|
215
|
+
{ context: { index: i } });
|
|
216
|
+
}
|
|
217
|
+
if (step.hasDss) sawDss = true;
|
|
218
|
+
if (step.hasDocTimestamp && sawDss) sawDocTsOverDss = true;
|
|
219
|
+
const ctx = {
|
|
220
|
+
dss: sawDss ? {} : undefined,
|
|
221
|
+
hasDocTimestampOverDss: sawDocTsOverDss,
|
|
222
|
+
hasSignatureTimestamp: !!step.hasSignatureTimestamp
|
|
223
|
+
};
|
|
224
|
+
const detected = detectPadesProfile(step.sigDict, ctx);
|
|
225
|
+
trace.push({ index: i, level: detected.level,
|
|
226
|
+
isPades: detected.isPades });
|
|
227
|
+
}
|
|
228
|
+
const last = trace[trace.length - 1];
|
|
229
|
+
return { chainLevel: last ? last.level : null, trace };
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return {
|
|
233
|
+
detectPadesProfile,
|
|
234
|
+
typeReferenceArray,
|
|
235
|
+
typeDSS,
|
|
236
|
+
validateDocMdp,
|
|
237
|
+
validateBLtaChain,
|
|
238
|
+
SIG_SUBFILTERS
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// Copyright (c) 2026 AwaCloud SAS
|
|
2
|
+
// Author: Matthieu Bouilloux
|
|
3
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
4
|
+
// Dual-licensed; see the NOTICE file for licensing and any additional terms.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @fileoverview Opt-in: typed StructElem attribute objects per
|
|
8
|
+
* ISO 32000-2:2020 §14.8.5 (standard structure attribute owners) —
|
|
9
|
+
* Layout (§14.8.5.4), List (§14.8.5.5), Table (§14.8.5.7),
|
|
10
|
+
* PrintField (§14.8.5.6), Artifact (§14.8.2.2), UserProperties
|
|
11
|
+
* (§14.8.5.10).
|
|
12
|
+
*
|
|
13
|
+
* Attribute classes appear as dicts with an `/O` (Owner) name. We
|
|
14
|
+
* dispatch by `/O` and apply a typed reader that returns plain JS
|
|
15
|
+
* values for the well-defined keys, preserving unknowns in `_extras`.
|
|
16
|
+
*
|
|
17
|
+
* @module pdf/extra/tagged-pdf-typed
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Module factory.
|
|
22
|
+
*/
|
|
23
|
+
import { pdfErrors } from '../errors.js';
|
|
24
|
+
import { pdfParserObj } from '../syntax/parser-obj.js';
|
|
25
|
+
|
|
26
|
+
export const pdfTaggedPdfTyped = {
|
|
27
|
+
name: 'pdfTaggedPdfTyped',
|
|
28
|
+
dependencies: ['pdfErrors', 'pdfParserObj'],
|
|
29
|
+
deps: [pdfErrors, pdfParserObj],
|
|
30
|
+
factory(errors, parserObj) {
|
|
31
|
+
const { ParseError } = errors;
|
|
32
|
+
const { isType } = parserObj;
|
|
33
|
+
|
|
34
|
+
const OWNERS = new Set([
|
|
35
|
+
'Layout', 'List', 'Table', 'PrintField', 'Artifact', 'UserProperties'
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
const KNOWN_BY_OWNER = {
|
|
39
|
+
Layout: new Set(['O', 'Placement', 'WritingMode', 'BackgroundColor',
|
|
40
|
+
'BorderColor', 'BorderStyle', 'BorderThickness', 'Color',
|
|
41
|
+
'Padding', 'SpaceBefore', 'SpaceAfter', 'StartIndent', 'EndIndent',
|
|
42
|
+
'TextIndent', 'TextAlign', 'BBox', 'Width', 'Height', 'BlockAlign',
|
|
43
|
+
'InlineAlign', 'TBorderStyle', 'TPadding', 'LineHeight',
|
|
44
|
+
'BaselineShift', 'TextPosition', 'TextDecorationType',
|
|
45
|
+
'TextDecorationColor', 'TextDecorationThickness',
|
|
46
|
+
'RubyAlign', 'RubyPosition', 'GlyphOrientationVertical',
|
|
47
|
+
'ColumnCount', 'ColumnGap', 'ColumnWidths']),
|
|
48
|
+
List: new Set(['O', 'ListNumbering', 'ContinuedList', 'ContinuedFrom']),
|
|
49
|
+
Table: new Set(['O', 'RowSpan', 'ColSpan', 'Headers', 'Scope', 'Summary']),
|
|
50
|
+
PrintField: new Set(['O', 'Role', 'checked', 'Desc']),
|
|
51
|
+
Artifact: new Set(['O', 'Type', 'BBox', 'Attached', 'Subtype']),
|
|
52
|
+
UserProperties: new Set(['O', 'P'])
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
function knownFor(owner) {
|
|
56
|
+
return KNOWN_BY_OWNER[owner] || new Set(['O']);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function typeStructAttribute(dict) {
|
|
60
|
+
if (!isType(dict, 'dict')) {
|
|
61
|
+
throw new ParseError('pdf/extra/tagged/not-dict',
|
|
62
|
+
'attribute class must be a dictionary',
|
|
63
|
+
{ context: { type: dict && dict.type } });
|
|
64
|
+
}
|
|
65
|
+
const e = dict.entries;
|
|
66
|
+
if (!isType(e.O, 'name')) {
|
|
67
|
+
throw new ParseError('pdf/extra/tagged/missing-owner',
|
|
68
|
+
'attribute class missing /O owner name',
|
|
69
|
+
{ context: { type: e.O && e.O.type } });
|
|
70
|
+
}
|
|
71
|
+
const owner = e.O.value;
|
|
72
|
+
let typed;
|
|
73
|
+
switch (owner) {
|
|
74
|
+
case 'Layout': typed = readLayout(e); break;
|
|
75
|
+
case 'List': typed = readList(e); break;
|
|
76
|
+
case 'Table': typed = readTable(e); break;
|
|
77
|
+
case 'PrintField': typed = readPrintField(e); break;
|
|
78
|
+
case 'Artifact': typed = readArtifact(e); break;
|
|
79
|
+
case 'UserProperties': typed = readUserProperties(e); break;
|
|
80
|
+
default:
|
|
81
|
+
typed = { owner, vendor: true };
|
|
82
|
+
}
|
|
83
|
+
typed.owner = owner;
|
|
84
|
+
typed.raw = dict;
|
|
85
|
+
typed._extras = collectExtras(e, knownFor(owner));
|
|
86
|
+
return typed;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function readLayout(e) {
|
|
90
|
+
return {
|
|
91
|
+
placement: nameVal(e.Placement),
|
|
92
|
+
writingMode: nameVal(e.WritingMode),
|
|
93
|
+
backgroundColor: numArr(e.BackgroundColor),
|
|
94
|
+
borderColor: e.BorderColor || null,
|
|
95
|
+
borderStyle: e.BorderStyle || null,
|
|
96
|
+
borderThickness: e.BorderThickness || null,
|
|
97
|
+
color: numArr(e.Color),
|
|
98
|
+
padding: e.Padding || null,
|
|
99
|
+
spaceBefore: numVal(e.SpaceBefore, null),
|
|
100
|
+
spaceAfter: numVal(e.SpaceAfter, null),
|
|
101
|
+
startIndent: numVal(e.StartIndent, null),
|
|
102
|
+
endIndent: numVal(e.EndIndent, null),
|
|
103
|
+
textIndent: numVal(e.TextIndent, null),
|
|
104
|
+
textAlign: nameVal(e.TextAlign),
|
|
105
|
+
bbox: numArr(e.BBox),
|
|
106
|
+
width: numVal(e.Width, null),
|
|
107
|
+
height: numVal(e.Height, null),
|
|
108
|
+
blockAlign: nameVal(e.BlockAlign),
|
|
109
|
+
inlineAlign: nameVal(e.InlineAlign),
|
|
110
|
+
lineHeight: numVal(e.LineHeight, null),
|
|
111
|
+
baselineShift: numVal(e.BaselineShift, null),
|
|
112
|
+
textPosition: nameVal(e.TextPosition),
|
|
113
|
+
textDecorationType: nameVal(e.TextDecorationType),
|
|
114
|
+
textDecorationColor: numArr(e.TextDecorationColor),
|
|
115
|
+
textDecorationThickness: numVal(e.TextDecorationThickness, null),
|
|
116
|
+
columnCount: numVal(e.ColumnCount, null),
|
|
117
|
+
columnGap: e.ColumnGap || null,
|
|
118
|
+
columnWidths: e.ColumnWidths || null
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function readList(e) {
|
|
123
|
+
return {
|
|
124
|
+
listNumbering: nameVal(e.ListNumbering),
|
|
125
|
+
continuedList: isType(e.ContinuedList, 'bool') ? e.ContinuedList.value : null,
|
|
126
|
+
continuedFrom: e.ContinuedFrom || null
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function readTable(e) {
|
|
131
|
+
return {
|
|
132
|
+
rowSpan: numVal(e.RowSpan, null),
|
|
133
|
+
colSpan: numVal(e.ColSpan, null),
|
|
134
|
+
headers: e.Headers || null,
|
|
135
|
+
scope: nameVal(e.Scope),
|
|
136
|
+
summary: isType(e.Summary, 'string') ? e.Summary.value : null
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function readPrintField(e) {
|
|
141
|
+
return {
|
|
142
|
+
role: nameVal(e.Role),
|
|
143
|
+
checked: nameVal(e.checked) || nameVal(e.Checked),
|
|
144
|
+
desc: isType(e.Desc, 'string') ? e.Desc.value : null
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function readArtifact(e) {
|
|
149
|
+
return {
|
|
150
|
+
artifactType: nameVal(e.Type),
|
|
151
|
+
bbox: numArr(e.BBox),
|
|
152
|
+
attached: e.Attached || null,
|
|
153
|
+
artifactSubtype: nameVal(e.Subtype)
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function readUserProperties(e) {
|
|
158
|
+
const out = { properties: [] };
|
|
159
|
+
if (isType(e.P, 'array')) {
|
|
160
|
+
for (const it of e.P.items) {
|
|
161
|
+
if (!isType(it, 'dict')) {
|
|
162
|
+
throw new ParseError('pdf/extra/tagged/bad-user-property',
|
|
163
|
+
'/P items must be dicts');
|
|
164
|
+
}
|
|
165
|
+
const pe = it.entries;
|
|
166
|
+
out.properties.push({
|
|
167
|
+
name: isType(pe.N, 'string') ? pe.N.value : null,
|
|
168
|
+
value: pe.V || null,
|
|
169
|
+
formatted: isType(pe.F, 'string') ? pe.F.value : null,
|
|
170
|
+
hidden: isType(pe.H, 'bool') ? pe.H.value : false
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return out;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function nameVal(v) { return isType(v, 'name') ? v.value : null; }
|
|
178
|
+
function numVal(v, dflt) {
|
|
179
|
+
if (!v) return dflt;
|
|
180
|
+
return (v.type === 'int' || v.type === 'real') ? v.value : dflt;
|
|
181
|
+
}
|
|
182
|
+
function numArr(v) {
|
|
183
|
+
if (!isType(v, 'array')) return null;
|
|
184
|
+
const out = [];
|
|
185
|
+
for (const it of v.items) {
|
|
186
|
+
if (!it || (it.type !== 'int' && it.type !== 'real')) return null;
|
|
187
|
+
out.push(it.value);
|
|
188
|
+
}
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function collectExtras(entries, known) {
|
|
193
|
+
const out = {};
|
|
194
|
+
for (const k of Object.keys(entries)) {
|
|
195
|
+
if (!known.has(k)) out[k] = entries[k];
|
|
196
|
+
}
|
|
197
|
+
return out;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return { typeStructAttribute, ATTRIBUTE_OWNERS: OWNERS };
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|