/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 |