Coverage Report

Created: 2026-08-11 07:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/poppler/poppler/PDFDoc.h
Line
Count
Source
1
//========================================================================
2
//
3
// PDFDoc.h
4
//
5
// Copyright 1996-2003 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
//========================================================================
10
//
11
// Modified under the Poppler project - http://poppler.freedesktop.org
12
//
13
// All changes made under the Poppler project to this file are licensed
14
// under GPL version 2 or later
15
//
16
// Copyright (C) 2005, 2006, 2008 Brad Hards <bradh@frogmouth.net>
17
// Copyright (C) 2005, 2009, 2014, 2015, 2017-2022, 2024-2026 Albert Astals Cid <aacid@kde.org>
18
// Copyright (C) 2008 Julien Rebetez <julienr@svn.gnome.org>
19
// Copyright (C) 2008 Pino Toscano <pino@kde.org>
20
// Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
21
// Copyright (C) 2009 Eric Toombs <ewtoombs@uwaterloo.ca>
22
// Copyright (C) 2009 Kovid Goyal <kovid@kovidgoyal.net>
23
// Copyright (C) 2010, 2014 Hib Eris <hib@hiberis.nl>
24
// Copyright (C) 2010 Srinivas Adicherla <srinivas.adicherla@geodesic.com>
25
// Copyright (C) 2011, 2013, 2014, 2016 Thomas Freitag <Thomas.Freitag@alfa.de>
26
// Copyright (C) 2012 Fabio D'Urso <fabiodurso@hotmail.it>
27
// Copyright (C) 2013, 2017 Adrian Johnson <ajohnson@redneon.com>
28
// Copyright (C) 2013, 2018 Adam Reichold <adamreichold@myopera.com>
29
// Copyright (C) 2013 Adrian Perez de Castro <aperez@igalia.com>
30
// Copyright (C) 2015 André Guerreiro <aguerreiro1985@gmail.com>
31
// Copyright (C) 2015 André Esser <bepandre@hotmail.com>
32
// Copyright (C) 2016 Jakub Alba <jakubalba@gmail.com>
33
// Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by the LiMux project of the city of Munich
34
// Copyright (C) 2018 Evangelos Rigas <erigas@rnd2.org>
35
// Copyright (C) 2020-2023 Oliver Sander <oliver.sander@tu-dresden.de>
36
// Copyright (C) 2020 Nelson Benítez León <nbenitezl@gmail.com>
37
// Copyright (C) 2021 Mahmoud Khalil <mahmoudkhalil11@gmail.com>
38
// Copyright (C) 2021 Georgiy Sgibnev <georgiy@sgibnev.com>. Work sponsored by lab50.net.
39
// Copyright (C) 2021 Marek Kasik <mkasik@redhat.com>
40
// Copyright (C) 2022 Felix Jung <fxjung@posteo.de>
41
// Copyright (C) 2022 crt <chluo@cse.cuhk.edu.hk>
42
// Copyright (C) 2023-2026 g10 Code GmbH, Author: Sune Stolborg Vuorela <sune@vuorela.dk>
43
// Copyright (C) 2024 Klarälvdalens Datakonsult AB, a KDAB Group company, <info@kdab.com>. Work sponsored by Technische Universität Dresden
44
// Copyright (C) 2025 Jonathan Hähne <jonathan.haehne@hotmail.com>
45
//
46
// To see a description of the changes please see the Changelog file that
47
// came with your tarball or type make ChangeLog if you are building from git
48
//
49
//========================================================================
50
51
#ifndef PDFDOC_H
52
#define PDFDOC_H
53
54
#include <algorithm>
55
#include <mutex>
56
57
#include "CryptoSignBackend.h"
58
59
#include "poppler_private_export.h"
60
61
#include "XRef.h"
62
#include "Catalog.h"
63
#include "Page.h"
64
#include "ErrorCodes.h"
65
#include "Stream.h"
66
67
class AnnotColor;
68
class AnnotWidget;
69
class FormFieldSignature;
70
class FormWidget;
71
class GooString;
72
class GooFile;
73
class BaseStream;
74
class OutputDev;
75
class Links;
76
class LinkAction;
77
class LinkDest;
78
class Outline;
79
class Linearization;
80
class SecurityHandler;
81
class Hints;
82
class StructTreeRoot;
83
84
enum PDFWriteMode
85
{
86
    writeStandard,
87
    writeForceRewrite,
88
    writeForceIncremental
89
};
90
91
enum PDFSubtype
92
{
93
    subtypeNull,
94
    subtypePDFA,
95
    subtypePDFE,
96
    subtypePDFUA,
97
    subtypePDFVT,
98
    subtypePDFX,
99
    subtypeNone
100
};
101
102
enum PDFSubtypePart
103
{
104
    subtypePartNull,
105
    subtypePart1,
106
    subtypePart2,
107
    subtypePart3,
108
    subtypePart4,
109
    subtypePart5,
110
    subtypePart6,
111
    subtypePart7,
112
    subtypePart8,
113
    subtypePartNone
114
};
115
116
enum PDFSubtypeConformance
117
{
118
    subtypeConfNull,
119
    subtypeConfA,
120
    subtypeConfB,
121
    subtypeConfG,
122
    subtypeConfN,
123
    subtypeConfP,
124
    subtypeConfPG,
125
    subtypeConfU,
126
    subtypeConfNone
127
};
128
129
//------------------------------------------------------------------------
130
// PDFDoc
131
//------------------------------------------------------------------------
132
133
class POPPLER_PRIVATE_EXPORT PDFDoc
134
{
135
public:
136
    explicit PDFDoc(std::unique_ptr<GooString> &&fileNameA, const std::optional<GooString> &ownerPassword = {}, const std::optional<GooString> &userPassword = {}, const std::function<void()> &xrefReconstructedCallback = {});
137
138
#ifdef _WIN32
139
    PDFDoc(wchar_t *fileNameA, int fileNameLen, const std::optional<GooString> &ownerPassword = {}, const std::optional<GooString> &userPassword = {}, const std::function<void()> &xrefReconstructedCallback = {});
140
#endif
141
142
    explicit PDFDoc(std::unique_ptr<BaseStream> strA, const std::optional<GooString> &ownerPassword = {}, const std::optional<GooString> &userPassword = {}, const std::function<void()> &xrefReconstructedCallback = {});
143
    ~PDFDoc();
144
145
    PDFDoc(const PDFDoc &) = delete;
146
    PDFDoc &operator=(const PDFDoc &) = delete;
147
148
    static std::unique_ptr<PDFDoc> ErrorPDFDoc(int errorCode, std::unique_ptr<GooString> &&fileNameA);
149
150
    // Was PDF document successfully opened?
151
8.75k
    bool isOk() const { return ok; }
152
153
    // Get the error code (if isOk() returns false).
154
8.75k
    int getErrorCode() const { return errCode; }
155
156
    // Get the error code returned by fopen() (if getErrorCode() ==
157
    // errOpenFile).
158
0
    int getFopenErrno() const { return fopenErrno; }
159
160
    // Get file name.
161
0
    const GooString *getFileName() const { return fileName.get(); }
162
#ifdef _WIN32
163
    std::wstring getFileNameU() { return fileNameU; }
164
#endif
165
166
    // Get the linearization table.
167
    Linearization *getLinearization();
168
    bool checkLinearization();
169
170
    // Get the xref table.
171
14.3k
    XRef *getXRef() const { return xref; }
172
173
    // Get catalog.
174
13.3k
    Catalog *getCatalog() const { return catalog; }
175
176
    // Get optional content configuration
177
0
    const OCGs *getOptContentConfig() const { return catalog->getOptContentConfig(); }
178
179
    // Get base stream.
180
0
    BaseStream *getBaseStream() const { return str.get(); }
181
182
    // Get page parameters.
183
0
    double getPageMediaWidth(int page) { return getPage(page) ? getPage(page)->getMediaWidth() : 0.0; }
184
0
    double getPageMediaHeight(int page) { return getPage(page) ? getPage(page)->getMediaHeight() : 0.0; }
185
0
    double getPageCropWidth(int page) { return getPage(page) ? getPage(page)->getCropWidth() : 0.0; }
186
0
    double getPageCropHeight(int page) { return getPage(page) ? getPage(page)->getCropHeight() : 0.0; }
187
0
    int getPageRotate(int page) { return getPage(page) ? getPage(page)->getRotate() : 0; }
188
189
    // Get number of pages.
190
    int getNumPages();
191
192
    // Return the contents of the metadata stream, or nullptr if there is
193
    // no metadata.
194
0
    std::optional<std::string> readMetadata() const { return catalog->readMetadata(); }
195
196
    // Return the structure tree root object.
197
0
    const StructTreeRoot *getStructTreeRoot() const { return catalog->getStructTreeRoot(); }
198
199
    // Get page. First page is page 1.
200
    Page *getPage(int page);
201
202
    // Display a page.
203
    void displayPage(OutputDev *out, int page, double hDPI, double vDPI, int rotate, bool useMediaBox, bool crop, bool printing, bool (*abortCheckCbk)(void *data) = nullptr, void *abortCheckCbkData = nullptr,
204
                     bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = nullptr, void *annotDisplayDecideCbkData = nullptr, bool copyXRef = false);
205
206
    // Display a range of pages.
207
    void displayPages(OutputDev *out, int firstPage, int lastPage, double hDPI, double vDPI, int rotate, bool useMediaBox, bool crop, bool printing, bool (*abortCheckCbk)(void *data) = nullptr, void *abortCheckCbkData = nullptr,
208
                      bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = nullptr, void *annotDisplayDecideCbkData = nullptr);
209
210
    // Display part of a page.
211
    void displayPageSlice(OutputDev *out, int page, double hDPI, double vDPI, int rotate, bool useMediaBox, bool crop, bool printing, int sliceX, int sliceY, int sliceW, int sliceH, bool (*abortCheckCbk)(void *data) = nullptr,
212
                          void *abortCheckCbkData = nullptr, bool (*annotDisplayDecideCbk)(Annot *annot, void *user_data) = nullptr, void *annotDisplayDecideCbkData = nullptr, bool copyXRef = false);
213
214
    // Find a page, given its object ID.  Returns page number, or 0 if
215
    // not found.
216
0
    int findPage(const Ref ref) { return catalog->findPage(ref); }
217
218
    // Returns the links for the current page, transferring ownership to
219
    // the caller.
220
    std::unique_ptr<Links> getLinks(int page);
221
222
    // Find a named destination.  Returns the link destination, or
223
    // nullptr if <name> is not a destination.
224
0
    std::unique_ptr<LinkDest> findDest(const GooString *name) { return catalog->findDest(name); }
225
226
    // Process the links for a page.
227
    void processLinks(OutputDev *out, int page);
228
229
    // Return the outline object.
230
    Outline *getOutline();
231
232
    // Is the file encrypted?
233
0
    bool isEncrypted() { return xref->isEncrypted(); }
234
235
    std::vector<FormFieldSignature *> getSignatureFields();
236
237
    // Check various permissions.
238
0
    bool okToPrint(bool ignoreOwnerPW = false) { return xref->okToPrint(ignoreOwnerPW); }
239
0
    bool okToPrintHighRes(bool ignoreOwnerPW = false) { return xref->okToPrintHighRes(ignoreOwnerPW); }
240
0
    bool okToChange(bool ignoreOwnerPW = false) { return xref->okToChange(ignoreOwnerPW); }
241
0
    bool okToCopy(bool ignoreOwnerPW = false) { return xref->okToCopy(ignoreOwnerPW); }
242
0
    bool okToAddNotes(bool ignoreOwnerPW = false) { return xref->okToAddNotes(ignoreOwnerPW); }
243
0
    bool okToFillForm(bool ignoreOwnerPW = false) { return xref->okToFillForm(ignoreOwnerPW); }
244
0
    bool okToAccessibility(bool ignoreOwnerPW = false) { return xref->okToAccessibility(ignoreOwnerPW); }
245
0
    bool okToAssemble(bool ignoreOwnerPW = false) { return xref->okToAssemble(ignoreOwnerPW); }
246
247
    // Is this document linearized?
248
    bool isLinearized(bool tryingToReconstruct = false);
249
250
    // Return the document's Info dictionary (if any).
251
48.2k
    Object getDocInfo() { return xref->getDocInfo(); }
252
0
    Object getDocInfoNF() { return xref->getDocInfoNF(); }
253
254
    // Remove the document's Info dictionary and update the trailer dictionary.
255
0
    void removeDocInfo() { xref->removeDocInfo(); }
256
257
    // Set doc info string entry. nullptr or empty value will cause a removal.
258
    // Takes ownership of value.
259
    void setDocInfoStringEntry(const char *key, std::unique_ptr<GooString> value);
260
261
    // Set document's properties in document's Info dictionary.
262
    // nullptr or empty value will cause a removal.
263
0
    void setDocInfoTitle(std::unique_ptr<GooString> title) { setDocInfoStringEntry("Title", std::move(title)); }
264
0
    void setDocInfoAuthor(std::unique_ptr<GooString> author) { setDocInfoStringEntry("Author", std::move(author)); }
265
0
    void setDocInfoSubject(std::unique_ptr<GooString> subject) { setDocInfoStringEntry("Subject", std::move(subject)); }
266
0
    void setDocInfoKeywords(std::unique_ptr<GooString> keywords) { setDocInfoStringEntry("Keywords", std::move(keywords)); }
267
0
    void setDocInfoCreator(std::unique_ptr<GooString> creator) { setDocInfoStringEntry("Creator", std::move(creator)); }
268
0
    void setDocInfoProducer(std::unique_ptr<GooString> producer) { setDocInfoStringEntry("Producer", std::move(producer)); }
269
0
    void setDocInfoCreatDate(std::unique_ptr<GooString> creatDate) { setDocInfoStringEntry("CreationDate", std::move(creatDate)); }
270
0
    void setDocInfoModDate(std::unique_ptr<GooString> modDate) { setDocInfoStringEntry("ModDate", std::move(modDate)); }
271
272
    // Get document's properties from document's Info dictionary.
273
    // Returns nullptr on fail.
274
    std::optional<std::string> getDocInfoStringEntry(std::string_view key);
275
276
4.82k
    std::optional<std::string> getDocInfoTitle() { return getDocInfoStringEntry("Title"); }
277
4.82k
    std::optional<std::string> getDocInfoAuthor() { return getDocInfoStringEntry("Author"); }
278
4.82k
    std::optional<std::string> getDocInfoSubject() { return getDocInfoStringEntry("Subject"); }
279
0
    std::optional<std::string> getDocInfoKeywords() { return getDocInfoStringEntry("Keywords"); }
280
0
    std::optional<std::string> getDocInfoCreator() { return getDocInfoStringEntry("Creator"); }
281
4.82k
    std::optional<std::string> getDocInfoProducer() { return getDocInfoStringEntry("Producer"); }
282
4.82k
    std::optional<std::string> getDocInfoCreatDate() { return getDocInfoStringEntry("CreationDate"); }
283
0
    std::optional<std::string> getDocInfoModDate() { return getDocInfoStringEntry("ModDate"); }
284
285
    // Return the PDF subtype, part, and conformance
286
0
    PDFSubtype getPDFSubtype() const { return pdfSubtype; }
287
0
    PDFSubtypePart getPDFSubtypePart() const { return pdfPart; }
288
0
    PDFSubtypeConformance getPDFSubtypeConformance() const { return pdfConformance; }
289
290
    // Return the PDF version specified by the file (either header or catalog).
291
0
    int getPDFMajorVersion() const { return std::max(headerPdfMajorVersion, catalog->getPDFMajorVersion()); }
292
    int getPDFMinorVersion() const
293
0
    {
294
0
        const int catalogMajorVersion = catalog->getPDFMajorVersion();
295
0
        if (catalogMajorVersion > headerPdfMajorVersion) {
296
0
            return catalog->getPDFMinorVersion();
297
0
        }
298
0
        if (headerPdfMajorVersion > catalogMajorVersion) {
299
0
            return headerPdfMinorVersion;
300
0
        }
301
0
        return std::max(headerPdfMinorVersion, catalog->getPDFMinorVersion());
302
0
    }
303
304
    // Return the PDF ID in the trailer dictionary (if any).
305
    bool getID(GooString *permanent_id, GooString *update_id) const;
306
307
    // Save one page with another name.
308
    int savePageAs(const std::string &name, int pageNo);
309
    // Save this file with another name.
310
    int saveAs(const std::string &name, PDFWriteMode mode = writeStandard);
311
    // Save this file in the given output stream.
312
    int saveAs(OutStream *outStr, PDFWriteMode mode = writeStandard);
313
    // Save this file with another name without saving changes
314
    int saveWithoutChangesAs(const std::string &name);
315
    // Save this file in the given output stream without saving changes
316
    int saveWithoutChangesAs(OutStream *outStr);
317
318
    // rewrite pageDict with MediaBox, CropBox and new page CTM
319
    bool replacePageDict(int pageNo, int rotate, const PDFRectangle &mediaBox, const PDFRectangle *cropBox) const;
320
    bool markPageObjects(Dict *pageDict, XRef *xRef, XRef *countRef, unsigned int numOffset, int oldRefNum, int newRefNum, std::set<Dict *> *alreadyMarkedDicts = nullptr);
321
    bool markAnnotations(Object *annots, XRef *xRef, XRef *countRef, unsigned int numOffset, int oldPageNum, int newPageNum, std::set<Dict *> *alreadyMarkedDicts = nullptr);
322
    void markAcroForm(Object *afObj, XRef *xRef, XRef *countRef, unsigned int numOffset, int oldRefNum, int newRefNum);
323
    // write all objects used by pageDict to outStr
324
    unsigned int writePageObjects(OutStream *outStr, XRef *xRef, unsigned int numOffset, bool combine = false);
325
    static void writeObject(Object *obj, OutStream *outStr, XRef *xref, unsigned int numOffset, const unsigned char *fileKey, CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen,
326
                            std::set<Dict *> *alreadyWrittenDicts = nullptr);
327
    static void writeObject(Object *obj, OutStream *outStr, XRef *xref, unsigned int numOffset, const unsigned char *fileKey, CryptAlgorithm encAlgorithm, int keyLength, Ref ref, std::set<Dict *> *alreadyWrittenDicts = nullptr);
328
    static void writeHeader(OutStream *outStr, int major, int minor);
329
330
    static Object createTrailerDict(int uxrefSize, bool incrUpdate, Goffset startxRef, Ref *root, XRef *xRef, const char *fileName, Goffset fileSize);
331
    static void writeXRefTableTrailer(Object &&trailerDict, XRef *uxref, bool writeAllEntries, Goffset uxrefOffset, OutStream *outStr, XRef *xRef);
332
    static void writeXRefStreamTrailer(Object &&trailerDict, XRef *uxref, Ref *uxrefStreamRef, Goffset uxrefOffset, OutStream *outStr, XRef *xRef);
333
    // scans the PDF and returns whether it contains any javascript
334
    bool hasJavascript();
335
336
    // Arguments signatureText and signatureTextLeft are UTF-16 big endian strings with BOM.
337
    // Arguments reason and location are UTF-16 big endian strings with BOM. An empty string and nullptr are acceptable too.
338
    // Argument imagePath is a background image (a path to a file).
339
    // sign() takes ownership of partialFieldName.
340
    std::optional<CryptoSign::SigningErrorMessage> sign(const std::string &saveFilename, const std::string &certNickname, const std::string &password, std::unique_ptr<GooString> &&partialFieldName, int page, const PDFRectangle &rect,
341
                                                        const GooString &signatureText, const GooString &signatureTextLeft, double fontSize, double leftFontSize, std::unique_ptr<AnnotColor> &&fontColor, double borderWidth,
342
                                                        std::unique_ptr<AnnotColor> &&borderColor, std::unique_ptr<AnnotColor> &&backgroundColor, const GooString *reason = nullptr, const GooString *location = nullptr,
343
                                                        const std::string &imagePath = "", const std::optional<GooString> &ownerPassword = {}, const std::optional<GooString> &userPassword = {});
344
345
    struct SignatureData
346
    {
347
        Ref ref;
348
        std::shared_ptr<AnnotWidget> annotWidget = nullptr;
349
        FormWidget *formWidget = nullptr;
350
        std::unique_ptr<::FormFieldSignature> field;
351
    };
352
353
    std::variant<SignatureData, CryptoSign::SigningErrorMessage> createSignature(::Page *destPage, std::unique_ptr<GooString> &&partialFieldName, const PDFRectangle &rect, const GooString &signatureText, const GooString &signatureTextLeft,
354
                                                                                 double fontSize, double leftFontSize, std::unique_ptr<AnnotColor> &&fontColor, double borderWidth, std::unique_ptr<AnnotColor> &&borderColor,
355
                                                                                 std::unique_ptr<AnnotColor> &&backgroundColor, const std::string &imagePath);
356
357
private:
358
    // insert referenced objects in XRef
359
    bool markDictionary(Dict *dict, XRef *xRef, XRef *countRef, unsigned int numOffset, int oldRefNum, int newRefNum, std::set<Dict *> *alreadyMarkedDicts);
360
    bool markObject(Object *obj, XRef *xRef, XRef *countRef, unsigned int numOffset, int oldRefNum, int newRefNum, std::set<Dict *> *alreadyMarkedDicts = nullptr);
361
362
    // Sanitizes the string so that it does
363
    // not contain any ( ) < > [ ] { } / %
364
    static std::string sanitizedName(const std::string &name);
365
366
    static void writeDictionary(Dict *dict, OutStream *outStr, XRef *xRef, unsigned int numOffset, const unsigned char *fileKey, CryptAlgorithm encAlgorithm, int keyLength, Ref ref, std::set<Dict *> *alreadyWrittenDicts);
367
368
    // Write object header to current file stream and return its offset
369
    static Goffset writeObjectHeader(Ref *ref, OutStream *outStr);
370
    static void writeObjectFooter(OutStream *outStr);
371
372
    void writeObject(Object *obj, OutStream *outStr, const unsigned char *fileKey, CryptAlgorithm encAlgorithm, int keyLength, int objNum, int objGen) const
373
0
    {
374
0
        writeObject(obj, outStr, getXRef(), 0, fileKey, encAlgorithm, keyLength, { .num = objNum, .gen = objGen });
375
0
    }
376
0
    void writeObject(Object *obj, OutStream *outStr, const unsigned char *fileKey, CryptAlgorithm encAlgorithm, int keyLength, Ref ref) const { writeObject(obj, outStr, getXRef(), 0, fileKey, encAlgorithm, keyLength, ref); }
377
    static void writeStream(Stream *str, OutStream *outStr);
378
    static void writeRawStream(Stream *str, OutStream *outStr);
379
    void writeXRefTableTrailer(Goffset uxrefOffset, XRef *uxref, bool writeAllEntries, int uxrefSize, OutStream *outStr, bool incrUpdate);
380
    static void writeString(const std::string &s, OutStream *outStr, const unsigned char *fileKey, CryptAlgorithm encAlgorithm, int keyLength, Ref ref);
381
    void saveIncrementalUpdate(OutStream *outStr);
382
    void saveCompleteRewrite(OutStream *outStr);
383
384
    std::unique_ptr<Page> parsePage(int page);
385
386
    // Get hints.
387
    Hints *getHints();
388
389
    PDFDoc();
390
    bool setup(const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword, const std::function<void()> &xrefReconstructedCallback);
391
    bool checkFooter();
392
    void checkHeader();
393
    bool checkEncryption(const std::optional<GooString> &ownerPassword, const std::optional<GooString> &userPassword);
394
    void extractPDFSubtype();
395
396
    // Get the offset of the start xref table.
397
    Goffset getStartXRef(bool tryingToReconstruct = false);
398
    // Get the offset of the entries in the main XRef table of a
399
    // linearized document (0 for non linearized documents).
400
    Goffset getMainXRefEntriesOffset(bool tryingToReconstruct = false);
401
    static long long strToLongLong(const char *s);
402
403
    std::unique_ptr<GooString> fileName;
404
#ifdef _WIN32
405
    std::wstring fileNameU;
406
#endif
407
    std::unique_ptr<GooFile> file;
408
    std::unique_ptr<BaseStream> str;
409
    int headerPdfMajorVersion;
410
    int headerPdfMinorVersion;
411
    PDFSubtype pdfSubtype;
412
    PDFSubtypePart pdfPart;
413
    PDFSubtypeConformance pdfConformance;
414
    Linearization *linearization = nullptr;
415
    // linearizationState = 0: unchecked
416
    // linearizationState = 1: checked and valid
417
    // linearizationState = 2: checked and invalid
418
    int linearizationState;
419
    XRef *xref = nullptr;
420
    SecurityHandler *secHdlr = nullptr;
421
    Catalog *catalog = nullptr;
422
    Hints *hints = nullptr;
423
    Outline *outline = nullptr;
424
    std::vector<std::unique_ptr<Page>> pageCache;
425
426
    bool ok = false;
427
    int errCode = errNone;
428
    // If there is an error opening the PDF file with fopen() in the constructor,
429
    // then the POSIX errno will be here.
430
    int fopenErrno;
431
432
    Goffset startXRefPos = -1; // offset of last xref table
433
    mutable std::recursive_mutex mutex;
434
};
435
436
#endif