@patrickdk77/pdf-defuse 0.0.0-stage → 0.1.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.
@@ -0,0 +1,191 @@
1
+ import { type OpenResult, SecurityHandler } from './crypto';
2
+ import { Reader, TempDir } from './io';
3
+ import { PdfDict, type PdfObject, PdfRef, PdfStream } from './objects';
4
+ import type { ByteSource } from './types';
5
+ type XrefEntry = {
6
+ type: 1;
7
+ offset: number;
8
+ gen: number;
9
+ } | {
10
+ type: 2;
11
+ stream: number;
12
+ };
13
+ /** Entries are packed into one number each, so the index costs a few bytes per object. */
14
+ export declare const packOffset: (offset: number, gen: number) => number;
15
+ export declare const packStream: (stream: number) => number;
16
+ export declare function unpack(v: number | undefined): XrefEntry | undefined;
17
+ export declare class OpenError extends Error {
18
+ readonly kind: 'unparseable' | 'truncated' | 'not-pdf';
19
+ constructor(kind: 'unparseable' | 'truncated' | 'not-pdf', message: string);
20
+ }
21
+ /** Past the deadline. The code makes every package of the family pass it up to the top. */
22
+ export declare class TimeLimitError extends Error {
23
+ readonly code = "DEFUSE_LIMIT";
24
+ readonly limit = "time";
25
+ }
26
+ export declare class ObjectLimitError extends Error {
27
+ }
28
+ interface DocumentIssues {
29
+ escapedNames: Set<string>;
30
+ streamLengthWrong: number;
31
+ malformed: number;
32
+ /** An object whose header generation differs from its xref entry. */
33
+ genMismatch: number;
34
+ /** An xref entry that does not point at its object. */
35
+ badOffsets: number;
36
+ /** Dictionaries that repeat a key. */
37
+ duplicateKeys: Set<string>;
38
+ /** Object definitions in older revisions that a newer revision replaced or freed. */
39
+ superseded: number;
40
+ /** References to object streams or xref streams as if they were ordinary objects. */
41
+ structuralRefs: number;
42
+ /** /XRefStm entries that lead to no xref stream. qpdf and the readers built on it then rebuild the map by scanning. */
43
+ badXRefStm: number;
44
+ /** Rows /XRefStm gives for numbers its own table marks free. pdf.js keeps the free row and qpdf takes the stream's. */
45
+ xrefStmOverFree: number;
46
+ /** Object streams whose header pdf.js refuses, offsets that do not increase or numbers that are not whole. */
47
+ badObjStm: Set<number>;
48
+ /** Objects referenced with a generation their entry does not have, which pdf.js refuses to resolve. */
49
+ refGen: Set<number>;
50
+ /** Parts held in a temporary file instead of memory. */
51
+ memoryFallback: string[];
52
+ }
53
+ interface OpenOptions {
54
+ password?: string;
55
+ decompressedBytes?: number;
56
+ objectLimit?: number;
57
+ deadline?: number;
58
+ temp?: TempDir;
59
+ memoryThreshold?: number;
60
+ }
61
+ /** A PDF opened for random access. Objects are read on demand and never all held at once. */
62
+ export declare class PdfDocument {
63
+ readonly reader: Reader;
64
+ readonly size: number;
65
+ private readonly opts;
66
+ headerOffset: number;
67
+ headerVersion: string;
68
+ /** Added to every offset when the file has bytes before its header and the xref ignores them. */
69
+ private base;
70
+ /** Object number to packed entry. */
71
+ readonly xref: Map<number, number>;
72
+ trailer: PdfDict;
73
+ sections: number;
74
+ rebuilt: boolean;
75
+ hasEof: boolean;
76
+ trailingBytes: number;
77
+ security?: SecurityHandler;
78
+ securityResult?: OpenResult;
79
+ encryptRef?: PdfRef;
80
+ readonly issues: DocumentIssues;
81
+ /** Body offsets of the streams already counted in issues.streamLengthWrong, so a second read adds nothing. */
82
+ private readonly lengthWrongAt;
83
+ private objCache;
84
+ private objStmCache;
85
+ /** Object streams that spilled to a temporary file. Kept for the life of the document, so each is decoded once. */
86
+ private readonly spilledObjStm;
87
+ /** Object streams found by scan(), indexed once the key exists. */
88
+ private pendingObjStm;
89
+ /** Streams whose indirect /Length or filter entries are being resolved, so a cycle ends after one lap. */
90
+ private readonly lengthResolving;
91
+ /**
92
+ * Stream number to the objects its filter entries name. Their values are copied into the stream, so the objects
93
+ * are referenced when the walk visits the stream, though it never visits them.
94
+ */
95
+ readonly filterRefs: Map<number, number[]>;
96
+ /** Objects read for the Encrypt dictionary, which the walk never visits. */
97
+ readonly encryptRefs: Set<number>;
98
+ /** Set while a lookup must leave the issues as they are. */
99
+ private quiet;
100
+ private readonly hooks;
101
+ /** Where the objects whose bad tokens are already in issues.malformed were read, so a second read adds nothing. */
102
+ private readonly badTokensCounted;
103
+ private scanned;
104
+ /** Offsets of the xref sections and xref streams that read, which are not ordinary object definitions. */
105
+ readonly structuralOffsets: Set<number>;
106
+ /** The definitions that older xref sections use and newer ones replaced or freed, as object number then offset. */
107
+ private readonly supersededAt;
108
+ private sortedOffsets?;
109
+ /** Live uncompressed objects sorted by offset, for finding the object around a position. */
110
+ private liveByOffset?;
111
+ /** The extent of the live object insideLiveObject() read last, empty when it does not parse. */
112
+ private lastLive?;
113
+ private unboundedScanBudget;
114
+ /** Bytes parseWindowed() may still read past the next known object. */
115
+ private parseBudget;
116
+ private constructor();
117
+ static open(source: ByteSource, opts?: OpenOptions): Promise<PdfDocument>;
118
+ checkTime(): void;
119
+ private checkObjectLimit;
120
+ private init;
121
+ private initSecurity;
122
+ private loadXrefChain;
123
+ /** Reads one section; for hybrid files its XRefStm entries add the objects the table does not give. */
124
+ private readXrefSection;
125
+ private readXrefTable;
126
+ /** `at` is where the stream's object header starts, which can be past whitespace at `offset`. */
127
+ private readXrefStream;
128
+ /** Rebuilds the object map by scanning every byte. Used when the xref is missing or wrong. */
129
+ private scan;
130
+ /** Adds the objects held in the object streams scan() found. Their bodies may be encrypted, so this runs after initSecurity(). */
131
+ private indexObjStms;
132
+ /**
133
+ * Parses the indirect object ("N G obj ...") at a source offset. `at` is where its header starts, past any
134
+ * whitespace, and `end` where its value or its stream body ends.
135
+ */
136
+ private parseIndirectAt;
137
+ /** Finds a stream body's true length, trusting /Length only when "endstream" follows it. */
138
+ private locateStream;
139
+ /** Position just before the EOL that precedes "endstream" in [from, to), or -1. */
140
+ private findEndstream;
141
+ /** The smallest known object or xref offset after `pos`, or the end of the file. */
142
+ private nextOffsetAfter;
143
+ /** Loads an object by reference, decrypted. Missing and free objects are null. */
144
+ getObject(ref: PdfRef, raw?: boolean): Promise<PdfObject>;
145
+ private decryptObject;
146
+ private getFromObjStm;
147
+ /** Decodes an object stream in chunks; large ones go to a temporary file instead of memory. */
148
+ private loadObjStm;
149
+ private ownTemp?;
150
+ /**
151
+ * Parses at an offset in any reader, growing the window as needed. A window that reaches `bound`, the next known
152
+ * object, grows further only while a budget for the whole file lasts, so damaged files still parse and crafted
153
+ * ones stay linear. `key` names the place read, so its bad tokens count once however often it is parsed.
154
+ */
155
+ private parseWindowed;
156
+ resolve(v: PdfObject | undefined): Promise<PdfObject | undefined>;
157
+ /** The generation of a live object's entry, 0 for one in an object stream or none. */
158
+ genOf(num: number): number;
159
+ /** Length of the stream once decrypted, which is what gets written out. */
160
+ plainLength(stream: PdfStream, num: number): Promise<number>;
161
+ /** Yields the decrypted, still-encoded body in chunks. */
162
+ plainChunks(stream: PdfStream, num: number): AsyncGenerator<Uint8Array>;
163
+ /** Decrypts and decodes a whole stream body into memory, subject to the decompression limit and an optional cap. */
164
+ decode(stream: PdfStream, num: number, limit?: number | undefined, cap?: number): Promise<Uint8Array>;
165
+ /**
166
+ * Counts object definitions in the file body that no xref section uses. Reads the whole file once, in chunks.
167
+ * Definitions an older section uses are left to the superseded count. A header inside a live object counts only
168
+ * with `inLive`, since only a reader that rebuilds the map by scanning takes it.
169
+ */
170
+ countDeadDefinitions(inLive?: boolean): Promise<number>;
171
+ /**
172
+ * Yields every "N G obj" header in the file, with the byte before it or -1 at the start of the file, and where its
173
+ * "obj" ends. Each "obj" is read back to its two numbers. The whitespace inside a header can run to any length, as
174
+ * other readers allow, so the read back can reach into earlier chunks: chunks that overlap by a fixed amount miss
175
+ * such a header. `onChunk` sees each chunk once.
176
+ */
177
+ private objectHeaders;
178
+ /**
179
+ * True when [pos, end) lies inside a live object, from its header to the end of its value or stream body. An object
180
+ * header there is data, such as text quoted in a string or an uncompressed attached PDF, not a definition in this
181
+ * file. Parsing the object must not change the issue counts, which describe the walked document and are final by now.
182
+ */
183
+ private insideLiveObject;
184
+ /** Live object numbers, for the unreferenced-object count. */
185
+ liveNumbers(): IterableIterator<number>;
186
+ /** Drops caches and the object index once the document is no longer read, and deletes spilled object streams. */
187
+ release(): Promise<void>;
188
+ /** Forgets every decoded object stream, closing and deleting the ones that spilled to a temporary file. */
189
+ private dropObjStms;
190
+ }
191
+ export {};